diff --git a/pom.xml b/pom.xml index 82acff50e..82676af7b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ UTF-8 - 1.2.5-R1.2-SNAPSHOT + 1.2.5-R4.1-SNAPSHOT 2.0-SNAPSHOT Unknown diff --git a/src/main/java/net/citizensnpcs/Citizens.java b/src/main/java/net/citizensnpcs/Citizens.java index ee0212885..bbf7b733e 100644 --- a/src/main/java/net/citizensnpcs/Citizens.java +++ b/src/main/java/net/citizensnpcs/Citizens.java @@ -15,7 +15,7 @@ import net.citizensnpcs.api.npc.NPCRegistry; import net.citizensnpcs.api.scripting.EventRegistrar; import net.citizensnpcs.api.scripting.ObjectProvider; import net.citizensnpcs.api.scripting.ScriptCompiler; -import net.citizensnpcs.api.trait.TraitManager; +import net.citizensnpcs.api.trait.TraitFactory; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.api.util.DatabaseStorage; import net.citizensnpcs.api.util.NBTStorage; @@ -36,7 +36,7 @@ import net.citizensnpcs.command.exception.WrappedCommandException; import net.citizensnpcs.editor.Editor; import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.CitizensNPCRegistry; -import net.citizensnpcs.npc.CitizensTraitManager; +import net.citizensnpcs.npc.CitizensTraitFactory; import net.citizensnpcs.npc.NPCSelector; import net.citizensnpcs.util.Messaging; import net.citizensnpcs.util.StringHelper; @@ -48,6 +48,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import com.google.common.collect.Iterables; @@ -60,7 +61,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { private CitizensNPCRegistry npcRegistry; private Storage saves; // TODO: refactor this, it's used in too many places private NPCSelector selector; - private CitizensTraitManager traitManager; + private CitizensTraitFactory traitFactory; private void despawnNPCs() { Iterator itr = npcRegistry.iterator(); @@ -90,8 +91,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { } @Override - public TraitManager getTraitManager() { - return traitManager; + public TraitFactory getTraitFactory() { + return traitFactory; } @Override @@ -171,7 +172,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { setupStorage(); npcRegistry = new CitizensNPCRegistry(saves); - traitManager = new CitizensTraitManager(); + traitFactory = new CitizensTraitFactory(); selector = new NPCSelector(this); CitizensAPI.setImplementation(this); @@ -188,31 +189,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { public void run() { setupNPCs(); startMetrics(); - } - - private void startMetrics() { - new Thread() { - @Override - public void run() { - try { - Metrics metrics = new Metrics(Citizens.this); - if (metrics.isOptOut()) - return; - metrics.addCustomData(new Metrics.Plotter("Total NPCs") { - @Override - public int getValue() { - return Iterables.size(npcRegistry); - } - }); - - traitManager.addPlotters(metrics.createGraph("traits")); - metrics.start(); - Messaging.log("Metrics started."); - } catch (IOException e) { - Messaging.logF("Unable to start metrics: %s.", e.getMessage()); - } - } - }.start(); + enableSubPlugins(); } }) == -1) { Messaging.severe("Issue enabling plugin. Disabling."); @@ -226,6 +203,48 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { Bukkit.getPluginManager().disablePlugin(this); } + private void enableSubPlugins() { + File root = new File(getDataFolder(), Setting.SUBPLUGIN_FOLDER.asString()); + if (!root.exists() || !root.isDirectory()) + return; + Plugin[] plugins = Bukkit.getPluginManager().loadPlugins(root); + // code beneath modified from CraftServer + for (Plugin plugin : plugins) { + try { + Messaging.logF("Loading %s", plugin.getDescription().getFullName()); + plugin.onLoad(); + } catch (Throwable ex) { + Messaging.severe(ex.getMessage() + " initializing " + plugin.getDescription().getFullName()); + ex.printStackTrace(); + } + } + } + + private void startMetrics() { + new Thread() { + @Override + public void run() { + try { + Metrics metrics = new Metrics(Citizens.this); + if (metrics.isOptOut()) + return; + metrics.addCustomData(new Metrics.Plotter("Total NPCs") { + @Override + public int getValue() { + return Iterables.size(npcRegistry); + } + }); + + traitFactory.addPlotters(metrics.createGraph("traits")); + metrics.start(); + Messaging.log("Metrics started."); + } catch (IOException e) { + Messaging.logF("Unable to start metrics: %s.", e.getMessage()); + } + } + }.start(); + } + private void registerCommands() { commands.setInjector(new Injector(this)); @@ -293,7 +312,11 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { private void setupScripting() { contextClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader()); - // workaround to fix scripts not loading plugin classes properly + // Workaround to fix scripts not loading plugin classes properly. + // The built in Sun Rhino Javascript engine uses the context classloader + // to search for class imports. Since the context classloader only has + // CraftBukkit classes, we replace it with a PluginClassLoader, which + // allows all plugin classes to be imported. } private void setupStorage() { diff --git a/src/main/java/net/citizensnpcs/Settings.java b/src/main/java/net/citizensnpcs/Settings.java index 95911b474..225764757 100644 --- a/src/main/java/net/citizensnpcs/Settings.java +++ b/src/main/java/net/citizensnpcs/Settings.java @@ -71,7 +71,8 @@ public class Settings { STORAGE_TYPE("storage.type", "yaml"), TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 60), TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 30), - TALK_ITEM("npc.text.talk-item", "340"); + TALK_ITEM("npc.text.talk-item", "340"), + SUBPLUGIN_FOLDER("subplugins.folder", "plugins"); protected String path; protected Object value; diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index 7b8f1cc5e..ca54d08d7 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -61,8 +61,8 @@ public class NPCCommands { min = 1, max = 2, permission = "npc.age") - @Requirements(selected = true, ownership = true, types = { EntityType.CHICKEN, EntityType.COW, EntityType.OCELOT, - EntityType.PIG, EntityType.SHEEP, EntityType.VILLAGER, EntityType.WOLF }) + @Requirements(selected = true, ownership = true, types = { EntityType.CHICKEN, EntityType.COW, + EntityType.OCELOT, EntityType.PIG, EntityType.SHEEP, EntityType.VILLAGER, EntityType.WOLF }) public void age(CommandContext args, CommandSender sender, NPC npc) throws CommandException { Age trait = npc.getTrait(Age.class); @@ -90,8 +90,13 @@ public class NPCCommands { Messaging.send(sender, "Age " + (trait.toggle() ? "locked" : "unlocked") + "."); } - @Command(aliases = { "npc" }, usage = "behaviour [scripts]", desc = "Sets the behaviour of a NPC", modifiers = { - "behaviour", "ai" }, min = 2, max = -1) + @Command( + aliases = { "npc" }, + usage = "behaviour [scripts]", + desc = "Sets the behaviour of a NPC", + modifiers = { "behaviour", "ai" }, + min = 2, + max = -1) public void behaviour(CommandContext args, CommandSender sender, NPC npc) throws CommandException { Iterable files = Splitter.on(',').split(args.getJoinedStrings(1, ',')); npc.getTrait(Behaviour.class).addScripts(files); @@ -128,7 +133,8 @@ public class NPCCommands { public void create(CommandContext args, final Player player, NPC npc) { String name = args.getString(1); if (name.length() > 16) { - Messaging.sendError(player, "NPC names cannot be longer than 16 characters. The name has been shortened."); + Messaging.sendError(player, + "NPC names cannot be longer than 16 characters. The name has been shortened."); name = name.substring(0, 15); } EntityType type = EntityType.PLAYER; @@ -141,7 +147,8 @@ public class NPCCommands { } } npc = npcRegistry.createNPC(type, name); - String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(npc.getName()) + " at your location"; + String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(npc.getName()) + + " at your location"; int age = 0; if (args.hasFlag('b')) { @@ -177,13 +184,21 @@ public class NPCCommands { @Command( aliases = { "npc" }, - usage = "despawn", + usage = "despawn (id)", desc = "Despawn a NPC", modifiers = { "despawn" }, min = 1, - max = 1, + max = 2, permission = "npc.despawn") - public void despawn(CommandContext args, CommandSender sender, NPC npc) { + @Requirements + public void despawn(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + if (npc == null || args.argsLength() == 2) { + if (args.argsLength() < 2) + throw new CommandException("No NPC selected."); + npc = CitizensAPI.getNPCRegistry().getById(args.getInteger(2)); + if (npc == null) + throw new CommandException("No NPC found with that ID."); + } npc.getTrait(Spawned.class).setSpawned(false); npc.despawn(); Messaging.send(sender, ChatColor.GREEN + "You despawned " + StringHelper.wrap(npc.getName()) + "."); @@ -351,11 +366,10 @@ public class NPCCommands { public void profession(CommandContext args, CommandSender sender, NPC npc) throws CommandException { String profession = args.getString(1); try { - npc.getTrait(VillagerProfession.class).setProfession(Profession.valueOf(profession.toUpperCase())); - Messaging.send( - sender, - StringHelper.wrap(npc.getName()) + " is now the profession " - + StringHelper.wrap(profession.toUpperCase()) + "."); + npc.getTrait(VillagerProfession.class) + .setProfession(Profession.valueOf(profession.toUpperCase())); + Messaging.send(sender, StringHelper.wrap(npc.getName()) + " is now the profession " + + StringHelper.wrap(profession.toUpperCase()) + "."); } catch (IllegalArgumentException ex) { throw new CommandException("'" + profession + "' is not a valid profession."); } @@ -404,11 +418,13 @@ public class NPCCommands { String oldName = npc.getName(); String newName = args.getString(1); if (newName.length() > 16) { - Messaging.sendError(sender, "NPC names cannot be longer than 16 characters. The name has been shortened."); + Messaging.sendError(sender, + "NPC names cannot be longer than 16 characters. The name has been shortened."); newName = newName.substring(0, 15); } npc.setName(newName); - String msg = String.format("You renamed %s to %s.", StringHelper.wrap(oldName), StringHelper.wrap(newName)); + String msg = String.format("You renamed %s to %s.", StringHelper.wrap(oldName), + StringHelper.wrap(newName)); Messaging.send(sender, ChatColor.GREEN + msg); } @@ -439,22 +455,25 @@ public class NPCCommands { min = 2, max = 2, permission = "npc.spawn") - @Requirements - public void spawn(CommandContext args, Player player, NPC npc) throws CommandException { + @Requirements(ownership = true) + public void spawn(CommandContext args, CommandSender sender, NPC npc) throws CommandException { NPC respawn = npcRegistry.getById(args.getInteger(1)); if (respawn == null) throw new CommandException("No NPC with the ID '" + args.getInteger(1) + "' exists."); - - if (!respawn.getTrait(Owner.class).isOwnedBy(player)) - throw new CommandException("You must be the owner of this NPC to execute that command."); - - if (respawn.spawn(player.getLocation())) { - selector.select(player, respawn); - Messaging.send(player, ChatColor.GREEN + "You respawned " + StringHelper.wrap(respawn.getName()) - + " at your location."); - } else + if (respawn.isSpawned()) throw new CommandException(respawn.getName() + " is already spawned at another location." + " Use '/npc tphere' to teleport the NPC to your location."); + + Location location = respawn.getTrait(CurrentLocation.class).getLocation(); + if (location == null && sender instanceof Player) + location = ((Player) sender).getLocation(); + else + throw new CommandException("No stored location available - command must be used ingame."); + if (respawn.spawn(location)) { + selector.select(sender, respawn); + Messaging.send(sender, ChatColor.GREEN + "You respawned " + StringHelper.wrap(respawn.getName()) + + " at your location."); + } } @Command( @@ -470,11 +489,12 @@ public class NPCCommands { if (!npc.isSpawned()) npc.spawn(npc.getTrait(CurrentLocation.class).getLocation()); player.teleport(npc.getBukkitEntity(), TeleportCause.COMMAND); - Messaging.send(player, ChatColor.GREEN + "You teleported to " + StringHelper.wrap(npc.getName()) + "."); + Messaging.send(player, ChatColor.GREEN + "You teleported to " + StringHelper.wrap(npc.getName()) + + "."); } - @Command(aliases = { "npc" }, usage = "tphere", desc = "Teleport a NPC to your location", modifiers = { "tphere", - "move" }, min = 1, max = 1, permission = "npc.tphere") + @Command(aliases = { "npc" }, usage = "tphere", desc = "Teleport a NPC to your location", modifiers = { + "tphere", "move" }, min = 1, max = 1, permission = "npc.tphere") public void tphere(CommandContext args, Player player, NPC npc) { // Spawn the NPC if it isn't spawned to prevent NPEs if (!npc.isSpawned()) @@ -492,10 +512,11 @@ public class NPCCommands { max = 2, permission = "npc.trait") public void trait(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Trait trait = CitizensAPI.getTraitManager().getTrait(args.getString(1), npc); + Trait trait = CitizensAPI.getTraitFactory().getTrait(args.getString(1)); if (trait == null) throw new CommandException("Trait not found."); npc.addTrait(trait); - Messaging.sendF(sender, ChatColor.GREEN + "Trait %s added successfully.", StringHelper.wrap(trait.getName())); + Messaging.sendF(sender, ChatColor.GREEN + "Trait %s added successfully.", + StringHelper.wrap(trait.getName())); } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index dab1b1847..820a86f94 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -1,6 +1,7 @@ package net.citizensnpcs.npc; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.ai.Navigator; import net.citizensnpcs.api.event.NPCDespawnEvent; import net.citizensnpcs.api.event.NPCSpawnEvent; import net.citizensnpcs.api.exception.NPCLoadException; @@ -8,21 +9,20 @@ import net.citizensnpcs.api.npc.AbstractNPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.trait.Spawned; import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.npc.ai.CitizensAI; +import net.citizensnpcs.npc.ai.CitizensNavigator; import net.citizensnpcs.trait.CurrentLocation; import net.citizensnpcs.util.Messaging; -import net.citizensnpcs.util.StringHelper; import net.minecraft.server.EntityLiving; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.Inventory; +import org.bukkit.metadata.FixedMetadataValue; public abstract class CitizensNPC extends AbstractNPC { - private final CitizensAI ai = new CitizensAI(this); protected EntityLiving mcEntity; + private final CitizensNavigator navigator = new CitizensNavigator(this); protected CitizensNPC(int id, String name) { super(id, name); @@ -47,17 +47,6 @@ public abstract class CitizensNPC extends AbstractNPC { return true; } - @Override - public void destroy() { - super.destroy(); - CitizensAPI.getNPCRegistry().deregister(this); - } - - @Override - public CitizensAI getAI() { - return ai; - } - @Override public LivingEntity getBukkitEntity() { return (LivingEntity) getHandle().getBukkitEntity(); @@ -68,15 +57,13 @@ public abstract class CitizensNPC extends AbstractNPC { } @Override - public org.bukkit.inventory.Inventory getInventory() { - Inventory inventory = Bukkit.getServer().createInventory(this, 36, StringHelper.parseColors(getFullName())); - inventory.setContents(getTrait(net.citizensnpcs.api.trait.trait.Inventory.class).getContents()); - return inventory; + public Navigator getNavigator() { + return navigator; } @Override public Trait getTraitFor(Class clazz) { - return CitizensAPI.getTraitManager().getTrait(clazz, this); + return CitizensAPI.getTraitFactory().getTrait(clazz); } @Override @@ -87,9 +74,10 @@ public abstract class CitizensNPC extends AbstractNPC { public void load(DataKey root) { // Load traits for (DataKey traitKey : root.getRelative("traits").getSubKeys()) { - Trait trait = CitizensAPI.getTraitManager().getTrait(traitKey.name(), this); + Trait trait = CitizensAPI.getTraitFactory().getTrait(traitKey.name()); if (trait == null) { - Messaging.severeF("Skipped missing trait '%s' while loading NPC ID: '%d'. Has the name changed?", + Messaging.severeF( + "Skipped missing trait '%s' while loading NPC ID: '%d'. Has the name changed?", traitKey.name(), getId()); continue; } @@ -135,6 +123,8 @@ public abstract class CitizensNPC extends AbstractNPC { mcEntity.world.addEntity(mcEntity); mcEntity.world.players.remove(mcEntity); + getBukkitEntity().setMetadata(NPC_METADATA_MARKER, + new FixedMetadataValue(CitizensAPI.getPlugin(), true)); // Set the spawned state getTrait(CurrentLocation.class).setLocation(loc); @@ -142,7 +132,7 @@ public abstract class CitizensNPC extends AbstractNPC { // Modify NPC using traits after the entity has been created for (Trait trait : traits.values()) - trait.onNPCSpawn(); + trait.onSpawn(); return true; } @@ -150,10 +140,12 @@ public abstract class CitizensNPC extends AbstractNPC { public void update() { try { super.update(); - ai.update(); + navigator.update(); } catch (Exception ex) { Messaging.logF("Exception while updating %d: %s.", getId(), ex.getMessage()); ex.printStackTrace(); } } + + private static final String NPC_METADATA_MARKER = "NPC"; } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java similarity index 90% rename from src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java rename to src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index cb4df88fc..dfc48bce5 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -8,7 +8,7 @@ import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.TraitInfo; -import net.citizensnpcs.api.trait.TraitManager; +import net.citizensnpcs.api.trait.TraitFactory; import net.citizensnpcs.api.trait.trait.Equipment; import net.citizensnpcs.api.trait.trait.Inventory; import net.citizensnpcs.api.trait.trait.MobType; @@ -30,11 +30,11 @@ import net.citizensnpcs.trait.waypoint.Waypoints; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; -public class CitizensTraitManager implements TraitManager { +public class CitizensTraitFactory implements TraitFactory { private final Map> registered = Maps.newHashMap(); // TODO: find a way to avoid naming conflicts - public CitizensTraitManager() { + public CitizensTraitFactory() { registerTrait(TraitInfo.create(Age.class).withName("age")); registerTrait(TraitInfo.create(CurrentLocation.class).withName("location")); registerTrait(TraitInfo.create(Equipment.class).withName("equipment")); @@ -71,7 +71,7 @@ public class CitizensTraitManager implements TraitManager { } } - private T create(Class trait, NPC npc) { + private T create(Class trait) { try { return trait.newInstance(); } catch (Exception ex) { @@ -81,19 +81,19 @@ public class CitizensTraitManager implements TraitManager { } @Override - public T getTrait(Class clazz, NPC npc) { + public T getTrait(Class clazz) { if (!registered.containsValue(clazz)) return null; - return create(clazz, npc); + return create(clazz); } @Override @SuppressWarnings("unchecked") - public T getTrait(String name, NPC npc) { + public T getTrait(String name) { Class clazz = registered.get(name); if (clazz == null) return null; - return (T) create(clazz, npc); + return (T) create(clazz); } @Override diff --git a/src/main/java/net/citizensnpcs/npc/ai/CitizensAI.java b/src/main/java/net/citizensnpcs/npc/ai/CitizensAI.java deleted file mode 100644 index 57c10f238..000000000 --- a/src/main/java/net/citizensnpcs/npc/ai/CitizensAI.java +++ /dev/null @@ -1,236 +0,0 @@ -package net.citizensnpcs.npc.ai; - -import java.lang.ref.WeakReference; -import java.util.Iterator; -import java.util.List; - -import net.citizensnpcs.api.ai.AI; -import net.citizensnpcs.api.ai.Goal; -import net.citizensnpcs.api.ai.NavigationCallback; -import net.citizensnpcs.api.ai.NavigationCallback.CancelReason; -import net.citizensnpcs.npc.CitizensNPC; - -import org.bukkit.Location; -import org.bukkit.entity.LivingEntity; - -import com.google.common.collect.Lists; - -public class CitizensAI implements AI { - private final List> callbacks = Lists.newArrayList(); - private PathStrategy executing; - private final List executingGoals = Lists.newArrayList(); - private final List goals = Lists.newArrayList(); - private final CitizensNPC npc; - private boolean paused; - private List toRemove = null; - - public CitizensAI(CitizensNPC npc) { - this.npc = npc; - } - - @Override - public void addGoal(int priority, Goal goal) { - if (goals.contains(goal)) - return; - goals.add(new GoalEntry(priority, goal)); - } - - @Override - public void cancelDestination() { - if (executing == null) - return; - executing = null; - for (int i = 0; i < callbacks.size(); ++i) { - NavigationCallback next = callbacks.get(i).get(); - if (next == null || next.onCancel(this, CancelReason.CANCEL)) { - callbacks.remove(i); - } - } - } - - @Override - public boolean hasDestination() { - return executing != null; - } - - private boolean isGoalAllowable(GoalEntry test) { - for (int i = 0; i < goals.size(); ++i) { - GoalEntry item = goals.get(i); - if (item == test) - continue; - if (test.getPriority() >= item.getPriority()) { - if (!test.getGoal().isCompatibleWith(item.getGoal()) && executingGoals.contains(item)) { - return false; - } - } /*else if (executingGoals.contains(item) && !item.goal.requiresUpdates()) { - return false; - }*/ - } - - return true; - } - - public void pause() { - paused = true; - } - - @Override - public void registerNavigationCallback(NavigationCallback callback) { - if (!callbacks.contains(callback)) { - callbacks.add(new WeakReference(callback)); - callback.onAttach(this); - } - } - - @Override - public void removeGoal(Goal goal) { - if (toRemove == null) - toRemove = Lists.newArrayList(); - toRemove.add(goal); - } - - private void removeGoals() { - if (toRemove == null) - return; - for (Goal goal : toRemove) { - Iterator itr = executingGoals.iterator(); - while (itr.hasNext()) { - GoalEntry entry = itr.next(); - if (entry.getGoal().equals(goal)) { - entry.getGoal().reset(); - itr.remove(); - } - } - itr = goals.iterator(); - while (itr.hasNext()) { - GoalEntry entry = itr.next(); - if (entry.getGoal().equals(goal)) - itr.remove(); - } - } - - toRemove = null; - } - - public void resume() { - paused = false; - } - - @Override - public void setDestination(Location destination) { - if (destination == null) - throw new IllegalArgumentException("destination cannot be null"); - if (!npc.isSpawned()) - throw new IllegalStateException("npc is not spawned"); - if (destination.getWorld() != npc.getBukkitEntity().getWorld()) - throw new IllegalArgumentException("location is not in the same world"); - - boolean replaced = executing != null; - executing = new MCNavigationStrategy(npc, destination); - - for (int i = 0; i < callbacks.size(); ++i) { - NavigationCallback next = callbacks.get(i).get(); - if (next == null || (replaced && next.onCancel(this, CancelReason.REPLACE)) || next.onBegin(this)) { - callbacks.remove(i); - } - } - } - - @Override - public void setTarget(LivingEntity target, boolean aggressive) { - if (target == null) - throw new IllegalArgumentException("target cannot be null"); - - boolean replaced = executing != null; - executing = new MCTargetStrategy(npc, target, aggressive); - - for (int i = 0; i < callbacks.size(); ++i) { - NavigationCallback next = callbacks.get(i).get(); - if (next == null || (replaced && next.onCancel(this, CancelReason.REPLACE)) || next.onBegin(this)) { - callbacks.remove(i); - } - } - } - - public void update() { - if (paused || !npc.isSpawned()) { - return; - } - - if (executing != null && executing.update()) { - executing = null; - for (int i = 0; i < callbacks.size(); ++i) { - NavigationCallback next = callbacks.get(i).get(); - if (next == null || next.onCompletion(this)) { - callbacks.remove(i); - } - } - } - removeGoals(); - for (int i = 0; i < goals.size(); ++i) { - GoalEntry entry = goals.get(i); - boolean executing = executingGoals.contains(entry); - - if (executing) { - if (!entry.getGoal().continueExecuting() || !isGoalAllowable(entry)) { - entry.getGoal().reset(); - executingGoals.remove(entry); - } - } else if (entry.getGoal().shouldExecute() && isGoalAllowable(entry)) { - entry.getGoal().start(); - executingGoals.add(entry); - } - } - - for (int i = 0; i < executingGoals.size(); ++i) { - executingGoals.get(i).getGoal().update(); - } - } - - public static class GoalEntry implements Comparable { - private final Goal goal; - private final int priority; - - public GoalEntry(int priority, Goal goal) { - this.priority = priority; - this.goal = goal; - } - - @Override - public int compareTo(GoalEntry o) { - return o.priority > priority ? 1 : o.priority < priority ? -1 : 0; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - GoalEntry other = (GoalEntry) obj; - if (goal == null) { - if (other.goal != null) { - return false; - } - } else if (!goal.equals(other.goal)) { - return false; - } - return true; - } - - public Goal getGoal() { - return goal; - } - - public int getPriority() { - return priority; - } - - @Override - public int hashCode() { - return 31 + ((goal == null) ? 0 : goal.hashCode()); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java b/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java new file mode 100644 index 000000000..90c9c7b1b --- /dev/null +++ b/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java @@ -0,0 +1,137 @@ +package net.citizensnpcs.npc.ai; + +import java.lang.reflect.Field; +import java.util.Map; + +import net.citizensnpcs.api.ai.EntityTarget; +import net.citizensnpcs.api.ai.Navigator; +import net.citizensnpcs.api.ai.TargetType; +import net.citizensnpcs.api.ai.event.NavigationBeginEvent; +import net.citizensnpcs.api.ai.event.NavigationCancelEvent; +import net.citizensnpcs.api.ai.event.NavigationReplaceEvent; +import net.citizensnpcs.npc.CitizensNPC; +import net.minecraft.server.EntityLiving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; + +import com.google.common.collect.Maps; + +public class CitizensNavigator implements Navigator { + private final CitizensNPC npc; + private float speed; + private PathStrategy executing; + + public CitizensNavigator(CitizensNPC npc) { + this.npc = npc; + this.speed = getSpeedFor(npc.getHandle()); + } + + public void update() { + if (executing == null) + return; + boolean finished = executing.update(); + if (finished) { + Bukkit.getPluginManager().callEvent(new NavigationCompleteEvent(this)); + executing = null; + } + } + + @Override + public void cancelNavigation() { + if (executing != null) { + Bukkit.getPluginManager().callEvent(new NavigationCancelEvent(this)); + } + executing = null; + } + + @Override + public float getSpeed() { + return speed; + } + + @Override + public EntityTarget getEntityTarget() { + return executing instanceof EntityTarget ? (EntityTarget) executing : null; + } + + @Override + public Location getTargetAsLocation() { + return executing.getTargetAsLocation(); + } + + @Override + public TargetType getTargetType() { + return executing.getTargetType(); + } + + @Override + public boolean isNavigating() { + return executing != null; + } + + @Override + public void setSpeed(float speed) { + this.speed = speed; + } + + @Override + public void setTarget(LivingEntity target, boolean aggressive) { + PathStrategy newStrategy = new MCTargetStrategy(npc, target, aggressive, speed); + switchStrategyTo(newStrategy); + } + + private void switchStrategyTo(PathStrategy newStrategy) { + if (executing != null) + Bukkit.getPluginManager().callEvent(new NavigationReplaceEvent(this)); + + executing = newStrategy; + + Bukkit.getPluginManager().callEvent(new NavigationBeginEvent(this)); + } + + @Override + public void setTarget(Location target) { + PathStrategy newStrategy = new MCNavigationStrategy(npc, target, speed); + switchStrategyTo(newStrategy); + } + + private float getSpeedFor(EntityLiving from) { + EntityType entityType = from.getBukkitEntity().getType(); + Float cached = MOVEMENT_SPEEDS.get(entityType); + if (cached != null) + return cached; + if (SPEED_FIELD == null) { + MOVEMENT_SPEEDS.put(entityType, DEFAULT_SPEED); + return DEFAULT_SPEED; + } + try { + float speed = SPEED_FIELD.getFloat(from); + MOVEMENT_SPEEDS.put(entityType, speed); + return speed; + } catch (IllegalAccessException ex) { + ex.printStackTrace(); + return DEFAULT_SPEED; + } + } + + private static final float DEFAULT_SPEED = 0.3F; + private static final Map MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class); + private static Field SPEED_FIELD; + static { + MOVEMENT_SPEEDS.put(EntityType.IRON_GOLEM, 0.15F); + MOVEMENT_SPEEDS.put(EntityType.CHICKEN, 0.25F); + MOVEMENT_SPEEDS.put(EntityType.COW, 0.2F); + MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F); + MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F); + MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F); + try { + SPEED_FIELD = EntityLiving.class.getDeclaredField("bb"); + SPEED_FIELD.setAccessible(true); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java index 214a490a1..e2e9fa698 100644 --- a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java +++ b/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java @@ -1,60 +1,37 @@ package net.citizensnpcs.npc.ai; -import java.lang.reflect.Field; -import java.util.Map; - +import net.citizensnpcs.api.ai.TargetType; import net.citizensnpcs.npc.CitizensNPC; import net.minecraft.server.EntityLiving; import net.minecraft.server.Navigation; import org.bukkit.Location; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -import com.google.common.collect.Maps; - public class MCNavigationStrategy implements PathStrategy { - private final EntityLiving entity; private final Navigation navigation; + private final Location target; - MCNavigationStrategy(final CitizensNPC npc, final Location dest) { - entity = npc.getHandle(); - if (npc.getBukkitEntity() instanceof Player) { + MCNavigationStrategy(final CitizensNPC npc, Location dest, float speed) { + this(npc.getHandle(), dest); + navigation.a(dest.getX(), dest.getY(), dest.getZ(), speed); + + } + + MCNavigationStrategy(EntityLiving entity, EntityLiving target, float speed) { + this(entity, target.getBukkitEntity().getLocation()); + navigation.a(target, speed); + } + + private MCNavigationStrategy(EntityLiving entity, Location target) { + this.target = target; + if (entity.getBukkitEntity() instanceof Player) { entity.onGround = true; // not sure of a better way around this - if onGround is false, then // navigation won't execute, and calling entity.move doesn't // entirely fix the problem. } navigation = entity.al(); - navigation.a(dest.getX(), dest.getY(), dest.getZ(), getSpeed(npc.getHandle())); - - } - - MCNavigationStrategy(EntityLiving entity, EntityLiving target) { - this.entity = entity; - if (entity.getBukkitEntity() instanceof Player) { - entity.onGround = true; // see above - } - navigation = entity.al(); - navigation.a(target, getSpeed(entity)); - } - - private float getSpeed(EntityLiving from) { - Float cached = MOVEMENT_SPEEDS.get(from.getBukkitEntity().getType()); - if (cached != null) - return cached; - if (SPEED_FIELD == null) { - MOVEMENT_SPEEDS.put(from.getBukkitEntity().getType(), DEFAULT_SPEED); - return DEFAULT_SPEED; - } - try { - float speed = SPEED_FIELD.getFloat(from); - MOVEMENT_SPEEDS.put(from.getBukkitEntity().getType(), speed); - return speed; - } catch (IllegalAccessException ex) { - ex.printStackTrace(); - return DEFAULT_SPEED; - } } @Override @@ -62,21 +39,13 @@ public class MCNavigationStrategy implements PathStrategy { return navigation.e(); } - private static final float DEFAULT_SPEED = 0.3F; - private static final Map MOVEMENT_SPEEDS = Maps.newEnumMap(EntityType.class); - private static Field SPEED_FIELD; - static { - MOVEMENT_SPEEDS.put(EntityType.IRON_GOLEM, 0.15F); - MOVEMENT_SPEEDS.put(EntityType.CHICKEN, 0.25F); - MOVEMENT_SPEEDS.put(EntityType.COW, 0.2F); - MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F); - MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F); - MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F); - try { - SPEED_FIELD = EntityLiving.class.getDeclaredField("bb"); - SPEED_FIELD.setAccessible(true); - } catch (Exception ex) { - ex.printStackTrace(); - } + @Override + public Location getTargetAsLocation() { + return target; + } + + @Override + public TargetType getTargetType() { + return TargetType.LOCATION; } } diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java index 9f6e0860e..924c7f9ef 100644 --- a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java +++ b/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java @@ -1,5 +1,7 @@ package net.citizensnpcs.npc.ai; +import net.citizensnpcs.api.ai.EntityTarget; +import net.citizensnpcs.api.ai.TargetType; import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.util.Util; import net.minecraft.server.EntityLiving; @@ -7,17 +9,20 @@ import net.minecraft.server.EntityMonster; import net.minecraft.server.EntityPlayer; import net.minecraft.server.Packet18ArmAnimation; +import org.bukkit.Location; import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.entity.LivingEntity; -public class MCTargetStrategy implements PathStrategy { +public class MCTargetStrategy implements PathStrategy, EntityTarget { private final boolean aggro; private final EntityLiving handle, target; + private final float speed; - public MCTargetStrategy(CitizensNPC handle, LivingEntity target, boolean aggro) { + public MCTargetStrategy(CitizensNPC handle, LivingEntity target, boolean aggro, float speed) { this.handle = handle.getHandle(); this.target = ((CraftLivingEntity) target).getHandle(); this.aggro = aggro; + this.speed = speed; } private boolean canAttack() { @@ -34,7 +39,7 @@ public class MCTargetStrategy implements PathStrategy { public boolean update() { if (target == null || target.dead) return true; - new MCNavigationStrategy(handle, target).update(); + new MCNavigationStrategy(handle, target, speed).update(); handle.getControllerLook().a(target, 10.0F, handle.D()); if (aggro && canAttack()) { if (handle instanceof EntityMonster) { @@ -43,8 +48,8 @@ public class MCTargetStrategy implements PathStrategy { } else if (handle instanceof EntityPlayer) { EntityPlayer humanHandle = (EntityPlayer) handle; humanHandle.attack(target); - Util.sendPacketNearby(handle.getBukkitEntity().getLocation(), new Packet18ArmAnimation(humanHandle, 1), - 64); + Util.sendPacketNearby(handle.getBukkitEntity().getLocation(), new Packet18ArmAnimation( + humanHandle, 1), 64); } } @@ -52,4 +57,24 @@ public class MCTargetStrategy implements PathStrategy { } private static final double ATTACK_DISTANCE = 1.75 * 1.75; + + @Override + public LivingEntity getTarget() { + return (LivingEntity) target.getBukkitEntity(); + } + + @Override + public boolean isAggressive() { + return aggro; + } + + @Override + public Location getTargetAsLocation() { + return getTarget().getLocation(); + } + + @Override + public TargetType getTargetType() { + return TargetType.ENTITY; + } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/ai/NavigationCompleteEvent.java b/src/main/java/net/citizensnpcs/npc/ai/NavigationCompleteEvent.java new file mode 100644 index 000000000..2deacc008 --- /dev/null +++ b/src/main/java/net/citizensnpcs/npc/ai/NavigationCompleteEvent.java @@ -0,0 +1,23 @@ +package net.citizensnpcs.npc.ai; + +import net.citizensnpcs.api.ai.Navigator; +import net.citizensnpcs.api.ai.event.NavigationEvent; + +import org.bukkit.event.HandlerList; + +public class NavigationCompleteEvent extends NavigationEvent { + public NavigationCompleteEvent(Navigator navigator) { + super(navigator); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/net/citizensnpcs/npc/ai/PathStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/PathStrategy.java index 3af3fbe6e..3d4144848 100644 --- a/src/main/java/net/citizensnpcs/npc/ai/PathStrategy.java +++ b/src/main/java/net/citizensnpcs/npc/ai/PathStrategy.java @@ -1,6 +1,13 @@ package net.citizensnpcs.npc.ai; -public interface PathStrategy { +import net.citizensnpcs.api.ai.TargetType; +import org.bukkit.Location; + +public interface PathStrategy { boolean update(); + + Location getTargetAsLocation(); + + TargetType getTargetType(); } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java index eca788a48..98b5d639d 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java @@ -31,8 +31,10 @@ public class CitizensBlazeNPC extends CitizensMobNPC { public EntityBlazeNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -47,5 +49,11 @@ public class CitizensBlazeNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java index c38049555..f4e42add5 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java @@ -27,8 +27,10 @@ public class CitizensCaveSpiderNPC extends CitizensMobNPC { public EntityCaveSpiderNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -41,5 +43,11 @@ public class CitizensCaveSpiderNPC extends CitizensMobNPC { super.z_(); npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java index 822d94351..4e8c37b54 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java @@ -31,8 +31,10 @@ public class CitizensChickenNPC extends CitizensMobNPC { public EntityChickenNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensChickenNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java index 472671225..387c12be3 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java @@ -31,8 +31,10 @@ public class CitizensCowNPC extends CitizensMobNPC { public EntityCowNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensCowNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java index ca495576c..98f4db3ab 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java @@ -32,12 +32,16 @@ public class CitizensCreeperNPC extends CitizensMobNPC { public EntityCreeperNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override public void a(EntityWeatherLighting entityweatherlighting) { + if (npc == null) + super.a(entityweatherlighting); } @Override @@ -51,5 +55,11 @@ public class CitizensCreeperNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java index c4a034054..21ee64e25 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java @@ -27,22 +27,35 @@ public class CitizensEnderDragonNPC extends CitizensMobNPC { public EntityEnderDragonNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override public void d_() { + if (npc == null) + super.d_(); } @Override public void e() { - npc.update(); + if (npc != null) + npc.update(); + else + super.e(); } @Override public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java index dbe100ba7..310890f31 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java @@ -69,12 +69,16 @@ public class CitizensEndermanNPC extends CitizensMobNPC implements Equipable { public EntityEndermanNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override public void d_() { + if (npc == null) + super.d_(); } @Override @@ -89,5 +93,11 @@ public class CitizensEndermanNPC extends CitizensMobNPC implements Equipable { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java index d522d2be3..62526d27f 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java @@ -31,8 +31,10 @@ public class CitizensGhastNPC extends CitizensMobNPC { public EntityGhastNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -47,5 +49,11 @@ public class CitizensGhastNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java index a6ea42179..0c5050f39 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java @@ -27,8 +27,10 @@ public class CitizensGiantNPC extends CitizensMobNPC { public EntityGiantNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -40,5 +42,11 @@ public class CitizensGiantNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java index 0d59da5b1..bb0e01076 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java @@ -48,48 +48,50 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable { Material type = hand == null ? Material.AIR : hand.getType(); // First, determine the slot to edit switch (type) { - case PUMPKIN: - case JACK_O_LANTERN: - case LEATHER_HELMET: - case CHAINMAIL_HELMET: - case GOLD_HELMET: - case IRON_HELMET: - case DIAMOND_HELMET: - if (!equipper.isSneaking()) - slot = 1; - break; - case LEATHER_CHESTPLATE: - case CHAINMAIL_CHESTPLATE: - case GOLD_CHESTPLATE: - case IRON_CHESTPLATE: - case DIAMOND_CHESTPLATE: - if (!equipper.isSneaking()) - slot = 2; - break; - case LEATHER_LEGGINGS: - case CHAINMAIL_LEGGINGS: - case GOLD_LEGGINGS: - case IRON_LEGGINGS: - case DIAMOND_LEGGINGS: - if (!equipper.isSneaking()) - slot = 3; - break; - case LEATHER_BOOTS: - case CHAINMAIL_BOOTS: - case GOLD_BOOTS: - case IRON_BOOTS: - case DIAMOND_BOOTS: - if (!equipper.isSneaking()) - slot = 4; - break; - case AIR: - for (int i = 0; i < 5; i++) { - if (trait.get(i) != null && trait.get(i).getType() != Material.AIR) { - equipper.getWorld().dropItemNaturally(getBukkitEntity().getLocation(), trait.get(i)); - trait.set(i, null); + case PUMPKIN: + case JACK_O_LANTERN: + case LEATHER_HELMET: + case CHAINMAIL_HELMET: + case GOLD_HELMET: + case IRON_HELMET: + case DIAMOND_HELMET: + if (!equipper.isSneaking()) + slot = 1; + break; + case LEATHER_CHESTPLATE: + case CHAINMAIL_CHESTPLATE: + case GOLD_CHESTPLATE: + case IRON_CHESTPLATE: + case DIAMOND_CHESTPLATE: + if (!equipper.isSneaking()) + slot = 2; + break; + case LEATHER_LEGGINGS: + case CHAINMAIL_LEGGINGS: + case GOLD_LEGGINGS: + case IRON_LEGGINGS: + case DIAMOND_LEGGINGS: + if (!equipper.isSneaking()) + slot = 3; + break; + case LEATHER_BOOTS: + case CHAINMAIL_BOOTS: + case GOLD_BOOTS: + case IRON_BOOTS: + case DIAMOND_BOOTS: + if (!equipper.isSneaking()) + slot = 4; + break; + case AIR: + for (int i = 0; i < 5; i++) { + if (trait.get(i) != null && trait.get(i).getType() != Material.AIR) { + equipper.getWorld().dropItemNaturally(getBukkitEntity().getLocation(), trait.get(i)); + trait.set(i, null); + } } - } - Messaging.sendF(equipper, "%shad all of its items removed.", getName()); + Messaging.sendF(equipper, "%shad all of its items removed.", getName()); + default: + break; } // Drop any previous equipment on the ground if (trait.get(slot) != null && trait.get(slot).getType() != Material.AIR) diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java index d5d4c33c9..f3ace3910 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java @@ -27,8 +27,10 @@ public class CitizensIronGolemNPC extends CitizensMobNPC { public EntityIronGolemNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -39,7 +41,14 @@ public class CitizensIronGolemNPC extends CitizensMobNPC { @Override public void z_() { super.z_(); - npc.update(); + if (npc != null) + npc.update(); + } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java index f6543b380..c4ce98771 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java @@ -31,9 +31,11 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC { public EntityMagmaCubeNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - setSize(3); - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + setSize(3); + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -48,5 +50,11 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java index e240ed7ca..1de97fc46 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java @@ -31,8 +31,10 @@ public class CitizensMushroomCowNPC extends CitizensMobNPC { public EntityMushroomCowNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensMushroomCowNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java index ad7f3b015..a620ddeab 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java @@ -31,8 +31,10 @@ public class CitizensOcelotNPC extends CitizensMobNPC { public EntityOcelotNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensOcelotNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java index b607dd935..bb7ac7b77 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java @@ -58,12 +58,16 @@ public class CitizensPigNPC extends CitizensMobNPC implements Equipable { public EntityPigNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override public void a(EntityWeatherLighting entityweatherlighting) { + if (npc == null) + super.a(entityweatherlighting); } @Override @@ -77,5 +81,11 @@ public class CitizensPigNPC extends CitizensMobNPC implements Equipable { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java index c30865538..435433822 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java @@ -31,8 +31,10 @@ public class CitizensPigZombieNPC extends CitizensMobNPC { public EntityPigZombieNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -47,5 +49,11 @@ public class CitizensPigZombieNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java index f6a593277..167779da4 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java @@ -49,7 +49,8 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable { equipper.setItemInHand(hand); } else { getTrait(WoolColor.class).setColor(DyeColor.WHITE); - Messaging.send(equipper, StringHelper.wrap(getName()) + " is now " + StringHelper.wrap("white") + "."); + Messaging.send(equipper, StringHelper.wrap(getName()) + " is now " + StringHelper.wrap("white") + + "."); } } @@ -68,8 +69,10 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable { public EntitySheepNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -83,5 +86,11 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java index 8d4784345..2139cda36 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java @@ -31,8 +31,10 @@ public class CitizensSilverfishNPC extends CitizensMobNPC { public EntitySilverfishNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensSilverfishNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java index 9a246d7c8..d1c44b8cf 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java @@ -31,8 +31,10 @@ public class CitizensSkeletonNPC extends CitizensMobNPC { public EntitySkeletonNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensSkeletonNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java index 75d2b9405..133b44077 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java @@ -31,9 +31,11 @@ public class CitizensSlimeNPC extends CitizensMobNPC { public EntitySlimeNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - setSize(3); - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + setSize(3); + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -47,5 +49,11 @@ public class CitizensSlimeNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java index 98b5f10b4..75c764b0b 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java @@ -27,8 +27,10 @@ public class CitizensSnowmanNPC extends CitizensMobNPC { public EntitySnowmanNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -41,5 +43,11 @@ public class CitizensSnowmanNPC extends CitizensMobNPC { super.z_(); npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java index 654cf5a3d..fce102fbe 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java @@ -31,8 +31,10 @@ public class CitizensSpiderNPC extends CitizensMobNPC { public EntitySpiderNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensSpiderNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java index 74fe80ffd..47cf51c21 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java @@ -31,8 +31,10 @@ public class CitizensSquidNPC extends CitizensMobNPC { public EntitySquidNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -47,5 +49,11 @@ public class CitizensSquidNPC extends CitizensMobNPC { public NPC getNPC() { return npc; } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java index eea34b8bb..02c88c347 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java @@ -31,8 +31,10 @@ public class CitizensVillagerNPC extends CitizensMobNPC { public EntityVillagerNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensVillagerNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java index 1b58b8b34..0a7e9e09f 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java @@ -31,8 +31,10 @@ public class CitizensWolfNPC extends CitizensMobNPC { public EntityWolfNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensWolfNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java index ab6bda757..ef1ddcc11 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java @@ -31,8 +31,10 @@ public class CitizensZombieNPC extends CitizensMobNPC { public EntityZombieNPC(World world, NPC npc) { super(world); this.npc = (CitizensNPC) npc; - goalSelector = new PathfinderGoalSelector(); - targetSelector = new PathfinderGoalSelector(); + if (npc != null) { + goalSelector = new PathfinderGoalSelector(); + targetSelector = new PathfinderGoalSelector(); + } } @Override @@ -46,5 +48,11 @@ public class CitizensZombieNPC extends CitizensMobNPC { if (npc != null) npc.update(); } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java index aa83e7677..a49358b50 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java @@ -81,4 +81,10 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder { a(aW, aX); X = yaw; // TODO: this looks jerky } + + @Override + public void b_(double x, double y, double z) { + // when another entity collides, b_ is called to push the NPC + // so we prevent b_ from doing anything. + } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/trait/Age.java b/src/main/java/net/citizensnpcs/trait/Age.java index d3991bd96..36930889b 100644 --- a/src/main/java/net/citizensnpcs/trait/Age.java +++ b/src/main/java/net/citizensnpcs/trait/Age.java @@ -6,7 +6,7 @@ import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Ageable; -public class Age extends Trait implements Runnable, Toggleable { +public class Age extends Trait implements Toggleable { private int age = 0; private boolean ageable = false; private boolean locked = true; @@ -24,7 +24,7 @@ public class Age extends Trait implements Runnable, Toggleable { } @Override - public void onNPCSpawn() { + public void onSpawn() { if (npc instanceof Ageable) { Ageable entity = (Ageable) npc.getBukkitEntity(); entity.setAge(age); diff --git a/src/main/java/net/citizensnpcs/trait/Behaviour.java b/src/main/java/net/citizensnpcs/trait/Behaviour.java index c1316d790..4b22d02b6 100644 --- a/src/main/java/net/citizensnpcs/trait/Behaviour.java +++ b/src/main/java/net/citizensnpcs/trait/Behaviour.java @@ -57,9 +57,9 @@ public class Behaviour extends Trait { } @Override - public void onNPCSpawn() { + public void onSpawn() { for (Entry entry : addedGoals.entrySet()) { - npc.getAI().addGoal(entry.getValue(), entry.getKey()); + npc.getDefaultGoalController().addGoal(entry.getKey(), entry.getValue()); } } @@ -70,7 +70,7 @@ public class Behaviour extends Trait { private void removeGoals() { for (Goal entry : addedGoals.keySet()) { - npc.getAI().removeGoal(entry); + npc.getDefaultGoalController().removeGoal(entry); } } @@ -98,7 +98,7 @@ public class Behaviour extends Trait { if (!npc.isSpawned()) return; for (Entry entry : goals.goals.entrySet()) { - npc.getAI().addGoal(entry.getValue(), entry.getKey()); + npc.getDefaultGoalController().addGoal(entry.getKey(), entry.getValue()); } } @@ -111,7 +111,7 @@ public class Behaviour extends Trait { public static class Goals { private final Map goals = Maps.newHashMap(); - public void addGoal(int priority, Goal goal) { + public void addGoal(Goal goal, int priority) { Validate.notNull(goal); goals.put(goal, priority); } diff --git a/src/main/java/net/citizensnpcs/trait/Controllable.java b/src/main/java/net/citizensnpcs/trait/Controllable.java index 30657b165..11e77c988 100644 --- a/src/main/java/net/citizensnpcs/trait/Controllable.java +++ b/src/main/java/net/citizensnpcs/trait/Controllable.java @@ -11,12 +11,11 @@ import net.minecraft.server.EntityPlayer; import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; //TODO: reduce reliance on CitizensNPC -public class Controllable extends Trait implements Runnable, Listener, Toggleable { +public class Controllable extends Trait implements Toggleable { private boolean enabled; public Controllable(NPC npc) { @@ -86,6 +85,7 @@ public class Controllable extends Trait implements Runnable, Listener, Toggleabl public boolean toggle() { return (enabled = !enabled); } + private static final double AIR_SPEED = 1.5; private static final double GROUND_SPEED = 4; diff --git a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java index 4614c52d9..0cb55c0cd 100644 --- a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java +++ b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java @@ -7,7 +7,7 @@ import net.citizensnpcs.api.util.DataKey; import org.bukkit.Bukkit; import org.bukkit.Location; -public class CurrentLocation extends Trait implements Runnable { +public class CurrentLocation extends Trait { private Location loc; public CurrentLocation() { diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java index 1c8c635d5..2d8de7572 100644 --- a/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -15,7 +15,7 @@ import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -public class LookClose extends Trait implements Runnable, Toggleable { +public class LookClose extends Trait implements Toggleable { private boolean enabled = Setting.DEFAULT_LOOK_CLOSE.asBoolean(); private Player lookingAt; @@ -84,7 +84,7 @@ public class LookClose extends Trait implements Runnable, Toggleable { @Override public void run() { - if (!enabled || npc.getAI().hasDestination()) + if (!enabled || npc.getNavigator().isNavigating()) return; if (hasInvalidTarget()) { findNewTarget(); diff --git a/src/main/java/net/citizensnpcs/trait/Powered.java b/src/main/java/net/citizensnpcs/trait/Powered.java index b41d7445e..5a976e668 100644 --- a/src/main/java/net/citizensnpcs/trait/Powered.java +++ b/src/main/java/net/citizensnpcs/trait/Powered.java @@ -19,7 +19,7 @@ public class Powered extends Trait implements Toggleable { } @Override - public void onNPCSpawn() { + public void onSpawn() { if (npc.getBukkitEntity() instanceof Creeper) ((Creeper) npc.getBukkitEntity()).setPowered(powered); } diff --git a/src/main/java/net/citizensnpcs/trait/Saddle.java b/src/main/java/net/citizensnpcs/trait/Saddle.java index 5a32fb700..86c22bc29 100644 --- a/src/main/java/net/citizensnpcs/trait/Saddle.java +++ b/src/main/java/net/citizensnpcs/trait/Saddle.java @@ -7,10 +7,9 @@ import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Pig; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEntityEvent; -public class Saddle extends Trait implements Toggleable, Listener { +public class Saddle extends Trait implements Toggleable { private boolean pig; private boolean saddle; @@ -24,7 +23,7 @@ public class Saddle extends Trait implements Toggleable, Listener { } @Override - public void onNPCSpawn() { + public void onSpawn() { if (npc.getBukkitEntity() instanceof Pig) { ((Pig) npc.getBukkitEntity()).setSaddle(saddle); pig = true; diff --git a/src/main/java/net/citizensnpcs/trait/Sheared.java b/src/main/java/net/citizensnpcs/trait/Sheared.java index 05e33de8a..e116c979a 100644 --- a/src/main/java/net/citizensnpcs/trait/Sheared.java +++ b/src/main/java/net/citizensnpcs/trait/Sheared.java @@ -7,10 +7,9 @@ import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Sheep; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerShearEntityEvent; -public class Sheared extends Trait implements Toggleable, Listener { +public class Sheared extends Trait implements Toggleable { private boolean sheared; public Sheared() { @@ -23,7 +22,7 @@ public class Sheared extends Trait implements Toggleable, Listener { } @Override - public void onNPCSpawn() { + public void onSpawn() { ((Sheep) npc.getBukkitEntity()).setSheared(sheared); } diff --git a/src/main/java/net/citizensnpcs/trait/VillagerProfession.java b/src/main/java/net/citizensnpcs/trait/VillagerProfession.java index 8638ad6a0..b89cab228 100644 --- a/src/main/java/net/citizensnpcs/trait/VillagerProfession.java +++ b/src/main/java/net/citizensnpcs/trait/VillagerProfession.java @@ -24,7 +24,7 @@ public class VillagerProfession extends Trait { } @Override - public void onNPCSpawn() { + public void onSpawn() { if (npc.getBukkitEntity() instanceof Villager) ((Villager) npc.getBukkitEntity()).setProfession(profession); } diff --git a/src/main/java/net/citizensnpcs/trait/WoolColor.java b/src/main/java/net/citizensnpcs/trait/WoolColor.java index 354480d29..e3006428c 100644 --- a/src/main/java/net/citizensnpcs/trait/WoolColor.java +++ b/src/main/java/net/citizensnpcs/trait/WoolColor.java @@ -8,10 +8,9 @@ import net.citizensnpcs.api.util.DataKey; import org.bukkit.DyeColor; import org.bukkit.entity.Sheep; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.entity.SheepDyeWoolEvent; -public class WoolColor extends Trait implements Listener { +public class WoolColor extends Trait { private DyeColor color = DyeColor.WHITE; boolean sheep = false; @@ -29,7 +28,7 @@ public class WoolColor extends Trait implements Listener { } @Override - public void onNPCSpawn() { + public void onSpawn() { if (npc.getBukkitEntity() instanceof Sheep) { ((Sheep) npc.getBukkitEntity()).setColor(color); sheep = true; diff --git a/src/main/java/net/citizensnpcs/trait/text/Text.java b/src/main/java/net/citizensnpcs/trait/text/Text.java index 015d90381..44dc9bf68 100644 --- a/src/main/java/net/citizensnpcs/trait/text/Text.java +++ b/src/main/java/net/citizensnpcs/trait/text/Text.java @@ -96,7 +96,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve } @Override - public void onNPCSpawn() { + public void onSpawn() { if (text.isEmpty()) populateDefaultText(); } diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java b/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java index c675591d6..f467325ea 100644 --- a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java +++ b/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java @@ -3,7 +3,6 @@ package net.citizensnpcs.trait.waypoint; import java.util.Iterator; import java.util.List; -import net.citizensnpcs.api.ai.NavigationCallback; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.editor.Editor; import net.citizensnpcs.util.Messaging; @@ -21,7 +20,7 @@ import org.bukkit.event.player.PlayerItemHeldEvent; import com.google.common.collect.Lists; public class LinearWaypointProvider implements WaypointProvider, Iterable { - private final GenericWaypointCallback callback = new GenericWaypointCallback(this); + private final PassiveWaypointCycler cycler = new PassiveWaypointCycler(this); private final List waypoints = Lists.newArrayList(); @Override @@ -41,35 +40,37 @@ public class LinearWaypointProvider implements WaypointProvider, Iterable%d, %d, %d", location.getBlockX(), location.getBlockY(), - location.getBlockZ()); + return String.format("%d, %d, %d", location.getBlockX(), + location.getBlockY(), location.getBlockZ()); } @EventHandler - @SuppressWarnings("unused") public void onPlayerInteract(PlayerInteractEvent event) { if (!event.getPlayer().equals(player) || event.getAction() == Action.PHYSICAL) return; - if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) { + if (event.getAction() == Action.LEFT_CLICK_BLOCK + || event.getAction() == Action.LEFT_CLICK_AIR) { if (event.getClickedBlock() == null) return; Location at = event.getClickedBlock().getLocation(); waypoints.add(Math.max(0, editingSlot), new Waypoint(at)); editingSlot = Math.min(editingSlot + 1, waypoints.size()); - Messaging.send(player, String.format("Added a waypoint at (" + formatLoc(at) - + ") (%d, %d)", editingSlot + 1, waypoints.size())); + Messaging.send( + player, + String.format("Added a waypoint at (" + formatLoc(at) + + ") (%d, %d)", editingSlot + 1, waypoints.size())); } else if (waypoints.size() > 0) { editingSlot = Math.min(0, Math.max(waypoints.size() - 1, editingSlot)); waypoints.remove(editingSlot); editingSlot = Math.max(0, editingSlot - 1); - Messaging.send(player, String.format("Removed a waypoint (%d remaining) (%d)", - waypoints.size(), editingSlot + 1)); + Messaging.send(player, String.format( + "Removed a waypoint (%d remaining) (%d)", waypoints.size(), + editingSlot + 1)); } - callback.onProviderChanged(); + cycler.onProviderChanged(); } @EventHandler - @SuppressWarnings("unused") public void onPlayerItemHeldChange(PlayerItemHeldEvent event) { if (!event.getPlayer().equals(player) || waypoints.size() == 0) return; @@ -97,11 +98,6 @@ public class LinearWaypointProvider implements WaypointProvider, Iterable iterator() { return waypoints.iterator(); @@ -111,15 +107,15 @@ public class LinearWaypointProvider implements WaypointProvider, Iterable itr; private final Iterable provider; - public GenericWaypointCallback(Iterable provider) { + public PassiveWaypointCycler(Iterable provider) { this.provider = provider; } @@ -26,24 +21,7 @@ public class GenericWaypointCallback extends NavigationCallback { } } - @Override - public void onAttach(AI ai) { - this.ai = ai; - executing |= !ai.hasDestination(); - if (!executing) - return; - if (dest == null) { - ensureItr(); - if (itr.hasNext()) { - dest = itr.next().getLocation(); - } - } - if (dest != null) { - ai.setDestination(dest); - } - } - - @Override + /*@Override public boolean onCancel(AI ai, CancelReason reason) { if (hackfix) { hackfix = false; @@ -90,5 +68,8 @@ public class GenericWaypointCallback extends NavigationCallback { if (dest != null) { ai.setDestination(dest); } + }*/ + + public void onProviderChanged() { } } diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java b/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java index 720cd6a27..ed48f1c66 100644 --- a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java +++ b/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java @@ -1,7 +1,5 @@ package net.citizensnpcs.trait.waypoint; -import net.citizensnpcs.api.ai.AI; -import net.citizensnpcs.api.ai.NavigationCallback; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.editor.Editor; @@ -18,14 +16,6 @@ public interface WaypointProvider { */ public Editor createEditor(Player player); - /** - * Returns the {@link NavigationCallback} linked to this provider. This will - * be linked to the NPC's {@link AI}. - * - * @return The callback in use - */ - public NavigationCallback getCallback(); - /** * Loads from the specified {@link DataKey}. * @@ -34,7 +24,11 @@ public interface WaypointProvider { */ public void load(DataKey key); - public void onAttach(); + /** + * Called when the NPC attached to this provider's {@link Waypoints} is + * spawned. + */ + public void onSpawn(); /** * Saves to the specified {@link DataKey}. diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java b/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java index 6f738a725..10ec896e7 100644 --- a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java +++ b/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java @@ -49,8 +49,9 @@ public class Waypoints extends Trait { } @Override - public void onNPCSpawn() { - npc.getAI().registerNavigationCallback(provider.getCallback()); + public void onSpawn() { + if (provider != null) + provider.onSpawn(); } @Override