diff --git a/dist/pom.xml b/dist/pom.xml
new file mode 100644
index 000000000..89d46c2fe
--- /dev/null
+++ b/dist/pom.xml
@@ -0,0 +1,43 @@
+
+ 4.0.0
+
+ net.citizensnpcs
+ citizens-parent
+ 2.0.20-SNAPSHOT
+
+ citizens
+ pom
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.2
+
+
+ package-all
+ package
+
+ single
+
+
+
+ src/main/assembly/all-jar.xml
+
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ citizens-main
+ ${project.version}
+ jar
+ compile
+
+
+
\ No newline at end of file
diff --git a/dist/src/main/assembly/all-jar.xml b/dist/src/main/assembly/all-jar.xml
new file mode 100644
index 000000000..d60accf82
--- /dev/null
+++ b/dist/src/main/assembly/all-jar.xml
@@ -0,0 +1,18 @@
+
+ all-jar
+
+ jar
+
+
+ false
+
+
+
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/main/pom.xml b/main/pom.xml
new file mode 100644
index 000000000..92796a250
--- /dev/null
+++ b/main/pom.xml
@@ -0,0 +1,163 @@
+
+
+
+ 4.0.0
+
+ net.citizensnpcs
+ citizens-parent
+ 2.0.20-SNAPSHOT
+
+ citizens-main
+
+
+ UTF-8
+ 1.10-R0.1-SNAPSHOT
+ 2.0.20-SNAPSHOT
+ 1.5.4
+ 1.4.12
+ Unknown
+ Unknown
+
+
+
+
+ bukkit-repo
+ http://repo.bukkit.org/content/groups/public/
+
+
+ everything
+ http://repo.citizensnpcs.co
+
+
+ vault-repo
+ http://nexus.theyeticave.net/content/repositories/pub_releases
+
+
+
+
+
+ bukkit-plugins
+ http://repo.bukkit.org/content/groups/public
+
+
+
+
+
+ org.bukkit
+ craftbukkit
+ ${craftbukkit.version}
+ jar
+ provided
+
+
+ net.sf.trove4j
+ trove4j
+ 3.0.3
+ compile
+
+
+ net.citizensnpcs
+ citizensapi
+ ${citizensapi.version}
+ jar
+ compile
+
+
+ net.milkbowl.vault
+ Vault
+ ${vault.version}
+ jar
+ provided
+
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+ test
+
+
+ org.powermock
+ powermock-api-mockito
+ ${powermock.version}
+ test
+
+
+
+ http://www.citizensnpcs.co
+
+ jenkins
+ http://ci.citizensnpcs.co
+
+
+ scm:git:git://github.com/CitizensDev/Citizens2.git
+ scm:git:git:@github.com:CitizensDev/Citizens2.git
+ https://github.com/CitizensDev/Citizens2/tree/master/
+
+
+ clean package install
+ ${basedir}/src/main/java
+
+
+
+ .
+ true
+ ${basedir}/src/main/resources
+
+ plugin.yml
+ *.properties
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.6
+ 1.6
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.3.2
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.1
+
+
+ package
+
+ shade
+
+
+ true
+
+
+ net.citizensnpcs:citizensapi
+
+ **
+
+
+
+
+
+ gnu.trove
+ lib.trove
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/net/citizensnpcs/Citizens.java b/main/src/main/java/net/citizensnpcs/Citizens.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/Citizens.java
rename to main/src/main/java/net/citizensnpcs/Citizens.java
diff --git a/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/EventListen.java
rename to main/src/main/java/net/citizensnpcs/EventListen.java
diff --git a/src/main/java/net/citizensnpcs/Metrics.java b/main/src/main/java/net/citizensnpcs/Metrics.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/Metrics.java
rename to main/src/main/java/net/citizensnpcs/Metrics.java
diff --git a/src/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java b/main/src/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java
rename to main/src/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java
diff --git a/src/main/java/net/citizensnpcs/PaymentListener.java b/main/src/main/java/net/citizensnpcs/PaymentListener.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/PaymentListener.java
rename to main/src/main/java/net/citizensnpcs/PaymentListener.java
diff --git a/src/main/java/net/citizensnpcs/Settings.java b/main/src/main/java/net/citizensnpcs/Settings.java
similarity index 97%
rename from src/main/java/net/citizensnpcs/Settings.java
rename to main/src/main/java/net/citizensnpcs/Settings.java
index f9f907148..9da3935d4 100644
--- a/src/main/java/net/citizensnpcs/Settings.java
+++ b/main/src/main/java/net/citizensnpcs/Settings.java
@@ -1,181 +1,181 @@
-package net.citizensnpcs;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-import net.citizensnpcs.api.CitizensAPI;
-import net.citizensnpcs.api.util.DataKey;
-import net.citizensnpcs.api.util.Messaging;
-import net.citizensnpcs.api.util.Storage;
-import net.citizensnpcs.api.util.YamlStorage;
-
-public class Settings {
- private final Storage config;
- private final DataKey root;
-
- public Settings(File folder) {
- config = new YamlStorage(new File(folder, "config.yml"), "Citizens Configuration");
- root = config.getKey("");
-
- config.load();
- for (Setting setting : Setting.values()) {
- if (!root.keyExists(setting.path)) {
- setting.setAtKey(root);
- } else
- setting.loadFromKey(root);
- }
- updateMessagingSettings();
-
- save();
- }
-
- public void reload() {
- config.load();
- for (Setting setting : Setting.values()) {
- if (root.keyExists(setting.path)) {
- setting.loadFromKey(root);
- }
- }
- updateMessagingSettings();
- save();
- }
-
- public void save() {
- config.save();
- }
-
- private void updateMessagingSettings() {
- File file = null;
- if (!Setting.DEBUG_FILE.asString().isEmpty()) {
- file = new File(CitizensAPI.getPlugin().getDataFolder(), Setting.DEBUG_FILE.asString());
- }
- Messaging.configure(file, Setting.DEBUG_MODE.asBoolean(), Setting.MESSAGE_COLOUR.asString(),
- Setting.HIGHLIGHT_COLOUR.asString());
- }
-
- public enum Setting {
- AUTH_SERVER_URL("general.authlib.profile-url", "https://sessionserver.mojang.com/session/minecraft/profile/"),
- CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true),
- CHAT_FORMAT("npc.chat.format.no-targets", "[]: "),
- CHAT_FORMAT_TO_BYSTANDERS("npc.chat.format.with-target-to-bystanders", "[] -> []: "),
- CHAT_FORMAT_TO_TARGET("npc.chat.format.to-target", "[] -> You: "),
- CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS("npc.chat.format.with-targets-to-bystanders",
- "[] -> []: "),
- CHAT_MAX_NUMBER_OF_TARGETS("npc.chat.options.max-number-of-targets-to-show", 2),
- CHAT_MULTIPLE_TARGETS_FORMAT("npc.chat.options.multiple-targets-format",
- "|, | & | & others"),
- CHAT_RANGE("npc.chat.options.range", 5),
- CHECK_MINECRAFT_VERSION("advanced.check-minecraft-version", true),
- DEBUG_FILE("general.debug-file", ""),
- DEBUG_MODE("general.debug-mode", false),
- DEBUG_PATHFINDING("general.debug-pathfinding", false),
- DEFAULT_DISTANCE_MARGIN("npc.pathfinding.default-distance-margin", 2),
- DEFAULT_LOOK_CLOSE("npc.default.look-close.enabled", false),
- DEFAULT_LOOK_CLOSE_RANGE("npc.default.look-close.range", 5),
- DEFAULT_NPC_LIMIT("npc.limits.default-limit", 10),
- DEFAULT_PATHFINDER_UPDATE_PATH_RATE("npc.pathfinding.update-path-rate", 20),
- DEFAULT_PATHFINDING_RANGE("npc.default.pathfinding.range", 25F),
- DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
- DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
- DEFAULT_STATIONARY_TICKS("npc.default.stationary-ticks", -1),
- DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false),
- DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
- DEFAULT_TEXT("npc.default.text.0", "Hi, I'm !") {
- @Override
- public void loadFromKey(DataKey root) {
- List list = new ArrayList();
- for (DataKey key : root.getRelative("npc.default.text").getSubKeys())
- list.add(key.getString(""));
- value = list;
- }
- },
- DISABLE_TABLIST("npc.tablist.disable", true),
- HIGHLIGHT_COLOUR("general.color-scheme.message-highlight", ""),
- KEEP_CHUNKS_LOADED("npc.chunks.always-keep-loaded", false),
- LOCALE("general.translation.locale", ""),
- MAX_NPC_LIMIT_CHECKS("npc.limits.max-permission-checks", 100),
- MAX_NPC_SKIN_RETRIES("npc.skins.max-retries", -1),
- MAX_PACKET_ENTRIES("npc.limits.max-packet-entries", 15),
- MAX_SPEED("npc.limits.max-speed", 100),
- MAX_TEXT_RANGE("npc.chat.options.max-text-range", 500),
- MESSAGE_COLOUR("general.color-scheme.message", ""),
- NEW_PATHFINDER_OPENS_DOORS("npc.pathfinding.new-finder-open-doors", false),
- NPC_ATTACK_DISTANCE("npc.pathfinding.attack-range", 1.75 * 1.75),
- NPC_COST("economy.npc.cost", 100D),
- NPC_SKIN_RETRY_DELAY("npc.skins.retry-delay", 120),
- NPC_SKIN_ROTATION_UPDATE_DEGREES("npc.skins.rotation-update-degrees", 90f),
- NPC_SKIN_USE_LATEST("npc.skins.use-latest", true),
- NPC_SKIN_VIEW_DISTANCE("npc.skins.view-distance", 100D),
- PACKET_UPDATE_DELAY("npc.packets.update-delay", 30),
- QUICK_SELECT("npc.selection.quick-select", false),
- REMOVE_PLAYERS_FROM_PLAYER_LIST("npc.player.remove-from-list", true),
- SAVE_TASK_DELAY("storage.save-task.delay", 20 * 60 * 60),
- SELECTION_ITEM("npc.selection.item", "280"),
- SELECTION_MESSAGE("npc.selection.message", "You selected !"),
- 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", 5),
- TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 10),
- TALK_ITEM("npc.text.talk-item", "340"),
- TELEPORT_DELAY("npc.teleport-delay", -1),
- USE_BOAT_CONTROLS("npc.controllable.use-boat-controls", true),
- USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false),
- USE_SCOREBOARD_TEAMS("npc.player-scoreboard-teams.enable", true);
-
- protected String path;
- protected Object value;
-
- Setting(String path, Object value) {
- this.path = path;
- this.value = value;
- }
-
- public boolean asBoolean() {
- return (Boolean) value;
- }
-
- public double asDouble() {
- return ((Number) value).doubleValue();
- }
-
- public float asFloat() {
- return ((Number) value).floatValue();
- }
-
- public int asInt() {
- if (value instanceof String) {
- return Integer.parseInt(value.toString());
- }
- return ((Number) value).intValue();
- }
-
- @SuppressWarnings("unchecked")
- public List asList() {
- if (!(value instanceof List)) {
- value = Lists.newArrayList(value);
- }
- return (List) value;
- }
-
- public long asLong() {
- return ((Number) value).longValue();
- }
-
- public String asString() {
- return value.toString();
- }
-
- protected void loadFromKey(DataKey root) {
- value = root.getRaw(path);
- }
-
- protected void setAtKey(DataKey root) {
- root.setRaw(path, value);
- }
- }
-}
+package net.citizensnpcs;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.util.DataKey;
+import net.citizensnpcs.api.util.Messaging;
+import net.citizensnpcs.api.util.Storage;
+import net.citizensnpcs.api.util.YamlStorage;
+
+public class Settings {
+ private final Storage config;
+ private final DataKey root;
+
+ public Settings(File folder) {
+ config = new YamlStorage(new File(folder, "config.yml"), "Citizens Configuration");
+ root = config.getKey("");
+
+ config.load();
+ for (Setting setting : Setting.values()) {
+ if (!root.keyExists(setting.path)) {
+ setting.setAtKey(root);
+ } else
+ setting.loadFromKey(root);
+ }
+ updateMessagingSettings();
+
+ save();
+ }
+
+ public void reload() {
+ config.load();
+ for (Setting setting : Setting.values()) {
+ if (root.keyExists(setting.path)) {
+ setting.loadFromKey(root);
+ }
+ }
+ updateMessagingSettings();
+ save();
+ }
+
+ public void save() {
+ config.save();
+ }
+
+ private void updateMessagingSettings() {
+ File file = null;
+ if (!Setting.DEBUG_FILE.asString().isEmpty()) {
+ file = new File(CitizensAPI.getPlugin().getDataFolder(), Setting.DEBUG_FILE.asString());
+ }
+ Messaging.configure(file, Setting.DEBUG_MODE.asBoolean(), Setting.MESSAGE_COLOUR.asString(),
+ Setting.HIGHLIGHT_COLOUR.asString());
+ }
+
+ public enum Setting {
+ AUTH_SERVER_URL("general.authlib.profile-url", "https://sessionserver.mojang.com/session/minecraft/profile/"),
+ CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true),
+ CHAT_FORMAT("npc.chat.format.no-targets", "[]: "),
+ CHAT_FORMAT_TO_BYSTANDERS("npc.chat.format.with-target-to-bystanders", "[] -> []: "),
+ CHAT_FORMAT_TO_TARGET("npc.chat.format.to-target", "[] -> You: "),
+ CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS("npc.chat.format.with-targets-to-bystanders",
+ "[] -> []: "),
+ CHAT_MAX_NUMBER_OF_TARGETS("npc.chat.options.max-number-of-targets-to-show", 2),
+ CHAT_MULTIPLE_TARGETS_FORMAT("npc.chat.options.multiple-targets-format",
+ "|, | & | & others"),
+ CHAT_RANGE("npc.chat.options.range", 5),
+ CHECK_MINECRAFT_VERSION("advanced.check-minecraft-version", true),
+ DEBUG_FILE("general.debug-file", ""),
+ DEBUG_MODE("general.debug-mode", false),
+ DEBUG_PATHFINDING("general.debug-pathfinding", false),
+ DEFAULT_DISTANCE_MARGIN("npc.pathfinding.default-distance-margin", 2),
+ DEFAULT_LOOK_CLOSE("npc.default.look-close.enabled", false),
+ DEFAULT_LOOK_CLOSE_RANGE("npc.default.look-close.range", 5),
+ DEFAULT_NPC_LIMIT("npc.limits.default-limit", 10),
+ DEFAULT_PATHFINDER_UPDATE_PATH_RATE("npc.pathfinding.update-path-rate", 20),
+ DEFAULT_PATHFINDING_RANGE("npc.default.pathfinding.range", 25F),
+ DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
+ DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
+ DEFAULT_STATIONARY_TICKS("npc.default.stationary-ticks", -1),
+ DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false),
+ DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
+ DEFAULT_TEXT("npc.default.text.0", "Hi, I'm !") {
+ @Override
+ public void loadFromKey(DataKey root) {
+ List list = new ArrayList();
+ for (DataKey key : root.getRelative("npc.default.text").getSubKeys())
+ list.add(key.getString(""));
+ value = list;
+ }
+ },
+ DISABLE_TABLIST("npc.tablist.disable", true),
+ HIGHLIGHT_COLOUR("general.color-scheme.message-highlight", ""),
+ KEEP_CHUNKS_LOADED("npc.chunks.always-keep-loaded", false),
+ LOCALE("general.translation.locale", ""),
+ MAX_NPC_LIMIT_CHECKS("npc.limits.max-permission-checks", 100),
+ MAX_NPC_SKIN_RETRIES("npc.skins.max-retries", -1),
+ MAX_PACKET_ENTRIES("npc.limits.max-packet-entries", 15),
+ MAX_SPEED("npc.limits.max-speed", 100),
+ MAX_TEXT_RANGE("npc.chat.options.max-text-range", 500),
+ MESSAGE_COLOUR("general.color-scheme.message", ""),
+ NEW_PATHFINDER_OPENS_DOORS("npc.pathfinding.new-finder-open-doors", false),
+ NPC_ATTACK_DISTANCE("npc.pathfinding.attack-range", 1.75 * 1.75),
+ NPC_COST("economy.npc.cost", 100D),
+ NPC_SKIN_RETRY_DELAY("npc.skins.retry-delay", 120),
+ NPC_SKIN_ROTATION_UPDATE_DEGREES("npc.skins.rotation-update-degrees", 90f),
+ NPC_SKIN_USE_LATEST("npc.skins.use-latest", true),
+ NPC_SKIN_VIEW_DISTANCE("npc.skins.view-distance", 100D),
+ PACKET_UPDATE_DELAY("npc.packets.update-delay", 30),
+ QUICK_SELECT("npc.selection.quick-select", false),
+ REMOVE_PLAYERS_FROM_PLAYER_LIST("npc.player.remove-from-list", true),
+ SAVE_TASK_DELAY("storage.save-task.delay", 20 * 60 * 60),
+ SELECTION_ITEM("npc.selection.item", "280"),
+ SELECTION_MESSAGE("npc.selection.message", "You selected !"),
+ 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", 5),
+ TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 10),
+ TALK_ITEM("npc.text.talk-item", "340"),
+ TELEPORT_DELAY("npc.teleport-delay", -1),
+ USE_BOAT_CONTROLS("npc.controllable.use-boat-controls", true),
+ USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false),
+ USE_SCOREBOARD_TEAMS("npc.player-scoreboard-teams.enable", true);
+
+ protected String path;
+ protected Object value;
+
+ Setting(String path, Object value) {
+ this.path = path;
+ this.value = value;
+ }
+
+ public boolean asBoolean() {
+ return (Boolean) value;
+ }
+
+ public double asDouble() {
+ return ((Number) value).doubleValue();
+ }
+
+ public float asFloat() {
+ return ((Number) value).floatValue();
+ }
+
+ public int asInt() {
+ if (value instanceof String) {
+ return Integer.parseInt(value.toString());
+ }
+ return ((Number) value).intValue();
+ }
+
+ @SuppressWarnings("unchecked")
+ public List asList() {
+ if (!(value instanceof List)) {
+ value = Lists.newArrayList(value);
+ }
+ return (List) value;
+ }
+
+ public long asLong() {
+ return ((Number) value).longValue();
+ }
+
+ public String asString() {
+ return value.toString();
+ }
+
+ protected void loadFromKey(DataKey root) {
+ value = root.getRaw(path);
+ }
+
+ protected void setAtKey(DataKey root) {
+ root.setRaw(path, value);
+ }
+ }
+}
diff --git a/src/main/java/net/citizensnpcs/commands/AdminCommands.java b/main/src/main/java/net/citizensnpcs/commands/AdminCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/AdminCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/AdminCommands.java
diff --git a/src/main/java/net/citizensnpcs/commands/EditorCommands.java b/main/src/main/java/net/citizensnpcs/commands/EditorCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/EditorCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/EditorCommands.java
diff --git a/src/main/java/net/citizensnpcs/commands/NPCCommandSelector.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommandSelector.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/NPCCommandSelector.java
rename to main/src/main/java/net/citizensnpcs/commands/NPCCommandSelector.java
diff --git a/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/NPCCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/NPCCommands.java
diff --git a/src/main/java/net/citizensnpcs/commands/TemplateCommands.java b/main/src/main/java/net/citizensnpcs/commands/TemplateCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/TemplateCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/TemplateCommands.java
diff --git a/src/main/java/net/citizensnpcs/commands/TraitCommands.java b/main/src/main/java/net/citizensnpcs/commands/TraitCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/TraitCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/TraitCommands.java
diff --git a/src/main/java/net/citizensnpcs/commands/WaypointCommands.java b/main/src/main/java/net/citizensnpcs/commands/WaypointCommands.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/commands/WaypointCommands.java
rename to main/src/main/java/net/citizensnpcs/commands/WaypointCommands.java
diff --git a/src/main/java/net/citizensnpcs/editor/CopierEditor.java b/main/src/main/java/net/citizensnpcs/editor/CopierEditor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/CopierEditor.java
rename to main/src/main/java/net/citizensnpcs/editor/CopierEditor.java
diff --git a/src/main/java/net/citizensnpcs/editor/Editor.java b/main/src/main/java/net/citizensnpcs/editor/Editor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/Editor.java
rename to main/src/main/java/net/citizensnpcs/editor/Editor.java
diff --git a/src/main/java/net/citizensnpcs/editor/EndermanEquipper.java b/main/src/main/java/net/citizensnpcs/editor/EndermanEquipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/EndermanEquipper.java
rename to main/src/main/java/net/citizensnpcs/editor/EndermanEquipper.java
diff --git a/src/main/java/net/citizensnpcs/editor/EquipmentEditor.java b/main/src/main/java/net/citizensnpcs/editor/EquipmentEditor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/EquipmentEditor.java
rename to main/src/main/java/net/citizensnpcs/editor/EquipmentEditor.java
diff --git a/src/main/java/net/citizensnpcs/editor/Equipper.java b/main/src/main/java/net/citizensnpcs/editor/Equipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/Equipper.java
rename to main/src/main/java/net/citizensnpcs/editor/Equipper.java
diff --git a/src/main/java/net/citizensnpcs/editor/GenericEquipper.java b/main/src/main/java/net/citizensnpcs/editor/GenericEquipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/GenericEquipper.java
rename to main/src/main/java/net/citizensnpcs/editor/GenericEquipper.java
diff --git a/src/main/java/net/citizensnpcs/editor/HorseEquipper.java b/main/src/main/java/net/citizensnpcs/editor/HorseEquipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/HorseEquipper.java
rename to main/src/main/java/net/citizensnpcs/editor/HorseEquipper.java
diff --git a/src/main/java/net/citizensnpcs/editor/PigEquipper.java b/main/src/main/java/net/citizensnpcs/editor/PigEquipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/PigEquipper.java
rename to main/src/main/java/net/citizensnpcs/editor/PigEquipper.java
diff --git a/src/main/java/net/citizensnpcs/editor/SheepEquipper.java b/main/src/main/java/net/citizensnpcs/editor/SheepEquipper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/editor/SheepEquipper.java
rename to main/src/main/java/net/citizensnpcs/editor/SheepEquipper.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerAnimationImpl.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerAnimationImpl.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerAnimationImpl.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerAnimationImpl.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerJump.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerJump.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerJump.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerJump.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerLook.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerLook.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerLook.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerLook.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerNavigation.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerNavigation.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerNavigation.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerNavigation.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinder.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinder.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinder.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinder.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderAbstract.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderAbstract.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderAbstract.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderAbstract.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderNormal.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderNormal.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderNormal.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerPathfinderNormal.java
diff --git a/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerlistTrackerEntry.java b/main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerlistTrackerEntry.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerlistTrackerEntry.java
rename to main/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerlistTrackerEntry.java
diff --git a/src/main/java/net/citizensnpcs/npc/AbstractEntityController.java b/main/src/main/java/net/citizensnpcs/npc/AbstractEntityController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/AbstractEntityController.java
rename to main/src/main/java/net/citizensnpcs/npc/AbstractEntityController.java
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/CitizensNPC.java
rename to main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
rename to main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java
diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
similarity index 97%
rename from src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
rename to main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
index 68600f503..8072adb27 100644
--- a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
+++ b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
@@ -1,177 +1,177 @@
-package net.citizensnpcs.npc;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-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.TraitFactory;
-import net.citizensnpcs.api.trait.TraitInfo;
-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.api.trait.trait.Speech;
-import net.citizensnpcs.trait.Age;
-import net.citizensnpcs.trait.Anchors;
-import net.citizensnpcs.trait.ArmorStandTrait;
-import net.citizensnpcs.trait.BossBarTrait;
-import net.citizensnpcs.trait.Controllable;
-import net.citizensnpcs.trait.CurrentLocation;
-import net.citizensnpcs.trait.Gravity;
-import net.citizensnpcs.trait.HorseModifiers;
-import net.citizensnpcs.trait.LookClose;
-import net.citizensnpcs.trait.MountTrait;
-import net.citizensnpcs.trait.NPCSkeletonType;
-import net.citizensnpcs.trait.OcelotModifiers;
-import net.citizensnpcs.trait.Poses;
-import net.citizensnpcs.trait.Powered;
-import net.citizensnpcs.trait.RabbitType;
-import net.citizensnpcs.trait.Saddle;
-import net.citizensnpcs.trait.ScriptTrait;
-import net.citizensnpcs.trait.SheepTrait;
-import net.citizensnpcs.trait.SkinLayers;
-import net.citizensnpcs.trait.SlimeSize;
-import net.citizensnpcs.trait.VillagerProfession;
-import net.citizensnpcs.trait.WitherTrait;
-import net.citizensnpcs.trait.WolfModifiers;
-import net.citizensnpcs.trait.WoolColor;
-import net.citizensnpcs.trait.ZombieModifier;
-import net.citizensnpcs.trait.text.Text;
-import net.citizensnpcs.trait.waypoint.Waypoints;
-
-public class CitizensTraitFactory implements TraitFactory {
- private final List defaultTraits = Lists.newArrayList();
- private final Map registered = Maps.newHashMap();
-
- public CitizensTraitFactory() {
- registerTrait(TraitInfo.create(Age.class));
- registerTrait(TraitInfo.create(ArmorStandTrait.class));
- registerTrait(TraitInfo.create(Anchors.class));
- registerTrait(TraitInfo.create(BossBarTrait.class));
- registerTrait(TraitInfo.create(Controllable.class));
- registerTrait(TraitInfo.create(Equipment.class));
- registerTrait(TraitInfo.create(Gravity.class));
- registerTrait(TraitInfo.create(HorseModifiers.class));
- registerTrait(TraitInfo.create(Inventory.class));
- registerTrait(TraitInfo.create(CurrentLocation.class));
- registerTrait(TraitInfo.create(LookClose.class));
- registerTrait(TraitInfo.create(OcelotModifiers.class));
- registerTrait(TraitInfo.create(Owner.class));
- registerTrait(TraitInfo.create(Poses.class));
- registerTrait(TraitInfo.create(Powered.class));
- registerTrait(TraitInfo.create(RabbitType.class));
- registerTrait(TraitInfo.create(Saddle.class));
- registerTrait(TraitInfo.create(ScriptTrait.class));
- registerTrait(TraitInfo.create(SheepTrait.class));
- registerTrait(TraitInfo.create(SkinLayers.class));
- registerTrait(TraitInfo.create(MountTrait.class));
- registerTrait(TraitInfo.create(NPCSkeletonType.class));
- registerTrait(TraitInfo.create(SlimeSize.class));
- registerTrait(TraitInfo.create(Spawned.class));
- registerTrait(TraitInfo.create(Speech.class));
- registerTrait(TraitInfo.create(Text.class));
- registerTrait(TraitInfo.create(MobType.class).asDefaultTrait());
- registerTrait(TraitInfo.create(Waypoints.class));
- registerTrait(TraitInfo.create(WitherTrait.class));
- registerTrait(TraitInfo.create(WoolColor.class));
- registerTrait(TraitInfo.create(WolfModifiers.class));
- registerTrait(TraitInfo.create(VillagerProfession.class));
- registerTrait(TraitInfo.create(ZombieModifier.class));
-
- for (String trait : registered.keySet()) {
- INTERNAL_TRAITS.add(trait);
- }
- }
-
- @Override
- public void addDefaultTraits(NPC npc) {
- for (TraitInfo info : defaultTraits) {
- npc.addTrait(create(info));
- }
- }
-
- public void addPlotters(Graph graph) {
- for (Map.Entry entry : registered.entrySet()) {
- if (INTERNAL_TRAITS.contains(entry.getKey()))
- continue;
- final Class extends Trait> traitClass = entry.getValue().getTraitClass();
- 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(TraitInfo info) {
- return info.tryCreateInstance();
- }
-
- @Override
- public void deregisterTrait(TraitInfo info) {
- Preconditions.checkNotNull(info, "info cannot be null");
- registered.remove(info.getTraitName());
- }
-
- @Override
- public T getTrait(Class clazz) {
- for (TraitInfo entry : registered.values()) {
- if (clazz == entry.getTraitClass()) {
- return create(entry);
- }
- }
- return null;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public T getTrait(String name) {
- TraitInfo info = registered.get(name);
- if (info == null)
- return null;
- return (T) create(info);
- }
-
- @Override
- public Class extends Trait> getTraitClass(String name) {
- TraitInfo info = registered.get(name.toLowerCase());
- return info == null ? null : info.getTraitClass();
- }
-
- @Override
- public boolean isInternalTrait(Trait trait) {
- return INTERNAL_TRAITS.contains(trait.getName());
- }
-
- @Override
- public void registerTrait(TraitInfo info) {
- Preconditions.checkNotNull(info, "info cannot be null");
- if (registered.containsKey(info.getTraitName())) {
- System.out.println(info.getTraitClass());
- throw new IllegalArgumentException("trait name already registered");
- }
- registered.put(info.getTraitName(), info);
- if (info.isDefaultTrait()) {
- defaultTraits.add(info);
- }
- }
-
- private static final Set INTERNAL_TRAITS = Sets.newHashSet();
+package net.citizensnpcs.npc;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+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.TraitFactory;
+import net.citizensnpcs.api.trait.TraitInfo;
+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.api.trait.trait.Speech;
+import net.citizensnpcs.trait.Age;
+import net.citizensnpcs.trait.Anchors;
+import net.citizensnpcs.trait.ArmorStandTrait;
+import net.citizensnpcs.trait.BossBarTrait;
+import net.citizensnpcs.trait.Controllable;
+import net.citizensnpcs.trait.CurrentLocation;
+import net.citizensnpcs.trait.Gravity;
+import net.citizensnpcs.trait.HorseModifiers;
+import net.citizensnpcs.trait.LookClose;
+import net.citizensnpcs.trait.MountTrait;
+import net.citizensnpcs.trait.NPCSkeletonType;
+import net.citizensnpcs.trait.OcelotModifiers;
+import net.citizensnpcs.trait.Poses;
+import net.citizensnpcs.trait.Powered;
+import net.citizensnpcs.trait.RabbitType;
+import net.citizensnpcs.trait.Saddle;
+import net.citizensnpcs.trait.ScriptTrait;
+import net.citizensnpcs.trait.SheepTrait;
+import net.citizensnpcs.trait.SkinLayers;
+import net.citizensnpcs.trait.SlimeSize;
+import net.citizensnpcs.trait.VillagerProfession;
+import net.citizensnpcs.trait.WitherTrait;
+import net.citizensnpcs.trait.WolfModifiers;
+import net.citizensnpcs.trait.WoolColor;
+import net.citizensnpcs.trait.ZombieModifier;
+import net.citizensnpcs.trait.text.Text;
+import net.citizensnpcs.trait.waypoint.Waypoints;
+
+public class CitizensTraitFactory implements TraitFactory {
+ private final List defaultTraits = Lists.newArrayList();
+ private final Map registered = Maps.newHashMap();
+
+ public CitizensTraitFactory() {
+ registerTrait(TraitInfo.create(Age.class));
+ registerTrait(TraitInfo.create(ArmorStandTrait.class));
+ registerTrait(TraitInfo.create(Anchors.class));
+ registerTrait(TraitInfo.create(BossBarTrait.class));
+ registerTrait(TraitInfo.create(Controllable.class));
+ registerTrait(TraitInfo.create(Equipment.class));
+ registerTrait(TraitInfo.create(Gravity.class));
+ registerTrait(TraitInfo.create(HorseModifiers.class));
+ registerTrait(TraitInfo.create(Inventory.class));
+ registerTrait(TraitInfo.create(CurrentLocation.class));
+ registerTrait(TraitInfo.create(LookClose.class));
+ registerTrait(TraitInfo.create(OcelotModifiers.class));
+ registerTrait(TraitInfo.create(Owner.class));
+ registerTrait(TraitInfo.create(Poses.class));
+ registerTrait(TraitInfo.create(Powered.class));
+ registerTrait(TraitInfo.create(RabbitType.class));
+ registerTrait(TraitInfo.create(Saddle.class));
+ registerTrait(TraitInfo.create(ScriptTrait.class));
+ registerTrait(TraitInfo.create(SheepTrait.class));
+ registerTrait(TraitInfo.create(SkinLayers.class));
+ registerTrait(TraitInfo.create(MountTrait.class));
+ registerTrait(TraitInfo.create(NPCSkeletonType.class));
+ registerTrait(TraitInfo.create(SlimeSize.class));
+ registerTrait(TraitInfo.create(Spawned.class));
+ registerTrait(TraitInfo.create(Speech.class));
+ registerTrait(TraitInfo.create(Text.class));
+ registerTrait(TraitInfo.create(MobType.class).asDefaultTrait());
+ registerTrait(TraitInfo.create(Waypoints.class));
+ registerTrait(TraitInfo.create(WitherTrait.class));
+ registerTrait(TraitInfo.create(WoolColor.class));
+ registerTrait(TraitInfo.create(WolfModifiers.class));
+ registerTrait(TraitInfo.create(VillagerProfession.class));
+ registerTrait(TraitInfo.create(ZombieModifier.class));
+
+ for (String trait : registered.keySet()) {
+ INTERNAL_TRAITS.add(trait);
+ }
+ }
+
+ @Override
+ public void addDefaultTraits(NPC npc) {
+ for (TraitInfo info : defaultTraits) {
+ npc.addTrait(create(info));
+ }
+ }
+
+ public void addPlotters(Graph graph) {
+ for (Map.Entry entry : registered.entrySet()) {
+ if (INTERNAL_TRAITS.contains(entry.getKey()))
+ continue;
+ final Class extends Trait> traitClass = entry.getValue().getTraitClass();
+ 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(TraitInfo info) {
+ return info.tryCreateInstance();
+ }
+
+ @Override
+ public void deregisterTrait(TraitInfo info) {
+ Preconditions.checkNotNull(info, "info cannot be null");
+ registered.remove(info.getTraitName());
+ }
+
+ @Override
+ public T getTrait(Class clazz) {
+ for (TraitInfo entry : registered.values()) {
+ if (clazz == entry.getTraitClass()) {
+ return create(entry);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T getTrait(String name) {
+ TraitInfo info = registered.get(name);
+ if (info == null)
+ return null;
+ return (T) create(info);
+ }
+
+ @Override
+ public Class extends Trait> getTraitClass(String name) {
+ TraitInfo info = registered.get(name.toLowerCase());
+ return info == null ? null : info.getTraitClass();
+ }
+
+ @Override
+ public boolean isInternalTrait(Trait trait) {
+ return INTERNAL_TRAITS.contains(trait.getName());
+ }
+
+ @Override
+ public void registerTrait(TraitInfo info) {
+ Preconditions.checkNotNull(info, "info cannot be null");
+ if (registered.containsKey(info.getTraitName())) {
+ System.out.println(info.getTraitClass());
+ throw new IllegalArgumentException("trait name already registered");
+ }
+ registered.put(info.getTraitName(), info);
+ if (info.isDefaultTrait()) {
+ defaultTraits.add(info);
+ }
+ }
+
+ private static final Set INTERNAL_TRAITS = Sets.newHashSet();
}
\ No newline at end of file
diff --git a/src/main/java/net/citizensnpcs/npc/EntityController.java b/main/src/main/java/net/citizensnpcs/npc/EntityController.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/EntityController.java
rename to main/src/main/java/net/citizensnpcs/npc/EntityController.java
diff --git a/src/main/java/net/citizensnpcs/npc/EntityControllers.java b/main/src/main/java/net/citizensnpcs/npc/EntityControllers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/EntityControllers.java
rename to main/src/main/java/net/citizensnpcs/npc/EntityControllers.java
diff --git a/src/main/java/net/citizensnpcs/npc/NPCSelector.java b/main/src/main/java/net/citizensnpcs/npc/NPCSelector.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/NPCSelector.java
rename to main/src/main/java/net/citizensnpcs/npc/NPCSelector.java
diff --git a/src/main/java/net/citizensnpcs/npc/Template.java b/main/src/main/java/net/citizensnpcs/npc/Template.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/Template.java
rename to main/src/main/java/net/citizensnpcs/npc/Template.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/CitizensBlockBreaker.java b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensBlockBreaker.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/CitizensBlockBreaker.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/CitizensBlockBreaker.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java b/main/src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/NPCHolder.java
diff --git a/src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java b/main/src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
similarity index 97%
rename from src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
index fd1afcf45..7533cdc77 100644
--- a/src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
+++ b/main/src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
@@ -1,133 +1,133 @@
-package net.citizensnpcs.npc.ai.speech;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.citizensnpcs.Settings.Setting;
-import net.citizensnpcs.api.CitizensAPI;
-import net.citizensnpcs.api.ai.speech.SpeechContext;
-import net.citizensnpcs.api.ai.speech.Talkable;
-import net.citizensnpcs.api.ai.speech.VocalChord;
-import net.citizensnpcs.api.npc.NPC;
-import net.citizensnpcs.api.util.Messaging;
-
-import org.bukkit.entity.Entity;
-
-public class Chat implements VocalChord {
- public final String VOCAL_CHORD_NAME = "chat";
-
- @Override
- public String getName() {
- return VOCAL_CHORD_NAME;
- }
-
- @Override
- public void talk(SpeechContext context) {
- if (context.getTalker() == null)
- return;
- NPC npc = CitizensAPI.getNPCRegistry().getNPC(context.getTalker().getEntity());
- if (npc == null)
- return;
-
- // chat to the world with CHAT_FORMAT and CHAT_RANGE settings
- if (!context.hasRecipients()) {
- String text = Setting.CHAT_FORMAT.asString().replace("", npc.getName()).replace("",
- context.getMessage());
- talkToBystanders(npc, text, context);
- return;
- }
-
- // Assumed recipients at this point
- else if (context.size() <= 1) {
- String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("", npc.getName()).replace("",
- context.getMessage());
- String targetName = "";
- // For each recipient
- for (Talkable entity : context) {
- entity.talkTo(context, text, this);
- targetName = entity.getName();
- }
- // Check if bystanders hear targeted chat
- if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
- return;
- // Format message with config setting and send to bystanders
- String bystanderText = Setting.CHAT_FORMAT_TO_BYSTANDERS.asString().replace("", npc.getName())
- .replace("", targetName).replace("", context.getMessage());
- talkToBystanders(npc, bystanderText, context);
- return;
- }
-
- else { // Multiple recipients
- String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("", npc.getName()).replace("",
- context.getMessage());
- List targetNames = new ArrayList();
- // Talk to each recipient
- for (Talkable entity : context) {
- entity.talkTo(context, text, this);
- targetNames.add(entity.getName());
- }
-
- if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
- return;
- String targets = "";
- int max = Setting.CHAT_MAX_NUMBER_OF_TARGETS.asInt();
- String[] format = Setting.CHAT_MULTIPLE_TARGETS_FORMAT.asString().split("\\|");
- if (format.length != 4)
- Messaging.severe("npc.chat.options.multiple-targets-format invalid!");
- if (max == 1) {
- targets = format[0].replace("", targetNames.get(0)) + format[3];
- } else if (max == 2 || targetNames.size() == 2) {
- if (targetNames.size() == 2) {
- targets = format[0].replace("", targetNames.get(0))
- + format[2].replace("", targetNames.get(1));
- } else
- targets = format[0].replace("", targetNames.get(0))
- + format[1].replace("", targetNames.get(1)) + format[3];
- } else if (max >= 3) {
- targets = format[0].replace("", targetNames.get(0));
-
- int x = 1;
- for (x = 1; x < max - 1; x++) {
- if (targetNames.size() - 1 == x)
- break;
- targets = targets + format[1].replace("", targetNames.get(x));
- }
- if (targetNames.size() == max) {
- targets = targets + format[2].replace("", targetNames.get(x));
- } else
- targets = targets + format[3];
- }
-
- String bystanderText = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString()
- .replace("", npc.getName()).replace("", targets)
- .replace("", context.getMessage());
- talkToBystanders(npc, bystanderText, context);
- }
- }
-
- private void talkToBystanders(NPC npc, String text, SpeechContext context) {
- // Get list of nearby entities
- List bystanderEntities = npc.getEntity().getNearbyEntities(Setting.CHAT_RANGE.asDouble(),
- Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble());
- for (Entity bystander : bystanderEntities) {
- // Continue if a LivingEntity, which is compatible with
- // TalkableEntity
- boolean shouldTalk = true;
- // Exclude targeted recipients
- if (context.hasRecipients()) {
- for (Talkable target : context) {
- if (target.getEntity().equals(bystander)) {
- shouldTalk = false;
- break;
- }
- }
- }
-
- // Found a nearby LivingEntity, make it Talkable and
- // talkNear it if 'should_talk'
- if (shouldTalk) {
- new TalkableEntity(bystander).talkNear(context, text, this);
- }
- }
- }
-}
+package net.citizensnpcs.npc.ai.speech;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.citizensnpcs.Settings.Setting;
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.ai.speech.SpeechContext;
+import net.citizensnpcs.api.ai.speech.Talkable;
+import net.citizensnpcs.api.ai.speech.VocalChord;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.util.Messaging;
+
+import org.bukkit.entity.Entity;
+
+public class Chat implements VocalChord {
+ public final String VOCAL_CHORD_NAME = "chat";
+
+ @Override
+ public String getName() {
+ return VOCAL_CHORD_NAME;
+ }
+
+ @Override
+ public void talk(SpeechContext context) {
+ if (context.getTalker() == null)
+ return;
+ NPC npc = CitizensAPI.getNPCRegistry().getNPC(context.getTalker().getEntity());
+ if (npc == null)
+ return;
+
+ // chat to the world with CHAT_FORMAT and CHAT_RANGE settings
+ if (!context.hasRecipients()) {
+ String text = Setting.CHAT_FORMAT.asString().replace("", npc.getName()).replace("",
+ context.getMessage());
+ talkToBystanders(npc, text, context);
+ return;
+ }
+
+ // Assumed recipients at this point
+ else if (context.size() <= 1) {
+ String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("", npc.getName()).replace("",
+ context.getMessage());
+ String targetName = "";
+ // For each recipient
+ for (Talkable entity : context) {
+ entity.talkTo(context, text, this);
+ targetName = entity.getName();
+ }
+ // Check if bystanders hear targeted chat
+ if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
+ return;
+ // Format message with config setting and send to bystanders
+ String bystanderText = Setting.CHAT_FORMAT_TO_BYSTANDERS.asString().replace("", npc.getName())
+ .replace("", targetName).replace("", context.getMessage());
+ talkToBystanders(npc, bystanderText, context);
+ return;
+ }
+
+ else { // Multiple recipients
+ String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("", npc.getName()).replace("",
+ context.getMessage());
+ List targetNames = new ArrayList();
+ // Talk to each recipient
+ for (Talkable entity : context) {
+ entity.talkTo(context, text, this);
+ targetNames.add(entity.getName());
+ }
+
+ if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean())
+ return;
+ String targets = "";
+ int max = Setting.CHAT_MAX_NUMBER_OF_TARGETS.asInt();
+ String[] format = Setting.CHAT_MULTIPLE_TARGETS_FORMAT.asString().split("\\|");
+ if (format.length != 4)
+ Messaging.severe("npc.chat.options.multiple-targets-format invalid!");
+ if (max == 1) {
+ targets = format[0].replace("", targetNames.get(0)) + format[3];
+ } else if (max == 2 || targetNames.size() == 2) {
+ if (targetNames.size() == 2) {
+ targets = format[0].replace("", targetNames.get(0))
+ + format[2].replace("", targetNames.get(1));
+ } else
+ targets = format[0].replace("", targetNames.get(0))
+ + format[1].replace("", targetNames.get(1)) + format[3];
+ } else if (max >= 3) {
+ targets = format[0].replace("", targetNames.get(0));
+
+ int x = 1;
+ for (x = 1; x < max - 1; x++) {
+ if (targetNames.size() - 1 == x)
+ break;
+ targets = targets + format[1].replace("", targetNames.get(x));
+ }
+ if (targetNames.size() == max) {
+ targets = targets + format[2].replace("", targetNames.get(x));
+ } else
+ targets = targets + format[3];
+ }
+
+ String bystanderText = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString()
+ .replace("", npc.getName()).replace("", targets)
+ .replace("", context.getMessage());
+ talkToBystanders(npc, bystanderText, context);
+ }
+ }
+
+ private void talkToBystanders(NPC npc, String text, SpeechContext context) {
+ // Get list of nearby entities
+ List bystanderEntities = npc.getEntity().getNearbyEntities(Setting.CHAT_RANGE.asDouble(),
+ Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble());
+ for (Entity bystander : bystanderEntities) {
+ // Continue if a LivingEntity, which is compatible with
+ // TalkableEntity
+ boolean shouldTalk = true;
+ // Exclude targeted recipients
+ if (context.hasRecipients()) {
+ for (Talkable target : context) {
+ if (target.getEntity().equals(bystander)) {
+ shouldTalk = false;
+ break;
+ }
+ }
+ }
+
+ // Found a nearby LivingEntity, make it Talkable and
+ // talkNear it if 'should_talk'
+ if (shouldTalk) {
+ new TalkableEntity(bystander).talkNear(context, text, this);
+ }
+ }
+ }
+}
diff --git a/src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java b/main/src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java
similarity index 97%
rename from src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java
index a05b1ece8..f5e59995b 100644
--- a/src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java
+++ b/main/src/main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java
@@ -1,82 +1,82 @@
-package net.citizensnpcs.npc.ai.speech;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import net.citizensnpcs.api.ai.speech.SpeechFactory;
-import net.citizensnpcs.api.ai.speech.Talkable;
-import net.citizensnpcs.api.ai.speech.VocalChord;
-
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-
-import com.google.common.base.Preconditions;
-
-public class CitizensSpeechFactory implements SpeechFactory {
- Map> registered = new HashMap>();
-
- @Override
- public VocalChord getVocalChord(Class extends VocalChord> clazz) {
- // Return a new instance of the VocalChord specified
- try {
- return clazz.newInstance();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- public VocalChord getVocalChord(String name) {
- // Check if VocalChord name is a registered type
- if (isRegistered(name))
- // Return a new instance of the VocalChord specified
- try {
- return registered.get(name.toLowerCase()).newInstance();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- public String getVocalChordName(Class extends VocalChord> clazz) {
- // Get the name of a VocalChord class that has been registered
- for (Entry> vocalChord : registered.entrySet())
- if (vocalChord.getValue() == clazz)
- return vocalChord.getKey();
-
- return null;
- }
-
- @Override
- public boolean isRegistered(String name) {
- return registered.containsKey(name.toLowerCase());
- }
-
- @Override
- public Talkable newTalkableEntity(Entity entity) {
- if (entity == null)
- return null;
- return new TalkableEntity(entity);
- }
-
- public Talkable newTalkableEntity(LivingEntity entity) {
- return newTalkableEntity((Entity) entity);
- }
-
- @Override
- public void register(Class extends VocalChord> clazz, String name) {
- Preconditions.checkNotNull(name, "info cannot be null");
- Preconditions.checkNotNull(clazz, "vocalchord cannot be null");
- if (registered.containsKey(name.toLowerCase()))
- throw new IllegalArgumentException("vocalchord name already registered");
- registered.put(name.toLowerCase(), clazz);
- }
-
-}
+package net.citizensnpcs.npc.ai.speech;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import net.citizensnpcs.api.ai.speech.SpeechFactory;
+import net.citizensnpcs.api.ai.speech.Talkable;
+import net.citizensnpcs.api.ai.speech.VocalChord;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+
+import com.google.common.base.Preconditions;
+
+public class CitizensSpeechFactory implements SpeechFactory {
+ Map> registered = new HashMap>();
+
+ @Override
+ public VocalChord getVocalChord(Class extends VocalChord> clazz) {
+ // Return a new instance of the VocalChord specified
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public VocalChord getVocalChord(String name) {
+ // Check if VocalChord name is a registered type
+ if (isRegistered(name))
+ // Return a new instance of the VocalChord specified
+ try {
+ return registered.get(name.toLowerCase()).newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public String getVocalChordName(Class extends VocalChord> clazz) {
+ // Get the name of a VocalChord class that has been registered
+ for (Entry> vocalChord : registered.entrySet())
+ if (vocalChord.getValue() == clazz)
+ return vocalChord.getKey();
+
+ return null;
+ }
+
+ @Override
+ public boolean isRegistered(String name) {
+ return registered.containsKey(name.toLowerCase());
+ }
+
+ @Override
+ public Talkable newTalkableEntity(Entity entity) {
+ if (entity == null)
+ return null;
+ return new TalkableEntity(entity);
+ }
+
+ public Talkable newTalkableEntity(LivingEntity entity) {
+ return newTalkableEntity((Entity) entity);
+ }
+
+ @Override
+ public void register(Class extends VocalChord> clazz, String name) {
+ Preconditions.checkNotNull(name, "info cannot be null");
+ Preconditions.checkNotNull(clazz, "vocalchord cannot be null");
+ if (registered.containsKey(name.toLowerCase()))
+ throw new IllegalArgumentException("vocalchord name already registered");
+ registered.put(name.toLowerCase(), clazz);
+ }
+
+}
diff --git a/src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java b/main/src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java
similarity index 97%
rename from src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java
rename to main/src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java
index 0453cddd8..c2c8248d9 100644
--- a/src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java
+++ b/main/src/main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java
@@ -1,92 +1,92 @@
-package net.citizensnpcs.npc.ai.speech;
-
-import net.citizensnpcs.api.CitizensAPI;
-import net.citizensnpcs.api.ai.speech.SpeechContext;
-import net.citizensnpcs.api.ai.speech.Talkable;
-import net.citizensnpcs.api.ai.speech.VocalChord;
-import net.citizensnpcs.api.ai.speech.event.SpeechBystanderEvent;
-import net.citizensnpcs.api.ai.speech.event.SpeechTargetedEvent;
-import net.citizensnpcs.api.npc.NPC;
-import net.citizensnpcs.api.util.Messaging;
-
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.Player;
-
-public class TalkableEntity implements Talkable {
- Entity entity;
-
- public TalkableEntity(Entity entity) {
- this.entity = entity;
- }
-
- public TalkableEntity(NPC npc) {
- entity = npc.getEntity();
- }
-
- public TalkableEntity(Player player) {
- entity = player;
- }
-
- /**
- * Used to compare a LivingEntity to this TalkableEntity
- *
- * @return 0 if the Entities are the same, 1 if they are not, -1 if the object compared is not a valid LivingEntity
- */
- @Override
- public int compareTo(Object o) {
- // If not living entity, return -1
- if (!(o instanceof Entity)) {
- return -1;
- // If NPC and matches, return 0
- } else if (CitizensAPI.getNPCRegistry().isNPC((Entity) o) && CitizensAPI.getNPCRegistry().isNPC(entity)
- && CitizensAPI.getNPCRegistry().getNPC((Entity) o).getUniqueId()
- .equals(CitizensAPI.getNPCRegistry().getNPC(entity).getUniqueId())) {
- return 0;
- } else if (entity.equals(o)) {
- return 0;
- } else {
- return 1;
- }
- }
-
- @Override
- public Entity getEntity() {
- return entity;
- }
-
- @Override
- public String getName() {
- if (CitizensAPI.getNPCRegistry().isNPC(entity)) {
- return CitizensAPI.getNPCRegistry().getNPC(entity).getName();
- } else if (entity instanceof Player) {
- return ((Player) entity).getName();
- } else {
- return entity.getType().name().replace("_", " ");
- }
- }
-
- private void talk(String message) {
- if (entity instanceof Player && !CitizensAPI.getNPCRegistry().isNPC(entity))
- Messaging.send((Player) entity, message);
- }
-
- @Override
- public void talkNear(SpeechContext context, String text, VocalChord vocalChord) {
- SpeechBystanderEvent event = new SpeechBystanderEvent(this, context, text, vocalChord);
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled())
- return;
- talk(event.getMessage());
- }
-
- @Override
- public void talkTo(SpeechContext context, String text, VocalChord vocalChord) {
- SpeechTargetedEvent event = new SpeechTargetedEvent(this, context, text, vocalChord);
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled())
- return;
- talk(event.getMessage());
- }
-
-}
+package net.citizensnpcs.npc.ai.speech;
+
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.ai.speech.SpeechContext;
+import net.citizensnpcs.api.ai.speech.Talkable;
+import net.citizensnpcs.api.ai.speech.VocalChord;
+import net.citizensnpcs.api.ai.speech.event.SpeechBystanderEvent;
+import net.citizensnpcs.api.ai.speech.event.SpeechTargetedEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.util.Messaging;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class TalkableEntity implements Talkable {
+ Entity entity;
+
+ public TalkableEntity(Entity entity) {
+ this.entity = entity;
+ }
+
+ public TalkableEntity(NPC npc) {
+ entity = npc.getEntity();
+ }
+
+ public TalkableEntity(Player player) {
+ entity = player;
+ }
+
+ /**
+ * Used to compare a LivingEntity to this TalkableEntity
+ *
+ * @return 0 if the Entities are the same, 1 if they are not, -1 if the object compared is not a valid LivingEntity
+ */
+ @Override
+ public int compareTo(Object o) {
+ // If not living entity, return -1
+ if (!(o instanceof Entity)) {
+ return -1;
+ // If NPC and matches, return 0
+ } else if (CitizensAPI.getNPCRegistry().isNPC((Entity) o) && CitizensAPI.getNPCRegistry().isNPC(entity)
+ && CitizensAPI.getNPCRegistry().getNPC((Entity) o).getUniqueId()
+ .equals(CitizensAPI.getNPCRegistry().getNPC(entity).getUniqueId())) {
+ return 0;
+ } else if (entity.equals(o)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ public Entity getEntity() {
+ return entity;
+ }
+
+ @Override
+ public String getName() {
+ if (CitizensAPI.getNPCRegistry().isNPC(entity)) {
+ return CitizensAPI.getNPCRegistry().getNPC(entity).getName();
+ } else if (entity instanceof Player) {
+ return ((Player) entity).getName();
+ } else {
+ return entity.getType().name().replace("_", " ");
+ }
+ }
+
+ private void talk(String message) {
+ if (entity instanceof Player && !CitizensAPI.getNPCRegistry().isNPC(entity))
+ Messaging.send((Player) entity, message);
+ }
+
+ @Override
+ public void talkNear(SpeechContext context, String text, VocalChord vocalChord) {
+ SpeechBystanderEvent event = new SpeechBystanderEvent(this, context, text, vocalChord);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled())
+ return;
+ talk(event.getMessage());
+ }
+
+ @Override
+ public void talkTo(SpeechContext context, String text, VocalChord vocalChord) {
+ SpeechTargetedEvent event = new SpeechTargetedEvent(this, context, text, vocalChord);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled())
+ return;
+ talk(event.getMessage());
+ }
+
+}
diff --git a/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchHandler.java b/main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchHandler.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/profile/ProfileFetchHandler.java
rename to main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchHandler.java
diff --git a/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchResult.java b/main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchResult.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/profile/ProfileFetchResult.java
rename to main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchResult.java
diff --git a/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchThread.java b/main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchThread.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/profile/ProfileFetchThread.java
rename to main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetchThread.java
diff --git a/src/main/java/net/citizensnpcs/npc/profile/ProfileFetcher.java b/main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetcher.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/profile/ProfileFetcher.java
rename to main/src/main/java/net/citizensnpcs/npc/profile/ProfileFetcher.java
diff --git a/src/main/java/net/citizensnpcs/npc/profile/ProfileRequest.java b/main/src/main/java/net/citizensnpcs/npc/profile/ProfileRequest.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/profile/ProfileRequest.java
rename to main/src/main/java/net/citizensnpcs/npc/profile/ProfileRequest.java
diff --git a/src/main/java/net/citizensnpcs/npc/skin/Skin.java b/main/src/main/java/net/citizensnpcs/npc/skin/Skin.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/skin/Skin.java
rename to main/src/main/java/net/citizensnpcs/npc/skin/Skin.java
diff --git a/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java b/main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java
rename to main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java
diff --git a/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java b/main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java
rename to main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java
diff --git a/src/main/java/net/citizensnpcs/npc/skin/SkinnableEntity.java b/main/src/main/java/net/citizensnpcs/npc/skin/SkinnableEntity.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/skin/SkinnableEntity.java
rename to main/src/main/java/net/citizensnpcs/npc/skin/SkinnableEntity.java
diff --git a/src/main/java/net/citizensnpcs/npc/skin/TabListRemover.java b/main/src/main/java/net/citizensnpcs/npc/skin/TabListRemover.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/npc/skin/TabListRemover.java
rename to main/src/main/java/net/citizensnpcs/npc/skin/TabListRemover.java
diff --git a/src/main/java/net/citizensnpcs/trait/Age.java b/main/src/main/java/net/citizensnpcs/trait/Age.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Age.java
rename to main/src/main/java/net/citizensnpcs/trait/Age.java
diff --git a/src/main/java/net/citizensnpcs/trait/Anchors.java b/main/src/main/java/net/citizensnpcs/trait/Anchors.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Anchors.java
rename to main/src/main/java/net/citizensnpcs/trait/Anchors.java
diff --git a/src/main/java/net/citizensnpcs/trait/ArmorStandTrait.java b/main/src/main/java/net/citizensnpcs/trait/ArmorStandTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/ArmorStandTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/ArmorStandTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/BossBarTrait.java b/main/src/main/java/net/citizensnpcs/trait/BossBarTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/BossBarTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/BossBarTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/Controllable.java b/main/src/main/java/net/citizensnpcs/trait/Controllable.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Controllable.java
rename to main/src/main/java/net/citizensnpcs/trait/Controllable.java
diff --git a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java b/main/src/main/java/net/citizensnpcs/trait/CurrentLocation.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/CurrentLocation.java
rename to main/src/main/java/net/citizensnpcs/trait/CurrentLocation.java
diff --git a/src/main/java/net/citizensnpcs/trait/Gravity.java b/main/src/main/java/net/citizensnpcs/trait/Gravity.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Gravity.java
rename to main/src/main/java/net/citizensnpcs/trait/Gravity.java
diff --git a/src/main/java/net/citizensnpcs/trait/HorseModifiers.java b/main/src/main/java/net/citizensnpcs/trait/HorseModifiers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/HorseModifiers.java
rename to main/src/main/java/net/citizensnpcs/trait/HorseModifiers.java
diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/main/src/main/java/net/citizensnpcs/trait/LookClose.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/LookClose.java
rename to main/src/main/java/net/citizensnpcs/trait/LookClose.java
diff --git a/src/main/java/net/citizensnpcs/trait/MountTrait.java b/main/src/main/java/net/citizensnpcs/trait/MountTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/MountTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/MountTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/NPCSkeletonType.java b/main/src/main/java/net/citizensnpcs/trait/NPCSkeletonType.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/NPCSkeletonType.java
rename to main/src/main/java/net/citizensnpcs/trait/NPCSkeletonType.java
diff --git a/src/main/java/net/citizensnpcs/trait/OcelotModifiers.java b/main/src/main/java/net/citizensnpcs/trait/OcelotModifiers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/OcelotModifiers.java
rename to main/src/main/java/net/citizensnpcs/trait/OcelotModifiers.java
diff --git a/src/main/java/net/citizensnpcs/trait/Poses.java b/main/src/main/java/net/citizensnpcs/trait/Poses.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Poses.java
rename to main/src/main/java/net/citizensnpcs/trait/Poses.java
diff --git a/src/main/java/net/citizensnpcs/trait/Powered.java b/main/src/main/java/net/citizensnpcs/trait/Powered.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Powered.java
rename to main/src/main/java/net/citizensnpcs/trait/Powered.java
diff --git a/src/main/java/net/citizensnpcs/trait/RabbitType.java b/main/src/main/java/net/citizensnpcs/trait/RabbitType.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/RabbitType.java
rename to main/src/main/java/net/citizensnpcs/trait/RabbitType.java
diff --git a/src/main/java/net/citizensnpcs/trait/Saddle.java b/main/src/main/java/net/citizensnpcs/trait/Saddle.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Saddle.java
rename to main/src/main/java/net/citizensnpcs/trait/Saddle.java
diff --git a/src/main/java/net/citizensnpcs/trait/ScriptTrait.java b/main/src/main/java/net/citizensnpcs/trait/ScriptTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/ScriptTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/ScriptTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/SheepTrait.java b/main/src/main/java/net/citizensnpcs/trait/SheepTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/SheepTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/SheepTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/SkinLayers.java b/main/src/main/java/net/citizensnpcs/trait/SkinLayers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/SkinLayers.java
rename to main/src/main/java/net/citizensnpcs/trait/SkinLayers.java
diff --git a/src/main/java/net/citizensnpcs/trait/SlimeSize.java b/main/src/main/java/net/citizensnpcs/trait/SlimeSize.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/SlimeSize.java
rename to main/src/main/java/net/citizensnpcs/trait/SlimeSize.java
diff --git a/src/main/java/net/citizensnpcs/trait/Toggleable.java b/main/src/main/java/net/citizensnpcs/trait/Toggleable.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/Toggleable.java
rename to main/src/main/java/net/citizensnpcs/trait/Toggleable.java
diff --git a/src/main/java/net/citizensnpcs/trait/VillagerProfession.java b/main/src/main/java/net/citizensnpcs/trait/VillagerProfession.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/VillagerProfession.java
rename to main/src/main/java/net/citizensnpcs/trait/VillagerProfession.java
diff --git a/src/main/java/net/citizensnpcs/trait/WitherTrait.java b/main/src/main/java/net/citizensnpcs/trait/WitherTrait.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/WitherTrait.java
rename to main/src/main/java/net/citizensnpcs/trait/WitherTrait.java
diff --git a/src/main/java/net/citizensnpcs/trait/WolfModifiers.java b/main/src/main/java/net/citizensnpcs/trait/WolfModifiers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/WolfModifiers.java
rename to main/src/main/java/net/citizensnpcs/trait/WolfModifiers.java
diff --git a/src/main/java/net/citizensnpcs/trait/WoolColor.java b/main/src/main/java/net/citizensnpcs/trait/WoolColor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/WoolColor.java
rename to main/src/main/java/net/citizensnpcs/trait/WoolColor.java
diff --git a/src/main/java/net/citizensnpcs/trait/ZombieModifier.java b/main/src/main/java/net/citizensnpcs/trait/ZombieModifier.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/ZombieModifier.java
rename to main/src/main/java/net/citizensnpcs/trait/ZombieModifier.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/PageChangePrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/PageChangePrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/PageChangePrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/PageChangePrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/Text.java b/main/src/main/java/net/citizensnpcs/trait/text/Text.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/Text.java
rename to main/src/main/java/net/citizensnpcs/trait/text/Text.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/TextAddPrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/TextAddPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/TextAddPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/TextAddPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/TextEditPrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/TextEditPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/TextEditPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/TextEditPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/TextEditStartPrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/TextEditStartPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/TextEditStartPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/TextEditStartPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/TextRemovePrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/TextRemovePrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/TextRemovePrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/TextRemovePrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/text/TextStartPrompt.java b/main/src/main/java/net/citizensnpcs/trait/text/TextStartPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/text/TextStartPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/text/TextStartPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/GuidedWaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/GuidedWaypointProvider.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/GuidedWaypointProvider.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/GuidedWaypointProvider.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointsCompleteEvent.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointsCompleteEvent.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointsCompleteEvent.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointsCompleteEvent.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WanderWaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/WanderWaypointProvider.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/WanderWaypointProvider.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/WanderWaypointProvider.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointEditor.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointEditor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/WaypointEditor.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointEditor.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointMarkers.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointMarkers.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/WaypointMarkers.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointMarkers.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoints.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerRemovePrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerRemovePrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerRemovePrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerRemovePrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTrigger.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTrigger.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTrigger.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTrigger.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerPrompt.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerPrompt.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerPrompt.java
diff --git a/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerRegistry.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerRegistry.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerRegistry.java
rename to main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerRegistry.java
diff --git a/src/main/java/net/citizensnpcs/util/Anchor.java b/main/src/main/java/net/citizensnpcs/util/Anchor.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/Anchor.java
rename to main/src/main/java/net/citizensnpcs/util/Anchor.java
diff --git a/src/main/java/net/citizensnpcs/util/BoundingBox.java b/main/src/main/java/net/citizensnpcs/util/BoundingBox.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/BoundingBox.java
rename to main/src/main/java/net/citizensnpcs/util/BoundingBox.java
diff --git a/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/Messages.java
rename to main/src/main/java/net/citizensnpcs/util/Messages.java
diff --git a/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/NMS.java
rename to main/src/main/java/net/citizensnpcs/util/NMS.java
diff --git a/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/NMSBridge.java
rename to main/src/main/java/net/citizensnpcs/util/NMSBridge.java
diff --git a/src/main/java/net/citizensnpcs/util/PlayerAnimation.java b/main/src/main/java/net/citizensnpcs/util/PlayerAnimation.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/PlayerAnimation.java
rename to main/src/main/java/net/citizensnpcs/util/PlayerAnimation.java
diff --git a/src/main/java/net/citizensnpcs/util/PlayerUpdateTask.java b/main/src/main/java/net/citizensnpcs/util/PlayerUpdateTask.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/PlayerUpdateTask.java
rename to main/src/main/java/net/citizensnpcs/util/PlayerUpdateTask.java
diff --git a/src/main/java/net/citizensnpcs/util/Pose.java b/main/src/main/java/net/citizensnpcs/util/Pose.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/Pose.java
rename to main/src/main/java/net/citizensnpcs/util/Pose.java
diff --git a/src/main/java/net/citizensnpcs/util/StringHelper.java b/main/src/main/java/net/citizensnpcs/util/StringHelper.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/StringHelper.java
rename to main/src/main/java/net/citizensnpcs/util/StringHelper.java
diff --git a/src/main/java/net/citizensnpcs/util/Util.java b/main/src/main/java/net/citizensnpcs/util/Util.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/Util.java
rename to main/src/main/java/net/citizensnpcs/util/Util.java
diff --git a/src/main/java/net/citizensnpcs/util/XORShiftRNG.java b/main/src/main/java/net/citizensnpcs/util/XORShiftRNG.java
similarity index 100%
rename from src/main/java/net/citizensnpcs/util/XORShiftRNG.java
rename to main/src/main/java/net/citizensnpcs/util/XORShiftRNG.java
diff --git a/src/main/resources/messages_de.properties b/main/src/main/resources/messages_de.properties
similarity index 100%
rename from src/main/resources/messages_de.properties
rename to main/src/main/resources/messages_de.properties
diff --git a/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties
similarity index 100%
rename from src/main/resources/messages_en.properties
rename to main/src/main/resources/messages_en.properties
diff --git a/src/main/resources/messages_es.properties b/main/src/main/resources/messages_es.properties
similarity index 100%
rename from src/main/resources/messages_es.properties
rename to main/src/main/resources/messages_es.properties
diff --git a/src/main/resources/messages_fr.properties b/main/src/main/resources/messages_fr.properties
similarity index 100%
rename from src/main/resources/messages_fr.properties
rename to main/src/main/resources/messages_fr.properties
diff --git a/src/main/resources/messages_nl.properties b/main/src/main/resources/messages_nl.properties
similarity index 100%
rename from src/main/resources/messages_nl.properties
rename to main/src/main/resources/messages_nl.properties
diff --git a/src/main/resources/plugin.yml b/main/src/main/resources/plugin.yml
similarity index 100%
rename from src/main/resources/plugin.yml
rename to main/src/main/resources/plugin.yml
diff --git a/pom.xml b/pom.xml
index 4ed508905..3e8393ed2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,177 +1,16 @@
-
+
+
+ 4.0.0
-
- 4.0.0
-
- net.citizensnpcs
- citizens
- 2.0.20-SNAPSHOT
- Citizens
-
-
- UTF-8
- 1.10-R0.1-SNAPSHOT
- 1.9.4-R0.1-SNAPSHOT
- 2.0.20-SNAPSHOT
- 1.5.4
- 1.4.12
- Unknown
- Unknown
-
-
-
-
- bukkit-repo
- http://repo.bukkit.org/content/groups/public/
-
-
- everything
- http://repo.citizensnpcs.co
-
-
- vault-repo
- http://nexus.theyeticave.net/content/repositories/pub_releases
-
-
-
-
-
- bukkit-plugins
- http://repo.bukkit.org/content/groups/public
-
-
-
-
-
- org.bukkit
- bukkit
- ${craftbukkit.version}
- jar
- provided
-
-
- org.bukkit
- craftbukkit
- ${craftbukkit.1.9.version}
- jar
- provided
-
-
- org.bukkit
- craftbukkit
- ${craftbukkit.version}
- jar
- provided
-
-
- net.citizensnpcs
- citizensapi
- ${citizensapi.version}
- jar
- compile
-
-
- net.sf.trove4j
- trove4j
- 3.0.3
- compile
-
-
- net.milkbowl.vault
- Vault
- ${vault.version}
- jar
- provided
-
-
- org.powermock
- powermock-module-junit4
- ${powermock.version}
- test
-
-
- org.powermock
- powermock-api-mockito
- ${powermock.version}
- test
-
-
-
- http://www.citizensnpcs.co
-
- jenkins
- http://ci.citizensnpcs.co
-
-
- scm:git:git://github.com/CitizensDev/Citizens2.git
- scm:git:git:@github.com:CitizensDev/Citizens2.git
- https://github.com/CitizensDev/Citizens2/tree/master/
-
-
- clean package install
- ${basedir}/src/main/java
-
-
-
- .
- true
- ${basedir}/src/main/resources
-
- plugin.yml
- *.properties
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
-
- 1.6
- 1.6
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.3.2
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.1
-
-
- package
-
- shade
-
-
- true
-
-
- net.citizensnpcs:citizensapi
-
- **
-
-
-
-
-
- gnu.trove
- lib.trove
-
-
-
-
-
-
-
-
-
-
+ pom
+ net.citizensnpcs
+ citizens-parent
+ 2.0.20-SNAPSHOT
+
+ Main
+ v1_10_R1
+ Dist
+
+
\ No newline at end of file
diff --git a/v1_10_R1/pom.xml b/v1_10_R1/pom.xml
new file mode 100644
index 000000000..6101f57e4
--- /dev/null
+++ b/v1_10_R1/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+ net.citizensnpcs
+ citizens-parent
+ 2.0.20-SNAPSHOT
+
+ citizens-v1_10_R1
+
+
+ UTF-8
+ 1.10-R0.1-SNAPSHOT
+
+
+
+
+ everything
+ http://repo.citizensnpcs.co
+
+
+
+
+
+ ${project.groupId}
+ citizens-main
+ ${project.version}
+ jar
+ provided
+
+
+ org.bukkit
+ craftbukkit
+ ${craftbukkit.version}
+ jar
+ provided
+
+
+
+
+ clean package install
+ ${basedir}/src/main/java
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.6
+ 1.6
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.3.2
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.1
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java
new file mode 100644
index 000000000..2eb87ee0f
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BatController.java
@@ -0,0 +1,172 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftBat;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Bat;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityBat;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class BatController extends MobEntityController {
+ public BatController() {
+ super(EntityBatNPC.class);
+ }
+
+ @Override
+ public Bat getBukkitEntity() {
+ return (Bat) super.getBukkitEntity();
+ }
+
+ public static class BatNPC extends CraftBat implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public BatNPC(EntityBatNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityBatNPC extends EntityBat implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityBatNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityBatNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ setFlying(false);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new BatNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null) {
+ return super.isLeashed();
+ }
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ if (npc == null) {
+ super.M();
+ } else {
+ NMSImpl.updateAI(this);
+ npc.update();
+ }
+ }
+
+ public void setFlying(boolean flying) {
+ setAsleep(flying);
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java
new file mode 100644
index 000000000..f9a46920d
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/BlazeController.java
@@ -0,0 +1,163 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftBlaze;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Blaze;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityBlaze;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class BlazeController extends MobEntityController {
+ public BlazeController() {
+ super(EntityBlazeNPC.class);
+ }
+
+ @Override
+ public Blaze getBukkitEntity() {
+ return (Blaze) super.getBukkitEntity();
+ }
+
+ public static class BlazeNPC extends CraftBlaze implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public BlazeNPC(EntityBlazeNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityBlazeNPC extends EntityBlaze implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityBlazeNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityBlazeNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new BlazeNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ if (npc != null) {
+ npc.update();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java
new file mode 100644
index 000000000..8c8683ec3
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CaveSpiderController.java
@@ -0,0 +1,209 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftCaveSpider;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.CaveSpider;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityCaveSpider;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class CaveSpiderController extends MobEntityController {
+ public CaveSpiderController() {
+ super(EntityCaveSpiderNPC.class);
+ }
+
+ @Override
+ public CaveSpider getBukkitEntity() {
+ return (CaveSpider) super.getBukkitEntity();
+ }
+
+ public static class CaveSpiderNPC extends CraftCaveSpider implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public CaveSpiderNPC(EntityCaveSpiderNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityCaveSpiderNPC extends EntityCaveSpider implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityCaveSpiderNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityCaveSpiderNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new CaveSpiderNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null) {
+ return super.isLeashed();
+ }
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) {
+ return super.isLeashed();
+ }
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java
new file mode 100644
index 000000000..1e9758de3
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ChickenController.java
@@ -0,0 +1,217 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftChicken;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Chicken;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityChicken;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ChickenController extends MobEntityController {
+ public ChickenController() {
+ super(EntityChickenNPC.class);
+ }
+
+ @Override
+ public Chicken getBukkitEntity() {
+ return (Chicken) super.getBukkitEntity();
+ }
+
+ public static class ChickenNPC extends CraftChicken implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ChickenNPC(EntityChickenNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityChickenNPC extends EntityChicken implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityChickenNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityChickenNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new ChickenNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void n() {
+ if (npc != null) {
+ this.bD = 100; // egg timer
+ }
+ super.n();
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java
new file mode 100644
index 000000000..38c52de59
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CowController.java
@@ -0,0 +1,210 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftCow;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Cow;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityCow;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class CowController extends MobEntityController {
+ public CowController() {
+ super(EntityCowNPC.class);
+ }
+
+ @Override
+ public Cow getBukkitEntity() {
+ return (Cow) super.getBukkitEntity();
+ }
+
+ public static class CowNPC extends CraftCow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public CowNPC(EntityCowNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityCowNPC extends EntityCow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityCowNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityCowNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new CowNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java
new file mode 100644
index 000000000..6352c4068
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/CreeperController.java
@@ -0,0 +1,229 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftCreeper;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Creeper;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityCreeper;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntityLightning;
+import net.minecraft.server.v1_10_R1.EnumHand;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.ItemStack;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class CreeperController extends MobEntityController {
+ public CreeperController() {
+ super(EntityCreeperNPC.class);
+ }
+
+ @Override
+ public Creeper getBukkitEntity() {
+ return (Creeper) super.getBukkitEntity();
+ }
+
+ public static class CreeperNPC extends CraftCreeper implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public CreeperNPC(EntityCreeperNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityCreeperNPC extends EntityCreeper implements NPCHolder {
+ private boolean allowPowered;
+ private final CitizensNPC npc;
+
+ public EntityCreeperNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityCreeperNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected boolean a(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) {
+ return npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)
+ ? super.a(entityhuman, enumhand, itemstack) : false;
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.g(x, y, z);
+ }
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new CreeperNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void onLightningStrike(EntityLightning entitylightning) {
+ if (npc == null || allowPowered) {
+ super.onLightningStrike(entitylightning);
+ }
+ }
+
+ public void setAllowPowered(boolean allowPowered) {
+ this.allowPowered = allowPowered;
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java
new file mode 100644
index 000000000..420170208
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EnderDragonController.java
@@ -0,0 +1,180 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEnderDragon;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.EnderDragon;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityEnderDragon;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class EnderDragonController extends MobEntityController {
+ public EnderDragonController() {
+ super(EntityEnderDragonNPC.class);
+ }
+
+ @Override
+ public EnderDragon getBukkitEntity() {
+ return (EnderDragon) super.getBukkitEntity();
+ }
+
+ public static class EnderDragonNPC extends CraftEnderDragon implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EnderDragonNPC(EntityEnderDragonNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEnderDragonNPC extends EntityEnderDragon implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEnderDragonNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityEnderDragonNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new EnderDragonNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ private float getCorrectYaw(double tX, double tZ) {
+ if (locZ > tZ)
+ return (float) (-Math.toDegrees(Math.atan((locX - tX) / (locZ - tZ))));
+ if (locZ < tZ) {
+ return (float) (-Math.toDegrees(Math.atan((locX - tX) / (locZ - tZ)))) + 180.0F;
+ }
+ return yaw;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void n() {
+ if (npc != null) {
+ npc.update();
+ if (motX != 0 || motY != 0 || motZ != 0) {
+ motX *= 0.98;
+ motY *= 0.98;
+ motZ *= 0.98;
+ yaw = getCorrectYaw(locX + motX, locZ + motZ);
+ setPosition(locX + motX, locY + motY, locZ + motZ);
+ }
+ } else {
+ super.n();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java
new file mode 100644
index 000000000..a61335895
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermanController.java
@@ -0,0 +1,214 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEnderman;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Enderman;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityEnderman;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class EndermanController extends MobEntityController {
+ public EndermanController() {
+ super(EntityEndermanNPC.class);
+ }
+
+ @Override
+ public Enderman getBukkitEntity() {
+ return (Enderman) super.getBukkitEntity();
+ }
+
+ public static class EndermanNPC extends CraftEnderman implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EndermanNPC(EntityEndermanNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEndermanNPC extends EntityEnderman implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEndermanNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityEndermanNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new EndermanNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ public boolean k(double d1, double d2, double d3) {
+ if (npc == null) {
+ return super.k(d1, d2, d3);
+ }
+ return false;
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java
new file mode 100644
index 000000000..00983e1d4
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EndermiteController.java
@@ -0,0 +1,205 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEndermite;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Endermite;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityEndermite;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class EndermiteController extends MobEntityController {
+ public EndermiteController() {
+ super(EntityEndermiteNPC.class);
+ }
+
+ @Override
+ public Endermite getBukkitEntity() {
+ return (Endermite) super.getBukkitEntity();
+ }
+
+ public static class EndermiteNPC extends CraftEndermite implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EndermiteNPC(EntityEndermiteNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEndermiteNPC extends EntityEndermite implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEndermiteNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityEndermiteNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new EndermiteNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java
new file mode 100644
index 000000000..3f23b8e95
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/EntityHumanNPC.java
@@ -0,0 +1,475 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.List;
+import java.util.Map;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.metadata.MetadataValue;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.util.Vector;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.mojang.authlib.GameProfile;
+
+import net.citizensnpcs.Settings.Setting;
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.MetadataStore;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.trait.trait.Inventory;
+import net.citizensnpcs.nms.v1_10_R1.network.EmptyNetHandler;
+import net.citizensnpcs.nms.v1_10_R1.network.EmptyNetworkManager;
+import net.citizensnpcs.nms.v1_10_R1.network.EmptySocket;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerControllerJump;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerControllerLook;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerControllerMove;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerNavigation;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.npc.skin.SkinPacketTracker;
+import net.citizensnpcs.npc.skin.SkinnableEntity;
+import net.citizensnpcs.trait.Gravity;
+import net.citizensnpcs.util.NMS;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.AttributeInstance;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.Entity;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntityPlayer;
+import net.minecraft.server.v1_10_R1.EnumGamemode;
+import net.minecraft.server.v1_10_R1.EnumItemSlot;
+import net.minecraft.server.v1_10_R1.EnumProtocolDirection;
+import net.minecraft.server.v1_10_R1.GenericAttributes;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.MathHelper;
+import net.minecraft.server.v1_10_R1.MinecraftServer;
+import net.minecraft.server.v1_10_R1.NavigationAbstract;
+import net.minecraft.server.v1_10_R1.NetworkManager;
+import net.minecraft.server.v1_10_R1.Packet;
+import net.minecraft.server.v1_10_R1.PacketPlayOutEntityEquipment;
+import net.minecraft.server.v1_10_R1.PacketPlayOutEntityHeadRotation;
+import net.minecraft.server.v1_10_R1.PathType;
+import net.minecraft.server.v1_10_R1.PlayerInteractManager;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+public class EntityHumanNPC extends EntityPlayer implements NPCHolder, SkinnableEntity {
+ private final Map bz = Maps.newEnumMap(PathType.class);
+ private PlayerControllerJump controllerJump;
+ private PlayerControllerLook controllerLook;
+ private PlayerControllerMove controllerMove;
+ private int jumpTicks = 0;
+ private PlayerNavigation navigation;
+ private final CitizensNPC npc;
+ private final Location packetLocationCache = new Location(null, 0, 0, 0);
+ private final SkinPacketTracker skinTracker;
+ private int updateCounter = 0;
+
+ public EntityHumanNPC(MinecraftServer minecraftServer, WorldServer world, GameProfile gameProfile,
+ PlayerInteractManager playerInteractManager, NPC npc) {
+ super(minecraftServer, world, gameProfile, playerInteractManager);
+
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ skinTracker = new SkinPacketTracker(this);
+ playerInteractManager.setGameMode(EnumGamemode.SURVIVAL);
+ initialise(minecraftServer);
+ } else {
+ skinTracker = null;
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ public float a(PathType pathtype) {
+ return this.bz.containsKey(pathtype) ? this.bz.get(pathtype).floatValue() : pathtype.a();
+ }
+
+ public void a(PathType pathtype, float f) {
+ this.bz.put(pathtype, Float.valueOf(f));
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ // knock back velocity is cancelled and sent to client for handling when
+ // the entity is a player. there is no client so make this happen
+ // manually.
+ boolean damaged = super.damageEntity(damagesource, f);
+ if (damaged && velocityChanged) {
+ velocityChanged = false;
+ Bukkit.getScheduler().runTask(CitizensAPI.getPlugin(), new Runnable() {
+ @Override
+ public void run() {
+ EntityHumanNPC.this.velocityChanged = true;
+ }
+ });
+ }
+ return damaged;
+ }
+
+ @Override
+ public void die(DamageSource damagesource) {
+ // players that die are not normally removed from the world. when the
+ // NPC dies, we are done with the instance and it should be removed.
+ if (dead) {
+ return;
+ }
+ super.die(damagesource);
+ Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
+ @Override
+ public void run() {
+ world.removeEntity(EntityHumanNPC.this);
+ }
+ }, 35); // give enough time for death and smoke animation
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.g(x, y, z);
+ }
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ public CraftPlayer getBukkitEntity() {
+ if (npc != null && bukkitEntity == null) {
+ bukkitEntity = new PlayerNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ public PlayerControllerJump getControllerJump() {
+ return controllerJump;
+ }
+
+ public PlayerControllerMove getControllerMove() {
+ return controllerMove;
+ }
+
+ public NavigationAbstract getNavigation() {
+ return navigation;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public String getSkinName() {
+ MetadataStore meta = npc.data();
+
+ String skinName = meta.get(NPC.PLAYER_SKIN_UUID_METADATA);
+ if (skinName == null) {
+ skinName = ChatColor.stripColor(getName());
+ }
+ return skinName.toLowerCase();
+ }
+
+ @Override
+ public SkinPacketTracker getSkinTracker() {
+ return skinTracker;
+ }
+
+ private void initialise(MinecraftServer minecraftServer) {
+ Socket socket = new EmptySocket();
+ NetworkManager conn = null;
+ try {
+ conn = new EmptyNetworkManager(EnumProtocolDirection.CLIENTBOUND);
+ playerConnection = new EmptyNetHandler(minecraftServer, conn, this);
+ conn.setPacketListener(playerConnection);
+ socket.close();
+ } catch (IOException e) {
+ // swallow
+ }
+
+ AttributeInstance range = getAttributeInstance(GenericAttributes.FOLLOW_RANGE);
+ if (range == null) {
+ range = getAttributeMap().b(GenericAttributes.FOLLOW_RANGE);
+ }
+ range.setValue(Setting.DEFAULT_PATHFINDING_RANGE.asDouble());
+
+ controllerJump = new PlayerControllerJump(this);
+ controllerLook = new PlayerControllerLook(this);
+ controllerMove = new PlayerControllerMove(this);
+ navigation = new PlayerNavigation(this, world);
+ NMS.setStepHeight(getBukkitEntity(), 1); // the default (0) breaks step climbing
+
+ setSkinFlags((byte) 0xFF);
+ }
+
+ @Override
+ public boolean isCollidable() {
+ return npc == null ? super.isCollidable() : npc.data().get(NPC.COLLIDABLE_METADATA, true);
+ }
+
+ public boolean isNavigating() {
+ return npc.getNavigator().isNavigating();
+ }
+
+ @Override
+ public void m() {
+ super.m();
+ if (npc == null)
+ return;
+ if (updateCounter + 1 > Setting.PACKET_UPDATE_DELAY.asInt()) {
+ updateEffects = true;
+ }
+ tickPotionEffects();
+
+ boolean navigating = npc.getNavigator().isNavigating();
+ updatePackets(navigating);
+ if (!navigating && getBukkitEntity() != null && npc.getTrait(Gravity.class).hasGravity()
+ && Util.isLoaded(getBukkitEntity().getLocation(LOADED_LOCATION))) {
+ g(0, 0);
+ }
+
+ if (Math.abs(motX) < EPSILON && Math.abs(motY) < EPSILON && Math.abs(motZ) < EPSILON) {
+ motX = motY = motZ = 0;
+ }
+ if (navigating) {
+ if (!NMSImpl.isNavigationFinished(navigation)) {
+ NMSImpl.updateNavigation(navigation);
+ }
+ moveOnCurrentHeading();
+ }
+
+ if (noDamageTicks > 0) {
+ --noDamageTicks;
+ }
+
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ private void moveOnCurrentHeading() {
+ NMSImpl.updateAI(this);
+ if (be) {
+ if (onGround && jumpTicks == 0) {
+ cl();
+ jumpTicks = 10;
+ }
+ } else {
+ jumpTicks = 0;
+ }
+ bf *= 0.98F;
+ bg *= 0.98F;
+ bh *= 0.9F;
+ g(bf, bg); // movement method
+ NMS.setHeadYaw(getBukkitEntity(), yaw);
+ if (jumpTicks > 0) {
+ jumpTicks--;
+ }
+ }
+
+ public void setMoveDestination(double x, double y, double z, double speed) {
+ controllerMove.a(x, y, z, speed);
+ }
+
+ public void setShouldJump() {
+ controllerJump.a();
+ }
+
+ @Override
+ public void setSkinFlags(byte flags) {
+ // set skin flag byte
+ getDataWatcher().set(EntityHuman.br, flags);
+ }
+
+ @Override
+ public void setSkinName(String name) {
+ setSkinName(name, false);
+ }
+
+ @Override
+ public void setSkinName(String name, boolean forceUpdate) {
+ Preconditions.checkNotNull(name);
+
+ npc.data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, name.toLowerCase());
+ skinTracker.notifySkinChange(forceUpdate);
+ }
+
+ public void setTargetLook(Entity target, float yawOffset, float renderOffset) {
+ controllerLook.a(target, yawOffset, renderOffset);
+ }
+
+ public void updateAI() {
+ controllerMove.c();
+ controllerLook.a();
+ controllerJump.b();
+ }
+
+ private void updatePackets(boolean navigating) {
+ if (updateCounter++ > Setting.PACKET_UPDATE_DELAY.asInt()) {
+ updateCounter = 0;
+ Location current = getBukkitEntity().getLocation(packetLocationCache);
+ Packet>[] packets = new Packet[navigating ? EnumItemSlot.values().length
+ : EnumItemSlot.values().length + 1];
+ if (!navigating) {
+ packets[5] = new PacketPlayOutEntityHeadRotation(this,
+ (byte) MathHelper.d(NMSImpl.getHeadYaw(this) * 256.0F / 360.0F));
+ }
+ int i = 0;
+ for (EnumItemSlot slot : EnumItemSlot.values()) {
+ packets[i++] = new PacketPlayOutEntityEquipment(getId(), slot, getEquipment(slot));
+ }
+ NMSImpl.sendPacketsNearby(getBukkitEntity(), current, packets);
+ }
+ }
+
+ public void updatePathfindingRange(float pathfindingRange) {
+ this.navigation.setRange(pathfindingRange);
+ }
+
+ public static class PlayerNPC extends CraftPlayer implements NPCHolder, SkinnableEntity {
+ private final CraftServer cserver;
+ private final CitizensNPC npc;
+
+ private PlayerNPC(EntityHumanNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ this.cserver = (CraftServer) Bukkit.getServer();
+ npc.getTrait(Inventory.class);
+ }
+
+ @Override
+ public Player getBukkitEntity() {
+ return this;
+ }
+
+ @Override
+ public EntityHumanNPC getHandle() {
+ return (EntityHumanNPC) this.entity;
+ }
+
+ @Override
+ public List getMetadata(String metadataKey) {
+ return cserver.getEntityMetadata().getMetadata(this, metadataKey);
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public String getSkinName() {
+ return ((SkinnableEntity) this.entity).getSkinName();
+ }
+
+ @Override
+ public SkinPacketTracker getSkinTracker() {
+ return ((SkinnableEntity) this.entity).getSkinTracker();
+ }
+
+ @Override
+ public boolean hasMetadata(String metadataKey) {
+ return cserver.getEntityMetadata().hasMetadata(this, metadataKey);
+ }
+
+ @Override
+ public void removeMetadata(String metadataKey, Plugin owningPlugin) {
+ cserver.getEntityMetadata().removeMetadata(this, metadataKey, owningPlugin);
+ }
+
+ @Override
+ public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
+ cserver.getEntityMetadata().setMetadata(this, metadataKey, newMetadataValue);
+ }
+
+ @Override
+ public void setSkinFlags(byte flags) {
+ ((SkinnableEntity) this.entity).setSkinFlags(flags);
+ }
+
+ @Override
+ public void setSkinName(String name) {
+ ((SkinnableEntity) this.entity).setSkinName(name);
+ }
+
+ @Override
+ public void setSkinName(String skinName, boolean forceUpdate) {
+ ((SkinnableEntity) this.entity).setSkinName(skinName, forceUpdate);
+ }
+ }
+
+ private static final float EPSILON = 0.005F;
+
+ private static final Location LOADED_LOCATION = new Location(null, 0, 0, 0);
+}
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java
new file mode 100644
index 000000000..7806fca8b
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GhastController.java
@@ -0,0 +1,169 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftGhast;
+import org.bukkit.entity.Ghast;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityGhast;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class GhastController extends MobEntityController {
+ public GhastController() {
+ super(EntityGhastNPC.class);
+ }
+
+ @Override
+ public Ghast getBukkitEntity() {
+ return (Ghast) super.getBukkitEntity();
+ }
+
+ public static class EntityGhastNPC extends EntityGhast implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityGhastNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityGhastNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean ct() {
+ return npc != null;
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new GhastNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ if (npc != null) {
+ npc.update();
+ }
+ super.M();
+ }
+ }
+
+ public static class GhastNPC extends CraftGhast implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public GhastNPC(EntityGhastNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java
new file mode 100644
index 000000000..5ba76aee4
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GiantController.java
@@ -0,0 +1,206 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftGiant;
+import org.bukkit.entity.Giant;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityGiantZombie;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class GiantController extends MobEntityController {
+ public GiantController() {
+ super(EntityGiantNPC.class);
+ }
+
+ @Override
+ public Giant getBukkitEntity() {
+ return (Giant) super.getBukkitEntity();
+ }
+
+ public static class EntityGiantNPC extends EntityGiantZombie implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityGiantNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityGiantNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new GiantNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class GiantNPC extends CraftGiant implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public GiantNPC(EntityGiantNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java
new file mode 100644
index 000000000..bc9f3ef46
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/GuardianController.java
@@ -0,0 +1,219 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftGuardian;
+import org.bukkit.entity.Guardian;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityGuardian;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class GuardianController extends MobEntityController {
+ public GuardianController() {
+ super(EntityGuardianNPC.class);
+ }
+
+ @Override
+ public Guardian getBukkitEntity() {
+ return (Guardian) super.getBukkitEntity();
+ }
+
+ public static class EntityGuardianNPC extends EntityGuardian implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityGuardianNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityGuardianNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new GuardianNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void m() {
+ if (npc == null) {
+ super.m();
+ } else {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setElder(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.setElder(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class GuardianNPC extends CraftGuardian implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public GuardianNPC(EntityGuardianNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java
new file mode 100644
index 000000000..f4f04644b
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HorseController.java
@@ -0,0 +1,229 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftHorse;
+import org.bukkit.entity.Horse;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.trait.HorseModifiers;
+import net.citizensnpcs.util.NMS;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityHorse;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class HorseController extends MobEntityController {
+ public HorseController() {
+ super(EntityHorseNPC.class);
+ }
+
+ @Override
+ public Horse getBukkitEntity() {
+ return (Horse) super.getBukkitEntity();
+ }
+
+ @Override
+ public void spawn(Location at, NPC npc) {
+ npc.getTrait(HorseModifiers.class);
+ super.spawn(at, npc);
+ }
+
+ public static class EntityHorseNPC extends EntityHorse implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityHorseNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityHorseNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ ((Horse) getBukkitEntity()).setDomestication(((Horse) getBukkitEntity()).getMaxDomestication());
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean di() {
+ if (npc == null)
+ return super.di();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ return super.di() && !protectedDefault;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new HorseNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ if (npc == null) {
+ super.M();
+ } else {
+ NMS.setStepHeight(getBukkitEntity(), 1);
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class HorseNPC extends CraftHorse implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public HorseNPC(EntityHorseNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java
new file mode 100644
index 000000000..4d7ec3716
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/HumanController.java
@@ -0,0 +1,142 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.scoreboard.Scoreboard;
+import org.bukkit.scoreboard.Team;
+
+import com.mojang.authlib.GameProfile;
+
+import net.citizensnpcs.Settings.Setting;
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.util.Colorizer;
+import net.citizensnpcs.npc.AbstractEntityController;
+import net.citizensnpcs.npc.skin.Skin;
+import net.citizensnpcs.npc.skin.SkinnableEntity;
+import net.citizensnpcs.util.NMS;
+import net.minecraft.server.v1_10_R1.PlayerInteractManager;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+public class HumanController extends AbstractEntityController {
+ public HumanController() {
+ super();
+ }
+
+ @Override
+ protected Entity createEntity(final Location at, final NPC npc) {
+ final WorldServer nmsWorld = ((CraftWorld) at.getWorld()).getHandle();
+ String coloredName = Colorizer.parseColors(npc.getFullName());
+
+ String name = coloredName, prefix = null, suffix = null;
+ if (coloredName.length() > 16) {
+ prefix = coloredName.substring(0, 16);
+ if (coloredName.length() > 30) {
+ int len = 30;
+ name = coloredName.substring(16, 30);
+ if (NON_ALPHABET_MATCHER.matcher(name).matches()) {
+ if (coloredName.length() >= 32) {
+ len = 32;
+ name = coloredName.substring(16, 32);
+ } else if (coloredName.length() == 31) {
+ len = 31;
+ name = coloredName.substring(16, 31);
+ }
+ } else {
+ name = ChatColor.RESET + name;
+ }
+ suffix = coloredName.substring(len);
+ } else {
+ name = coloredName.substring(16);
+ if (!NON_ALPHABET_MATCHER.matcher(name).matches()) {
+ name = ChatColor.RESET + name;
+ }
+ if (name.length() > 16) {
+ suffix = name.substring(16);
+ name = name.substring(0, 16);
+ }
+ }
+ coloredName = coloredName.substring(0, 16);
+ }
+
+ final String prefixCapture = prefix, suffixCapture = suffix;
+
+ UUID uuid = npc.getUniqueId();
+ if (uuid.version() == 4) { // clear version
+ long msb = uuid.getMostSignificantBits();
+ msb &= ~0x0000000000004000L;
+ msb |= 0x0000000000002000L;
+ uuid = new UUID(msb, uuid.getLeastSignificantBits());
+ }
+
+ final GameProfile profile = new GameProfile(uuid, name);
+
+ final EntityHumanNPC handle = new EntityHumanNPC(nmsWorld.getServer().getServer(), nmsWorld, profile,
+ new PlayerInteractManager(nmsWorld), npc);
+
+ Skin skin = handle.getSkinTracker().getSkin();
+ if (skin != null) {
+ skin.apply(handle);
+ }
+
+ Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
+ @Override
+ public void run() {
+ if (getBukkitEntity() == null || !getBukkitEntity().isValid())
+ return;
+ boolean removeFromPlayerList = npc.data().get("removefromplayerlist",
+ Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean());
+ NMS.addOrRemoveFromPlayerList(getBukkitEntity(),
+ npc.data().get("removefromplayerlist", removeFromPlayerList));
+
+ if (Setting.USE_SCOREBOARD_TEAMS.asBoolean()) {
+ Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard();
+ String teamName = profile.getId().toString().substring(0, 16);
+
+ Team team = scoreboard.getTeam(teamName);
+ if (team == null) {
+ team = scoreboard.registerNewTeam(teamName);
+ if (prefixCapture != null) {
+ team.setPrefix(prefixCapture);
+ }
+ if (suffixCapture != null) {
+ team.setSuffix(suffixCapture);
+ }
+ }
+ team.addPlayer(handle.getBukkitEntity());
+
+ handle.getNPC().data().set(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, teamName);
+ }
+ }
+ }, 20);
+
+ handle.getBukkitEntity().setSleepingIgnored(true);
+
+ return handle.getBukkitEntity();
+ }
+
+ @Override
+ public Player getBukkitEntity() {
+ return (Player) super.getBukkitEntity();
+ }
+
+ @Override
+ public void remove() {
+ Player entity = getBukkitEntity();
+ if (entity != null) {
+ NMS.removeFromWorld(entity);
+ SkinnableEntity npc = entity instanceof SkinnableEntity ? (SkinnableEntity) entity : null;
+ npc.getSkinTracker().onRemoveNPC();
+ }
+ super.remove();
+ }
+
+ private static Pattern NON_ALPHABET_MATCHER = Pattern.compile(".*[^A-Za-z0-9_].*");
+}
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java
new file mode 100644
index 000000000..b9d507396
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/IronGolemController.java
@@ -0,0 +1,206 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftIronGolem;
+import org.bukkit.entity.IronGolem;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityIronGolem;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class IronGolemController extends MobEntityController {
+ public IronGolemController() {
+ super(EntityIronGolemNPC.class);
+ }
+
+ @Override
+ public IronGolem getBukkitEntity() {
+ return (IronGolem) super.getBukkitEntity();
+ }
+
+ public static class EntityIronGolemNPC extends EntityIronGolem implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityIronGolemNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityIronGolemNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new IronGolemNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class IronGolemNPC extends CraftIronGolem implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public IronGolemNPC(EntityIronGolemNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java
new file mode 100644
index 000000000..92ebb45de
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MagmaCubeController.java
@@ -0,0 +1,209 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMagmaCube;
+import org.bukkit.entity.MagmaCube;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerControllerMove;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityMagmaCube;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MagmaCubeController extends MobEntityController {
+ public MagmaCubeController() {
+ super(EntityMagmaCubeNPC.class);
+ }
+
+ @Override
+ public MagmaCube getBukkitEntity() {
+ return (MagmaCube) super.getBukkitEntity();
+ }
+
+ public static class EntityMagmaCubeNPC extends EntityMagmaCube implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMagmaCubeNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMagmaCubeNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ setSize(3);
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ this.moveController = new PlayerControllerMove(this);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new MagmaCubeNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void m() {
+ super.m();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class MagmaCubeNPC extends CraftMagmaCube implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MagmaCubeNPC(EntityMagmaCubeNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java
new file mode 100644
index 000000000..b7e3a8484
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MobEntityController.java
@@ -0,0 +1,61 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import java.lang.reflect.Constructor;
+import java.util.Map;
+
+import org.bukkit.Location;
+import org.bukkit.block.BlockFace;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.entity.Entity;
+
+import com.google.common.collect.Maps;
+
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.npc.AbstractEntityController;
+import net.minecraft.server.v1_10_R1.World;
+
+public abstract class MobEntityController extends AbstractEntityController {
+ private final Constructor> constructor;
+
+ protected MobEntityController(Class> clazz) {
+ super(clazz);
+ this.constructor = getConstructor(clazz);
+ }
+
+ @Override
+ protected Entity createEntity(Location at, NPC npc) {
+ net.minecraft.server.v1_10_R1.Entity entity = createEntityFromClass(((CraftWorld) at.getWorld()).getHandle(),
+ npc);
+ entity.setPositionRotation(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch());
+
+ // entity.onGround isn't updated right away - we approximate here so
+ // that things like pathfinding still work *immediately* after spawn.
+ org.bukkit.Material beneath = at.getBlock().getRelative(BlockFace.DOWN).getType();
+ if (beneath.isBlock()) {
+ entity.onGround = true;
+ }
+ return entity.getBukkitEntity();
+ }
+
+ private net.minecraft.server.v1_10_R1.Entity createEntityFromClass(Object... args) {
+ try {
+ return (net.minecraft.server.v1_10_R1.Entity) constructor.newInstance(args);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ private static Constructor> getConstructor(Class> clazz) {
+ Constructor> constructor = CONSTRUCTOR_CACHE.get(clazz);
+ if (constructor != null)
+ return constructor;
+ try {
+ return clazz.getConstructor(World.class, NPC.class);
+ } catch (Exception ex) {
+ throw new IllegalStateException("unable to find an entity constructor");
+ }
+ }
+
+ private static final Map, Constructor>> CONSTRUCTOR_CACHE = Maps.newHashMap();
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java
new file mode 100644
index 000000000..982429ac7
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/MushroomCowController.java
@@ -0,0 +1,208 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMushroomCow;
+import org.bukkit.entity.MushroomCow;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityMushroomCow;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MushroomCowController extends MobEntityController {
+
+ public MushroomCowController() {
+ super(EntityMushroomCowNPC.class);
+ }
+
+ @Override
+ public MushroomCow getBukkitEntity() {
+ return (MushroomCow) super.getBukkitEntity();
+ }
+
+ public static class EntityMushroomCowNPC extends EntityMushroomCow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMushroomCowNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMushroomCowNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new MushroomCowNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class MushroomCowNPC extends CraftMushroomCow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MushroomCowNPC(EntityMushroomCowNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java
new file mode 100644
index 000000000..2b68d0616
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/OcelotController.java
@@ -0,0 +1,207 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftOcelot;
+import org.bukkit.entity.Ocelot;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityOcelot;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class OcelotController extends MobEntityController {
+ public OcelotController() {
+ super(EntityOcelotNPC.class);
+ }
+
+ @Override
+ public Ocelot getBukkitEntity() {
+ return (Ocelot) super.getBukkitEntity();
+ }
+
+ public static class EntityOcelotNPC extends EntityOcelot implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityOcelotNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityOcelotNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new OcelotNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class OcelotNPC extends CraftOcelot implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public OcelotNPC(EntityOcelotNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java
new file mode 100644
index 000000000..c4be0bf84
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigController.java
@@ -0,0 +1,217 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPig;
+import org.bukkit.entity.Pig;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityLightning;
+import net.minecraft.server.v1_10_R1.EntityPig;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class PigController extends MobEntityController {
+ public PigController() {
+ super(EntityPigNPC.class);
+ }
+
+ @Override
+ public Pig getBukkitEntity() {
+ return (Pig) super.getBukkitEntity();
+ }
+
+ public static class EntityPigNPC extends EntityPig implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityPigNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityPigNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new PigNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void onLightningStrike(EntityLightning entitylightning) {
+ if (npc == null) {
+ super.onLightningStrike(entitylightning);
+ }
+ }
+ }
+
+ public static class PigNPC extends CraftPig implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public PigNPC(EntityPigNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java
new file mode 100644
index 000000000..b785ba228
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PigZombieController.java
@@ -0,0 +1,198 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPigZombie;
+import org.bukkit.entity.PigZombie;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityPigZombie;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class PigZombieController extends MobEntityController {
+
+ public PigZombieController() {
+ super(EntityPigZombieNPC.class);
+ }
+
+ @Override
+ public PigZombie getBukkitEntity() {
+ return (PigZombie) super.getBukkitEntity();
+ }
+
+ public static class EntityPigZombieNPC extends EntityPigZombie implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityPigZombieNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityPigZombieNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.g(x, y, z);
+ }
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new PigZombieNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class PigZombieNPC extends CraftPigZombie implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public PigZombieNPC(EntityPigZombieNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java
new file mode 100644
index 000000000..4a946f035
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/PolarBearController.java
@@ -0,0 +1,177 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPolarBear;
+import org.bukkit.entity.PolarBear;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityPolarBear;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class PolarBearController extends MobEntityController {
+ public PolarBearController() {
+ super(EntityPolarBearNPC.class);
+ }
+
+ @Override
+ public PolarBear getBukkitEntity() {
+ return (PolarBear) super.getBukkitEntity();
+ }
+
+ public static class EntityPolarBearNPC extends EntityPolarBear implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityPolarBearNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityPolarBearNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new PolarBearNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null) {
+ return super.isLeashed();
+ }
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void m() {
+ super.m();
+ if (npc != null) {
+ NMSImpl.updateAI(this);
+ npc.update();
+ }
+ }
+ }
+
+ public static class PolarBearNPC extends CraftPolarBear implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public PolarBearNPC(EntityPolarBearNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java
new file mode 100644
index 000000000..12302a8fe
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/RabbitController.java
@@ -0,0 +1,229 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftRabbit;
+import org.bukkit.entity.Rabbit;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityLiving;
+import net.minecraft.server.v1_10_R1.EntityRabbit;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class RabbitController extends MobEntityController {
+ public RabbitController() {
+ super(EntityRabbitNPC.class);
+ }
+
+ @Override
+ public Rabbit getBukkitEntity() {
+ return (Rabbit) super.getBukkitEntity();
+ }
+
+ public static class EntityRabbitNPC extends EntityRabbit implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityRabbitNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityRabbitNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new RabbitNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public EntityLiving getGoalTarget() {
+ return npc != null ? null : super.getGoalTarget();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ if (npc != null) {
+ super.M();
+ this.be = npc.getNavigator().isNavigating();
+ npc.update();
+ } else {
+ super.M();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setRabbitType(int i) {
+ if (npc != null) {
+ if (NMSImpl.getRabbitTypeField() == null)
+ return;
+ this.datawatcher.set(NMSImpl.getRabbitTypeField(), i);
+ return;
+ }
+ super.setRabbitType(i);
+ }
+ }
+
+ public static class RabbitNPC extends CraftRabbit implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public RabbitNPC(EntityRabbitNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java
new file mode 100644
index 000000000..d5a8f5bba
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SheepController.java
@@ -0,0 +1,207 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSheep;
+import org.bukkit.entity.Sheep;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySheep;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SheepController extends MobEntityController {
+ public SheepController() {
+ super(EntitySheepNPC.class);
+ }
+
+ @Override
+ public Sheep getBukkitEntity() {
+ return (Sheep) super.getBukkitEntity();
+ }
+
+ public static class EntitySheepNPC extends EntitySheep implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySheepNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySheepNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SheepNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class SheepNPC extends CraftSheep implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SheepNPC(EntitySheepNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java
new file mode 100644
index 000000000..a927c5ca2
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ShulkerController.java
@@ -0,0 +1,220 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftShulker;
+import org.bukkit.entity.Shulker;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityAIBodyControl;
+import net.minecraft.server.v1_10_R1.EntityShulker;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ShulkerController extends MobEntityController {
+ public ShulkerController() {
+ super(EntityShulkerNPC.class);
+ }
+
+ @Override
+ public Shulker getBukkitEntity() {
+ return (Shulker) super.getBukkitEntity();
+ }
+
+ public static class EntityShulkerNPC extends EntityShulker implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityShulkerNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityShulkerNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new ShulkerNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void n() {
+ if (npc == null) {
+ super.n();
+ }
+ }
+
+ @Override
+ protected EntityAIBodyControl s() {
+ return new EntityAIBodyControl(this);
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class ShulkerNPC extends CraftShulker implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ShulkerNPC(EntityShulkerNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java
new file mode 100644
index 000000000..5813fba9b
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SilverfishController.java
@@ -0,0 +1,205 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSilverfish;
+import org.bukkit.entity.Silverfish;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySilverfish;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SilverfishController extends MobEntityController {
+ public SilverfishController() {
+ super(EntitySilverfishNPC.class);
+ }
+
+ @Override
+ public Silverfish getBukkitEntity() {
+ return (Silverfish) super.getBukkitEntity();
+ }
+
+ public static class EntitySilverfishNPC extends EntitySilverfish implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySilverfishNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySilverfishNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SilverfishNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class SilverfishNPC extends CraftSilverfish implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SilverfishNPC(EntitySilverfishNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java
new file mode 100644
index 000000000..1de70872d
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SkeletonController.java
@@ -0,0 +1,206 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSkeleton;
+import org.bukkit.entity.Skeleton;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySkeleton;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SkeletonController extends MobEntityController {
+ public SkeletonController() {
+ super(EntitySkeletonNPC.class);
+ }
+
+ @Override
+ public Skeleton getBukkitEntity() {
+ return (Skeleton) super.getBukkitEntity();
+ }
+
+ public static class EntitySkeletonNPC extends EntitySkeleton implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySkeletonNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySkeletonNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SkeletonNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class SkeletonNPC extends CraftSkeleton implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SkeletonNPC(EntitySkeletonNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java
new file mode 100644
index 000000000..b317c7532
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SlimeController.java
@@ -0,0 +1,218 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSlime;
+import org.bukkit.entity.Slime;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.nms.v1_10_R1.util.PlayerControllerMove;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntitySlime;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SlimeController extends MobEntityController {
+ public SlimeController() {
+ super(EntitySlimeNPC.class);
+ }
+
+ @Override
+ public Slime getBukkitEntity() {
+ return (Slime) super.getBukkitEntity();
+ }
+
+ public static class EntitySlimeNPC extends EntitySlime implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySlimeNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySlimeNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ setSize(3);
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ this.moveController = new PlayerControllerMove(this);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void d(EntityHuman human) {
+ if (npc == null) {
+ super.d(human);
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SlimeNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void m() {
+ super.m();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class SlimeNPC extends CraftSlime implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SlimeNPC(EntitySlimeNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java
new file mode 100644
index 000000000..9952e6384
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SnowmanController.java
@@ -0,0 +1,218 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSnowman;
+import org.bukkit.entity.Snowman;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySnowman;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SnowmanController extends MobEntityController {
+ public SnowmanController() {
+ super(EntitySnowmanNPC.class);
+ }
+
+ @Override
+ public Snowman getBukkitEntity() {
+ return (Snowman) super.getBukkitEntity();
+ }
+
+ public static class EntitySnowmanNPC extends EntitySnowman implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySnowmanNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySnowmanNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SnowmanNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void n() {
+ boolean allowsGriefing = this.world.getGameRules().getBoolean("mobGriefing");
+ if (npc != null) {
+ this.world.getGameRules().set("mobGriefing", "false");
+ }
+ super.n();
+ if (npc != null) {
+ this.world.getGameRules().set("mobGriefing", Boolean.toString(allowsGriefing));
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class SnowmanNPC extends CraftSnowman implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SnowmanNPC(EntitySnowmanNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java
new file mode 100644
index 000000000..141b6cc67
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SpiderController.java
@@ -0,0 +1,206 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSpider;
+import org.bukkit.entity.Spider;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySpider;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SpiderController extends MobEntityController {
+ public SpiderController() {
+ super(EntitySpiderNPC.class);
+ }
+
+ @Override
+ public Spider getBukkitEntity() {
+ return (Spider) super.getBukkitEntity();
+ }
+
+ public static class EntitySpiderNPC extends EntitySpider implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySpiderNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySpiderNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SpiderNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+
+ }
+
+ public static class SpiderNPC extends CraftSpider implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SpiderNPC(EntitySpiderNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java
new file mode 100644
index 000000000..7b5a11a94
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/SquidController.java
@@ -0,0 +1,198 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSquid;
+import org.bukkit.entity.Squid;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntitySquid;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SquidController extends MobEntityController {
+ public SquidController() {
+ super(EntitySquidNPC.class);
+ }
+
+ @Override
+ public Squid getBukkitEntity() {
+ return (Squid) super.getBukkitEntity();
+ }
+
+ public static class EntitySquidNPC extends EntitySquid implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySquidNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySquidNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new SquidNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class SquidNPC extends CraftSquid implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SquidNPC(EntitySquidNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java
new file mode 100644
index 000000000..e8b6c6351
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/VillagerController.java
@@ -0,0 +1,228 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftVillager;
+import org.bukkit.entity.Villager;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.NMS;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntityVillager;
+import net.minecraft.server.v1_10_R1.EnumHand;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.ItemStack;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class VillagerController extends MobEntityController {
+ public VillagerController() {
+ super(EntityVillagerNPC.class);
+ }
+
+ @Override
+ public Villager getBukkitEntity() {
+ return (Villager) super.getBukkitEntity();
+ }
+
+ public static class EntityVillagerNPC extends EntityVillager implements NPCHolder {
+ private boolean blockTrades = true;
+ private final CitizensNPC npc;
+
+ public EntityVillagerNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityVillagerNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ public boolean a(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) {
+ return npc == null || !blockTrades ? super.a(entityhuman) : false; // block trades
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new VillagerNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ public boolean isBlockingTrades() {
+ return blockTrades;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ NMS.setHeadYaw(getBukkitEntity(), yaw);
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ public void setBlockTrades(boolean blocked) {
+ this.blockTrades = blocked;
+ }
+ }
+
+ public static class VillagerNPC extends CraftVillager implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public VillagerNPC(EntityVillagerNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java
new file mode 100644
index 000000000..87890f57c
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitchController.java
@@ -0,0 +1,205 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWitch;
+import org.bukkit.entity.Witch;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityWitch;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class WitchController extends MobEntityController {
+ public WitchController() {
+ super(EntityWitchNPC.class);
+ }
+
+ @Override
+ public Witch getBukkitEntity() {
+ return (Witch) super.getBukkitEntity();
+ }
+
+ public static class EntityWitchNPC extends EntityWitch implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityWitchNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityWitchNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new WitchNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null)
+ npc.update();
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+
+ public static class WitchNPC extends CraftWitch implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public WitchNPC(EntityWitchNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java
new file mode 100644
index 000000000..29647b1dd
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WitherController.java
@@ -0,0 +1,168 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWither;
+import org.bukkit.entity.Wither;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityWither;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class WitherController extends MobEntityController {
+ public WitherController() {
+ super(EntityWitherNPC.class);
+ }
+
+ @Override
+ public Wither getBukkitEntity() {
+ return (Wither) super.getBukkitEntity();
+ }
+
+ public static class EntityWitherNPC extends EntityWither implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityWitherNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityWitherNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new WitherNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public int m(int i) {
+ return npc == null ? super.m(i) : 0;
+ }
+
+ @Override
+ protected void M() {
+ if (npc == null) {
+ super.M();
+ }
+ npc.update();
+ }
+ }
+
+ public static class WitherNPC extends CraftWither implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public WitherNPC(EntityWitherNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java
new file mode 100644
index 000000000..86da48d90
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/WolfController.java
@@ -0,0 +1,222 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWolf;
+import org.bukkit.entity.Wolf;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityLiving;
+import net.minecraft.server.v1_10_R1.EntityWolf;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class WolfController extends MobEntityController {
+ public WolfController() {
+ super(EntityWolfNPC.class);
+ }
+
+ @Override
+ public Wolf getBukkitEntity() {
+ return (Wolf) super.getBukkitEntity();
+ }
+
+ public static class EntityWolfNPC extends EntityWolf implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityWolfNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityWolfNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ public void a(boolean flag) {
+ float oldw = width;
+ float oldl = length;
+ super.a(flag);
+ if (oldw != width || oldl != length) {
+ this.setPosition(locX - 0.01, locY, locZ - 0.01);
+ this.setPosition(locX + 0.01, locY, locZ + 0.01);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new WolfNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setGoalTarget(EntityLiving entityliving, EntityTargetEvent.TargetReason reason, boolean fire) {
+ return npc == null ? super.setGoalTarget(killer, reason, fire) : false;
+ }
+ }
+
+ public static class WolfNPC extends CraftWolf implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public WolfNPC(EntityWolfNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void setSitting(boolean sitting) {
+ getHandle().setSitting(sitting);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java
new file mode 100644
index 000000000..8c28a4a34
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/ZombieController.java
@@ -0,0 +1,197 @@
+package net.citizensnpcs.nms.v1_10_R1.entity;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftZombie;
+import org.bukkit.entity.Zombie;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCEnderTeleportEvent;
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityZombie;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ZombieController extends MobEntityController {
+ public ZombieController() {
+ super(EntityZombieNPC.class);
+ }
+
+ @Override
+ public Zombie getBukkitEntity() {
+ return (Zombie) super.getBukkitEntity();
+ }
+
+ public static class EntityZombieNPC extends EntityZombie implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityZombieNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityZombieNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ if (npc != null) {
+ NMSImpl.clearGoals(goalSelector, targetSelector);
+ }
+ }
+
+ @Override
+ protected void a(double d0, boolean flag, IBlockData block, BlockPosition blockposition) {
+ if (npc == null || !npc.isFlyable()) {
+ super.a(d0, flag, block, blockposition);
+ }
+ }
+
+ @Override
+ protected SoundEffect bV() {
+ return NMSImpl.getSoundEffect(npc, super.bV(), NPC.DEATH_SOUND_METADATA);
+ }
+
+ @Override
+ protected SoundEffect bW() {
+ return NMSImpl.getSoundEffect(npc, super.bW(), NPC.HURT_SOUND_METADATA);
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null)
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void e(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.e(f, f1);
+ }
+ }
+
+ @Override
+ public void enderTeleportTo(double d0, double d1, double d2) {
+ if (npc == null)
+ super.enderTeleportTo(d0, d1, d2);
+ NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ super.enderTeleportTo(d0, d1, d2);
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public void g(float f, float f1) {
+ if (npc == null || !npc.isFlyable()) {
+ super.g(f, f1);
+ } else {
+ NMSImpl.flyingMoveLogic(this, f, f1);
+ }
+ }
+
+ @Override
+ protected SoundEffect G() {
+ return NMSImpl.getSoundEffect(npc, super.G(), NPC.AMBIENT_SOUND_METADATA);
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null)
+ bukkitEntity = new ZombieNPC(this);
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean isLeashed() {
+ if (npc == null)
+ return super.isLeashed();
+ boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true);
+ if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault))
+ return super.isLeashed();
+ if (super.isLeashed()) {
+ unleash(true, false); // clearLeash with client update
+ }
+ return false; // shouldLeash
+ }
+
+ @Override
+ protected void L() {
+ if (npc == null) {
+ super.L();
+ }
+ }
+
+ @Override
+ public void M() {
+ super.M();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public boolean m_() {
+ if (npc == null || !npc.isFlyable()) {
+ return super.m_();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static class ZombieNPC extends CraftZombie implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ZombieNPC(EntityZombieNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java
new file mode 100644
index 000000000..fb8962388
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/AreaEffectCloudController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftAreaEffectCloud;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.AreaEffectCloud;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityAreaEffectCloud;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class AreaEffectCloudController extends MobEntityController {
+ public AreaEffectCloudController() {
+ super(EntityAreaEffectCloudNPC.class);
+ }
+
+ @Override
+ public AreaEffectCloud getBukkitEntity() {
+ return (AreaEffectCloud) super.getBukkitEntity();
+ }
+
+ public static class AreaEffectCloudNPC extends CraftAreaEffectCloud implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public AreaEffectCloudNPC(EntityAreaEffectCloudNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityAreaEffectCloudNPC extends EntityAreaEffectCloud implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityAreaEffectCloudNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityAreaEffectCloudNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new AreaEffectCloudNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java
new file mode 100644
index 000000000..68858b50d
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ArmorStandController.java
@@ -0,0 +1,142 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftArmorStand;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityArmorStand;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EnumHand;
+import net.minecraft.server.v1_10_R1.EnumInteractionResult;
+import net.minecraft.server.v1_10_R1.ItemStack;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.Vec3D;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ArmorStandController extends MobEntityController {
+ public ArmorStandController() {
+ super(EntityArmorStandNPC.class);
+ }
+
+ @Override
+ public ArmorStand getBukkitEntity() {
+ return (ArmorStand) super.getBukkitEntity();
+ }
+
+ public static class ArmorStandNPC extends CraftArmorStand implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ArmorStandNPC(EntityArmorStandNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityArmorStandNPC extends EntityArmorStand implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityArmorStandNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityArmorStandNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public EnumInteractionResult a(EntityHuman entityhuman, Vec3D vec3d, ItemStack itemstack, EnumHand enumhand) {
+ if (npc == null) {
+ return super.a(entityhuman, vec3d, itemstack, enumhand);
+ }
+ PlayerInteractEntityEvent event = new PlayerInteractEntityEvent((Player) entityhuman.getBukkitEntity(),
+ getBukkitEntity());
+ Bukkit.getPluginManager().callEvent(event);
+ return event.isCancelled() ? EnumInteractionResult.FAIL : EnumInteractionResult.SUCCESS;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ArmorStandNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ super.m();
+ if (npc != null) {
+ npc.update();
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java
new file mode 100644
index 000000000..ded276917
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/BoatController.java
@@ -0,0 +1,125 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftBoat;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Boat;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityBoat;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class BoatController extends MobEntityController {
+ public BoatController() {
+ super(EntityBoatNPC.class);
+ }
+
+ @Override
+ public Boat getBukkitEntity() {
+ return (Boat) super.getBukkitEntity();
+ }
+
+ public static class BoatNPC extends CraftBoat implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public BoatNPC(EntityBoatNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityBoatNPC extends EntityBoat implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityBoatNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityBoatNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new BoatNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java
new file mode 100644
index 000000000..f7b5c1087
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/DragonFireballController.java
@@ -0,0 +1,128 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftDragonFireball;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.DragonFireball;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityDragonFireball;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class DragonFireballController extends MobEntityController {
+ public DragonFireballController() {
+ super(EntityDragonFireballNPC.class);
+ }
+
+ @Override
+ public DragonFireball getBukkitEntity() {
+ return (DragonFireball) super.getBukkitEntity();
+ }
+
+ public static class DragonFireballNPC extends CraftDragonFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public DragonFireballNPC(EntityDragonFireballNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityDragonFireballNPC extends EntityDragonFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityDragonFireballNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityDragonFireballNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new DragonFireballNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java
new file mode 100644
index 000000000..7a4b0b439
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EggController.java
@@ -0,0 +1,134 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.npc.AbstractEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityEgg;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEgg;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Egg;
+import org.bukkit.entity.Entity;
+import org.bukkit.util.Vector;
+
+public class EggController extends AbstractEntityController {
+ public EggController() {
+ super(EntityEggNPC.class);
+ }
+
+ @Override
+ protected Entity createEntity(Location at, NPC npc) {
+ WorldServer ws = ((CraftWorld) at.getWorld()).getHandle();
+ final EntityEggNPC handle = new EntityEggNPC(ws, npc, at.getX(), at.getY(), at.getZ());
+ return handle.getBukkitEntity();
+ }
+
+ @Override
+ public Egg getBukkitEntity() {
+ return (Egg) super.getBukkitEntity();
+ }
+
+ public static class EggNPC extends CraftEgg implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EggNPC(EntityEggNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEggNPC extends EntityEgg implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEggNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityEggNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntityEggNPC(World world, NPC npc, double d0, double d1, double d2) {
+ super(world, d0, d1, d2);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new EggNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java
new file mode 100644
index 000000000..816cd9925
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderCrystalController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityEnderCrystal;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEnderCrystal;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.EnderCrystal;
+import org.bukkit.util.Vector;
+
+public class EnderCrystalController extends MobEntityController {
+ public EnderCrystalController() {
+ super(EntityEnderCrystalNPC.class);
+ }
+
+ @Override
+ public EnderCrystal getBukkitEntity() {
+ return (EnderCrystal) super.getBukkitEntity();
+ }
+
+ public static class EnderCrystalNPC extends CraftEnderCrystal implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EnderCrystalNPC(EntityEnderCrystalNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEnderCrystalNPC extends EntityEnderCrystal implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEnderCrystalNPC(World world) {
+ this(world, null);
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntityEnderCrystalNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new EnderCrystalNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java
new file mode 100644
index 000000000..2d44f1430
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderPearlController.java
@@ -0,0 +1,118 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEnderPearl;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.EnderPearl;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityEnderPearl;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class EnderPearlController extends MobEntityController {
+ public EnderPearlController() {
+ super(EntityEnderPearlNPC.class);
+ }
+
+ @Override
+ public EnderPearl getBukkitEntity() {
+ return (EnderPearl) super.getBukkitEntity();
+ }
+
+ public static class EnderPearlNPC extends CraftEnderPearl implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EnderPearlNPC(EntityEnderPearlNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEnderPearlNPC extends EntityEnderPearl implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEnderPearlNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityEnderPearlNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new EnderPearlNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java
new file mode 100644
index 000000000..b496a33b6
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/EnderSignalController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityEnderSignal;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEnderSignal;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.EnderSignal;
+import org.bukkit.util.Vector;
+
+public class EnderSignalController extends MobEntityController {
+ public EnderSignalController() {
+ super(EntityEnderSignalNPC.class);
+ }
+
+ @Override
+ public EnderSignal getBukkitEntity() {
+ return (EnderSignal) super.getBukkitEntity();
+ }
+
+ public static class EnderSignalNPC extends CraftEnderSignal implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EnderSignalNPC(EntityEnderSignalNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntityEnderSignalNPC extends EntityEnderSignal implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityEnderSignalNPC(World world) {
+ this(world, null);
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntityEnderSignalNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new EnderSignalNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java
new file mode 100644
index 000000000..977c968b8
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ExperienceOrbController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityExperienceOrb;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftExperienceOrb;
+import org.bukkit.entity.ExperienceOrb;
+import org.bukkit.util.Vector;
+
+public class ExperienceOrbController extends MobEntityController {
+ public ExperienceOrbController() {
+ super(EntityExperienceOrbNPC.class);
+ }
+
+ @Override
+ public ExperienceOrb getBukkitEntity() {
+ return (ExperienceOrb) super.getBukkitEntity();
+ }
+
+ public static class EntityExperienceOrbNPC extends EntityExperienceOrb implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityExperienceOrbNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityExperienceOrbNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ExperienceOrbNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class ExperienceOrbNPC extends CraftExperienceOrb implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ExperienceOrbNPC(EntityExperienceOrbNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java
new file mode 100644
index 000000000..9dbe3db9c
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FallingBlockController.java
@@ -0,0 +1,170 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftFallingSand;
+import org.bukkit.craftbukkit.v1_10_R1.util.CraftMagicNumbers;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.FallingBlock;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.AbstractEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.Block;
+import net.minecraft.server.v1_10_R1.Blocks;
+import net.minecraft.server.v1_10_R1.EntityFallingBlock;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+public class FallingBlockController extends AbstractEntityController {
+ public FallingBlockController() {
+ super(EntityFallingBlockNPC.class);
+ }
+
+ @Override
+ protected Entity createEntity(Location at, NPC npc) {
+ WorldServer ws = ((CraftWorld) at.getWorld()).getHandle();
+ Block id = Blocks.STONE;
+ int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0));
+ if (npc.data().has("falling-block-id") || npc.data().has(NPC.ITEM_ID_METADATA)) {
+ id = CraftMagicNumbers.getBlock(Material.getMaterial(
+ npc.data(). get(NPC.ITEM_ID_METADATA, npc.data(). get("falling-block-id"))));
+ }
+ final EntityFallingBlockNPC handle = new EntityFallingBlockNPC(ws, npc, at.getX(), at.getY(), at.getZ(),
+ id.fromLegacyData(data));
+ return handle.getBukkitEntity();
+ }
+
+ @Override
+ public FallingBlock getBukkitEntity() {
+ return (FallingBlock) super.getBukkitEntity();
+ }
+
+ public static class EntityFallingBlockNPC extends EntityFallingBlock implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityFallingBlockNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityFallingBlockNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ public EntityFallingBlockNPC(World world, NPC npc, double d0, double d1, double d2, IBlockData data) {
+ super(world, d0, d1, d2, data);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new FallingBlockNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (Math.abs(motX) > EPSILON || Math.abs(motY) > EPSILON || Math.abs(motZ) > EPSILON) {
+ motX *= 0.98;
+ motY *= 0.98;
+ motZ *= 0.98;
+ move(motX, motY, motZ);
+ }
+ } else {
+ super.m();
+ }
+ }
+
+ private static final double EPSILON = 0.001;
+ }
+
+ public static class FallingBlockNPC extends CraftFallingSand implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public FallingBlockNPC(EntityFallingBlockNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ public void setType(Material material, int data) {
+ npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name());
+ npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data);
+ if (npc.isSpawned()) {
+ npc.despawn();
+ npc.spawn(npc.getStoredLocation());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java
new file mode 100644
index 000000000..a2156391a
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FireworkController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityFireworks;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftFirework;
+import org.bukkit.entity.Firework;
+import org.bukkit.util.Vector;
+
+public class FireworkController extends MobEntityController {
+ public FireworkController() {
+ super(EntityFireworkNPC.class);
+ }
+
+ @Override
+ public Firework getBukkitEntity() {
+ return (Firework) super.getBukkitEntity();
+ }
+
+ public static class EntityFireworkNPC extends EntityFireworks implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityFireworkNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityFireworkNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new FireworkNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class FireworkNPC extends CraftFirework implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public FireworkNPC(EntityFireworkNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java
new file mode 100644
index 000000000..f46775a3f
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/FishingHookController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftFish;
+import org.bukkit.entity.FishHook;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityFishingHook;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class FishingHookController extends MobEntityController {
+ public FishingHookController() {
+ super(EntityFishingHookNPC.class);
+ }
+
+ @Override
+ public FishHook getBukkitEntity() {
+ return (FishHook) super.getBukkitEntity();
+ }
+
+ public static class EntityFishingHookNPC extends EntityFishingHook implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityFishingHookNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityFishingHookNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new FishingHookNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class FishingHookNPC extends CraftFish implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public FishingHookNPC(EntityFishingHookNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java
new file mode 100644
index 000000000..ae37c9a6e
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemController.java
@@ -0,0 +1,153 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.npc.AbstractEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntityItem;
+import net.minecraft.server.v1_10_R1.ItemStack;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftItem;
+import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Item;
+import org.bukkit.util.Vector;
+
+public class ItemController extends AbstractEntityController {
+ public ItemController() {
+ super(EntityItemNPC.class);
+ }
+
+ @Override
+ protected Entity createEntity(Location at, NPC npc) {
+ WorldServer ws = ((CraftWorld) at.getWorld()).getHandle();
+ Material id = Material.STONE;
+ int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0));
+ if (npc.data().has(NPC.ITEM_ID_METADATA)) {
+ id = Material.getMaterial(npc.data(). get(NPC.ITEM_ID_METADATA));
+ }
+ final EntityItemNPC handle = new EntityItemNPC(ws, npc, at.getX(), at.getY(), at.getZ(),
+ CraftItemStack.asNMSCopy(new org.bukkit.inventory.ItemStack(id, 1, (short) data)));
+ return handle.getBukkitEntity();
+ }
+
+ @Override
+ public Item getBukkitEntity() {
+ return (Item) super.getBukkitEntity();
+ }
+
+ public static class EntityItemNPC extends EntityItem implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityItemNPC(World world) {
+ super(world);
+ this.npc = null;
+ }
+
+ public EntityItemNPC(World world, NPC npc, double x, double y, double z, ItemStack stack) {
+ super(world, x, y, z, stack);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void d(EntityHuman entityhuman) {
+ if (npc == null) {
+ super.d(entityhuman);
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ItemNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class ItemNPC extends CraftItem implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ItemNPC(EntityItemNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ public void setType(Material material, int data) {
+ npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name());
+ npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data);
+ if (npc.isSpawned()) {
+ npc.despawn();
+ npc.spawn(npc.getStoredLocation());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java
new file mode 100644
index 000000000..3f3b9fd52
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ItemFrameController.java
@@ -0,0 +1,150 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftItemFrame;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.ItemFrame;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.EntityItemFrame;
+import net.minecraft.server.v1_10_R1.EnumDirection;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ItemFrameController extends MobEntityController {
+ public ItemFrameController() {
+ super(EntityItemFrameNPC.class);
+ }
+
+ @Override
+ protected Entity createEntity(Location at, NPC npc) {
+ Entity e = super.createEntity(at, npc);
+ EntityItemFrame item = (EntityItemFrame) ((CraftEntity) e).getHandle();
+ item.setDirection(EnumDirection.EAST);
+ item.blockPosition = new BlockPosition(at.getX(), at.getY(), at.getZ());
+ return e;
+ }
+
+ @Override
+ public ItemFrame getBukkitEntity() {
+ return (ItemFrame) super.getBukkitEntity();
+ }
+
+ public static class EntityItemFrameNPC extends EntityItemFrame implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityItemFrameNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityItemFrameNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ItemFrameNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public boolean survives() {
+ return npc == null || !npc.isProtected() ? super.survives() : true;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class ItemFrameNPC extends CraftItemFrame implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ItemFrameNPC(EntityItemFrameNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ Material id = Material.STONE;
+ int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0));
+ if (npc.data().has(NPC.ITEM_ID_METADATA)) {
+ id = Material.getMaterial(npc.data(). get(NPC.ITEM_ID_METADATA));
+ }
+ getItem().setType(id);
+ getItem().setDurability((short) data);
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ public void setType(Material material, int data) {
+ npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name());
+ npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data);
+ if (npc.isSpawned()) {
+ npc.despawn();
+ npc.spawn(npc.getStoredLocation());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java
new file mode 100644
index 000000000..4d68b32b8
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LargeFireballController.java
@@ -0,0 +1,128 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLargeFireball;
+import org.bukkit.entity.LargeFireball;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityLargeFireball;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class LargeFireballController extends MobEntityController {
+ public LargeFireballController() {
+ super(EntityLargeFireballNPC.class);
+ }
+
+ @Override
+ public LargeFireball getBukkitEntity() {
+ return (LargeFireball) super.getBukkitEntity();
+ }
+
+ public static class EntityLargeFireballNPC extends EntityLargeFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityLargeFireballNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityLargeFireballNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new LargeFireballNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void setSize(float f, float f1) {
+ if (npc == null) {
+ super.setSize(f, f1);
+ } else {
+ NMSImpl.setSize(this, f, f1, justCreated);
+ }
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class LargeFireballNPC extends CraftLargeFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public LargeFireballNPC(EntityLargeFireballNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java
new file mode 100644
index 000000000..cfedbe134
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/LeashController.java
@@ -0,0 +1,120 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityLeash;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLeash;
+import org.bukkit.entity.LeashHitch;
+import org.bukkit.util.Vector;
+
+public class LeashController extends MobEntityController {
+ public LeashController() {
+ super(EntityLeashNPC.class);
+ }
+
+ @Override
+ public LeashHitch getBukkitEntity() {
+ return (LeashHitch) super.getBukkitEntity();
+ }
+
+ public static class EntityLeashNPC extends EntityLeash implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityLeashNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityLeashNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new LeashNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+
+ @Override
+ public boolean survives() {
+ return npc == null || !npc.isProtected() ? super.survives() : true;
+ }
+ }
+
+ public static class LeashNPC extends CraftLeash implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public LeashNPC(EntityLeashNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java
new file mode 100644
index 000000000..0d3a37df7
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartChestController.java
@@ -0,0 +1,125 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMinecartChest;
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartChest;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartChestController extends MobEntityController {
+ public MinecartChestController() {
+ super(EntityMinecartChestNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartChestNPC extends EntityMinecartChest implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartChestNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartChestNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new MinecartChestNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class MinecartChestNPC extends CraftMinecartChest implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MinecartChestNPC(EntityMinecartChestNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java
new file mode 100644
index 000000000..445e6340e
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartCommandController.java
@@ -0,0 +1,125 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMinecartCommand;
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartCommandBlock;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartCommandController extends MobEntityController {
+ public MinecartCommandController() {
+ super(EntityMinecartCommandNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartCommandNPC extends EntityMinecartCommandBlock implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartCommandNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartCommandNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new MinecartCommandNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class MinecartCommandNPC extends CraftMinecartCommand implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MinecartCommandNPC(EntityMinecartCommandNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java
new file mode 100644
index 000000000..56284d3a8
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartFurnaceController.java
@@ -0,0 +1,125 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMinecartFurnace;
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartFurnace;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartFurnaceController extends MobEntityController {
+ public MinecartFurnaceController() {
+ super(EntityMinecartFurnaceNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartFurnaceNPC extends EntityMinecartFurnace implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartFurnaceNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartFurnaceNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new MinecartFurnaceNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class MinecartFurnaceNPC extends CraftMinecartFurnace implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MinecartFurnaceNPC(EntityMinecartFurnaceNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java
new file mode 100644
index 000000000..4578b8268
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartHopperController.java
@@ -0,0 +1,99 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartHopper;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartHopperController extends MobEntityController {
+ public MinecartHopperController() {
+ super(EntityMinecartHopperNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartHopperNPC extends EntityMinecartHopper implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartHopperNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartHopperNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java
new file mode 100644
index 000000000..c2e3c6c16
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartRideableController.java
@@ -0,0 +1,125 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftMinecartRideable;
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartRideable;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartRideableController extends MobEntityController {
+ public MinecartRideableController() {
+ super(EntityMinecartRideableNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartRideableNPC extends EntityMinecartRideable implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartRideableNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartRideableNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new MinecartRideableNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class MinecartRideableNPC extends CraftMinecartRideable implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public MinecartRideableNPC(EntityMinecartRideableNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java
new file mode 100644
index 000000000..82d60d921
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartSpawnerController.java
@@ -0,0 +1,99 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartMobSpawner;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartSpawnerController extends MobEntityController {
+ public MinecartSpawnerController() {
+ super(EntityMinecartSpawnerNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartSpawnerNPC extends EntityMinecartMobSpawner implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartSpawnerNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartSpawnerNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java
new file mode 100644
index 000000000..9a1a80720
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/MinecartTNTController.java
@@ -0,0 +1,99 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.entity.Minecart;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.EntityMinecartTNT;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class MinecartTNTController extends MobEntityController {
+ public MinecartTNTController() {
+ super(EntityMinecartTNTNPC.class);
+ }
+
+ @Override
+ public Minecart getBukkitEntity() {
+ return (Minecart) super.getBukkitEntity();
+ }
+
+ public static class EntityMinecartTNTNPC extends EntityMinecartTNT implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityMinecartTNTNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityMinecartTNTNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public boolean damageEntity(DamageSource damagesource, float f) {
+ if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ return super.damageEntity(damagesource, f);
+ return false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ NMSImpl.minecartItemLogic(this);
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java
new file mode 100644
index 000000000..2ecf66082
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/PaintingController.java
@@ -0,0 +1,120 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityPainting;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPainting;
+import org.bukkit.entity.Painting;
+import org.bukkit.util.Vector;
+
+public class PaintingController extends MobEntityController {
+ public PaintingController() {
+ super(EntityPaintingNPC.class);
+ }
+
+ @Override
+ public Painting getBukkitEntity() {
+ return (Painting) super.getBukkitEntity();
+ }
+
+ public static class EntityPaintingNPC extends EntityPainting implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityPaintingNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityPaintingNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new PaintingNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+
+ @Override
+ public boolean survives() {
+ return npc == null || !npc.isProtected() ? super.survives() : true;
+ }
+ }
+
+ public static class PaintingNPC extends CraftPainting implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public PaintingNPC(EntityPaintingNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java
new file mode 100644
index 000000000..469937d67
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ShulkerBulletController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftShulkerBullet;
+import org.bukkit.entity.ShulkerBullet;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityShulkerBullet;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ShulkerBulletController extends MobEntityController {
+ public ShulkerBulletController() {
+ super(EntityShulkerBulletNPC.class);
+ }
+
+ @Override
+ public ShulkerBullet getBukkitEntity() {
+ return (ShulkerBullet) super.getBukkitEntity();
+ }
+
+ public static class EntityShulkerBulletNPC extends EntityShulkerBullet implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityShulkerBulletNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityShulkerBulletNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ShulkerBulletNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class ShulkerBulletNPC extends CraftShulkerBullet implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ShulkerBulletNPC(EntityShulkerBulletNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java
new file mode 100644
index 000000000..639aa91b6
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SmallFireballController.java
@@ -0,0 +1,118 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSmallFireball;
+import org.bukkit.entity.SmallFireball;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntitySmallFireball;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SmallFireballController extends MobEntityController {
+ public SmallFireballController() {
+ super(EntitySmallFireballNPC.class);
+ }
+
+ @Override
+ public SmallFireball getBukkitEntity() {
+ return (SmallFireball) super.getBukkitEntity();
+ }
+
+ public static class EntitySmallFireballNPC extends EntitySmallFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySmallFireballNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySmallFireballNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new SmallFireballNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class SmallFireballNPC extends CraftSmallFireball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SmallFireballNPC(EntitySmallFireballNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java
new file mode 100644
index 000000000..308dc6fa9
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SnowballController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntitySnowball;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftSnowball;
+import org.bukkit.entity.Snowball;
+import org.bukkit.util.Vector;
+
+public class SnowballController extends MobEntityController {
+ public SnowballController() {
+ super(EntitySnowballNPC.class);
+ }
+
+ @Override
+ public Snowball getBukkitEntity() {
+ return (Snowball) super.getBukkitEntity();
+ }
+
+ public static class SnowballNPC extends CraftSnowball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SnowballNPC(EntitySnowballNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class EntitySnowballNPC extends EntitySnowball implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySnowballNPC(World world) {
+ this(world, null);
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntitySnowballNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new SnowballNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java
new file mode 100644
index 000000000..01d8bcba4
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/SpectralArrowController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftArrow;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Arrow;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntitySpectralArrow;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class SpectralArrowController extends MobEntityController {
+ public SpectralArrowController() {
+ super(EntitySpectralArrowNPC.class);
+ }
+
+ @Override
+ public Arrow getBukkitEntity() {
+ return (Arrow) super.getBukkitEntity();
+ }
+
+ public static class EntitySpectralArrowNPC extends EntitySpectralArrow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntitySpectralArrowNPC(World world) {
+ this(world, null);
+ }
+
+ public EntitySpectralArrowNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new SpectralArrowNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class SpectralArrowNPC extends CraftArrow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SpectralArrowNPC(EntitySpectralArrowNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java
new file mode 100644
index 000000000..5a9184c1a
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TNTPrimedController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityTNTPrimed;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftTNTPrimed;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.util.Vector;
+
+public class TNTPrimedController extends MobEntityController {
+ public TNTPrimedController() {
+ super(EntityTNTPrimedNPC.class);
+ }
+
+ @Override
+ public TNTPrimed getBukkitEntity() {
+ return (TNTPrimed) super.getBukkitEntity();
+ }
+
+ public static class EntityTNTPrimedNPC extends EntityTNTPrimed implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityTNTPrimedNPC(World world) {
+ this(world, null);
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntityTNTPrimedNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new TNTPrimedNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class TNTPrimedNPC extends CraftTNTPrimed implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public TNTPrimedNPC(EntityTNTPrimedNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java
new file mode 100644
index 000000000..ad31c4359
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownExpBottleController.java
@@ -0,0 +1,118 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftThrownExpBottle;
+import org.bukkit.entity.ThrownExpBottle;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityThrownExpBottle;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ThrownExpBottleController extends MobEntityController {
+ public ThrownExpBottleController() {
+ super(EntityThrownExpBottleNPC.class);
+ }
+
+ @Override
+ public ThrownExpBottle getBukkitEntity() {
+ return (ThrownExpBottle) super.getBukkitEntity();
+ }
+
+ public static class EntityThrownExpBottleNPC extends EntityThrownExpBottle implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityThrownExpBottleNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityThrownExpBottleNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new ThrownExpBottleNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) {
+ super.m();
+ }
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class ThrownExpBottleNPC extends CraftThrownExpBottle implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public ThrownExpBottleNPC(EntityThrownExpBottleNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java
new file mode 100644
index 000000000..0e329971f
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/ThrownPotionController.java
@@ -0,0 +1,134 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLingeringPotion;
+import org.bukkit.entity.ThrownPotion;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityPotion;
+import net.minecraft.server.v1_10_R1.Items;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class ThrownPotionController extends MobEntityController {
+ public ThrownPotionController() {
+ super(EntityThrownPotionNPC.class);
+ }
+
+ @Override
+ public ThrownPotion getBukkitEntity() {
+ return (ThrownPotion) super.getBukkitEntity();
+ }
+
+ public static class EntityThrownPotionNPC extends EntityPotion implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityThrownPotionNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityThrownPotionNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ if (getItem() != null && getItem().getItem().equals(Items.LINGERING_POTION)) {
+ bukkitEntity = new LingeringThrownPotionNPC(this);
+ } else {
+ bukkitEntity = new SplashThrownPotionNPC(this);
+ }
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class LingeringThrownPotionNPC extends CraftLingeringPotion implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public LingeringThrownPotionNPC(EntityThrownPotionNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+
+ public static class SplashThrownPotionNPC extends CraftLingeringPotion implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public SplashThrownPotionNPC(EntityThrownPotionNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java
new file mode 100644
index 000000000..2c81ed49e
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/TippedArrowController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftArrow;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.entity.Arrow;
+import org.bukkit.util.Vector;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityTippedArrow;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+public class TippedArrowController extends MobEntityController {
+ public TippedArrowController() {
+ super(EntityTippedArrowNPC.class);
+ }
+
+ @Override
+ public Arrow getBukkitEntity() {
+ return (Arrow) super.getBukkitEntity();
+ }
+
+ public static class EntityTippedArrowNPC extends EntityTippedArrow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityTippedArrowNPC(World world) {
+ this(world, null);
+ }
+
+ public EntityTippedArrowNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new TippedArrowNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class TippedArrowNPC extends CraftArrow implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public TippedArrowNPC(EntityTippedArrowNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java
new file mode 100644
index 000000000..8702abf84
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/entity/nonliving/WitherSkullController.java
@@ -0,0 +1,115 @@
+package net.citizensnpcs.nms.v1_10_R1.entity.nonliving;
+
+import net.citizensnpcs.api.event.NPCPushEvent;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.MobEntityController;
+import net.citizensnpcs.npc.CitizensNPC;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.EntityWitherSkull;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.World;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWitherSkull;
+import org.bukkit.entity.WitherSkull;
+import org.bukkit.util.Vector;
+
+public class WitherSkullController extends MobEntityController {
+ public WitherSkullController() {
+ super(EntityWitherSkullNPC.class);
+ }
+
+ @Override
+ public WitherSkull getBukkitEntity() {
+ return (WitherSkull) super.getBukkitEntity();
+ }
+
+ public static class EntityWitherSkullNPC extends EntityWitherSkull implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public EntityWitherSkullNPC(World world) {
+ this(world, null);
+ }
+
+ @Override
+ public boolean d(NBTTagCompound save) {
+ return npc == null ? super.d(save) : false;
+ }
+
+ public EntityWitherSkullNPC(World world, NPC npc) {
+ super(world);
+ this.npc = (CitizensNPC) npc;
+ }
+
+ @Override
+ public void collide(net.minecraft.server.v1_10_R1.Entity entity) {
+ // this method is called by both the entities involved - cancelling
+ // it will not stop the NPC from moving.
+ super.collide(entity);
+ if (npc != null) {
+ Util.callCollisionEvent(npc, entity.getBukkitEntity());
+ }
+ }
+
+ @Override
+ public void g(double x, double y, double z) {
+ if (npc == null) {
+ super.g(x, y, z);
+ return;
+ }
+ if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
+ super.g(x, y, z);
+ return;
+ }
+ Vector vector = new Vector(x, y, z);
+ NPCPushEvent event = Util.callPushEvent(npc, vector);
+ if (!event.isCancelled()) {
+ vector = event.getCollisionVector();
+ super.g(vector.getX(), vector.getY(), vector.getZ());
+ }
+ // when another entity collides, this method is called to push the
+ // NPC so we prevent it from doing anything if the event is
+ // cancelled.
+ }
+
+ @Override
+ public CraftEntity getBukkitEntity() {
+ if (bukkitEntity == null && npc != null) {
+ bukkitEntity = new WitherSkullNPC(this);
+ }
+ return super.getBukkitEntity();
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+
+ @Override
+ public void m() {
+ if (npc != null) {
+ npc.update();
+ } else {
+ super.m();
+ }
+ }
+ }
+
+ public static class WitherSkullNPC extends CraftWitherSkull implements NPCHolder {
+ private final CitizensNPC npc;
+
+ public WitherSkullNPC(EntityWitherSkullNPC entity) {
+ super((CraftServer) Bukkit.getServer(), entity);
+ this.npc = entity.npc;
+ }
+
+ @Override
+ public NPC getNPC() {
+ return npc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java
new file mode 100644
index 000000000..f034fb273
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyChannel.java
@@ -0,0 +1,80 @@
+package net.citizensnpcs.nms.v1_10_R1.network;
+
+import io.netty.channel.AbstractChannel;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelMetadata;
+import io.netty.channel.ChannelOutboundBuffer;
+import io.netty.channel.DefaultChannelConfig;
+import io.netty.channel.EventLoop;
+
+import java.net.SocketAddress;
+
+public class EmptyChannel extends AbstractChannel {
+ private final ChannelConfig config = new DefaultChannelConfig(this);
+
+ public EmptyChannel(Channel parent) {
+ super(parent);
+ }
+
+ @Override
+ public ChannelConfig config() {
+ config.setAutoRead(true);
+ return config;
+ }
+
+ @Override
+ protected void doBeginRead() throws Exception {
+ }
+
+ @Override
+ protected void doBind(SocketAddress arg0) throws Exception {
+ }
+
+ @Override
+ protected void doClose() throws Exception {
+ }
+
+ @Override
+ protected void doDisconnect() throws Exception {
+ }
+
+ @Override
+ protected void doWrite(ChannelOutboundBuffer arg0) throws Exception {
+ }
+
+ @Override
+ public boolean isActive() {
+ return false;
+ }
+
+ @Override
+ protected boolean isCompatible(EventLoop arg0) {
+ return true;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return false;
+ }
+
+ @Override
+ protected SocketAddress localAddress0() {
+ return null;
+ }
+
+ @Override
+ public ChannelMetadata metadata() {
+ return null;
+ }
+
+ @Override
+ protected AbstractUnsafe newUnsafe() {
+ return null;
+ }
+
+ @Override
+ protected SocketAddress remoteAddress0() {
+ return null;
+ }
+}
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java
new file mode 100644
index 000000000..2bb552136
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetHandler.java
@@ -0,0 +1,17 @@
+package net.citizensnpcs.nms.v1_10_R1.network;
+
+import net.minecraft.server.v1_10_R1.EntityPlayer;
+import net.minecraft.server.v1_10_R1.MinecraftServer;
+import net.minecraft.server.v1_10_R1.NetworkManager;
+import net.minecraft.server.v1_10_R1.Packet;
+import net.minecraft.server.v1_10_R1.PlayerConnection;
+
+public class EmptyNetHandler extends PlayerConnection {
+ public EmptyNetHandler(MinecraftServer minecraftServer, NetworkManager networkManager, EntityPlayer entityPlayer) {
+ super(minecraftServer, networkManager, entityPlayer);
+ }
+
+ @Override
+ public void sendPacket(Packet> packet) {
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java
new file mode 100644
index 000000000..161331bb8
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptyNetworkManager.java
@@ -0,0 +1,19 @@
+package net.citizensnpcs.nms.v1_10_R1.network;
+
+import java.io.IOException;
+
+import net.citizensnpcs.nms.v1_10_R1.util.NMSImpl;
+import net.minecraft.server.v1_10_R1.EnumProtocolDirection;
+import net.minecraft.server.v1_10_R1.NetworkManager;
+
+public class EmptyNetworkManager extends NetworkManager {
+ public EmptyNetworkManager(EnumProtocolDirection flag) throws IOException {
+ super(flag);
+ NMSImpl.initNetworkManager(this);
+ }
+
+ @Override
+ public boolean isConnected() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java
new file mode 100644
index 000000000..eb6f7f02c
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/network/EmptySocket.java
@@ -0,0 +1,21 @@
+package net.citizensnpcs.nms.v1_10_R1.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(EMPTY);
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return new ByteArrayOutputStream(10);
+ }
+
+ private static final byte[] EMPTY = new byte[50];
+}
\ No newline at end of file
diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java
new file mode 100644
index 000000000..45ada5a74
--- /dev/null
+++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java
@@ -0,0 +1,1349 @@
+package net.citizensnpcs.nms.v1_10_R1.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.SocketAddress;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.World;
+import org.bukkit.boss.BarColor;
+import org.bukkit.boss.BarStyle;
+import org.bukkit.boss.BossBar;
+import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_10_R1.CraftSound;
+import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_10_R1.boss.CraftBossBar;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_10_R1.entity.CraftWither;
+import org.bukkit.craftbukkit.v1_10_R1.event.CraftEventFactory;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.FishHook;
+import org.bukkit.entity.Horse;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Tameable;
+import org.bukkit.entity.Wither;
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
+import org.bukkit.inventory.meta.SkullMeta;
+import org.bukkit.plugin.PluginLoadOrder;
+import org.bukkit.util.Vector;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.GameProfileRepository;
+import com.mojang.authlib.HttpAuthenticationService;
+import com.mojang.authlib.minecraft.MinecraftSessionService;
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
+import com.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse;
+import com.mojang.util.UUIDTypeAdapter;
+
+import net.citizensnpcs.Settings.Setting;
+import net.citizensnpcs.api.ai.NavigatorParameters;
+import net.citizensnpcs.api.ai.event.CancelReason;
+import net.citizensnpcs.api.command.exception.CommandException;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.npc.NPCRegistry;
+import net.citizensnpcs.api.util.Messaging;
+import net.citizensnpcs.nms.v1_10_R1.entity.BatController;
+import net.citizensnpcs.nms.v1_10_R1.entity.BlazeController;
+import net.citizensnpcs.nms.v1_10_R1.entity.CaveSpiderController;
+import net.citizensnpcs.nms.v1_10_R1.entity.ChickenController;
+import net.citizensnpcs.nms.v1_10_R1.entity.CowController;
+import net.citizensnpcs.nms.v1_10_R1.entity.CreeperController;
+import net.citizensnpcs.nms.v1_10_R1.entity.EnderDragonController;
+import net.citizensnpcs.nms.v1_10_R1.entity.EndermanController;
+import net.citizensnpcs.nms.v1_10_R1.entity.EndermiteController;
+import net.citizensnpcs.nms.v1_10_R1.entity.EntityHumanNPC;
+import net.citizensnpcs.nms.v1_10_R1.entity.GhastController;
+import net.citizensnpcs.nms.v1_10_R1.entity.GiantController;
+import net.citizensnpcs.nms.v1_10_R1.entity.GuardianController;
+import net.citizensnpcs.nms.v1_10_R1.entity.HorseController;
+import net.citizensnpcs.nms.v1_10_R1.entity.HumanController;
+import net.citizensnpcs.nms.v1_10_R1.entity.IronGolemController;
+import net.citizensnpcs.nms.v1_10_R1.entity.MagmaCubeController;
+import net.citizensnpcs.nms.v1_10_R1.entity.MushroomCowController;
+import net.citizensnpcs.nms.v1_10_R1.entity.OcelotController;
+import net.citizensnpcs.nms.v1_10_R1.entity.PigController;
+import net.citizensnpcs.nms.v1_10_R1.entity.PigZombieController;
+import net.citizensnpcs.nms.v1_10_R1.entity.PolarBearController;
+import net.citizensnpcs.nms.v1_10_R1.entity.RabbitController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SheepController;
+import net.citizensnpcs.nms.v1_10_R1.entity.ShulkerController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SilverfishController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SkeletonController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SlimeController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SnowmanController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SpiderController;
+import net.citizensnpcs.nms.v1_10_R1.entity.SquidController;
+import net.citizensnpcs.nms.v1_10_R1.entity.VillagerController;
+import net.citizensnpcs.nms.v1_10_R1.entity.WitchController;
+import net.citizensnpcs.nms.v1_10_R1.entity.WitherController;
+import net.citizensnpcs.nms.v1_10_R1.entity.WolfController;
+import net.citizensnpcs.nms.v1_10_R1.entity.ZombieController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.AreaEffectCloudController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ArmorStandController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.BoatController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.DragonFireballController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.EggController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.EnderCrystalController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.EnderPearlController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.EnderSignalController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.FallingBlockController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.FireworkController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.FishingHookController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ItemController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ItemFrameController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.LargeFireballController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.LeashController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartChestController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartCommandController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartFurnaceController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartHopperController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartRideableController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.MinecartTNTController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.PaintingController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ShulkerBulletController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.SmallFireballController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.SnowballController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.SpectralArrowController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.TNTPrimedController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ThrownExpBottleController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.ThrownPotionController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.TippedArrowController;
+import net.citizensnpcs.nms.v1_10_R1.entity.nonliving.WitherSkullController;
+import net.citizensnpcs.nms.v1_10_R1.network.EmptyChannel;
+import net.citizensnpcs.npc.EntityControllers;
+import net.citizensnpcs.npc.ai.MCNavigationStrategy.MCNavigator;
+import net.citizensnpcs.npc.ai.MCTargetStrategy.TargetNavigator;
+import net.citizensnpcs.npc.ai.NPCHolder;
+import net.citizensnpcs.npc.skin.SkinnableEntity;
+import net.citizensnpcs.util.BoundingBox;
+import net.citizensnpcs.util.Messages;
+import net.citizensnpcs.util.NMS;
+import net.citizensnpcs.util.NMSBridge;
+import net.citizensnpcs.util.PlayerAnimation;
+import net.citizensnpcs.util.PlayerUpdateTask;
+import net.citizensnpcs.util.Util;
+import net.minecraft.server.v1_10_R1.AttributeInstance;
+import net.minecraft.server.v1_10_R1.AxisAlignedBB;
+import net.minecraft.server.v1_10_R1.Block;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.BossBattleServer;
+import net.minecraft.server.v1_10_R1.ControllerJump;
+import net.minecraft.server.v1_10_R1.CrashReport;
+import net.minecraft.server.v1_10_R1.CrashReportSystemDetails;
+import net.minecraft.server.v1_10_R1.DamageSource;
+import net.minecraft.server.v1_10_R1.DataWatcherObject;
+import net.minecraft.server.v1_10_R1.EnchantmentManager;
+import net.minecraft.server.v1_10_R1.EnderDragonBattle;
+import net.minecraft.server.v1_10_R1.Entity;
+import net.minecraft.server.v1_10_R1.EntityEnderDragon;
+import net.minecraft.server.v1_10_R1.EntityFishingHook;
+import net.minecraft.server.v1_10_R1.EntityHorse;
+import net.minecraft.server.v1_10_R1.EntityHuman;
+import net.minecraft.server.v1_10_R1.EntityInsentient;
+import net.minecraft.server.v1_10_R1.EntityLiving;
+import net.minecraft.server.v1_10_R1.EntityMinecartAbstract;
+import net.minecraft.server.v1_10_R1.EntityPlayer;
+import net.minecraft.server.v1_10_R1.EntityPolarBear;
+import net.minecraft.server.v1_10_R1.EntityRabbit;
+import net.minecraft.server.v1_10_R1.EntityTameableAnimal;
+import net.minecraft.server.v1_10_R1.EntityTracker;
+import net.minecraft.server.v1_10_R1.EntityTrackerEntry;
+import net.minecraft.server.v1_10_R1.EntityTypes;
+import net.minecraft.server.v1_10_R1.EntityWither;
+import net.minecraft.server.v1_10_R1.GenericAttributes;
+import net.minecraft.server.v1_10_R1.MathHelper;
+import net.minecraft.server.v1_10_R1.MinecraftKey;
+import net.minecraft.server.v1_10_R1.MobEffects;
+import net.minecraft.server.v1_10_R1.NavigationAbstract;
+import net.minecraft.server.v1_10_R1.NetworkManager;
+import net.minecraft.server.v1_10_R1.Packet;
+import net.minecraft.server.v1_10_R1.PacketPlayOutEntityTeleport;
+import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo;
+import net.minecraft.server.v1_10_R1.PathEntity;
+import net.minecraft.server.v1_10_R1.PathPoint;
+import net.minecraft.server.v1_10_R1.PathfinderGoalSelector;
+import net.minecraft.server.v1_10_R1.ReportedException;
+import net.minecraft.server.v1_10_R1.SoundEffect;
+import net.minecraft.server.v1_10_R1.Vec3D;
+import net.minecraft.server.v1_10_R1.WorldServer;
+
+@SuppressWarnings("unchecked")
+public class NMSImpl implements NMSBridge {
+ public NMSImpl() {
+ loadEntityTypes();
+ }
+
+ @Override
+ public boolean addEntityToWorld(org.bukkit.entity.Entity entity, SpawnReason custom) {
+ return getHandle(entity).world.addEntity(getHandle(entity), custom);
+ }
+
+ @Override
+ public void addOrRemoveFromPlayerList(org.bukkit.entity.Entity entity, boolean remove) {
+ if (entity == null)
+ return;
+ EntityHuman handle = (EntityHuman) getHandle(entity);
+ if (handle.world == null)
+ return;
+ if (remove) {
+ handle.world.players.remove(handle);
+ } else if (!handle.world.players.contains(handle)) {
+ handle.world.players.add(handle);
+ }
+ PlayerUpdateTask.addOrRemove(entity, remove);
+ }
+
+ @Override
+ public void attack(LivingEntity attacker, LivingEntity btarget) {
+ EntityLiving handle = getHandle(attacker);
+ EntityLiving target = getHandle(btarget);
+ if (handle instanceof EntityPlayer) {
+ EntityPlayer humanHandle = (EntityPlayer) handle;
+ humanHandle.attack(target);
+ PlayerAnimation.ARM_SWING.play(humanHandle.getBukkitEntity());
+ return;
+ }
+ AttributeInstance attackDamage = handle.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE);
+ float f = (float) (attackDamage == null ? 1 : attackDamage.getValue());
+ int i = 0;
+
+ if (target instanceof EntityLiving) {
+ f += EnchantmentManager.a(handle.getItemInMainHand(), target.getMonsterType());
+ i += EnchantmentManager.a(handle);
+ }
+
+ boolean flag = target.damageEntity(DamageSource.mobAttack(handle), f);
+
+ if (!flag)
+ return;
+ if (i > 0) {
+ target.g(-Math.sin(handle.yaw * Math.PI / 180.0F) * i * 0.5F, 0.1D,
+ Math.cos(handle.yaw * Math.PI / 180.0F) * i * 0.5F);
+ handle.motX *= 0.6D;
+ handle.motZ *= 0.6D;
+ }
+
+ int fireAspectLevel = EnchantmentManager.getFireAspectEnchantmentLevel(handle);
+
+ if (fireAspectLevel > 0) {
+ target.setOnFire(fireAspectLevel * 4);
+ }
+ }
+
+ @Override
+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) throws Exception {
+ if (Bukkit.isPrimaryThread())
+ throw new IllegalStateException("NMS.fillProfileProperties cannot be invoked from the main thread.");
+
+ MinecraftSessionService sessionService = ((CraftServer) Bukkit.getServer()).getServer().ay();
+
+ YggdrasilAuthenticationService auth = ((YggdrasilMinecraftSessionService) sessionService)
+ .getAuthenticationService();
+
+ URL url = HttpAuthenticationService
+ .constantURL(getAuthServerBaseUrl() + UUIDTypeAdapter.fromUUID(profile.getId()));
+
+ url = HttpAuthenticationService.concatenateURL(url, "unsigned=" + !requireSecure);
+
+ MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) MAKE_REQUEST.invoke(auth,
+ url, null, MinecraftProfilePropertiesResponse.class);
+ if (response == null)
+ return profile;
+
+ GameProfile result = new GameProfile(response.getId(), response.getName());
+ result.getProperties().putAll(response.getProperties());
+ profile.getProperties().putAll(response.getProperties());
+
+ return result;
+ }
+
+ public String getAuthServerBaseUrl() {
+ return Setting.AUTH_SERVER_URL.asString();
+ }
+
+ @Override
+ public BossBar getBossBar(org.bukkit.entity.Entity entity) {
+ BossBattleServer bserver = null;
+ try {
+ if (entity.getType() == EntityType.WITHER) {
+ bserver = (BossBattleServer) WITHER_BOSS_BAR_FIELD.get(NMSImpl.getHandle(entity));
+ } else if (entity.getType() == EntityType.ENDER_DRAGON) {
+ bserver = (BossBattleServer) ENDERDRAGON_BATTLE_BAR_FIELD
+ .get(ENDERDRAGON_BATTLE_FIELD.get(NMSImpl.getHandle(entity)));
+ }
+ } catch (Exception e) {
+ }
+ if (bserver == null) {
+ return null;
+ }
+ BossBar ret = Bukkit.createBossBar("", BarColor.BLUE, BarStyle.SEGMENTED_10);
+ try {
+ CRAFT_BOSSBAR_HANDLE_FIELD.set(ret, bserver);
+ } catch (Exception e) {
+ }
+ return ret;
+ }
+
+ @Override
+ public BoundingBox getBoundingBox(org.bukkit.entity.Entity handle) {
+ AxisAlignedBB bb = NMSImpl.getHandle(handle).getBoundingBox();
+ return new BoundingBox(bb.a, bb.b, bb.c, bb.d, bb.e, bb.f);
+ }
+
+ @Override
+ public GameProfileRepository getGameProfileRepository() {
+ return ((CraftServer) Bukkit.getServer()).getServer().getGameProfileRepository();
+ }
+
+ @Override
+ public float getHorizontalMovement(org.bukkit.entity.Entity entity) {
+ if (!entity.getType().isAlive())
+ return Float.NaN;
+ EntityLiving handle = NMSImpl.getHandle((LivingEntity) entity);
+ return handle.bg;
+ }
+
+ @Override
+ public NPC getNPC(org.bukkit.entity.Entity entity) {
+ return getHandle(entity) instanceof NPCHolder ? ((NPCHolder) getHandle(entity)).getNPC() : null;
+ }
+
+ @Override
+ public List getPassengers(org.bukkit.entity.Entity entity) {
+ return Lists.transform(NMSImpl.getHandle(entity).passengers, new Function() {
+ @Override
+ public org.bukkit.entity.Entity apply(Entity input) {
+ return input.getBukkitEntity();
+ }
+ });
+ }
+
+ @Override
+ public GameProfile getProfile(SkullMeta meta) {
+ if (SKULL_PROFILE_FIELD == null) {
+ try {
+ SKULL_PROFILE_FIELD = meta.getClass().getDeclaredField("profile");
+ SKULL_PROFILE_FIELD.setAccessible(true);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ try {
+ return (GameProfile) SKULL_PROFILE_FIELD.get(meta);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String getSound(String flag) throws CommandException {
+ try {
+ String ret = CraftSound.getSound(Sound.valueOf(flag.toUpperCase()));
+ if (ret == null)
+ throw new CommandException(Messages.INVALID_SOUND);
+ return ret;
+ } catch (Exception e) {
+ throw new CommandException(Messages.INVALID_SOUND);
+ }
+ }
+
+ @Override
+ public float getSpeedFor(NPC npc) {
+ if (!npc.isSpawned() || !(npc.getEntity() instanceof LivingEntity))
+ return DEFAULT_SPEED;
+ EntityLiving handle = NMSImpl.getHandle((LivingEntity) npc.getEntity());
+ if (handle == null)
+ return DEFAULT_SPEED;
+ return DEFAULT_SPEED;
+ // return (float)
+ // handle.getAttributeInstance(GenericAttributes.d).getValue();
+ }
+
+ @Override
+ public float getStepHeight(org.bukkit.entity.Entity entity) {
+ return NMSImpl.getHandle(entity).P;
+ }
+
+ @Override
+ public MCNavigator getTargetNavigator(org.bukkit.entity.Entity entity, Iterable dest,
+ final NavigatorParameters params) {
+ final PathEntity path = new PathEntity(
+ Iterables.toArray(Iterables.transform(dest, new Function() {
+ @Override
+ public PathPoint apply(Vector input) {
+ return new PathPoint(input.getBlockX(), input.getBlockY(), input.getBlockZ());
+ }
+ }), PathPoint.class));
+ return getTargetNavigator(entity, params, new Function() {
+ @Override
+ public Void apply(NavigationAbstract input) {
+ input.a(path, params.speed());
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public MCNavigator getTargetNavigator(final org.bukkit.entity.Entity entity, final Location dest,
+ final NavigatorParameters params) {
+ return getTargetNavigator(entity, params, new Function() {
+ @Override
+ public Void apply(NavigationAbstract input) {
+ input.a(dest.getX(), dest.getY(), dest.getZ(), params.speed());
+ return null;
+ }
+ });
+ }
+
+ private MCNavigator getTargetNavigator(final org.bukkit.entity.Entity entity, final NavigatorParameters params,
+ final Function function) {
+ net.minecraft.server.v1_10_R1.Entity raw = getHandle(entity);
+ raw.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.
+ final NavigationAbstract navigation = NMSImpl.getNavigation(entity);
+ float oldWidth = raw.width;
+ if (raw instanceof EntityHorse) {
+ raw.width = Math.min(0.99f, oldWidth);
+ }
+ function.apply(navigation);
+ raw.width = oldWidth; // minecraft requires that an entity fit onto both blocks if width >= 1f, but we'd
+ // prefer to make it just fit on 1 so hack around it a bit.
+ final CancelReason initial;
+ if (NMSImpl.isNavigationFinished(navigation)) {
+ initial = CancelReason.STUCK;
+ } else {
+ initial = null;
+ }
+ return new MCNavigator() {
+ float lastSpeed = params.speed();
+ CancelReason reason = initial;
+
+ @Override
+ public CancelReason getCancelReason() {
+ return reason;
+ }
+
+ @Override
+ public Iterable getPath() {
+ return new NavigationIterable(navigation);
+ }
+
+ @Override
+ public void stop() {
+ stopNavigation(navigation);
+ }
+
+ @Override
+ public boolean update() {
+ if (params.speed() != lastSpeed) {
+ Messaging.debug("Repathfinding " + ((NPCHolder) entity).getNPC().getId() + " due to speed change");
+ function.apply(navigation);
+ lastSpeed = params.speed();
+ }
+ navigation.a(params.speed());
+ return NMSImpl.isNavigationFinished(navigation);
+ }
+ };
+ }
+
+ @Override
+ public TargetNavigator getTargetNavigator(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity target,
+ NavigatorParameters parameters) {
+ NavigationAbstract navigation = getNavigation(entity);
+ return navigation == null ? null
+ : new NavigationFieldWrapper(navigation, target, parameters);
+ }
+
+ @Override
+ public org.bukkit.entity.Entity getVehicle(org.bukkit.entity.Entity entity) {
+ Entity e = NMSImpl.getHandle(entity).getVehicle();
+ return e == NMSImpl.getHandle(entity) ? null : e.getBukkitEntity();
+ }
+
+ @Override
+ public float getVerticalMovement(org.bukkit.entity.Entity entity) {
+ if (!entity.getType().isAlive())
+ return Float.NaN;
+ EntityLiving handle = NMSImpl.getHandle((LivingEntity) entity);
+ return handle.bf;
+ }
+
+ @Override
+ public boolean isOnGround(org.bukkit.entity.Entity entity) {
+ return NMSImpl.getHandle(entity).onGround;
+ }
+
+ private void loadEntityTypes() {
+ EntityControllers.setEntityControllerForType(EntityType.AREA_EFFECT_CLOUD, AreaEffectCloudController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ARROW, TippedArrowController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ARMOR_STAND, ArmorStandController.class);
+ EntityControllers.setEntityControllerForType(EntityType.BAT, BatController.class);
+ EntityControllers.setEntityControllerForType(EntityType.BLAZE, BlazeController.class);
+ EntityControllers.setEntityControllerForType(EntityType.BOAT, BoatController.class);
+ EntityControllers.setEntityControllerForType(EntityType.CAVE_SPIDER, CaveSpiderController.class);
+ EntityControllers.setEntityControllerForType(EntityType.CHICKEN, ChickenController.class);
+ EntityControllers.setEntityControllerForType(EntityType.COW, CowController.class);
+ EntityControllers.setEntityControllerForType(EntityType.CREEPER, CreeperController.class);
+ EntityControllers.setEntityControllerForType(EntityType.DRAGON_FIREBALL, DragonFireballController.class);
+ EntityControllers.setEntityControllerForType(EntityType.DROPPED_ITEM, ItemController.class);
+ EntityControllers.setEntityControllerForType(EntityType.EGG, EggController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDER_CRYSTAL, EnderCrystalController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDER_DRAGON, EnderDragonController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDER_PEARL, EnderPearlController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDER_SIGNAL, EnderSignalController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDERMAN, EndermanController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ENDERMITE, EndermiteController.class);
+ EntityControllers.setEntityControllerForType(EntityType.FALLING_BLOCK, FallingBlockController.class);
+ EntityControllers.setEntityControllerForType(EntityType.FIREWORK, FireworkController.class);
+ EntityControllers.setEntityControllerForType(EntityType.FIREBALL, LargeFireballController.class);
+ EntityControllers.setEntityControllerForType(EntityType.FISHING_HOOK, FishingHookController.class);
+ EntityControllers.setEntityControllerForType(EntityType.GHAST, GhastController.class);
+ EntityControllers.setEntityControllerForType(EntityType.GIANT, GiantController.class);
+ EntityControllers.setEntityControllerForType(EntityType.GUARDIAN, GuardianController.class);
+ EntityControllers.setEntityControllerForType(EntityType.HORSE, HorseController.class);
+ EntityControllers.setEntityControllerForType(EntityType.IRON_GOLEM, IronGolemController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ITEM_FRAME, ItemFrameController.class);
+ EntityControllers.setEntityControllerForType(EntityType.LEASH_HITCH, LeashController.class);
+ EntityControllers.setEntityControllerForType(EntityType.LINGERING_POTION, ThrownPotionController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MAGMA_CUBE, MagmaCubeController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART, MinecartRideableController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART_CHEST, MinecartChestController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART_COMMAND, MinecartCommandController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART_FURNACE, MinecartFurnaceController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART_HOPPER, MinecartHopperController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MINECART_TNT, MinecartTNTController.class);
+ EntityControllers.setEntityControllerForType(EntityType.MUSHROOM_COW, MushroomCowController.class);
+ EntityControllers.setEntityControllerForType(EntityType.OCELOT, OcelotController.class);
+ EntityControllers.setEntityControllerForType(EntityType.PAINTING, PaintingController.class);
+ EntityControllers.setEntityControllerForType(EntityType.PIG, PigController.class);
+ EntityControllers.setEntityControllerForType(EntityType.PIG_ZOMBIE, PigZombieController.class);
+ EntityControllers.setEntityControllerForType(EntityType.POLAR_BEAR, PolarBearController.class);
+ EntityControllers.setEntityControllerForType(EntityType.PLAYER, HumanController.class);
+ EntityControllers.setEntityControllerForType(EntityType.RABBIT, RabbitController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SHEEP, SheepController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SHULKER, ShulkerController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SHULKER_BULLET, ShulkerBulletController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SILVERFISH, SilverfishController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SKELETON, SkeletonController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SLIME, SlimeController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SMALL_FIREBALL, SmallFireballController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SNOWBALL, SnowballController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SNOWMAN, SnowmanController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SPECTRAL_ARROW, SpectralArrowController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SPIDER, SpiderController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SPLASH_POTION, ThrownPotionController.class);
+ EntityControllers.setEntityControllerForType(EntityType.SQUID, SquidController.class);
+ EntityControllers.setEntityControllerForType(EntityType.TIPPED_ARROW, TippedArrowController.class);
+ EntityControllers.setEntityControllerForType(EntityType.THROWN_EXP_BOTTLE, ThrownExpBottleController.class);
+ EntityControllers.setEntityControllerForType(EntityType.PRIMED_TNT, TNTPrimedController.class);
+ EntityControllers.setEntityControllerForType(EntityType.VILLAGER, VillagerController.class);
+ EntityControllers.setEntityControllerForType(EntityType.WOLF, WolfController.class);
+ EntityControllers.setEntityControllerForType(EntityType.WITCH, WitchController.class);
+ EntityControllers.setEntityControllerForType(EntityType.WITHER, WitherController.class);
+ EntityControllers.setEntityControllerForType(EntityType.WITHER_SKULL, WitherSkullController.class);
+ EntityControllers.setEntityControllerForType(EntityType.ZOMBIE, ZombieController.class);
+ }
+
+ @Override
+ public void loadPlugins() {
+ ((CraftServer) Bukkit.getServer()).enablePlugins(PluginLoadOrder.POSTWORLD);
+ }
+
+ @Override
+ public void look(org.bukkit.entity.Entity entity, float yaw, float pitch) {
+ Entity handle = NMSImpl.getHandle(entity);
+ if (handle == null)
+ return;
+ yaw = Util.clampYaw(yaw);
+ handle.yaw = yaw;
+ setHeadYaw(entity, yaw);
+ handle.pitch = pitch;
+ }
+
+ @Override
+ public void look(org.bukkit.entity.Entity from, org.bukkit.entity.Entity to) {
+ Entity handle = NMSImpl.getHandle(from), target = NMSImpl.getHandle(to);
+ if (handle instanceof EntityInsentient) {
+ ((EntityInsentient) handle).getControllerLook().a(target, 10.0F, ((EntityInsentient) handle).N());
+ } else if (handle instanceof EntityHumanNPC) {
+ ((EntityHumanNPC) handle).setTargetLook(target, 10F, 40F);
+ }
+ }
+
+ @Override
+ public void mount(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity passenger) {
+ if (NMSImpl.getHandle(passenger) == null)
+ return;
+ NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity));
+ }
+
+ @Override
+ public void openHorseScreen(Horse horse, Player equipper) {
+ EntityLiving handle = NMSImpl.getHandle(horse);
+ EntityLiving equipperHandle = NMSImpl.getHandle(equipper);
+ if (handle == null || equipperHandle == null)
+ return;
+ boolean wasTamed = horse.isTamed();
+ horse.setTamed(true);
+ ((EntityHorse) handle).a((EntityHuman) equipperHandle);
+ horse.setTamed(wasTamed);
+ }
+
+ @Override
+ public void playAnimation(PlayerAnimation animation, Player player, int radius) {
+ PlayerAnimationImpl.play(animation, player, radius);
+ }
+
+ @Override
+ public void registerEntityClass(Class> clazz) {
+ if (ENTITY_CLASS_TO_INT == null || ENTITY_CLASS_TO_INT.containsKey(clazz))
+ return;
+ Class> search = clazz;
+ while ((search = search.getSuperclass()) != null && Entity.class.isAssignableFrom(search)) {
+ if (!ENTITY_CLASS_TO_INT.containsKey(search))
+ continue;
+ int code = ENTITY_CLASS_TO_INT.get(search);
+ ENTITY_CLASS_TO_INT.put(clazz, code);
+ ENTITY_CLASS_TO_NAME.put(clazz, ENTITY_CLASS_TO_NAME.get(search));
+ return;
+ }
+ throw new IllegalArgumentException("unable to find valid entity superclass for class " + clazz.toString());
+ }
+
+ @Override
+ public void removeFromServerPlayerList(Player player) {
+ EntityPlayer handle = (EntityPlayer) NMSImpl.getHandle(player);
+ ((CraftServer) Bukkit.getServer()).getHandle().players.remove(handle);
+ }
+
+ @Override
+ public void removeFromWorld(org.bukkit.entity.Entity entity) {
+ Preconditions.checkNotNull(entity);
+
+ Entity nmsEntity = ((CraftEntity) entity).getHandle();
+ nmsEntity.world.removeEntity(nmsEntity);
+ }
+
+ @Override
+ public void removeHookIfNecessary(NPCRegistry npcRegistry, FishHook entity) {
+ EntityFishingHook hook = (EntityFishingHook) NMSImpl.getHandle(entity);
+ if (hook.hooked == null)
+ return;
+ NPC npc = npcRegistry.getNPC(hook.hooked.getBukkitEntity());
+ if (npc == null)
+ return;
+ if (npc.isProtected()) {
+ hook.hooked = null;
+ hook.die();
+ }
+ }
+
+ @Override
+ public void replaceTrackerEntry(Player player) {
+ WorldServer server = (WorldServer) NMSImpl.getHandle(player).getWorld();
+ EntityTrackerEntry entry = server.getTracker().trackedEntities.get(player.getEntityId());
+ if (entry == null)
+ return;
+ PlayerlistTrackerEntry replace = new PlayerlistTrackerEntry(entry);
+ server.getTracker().trackedEntities.a(player.getEntityId(), replace);
+ if (TRACKED_ENTITY_SET != null) {
+ try {
+ Set