graphs = Collections.synchronizedSet(new HashSet());
+
/**
* Unique server id
*/
@@ -134,6 +98,11 @@ public class Metrics {
*/
private final Object optOutLock = new Object();
+ /**
+ * The plugin this metrics submits for
+ */
+ private final Plugin plugin;
+
/**
* Id of the scheduled task
*/
@@ -164,6 +133,23 @@ public class Metrics {
guid = configuration.getString("guid");
}
+ /**
+ * Adds a custom data plotter to the default graph
+ *
+ * @param plotter
+ */
+ public void addCustomData(final Plotter plotter) {
+ if (plotter == null) {
+ throw new IllegalArgumentException("Plotter cannot be null");
+ }
+
+ // Add the plotter to the graph o/
+ defaultGraph.addPlotter(plotter);
+
+ // Ensure the default graph is included in the submitted graphs
+ graphs.add(defaultGraph);
+ }
+
/**
* Construct and create a Graph that can be used to separate specific
* plotters to their own graphs on the metrics website. Plotters can be
@@ -189,99 +175,27 @@ public class Metrics {
}
/**
- * Adds a custom data plotter to the default graph
+ * Disables metrics for the server by setting "opt-out" to true in the
+ * config file and canceling the metrics task.
*
- * @param plotter
+ * @throws IOException
*/
- public void addCustomData(final Plotter plotter) {
- if (plotter == null) {
- throw new IllegalArgumentException("Plotter cannot be null");
- }
-
- // Add the plotter to the graph o/
- defaultGraph.addPlotter(plotter);
-
- // Ensure the default graph is included in the submitted graphs
- graphs.add(defaultGraph);
- }
-
- /**
- * Start measuring statistics. This will immediately create an async
- * repeating task as the plugin and send the initial data to the metrics
- * backend, and then after that it will post in increments of PING_INTERVAL
- * * 1200 ticks.
- *
- * @return True if statistics measuring is running, otherwise false.
- */
- public boolean start() {
+ public void disable() throws IOException {
+ // This has to be synchronized or it can collide with the check in the
+ // task.
synchronized (optOutLock) {
- // Did we opt out?
- if (isOptOut()) {
- return false;
+ // Check if the server owner has already set opt-out, if not, set
+ // it.
+ if (!isOptOut()) {
+ configuration.set("opt-out", true);
+ configuration.save(configurationFile);
}
- // Is metrics already running?
- if (taskId >= 0) {
- return true;
+ // Disable Task, if it is running
+ if (taskId > 0) {
+ this.plugin.getServer().getScheduler().cancelTask(taskId);
+ taskId = -1;
}
-
- // Begin hitting the server with glorious data
- taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
-
- private boolean firstPost = true;
-
- @Override
- public void run() {
- try {
- // This has to be synchronized or it can collide with
- // the disable method.
- synchronized (optOutLock) {
- // Disable Task, if it is running and the server
- // owner decided to opt-out
- if (isOptOut() && taskId > 0) {
- plugin.getServer().getScheduler().cancelTask(taskId);
- taskId = -1;
- }
- }
-
- // We use the inverse of firstPost because if it is the
- // first time we are posting,
- // it is not a interval ping, so it evaluates to FALSE
- // Each time thereafter it will evaluate to TRUE, i.e
- // PING!
- postPlugin(!firstPost);
-
- // After the first post we set firstPost to false
- // Each post thereafter will be a ping
- firstPost = false;
- } catch (IOException e) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
- }
- }
- }, 0, PING_INTERVAL * 1200);
-
- return true;
- }
- }
-
- /**
- * Has the server owner denied plugin metrics?
- *
- * @return
- */
- public boolean isOptOut() {
- synchronized (optOutLock) {
- try {
- // Reload the metrics file
- configuration.load(CONFIG_FILE);
- } catch (IOException ex) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
- return true;
- } catch (InvalidConfigurationException ex) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
- return true;
- }
- return configuration.getBoolean("opt-out", false);
}
}
@@ -310,27 +224,38 @@ public class Metrics {
}
/**
- * Disables metrics for the server by setting "opt-out" to true in the
- * config file and canceling the metrics task.
+ * Check if mineshafter is present. If it is, we need to bypass it to send
+ * POST requests
*
- * @throws IOException
+ * @return
*/
- public void disable() throws IOException {
- // This has to be synchronized or it can collide with the check in the
- // task.
- synchronized (optOutLock) {
- // Check if the server owner has already set opt-out, if not, set
- // it.
- if (!isOptOut()) {
- configuration.set("opt-out", true);
- configuration.save(configurationFile);
- }
+ private boolean isMineshafterPresent() {
+ try {
+ Class.forName("mineshafter.MineServer");
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
- // Disable Task, if it is running
- if (taskId > 0) {
- this.plugin.getServer().getScheduler().cancelTask(taskId);
- taskId = -1;
+ /**
+ * Has the server owner denied plugin metrics?
+ *
+ * @return
+ */
+ public boolean isOptOut() {
+ synchronized (optOutLock) {
+ try {
+ // Reload the metrics file
+ configuration.load(CONFIG_FILE);
+ } catch (IOException ex) {
+ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
+ return true;
+ } catch (InvalidConfigurationException ex) {
+ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
+ return true;
}
+ return configuration.getBoolean("opt-out", false);
}
}
@@ -444,51 +369,64 @@ public class Metrics {
}
/**
- * Check if mineshafter is present. If it is, we need to bypass it to send
- * POST requests
+ * Start measuring statistics. This will immediately create an async
+ * repeating task as the plugin and send the initial data to the metrics
+ * backend, and then after that it will post in increments of PING_INTERVAL
+ * * 1200 ticks.
*
- * @return
+ * @return True if statistics measuring is running, otherwise false.
*/
- private boolean isMineshafterPresent() {
- try {
- Class.forName("mineshafter.MineServer");
+ public boolean start() {
+ synchronized (optOutLock) {
+ // Did we opt out?
+ if (isOptOut()) {
+ return false;
+ }
+
+ // Is metrics already running?
+ if (taskId >= 0) {
+ return true;
+ }
+
+ // Begin hitting the server with glorious data
+ taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
+
+ private boolean firstPost = true;
+
+ @Override
+ public void run() {
+ try {
+ // This has to be synchronized or it can collide with
+ // the disable method.
+ synchronized (optOutLock) {
+ // Disable Task, if it is running and the server
+ // owner decided to opt-out
+ if (isOptOut() && taskId > 0) {
+ plugin.getServer().getScheduler().cancelTask(taskId);
+ taskId = -1;
+ }
+ }
+
+ // We use the inverse of firstPost because if it is the
+ // first time we are posting,
+ // it is not a interval ping, so it evaluates to FALSE
+ // Each time thereafter it will evaluate to TRUE, i.e
+ // PING!
+ postPlugin(!firstPost);
+
+ // After the first post we set firstPost to false
+ // Each post thereafter will be a ping
+ firstPost = false;
+ } catch (IOException e) {
+ Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
+ }
+ }
+ }, 0, PING_INTERVAL * 1200);
+
return true;
- } catch (Exception e) {
- return false;
}
}
- /**
- *
- * Encode a key/value data pair to be used in a HTTP post request. This
- * INCLUDES a & so the first key/value pair MUST be included manually, e.g:
- *
- *
- * StringBuffer data = new StringBuffer();
- * data.append(encode("guid")).append('=').append(encode(guid));
- * encodeDataPair(data, "version", description.getVersion());
- *
- *
- * @param buffer
- * @param key
- * @param value
- * @return
- */
- private static void encodeDataPair(final StringBuilder buffer, final String key, final String value)
- throws UnsupportedEncodingException {
- buffer.append('&').append(encode(key)).append('=').append(encode(value));
- }
-
- /**
- * Encode text as UTF-8
- *
- * @param text
- * @return
- */
- private static String encode(final String text) throws UnsupportedEncodingException {
- return URLEncoder.encode(text, "UTF-8");
- }
-
/**
* Represents a custom graph on the website
*/
@@ -509,15 +447,6 @@ public class Metrics {
this.name = name;
}
- /**
- * Gets the graph's name
- *
- * @return
- */
- public String getName() {
- return name;
- }
-
/**
* Add a plotter to the graph, which will be used to plot entries
*
@@ -527,13 +456,23 @@ public class Metrics {
plotters.add(plotter);
}
+ @Override
+ public boolean equals(final Object object) {
+ if (!(object instanceof Graph)) {
+ return false;
+ }
+
+ final Graph graph = (Graph) object;
+ return graph.name.equals(name);
+ }
+
/**
- * Remove a plotter from the graph
+ * Gets the graph's name
*
- * @param plotter
+ * @return
*/
- public void removePlotter(final Plotter plotter) {
- plotters.remove(plotter);
+ public String getName() {
+ return name;
}
/**
@@ -550,14 +489,13 @@ public class Metrics {
return name.hashCode();
}
- @Override
- public boolean equals(final Object object) {
- if (!(object instanceof Graph)) {
- return false;
- }
-
- final Graph graph = (Graph) object;
- return graph.name.equals(name);
+ /**
+ * Remove a plotter from the graph
+ *
+ * @param plotter
+ */
+ public void removePlotter(final Plotter plotter) {
+ plotters.remove(plotter);
}
}
@@ -588,12 +526,15 @@ public class Metrics {
this.name = name;
}
- /**
- * Get the current value for the plotted point
- *
- * @return
- */
- public abstract int getValue();
+ @Override
+ public boolean equals(final Object object) {
+ if (!(object instanceof Plotter)) {
+ return false;
+ }
+
+ final Plotter plotter = (Plotter) object;
+ return plotter.name.equals(name) && plotter.getValue() == getValue();
+ }
/**
* Get the column name for the plotted point
@@ -605,26 +546,85 @@ public class Metrics {
}
/**
- * Called after the website graphs have been updated
+ * Get the current value for the plotted point
+ *
+ * @return
*/
- public void reset() {
- }
+ public abstract int getValue();
@Override
public int hashCode() {
return getColumnName().hashCode() + getValue();
}
- @Override
- public boolean equals(final Object object) {
- if (!(object instanceof Plotter)) {
- return false;
- }
-
- final Plotter plotter = (Plotter) object;
- return plotter.name.equals(name) && plotter.getValue() == getValue();
+ /**
+ * Called after the website graphs have been updated
+ */
+ public void reset() {
}
}
+ /**
+ * The base url of the metrics domain
+ */
+ private static final String BASE_URL = "http://mcstats.org";
+
+ /**
+ * The file where guid and opt out is stored in
+ */
+ private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml";
+
+ /**
+ * The separator to use for custom data. This MUST NOT change unless you are
+ * hosting your own version of metrics and want to change it.
+ */
+ private static final String CUSTOM_DATA_SEPARATOR = "~~";
+
+ /**
+ * Interval of time to ping (in minutes)
+ */
+ private static final int PING_INTERVAL = 10;
+
+ /**
+ * The url used to report a server's status
+ */
+ private static final String REPORT_URL = "/report/%s";
+
+ /**
+ * The current revision number
+ */
+ private final static int REVISION = 5;
+
+ /**
+ * Encode text as UTF-8
+ *
+ * @param text
+ * @return
+ */
+ private static String encode(final String text) throws UnsupportedEncodingException {
+ return URLEncoder.encode(text, "UTF-8");
+ }
+
+ /**
+ *
+ * Encode a key/value data pair to be used in a HTTP post request. This
+ * INCLUDES a & so the first key/value pair MUST be included manually, e.g:
+ *
+ *
+ * StringBuffer data = new StringBuffer();
+ * data.append(encode("guid")).append('=').append(encode(guid));
+ * encodeDataPair(data, "version", description.getVersion());
+ *
+ *
+ * @param buffer
+ * @param key
+ * @param value
+ * @return
+ */
+ private static void encodeDataPair(final StringBuilder buffer, final String key, final String value)
+ throws UnsupportedEncodingException {
+ buffer.append('&').append(encode(key)).append('=').append(encode(value));
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/Settings.java b/src/main/java/net/citizensnpcs/Settings.java
index 65f39f97a..bc26cd53e 100644
--- a/src/main/java/net/citizensnpcs/Settings.java
+++ b/src/main/java/net/citizensnpcs/Settings.java
@@ -23,9 +23,9 @@ public class Settings {
for (Setting setting : Setting.values()) {
if (!root.keyExists(setting.path)) {
Messaging.logF("Writing default setting: '%s'", setting.path);
- setting.set(root);
+ setting.setAtKey(root);
} else
- setting.load(root);
+ setting.loadFromKey(root);
}
save();
@@ -35,7 +35,7 @@ public class Settings {
config.load();
for (Setting setting : Setting.values())
if (root.keyExists(setting.path))
- setting.load(root);
+ setting.loadFromKey(root);
save();
}
@@ -56,7 +56,7 @@ public class Settings {
DEFAULT_TALK_CLOSE("npc.default.talk-close", false),
DEFAULT_TEXT("npc.default.text.0", "Hi, I'm !") {
@Override
- public void load(DataKey root) {
+ public void loadFromKey(DataKey root) {
List list = new ArrayList();
for (DataKey key : root.getRelative("npc.default.text").getSubKeys())
list.add(key.getString(""));
@@ -69,6 +69,7 @@ public class Settings {
SERVER_OWNS_NPCS("npc.server-ownership", false),
STORAGE_FILE("storage.file", "saves.yml"),
STORAGE_TYPE("storage.type", "yaml"),
+ SUBPLUGIN_FOLDER("subplugins.folder", "plugins"),
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");
@@ -109,12 +110,12 @@ public class Settings {
return value.toString();
}
- protected void set(DataKey root) {
- root.setRaw(path, value);
+ protected void loadFromKey(DataKey root) {
+ value = root.getRaw(path);
}
- protected void load(DataKey root) {
- value = root.getRaw(path);
+ protected void setAtKey(DataKey root) {
+ root.setRaw(path, value);
}
}
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/command/CommandManager.java b/src/main/java/net/citizensnpcs/command/CommandManager.java
index 26e95359d..8a3696210 100644
--- a/src/main/java/net/citizensnpcs/command/CommandManager.java
+++ b/src/main/java/net/citizensnpcs/command/CommandManager.java
@@ -198,6 +198,11 @@ public class CommandManager {
|| commands.containsKey(command.toLowerCase() + " *");
}
+ // Returns whether a player has permission.
+ private boolean hasPermission(CommandSender sender, String perm) {
+ return sender.hasPermission("citizens." + perm);
+ }
+
// Returns whether a player has access to a command.
private boolean hasPermission(Method method, CommandSender sender) {
Command cmd = method.getAnnotation(Command.class);
@@ -207,11 +212,6 @@ public class CommandManager {
return false;
}
- // Returns whether a player has permission.
- private boolean hasPermission(CommandSender sender, String perm) {
- return sender.hasPermission("citizens." + perm);
- }
-
/*
* Register an class that contains commands (denoted by Command. If no
* dependency injector is specified, then the methods of the class will be
diff --git a/src/main/java/net/citizensnpcs/command/Requirements.java b/src/main/java/net/citizensnpcs/command/Requirements.java
index b2afbfd9f..9b78ea1c6 100644
--- a/src/main/java/net/citizensnpcs/command/Requirements.java
+++ b/src/main/java/net/citizensnpcs/command/Requirements.java
@@ -8,11 +8,11 @@ import org.bukkit.entity.EntityType;
@Retention(RetentionPolicy.RUNTIME)
public @interface Requirements {
+ EntityType[] excludedTypes() default { EntityType.UNKNOWN };
+
boolean ownership() default false;
boolean selected() default false;
EntityType[] types() default { EntityType.UNKNOWN };
-
- EntityType[] excludedTypes() default { EntityType.UNKNOWN };
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/command/command/HelpCommands.java b/src/main/java/net/citizensnpcs/command/command/HelpCommands.java
index d73e0d434..88739d326 100644
--- a/src/main/java/net/citizensnpcs/command/command/HelpCommands.java
+++ b/src/main/java/net/citizensnpcs/command/command/HelpCommands.java
@@ -59,24 +59,6 @@ public class HelpCommands {
return lines;
}
- @Command(
- aliases = { "script" },
- usage = "help (page)",
- desc = "Script help menu",
- modifiers = { "help" },
- min = 1,
- max = 2,
- permission = "script.help")
- @Requirements
- public void scriptHelp(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
- int page = args.argsLength() == 2 ? args.getInteger(1) : 1;
- Paginator paginator = new Paginator().header("Script Help");
- for (String line : getLines(sender, "script"))
- paginator.addLine(line);
- if (!paginator.sendPage(sender, page))
- throw new CommandException("The page '" + page + "' does not exist.");
- }
-
@Command(
aliases = { "npc" },
usage = "help (page)",
@@ -94,4 +76,22 @@ public class HelpCommands {
if (!paginator.sendPage(sender, page))
throw new CommandException("The page '" + page + "' does not exist.");
}
+
+ @Command(
+ aliases = { "script" },
+ usage = "help (page)",
+ desc = "Script help menu",
+ modifiers = { "help" },
+ min = 1,
+ max = 2,
+ permission = "script.help")
+ @Requirements
+ public void scriptHelp(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
+ int page = args.argsLength() == 2 ? args.getInteger(1) : 1;
+ Paginator paginator = new Paginator().header("Script Help");
+ for (String line : getLines(sender, "script"))
+ paginator.addLine(line);
+ if (!paginator.sendPage(sender, page))
+ throw new CommandException("The page '" + page + "' does not exist.");
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java
index 7eba59512..ca54d08d7 100644
--- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java
+++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java
@@ -8,8 +8,7 @@ import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCRegistry;
-import net.citizensnpcs.api.npc.character.Character;
-import net.citizensnpcs.api.npc.character.CharacterManager;
+import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.trait.MobType;
import net.citizensnpcs.api.trait.trait.Owner;
import net.citizensnpcs.api.trait.trait.Spawned;
@@ -26,15 +25,14 @@ import net.citizensnpcs.trait.CurrentLocation;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.VillagerProfession;
-import net.citizensnpcs.trait.text.Text;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.Paginator;
import net.citizensnpcs.util.StringHelper;
import org.bukkit.Bukkit;
-import org.bukkit.World;
-import org.bukkit.Location;
import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.EntityType;
@@ -46,7 +44,6 @@ import com.google.common.base.Splitter;
@Requirements(selected = true, ownership = true)
public class NPCCommands {
- private final CharacterManager characterManager = CitizensAPI.getCharacterManager();
private final NPCRegistry npcRegistry;
private final NPCSelector selector;
@@ -64,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);
@@ -93,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);
@@ -103,31 +105,19 @@ public class NPCCommands {
@Command(
aliases = { "npc" },
- usage = "character [character]",
- desc = "Set the character of a NPC",
- modifiers = { "character" },
- min = 2,
- max = 2)
- public void character(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
- String name = args.getString(1).toLowerCase();
- Character character = characterManager.getCharacter(name);
-
- if (character == null)
- throw new CommandException("The character '" + args.getString(1) + "' does not exist.");
- if (npc.getCharacter() != null && npc.getCharacter().getName().equalsIgnoreCase(character.getName()))
- throw new CommandException("The NPC already has the character '" + name + "'.");
- if (!sender.hasPermission("citizens.npc.character." + character.getName())
- && !sender.hasPermission("citizens.npc.character.*") && !sender.hasPermission("citizens.admin"))
- throw new NoPermissionsException();
-
- EntityType type = EntityType.valueOf(npc.getTrait(MobType.class).getType());
- if (!character.getValidTypes().isEmpty() && !character.getValidTypes().contains(type)) {
- Messaging.sendError(sender, "This NPC cannot be given the character '" + character.getName() + "'.");
- return;
+ usage = "controllable",
+ desc = "Toggles whether the NPC can be ridden and controlled",
+ modifiers = { "controllable" },
+ min = 1,
+ max = 1,
+ permission = "npc.controllable")
+ public void controllable(CommandContext args, CommandSender sender, NPC npc) {
+ boolean enabled = npc.getTrait(Controllable.class).toggle();
+ if (enabled) {
+ Messaging.send(sender, StringHelper.wrap(npc.getName()) + " can now be controlled.");
+ } else {
+ Messaging.send(sender, StringHelper.wrap(npc.getName()) + " can no longer be controlled.");
}
- Messaging.send(sender, StringHelper.wrap(npc.getName() + "'s") + " character is now " + StringHelper.wrap(name)
- + ".");
- npc.setCharacter(character);
}
@Command(
@@ -143,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;
@@ -156,25 +147,8 @@ public class NPCCommands {
}
}
npc = npcRegistry.createNPC(type, name);
- String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(npc.getName());
- if (args.hasValueFlag("char")) {
- String character = args.getFlag("char").toLowerCase();
- if (characterManager.getCharacter(character) == null) {
- Messaging.sendError(player, "'" + args.getFlag("char") + "' is not a valid character.");
- return;
- } else {
- Character set = characterManager.getCharacter(character);
- if (!set.getValidTypes().isEmpty() && !set.getValidTypes().contains(type)) {
- Messaging.sendError(player, "The character '" + set.getName() + "' cannot be given the mob type '"
- + type.name().toLowerCase() + "'.");
- npc.remove();
- return;
- }
- npc.setCharacter(characterManager.getCharacter(character));
- msg += " with the character " + StringHelper.wrap(character);
- }
- }
- msg += " at your location";
+ String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(npc.getName())
+ + " at your location";
int age = 0;
if (args.hasFlag('b')) {
@@ -195,32 +169,36 @@ public class NPCCommands {
msg += ".";
// Initialize necessary traits
- npc.addTrait(Owner.class);
if (!Setting.SERVER_OWNS_NPCS.asBoolean())
npc.getTrait(Owner.class).setOwner(player.getName());
npc.getTrait(MobType.class).setType(type.toString());
- npc.addTrait(LookClose.class);
- npc.addTrait(Text.class);
npc.spawn(player.getLocation());
// Set age after entity spawns
if (npc.getBukkitEntity() instanceof Ageable)
npc.getTrait(Age.class).setAge(age);
-
selector.select(player, npc);
Messaging.send(player, msg);
}
@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()) + ".");
@@ -267,17 +245,6 @@ public class NPCCommands {
npcs.add(add);
}
}
-
- if (args.hasValueFlag("char")) {
- String character = args.getFlag("char");
- if (characterManager.getCharacter(character) == null)
- throw new CommandException("'" + character + "' is not a valid character.");
-
- for (NPC add : npcRegistry.getNPCs(characterManager.getCharacter(character).getClass())) {
- if (!npcs.contains(add))
- npcs.add(add);
- }
- }
}
Paginator paginator = new Paginator().header("NPCs");
@@ -308,26 +275,23 @@ public class NPCCommands {
Messaging.send(sender, msg + " when a player is nearby.");
}
- @Command(aliases = { "npc" }, desc = "Show basic NPC information", max = 0)
- public void npc(CommandContext args, CommandSender sender, NPC npc) {
- Messaging.send(sender, StringHelper.wrapHeader(npc.getName()));
- Messaging.send(sender, " ID: " + npc.getId());
- Messaging.send(sender, " Character: "
- + (npc.getCharacter() != null ? npc.getCharacter().getName() : "None"));
- Messaging.send(sender, " Type: " + npc.getTrait(MobType.class).getType());
- }
-
- @Command(aliases = { "npc" }, usage = "moveto", desc = "Teleports a NPC to a given location", modifiers = "moveto",
- min = 1, max = 1, permission = "npc.moveto")
+ @Command(
+ aliases = { "npc" },
+ usage = "moveto",
+ desc = "Teleports a NPC to a given location",
+ modifiers = "moveto",
+ min = 1,
+ max = 1,
+ permission = "npc.moveto")
public void moveto(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
// Spawn the NPC if it isn't spawned to prevent NPEs
if (!npc.isSpawned())
npc.spawn(npc.getTrait(CurrentLocation.class).getLocation());
Location current = npc.getBukkitEntity().getLocation();
Location to = current.clone();
- if (args.hasValueFlag("x"))
+ if (args.hasValueFlag("x"))
to.setX(args.getFlagInteger("x"));
- if (args.hasValueFlag("y"))
+ if (args.hasValueFlag("y"))
to.setY(args.getFlagInteger("y"));
if (args.hasValueFlag("z"))
to.setZ(args.getFlagInteger("z"));
@@ -335,16 +299,24 @@ public class NPCCommands {
to.setYaw((float) args.getFlagDouble("yaw"));
if (args.hasValueFlag("pitch"))
to.setPitch((float) args.getFlagDouble("pitch"));
- if (args.hasValueFlag("world")){
+ if (args.hasValueFlag("world")) {
World world = Bukkit.getWorld(args.getFlag("world"));
if (world == null)
throw new CommandException("Given world not found.");
to.setWorld(world);
}
+
npc.getBukkitEntity().teleport(to, TeleportCause.COMMAND);
Messaging.send(sender, StringHelper.wrap(npc.getName()) + " was teleported to " + to + ".");
}
-
+
+ @Command(aliases = { "npc" }, desc = "Show basic NPC information", max = 0)
+ public void npc(CommandContext args, CommandSender sender, NPC npc) {
+ Messaging.send(sender, StringHelper.wrapHeader(npc.getName()));
+ Messaging.send(sender, " ID: " + npc.getId());
+ Messaging.send(sender, " Type: " + npc.getTrait(MobType.class).getType());
+ }
+
@Command(
aliases = { "npc" },
usage = "owner [name]",
@@ -394,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.");
}
@@ -431,7 +402,7 @@ public class NPCCommands {
throw new CommandException("You must be the owner of this NPC to execute that command.");
if (!player.hasPermission("citizens.npc.remove") && !player.hasPermission("citizens.admin"))
throw new NoPermissionsException();
- npc.remove();
+ npc.destroy();
Messaging.send(player, "You permanently removed " + StringHelper.wrap(npc.getName()) + ".");
}
@@ -447,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);
}
@@ -465,7 +438,7 @@ public class NPCCommands {
permission = "npc.select")
@Requirements(ownership = true)
public void select(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
- NPC toSelect = npcRegistry.getNPC(args.getInteger(1));
+ NPC toSelect = npcRegistry.getById(args.getInteger(1));
if (toSelect == null || !toSelect.getTrait(Spawned.class).shouldSpawn())
throw new CommandException("No NPC with the ID '" + args.getInteger(1) + "' is spawned.");
if (npc != null && toSelect.getId() == npc.getId())
@@ -482,38 +455,24 @@ public class NPCCommands {
min = 2,
max = 2,
permission = "npc.spawn")
- @Requirements
- public void spawn(CommandContext args, Player player, NPC npc) throws CommandException {
- NPC respawn = npcRegistry.getNPC(args.getInteger(1));
+ @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.");
- }
- @Command(
- aliases = { "npc" },
- usage = "controllable",
- desc = "Toggles whether the NPC can be ridden and controlled",
- modifiers = { "controllable" },
- min = 1,
- max = 1,
- permission = "npc.controllable")
- public void controllable(CommandContext args, CommandSender sender, NPC npc) {
- boolean enabled = npc.getTrait(Controllable.class).toggle();
- if (enabled) {
- Messaging.send(sender, StringHelper.wrap(npc.getName()) + " can now be controlled.");
- } else {
- Messaging.send(sender, StringHelper.wrap(npc.getName()) + " can no longer be controlled.");
+ 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.");
}
}
@@ -530,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())
@@ -542,4 +502,21 @@ public class NPCCommands {
npc.getBukkitEntity().teleport(player, TeleportCause.COMMAND);
Messaging.send(player, StringHelper.wrap(npc.getName()) + " was teleported to your location.");
}
+
+ @Command(
+ aliases = { "npc" },
+ usage = "trait [trait name]",
+ desc = "Adds a trait to the NPC",
+ modifiers = { "trait" },
+ min = 2,
+ max = 2,
+ permission = "npc.trait")
+ public void trait(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
+ 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()));
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java b/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java
index 29c07ee6a..7c2bbb4fa 100644
--- a/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java
+++ b/src/main/java/net/citizensnpcs/command/command/ScriptCommands.java
@@ -37,6 +37,10 @@ public class ScriptCommands {
if (!file.exists())
throw new CommandException("The file '" + args.getString(1) + "' doesn't exist!");
CitizensAPI.getScriptCompiler().compile(file).withCallback(new CompileCallback() {
+ @Override
+ public void onCompileTaskFinished() {
+ }
+
@Override
public void onScriptCompiled(ScriptFactory script) {
Script s = script.newInstance();
@@ -47,10 +51,6 @@ public class ScriptCommands {
}
Messaging.send(sender, " Done.");
}
-
- @Override
- public void onCompileTaskFinished() {
- }
}).begin();
sender.sendMessage("Compiling...");
}
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensCharacterManager.java b/src/main/java/net/citizensnpcs/npc/CitizensCharacterManager.java
deleted file mode 100644
index eb77f9936..000000000
--- a/src/main/java/net/citizensnpcs/npc/CitizensCharacterManager.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package net.citizensnpcs.npc;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import net.citizensnpcs.Metrics;
-import net.citizensnpcs.Metrics.Graph;
-import net.citizensnpcs.api.CitizensAPI;
-import net.citizensnpcs.api.exception.CharacterException;
-import net.citizensnpcs.api.npc.character.Character;
-import net.citizensnpcs.api.npc.character.CharacterFactory;
-import net.citizensnpcs.api.npc.character.CharacterManager;
-import net.citizensnpcs.util.StringHelper;
-
-public class CitizensCharacterManager implements CharacterManager {
- private final Map registered = new HashMap();
-
- @Override
- public Character getCharacter(String name) {
- return registered.get(name);
- }
-
- @Override
- public void registerCharacter(CharacterFactory factory) {
- try {
- Character character = factory.create();
- registered.put(character.getName(), character); // TODO: this only
- // allows singletons
- // for characters.
- } catch (CharacterException ex) {
- ex.printStackTrace();
- }
- }
-
- public void addPlotters(Metrics metrics) {
- Graph graph = metrics.createGraph("Character Type Usage");
- for (final Character character : registered.values()) {
- graph.addPlotter(new Metrics.Plotter(StringHelper.capitalize(character.getName())) {
- @Override
- public int getValue() {
- return CitizensAPI.getNPCRegistry().getNPCs(character.getClass()).size();
- }
- });
- }
-
- }
-}
\ 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 dc16732c9..9e0c8c6e7 100644
--- a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java
@@ -1,48 +1,31 @@
package net.citizensnpcs.npc;
-import net.citizensnpcs.Settings.Setting;
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;
import net.citizensnpcs.api.npc.AbstractNPC;
-import net.citizensnpcs.api.npc.character.Character;
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.entity.Player;
-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 CitizensTraitManager traitManager;
+ private final CitizensNavigator navigator = new CitizensNavigator(this);
protected CitizensNPC(int id, String name) {
super(id, name);
- traitManager = (CitizensTraitManager) CitizensAPI.getTraitManager();
- // TODO: remove this dependency
- }
-
- @Override
- public void chat(Player player, String message) {
- Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() + message, this);
- }
-
- @Override
- public void chat(String message) {
- for (Player player : Bukkit.getOnlinePlayers())
- chat(player, message);
}
protected abstract EntityLiving createHandle(Location loc);
@@ -57,18 +40,13 @@ public abstract class CitizensNPC extends AbstractNPC {
Bukkit.getPluginManager().callEvent(new NPCDespawnEvent(this));
boolean keepSelected = getTrait(Spawned.class).shouldSpawn();
if (!keepSelected)
- removeMetadata("selectors", CitizensAPI.getPlugin());
+ data().remove("selectors");
getBukkitEntity().remove();
mcEntity = null;
return true;
}
- @Override
- public CitizensAI getAI() {
- return ai;
- }
-
@Override
public LivingEntity getBukkitEntity() {
return (LivingEntity) getHandle().getBukkitEntity();
@@ -79,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 extends Trait> clazz) {
- return traitManager.getTrait(clazz, this);
+ return CitizensAPI.getTraitFactory().getTrait(clazz);
}
@Override
@@ -96,30 +72,18 @@ public abstract class CitizensNPC extends AbstractNPC {
}
public void load(DataKey root) {
- Character character = CitizensAPI.getCharacterManager().getCharacter(root.getString("character"));
-
- // Load the character if it exists
- if (character != null) {
- try {
- character.load(root.getRelative("characters." + character.getName()));
- } catch (NPCLoadException e) {
- Messaging.severe(String.format("Unable to load character '%s': %s.", character.getName(),
- e.getMessage()));
- }
- setCharacter(character);
- }
-
// Load traits
for (DataKey traitKey : root.getRelative("traits").getSubKeys()) {
- Trait trait = traitManager.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;
}
addTrait(trait);
try {
- getTrait(trait.getClass()).load(traitKey);
+ trait.load(traitKey);
} catch (NPCLoadException ex) {
Messaging.logF("The trait '%s' failed to load for NPC ID: '%d'.", traitKey.name(), getId(),
ex.getMessage());
@@ -134,32 +98,15 @@ public abstract class CitizensNPC extends AbstractNPC {
}
}
- @Override
- public void remove() {
- super.remove();
- CitizensAPI.getNPCRegistry().deregister(this);
- }
-
public void save(DataKey root) {
root.setString("name", getFullName());
- // Save the character if it exists
- if (getCharacter() != null) {
- root.setString("character", getCharacter().getName());
- getCharacter().save(root.getRelative("characters." + getCharacter().getName()));
- }
-
// Save all existing traits
for (Trait trait : traits.values()) {
trait.save(root.getRelative("traits." + trait.getName()));
}
}
- @Override
- public void setName(String name) {
- super.setName(name);
- }
-
@Override
public boolean spawn(Location loc) {
Validate.notNull(loc, "location cannot be null");
@@ -176,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);
@@ -183,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;
}
@@ -191,10 +140,13 @@ public abstract class CitizensNPC extends AbstractNPC {
public void update() {
try {
super.update();
- ai.update();
+ if (isSpawned())
+ 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/CitizensNPCRegistry.java b/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
index abd778c1c..a7ebc7b6b 100644
--- a/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
+++ b/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
@@ -1,17 +1,13 @@
package net.citizensnpcs.npc;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.EnumMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCRegistry;
-import net.citizensnpcs.api.npc.character.Character;
import net.citizensnpcs.api.util.Storage;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.npc.entity.CitizensBlazeNPC;
import net.citizensnpcs.npc.entity.CitizensCaveSpiderNPC;
import net.citizensnpcs.npc.entity.CitizensChickenNPC;
@@ -82,67 +78,17 @@ public class CitizensNPCRegistry implements NPCRegistry {
types.put(EntityType.ZOMBIE, CitizensZombieNPC.class);
}
- public NPC createNPC(EntityType type, int id, String name, Character character) {
+ public NPC createNPC(EntityType type, int id, String name) {
CitizensNPC npc = getByType(type, id, name);
if (npc == null)
throw new IllegalStateException("Could not create NPC.");
- if (character != null)
- npc.setCharacter(character);
npcs.put(npc.getId(), npc);
return npc;
}
@Override
public NPC createNPC(EntityType type, String name) {
- return createNPC(type, name, null);
- }
-
- @Override
- public NPC createNPC(EntityType type, String name, Character character) {
- return createNPC(type, generateUniqueId(), name, character);
- }
-
- private int generateUniqueId() {
- int count = 0;
- while (getNPC(count++) != null)
- ; // TODO: doesn't respect existing save data that might not have
- // been loaded. This causes DBs with NPCs that weren't loaded to
- // have conflicting primary keys.
- return count - 1;
- }
-
- @Override
- public NPC getNPC(Entity entity) {
- Validate.notNull(entity);
- net.minecraft.server.Entity handle = ((CraftEntity) entity).getHandle();
- return handle instanceof NPCHandle ? ((NPCHandle) handle).getNPC() : null;
- }
-
- @Override
- public NPC getNPC(int id) {
- if (id < 0)
- throw new IllegalArgumentException("invalid id");
- return npcs.get(id);
- }
-
- @Override
- public Collection getNPCs(Class extends Character> character) {
- List npcs = new ArrayList();
- for (NPC npc : this) {
- if (npc.getCharacter() != null && npc.getCharacter().getClass().equals(character))
- npcs.add(npc);
- }
- return npcs;
- }
-
- @Override
- public boolean isNPC(Entity entity) {
- return getNPC(entity) != null;
- }
-
- @Override
- public Iterator iterator() {
- return npcs.iterator();
+ return createNPC(type, generateUniqueId(), name);
}
@Override
@@ -163,6 +109,22 @@ public class CitizensNPCRegistry implements NPCRegistry {
}
}
+ private int generateUniqueId() {
+ int count = 0;
+ while (getById(count++) != null)
+ ; // TODO: doesn't respect existing save data that might not have
+ // been loaded. This causes DBs with NPCs that weren't loaded to
+ // have conflicting primary keys.
+ return count - 1;
+ }
+
+ @Override
+ public NPC getById(int id) {
+ if (id < 0)
+ throw new IllegalArgumentException("invalid id");
+ return npcs.get(id);
+ }
+
private CitizensNPC getByType(EntityType type, int id, String name) {
Class extends CitizensNPC> npcClass = types.get(type);
if (npcClass == null)
@@ -173,4 +135,21 @@ public class CitizensNPCRegistry implements NPCRegistry {
return null;
}
}
+
+ @Override
+ public NPC getNPC(Entity entity) {
+ Validate.notNull(entity);
+ net.minecraft.server.Entity handle = ((CraftEntity) entity).getHandle();
+ return handle instanceof NPCHolder ? ((NPCHolder) handle).getNPC() : null;
+ }
+
+ @Override
+ public boolean isNPC(Entity entity) {
+ return getNPC(entity) != null;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return npcs.iterator();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
new file mode 100644
index 000000000..dfc48bce5
--- /dev/null
+++ b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
@@ -0,0 +1,104 @@
+package net.citizensnpcs.npc;
+
+import java.util.Map;
+
+import net.citizensnpcs.Metrics;
+import net.citizensnpcs.Metrics.Graph;
+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.TraitFactory;
+import net.citizensnpcs.api.trait.trait.Equipment;
+import net.citizensnpcs.api.trait.trait.Inventory;
+import net.citizensnpcs.api.trait.trait.MobType;
+import net.citizensnpcs.api.trait.trait.Owner;
+import net.citizensnpcs.api.trait.trait.Spawned;
+import net.citizensnpcs.trait.Age;
+import net.citizensnpcs.trait.Behaviour;
+import net.citizensnpcs.trait.Controllable;
+import net.citizensnpcs.trait.CurrentLocation;
+import net.citizensnpcs.trait.LookClose;
+import net.citizensnpcs.trait.Powered;
+import net.citizensnpcs.trait.Saddle;
+import net.citizensnpcs.trait.Sheared;
+import net.citizensnpcs.trait.VillagerProfession;
+import net.citizensnpcs.trait.WoolColor;
+import net.citizensnpcs.trait.text.Text;
+import net.citizensnpcs.trait.waypoint.Waypoints;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+public class CitizensTraitFactory implements TraitFactory {
+ private final Map> registered = Maps.newHashMap();
+
+ // TODO: find a way to avoid naming conflicts
+ public CitizensTraitFactory() {
+ registerTrait(TraitInfo.create(Age.class).withName("age"));
+ registerTrait(TraitInfo.create(CurrentLocation.class).withName("location"));
+ registerTrait(TraitInfo.create(Equipment.class).withName("equipment"));
+ registerTrait(TraitInfo.create(Inventory.class).withName("inventory"));
+ registerTrait(TraitInfo.create(LookClose.class).withName("lookclose"));
+ registerTrait(TraitInfo.create(MobType.class).withName("type"));
+ registerTrait(TraitInfo.create(Owner.class).withName("owner"));
+ registerTrait(TraitInfo.create(Powered.class).withName("powered"));
+ registerTrait(TraitInfo.create(Saddle.class).withName("saddle"));
+ registerTrait(TraitInfo.create(Sheared.class).withName("sheared"));
+ registerTrait(TraitInfo.create(Spawned.class).withName("spawned"));
+ registerTrait(TraitInfo.create(Text.class).withName("text"));
+ registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession"));
+ registerTrait(TraitInfo.create(Waypoints.class).withName("waypoints"));
+ registerTrait(TraitInfo.create(WoolColor.class).withName("woolcolor"));
+ registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
+ registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
+ }
+
+ public void addPlotters(Graph graph) {
+ for (Map.Entry> entry : registered.entrySet()) {
+ final Class extends Trait> traitClass = entry.getValue();
+ graph.addPlotter(new Metrics.Plotter(entry.getKey()) {
+ @Override
+ public int getValue() {
+ int numberUsingTrait = 0;
+ for (NPC npc : CitizensAPI.getNPCRegistry()) {
+ if (npc.hasTrait(traitClass))
+ ++numberUsingTrait;
+ }
+ return numberUsingTrait;
+ }
+ });
+ }
+ }
+
+ private T create(Class trait) {
+ try {
+ return trait.newInstance();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public T getTrait(Class clazz) {
+ if (!registered.containsValue(clazz))
+ return null;
+ return create(clazz);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T getTrait(String name) {
+ Class extends Trait> clazz = registered.get(name);
+ if (clazz == null)
+ return null;
+ return (T) create(clazz);
+ }
+
+ @Override
+ public void registerTrait(TraitInfo info) {
+ Preconditions.checkNotNull(info, "info cannot be null");
+ registered.put(info.getTraitName(), info.getTraitClass());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java b/src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java
deleted file mode 100644
index a0ae78299..000000000
--- a/src/main/java/net/citizensnpcs/npc/CitizensTraitManager.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package net.citizensnpcs.npc;
-
-import java.lang.reflect.Constructor;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import net.citizensnpcs.api.npc.NPC;
-import net.citizensnpcs.api.trait.Trait;
-import net.citizensnpcs.api.trait.TraitFactory;
-import net.citizensnpcs.api.trait.TraitManager;
-import net.citizensnpcs.api.trait.trait.Equipment;
-import net.citizensnpcs.api.trait.trait.Inventory;
-import net.citizensnpcs.api.trait.trait.MobType;
-import net.citizensnpcs.api.trait.trait.Owner;
-import net.citizensnpcs.api.trait.trait.Spawned;
-import net.citizensnpcs.trait.Age;
-import net.citizensnpcs.trait.Behaviour;
-import net.citizensnpcs.trait.Controllable;
-import net.citizensnpcs.trait.CurrentLocation;
-import net.citizensnpcs.trait.LookClose;
-import net.citizensnpcs.trait.Powered;
-import net.citizensnpcs.trait.Saddle;
-import net.citizensnpcs.trait.Sheared;
-import net.citizensnpcs.trait.VillagerProfession;
-import net.citizensnpcs.trait.WoolColor;
-import net.citizensnpcs.trait.text.Text;
-import net.citizensnpcs.trait.waypoint.Waypoints;
-
-import org.bukkit.plugin.Plugin;
-
-public class CitizensTraitManager implements TraitManager {
- private final Map, Constructor extends Trait>> CACHED_CTORS = new HashMap, Constructor extends Trait>>();
- private final Map>> registered = new HashMap>>();
-
- // TODO: handle Plugin-setting/names better and avoid cruft. also find a
- // way to avoid naming conflicts
- public CitizensTraitManager(Plugin plugin) {
- registerTrait(new TraitFactory(Age.class).withName("age").withPlugin(plugin));
- registerTrait(new TraitFactory(CurrentLocation.class).withName("location").withPlugin(plugin));
- registerTrait(new TraitFactory(Equipment.class).withName("equipment").withPlugin(plugin));
- registerTrait(new TraitFactory(Inventory.class).withName("inventory").withPlugin(plugin));
- registerTrait(new TraitFactory(LookClose.class).withName("lookclose").withPlugin(plugin));
- registerTrait(new TraitFactory(MobType.class).withName("type").withPlugin(plugin));
- registerTrait(new TraitFactory(Owner.class).withName("owner").withPlugin(plugin));
- registerTrait(new TraitFactory(Powered.class).withName("powered").withPlugin(plugin));
- registerTrait(new TraitFactory(Saddle.class).withName("saddle").withPlugin(plugin));
- registerTrait(new TraitFactory(Sheared.class).withName("sheared").withPlugin(plugin));
- registerTrait(new TraitFactory(Spawned.class).withName("spawned").withPlugin(plugin));
- registerTrait(new TraitFactory(Text.class).withName("text").withPlugin(plugin));
- registerTrait(new TraitFactory(VillagerProfession.class).withName("profession").withPlugin(plugin));
- registerTrait(new TraitFactory(Waypoints.class).withName("waypoints").withPlugin(plugin));
- registerTrait(new TraitFactory(WoolColor.class).withName("woolcolor").withPlugin(plugin));
- registerTrait(new TraitFactory(Controllable.class).withName("controllable").withPlugin(plugin));
- registerTrait(new TraitFactory(Behaviour.class).withName("behaviour").withPlugin(plugin));
- }
-
- @SuppressWarnings("unchecked")
- private T create(Class trait, NPC npc) {
- Constructor extends Trait> constructor;
-
- if (!CACHED_CTORS.containsKey(trait)) {
- try {
- // TODO: replace this fixed constructor with a context class
- // which can have extra environment variables.
- constructor = trait.getConstructor(NPC.class);
- if (constructor == null)
- constructor = trait.getConstructor(CitizensNPC.class);
- constructor.setAccessible(true);
- } catch (Exception ex) {
- constructor = null;
- }
- CACHED_CTORS.put(trait, constructor);
- } else
- constructor = CACHED_CTORS.get(trait);
-
- try {
- if (constructor == null || npc == null)
- return trait.newInstance();
- return (T) constructor.newInstance(npc);
- } catch (Exception ex) {
- ex.printStackTrace();
- return null;
- }
- }
-
- @Override
- public T getTrait(Class clazz) {
- return getTrait(clazz, null);
- }
-
- @SuppressWarnings("unchecked")
- public T getTrait(Class clazz, NPC npc) {
- for (Entry>> entry : registered.entrySet()) {
- for (Entry> subEntry : entry.getValue().entrySet()) {
- if (!subEntry.getValue().equals(clazz))
- continue;
- Trait trait = create(subEntry.getValue(), npc);
- if (trait == null)
- return null;
- trait.setPlugin(entry.getKey());
- trait.setName(subEntry.getKey());
- return (T) trait;
- }
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T getTrait(String name) {
- for (Map> entry : registered.values()) {
- if (!entry.containsKey(name))
- continue;
- return (T) create(entry.get(name), null);
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public T getTrait(String name, NPC npc) {
- for (Map> entry : registered.values()) {
- Class extends Trait> clazz = entry.get(name);
- if (clazz == null)
- continue;
- return (T) getTrait(clazz, npc);
- }
- return null;
- }
-
- @Override
- public void registerTrait(TraitFactory factory) {
- Map> map = registered.get(factory.getTraitPlugin());
- if (map == null)
- map = new HashMap>();
- map.put(factory.getTraitName(), factory.getTraitClass());
- registered.put(factory.getTraitPlugin(), map);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/NPCSelector.java b/src/main/java/net/citizensnpcs/npc/NPCSelector.java
index 1b7e2989a..63fec7406 100644
--- a/src/main/java/net/citizensnpcs/npc/NPCSelector.java
+++ b/src/main/java/net/citizensnpcs/npc/NPCSelector.java
@@ -22,15 +22,48 @@ import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
+import com.google.common.collect.Lists;
+
public class NPCSelector implements Listener {
- private final Plugin plugin;
private int consoleSelectedNPC = -1;
+ private final Plugin plugin;
public NPCSelector(Plugin plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
+ public NPC getSelected(CommandSender sender) {
+ if (sender instanceof Player) {
+ List metadata = ((Player) sender).getMetadata("selected");
+ if (metadata.size() == 0)
+ return null;
+ return CitizensAPI.getNPCRegistry().getById(metadata.get(0).asInt());
+ } else {
+ if (consoleSelectedNPC == -1)
+ return null;
+ return CitizensAPI.getNPCRegistry().getById(consoleSelectedNPC);
+ }
+ }
+
+ @EventHandler
+ public void onNPCRemove(NPCRemoveEvent event) {
+ NPC npc = event.getNPC();
+ List selectors = npc.data().get("selectors");
+ if (selectors == null)
+ return;
+ for (String value : selectors) {
+ if (value.equals("console")) {
+ consoleSelectedNPC = -1;
+ } else {
+ Player search = Bukkit.getPlayerExact(value);
+ if (search != null)
+ search.removeMetadata("selected", plugin);
+ }
+ }
+ npc.data().remove("selectors");
+ }
+
@EventHandler
public void onNPCRightClick(NPCRightClickEvent event) {
Player player = event.getClicker();
@@ -48,51 +81,24 @@ public class NPCSelector implements Listener {
}
}
- @EventHandler
- public void onNPCRemove(NPCRemoveEvent event) {
- NPC npc = event.getNPC();
- for (MetadataValue value : npc.getMetadata("selectors")) {
- if (value.asString().equals("console")) {
- consoleSelectedNPC = -1;
- } else {
- Player search = Bukkit.getPlayerExact(value.asString());
- if (search != null)
- search.removeMetadata("selected", plugin);
- }
- }
- npc.removeMetadata("selectors", plugin);
- }
-
public void select(CommandSender sender, NPC npc) {
// Remove existing selection if any
+ List selectors = npc.data().get("selectors", Lists.newArrayList());
if (sender instanceof Player) {
Player player = (Player) sender;
if (player.hasMetadata("selected"))
player.removeMetadata("selected", plugin);
player.setMetadata("selected", new FixedMetadataValue(plugin, npc.getId()));
- npc.setMetadata("selectors", new FixedMetadataValue(plugin, player.getName()));
+ selectors.add(player.getName());
// Remove editor if the player has one
Editor.leave(player);
} else {
consoleSelectedNPC = npc.getId();
- npc.setMetadata("selectors", new FixedMetadataValue(plugin, "console"));
+ selectors.add("console");
}
Bukkit.getPluginManager().callEvent(new NPCSelectEvent(npc, sender));
}
-
- public NPC getSelected(CommandSender sender) {
- if (sender instanceof Player) {
- List metadata = ((Player) sender).getMetadata("selected");
- if (metadata.size() == 0)
- return null;
- return CitizensAPI.getNPCRegistry().getNPC(metadata.get(0).asInt());
- } else {
- if (consoleSelectedNPC == -1)
- return null;
- return CitizensAPI.getNPCRegistry().getNPC(consoleSelectedNPC);
- }
- }
}
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 30ea5a881..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 List toRemove = null;
- private final CitizensNPC npc;
- private boolean paused;
-
- 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);
- }
-
- 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();
- }
- }
-
- 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 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;
- }
-
- public Goal getGoal() {
- return goal;
- }
-
- public int getPriority() {
- return priority;
- }
-
- @Override
- public int hashCode() {
- return 31 + ((goal == null) ? 0 : goal.hashCode());
- }
-
- @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;
- }
- }
-}
\ 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..e036ce185
--- /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 PathStrategy executing;
+ private final CitizensNPC npc;
+ private float speed;
+
+ public CitizensNavigator(CitizensNPC npc) {
+ this.npc = npc;
+ this.speed = getSpeedFor(npc.getHandle());
+ }
+
+ @Override
+ public void cancelNavigation() {
+ if (executing != null) {
+ Bukkit.getPluginManager().callEvent(new NavigationCancelEvent(this));
+ }
+ executing = null;
+ }
+
+ @Override
+ public EntityTarget getEntityTarget() {
+ return executing instanceof EntityTarget ? (EntityTarget) executing : null;
+ }
+
+ @Override
+ public float getSpeed() {
+ return speed;
+ }
+
+ 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;
+ }
+ }
+
+ @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);
+ }
+
+ @Override
+ public void setTarget(Location target) {
+ PathStrategy newStrategy = new MCNavigationStrategy(npc, target, 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));
+ }
+
+ public void update() {
+ if (executing == null)
+ return;
+ boolean finished = executing.update();
+ if (finished) {
+ Bukkit.getPluginManager().callEvent(new NavigationCompleteEvent(this));
+ executing = null;
+ }
+ }
+
+ 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..3d4d5de46 100644
--- a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java
+++ b/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java
@@ -1,82 +1,51 @@
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));
+ @Override
+ public Location getTargetAsLocation() {
+ return target;
}
- 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
+ public TargetType getTargetType() {
+ return TargetType.LOCATION;
}
@Override
public boolean update() {
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();
- }
- }
}
diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java
index 9f6e0860e..e84446ce9 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() {
@@ -30,11 +35,31 @@ public class MCTargetStrategy implements PathStrategy {
return handle.getBukkitEntity().getLocation().distanceSquared(target.getBukkitEntity().getLocation());
}
+ @Override
+ public LivingEntity getTarget() {
+ return (LivingEntity) target.getBukkitEntity();
+ }
+
+ @Override
+ public Location getTargetAsLocation() {
+ return getTarget().getLocation();
+ }
+
+ @Override
+ public TargetType getTargetType() {
+ return TargetType.ENTITY;
+ }
+
+ @Override
+ public boolean isAggressive() {
+ return aggro;
+ }
+
@Override
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 +68,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);
}
}
diff --git a/src/main/java/net/citizensnpcs/npc/ai/NPCHandle.java b/src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
similarity index 77%
rename from src/main/java/net/citizensnpcs/npc/ai/NPCHandle.java
rename to src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
index 183b1078a..63c1a4b72 100644
--- a/src/main/java/net/citizensnpcs/npc/ai/NPCHandle.java
+++ b/src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
@@ -2,6 +2,6 @@ package net.citizensnpcs.npc.ai;
import net.citizensnpcs.api.npc.NPC;
-public interface NPCHandle {
+public interface NPCHolder {
public NPC getNPC();
}
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..43ea83e69 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;
+import net.citizensnpcs.api.ai.TargetType;
+
+import org.bukkit.Location;
+
public interface PathStrategy {
+ Location getTargetAsLocation();
+
+ TargetType getTargetType();
boolean update();
}
\ 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 06aa9f2b9..8efab604e 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensBlazeNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityBlaze;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensBlazeNPC extends CitizensMobNPC {
return (Blaze) getHandle().getBukkitEntity();
}
- public static class EntityBlazeNPC extends EntityBlaze implements NPCHandle {
+ public static class EntityBlazeNPC extends EntityBlaze implements NPCHolder {
private final CitizensNPC npc;
public EntityBlazeNPC(World world) {
@@ -31,8 +31,16 @@ 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
+ 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.
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java
index 4176a7a33..b3fe519fb 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCaveSpiderNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityCaveSpider;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,14 +21,27 @@ public class CitizensCaveSpiderNPC extends CitizensMobNPC {
return (CaveSpider) getHandle().getBukkitEntity();
}
- public static class EntityCaveSpiderNPC extends EntityCaveSpider implements NPCHandle {
+ public static class EntityCaveSpiderNPC extends EntityCaveSpider implements NPCHolder {
private final CitizensNPC npc;
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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -36,10 +49,5 @@ public class CitizensCaveSpiderNPC extends CitizensMobNPC {
super.z_();
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 f5b4fa2e4..c6108dee7 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensChickenNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityChicken;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensChickenNPC extends CitizensMobNPC {
return (Chicken) getHandle().getBukkitEntity();
}
- public static class EntityChickenNPC extends EntityChicken implements NPCHandle {
+ public static class EntityChickenNPC extends EntityChicken implements NPCHolder {
private final CitizensNPC npc;
public EntityChickenNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensChickenNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 4b0ee4309..bf2bed91b 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCowNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityCow;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensCowNPC extends CitizensMobNPC {
return (Cow) getHandle().getBukkitEntity();
}
- public static class EntityCowNPC extends EntityCow implements NPCHandle {
+ public static class EntityCowNPC extends EntityCow implements NPCHolder {
private final CitizensNPC npc;
public EntityCowNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensCowNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 79d83edb6..1c9c7b137 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensCreeperNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityCreeper;
import net.minecraft.server.EntityWeatherLighting;
import net.minecraft.server.PathfinderGoalSelector;
@@ -22,7 +22,7 @@ public class CitizensCreeperNPC extends CitizensMobNPC {
return (Creeper) getHandle().getBukkitEntity();
}
- public static class EntityCreeperNPC extends EntityCreeper implements NPCHandle {
+ public static class EntityCreeperNPC extends EntityCreeper implements NPCHolder {
private final CitizensNPC npc;
public EntityCreeperNPC(World world) {
@@ -32,12 +32,27 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -46,10 +61,5 @@ public class CitizensCreeperNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 651b6a54a..0970dfb04 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensEnderDragonNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityEnderDragon;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,23 +21,36 @@ public class CitizensEnderDragonNPC extends CitizensMobNPC {
return (EnderDragon) getHandle().getBukkitEntity();
}
- public static class EntityEnderDragonNPC extends EntityEnderDragon implements NPCHandle {
+ public static class EntityEnderDragonNPC extends EntityEnderDragon implements NPCHolder {
private final CitizensNPC npc;
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 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.
}
@Override
public void d_() {
+ if (npc == null)
+ super.d_();
}
@Override
public void e() {
- npc.update();
+ if (npc != null)
+ npc.update();
+ else
+ super.e();
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java
index 3d1344116..c85df1657 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensEndermanNPC.java
@@ -5,7 +5,7 @@ import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.editor.Equipable;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.Messaging;
import net.minecraft.server.EntityEnderman;
import net.minecraft.server.PathfinderGoalSelector;
@@ -59,7 +59,7 @@ public class CitizensEndermanNPC extends CitizensMobNPC implements Equipable {
return (Enderman) getHandle().getBukkitEntity();
}
- public static class EntityEndermanNPC extends EntityEnderman implements NPCHandle {
+ public static class EntityEndermanNPC extends EntityEnderman implements NPCHolder {
private final CitizensNPC npc;
public EntityEndermanNPC(World world) {
@@ -69,12 +69,22 @@ 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 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.
}
@Override
public void d_() {
+ if (npc == null)
+ super.d_();
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java
index 27d074c62..6cf0c1f86 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensGhastNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityGhast;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensGhastNPC extends CitizensMobNPC {
return (Ghast) getHandle().getBukkitEntity();
}
- public static class EntityGhastNPC extends EntityGhast implements NPCHandle {
+ public static class EntityGhastNPC extends EntityGhast implements NPCHolder {
private final CitizensNPC npc;
public EntityGhastNPC(World world) {
@@ -31,8 +31,16 @@ 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
+ 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.
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java
index 33d622fb0..80163f369 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensGiantNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityGiantZombie;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,14 +21,22 @@ public class CitizensGiantNPC extends CitizensMobNPC {
return (Giant) getHandle().getBukkitEntity();
}
- public static class EntityGiantNPC extends EntityGiantZombie implements NPCHandle {
+ public static class EntityGiantNPC extends EntityGiantZombie implements NPCHolder {
private final CitizensNPC npc;
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
+ 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.
}
@Override
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 20d1b2d38..6f3f40002 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensIronGolemNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityIronGolem;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,25 +21,34 @@ public class CitizensIronGolemNPC extends CitizensMobNPC {
return (IronGolem) getHandle().getBukkitEntity();
}
- public static class EntityIronGolemNPC extends EntityIronGolem implements NPCHandle {
+ public static class EntityIronGolemNPC extends EntityIronGolem implements NPCHolder {
private final CitizensNPC npc;
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
- public void z_() {
- super.z_();
- npc.update();
+ 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.
}
@Override
public NPC getNPC() {
return npc;
}
+
+ @Override
+ public void z_() {
+ super.z_();
+ if (npc != null)
+ npc.update();
+ }
}
}
\ 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 905c88245..e554bdf84 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensMagmaCubeNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityMagmaCube;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensMagmaCubeNPC extends CitizensMobNPC {
return (MagmaCube) getHandle().getBukkitEntity();
}
- public static class EntityMagmaCubeNPC extends EntityMagmaCube implements NPCHandle {
+ public static class EntityMagmaCubeNPC extends EntityMagmaCube implements NPCHolder {
private final CitizensNPC npc;
public EntityMagmaCubeNPC(World world) {
@@ -31,9 +31,17 @@ 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
+ 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.
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java
index 7a3bfedd0..420a861bc 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensMushroomCowNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityMushroomCow;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensMushroomCowNPC extends CitizensMobNPC {
return (MushroomCow) getHandle().getBukkitEntity();
}
- public static class EntityMushroomCowNPC extends EntityMushroomCow implements NPCHandle {
+ public static class EntityMushroomCowNPC extends EntityMushroomCow implements NPCHolder {
private final CitizensNPC npc;
public EntityMushroomCowNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensMushroomCowNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 9e692b93b..fd3d6148a 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensOcelotNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityOcelot;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensOcelotNPC extends CitizensMobNPC {
return (Ocelot) getHandle().getBukkitEntity();
}
- public static class EntityOcelotNPC extends EntityOcelot implements NPCHandle {
+ public static class EntityOcelotNPC extends EntityOcelot implements NPCHolder {
private final CitizensNPC npc;
public EntityOcelotNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensOcelotNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 bce59f966..936cba18f 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigNPC.java
@@ -4,7 +4,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.editor.Equipable;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.Saddle;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.StringHelper;
@@ -48,7 +48,7 @@ public class CitizensPigNPC extends CitizensMobNPC implements Equipable {
return (Pig) getHandle().getBukkitEntity();
}
- public static class EntityPigNPC extends EntityPig implements NPCHandle {
+ public static class EntityPigNPC extends EntityPig implements NPCHolder {
private final CitizensNPC npc;
public EntityPigNPC(World world) {
@@ -58,12 +58,27 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -72,10 +87,5 @@ public class CitizensPigNPC extends CitizensMobNPC implements Equipable {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 e350a6857..c1303cec5 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensPigZombieNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityPigZombie;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensPigZombieNPC extends CitizensMobNPC {
return (PigZombie) getHandle().getBukkitEntity();
}
- public static class EntityPigZombieNPC extends EntityPigZombie implements NPCHandle {
+ public static class EntityPigZombieNPC extends EntityPigZombie implements NPCHolder {
private final CitizensNPC npc;
public EntityPigZombieNPC(World world) {
@@ -31,8 +31,16 @@ 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
+ 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.
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java
index 218a5c110..1d5d18248 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSheepNPC.java
@@ -4,7 +4,7 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.editor.Equipable;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.Sheared;
import net.citizensnpcs.trait.WoolColor;
import net.citizensnpcs.util.Messaging;
@@ -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")
+ + ".");
}
}
@@ -58,7 +59,7 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable {
return (Sheep) getHandle().getBukkitEntity();
}
- public static class EntitySheepNPC extends EntitySheep implements NPCHandle {
+ public static class EntitySheepNPC extends EntitySheep implements NPCHolder {
private final CitizensNPC npc;
public EntitySheepNPC(World world) {
@@ -68,8 +69,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -78,10 +92,5 @@ public class CitizensSheepNPC extends CitizensMobNPC implements Equipable {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 692872fed..22b4c4f69 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSilverfishNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySilverfish;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensSilverfishNPC extends CitizensMobNPC {
return (Silverfish) getHandle().getBukkitEntity();
}
- public static class EntitySilverfishNPC extends EntitySilverfish implements NPCHandle {
+ public static class EntitySilverfishNPC extends EntitySilverfish implements NPCHolder {
private final CitizensNPC npc;
public EntitySilverfishNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensSilverfishNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 f4ae68741..999633fdd 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSkeletonNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySkeleton;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensSkeletonNPC extends CitizensMobNPC {
return (Skeleton) getHandle().getBukkitEntity();
}
- public static class EntitySkeletonNPC extends EntitySkeleton implements NPCHandle {
+ public static class EntitySkeletonNPC extends EntitySkeleton implements NPCHolder {
private final CitizensNPC npc;
public EntitySkeletonNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensSkeletonNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 341470990..c753daec5 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSlimeNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySlime;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensSlimeNPC extends CitizensMobNPC {
return (Slime) getHandle().getBukkitEntity();
}
- public static class EntitySlimeNPC extends EntitySlime implements NPCHandle {
+ public static class EntitySlimeNPC extends EntitySlime implements NPCHolder {
private final CitizensNPC npc;
public EntitySlimeNPC(World world) {
@@ -31,9 +31,22 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -42,10 +55,5 @@ public class CitizensSlimeNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 4cd639416..93d8d76a3 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSnowmanNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySnowman;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,14 +21,27 @@ public class CitizensSnowmanNPC extends CitizensMobNPC {
return (Snowman) getHandle().getBukkitEntity();
}
- public static class EntitySnowmanNPC extends EntitySnowman implements NPCHandle {
+ public static class EntitySnowmanNPC extends EntitySnowman implements NPCHolder {
private final CitizensNPC npc;
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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -36,10 +49,5 @@ public class CitizensSnowmanNPC extends CitizensMobNPC {
super.z_();
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 50dd406eb..6edf1983a 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSpiderNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySpider;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensSpiderNPC extends CitizensMobNPC {
return (Spider) getHandle().getBukkitEntity();
}
- public static class EntitySpiderNPC extends EntitySpider implements NPCHandle {
+ public static class EntitySpiderNPC extends EntitySpider implements NPCHolder {
private final CitizensNPC npc;
public EntitySpiderNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensSpiderNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 d7bba73dc..336545bc2 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensSquidNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntitySquid;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensSquidNPC extends CitizensMobNPC {
return (Squid) getHandle().getBukkitEntity();
}
- public static class EntitySquidNPC extends EntitySquid implements NPCHandle {
+ public static class EntitySquidNPC extends EntitySquid implements NPCHolder {
private final CitizensNPC npc;
public EntitySquidNPC(World world) {
@@ -31,8 +31,16 @@ 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
+ 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.
}
@Override
diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java
index 62ab5a899..6f9f15dc9 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensVillagerNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityVillager;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensVillagerNPC extends CitizensMobNPC {
return (Villager) getHandle().getBukkitEntity();
}
- public static class EntityVillagerNPC extends EntityVillager implements NPCHandle {
+ public static class EntityVillagerNPC extends EntityVillager implements NPCHolder {
private final CitizensNPC npc;
public EntityVillagerNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensVillagerNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 f76ac35d1..09e6a3464 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensWolfNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityWolf;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensWolfNPC extends CitizensMobNPC {
return (Wolf) getHandle().getBukkitEntity();
}
- public static class EntityWolfNPC extends EntityWolf implements NPCHandle {
+ public static class EntityWolfNPC extends EntityWolf implements NPCHolder {
private final CitizensNPC npc;
public EntityWolfNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensWolfNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 630678b97..137e2b336 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensZombieNPC.java
@@ -3,7 +3,7 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensMobNPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.minecraft.server.EntityZombie;
import net.minecraft.server.PathfinderGoalSelector;
import net.minecraft.server.World;
@@ -21,7 +21,7 @@ public class CitizensZombieNPC extends CitizensMobNPC {
return (Zombie) getHandle().getBukkitEntity();
}
- public static class EntityZombieNPC extends EntityZombie implements NPCHandle {
+ public static class EntityZombieNPC extends EntityZombie implements NPCHolder {
private final CitizensNPC npc;
public EntityZombieNPC(World world) {
@@ -31,8 +31,21 @@ 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
+ 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.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
}
@Override
@@ -41,10 +54,5 @@ public class CitizensZombieNPC extends CitizensMobNPC {
if (npc != null)
npc.update();
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
}
\ 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 65bc5fea6..2dc95065e 100644
--- a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java
+++ b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java
@@ -4,7 +4,7 @@ import java.io.IOException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.CitizensNPC;
-import net.citizensnpcs.npc.ai.NPCHandle;
+import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.npc.network.NPCNetHandler;
import net.citizensnpcs.npc.network.NPCNetworkManager;
import net.citizensnpcs.npc.network.NPCSocket;
@@ -16,7 +16,7 @@ import net.minecraft.server.NetHandler;
import net.minecraft.server.NetworkManager;
import net.minecraft.server.World;
-public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
+public class EntityHumanNPC extends EntityPlayer implements NPCHolder {
private CitizensNPC npc;
public EntityHumanNPC(MinecraftServer minecraftServer, World world, String string,
@@ -42,6 +42,12 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
}
}
+ @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.
+ }
+
@Override
public void F_() {
super.F_();
@@ -57,6 +63,11 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
npc.update();
}
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
private void moveOnCurrentHeading() {
getControllerMove().c();
getControllerLook().a();
@@ -76,9 +87,4 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
a(aW, aX);
X = yaw; // TODO: this looks jerky
}
-
- @Override
- public NPC getNPC() {
- return npc;
- }
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/network/EmptyNetHandler.java b/src/main/java/net/citizensnpcs/npc/network/EmptyNetHandler.java
new file mode 100644
index 000000000..8067a250d
--- /dev/null
+++ b/src/main/java/net/citizensnpcs/npc/network/EmptyNetHandler.java
@@ -0,0 +1,84 @@
+package net.citizensnpcs.npc.network;
+
+import net.minecraft.server.EntityPlayer;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.NetServerHandler;
+import net.minecraft.server.NetworkManager;
+import net.minecraft.server.Packet;
+import net.minecraft.server.Packet102WindowClick;
+import net.minecraft.server.Packet106Transaction;
+import net.minecraft.server.Packet10Flying;
+import net.minecraft.server.Packet130UpdateSign;
+import net.minecraft.server.Packet14BlockDig;
+import net.minecraft.server.Packet15Place;
+import net.minecraft.server.Packet16BlockItemSwitch;
+import net.minecraft.server.Packet255KickDisconnect;
+import net.minecraft.server.Packet28EntityVelocity;
+import net.minecraft.server.Packet3Chat;
+import net.minecraft.server.Packet51MapChunk;
+
+public class EmptyNetHandler extends NetServerHandler {
+ public EmptyNetHandler(MinecraftServer minecraftServer, NetworkManager networkManager, EntityPlayer entityPlayer) {
+ super(minecraftServer, networkManager, entityPlayer);
+ }
+
+ @Override
+ public void a() {
+ }
+
+ @Override
+ public void a(Packet102WindowClick packet) {
+ }
+
+ @Override
+ public void a(Packet106Transaction packet) {
+ }
+
+ @Override
+ public void a(Packet10Flying packet) {
+ }
+
+ @Override
+ public void a(Packet130UpdateSign packet) {
+ }
+
+ @Override
+ public void a(Packet14BlockDig packet) {
+ }
+
+ @Override
+ public void a(Packet15Place packet) {
+ }
+
+ @Override
+ public void a(Packet16BlockItemSwitch packet) {
+ }
+
+ @Override
+ public void a(Packet255KickDisconnect packet) {
+ }
+
+ @Override
+ public void a(Packet28EntityVelocity packet) {
+ }
+
+ @Override
+ public void a(Packet3Chat packet) {
+ }
+
+ @Override
+ public void a(Packet51MapChunk packet) {
+ }
+
+ @Override
+ public void a(String string, Object[] objects) {
+ }
+
+ @Override
+ public void sendMessage(String string) {
+ }
+
+ @Override
+ public void sendPacket(Packet packet) {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/network/EmptyNetworkManager.java b/src/main/java/net/citizensnpcs/npc/network/EmptyNetworkManager.java
new file mode 100644
index 000000000..daacf89f9
--- /dev/null
+++ b/src/main/java/net/citizensnpcs/npc/network/EmptyNetworkManager.java
@@ -0,0 +1,52 @@
+package net.citizensnpcs.npc.network;
+
+import java.lang.reflect.Field;
+import java.net.Socket;
+
+import net.minecraft.server.NetHandler;
+import net.minecraft.server.NetworkManager;
+import net.minecraft.server.Packet;
+
+public class EmptyNetworkManager extends NetworkManager {
+
+ public EmptyNetworkManager(Socket socket, String string, NetHandler netHandler) {
+ super(socket, string, netHandler);
+
+ try {
+ // the field above the 3 synchronized lists
+ Field f = NetworkManager.class.getDeclaredField("l");
+ f.setAccessible(true);
+ f.set(this, false);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ public void a() {
+ }
+
+ @Override
+ public void a(NetHandler netHandler) {
+ }
+
+ @Override
+ public void a(String s, Object... objects) {
+ }
+
+ @Override
+ public void b() {
+ }
+
+ @Override
+ public void d() {
+ }
+
+ @Override
+ public int e() {
+ return 0;
+ }
+
+ @Override
+ public void queue(Packet packet) {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/network/EmptySocket.java b/src/main/java/net/citizensnpcs/npc/network/EmptySocket.java
new file mode 100644
index 000000000..e68200db0
--- /dev/null
+++ b/src/main/java/net/citizensnpcs/npc/network/EmptySocket.java
@@ -0,0 +1,20 @@
+package net.citizensnpcs.npc.network;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+public class EmptySocket extends Socket {
+
+ @Override
+ public InputStream getInputStream() {
+ return new ByteArrayInputStream(new byte[10]);
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return new ByteArrayOutputStream();
+ }
+}
\ 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 a74c1092c..36930889b 100644
--- a/src/main/java/net/citizensnpcs/trait/Age.java
+++ b/src/main/java/net/citizensnpcs/trait/Age.java
@@ -1,20 +1,18 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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 locked = true;
private boolean ageable = false;
- private final NPC npc;
+ private boolean locked = true;
- public Age(NPC npc) {
- this.npc = npc;
+ public Age() {
+ super("age");
}
@Override
@@ -26,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 2c2e973dc..1f3759d86 100644
--- a/src/main/java/net/citizensnpcs/trait/Behaviour.java
+++ b/src/main/java/net/citizensnpcs/trait/Behaviour.java
@@ -8,7 +8,6 @@ import java.util.Map.Entry;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.Goal;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.scripting.CompileCallback;
import net.citizensnpcs.api.scripting.ScriptFactory;
import net.citizensnpcs.api.trait.Trait;
@@ -31,7 +30,6 @@ public class Behaviour extends Trait {
return new File(rootFolder, arg0);
}
};
- private final NPC npc;
private final File rootFolder = new File(CitizensAPI.getScriptFolder(), "behaviours");
private final List scripts = Lists.newArrayList();
{
@@ -39,8 +37,8 @@ public class Behaviour extends Trait {
rootFolder.mkdirs();
}
- public Behaviour(NPC npc) {
- this.npc = npc;
+ public Behaviour() {
+ super("behaviour");
}
public void addScripts(Iterable scripts) {
@@ -58,21 +56,21 @@ public class Behaviour extends Trait {
addScripts(Splitter.on(",").split(scripts));
}
- @Override
- public void onNPCSpawn() {
- for (Entry entry : addedGoals.entrySet()) {
- npc.getAI().addGoal(entry.getValue(), entry.getKey());
- }
- }
-
@Override
public void onRemove() {
removeGoals();
}
+ @Override
+ public void onSpawn() {
+ for (Entry entry : addedGoals.entrySet()) {
+ npc.getDefaultGoalController().addGoal(entry.getKey(), entry.getValue());
+ }
+ }
+
private void removeGoals() {
for (Goal entry : addedGoals.keySet()) {
- npc.getAI().removeGoal(entry);
+ npc.getDefaultGoalController().removeGoal(entry);
}
}
@@ -100,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());
}
}
@@ -113,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 b6a6eba86..11e77c988 100644
--- a/src/main/java/net/citizensnpcs/trait/Controllable.java
+++ b/src/main/java/net/citizensnpcs/trait/Controllable.java
@@ -5,30 +5,32 @@ import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
-import net.citizensnpcs.npc.CitizensNPC;
import net.minecraft.server.EntityLiving;
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 {
- private final CitizensNPC npc;
+public class Controllable extends Trait implements Toggleable {
private boolean enabled;
public Controllable(NPC npc) {
- this.npc = (CitizensNPC) npc;
+ super("controllable");
+ }
+
+ private EntityLiving getHandle() {
+ return ((CraftLivingEntity) npc.getBukkitEntity()).getHandle();
}
private void jump() {
- boolean allowed = npc.getHandle().onGround;
+ boolean allowed = getHandle().onGround;
if (!allowed)
return;
- npc.getHandle().motY = JUMP_VELOCITY;
+ getHandle().motY = JUMP_VELOCITY;
// TODO: make jumping work in liquid or make liquids float the npc
}
@@ -43,7 +45,7 @@ public class Controllable extends Trait implements Runnable, Listener, Toggleabl
return;
EntityPlayer handle = ((CraftPlayer) event.getPlayer()).getHandle();
Action performed = event.getAction();
- if (performed == Action.PHYSICAL || !handle.equals(npc.getHandle().passenger))
+ if (performed == Action.PHYSICAL || !handle.equals(getHandle().passenger))
return;
if (performed == Action.LEFT_CLICK_AIR || performed == Action.LEFT_CLICK_BLOCK) {
jump();
@@ -55,20 +57,20 @@ public class Controllable extends Trait implements Runnable, Listener, Toggleabl
if (!npc.isSpawned() || !event.getNPC().equals(npc))
return;
EntityPlayer handle = ((CraftPlayer) event.getClicker()).getHandle();
- if (npc.getHandle().passenger != null) {
- if (npc.getHandle().passenger == handle) {
+ if (getHandle().passenger != null) {
+ if (getHandle().passenger == handle) {
event.getClicker().leaveVehicle();
}
return;
}
- handle.setPassengerOf(npc.getHandle());
+ handle.setPassengerOf(getHandle());
}
@Override
public void run() {
- if (!npc.isSpawned() || npc.getHandle().passenger == null)
+ if (!npc.isSpawned() || getHandle().passenger == null)
return;
- EntityLiving handle = npc.getHandle();
+ EntityLiving handle = getHandle();
boolean onGround = handle.onGround;
handle.motX += handle.passenger.motX * (onGround ? GROUND_SPEED : AIR_SPEED);
handle.motZ += handle.passenger.motZ * (onGround ? GROUND_SPEED : AIR_SPEED);
@@ -79,12 +81,13 @@ public class Controllable extends Trait implements Runnable, Listener, Toggleabl
key.setBoolean("enabled", enabled);
}
- private static final double GROUND_SPEED = 4;
- private static final double AIR_SPEED = 1.5;
- private static final double JUMP_VELOCITY = 0.6;
-
@Override
public boolean toggle() {
return (enabled = !enabled);
}
+
+ private static final double AIR_SPEED = 1.5;
+ private static final double GROUND_SPEED = 4;
+
+ private static final double JUMP_VELOCITY = 0.6;
}
diff --git a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java
index c4a4eb91a..0cb55c0cd 100644
--- a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java
+++ b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java
@@ -1,29 +1,23 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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;
- private final NPC npc;
- public CurrentLocation(NPC npc) {
- this.npc = npc;
+ public CurrentLocation() {
+ super("location");
}
public Location getLocation() {
return loc;
}
- public void setLocation(Location loc) {
- this.loc = loc;
- }
-
@Override
public void load(DataKey key) throws NPCLoadException {
if (Bukkit.getWorld(key.getString("world")) == null)
@@ -56,6 +50,10 @@ public class CurrentLocation extends Trait implements Runnable {
key.setDouble("pitch", loc.getPitch());
}
+ public void setLocation(Location loc) {
+ this.loc = loc;
+ }
+
@Override
public String toString() {
return "CurrentLocation{" + loc + "}";
diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java
index 2fbab0bfd..2d8de7572 100644
--- a/src/main/java/net/citizensnpcs/trait/LookClose.java
+++ b/src/main/java/net/citizensnpcs/trait/LookClose.java
@@ -6,7 +6,6 @@ import java.util.List;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.minecraft.server.EntityLiving;
@@ -16,13 +15,12 @@ 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;
- private final NPC npc;
- public LookClose(NPC npc) {
- this.npc = npc;
+ public LookClose() {
+ super("lookclose");
}
private void faceEntity(Entity from, Entity at) {
@@ -49,23 +47,6 @@ public class LookClose extends Trait implements Runnable, Toggleable {
handle.X = handle.yaw;
}
- @Override
- public void load(DataKey key) throws NPCLoadException {
- enabled = key.getBoolean("");
- }
-
- @Override
- public void run() {
- if (!enabled || npc.getAI().hasDestination())
- return;
- if (hasInvalidTarget()) {
- findNewTarget();
- }
- if (lookingAt != null) {
- faceEntity(npc.getBukkitEntity(), lookingAt);
- }
- }
-
private void findNewTarget() {
List nearby = npc.getBukkitEntity().getNearbyEntities(2.5, 5, 2.5);
Collections.sort(nearby, new Comparator() {
@@ -96,6 +77,23 @@ public class LookClose extends Trait implements Runnable, Toggleable {
return false;
}
+ @Override
+ public void load(DataKey key) throws NPCLoadException {
+ enabled = key.getBoolean("");
+ }
+
+ @Override
+ public void run() {
+ if (!enabled || npc.getNavigator().isNavigating())
+ return;
+ if (hasInvalidTarget()) {
+ findNewTarget();
+ }
+ if (lookingAt != null) {
+ faceEntity(npc.getBukkitEntity(), lookingAt);
+ }
+ }
+
@Override
public void save(DataKey key) {
key.setBoolean("", enabled);
diff --git a/src/main/java/net/citizensnpcs/trait/Powered.java b/src/main/java/net/citizensnpcs/trait/Powered.java
index 582123751..5a976e668 100644
--- a/src/main/java/net/citizensnpcs/trait/Powered.java
+++ b/src/main/java/net/citizensnpcs/trait/Powered.java
@@ -1,18 +1,16 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import org.bukkit.entity.Creeper;
public class Powered extends Trait implements Toggleable {
- private final NPC npc;
private boolean powered;
- public Powered(NPC npc) {
- this.npc = npc;
+ public Powered() {
+ super("powered");
}
@Override
@@ -21,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 6f5629c59..cb7053b82 100644
--- a/src/main/java/net/citizensnpcs/trait/Saddle.java
+++ b/src/main/java/net/citizensnpcs/trait/Saddle.java
@@ -2,22 +2,19 @@ package net.citizensnpcs.trait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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 {
- private final NPC npc;
- private boolean saddle;
+public class Saddle extends Trait implements Toggleable {
private boolean pig;
+ private boolean saddle;
- public Saddle(NPC npc) {
- this.npc = npc;
+ public Saddle() {
+ super("saddle");
}
@Override
@@ -25,8 +22,14 @@ public class Saddle extends Trait implements Toggleable, Listener {
saddle = key.getBoolean("");
}
+ @EventHandler
+ public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
+ if (pig && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getRightClicked())))
+ event.setCancelled(true);
+ }
+
@Override
- public void onNPCSpawn() {
+ public void onSpawn() {
if (npc.getBukkitEntity() instanceof Pig) {
((Pig) npc.getBukkitEntity()).setSaddle(saddle);
pig = true;
@@ -34,12 +37,6 @@ public class Saddle extends Trait implements Toggleable, Listener {
pig = false;
}
- @EventHandler
- public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
- if (pig && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getRightClicked())))
- event.setCancelled(true);
- }
-
@Override
public void save(DataKey key) {
key.setBoolean("", saddle);
diff --git a/src/main/java/net/citizensnpcs/trait/Sheared.java b/src/main/java/net/citizensnpcs/trait/Sheared.java
index 26c4e6a8e..71b821d98 100644
--- a/src/main/java/net/citizensnpcs/trait/Sheared.java
+++ b/src/main/java/net/citizensnpcs/trait/Sheared.java
@@ -2,21 +2,18 @@ package net.citizensnpcs.trait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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 {
- private final NPC npc;
+public class Sheared extends Trait implements Toggleable {
private boolean sheared;
- public Sheared(NPC npc) {
- this.npc = npc;
+ public Sheared() {
+ super("sheared");
}
@Override
@@ -24,17 +21,17 @@ public class Sheared extends Trait implements Toggleable, Listener {
sheared = key.getBoolean("");
}
- @Override
- public void onNPCSpawn() {
- ((Sheep) npc.getBukkitEntity()).setSheared(sheared);
- }
-
@EventHandler
public void onPlayerShearEntityEvent(PlayerShearEntityEvent event) {
if (npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity())))
event.setCancelled(true);
}
+ @Override
+ public void onSpawn() {
+ ((Sheep) npc.getBukkitEntity()).setSheared(sheared);
+ }
+
@Override
public void save(DataKey key) {
key.setBoolean("", sheared);
diff --git a/src/main/java/net/citizensnpcs/trait/VillagerProfession.java b/src/main/java/net/citizensnpcs/trait/VillagerProfession.java
index 786ea71dd..b89cab228 100644
--- a/src/main/java/net/citizensnpcs/trait/VillagerProfession.java
+++ b/src/main/java/net/citizensnpcs/trait/VillagerProfession.java
@@ -1,7 +1,6 @@
package net.citizensnpcs.trait;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
@@ -9,11 +8,10 @@ import org.bukkit.entity.Villager;
import org.bukkit.entity.Villager.Profession;
public class VillagerProfession extends Trait {
- private final NPC npc;
private Profession profession = Profession.FARMER;
- public VillagerProfession(NPC npc) {
- this.npc = npc;
+ public VillagerProfession() {
+ super("profession");
}
@Override
@@ -26,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 a604b3afe..3ffab5102 100644
--- a/src/main/java/net/citizensnpcs/trait/WoolColor.java
+++ b/src/main/java/net/citizensnpcs/trait/WoolColor.java
@@ -2,23 +2,20 @@ package net.citizensnpcs.trait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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;
- private final NPC npc;
boolean sheep = false;
- public WoolColor(NPC npc) {
- this.npc = npc;
+ public WoolColor() {
+ super("woolcolor");
}
@Override
@@ -30,8 +27,14 @@ public class WoolColor extends Trait implements Listener {
}
}
+ @EventHandler
+ public void onSheepDyeWool(SheepDyeWoolEvent event) {
+ if (npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity())))
+ event.setCancelled(true);
+ }
+
@Override
- public void onNPCSpawn() {
+ public void onSpawn() {
if (npc.getBukkitEntity() instanceof Sheep) {
((Sheep) npc.getBukkitEntity()).setColor(color);
sheep = true;
@@ -39,12 +42,6 @@ public class WoolColor extends Trait implements Listener {
sheep = false;
}
- @EventHandler
- public void onSheepDyeWool(SheepDyeWoolEvent event) {
- if (npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity())))
- event.setCancelled(true);
- }
-
@Override
public void save(DataKey key) {
key.setString("", color.name());
diff --git a/src/main/java/net/citizensnpcs/trait/text/Text.java b/src/main/java/net/citizensnpcs/trait/text/Text.java
index 97ae9bf2e..135d68fd3 100644
--- a/src/main/java/net/citizensnpcs/trait/text/Text.java
+++ b/src/main/java/net/citizensnpcs/trait/text/Text.java
@@ -1,15 +1,16 @@
package net.citizensnpcs.trait.text;
import java.util.ArrayList;
-import java.util.Calendar;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.concurrent.TimeUnit;
import net.citizensnpcs.Settings.Setting;
+import net.citizensnpcs.api.event.NPCRightClickEvent;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
@@ -17,6 +18,7 @@ import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.trait.Toggleable;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.Paginator;
+import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityHuman;
import net.minecraft.server.EntityLiving;
@@ -26,19 +28,20 @@ import org.bukkit.conversations.ConversationAbandonedEvent;
import org.bukkit.conversations.ConversationAbandonedListener;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
-public class Text extends Trait implements Runnable, Toggleable, ConversationAbandonedListener {
- private final Map cooldowns = new HashMap();
+public class Text extends Trait implements Runnable, Toggleable, Listener, ConversationAbandonedListener {
+ private final Map cooldowns = new HashMap();
private int currentIndex;
- private final NPC npc;
private final Plugin plugin;
private boolean randomTalker = Setting.DEFAULT_RANDOM_TALKER.asBoolean();
private boolean talkClose = Setting.DEFAULT_TALK_CLOSE.asBoolean();
private final List text = new ArrayList();
- public Text(NPC npc) {
- this.npc = npc;
+ public Text() {
+ super("text");
this.plugin = Bukkit.getPluginManager().getPlugin("Citizens");
}
@@ -92,8 +95,16 @@ public class Text extends Trait implements Runnable, Toggleable, ConversationAba
randomTalker = key.getBoolean("random-talker");
}
+ @EventHandler
+ public void onRightClick(NPCRightClickEvent event) {
+ if (!event.getNPC().equals(npc))
+ return;
+ if (Util.isSettingFulfilled(event.getClicker(), Setting.TALK_ITEM) && !shouldTalkClose())
+ sendText(event.getClicker());
+ }
+
@Override
- public void onNPCSpawn() {
+ public void onSpawn() {
if (text.isEmpty())
populateDefaultText();
}
@@ -116,17 +127,17 @@ public class Text extends Trait implements Runnable, Toggleable, ConversationAba
Player player = (Player) search.getBukkitEntity();
// If the cooldown is not expired, do not send text
if (cooldowns.get(player.getName()) != null) {
- if (!Calendar.getInstance().after(cooldowns.get(player.getName())))
+ if (!new Date().after(cooldowns.get(player.getName())))
return;
cooldowns.remove(player.getName());
}
if (sendText(player)) {
// Add a cooldown if the text was successfully sent
- Calendar wait = Calendar.getInstance();
- wait.add(
- Calendar.SECOND,
- (new Random().nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt()) + Setting.TALK_CLOSE_MINIMUM_COOLDOWN
- .asInt()));
+ Date wait = new Date();
+ int secondsDelta = new Random().nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt())
+ + Setting.TALK_CLOSE_MINIMUM_COOLDOWN.asInt();
+ long millisecondsDelta = TimeUnit.MILLISECONDS.convert(secondsDelta, TimeUnit.SECONDS);
+ wait.setTime(wait.getTime() + millisecondsDelta);
cooldowns.put(player.getName(), wait);
}
}
@@ -162,7 +173,7 @@ public class Text extends Trait implements Runnable, Toggleable, ConversationAba
currentIndex = 0;
index = currentIndex++;
}
- npc.chat(player, text.get(index));
+ Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() + text.get(index), npc);
return true;
}
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/GenericWaypointCallback.java b/src/main/java/net/citizensnpcs/trait/waypoint/GenericWaypointCallback.java
deleted file mode 100644
index dda6807a8..000000000
--- a/src/main/java/net/citizensnpcs/trait/waypoint/GenericWaypointCallback.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package net.citizensnpcs.trait.waypoint;
-
-import java.util.Iterator;
-
-import net.citizensnpcs.api.ai.AI;
-import net.citizensnpcs.api.ai.NavigationCallback;
-
-import org.bukkit.Location;
-
-public class GenericWaypointCallback extends NavigationCallback {
- private AI ai;
- private Location dest;
- private boolean executing;
- private Iterator itr;
- private final Iterable provider;
-
- public GenericWaypointCallback(Iterable provider) {
- this.provider = provider;
- }
-
- private void ensureItr() {
- if (itr == null || !itr.hasNext()) {
- itr = provider.iterator();
- }
- }
-
- @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);
- }
- }
-
- boolean hackfix = false;
-
- @Override
- public boolean onCancel(AI ai, CancelReason reason) {
- if (hackfix) {
- hackfix = false;
- return false;
- }
- hackfix = false;
- if (executing && reason == CancelReason.REPLACE) {
- executing = false;
- return false;
- }
- executing = true;
- ensureItr();
- if (dest == null && itr.hasNext())
- dest = itr.next().getLocation();
- if (dest != null) {
- hackfix = true;
- ai.setDestination(dest);
- hackfix = false;
- }
- return false;
- }
-
- @Override
- public boolean onCompletion(AI ai) {
- if (executing) { // if we're executing, we need to get the next waypoint
- ensureItr();
- dest = itr.hasNext() ? itr.next().getLocation() : null;
- } else {
- executing = true;
- // we're free to return to our waypoints!
- // if we had a destination, we will return to it.
- }
- if (dest != null) {
- ai.setDestination(dest);
- }
- return false;
- }
-
- public void onProviderChanged() {
- itr = provider.iterator();
- if (ai == null)
- return;
- dest = itr.hasNext() ? itr.next().getLocation() : null;
- if (dest != null) {
- ai.setDestination(dest);
- }
- }
-}
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java b/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
index c675591d6..d786f77a8 100644
--- a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
+++ b/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
@@ -3,7 +3,8 @@ package net.citizensnpcs.trait.waypoint;
import java.util.Iterator;
import java.util.List;
-import net.citizensnpcs.api.ai.NavigationCallback;
+import net.citizensnpcs.api.ai.Goal;
+import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.util.Messaging;
@@ -21,7 +22,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 WaypointGoal currentGoal;
private final List waypoints = Lists.newArrayList();
@Override
@@ -41,35 +42,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();
+ currentGoal.onProviderChanged();
}
@EventHandler
- @SuppressWarnings("unused")
public void onPlayerItemHeldChange(PlayerItemHeldEvent event) {
if (!event.getPlayer().equals(player) || waypoints.size() == 0)
return;
@@ -98,8 +101,10 @@ public class LinearWaypointProvider implements WaypointProvider, Iterable itr;
+ private final Navigator navigator;
+ private final Iterable provider;
+ private GoalSelector selector;
+
+ public WaypointGoal(Iterable provider, Navigator navigator) {
+ this.provider = provider;
+ this.navigator = navigator;
+ }
+
+ private void ensureItr() {
+ if (itr == null || !itr.hasNext()) {
+ itr = provider.iterator();
+ }
+ }
+
+ @EventHandler
+ public void onNavigationCancel(NavigationCancelEvent event) {
+ if (!event.getNavigator().equals(navigator) || currentDestination == null)
+ return;
+ if (currentDestination.equals(event.getNavigator().getTargetAsLocation()))
+ selector.finish();
+ }
+
+ public void onProviderChanged() {
+ itr = provider.iterator();
+ if (currentDestination != null)
+ selector.finish();
+ }
+
+ @Override
+ public void reset() {
+ currentDestination = null;
+ selector = null;
+ }
+
+ @Override
+ public void run() {
+ }
+
+ @Override
+ public boolean shouldExecute(GoalSelector selector) {
+ ensureItr();
+ boolean shouldExecute = itr.hasNext();
+ if (shouldExecute) {
+ this.selector = selector;
+ currentDestination = itr.next().getLocation();
+ navigator.setTarget(currentDestination);
+ }
+ return shouldExecute;
+ }
+}
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java b/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
index a2eed8e83..c45194bc6 100644
--- a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
+++ b/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
@@ -1,7 +1,7 @@
package net.citizensnpcs.trait.waypoint;
-import net.citizensnpcs.api.ai.AI;
-import net.citizensnpcs.api.ai.NavigationCallback;
+import net.citizensnpcs.api.ai.Goal;
+import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
@@ -19,12 +19,12 @@ 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
+ * @param npc
+ * The attached {@link NPC} the goal is for.
+ * @return The {@link Goal} to attach to the NPC.
*/
- public NavigationCallback getCallback();
+ public Goal getGoal(NPC npc);
/**
* Loads from the specified {@link DataKey}.
@@ -41,6 +41,4 @@ public interface WaypointProvider {
* The key to save to
*/
public void save(DataKey key);
-
- public void onAttach();
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java b/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
index c9c3c1faa..87ac7d354 100644
--- a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
+++ b/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
@@ -4,8 +4,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import net.citizensnpcs.api.ai.Goal;
import net.citizensnpcs.api.exception.NPCLoadException;
-import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
@@ -13,13 +13,11 @@ import net.citizensnpcs.editor.Editor;
import org.bukkit.entity.Player;
public class Waypoints extends Trait {
- private final NPC npc;
private WaypointProvider provider = new LinearWaypointProvider();
private String providerName = "linear";
- public Waypoints(NPC npc) {
- this.npc = npc;
- npc.getAI().registerNavigationCallback(provider.getCallback());
+ public Waypoints() {
+ super("waypoints");
}
private WaypointProvider create(Class extends WaypointProvider> clazz) {
@@ -32,11 +30,6 @@ public class Waypoints extends Trait {
}
}
- @Override
- public void onNPCSpawn() {
- npc.getAI().registerNavigationCallback(provider.getCallback());
- }
-
public Editor getEditor(Player player) {
return provider.createEditor(player);
}
@@ -56,6 +49,14 @@ public class Waypoints extends Trait {
provider.load(key.getRelative(providerName));
}
+ @Override
+ public void onSpawn() {
+ if (provider != null) {
+ Goal goal = provider.getGoal(getNPC());
+ getNPC().getDefaultGoalController().addGoal(goal, 1);
+ }
+ }
+
@Override
public void save(DataKey key) {
if (provider == null)
diff --git a/src/main/java/net/citizensnpcs/util/Messaging.java b/src/main/java/net/citizensnpcs/util/Messaging.java
index ec007a9ba..3ff8c1c05 100644
--- a/src/main/java/net/citizensnpcs/util/Messaging.java
+++ b/src/main/java/net/citizensnpcs/util/Messaging.java
@@ -22,6 +22,12 @@ public class Messaging {
log(msg);
}
+ private static String getFormatted(Object[] msg) {
+ String toFormat = msg[0].toString();
+ Object[] args = msg.length > 1 ? Arrays.copyOfRange(msg, 1, msg.length) : new Object[] {};
+ return String.format(toFormat, args);
+ }
+
public static void log(Level level, Object... msg) {
Bukkit.getLogger().log(level, "[Citizens] " + SPACE.join(msg));
}
@@ -30,12 +36,6 @@ public class Messaging {
log(Level.INFO, msg);
}
- private static String getFormatted(Object[] msg) {
- String toFormat = msg[0].toString();
- Object[] args = msg.length > 1 ? Arrays.copyOfRange(msg, 1, msg.length) : new Object[] {};
- return String.format(toFormat, args);
- }
-
public static void logF(Object... msg) {
log(getFormatted(msg));
}
@@ -46,12 +46,6 @@ public class Messaging {
sender.sendMessage(joined);
}
- public static void sendF(CommandSender sender, Object... msg) {
- String joined = getFormatted(msg);
- joined = StringHelper.parseColors(joined);
- sender.sendMessage(joined);
- }
-
public static void sendError(CommandSender sender, Object... msg) {
send(sender, ChatColor.RED.toString() + SPACE.join(msg));
}
@@ -60,6 +54,12 @@ public class Messaging {
sendF(sender, ChatColor.RED.toString() + SPACE.join(msg));
}
+ public static void sendF(CommandSender sender, Object... msg) {
+ String joined = getFormatted(msg);
+ joined = StringHelper.parseColors(joined);
+ sender.sendMessage(joined);
+ }
+
public static void sendWithNPC(CommandSender sender, Object msg, NPC npc) {
String send = msg.toString();
diff --git a/src/main/java/net/citizensnpcs/util/Util.java b/src/main/java/net/citizensnpcs/util/Util.java
index 95e209f56..10ebf65a9 100644
--- a/src/main/java/net/citizensnpcs/util/Util.java
+++ b/src/main/java/net/citizensnpcs/util/Util.java
@@ -26,6 +26,8 @@ public class Util {
private Util() {
}
+ private static final Map, Class>> primitiveClassMap = Maps.newHashMap();
+
/**
* Given a set of instantiation parameters, attempts to find a matching
* constructor with the greatest number of matching class parameters and
@@ -85,6 +87,17 @@ public class Util {
return null;
}
+ public static boolean isSettingFulfilled(Player player, Setting setting) {
+ String parts = setting.asString();
+ if (parts.contains("*"))
+ return true;
+ for (String part : Splitter.on(',').split(parts)) {
+ if (Material.matchMaterial(part) == player.getItemInHand().getType()) {
+ return true;
+ }
+ }
+ return false;
+ }
private static boolean searchInterfaces(Class> class1, Class> class2) {
for (Class> test : class1.getInterfaces())
if (test == class2)
@@ -92,7 +105,31 @@ public class Util {
return false;
}
- private static final Map, Class>> primitiveClassMap = Maps.newHashMap();
+ public static void sendPacketNearby(Location location, Packet packet, double radius) {
+ radius *= radius;
+ final World world = location.getWorld();
+ for (Player ply : Bukkit.getServer().getOnlinePlayers()) {
+ if (ply == null || world != ply.getWorld()) {
+ continue;
+ }
+ if (location.distanceSquared(ply.getLocation()) > radius) {
+ continue;
+ }
+ ((CraftPlayer) ply).getHandle().netServerHandler.sendPacket(packet);
+ }
+ }
+
+ public static void sendToOnline(Packet... packets) {
+ Validate.notNull(packets, "packets cannot be null");
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ if (player == null || !player.isOnline())
+ continue;
+ for (Packet packet : packets) {
+ ((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet);
+ }
+ }
+ }
+
static {
primitiveClassMap.put(Boolean.class, boolean.class);
primitiveClassMap.put(Byte.class, byte.class);
@@ -111,41 +148,4 @@ public class Util {
primitiveClassMap.put(float.class, Float.class);
primitiveClassMap.put(double.class, Double.class);
}
-
- public static boolean isSettingFulfilled(Player player, Setting setting) {
- String parts = setting.asString();
- if (parts.contains("*"))
- return true;
- for (String part : Splitter.on(',').split(parts)) {
- if (Material.matchMaterial(part) == player.getItemInHand().getType()) {
- return true;
- }
- }
- return false;
- }
-
- public static void sendToOnline(Packet... packets) {
- Validate.notNull(packets, "packets cannot be null");
- for (Player player : Bukkit.getOnlinePlayers()) {
- if (player == null || !player.isOnline())
- continue;
- for (Packet packet : packets) {
- ((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet);
- }
- }
- }
-
- public static void sendPacketNearby(Location location, Packet packet, double radius) {
- radius *= radius;
- final World world = location.getWorld();
- for (Player ply : Bukkit.getServer().getOnlinePlayers()) {
- if (ply == null || world != ply.getWorld()) {
- continue;
- }
- if (location.distanceSquared(ply.getLocation()) > radius) {
- continue;
- }
- ((CraftPlayer) ply).getHandle().netServerHandler.sendPacket(packet);
- }
- }
}