diff --git a/src/main/java/net/citizensnpcs/EventListen.java b/src/main/java/net/citizensnpcs/EventListen.java index dbe3a8810..ff104f030 100644 --- a/src/main/java/net/citizensnpcs/EventListen.java +++ b/src/main/java/net/citizensnpcs/EventListen.java @@ -263,12 +263,6 @@ public class EventListen implements Listener { } } - @EventHandler(ignoreCancelled=true) - public void onPlayerFish(PlayerFishEvent event) { - if (npcRegistry.isNPC(event.getCaught()) && npcRegistry.getNPC(event.getCaught()).isProtected()) { - event.setCancelled(true); - } - } @EventHandler(priority = EventPriority.HIGHEST) public void onEntitySpawn(CreatureSpawnEvent event) { if (event.isCancelled() && npcRegistry.isNPC(event.getEntity())) { @@ -362,9 +356,14 @@ public class EventListen implements Listener { public void onNPCDespawn(NPCDespawnEvent event) { if (event.getReason() == DespawnReason.PLUGIN || event.getReason() == DespawnReason.REMOVAL || event.getReason() == DespawnReason.RELOAD) { + Messaging.debug("Preventing further respawns of " + event.getNPC().getId() + " due to DespawnReason." + + event.getReason().name()); if (event.getNPC().getStoredLocation() != null) { toRespawn.remove(toCoord(event.getNPC().getStoredLocation()), event.getNPC()); } + } else { + Messaging.debug("Removing " + event.getNPC().getId() + " from skin tracker due to DespawnReason." + + event.getReason().name()); } skinUpdateTracker.onNPCDespawn(event.getNPC()); } @@ -393,6 +392,13 @@ public class EventListen implements Listener { checkCreationEvent(event); } + @EventHandler(ignoreCancelled = true) + public void onPlayerFish(PlayerFishEvent event) { + if (npcRegistry.isNPC(event.getCaught()) && npcRegistry.getNPC(event.getCaught()).isProtected()) { + event.setCancelled(true); + } + } + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { NPC npc = npcRegistry.getNPC(event.getRightClicked()); diff --git a/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/src/main/java/net/citizensnpcs/commands/NPCCommands.java index 6a4039d7a..ea6eb8133 100644 --- a/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -15,6 +15,8 @@ import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; @@ -38,6 +40,7 @@ import org.bukkit.potion.PotionEffectType; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import net.citizensnpcs.Citizens; import net.citizensnpcs.Settings.Setting; @@ -74,6 +77,7 @@ import net.citizensnpcs.npc.skin.SkinnableEntity; import net.citizensnpcs.trait.Age; import net.citizensnpcs.trait.Anchors; import net.citizensnpcs.trait.ArmorStandTrait; +import net.citizensnpcs.trait.BossBarTrait; import net.citizensnpcs.trait.Controllable; import net.citizensnpcs.trait.CurrentLocation; import net.citizensnpcs.trait.Gravity; @@ -234,8 +238,8 @@ public class NPCCommands { @Command( aliases = { "npc" }, usage = "armorstand --visible [visible] --small [small] --gravity [gravity] --arms [arms] --baseplate [baseplate]", - desc = "C whether the NPC can be ridden and controlled", - modifiers = { "armorstand", "control" }, + desc = "Edit armorstand properties", + modifiers = { "armorstand" }, min = 1, max = 1) @Requirements(selected = true, ownership = true, types = EntityType.ARMOR_STAND) @@ -258,6 +262,38 @@ public class NPCCommands { } } + @Command( + aliases = { "npc" }, + usage = "bossbar --color [color] --title [title] --visible [visible] --flags [flags]", + desc = "Edit bossbar properties", + modifiers = { "bossbar" }, + min = 1, + max = 1) + @Requirements(selected = true, ownership = true, types = { EntityType.WITHER, EntityType.ENDER_DRAGON }) + public void bossbar(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + BossBarTrait trait = npc.getTrait(BossBarTrait.class); + if (args.hasValueFlag("color")) { + BarColor color = Util.matchEnum(BarColor.values(), args.getFlag("color")); + trait.setColor(color); + } + if (args.hasValueFlag("title")) { + trait.setTitle(args.getFlag("title")); + } + if (args.hasValueFlag("visible")) { + trait.setVisible(Boolean.parseBoolean(args.getFlag("visible"))); + } + if (args.hasValueFlag("flags")) { + List flags = Lists.newArrayList(); + for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(args.getFlag("flags"))) { + BarFlag flag = Util.matchEnum(BarFlag.values(), s); + if (flag != null) { + flags.add(flag); + } + } + trait.setFlags(flags); + } + } + @Command( aliases = { "npc" }, usage = "collidable", diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index f8078a070..68600f503 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -25,6 +25,7 @@ import net.citizensnpcs.api.trait.trait.Speech; import net.citizensnpcs.trait.Age; import net.citizensnpcs.trait.Anchors; import net.citizensnpcs.trait.ArmorStandTrait; +import net.citizensnpcs.trait.BossBarTrait; import net.citizensnpcs.trait.Controllable; import net.citizensnpcs.trait.CurrentLocation; import net.citizensnpcs.trait.Gravity; @@ -57,6 +58,7 @@ public class CitizensTraitFactory implements TraitFactory { registerTrait(TraitInfo.create(Age.class)); registerTrait(TraitInfo.create(ArmorStandTrait.class)); registerTrait(TraitInfo.create(Anchors.class)); + registerTrait(TraitInfo.create(BossBarTrait.class)); registerTrait(TraitInfo.create(Controllable.class)); registerTrait(TraitInfo.create(Equipment.class)); registerTrait(TraitInfo.create(Gravity.class)); diff --git a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java index d433e75e9..a236a449a 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java @@ -306,6 +306,15 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable npc.update(); } + @Override + public boolean m_() { + if (npc == null || !npc.isFlyable()) { + return super.m_(); + } else { + return false; + } + } + private void moveOnCurrentHeading() { NMS.updateAI(this); if (be) { @@ -326,15 +335,6 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable } } - @Override - public boolean m_() { - if (npc == null || !npc.isFlyable()) { - return super.m_(); - } else { - return false; - } - } - public void setMoveDestination(double x, double y, double z, double speed) { controllerMove.a(x, y, z, speed); } diff --git a/src/main/java/net/citizensnpcs/trait/BossBarTrait.java b/src/main/java/net/citizensnpcs/trait/BossBarTrait.java new file mode 100644 index 000000000..52dcb1737 --- /dev/null +++ b/src/main/java/net/citizensnpcs/trait/BossBarTrait.java @@ -0,0 +1,74 @@ +package net.citizensnpcs.trait; + +import java.util.Collection; +import java.util.List; + +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; + +import com.google.common.collect.Lists; + +import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.api.trait.Trait; +import net.citizensnpcs.api.trait.TraitName; +import net.citizensnpcs.util.NMS; + +@TraitName("bossbar") +public class BossBarTrait extends Trait { + @Persist("color") + private BarColor color = null; + @Persist("flags") + private List flags = Lists.newArrayList(); + @Persist("title") + private String title = null; + @Persist("visible") + private boolean visible = true; + + public BossBarTrait() { + super("bossbar"); + } + + private boolean isBoss(Entity entity) { + return entity.getType() == EntityType.ENDER_DRAGON || entity.getType() == EntityType.WITHER + || entity.getType() == EntityType.GUARDIAN; + } + + @Override + public void run() { + if (!npc.isSpawned() || !isBoss(npc.getEntity())) + return; + BossBar bar = NMS.getBossBar(npc.getEntity()); + bar.setVisible(visible); + if (color != null) { + bar.setColor(color); + } + if (title != null) { + bar.setTitle(title); + } + for (BarFlag flag : BarFlag.values()) { + bar.removeFlag(flag); + } + for (BarFlag flag : flags) { + bar.addFlag(flag); + } + } + + public void setColor(BarColor color) { + this.color = color; + } + + public void setFlags(Collection flags) { + this.flags = Lists.newArrayList(flags); + } + + public void setTitle(String title) { + this.title = title; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } +} diff --git a/src/main/java/net/citizensnpcs/util/NMS.java b/src/main/java/net/citizensnpcs/util/NMS.java index 11f43b202..3dcf4d535 100644 --- a/src/main/java/net/citizensnpcs/util/NMS.java +++ b/src/main/java/net/citizensnpcs/util/NMS.java @@ -21,9 +21,13 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; import org.bukkit.craftbukkit.v1_10_R1.CraftServer; import org.bukkit.craftbukkit.v1_10_R1.CraftSound; import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_10_R1.boss.CraftBossBar; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_10_R1.event.CraftEventFactory; @@ -60,11 +64,14 @@ import net.minecraft.server.v1_10_R1.AttributeInstance; import net.minecraft.server.v1_10_R1.AxisAlignedBB; import net.minecraft.server.v1_10_R1.Block; import net.minecraft.server.v1_10_R1.BlockPosition; +import net.minecraft.server.v1_10_R1.BossBattleServer; import net.minecraft.server.v1_10_R1.ControllerJump; import net.minecraft.server.v1_10_R1.DamageSource; import net.minecraft.server.v1_10_R1.DataWatcherObject; import net.minecraft.server.v1_10_R1.EnchantmentManager; +import net.minecraft.server.v1_10_R1.EnderDragonBattle; import net.minecraft.server.v1_10_R1.Entity; +import net.minecraft.server.v1_10_R1.EntityEnderDragon; import net.minecraft.server.v1_10_R1.EntityFishingHook; import net.minecraft.server.v1_10_R1.EntityHorse; import net.minecraft.server.v1_10_R1.EntityHuman; @@ -78,6 +85,7 @@ import net.minecraft.server.v1_10_R1.EntityTameableAnimal; import net.minecraft.server.v1_10_R1.EntityTracker; import net.minecraft.server.v1_10_R1.EntityTrackerEntry; import net.minecraft.server.v1_10_R1.EntityTypes; +import net.minecraft.server.v1_10_R1.EntityWither; import net.minecraft.server.v1_10_R1.GenericAttributes; import net.minecraft.server.v1_10_R1.MathHelper; import net.minecraft.server.v1_10_R1.MinecraftKey; @@ -370,6 +378,28 @@ public class NMS { entity.aI += entity.aH; } + public static BossBar getBossBar(org.bukkit.entity.Entity entity) { + BossBattleServer bserver = null; + try { + if (entity.getType() == EntityType.WITHER) { + bserver = (BossBattleServer) WITHER_BOSS_BAR_FIELD.get(NMS.getHandle(entity)); + } else if (entity.getType() == EntityType.ENDER_DRAGON) { + bserver = (BossBattleServer) ENDERDRAGON_BATTLE_BAR_FIELD + .get(ENDERDRAGON_BATTLE_FIELD.get(NMS.getHandle(entity))); + } + } catch (Exception e) { + } + if (bserver == null) { + return null; + } + BossBar ret = Bukkit.createBossBar("", BarColor.BLUE, BarStyle.SEGMENTED_10); + try { + CRAFT_BOSSBAR_HANDLE_FIELD.set(ret, bserver); + } catch (Exception e) { + } + return ret; + } + public static org.bukkit.entity.Entity getBukkitVehicle(org.bukkit.entity.Entity entity) { Entity vehicle = getVehicle(entity); return vehicle == null ? null : vehicle.getBukkitEntity(); @@ -919,7 +949,10 @@ public class NMS { } } + private static final Field CRAFT_BOSSBAR_HANDLE_FIELD = getField(CraftBossBar.class, "handle"); private static final float DEFAULT_SPEED = 1F; + private static final Field ENDERDRAGON_BATTLE_BAR_FIELD = getField(EnderDragonBattle.class, "c"); + private static final Field ENDERDRAGON_BATTLE_FIELD = getField(EntityEnderDragon.class, "bK"); private static Map, Integer> ENTITY_CLASS_TO_INT; private static Map, String> ENTITY_CLASS_TO_NAME; private static final Map, Constructor> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap, Constructor>(); @@ -934,6 +967,7 @@ public class NMS { private static final Random RANDOM = Util.getFastRandom(); private static Field SKULL_PROFILE_FIELD; private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); + private static final Field WITHER_BOSS_BAR_FIELD = getField(EntityWither.class, "bG"); static { try {