From f8d2e4ec1cc8f5add594f55b40626da1a9e821d9 Mon Sep 17 00:00:00 2001 From: fullwall Date: Thu, 1 Dec 2016 19:32:50 +0800 Subject: [PATCH] Remove unnecessary copy of files --- main/java/net/citizensnpcs/Citizens.java | 470 ---- main/java/net/citizensnpcs/EventListen.java | 614 ----- main/java/net/citizensnpcs/Metrics.java | 787 ------- .../citizensnpcs/NPCNeedsRespawnEvent.java | 31 - .../net/citizensnpcs/PaymentListener.java | 38 - main/java/net/citizensnpcs/Settings.java | 181 -- .../citizensnpcs/commands/AdminCommands.java | 67 - .../citizensnpcs/commands/EditorCommands.java | 70 - .../commands/NPCCommandSelector.java | 121 - .../citizensnpcs/commands/NPCCommands.java | 1997 ----------------- .../commands/TemplateCommands.java | 120 - .../citizensnpcs/commands/TraitCommands.java | 167 -- .../commands/WaypointCommands.java | 58 - .../net/citizensnpcs/editor/CopierEditor.java | 54 - main/java/net/citizensnpcs/editor/Editor.java | 60 - .../citizensnpcs/editor/EndermanEquipper.java | 42 - .../citizensnpcs/editor/EquipmentEditor.java | 113 - .../net/citizensnpcs/editor/Equipper.java | 9 - .../citizensnpcs/editor/GenericEquipper.java | 94 - .../citizensnpcs/editor/HorseEquipper.java | 15 - .../net/citizensnpcs/editor/PigEquipper.java | 31 - .../citizensnpcs/editor/SheepEquipper.java | 40 - .../npc/AbstractEntityController.java | 38 - .../net/citizensnpcs/npc/CitizensNPC.java | 345 --- .../citizensnpcs/npc/CitizensNPCRegistry.java | 251 --- .../npc/CitizensTraitFactory.java | 177 -- .../citizensnpcs/npc/EntityController.java | 14 - .../citizensnpcs/npc/EntityControllers.java | 32 - .../net/citizensnpcs/npc/NPCSelector.java | 148 -- main/java/net/citizensnpcs/npc/Template.java | 138 -- .../npc/ai/AStarNavigationStrategy.java | 120 - .../npc/ai/CitizensBlockBreaker.java | 172 -- .../npc/ai/CitizensNavigator.java | 407 ---- .../npc/ai/EnhancedMovementExaminer.java | 44 - .../npc/ai/FlyingAStarNavigationStrategy.java | 148 -- .../npc/ai/MCNavigationStrategy.java | 97 - .../citizensnpcs/npc/ai/MCTargetStrategy.java | 204 -- .../net/citizensnpcs/npc/ai/NPCHolder.java | 7 - .../net/citizensnpcs/npc/ai/speech/Chat.java | 133 -- .../npc/ai/speech/CitizensSpeechFactory.java | 82 - .../npc/ai/speech/TalkableEntity.java | 92 - .../npc/profile/ProfileFetchHandler.java | 14 - .../npc/profile/ProfileFetchResult.java | 29 - .../npc/profile/ProfileFetchThread.java | 107 - .../npc/profile/ProfileFetcher.java | 167 -- .../npc/profile/ProfileRequest.java | 127 -- main/java/net/citizensnpcs/npc/skin/Skin.java | 341 --- .../npc/skin/SkinPacketTracker.java | 255 --- .../npc/skin/SkinUpdateTracker.java | 481 ---- .../npc/skin/SkinnableEntity.java | 59 - .../citizensnpcs/npc/skin/TabListRemover.java | 158 -- main/java/net/citizensnpcs/trait/Age.java | 69 - main/java/net/citizensnpcs/trait/Anchors.java | 87 - .../citizensnpcs/trait/ArmorStandTrait.java | 108 - .../net/citizensnpcs/trait/BossBarTrait.java | 74 - .../net/citizensnpcs/trait/Controllable.java | 367 --- .../citizensnpcs/trait/CurrentLocation.java | 37 - main/java/net/citizensnpcs/trait/Gravity.java | 41 - .../citizensnpcs/trait/HorseModifiers.java | 105 - .../net/citizensnpcs/trait/LookClose.java | 139 -- .../net/citizensnpcs/trait/MountTrait.java | 37 - .../citizensnpcs/trait/NPCSkeletonType.java | 34 - .../citizensnpcs/trait/OcelotModifiers.java | 43 - main/java/net/citizensnpcs/trait/Poses.java | 104 - main/java/net/citizensnpcs/trait/Powered.java | 36 - .../net/citizensnpcs/trait/RabbitType.java | 31 - main/java/net/citizensnpcs/trait/Saddle.java | 49 - .../net/citizensnpcs/trait/ScriptTrait.java | 119 - .../net/citizensnpcs/trait/SheepTrait.java | 55 - .../net/citizensnpcs/trait/SkinLayers.java | 263 --- .../net/citizensnpcs/trait/SlimeSize.java | 41 - .../net/citizensnpcs/trait/Toggleable.java | 5 - .../trait/VillagerProfession.java | 57 - .../net/citizensnpcs/trait/WitherTrait.java | 38 - .../net/citizensnpcs/trait/WolfModifiers.java | 66 - .../net/citizensnpcs/trait/WoolColor.java | 64 - .../citizensnpcs/trait/ZombieModifier.java | 58 - .../trait/text/PageChangePrompt.java | 38 - .../net/citizensnpcs/trait/text/Text.java | 241 -- .../trait/text/TextAddPrompt.java | 30 - .../trait/text/TextEditPrompt.java | 31 - .../trait/text/TextEditStartPrompt.java | 44 - .../trait/text/TextRemovePrompt.java | 45 - .../trait/text/TextStartPrompt.java | 69 - .../waypoint/GuidedWaypointProvider.java | 393 ---- .../waypoint/LinearWaypointProvider.java | 475 ---- .../LinearWaypointsCompleteEvent.java | 40 - .../waypoint/WanderWaypointProvider.java | 71 - .../citizensnpcs/trait/waypoint/Waypoint.java | 113 - .../trait/waypoint/WaypointEditor.java | 9 - .../trait/waypoint/WaypointMarkers.java | 52 - .../trait/waypoint/WaypointProvider.java | 51 - .../trait/waypoint/Waypoints.java | 137 -- .../waypoint/triggers/AnimationTrigger.java | 42 - .../triggers/AnimationTriggerPrompt.java | 49 - .../trait/waypoint/triggers/ChatTrigger.java | 52 - .../waypoint/triggers/ChatTriggerPrompt.java | 47 - .../trait/waypoint/triggers/DelayTrigger.java | 48 - .../waypoint/triggers/DelayTriggerPrompt.java | 22 - .../trait/waypoint/triggers/SpeedTrigger.java | 32 - .../waypoint/triggers/SpeedTriggerPrompt.java | 22 - .../waypoint/triggers/TeleportTrigger.java | 32 - .../triggers/TeleportTriggerPrompt.java | 58 - .../waypoint/triggers/TriggerAddPrompt.java | 55 - .../waypoint/triggers/TriggerEditPrompt.java | 62 - .../triggers/TriggerRemovePrompt.java | 67 - .../waypoint/triggers/WaypointTrigger.java | 11 - .../triggers/WaypointTriggerPrompt.java | 18 - .../triggers/WaypointTriggerRegistry.java | 59 - main/java/net/citizensnpcs/util/Anchor.java | 96 - .../net/citizensnpcs/util/BoundingBox.java | 19 - main/java/net/citizensnpcs/util/Messages.java | 287 --- main/java/net/citizensnpcs/util/NMS.java | 266 --- .../java/net/citizensnpcs/util/NMSBridge.java | 133 -- .../citizensnpcs/util/PlayerAnimation.java | 29 - .../citizensnpcs/util/PlayerUpdateTask.java | 56 - main/java/net/citizensnpcs/util/Pose.java | 60 - .../net/citizensnpcs/util/StringHelper.java | 25 - main/java/net/citizensnpcs/util/Util.java | 173 -- .../net/citizensnpcs/util/XORShiftRNG.java | 139 -- 120 files changed, 15491 deletions(-) delete mode 100644 main/java/net/citizensnpcs/Citizens.java delete mode 100644 main/java/net/citizensnpcs/EventListen.java delete mode 100644 main/java/net/citizensnpcs/Metrics.java delete mode 100644 main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java delete mode 100644 main/java/net/citizensnpcs/PaymentListener.java delete mode 100644 main/java/net/citizensnpcs/Settings.java delete mode 100644 main/java/net/citizensnpcs/commands/AdminCommands.java delete mode 100644 main/java/net/citizensnpcs/commands/EditorCommands.java delete mode 100644 main/java/net/citizensnpcs/commands/NPCCommandSelector.java delete mode 100644 main/java/net/citizensnpcs/commands/NPCCommands.java delete mode 100644 main/java/net/citizensnpcs/commands/TemplateCommands.java delete mode 100644 main/java/net/citizensnpcs/commands/TraitCommands.java delete mode 100644 main/java/net/citizensnpcs/commands/WaypointCommands.java delete mode 100644 main/java/net/citizensnpcs/editor/CopierEditor.java delete mode 100644 main/java/net/citizensnpcs/editor/Editor.java delete mode 100644 main/java/net/citizensnpcs/editor/EndermanEquipper.java delete mode 100644 main/java/net/citizensnpcs/editor/EquipmentEditor.java delete mode 100644 main/java/net/citizensnpcs/editor/Equipper.java delete mode 100644 main/java/net/citizensnpcs/editor/GenericEquipper.java delete mode 100644 main/java/net/citizensnpcs/editor/HorseEquipper.java delete mode 100644 main/java/net/citizensnpcs/editor/PigEquipper.java delete mode 100644 main/java/net/citizensnpcs/editor/SheepEquipper.java delete mode 100644 main/java/net/citizensnpcs/npc/AbstractEntityController.java delete mode 100644 main/java/net/citizensnpcs/npc/CitizensNPC.java delete mode 100644 main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java delete mode 100644 main/java/net/citizensnpcs/npc/CitizensTraitFactory.java delete mode 100644 main/java/net/citizensnpcs/npc/EntityController.java delete mode 100644 main/java/net/citizensnpcs/npc/EntityControllers.java delete mode 100644 main/java/net/citizensnpcs/npc/NPCSelector.java delete mode 100644 main/java/net/citizensnpcs/npc/Template.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/CitizensBlockBreaker.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/EnhancedMovementExaminer.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/NPCHolder.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/speech/Chat.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/speech/CitizensSpeechFactory.java delete mode 100644 main/java/net/citizensnpcs/npc/ai/speech/TalkableEntity.java delete mode 100644 main/java/net/citizensnpcs/npc/profile/ProfileFetchHandler.java delete mode 100644 main/java/net/citizensnpcs/npc/profile/ProfileFetchResult.java delete mode 100644 main/java/net/citizensnpcs/npc/profile/ProfileFetchThread.java delete mode 100644 main/java/net/citizensnpcs/npc/profile/ProfileFetcher.java delete mode 100644 main/java/net/citizensnpcs/npc/profile/ProfileRequest.java delete mode 100644 main/java/net/citizensnpcs/npc/skin/Skin.java delete mode 100644 main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java delete mode 100644 main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java delete mode 100644 main/java/net/citizensnpcs/npc/skin/SkinnableEntity.java delete mode 100644 main/java/net/citizensnpcs/npc/skin/TabListRemover.java delete mode 100644 main/java/net/citizensnpcs/trait/Age.java delete mode 100644 main/java/net/citizensnpcs/trait/Anchors.java delete mode 100644 main/java/net/citizensnpcs/trait/ArmorStandTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/BossBarTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/Controllable.java delete mode 100644 main/java/net/citizensnpcs/trait/CurrentLocation.java delete mode 100644 main/java/net/citizensnpcs/trait/Gravity.java delete mode 100644 main/java/net/citizensnpcs/trait/HorseModifiers.java delete mode 100644 main/java/net/citizensnpcs/trait/LookClose.java delete mode 100644 main/java/net/citizensnpcs/trait/MountTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/NPCSkeletonType.java delete mode 100644 main/java/net/citizensnpcs/trait/OcelotModifiers.java delete mode 100644 main/java/net/citizensnpcs/trait/Poses.java delete mode 100644 main/java/net/citizensnpcs/trait/Powered.java delete mode 100644 main/java/net/citizensnpcs/trait/RabbitType.java delete mode 100644 main/java/net/citizensnpcs/trait/Saddle.java delete mode 100644 main/java/net/citizensnpcs/trait/ScriptTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/SheepTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/SkinLayers.java delete mode 100644 main/java/net/citizensnpcs/trait/SlimeSize.java delete mode 100644 main/java/net/citizensnpcs/trait/Toggleable.java delete mode 100644 main/java/net/citizensnpcs/trait/VillagerProfession.java delete mode 100644 main/java/net/citizensnpcs/trait/WitherTrait.java delete mode 100644 main/java/net/citizensnpcs/trait/WolfModifiers.java delete mode 100644 main/java/net/citizensnpcs/trait/WoolColor.java delete mode 100644 main/java/net/citizensnpcs/trait/ZombieModifier.java delete mode 100644 main/java/net/citizensnpcs/trait/text/PageChangePrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/text/Text.java delete mode 100644 main/java/net/citizensnpcs/trait/text/TextAddPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/text/TextEditPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/text/TextEditStartPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/text/TextRemovePrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/text/TextStartPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/GuidedWaypointProvider.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/LinearWaypointsCompleteEvent.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/WanderWaypointProvider.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/Waypoint.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/WaypointEditor.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/WaypointMarkers.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/WaypointProvider.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/Waypoints.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/AnimationTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/ChatTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/DelayTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/SpeedTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/TeleportTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerRemovePrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTrigger.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerPrompt.java delete mode 100644 main/java/net/citizensnpcs/trait/waypoint/triggers/WaypointTriggerRegistry.java delete mode 100644 main/java/net/citizensnpcs/util/Anchor.java delete mode 100644 main/java/net/citizensnpcs/util/BoundingBox.java delete mode 100644 main/java/net/citizensnpcs/util/Messages.java delete mode 100644 main/java/net/citizensnpcs/util/NMS.java delete mode 100644 main/java/net/citizensnpcs/util/NMSBridge.java delete mode 100644 main/java/net/citizensnpcs/util/PlayerAnimation.java delete mode 100644 main/java/net/citizensnpcs/util/PlayerUpdateTask.java delete mode 100644 main/java/net/citizensnpcs/util/Pose.java delete mode 100644 main/java/net/citizensnpcs/util/StringHelper.java delete mode 100644 main/java/net/citizensnpcs/util/Util.java delete mode 100644 main/java/net/citizensnpcs/util/XORShiftRNG.java diff --git a/main/java/net/citizensnpcs/Citizens.java b/main/java/net/citizensnpcs/Citizens.java deleted file mode 100644 index 7154b46ad..000000000 --- a/main/java/net/citizensnpcs/Citizens.java +++ /dev/null @@ -1,470 +0,0 @@ -package net.citizensnpcs; - -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.java.JavaPlugin; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; - -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.CitizensPlugin; -import net.citizensnpcs.api.ai.speech.SpeechFactory; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.CommandManager; -import net.citizensnpcs.api.command.CommandManager.CommandInfo; -import net.citizensnpcs.api.command.Injector; -import net.citizensnpcs.api.event.CitizensDisableEvent; -import net.citizensnpcs.api.event.CitizensEnableEvent; -import net.citizensnpcs.api.event.CitizensPreReloadEvent; -import net.citizensnpcs.api.event.CitizensReloadEvent; -import net.citizensnpcs.api.event.DespawnReason; -import net.citizensnpcs.api.exception.NPCLoadException; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCDataStore; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.npc.SimpleNPCDataStore; -import net.citizensnpcs.api.scripting.EventRegistrar; -import net.citizensnpcs.api.scripting.ObjectProvider; -import net.citizensnpcs.api.scripting.ScriptCompiler; -import net.citizensnpcs.api.trait.TraitFactory; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.api.util.NBTStorage; -import net.citizensnpcs.api.util.Storage; -import net.citizensnpcs.api.util.Translator; -import net.citizensnpcs.api.util.YamlStorage; -import net.citizensnpcs.commands.AdminCommands; -import net.citizensnpcs.commands.EditorCommands; -import net.citizensnpcs.commands.NPCCommands; -import net.citizensnpcs.commands.TemplateCommands; -import net.citizensnpcs.commands.TraitCommands; -import net.citizensnpcs.commands.WaypointCommands; -import net.citizensnpcs.editor.Editor; -import net.citizensnpcs.npc.CitizensNPCRegistry; -import net.citizensnpcs.npc.CitizensTraitFactory; -import net.citizensnpcs.npc.NPCSelector; -import net.citizensnpcs.npc.ai.speech.Chat; -import net.citizensnpcs.npc.ai.speech.CitizensSpeechFactory; -import net.citizensnpcs.npc.profile.ProfileFetcher; -import net.citizensnpcs.npc.skin.Skin; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.NMS; -import net.citizensnpcs.util.PlayerUpdateTask; -import net.citizensnpcs.util.StringHelper; -import net.citizensnpcs.util.Util; -import net.milkbowl.vault.economy.Economy; - -public class Citizens extends JavaPlugin implements CitizensPlugin { - private final CommandManager commands = new CommandManager(); - private boolean compatible; - private Settings config; - private CitizensNPCRegistry npcRegistry; - private NPCDataStore saves; - private NPCSelector selector; - private CitizensSpeechFactory speechFactory; - private final Map storedRegistries = Maps.newHashMap(); - private CitizensTraitFactory traitFactory; - - @Override - public NPCRegistry createAnonymousNPCRegistry(NPCDataStore store) { - return new CitizensNPCRegistry(store); - } - - @Override - public NPCRegistry createNamedNPCRegistry(String name, NPCDataStore store) { - NPCRegistry created = new CitizensNPCRegistry(store); - storedRegistries.put(name, created); - return created; - } - - private NPCDataStore createStorage(File folder) { - Storage saves = null; - String type = Setting.STORAGE_TYPE.asString(); - if (type.equalsIgnoreCase("nbt")) { - saves = new NBTStorage(new File(folder + File.separator + Setting.STORAGE_FILE.asString()), - "Citizens NPC Storage"); - } - if (saves == null) { - saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); - } - if (!saves.load()) - return null; - return SimpleNPCDataStore.create(saves); - } - - private void despawnNPCs() { - Iterator itr = npcRegistry.iterator(); - while (itr.hasNext()) { - NPC npc = itr.next(); - try { - npc.despawn(DespawnReason.RELOAD); - } catch (Throwable e) { - e.printStackTrace(); - // ensure that all entities are despawned - } - itr.remove(); - } - } - - private void enableSubPlugins() { - File root = new File(getDataFolder(), Setting.SUBPLUGIN_FOLDER.asString()); - if (!root.exists() || !root.isDirectory()) - return; - File[] files = root.listFiles(); - for (File file : files) { - Plugin plugin; - try { - plugin = Bukkit.getPluginManager().loadPlugin(file); - } catch (Exception e) { - continue; - } - if (plugin == null) - continue; - // code beneath modified from CraftServer - try { - Messaging.logTr(Messages.LOADING_SUB_PLUGIN, plugin.getDescription().getFullName()); - plugin.onLoad(); - } catch (Throwable ex) { - Messaging.severeTr(Messages.ERROR_INITALISING_SUB_PLUGIN, ex.getMessage(), - plugin.getDescription().getFullName()); - ex.printStackTrace(); - } - } - NMS.loadPlugins(); - } - - public CommandInfo getCommandInfo(String rootCommand, String modifier) { - return commands.getCommand(rootCommand, modifier); - } - - public Iterable getCommands(String base) { - return commands.getCommands(base); - } - - @Override - public net.citizensnpcs.api.npc.NPCSelector getDefaultNPCSelector() { - return selector; - } - - @Override - public NPCRegistry getNamedNPCRegistry(String name) { - return storedRegistries.get(name); - } - - @Override - public Iterable getNPCRegistries() { - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - Iterator stored; - - @Override - public boolean hasNext() { - return stored == null ? true : stored.hasNext(); - } - - @Override - public NPCRegistry next() { - if (stored == null) { - stored = storedRegistries.values().iterator(); - return npcRegistry; - } - return stored.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - @Override - public NPCRegistry getNPCRegistry() { - return npcRegistry; - } - - public NPCSelector getNPCSelector() { - return selector; - } - - @Override - public ClassLoader getOwningClassLoader() { - return getClassLoader(); - } - - @Override - public File getScriptFolder() { - return new File(getDataFolder(), "scripts"); - } - - @Override - public SpeechFactory getSpeechFactory() { - return speechFactory; - } - - @Override - public TraitFactory getTraitFactory() { - return traitFactory; - } - - @Override - public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String cmdName, String[] args) { - String modifier = args.length > 0 ? args[0] : ""; - if (!commands.hasCommand(command, modifier) && !modifier.isEmpty()) { - return suggestClosestModifier(sender, command.getName(), modifier); - } - - NPC npc = selector == null ? null : selector.getSelected(sender); - // TODO: change the args supplied to a context style system for - // flexibility (ie. adding more context in the future without - // changing everything) - - Object[] methodArgs = { sender, npc }; - return commands.executeSafe(command, args, sender, methodArgs); - } - - @Override - public void onDisable() { - Bukkit.getPluginManager().callEvent(new CitizensDisableEvent()); - Editor.leaveAll(); - - if (compatible) { - saves.storeAll(npcRegistry); - saves.saveToDiskImmediate(); - despawnNPCs(); - npcRegistry = null; - } - - CitizensAPI.shutdown(); - } - - @Override - public void onEnable() { - setupTranslator(); - CitizensAPI.setImplementation(this); - config = new Settings(getDataFolder()); - // Disable if the server is not using the compatible Minecraft version - String mcVersion = Util.getMinecraftRevision(); - compatible = true; - try { - NMS.loadBridge(mcVersion); - } catch (Exception e) { - compatible = false; - if (Messaging.isDebugging()) { - e.printStackTrace(); - } - Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion); - getServer().getPluginManager().disablePlugin(this); - return; - } - registerScriptHelpers(); - - saves = createStorage(getDataFolder()); - if (saves == null) { - Messaging.severeTr(Messages.FAILED_LOAD_SAVES); - getServer().getPluginManager().disablePlugin(this); - return; - } - - npcRegistry = new CitizensNPCRegistry(saves); - traitFactory = new CitizensTraitFactory(); - selector = new NPCSelector(this); - speechFactory = new CitizensSpeechFactory(); - speechFactory.register(Chat.class, "chat"); - - getServer().getPluginManager().registerEvents(new EventListen(storedRegistries), this); - - if (Setting.NPC_COST.asDouble() > 0) { - setupEconomy(); - } - - registerCommands(); - enableSubPlugins(); - - // Setup NPCs after all plugins have been enabled (allows for multiworld - // support and for NPCs to properly register external settings) - if (getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - @Override - public void run() { - saves.loadInto(npcRegistry); - Messaging.logTr(Messages.NUM_LOADED_NOTIFICATION, Iterables.size(npcRegistry), "?"); - startMetrics(); - scheduleSaveTask(Setting.SAVE_TASK_DELAY.asInt()); - Bukkit.getPluginManager().callEvent(new CitizensEnableEvent()); - new PlayerUpdateTask().runTaskTimer(Citizens.this, 0, 1); - } - }, 1) == -1) { - Messaging.severeTr(Messages.LOAD_TASK_NOT_SCHEDULED); - getServer().getPluginManager().disablePlugin(this); - } - } - - @Override - public void onImplementationChanged() { - Messaging.severeTr(Messages.CITIZENS_IMPLEMENTATION_DISABLED); - Bukkit.getPluginManager().disablePlugin(this); - } - - public void registerCommandClass(Class clazz) { - try { - commands.register(clazz); - } catch (Throwable ex) { - Messaging.logTr(Messages.CITIZENS_INVALID_COMMAND_CLASS); - ex.printStackTrace(); - } - } - - private void registerCommands() { - commands.setInjector(new Injector(this)); - // Register command classes - commands.register(AdminCommands.class); - commands.register(EditorCommands.class); - commands.register(NPCCommands.class); - commands.register(TemplateCommands.class); - commands.register(TraitCommands.class); - commands.register(WaypointCommands.class); - } - - private void registerScriptHelpers() { - ScriptCompiler compiler = CitizensAPI.getScriptCompiler(); - compiler.registerGlobalContextProvider(new EventRegistrar(this)); - compiler.registerGlobalContextProvider(new ObjectProvider("plugin", this)); - } - - public void reload() throws NPCLoadException { - Editor.leaveAll(); - config.reload(); - despawnNPCs(); - ProfileFetcher.reset(); - Skin.clearCache(); - getServer().getPluginManager().callEvent(new CitizensPreReloadEvent()); - - saves = createStorage(getDataFolder()); - saves.loadInto(npcRegistry); - - getServer().getPluginManager().callEvent(new CitizensReloadEvent()); - } - - @Override - public void removeNamedNPCRegistry(String name) { - storedRegistries.remove(name); - } - - private void scheduleSaveTask(int delay) { - Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { - @Override - public void run() { - storeNPCs(); - saves.saveToDisk(); - } - }, delay, delay); - } - - private void setupEconomy() { - try { - RegisteredServiceProvider provider = Bukkit.getServicesManager().getRegistration(Economy.class); - if (provider != null && provider.getProvider() != null) { - Economy economy = provider.getProvider(); - Bukkit.getPluginManager().registerEvents(new PaymentListener(economy), this); - } - } catch (NoClassDefFoundError e) { - Messaging.logTr(Messages.ERROR_LOADING_ECONOMY); - } - } - - private void setupTranslator() { - Locale locale = Locale.getDefault(); - String setting = Setting.LOCALE.asString(); - if (!setting.isEmpty()) { - String[] parts = setting.split("[\\._]"); - switch (parts.length) { - case 1: - locale = new Locale(parts[0]); - break; - case 2: - locale = new Locale(parts[0], parts[1]); - break; - case 3: - locale = new Locale(parts[0], parts[1], parts[2]); - break; - default: - break; - } - } - Translator.setInstance(new File(getDataFolder(), "lang"), locale); - } - - private void startMetrics() { - try { - Metrics metrics = new Metrics(Citizens.this); - if (metrics.isOptOut()) - return; - metrics.addCustomData(new Metrics.Plotter("Total NPCs") { - @Override - public int getValue() { - if (npcRegistry == null) - return 0; - return Iterables.size(npcRegistry); - } - }); - metrics.addCustomData(new Metrics.Plotter("Total goals") { - @Override - public int getValue() { - if (npcRegistry == null) - return 0; - int goalCount = 0; - for (NPC npc : npcRegistry) { - goalCount += Iterables.size(npc.getDefaultGoalController()); - } - return goalCount; - } - }); - traitFactory.addPlotters(metrics.createGraph("traits")); - metrics.start(); - } catch (IOException e) { - Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage()); - } - } - - public void storeNPCs() { - if (saves == null) - return; - for (NPC npc : npcRegistry) { - saves.store(npc); - } - } - - public void storeNPCs(CommandContext args) { - storeNPCs(); - boolean async = args.hasFlag('a'); - if (async) { - saves.saveToDisk(); - } else { - saves.saveToDiskImmediate(); - } - } - - private boolean suggestClosestModifier(CommandSender sender, String command, String modifier) { - String closest = commands.getClosestCommandModifier(command, modifier); - if (!closest.isEmpty()) { - sender.sendMessage(ChatColor.GRAY + Messaging.tr(Messages.UNKNOWN_COMMAND)); - sender.sendMessage(StringHelper.wrap(" /") + command + " " + StringHelper.wrap(closest)); - return true; - } - return false; - } -} diff --git a/main/java/net/citizensnpcs/EventListen.java b/main/java/net/citizensnpcs/EventListen.java deleted file mode 100644 index 4f3128dcc..000000000 --- a/main/java/net/citizensnpcs/EventListen.java +++ /dev/null @@ -1,614 +0,0 @@ -package net.citizensnpcs; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Minecart; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityCombustByBlockEvent; -import org.bukkit.event.entity.EntityCombustByEntityEvent; -import org.bukkit.event.entity.EntityCombustEvent; -import org.bukkit.event.entity.EntityDamageByBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityTargetEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.event.vehicle.VehicleDestroyEvent; -import org.bukkit.event.vehicle.VehicleEnterEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.event.world.WorldUnloadEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.meta.SkullMeta; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scoreboard.Team; - -import com.google.common.base.Predicates; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Iterables; -import com.google.common.collect.ListMultimap; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; - -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.ai.event.NavigationBeginEvent; -import net.citizensnpcs.api.ai.event.NavigationCompleteEvent; -import net.citizensnpcs.api.event.CitizensDeserialiseMetaEvent; -import net.citizensnpcs.api.event.CitizensPreReloadEvent; -import net.citizensnpcs.api.event.CitizensSerialiseMetaEvent; -import net.citizensnpcs.api.event.CommandSenderCreateNPCEvent; -import net.citizensnpcs.api.event.DespawnReason; -import net.citizensnpcs.api.event.EntityTargetNPCEvent; -import net.citizensnpcs.api.event.NPCCombustByBlockEvent; -import net.citizensnpcs.api.event.NPCCombustByEntityEvent; -import net.citizensnpcs.api.event.NPCCombustEvent; -import net.citizensnpcs.api.event.NPCDamageByBlockEvent; -import net.citizensnpcs.api.event.NPCDamageByEntityEvent; -import net.citizensnpcs.api.event.NPCDamageEntityEvent; -import net.citizensnpcs.api.event.NPCDamageEvent; -import net.citizensnpcs.api.event.NPCDeathEvent; -import net.citizensnpcs.api.event.NPCDespawnEvent; -import net.citizensnpcs.api.event.NPCLeftClickEvent; -import net.citizensnpcs.api.event.NPCRightClickEvent; -import net.citizensnpcs.api.event.NPCSpawnEvent; -import net.citizensnpcs.api.event.PlayerCreateNPCEvent; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.trait.trait.Owner; -import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.editor.Editor; -import net.citizensnpcs.npc.skin.SkinUpdateTracker; -import net.citizensnpcs.trait.Controllable; -import net.citizensnpcs.trait.CurrentLocation; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.NMS; - -public class EventListen implements Listener { - private final NPCRegistry npcRegistry = CitizensAPI.getNPCRegistry(); - private final Map registries; - private final SkinUpdateTracker skinUpdateTracker; - private final ListMultimap toRespawn = ArrayListMultimap.create(); - - EventListen(Map registries) { - this.registries = registries; - this.skinUpdateTracker = new SkinUpdateTracker(npcRegistry, registries); - } - - private void checkCreationEvent(CommandSenderCreateNPCEvent event) { - if (event.getCreator().hasPermission("citizens.admin.avoid-limits")) - return; - int limit = Setting.DEFAULT_NPC_LIMIT.asInt(); - int maxChecks = Setting.MAX_NPC_LIMIT_CHECKS.asInt(); - for (int i = maxChecks; i >= 0; i--) { - if (!event.getCreator().hasPermission("citizens.npc.limit." + i)) - continue; - limit = i; - break; - } - if (limit < 0) - return; - int owned = 0; - for (NPC npc : npcRegistry) { - if (!event.getNPC().equals(npc) && npc.hasTrait(Owner.class) - && npc.getTrait(Owner.class).isOwnedBy(event.getCreator())) - owned++; - } - int wouldOwn = owned + 1; - if (wouldOwn > limit) { - event.setCancelled(true); - event.setCancelReason(Messaging.tr(Messages.OVER_NPC_LIMIT, limit)); - } - } - - private Iterable getAllNPCs() { - return Iterables.filter(Iterables. concat(npcRegistry, Iterables.concat(registries.values())), - Predicates.notNull()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onChunkLoad(ChunkLoadEvent event) { - respawnAllFromCoord(toCoord(event.getChunk())); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onChunkUnload(ChunkUnloadEvent event) { - ChunkCoord coord = toCoord(event.getChunk()); - Location loc = new Location(null, 0, 0, 0); - for (NPC npc : getAllNPCs()) { - if (npc == null || !npc.isSpawned()) - continue; - loc = npc.getEntity().getLocation(loc); - boolean sameChunkCoordinates = coord.z == loc.getBlockZ() >> 4 && coord.x == loc.getBlockX() >> 4; - if (!sameChunkCoordinates || !event.getWorld().equals(loc.getWorld())) - continue; - if (!npc.despawn(DespawnReason.CHUNK_UNLOAD)) { - event.setCancelled(true); - if (Messaging.isDebugging()) { - Messaging.debug("Cancelled chunk unload at [" + coord.x + "," + coord.z + "]"); - } - respawnAllFromCoord(coord); - return; - } - toRespawn.put(coord, npc); - if (Messaging.isDebugging()) { - Messaging.debug("Despawned id", npc.getId(), - "due to chunk unload at [" + coord.x + "," + coord.z + "]"); - } - } - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onCitizensReload(CitizensPreReloadEvent event) { - skinUpdateTracker.reset(); - toRespawn.clear(); - } - - @EventHandler(ignoreCancelled = true) - public void onCommandSenderCreateNPC(CommandSenderCreateNPCEvent event) { - checkCreationEvent(event); - } - - /* - * Entity events - */ - @EventHandler - public void onEntityCombust(EntityCombustEvent event) { - NPC npc = npcRegistry.getNPC(event.getEntity()); - if (npc == null) - return; - event.setCancelled(npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)); - if (event instanceof EntityCombustByEntityEvent) { - Bukkit.getPluginManager().callEvent(new NPCCombustByEntityEvent((EntityCombustByEntityEvent) event, npc)); - } else if (event instanceof EntityCombustByBlockEvent) { - Bukkit.getPluginManager().callEvent(new NPCCombustByBlockEvent((EntityCombustByBlockEvent) event, npc)); - } else { - Bukkit.getPluginManager().callEvent(new NPCCombustEvent(event, npc)); - } - } - - @EventHandler - public void onEntityDamage(EntityDamageEvent event) { - NPC npc = npcRegistry.getNPC(event.getEntity()); - - if (npc == null) { - if (event instanceof EntityDamageByEntityEvent) { - npc = npcRegistry.getNPC(((EntityDamageByEntityEvent) event).getDamager()); - if (npc == null) - return; - event.setCancelled(!npc.data().get(NPC.DAMAGE_OTHERS_METADATA, true)); - NPCDamageEntityEvent damageEvent = new NPCDamageEntityEvent(npc, (EntityDamageByEntityEvent) event); - Bukkit.getPluginManager().callEvent(damageEvent); - } - return; - } - event.setCancelled(npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)); - if (event instanceof EntityDamageByEntityEvent) { - NPCDamageByEntityEvent damageEvent = new NPCDamageByEntityEvent(npc, (EntityDamageByEntityEvent) event); - Bukkit.getPluginManager().callEvent(damageEvent); - - if (!damageEvent.isCancelled() || !(damageEvent.getDamager() instanceof Player)) - return; - Player damager = (Player) damageEvent.getDamager(); - - NPCLeftClickEvent leftClickEvent = new NPCLeftClickEvent(npc, damager); - Bukkit.getPluginManager().callEvent(leftClickEvent); - } else if (event instanceof EntityDamageByBlockEvent) { - Bukkit.getPluginManager().callEvent(new NPCDamageByBlockEvent(npc, (EntityDamageByBlockEvent) event)); - } else { - Bukkit.getPluginManager().callEvent(new NPCDamageEvent(npc, event)); - } - } - - @EventHandler(ignoreCancelled = true) - public void onEntityDeath(EntityDeathEvent event) { - final NPC npc = npcRegistry.getNPC(event.getEntity()); - if (npc == null) { - return; - } - - if (!npc.data().get(NPC.DROPS_ITEMS_METADATA, false)) { - event.getDrops().clear(); - } - - final Location location = npc.getEntity().getLocation(); - Bukkit.getPluginManager().callEvent(new NPCDeathEvent(npc, event)); - npc.despawn(DespawnReason.DEATH); - - if (npc.data().has(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA)) { - String teamName = npc.data().get(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA); - Team team = Bukkit.getScoreboardManager().getMainScoreboard().getTeam(teamName); - if (team != null) { - team.unregister(); - } - - npc.data().remove(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA); - } - - if (npc.data().get(NPC.RESPAWN_DELAY_METADATA, -1) >= 0) { - int delay = npc.data().get(NPC.RESPAWN_DELAY_METADATA, -1); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - if (!npc.isSpawned() && npc.getOwningRegistry().getByUniqueId(npc.getUniqueId()) == npc) { - npc.spawn(location); - } - } - }, delay + 2); - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onEntitySpawn(CreatureSpawnEvent event) { - if (event.isCancelled() && npcRegistry.isNPC(event.getEntity())) { - event.setCancelled(false); - } - } - - @EventHandler - public void onEntityTarget(EntityTargetEvent event) { - NPC npc = npcRegistry.getNPC(event.getTarget()); - if (npc == null) - return; - event.setCancelled( - !npc.data().get(NPC.TARGETABLE_METADATA, !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))); - Bukkit.getPluginManager().callEvent(new EntityTargetNPCEvent(event, npc)); - } - - @EventHandler - public void onMetaDeserialise(CitizensDeserialiseMetaEvent event) { - if (event.getKey().keyExists("skull")) { - String owner = event.getKey().getString("skull.owner", ""); - UUID uuid = event.getKey().keyExists("skull.uuid") ? UUID.fromString(event.getKey().getString("skull.uuid")) - : null; - if (owner.isEmpty() && uuid == null) { - return; - } - GameProfile profile = new GameProfile(uuid, owner); - for (DataKey sub : event.getKey().getRelative("skull.properties").getSubKeys()) { - String propertyName = sub.name(); - for (DataKey property : sub.getIntegerSubKeys()) { - profile.getProperties().put(propertyName, - new Property(property.getString("name"), property.getString("value"), - property.keyExists("signature") ? property.getString("signature") : null)); - } - } - SkullMeta meta = (SkullMeta) Bukkit.getItemFactory().getItemMeta(Material.SKULL_ITEM); - NMS.setProfile(meta, profile); - event.getItemStack().setItemMeta(meta); - } - } - - @EventHandler - public void onMetaSerialise(CitizensSerialiseMetaEvent event) { - if (!(event.getMeta() instanceof SkullMeta)) - return; - SkullMeta meta = (SkullMeta) event.getMeta(); - GameProfile profile = NMS.getProfile(meta); - if (profile == null) - return; - if (profile.getName() != null) { - event.getKey().setString("skull.owner", profile.getName()); - } - if (profile.getId() != null) { - event.getKey().setString("skull.uuid", profile.getId().toString()); - } - if (profile.getProperties() != null) { - for (Entry> entry : profile.getProperties().asMap().entrySet()) { - DataKey relative = event.getKey().getRelative("skull.properties." + entry.getKey()); - int i = 0; - for (Property value : entry.getValue()) { - relative.getRelative(i).setString("name", value.getName()); - if (value.getSignature() != null) { - relative.getRelative(i).setString("signature", value.getSignature()); - } - relative.getRelative(i).setString("value", value.getValue()); - i++; - } - } - } - } - - @EventHandler - public void onNavigationBegin(NavigationBeginEvent event) { - skinUpdateTracker.onNPCNavigationBegin(event.getNPC()); - } - - @EventHandler - public void onNavigationComplete(NavigationCompleteEvent event) { - skinUpdateTracker.onNPCNavigationComplete(event.getNPC()); - } - - @EventHandler - public void onNeedsRespawn(NPCNeedsRespawnEvent event) { - ChunkCoord coord = toCoord(event.getSpawnLocation()); - if (toRespawn.containsEntry(coord, event.getNPC())) - return; - Messaging.debug("Stored", event.getNPC().getId(), "for respawn from NPCNeedsRespawnEvent"); - toRespawn.put(coord, event.getNPC()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onNPCDespawn(NPCDespawnEvent event) { - if (event.getReason() == DespawnReason.PLUGIN || event.getReason() == DespawnReason.REMOVAL - || event.getReason() == DespawnReason.RELOAD) { - Messaging.debug("Preventing further respawns of " + event.getNPC().getId() + " due to DespawnReason." - + event.getReason().name()); - if (event.getNPC().getStoredLocation() != null) { - toRespawn.remove(toCoord(event.getNPC().getStoredLocation()), event.getNPC()); - } - } else { - Messaging.debug("Removing " + event.getNPC().getId() + " from skin tracker due to DespawnReason." - + event.getReason().name()); - } - skinUpdateTracker.onNPCDespawn(event.getNPC()); - } - - @EventHandler(ignoreCancelled = true) - public void onNPCSpawn(NPCSpawnEvent event) { - skinUpdateTracker.onNPCSpawn(event.getNPC()); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { - if (npcRegistry.getNPC(event.getPlayer()) == null) - return; - NMS.removeFromServerPlayerList(event.getPlayer()); - // on teleport, player NPCs are added to the server player list. this is - // undesirable as player NPCs are not real players and confuse plugins. - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerChangeWorld(PlayerChangedWorldEvent event) { - skinUpdateTracker.updatePlayer(event.getPlayer(), 20, true); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerCreateNPC(PlayerCreateNPCEvent event) { - checkCreationEvent(event); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerFish(PlayerFishEvent event) { - if (npcRegistry.isNPC(event.getCaught()) && npcRegistry.getNPC(event.getCaught()).isProtected()) { - event.setCancelled(true); - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - NPC npc = npcRegistry.getNPC(event.getRightClicked()); - if (npc == null || event.getHand() == EquipmentSlot.OFF_HAND) { - return; - } - Player player = event.getPlayer(); - NPCRightClickEvent rightClickEvent = new NPCRightClickEvent(npc, player); - Bukkit.getPluginManager().callEvent(rightClickEvent); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerJoin(PlayerJoinEvent event) { - skinUpdateTracker.updatePlayer(event.getPlayer(), 20, true); - } - - // recalculate player NPCs the first time a player moves and every time - // a player moves a certain distance from their last position. - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerMove(final PlayerMoveEvent event) { - skinUpdateTracker.onPlayerMove(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerQuit(PlayerQuitEvent event) { - Editor.leave(event.getPlayer()); - if (event.getPlayer().isInsideVehicle()) { - NPC npc = npcRegistry.getNPC(event.getPlayer().getVehicle()); - if (npc != null) { - event.getPlayer().leaveVehicle(); - } - } - skinUpdateTracker.removePlayer(event.getPlayer().getUniqueId()); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerRespawn(PlayerRespawnEvent event) { - skinUpdateTracker.updatePlayer(event.getPlayer(), 15, true); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerTeleport(final PlayerTeleportEvent event) { - if (event.getCause() == TeleportCause.PLUGIN && !event.getPlayer().hasMetadata("citizens-force-teleporting") - && npcRegistry.getNPC(event.getPlayer()) != null && Setting.TELEPORT_DELAY.asInt() > 0) { - event.setCancelled(true); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - event.getPlayer().setMetadata("citizens-force-teleporting", - new FixedMetadataValue(CitizensAPI.getPlugin(), true)); - event.getPlayer().teleport(event.getTo()); - event.getPlayer().removeMetadata("citizens-force-teleporting", CitizensAPI.getPlugin()); - } - }, Setting.TELEPORT_DELAY.asInt()); - } - skinUpdateTracker.updatePlayer(event.getPlayer(), 15, true); - } - - @EventHandler(ignoreCancelled = true) - public void onProjectileHit(final ProjectileHitEvent event) { - if (!(event.getEntity() instanceof FishHook)) - return; - NMS.removeHookIfNecessary(npcRegistry, (FishHook) event.getEntity()); - new BukkitRunnable() { - int n = 0; - - @Override - public void run() { - if (n++ > 5) { - cancel(); - } - NMS.removeHookIfNecessary(npcRegistry, (FishHook) event.getEntity()); - } - }.runTaskTimer(CitizensAPI.getPlugin(), 0, 1); - } - - @EventHandler - public void onVehicleDestroy(VehicleDestroyEvent event) { - NPC npc = npcRegistry.getNPC(event.getVehicle()); - if (npc == null) { - return; - } - event.setCancelled(npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)); - } - - @EventHandler(ignoreCancelled = true) - public void onVehicleEnter(VehicleEnterEvent event) { - if (!npcRegistry.isNPC(event.getEntered())) - return; - NPC npc = npcRegistry.getNPC(event.getEntered()); - if ((npc.getEntity().getType() == EntityType.HORSE || npc.getEntity().getType() == EntityType.BOAT - || npc.getEntity() instanceof Minecart) && !npc.getTrait(Controllable.class).isEnabled()) { - event.setCancelled(true); - } - } - - @EventHandler(ignoreCancelled = true) - public void onWorldLoad(WorldLoadEvent event) { - for (ChunkCoord chunk : toRespawn.keySet()) { - if (!chunk.worldName.equals(event.getWorld().getName()) - || !event.getWorld().isChunkLoaded(chunk.x, chunk.z)) - continue; - respawnAllFromCoord(chunk); - } - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onWorldUnload(WorldUnloadEvent event) { - for (NPC npc : getAllNPCs()) { - if (npc == null || !npc.isSpawned() || !npc.getEntity().getWorld().equals(event.getWorld())) - continue; - boolean despawned = npc.despawn(DespawnReason.WORLD_UNLOAD); - if (event.isCancelled() || !despawned) { - for (ChunkCoord coord : toRespawn.keySet()) { - if (event.getWorld().getName().equals(coord.worldName)) { - respawnAllFromCoord(coord); - } - } - event.setCancelled(true); - return; - } - if (npc.isSpawned()) { - storeForRespawn(npc); - Messaging.debug("Despawned", npc.getId() + "due to world unload at", event.getWorld().getName()); - } - } - } - - private void respawnAllFromCoord(ChunkCoord coord) { - List ids = toRespawn.get(coord); - for (int i = 0; i < ids.size(); i++) { - NPC npc = ids.get(i); - boolean success = spawn(npc); - if (!success) { - if (Messaging.isDebugging()) { - Messaging.debug("Couldn't respawn id", npc.getId(), - "during chunk event at [" + coord.x + "," + coord.z + "]"); - } - continue; - } - ids.remove(i--); - if (Messaging.isDebugging()) { - Messaging.debug("Spawned id", npc.getId(), "due to chunk event at [" + coord.x + "," + coord.z + "]"); - } - } - } - - private boolean spawn(NPC npc) { - Location spawn = npc.getTrait(CurrentLocation.class).getLocation(); - if (spawn == null) { - if (Messaging.isDebugging()) { - Messaging.debug("Couldn't find a spawn location for despawned NPC id", npc.getId()); - } - return false; - } - return npc.spawn(spawn); - } - - private void storeForRespawn(NPC npc) { - toRespawn.put(toCoord(npc.getEntity().getLocation()), npc); - } - - private ChunkCoord toCoord(Chunk chunk) { - return new ChunkCoord(chunk); - } - - private ChunkCoord toCoord(Location loc) { - return new ChunkCoord(loc.getWorld().getName(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4); - } - - private static class ChunkCoord { - private final String worldName; - private final int x; - private final int z; - - private ChunkCoord(Chunk chunk) { - this(chunk.getWorld().getName(), chunk.getX(), chunk.getZ()); - } - - private ChunkCoord(String worldName, int x, int z) { - this.x = x; - this.z = z; - this.worldName = worldName; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ChunkCoord other = (ChunkCoord) obj; - if (worldName == null) { - if (other.worldName != null) { - return false; - } - } else if (!worldName.equals(other.worldName)) { - return false; - } - return x == other.x && z == other.z; - } - - @Override - public int hashCode() { - final int prime = 31; - return prime * (prime * (prime + ((worldName == null) ? 0 : worldName.hashCode())) + x) + z; - } - } -} diff --git a/main/java/net/citizensnpcs/Metrics.java b/main/java/net/citizensnpcs/Metrics.java deleted file mode 100644 index 4ba2114a7..000000000 --- a/main/java/net/citizensnpcs/Metrics.java +++ /dev/null @@ -1,787 +0,0 @@ -/* - * Copyright 2011-2013 Tyler Blair. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and contributors and should not be interpreted as representing official policies, - * either expressed or implied, of anybody else. - */ -package net.citizensnpcs; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.Proxy; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; -import java.util.logging.Level; -import java.util.zip.GZIPOutputStream; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.scheduler.BukkitTask; - -public class Metrics { - /** - * The plugin configuration file - */ - private final YamlConfiguration configuration; - - /** - * The plugin configuration file - */ - private final File configurationFile; - - /** - * Debug mode - */ - private final boolean debug; - - /** - * All of the custom graphs to submit to metrics - */ - private final Set graphs = Collections.synchronizedSet(new HashSet()); - - /** - * Unique server id - */ - private final String guid; - - /** - * Lock for synchronization - */ - private final Object optOutLock = new Object(); - - /** - * The plugin this metrics submits for - */ - private final Plugin plugin; - - /** - * The scheduled task - */ - private volatile BukkitTask task = null; - - public Metrics(final Plugin plugin) throws IOException { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } - - this.plugin = plugin; - - // load the config - configurationFile = getConfigFile(); - configuration = YamlConfiguration.loadConfiguration(configurationFile); - - // add some defaults - configuration.addDefault("opt-out", false); - configuration.addDefault("guid", UUID.randomUUID().toString()); - configuration.addDefault("debug", false); - - // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://mcstats.org").copyDefaults(true); - configuration.save(configurationFile); - } - - // Load the guid then - guid = configuration.getString("guid"); - debug = configuration.getBoolean("debug", false); - } - - public void addCustomData(Plotter plotter) { - Graph graph = new Graph(plotter.name); - graph.addPlotter(plotter); - addGraph(graph); - } - - /** - * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend - * - * @param graph - * The name of the graph - */ - public void addGraph(final Graph graph) { - if (graph == null) { - throw new IllegalArgumentException("Graph cannot be null"); - } - - graphs.add(graph); - } - - /** - * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics - * website. Plotters can be added to the graph object returned. - * - * @param name - * The name of the graph - * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given - */ - public Graph createGraph(final String name) { - if (name == null) { - throw new IllegalArgumentException("Graph name cannot be null"); - } - - // Construct the graph object - final Graph graph = new Graph(name); - - // Now we can add our graph - graphs.add(graph); - - // and return back - return graph; - } - - /** - * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. - * - * @throws java.io.IOException - */ - public void disable() throws IOException { - // This has to be synchronized or it can collide with the check in the - // task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set - // it. - if (!isOptOut()) { - configuration.set("opt-out", true); - configuration.save(configurationFile); - } - - // Disable Task, if it is running - if (task != null) { - task.cancel(); - task = null; - } - } - } - - /** - * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. - * - * @throws java.io.IOException - */ - public void enable() throws IOException { - // This has to be synchronized or it can collide with the check in the - // task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set - // it. - if (isOptOut()) { - configuration.set("opt-out", false); - configuration.save(configurationFile); - } - - // Enable Task, if it is not running - if (task == null) { - start(); - } - } - } - - /** - * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status - * - * @return the File object for the config file - */ - public File getConfigFile() { - // I believe the easiest way to get the base folder (e.g craftbukkit set - // via -P) for plugins to use - // is to abuse the plugin object we already have - // plugin.getDataFolder() => base/plugins/PluginA/ - // pluginsFolder => base/plugins/ - // The base is not necessarily relative to the startup directory. - File pluginsFolder = plugin.getDataFolder().getParentFile(); - - // return => base/plugins/PluginMetrics/config.yml - return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); - } - - /** - * Check if mineshafter is present. If it is, we need to bypass it to send POST requests - * - * @return true if mineshafter is installed on the server - */ - private boolean isMineshafterPresent() { - try { - Class.forName("mineshafter.MineServer"); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Has the server owner denied plugin metrics? - * - * @return true if metrics should be opted out of it - */ - public boolean isOptOut() { - synchronized (optOutLock) { - try { - // Reload the metrics file - configuration.load(getConfigFile()); - } catch (IOException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } catch (InvalidConfigurationException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } - return configuration.getBoolean("opt-out", false); - } - } - - /** - * Generic method that posts a plugin to the metrics website - */ - private void postPlugin(final boolean isPing) throws IOException { - // Server software specific section - PluginDescriptionFile description = plugin.getDescription(); - String pluginName = description.getName(); - boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if - // online mode - // is enabled - String pluginVersion = description.getVersion(); - String serverVersion = Bukkit.getVersion(); - int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); - - // END server software specific section -- all code below does not use - // any code outside of this class / Java - - // Construct the post data - StringBuilder json = new StringBuilder(1024); - json.append('{'); - - // The plugin's description file containg all of the plugin data such as - // name, version, author, etc - appendJSONPair(json, "guid", guid); - appendJSONPair(json, "plugin_version", pluginVersion); - appendJSONPair(json, "server_version", serverVersion); - appendJSONPair(json, "players_online", Integer.toString(playersOnline)); - - // New data as of R6 - String osname = System.getProperty("os.name"); - String osarch = System.getProperty("os.arch"); - String osversion = System.getProperty("os.version"); - String java_version = System.getProperty("java.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - // normalize os arch .. amd64 -> x86_64 - if (osarch.equals("amd64")) { - osarch = "x86_64"; - } - - appendJSONPair(json, "osname", osname); - appendJSONPair(json, "osarch", osarch); - appendJSONPair(json, "osversion", osversion); - appendJSONPair(json, "cores", Integer.toString(coreCount)); - appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); - appendJSONPair(json, "java_version", java_version); - - // If we're pinging, append it - if (isPing) { - appendJSONPair(json, "ping", "1"); - } - - if (graphs.size() > 0) { - synchronized (graphs) { - json.append(','); - json.append('"'); - json.append("graphs"); - json.append('"'); - json.append(':'); - json.append('{'); - - boolean firstGraph = true; - - final Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - Graph graph = iter.next(); - - StringBuilder graphJson = new StringBuilder(); - graphJson.append('{'); - - for (Plotter plotter : graph.getPlotters()) { - appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); - } - - graphJson.append('}'); - - if (!firstGraph) { - json.append(','); - } - - json.append(escapeJSON(graph.getName())); - json.append(':'); - json.append(graphJson); - - firstGraph = false; - } - - json.append('}'); - } - } - - // close json - json.append('}'); - - // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); - - // Connect to the website - URLConnection connection; - - // Mineshafter creates a socks proxy, so we can safely bypass it - // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { - connection = url.openConnection(Proxy.NO_PROXY); - } else { - connection = url.openConnection(); - } - - byte[] uncompressed = json.toString().getBytes(); - byte[] compressed = gzip(json.toString()); - - // Headers - connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - - connection.setDoOutput(true); - - if (debug) { - System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length - + " compressed=" + compressed.length); - } - - // Write the data - OutputStream os = connection.getOutputStream(); - os.write(compressed); - os.flush(); - - // Now read the response - final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String response = reader.readLine(); - - // close resources - os.close(); - reader.close(); - - if (response == null || response.startsWith("ERR") || response.startsWith("7")) { - if (response == null) { - response = "null"; - } else if (response.startsWith("7")) { - response = response.substring(response.startsWith("7,") ? 2 : 1); - } - - throw new IOException(response); - } else { - // Is this the first update this hour? - if (response.equals("1") || response.contains("This is your first update this hour")) { - synchronized (graphs) { - final Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - final Graph graph = iter.next(); - - for (Plotter plotter : graph.getPlotters()) { - plotter.reset(); - } - } - } - } - } - } - - /** - * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the - * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 - * ticks. - * - * @return True if statistics measuring is running, otherwise false. - */ - public boolean start() { - synchronized (optOutLock) { - // Did we opt out? - if (isOptOut()) { - return false; - } - - // Is metrics already running? - if (task != null) { - return true; - } - - // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - - private boolean firstPost = true; - - @Override - public void run() { - try { - // This has to be synchronized or it can collide with - // the disable method. - synchronized (optOutLock) { - // Disable Task, if it is running and the server - // owner decided to opt-out - if (isOptOut() && task != null) { - task.cancel(); - task = null; - // Tell all plotters to stop gathering - // information. - for (Graph graph : graphs) { - graph.onOptOut(); - } - } - } - - // We use the inverse of firstPost because if it is the - // first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e - // PING! - postPlugin(!firstPost); - - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (IOException e) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); - } - } - } - }, 0, PING_INTERVAL * 1200); - - return true; - } - } - - /** - * Represents a custom graph on the website - */ - public static class Graph { - - /** - * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is - * rejected - */ - private final String name; - - /** - * The set of plotters that are contained within this graph - */ - private final Set plotters = new LinkedHashSet(); - - private Graph(final String name) { - this.name = name; - } - - /** - * Add a plotter to the graph, which will be used to plot entries - * - * @param plotter - * the plotter to add to the graph - */ - public void addPlotter(final Plotter plotter) { - plotters.add(plotter); - } - - @Override - public boolean equals(final Object object) { - if (!(object instanceof Graph)) { - return false; - } - - final Graph graph = (Graph) object; - return graph.name.equals(name); - } - - /** - * Gets the graph's name - * - * @return the Graph's name - */ - public String getName() { - return name; - } - - /** - * Gets an unmodifiable set of the plotter objects in the graph - * - * @return an unmodifiable {@link java.util.Set} of the plotter objects - */ - public Set getPlotters() { - return Collections.unmodifiableSet(plotters); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - /** - * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. - */ - protected void onOptOut() { - } - - /** - * Remove a plotter from the graph - * - * @param plotter - * the plotter to remove from the graph - */ - public void removePlotter(final Plotter plotter) { - plotters.remove(plotter); - } - } - - /** - * Interface used to collect custom data for a plugin - */ - public static abstract class Plotter { - - /** - * The plot's name - */ - private final String name; - - /** - * Construct a plotter with the default plot name - */ - public Plotter() { - this("Default"); - } - - /** - * Construct a plotter with a specific plot name - * - * @param name - * the name of the plotter to use, which will show up on the website - */ - public Plotter(final String name) { - this.name = name; - } - - @Override - public boolean equals(final Object object) { - if (!(object instanceof Plotter)) { - return false; - } - - final Plotter plotter = (Plotter) object; - return plotter.name.equals(name) && plotter.getValue() == getValue(); - } - - /** - * Get the column name for the plotted point - * - * @return the plotted point's column name - */ - public String getColumnName() { - return name; - } - - /** - * Get the current value for the plotted point. Since this function defers to an external function it may or may - * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called - * from any thread so care should be taken when accessing resources that need to be synchronized. - * - * @return the current value for the point to be plotted. - */ - public abstract int getValue(); - - @Override - public int hashCode() { - return getColumnName().hashCode(); - } - - /** - * Called after the website graphs have been updated - */ - public void reset() { - } - } - - /** - * Appends a json encoded key/value pair to the given string builder. - * - * @param json - * @param key - * @param value - * @throws UnsupportedEncodingException - */ - private static void appendJSONPair(StringBuilder json, String key, String value) - throws UnsupportedEncodingException { - boolean isValueNumeric = false; - - try { - if (value.equals("0") || !value.endsWith("0")) { - Double.parseDouble(value); - isValueNumeric = true; - } - } catch (NumberFormatException e) { - isValueNumeric = false; - } - - if (json.charAt(json.length() - 1) != '{') { - json.append(','); - } - - json.append(escapeJSON(key)); - json.append(':'); - - if (isValueNumeric) { - json.append(value); - } else { - json.append(escapeJSON(value)); - } - } - - /** - * Escape a string to create a valid JSON string - * - * @param text - * @return - */ - private static String escapeJSON(String text) { - StringBuilder builder = new StringBuilder(); - - builder.append('"'); - for (int index = 0; index < text.length(); index++) { - char chr = text.charAt(index); - - switch (chr) { - case '"': - case '\\': - builder.append('\\'); - builder.append(chr); - break; - case '\b': - builder.append("\\b"); - break; - case '\t': - builder.append("\\t"); - break; - case '\n': - builder.append("\\n"); - break; - case '\r': - builder.append("\\r"); - break; - default: - if (chr < ' ') { - String t = "000" + Integer.toHexString(chr); - builder.append("\\u" + t.substring(t.length() - 4)); - } else { - builder.append(chr); - } - break; - } - } - builder.append('"'); - - return builder.toString(); - } - - /** - * GZip compress a string of bytes - * - * @param input - * @return - */ - public static byte[] gzip(String input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gzos = null; - - try { - gzos = new GZIPOutputStream(baos); - gzos.write(input.getBytes("UTF-8")); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (gzos != null) - try { - gzos.close(); - } catch (IOException ignore) { - } - } - - return baos.toByteArray(); - } - - /** - * Encode text as UTF-8 - * - * @param text - * the text to encode - * @return the encoded text, as UTF-8 - */ - private static String urlEncode(final String text) throws UnsupportedEncodingException { - return URLEncoder.encode(text, "UTF-8"); - } - - /** - * The base url of the metrics domain - */ - private static final String BASE_URL = "http://report.mcstats.org"; - - /** - * Interval of time to ping (in minutes) - */ - private static final int PING_INTERVAL = 15; - - /** - * The url used to report a server's status - */ - private static final String REPORT_URL = "/plugin/%s"; - - /** - * The current revision number - */ - private final static int REVISION = 7; -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java b/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java deleted file mode 100644 index b9e1264cc..000000000 --- a/main/java/net/citizensnpcs/NPCNeedsRespawnEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.citizensnpcs; - -import net.citizensnpcs.api.event.NPCEvent; -import net.citizensnpcs.api.npc.NPC; - -import org.bukkit.Location; -import org.bukkit.event.HandlerList; - -public class NPCNeedsRespawnEvent extends NPCEvent { - private final Location spawn; - - public NPCNeedsRespawnEvent(NPC npc, Location at) { - super(npc); - this.spawn = at; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public Location getSpawnLocation() { - return spawn; - } - - private static final HandlerList handlers = new HandlerList(); - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/main/java/net/citizensnpcs/PaymentListener.java b/main/java/net/citizensnpcs/PaymentListener.java deleted file mode 100644 index d237dabb9..000000000 --- a/main/java/net/citizensnpcs/PaymentListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.citizensnpcs; - -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.event.PlayerCreateNPCEvent; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; -import net.milkbowl.vault.economy.Economy; -import net.milkbowl.vault.economy.EconomyResponse; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -import com.google.common.base.Preconditions; - -public class PaymentListener implements Listener { - private final Economy provider; - - public PaymentListener(Economy provider) { - Preconditions.checkNotNull(provider, "provider cannot be null"); - this.provider = provider; - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerCreateNPC(PlayerCreateNPCEvent event) { - boolean hasAccount = provider.hasAccount(event.getCreator()); - if (!hasAccount || event.getCreator().hasPermission("citizens.npc.ignore-cost")) - return; - double cost = Setting.NPC_COST.asDouble(); - EconomyResponse response = provider.withdrawPlayer(event.getCreator(), cost); - if (!response.transactionSuccess()) { - event.setCancelled(true); - event.setCancelReason(response.errorMessage); - return; - } - String formattedCost = provider.format(cost); - Messaging.sendTr(event.getCreator(), Messages.MONEY_WITHDRAWN, formattedCost); - } -} diff --git a/main/java/net/citizensnpcs/Settings.java b/main/java/net/citizensnpcs/Settings.java deleted file mode 100644 index 9da3935d4..000000000 --- a/main/java/net/citizensnpcs/Settings.java +++ /dev/null @@ -1,181 +0,0 @@ -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/main/java/net/citizensnpcs/commands/AdminCommands.java b/main/java/net/citizensnpcs/commands/AdminCommands.java deleted file mode 100644 index 0c77d068b..000000000 --- a/main/java/net/citizensnpcs/commands/AdminCommands.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.citizensnpcs.commands; - -import org.bukkit.command.CommandSender; - -import net.citizensnpcs.Citizens; -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.exception.NPCLoadException; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.StringHelper; - -@Requirements -public class AdminCommands { - private final Citizens plugin; - - public AdminCommands(Citizens plugin) { - this.plugin = plugin; - } - - @Command(aliases = { "citizens" }, desc = "Show basic plugin information", max = 0, permission = "citizens.admin") - public void citizens(CommandContext args, CommandSender sender, NPC npc) { - Messaging.send(sender, - " " + StringHelper.wrapHeader("Citizens v" + plugin.getDescription().getVersion())); - Messaging.send(sender, " <7>-- Written by fullwall and aPunch"); - Messaging.send(sender, " <7>-- Source Code: http://github.com/CitizensDev"); - Messaging.send(sender, " <7>-- Website: " + plugin.getDescription().getWebsite()); - } - - @Command( - aliases = { "citizens" }, - usage = "reload", - desc = "Reload Citizens", - modifiers = { "reload" }, - min = 1, - max = 1, - permission = "citizens.admin") - public void reload(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Messaging.sendTr(sender, Messages.CITIZENS_RELOADING); - try { - plugin.reload(); - Messaging.sendTr(sender, Messages.CITIZENS_RELOADED); - } catch (NPCLoadException ex) { - ex.printStackTrace(); - throw new CommandException(Messages.CITIZENS_RELOAD_ERROR); - } - } - - @Command( - aliases = { "citizens" }, - usage = "save (-a)", - desc = "Save NPCs", - help = Messages.COMMAND_SAVE_HELP, - modifiers = { "save" }, - min = 1, - max = 1, - flags = "a", - permission = "citizens.admin") - public void save(CommandContext args, CommandSender sender, NPC npc) { - Messaging.sendTr(sender, Messages.CITIZENS_SAVING); - plugin.storeNPCs(args); - Messaging.sendTr(sender, Messages.CITIZENS_SAVED); - } -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/commands/EditorCommands.java b/main/java/net/citizensnpcs/commands/EditorCommands.java deleted file mode 100644 index 35249afd1..000000000 --- a/main/java/net/citizensnpcs/commands/EditorCommands.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.citizensnpcs.commands; - -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.editor.CopierEditor; -import net.citizensnpcs.editor.Editor; -import net.citizensnpcs.editor.EquipmentEditor; -import net.citizensnpcs.trait.text.Text; -import net.citizensnpcs.trait.waypoint.Waypoints; - -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -@Requirements(selected = true, ownership = true) -public class EditorCommands { - @Command( - aliases = { "npc" }, - usage = "copier", - desc = "Toggle the NPC copier", - modifiers = { "copier" }, - min = 1, - max = 1, - permission = "citizens.npc.edit.copier") - public void copier(CommandContext args, Player player, NPC npc) { - Editor.enterOrLeave(player, new CopierEditor(player, npc)); - } - - @Command( - aliases = { "npc" }, - usage = "equip", - desc = "Toggle the equipment editor", - modifiers = { "equip" }, - min = 1, - max = 1, - permission = "citizens.npc.edit.equip") - public void equip(CommandContext args, Player player, NPC npc) { - Editor.enterOrLeave(player, new EquipmentEditor(player, npc)); - } - - @Command( - aliases = { "npc" }, - usage = "path", - desc = "Toggle the waypoint editor", - modifiers = { "path" }, - min = 1, - max = 1, - flags = "*", - permission = "citizens.npc.edit.path") - @Requirements(selected = true, ownership = true) - public void path(CommandContext args, CommandSender player, NPC npc) { - Editor editor = npc.getTrait(Waypoints.class).getEditor(player, args); - if (editor == null) - return; - Editor.enterOrLeave((Player) player, editor); - } - - @Command( - aliases = { "npc" }, - usage = "text", - desc = "Toggle the text editor", - modifiers = { "text" }, - min = 1, - max = 1, - permission = "citizens.npc.edit.text") - public void text(CommandContext args, Player player, NPC npc) { - Editor.enterOrLeave(player, npc.getTrait(Text.class).getEditor(player)); - } -} diff --git a/main/java/net/citizensnpcs/commands/NPCCommandSelector.java b/main/java/net/citizensnpcs/commands/NPCCommandSelector.java deleted file mode 100644 index 8cb2c11eb..000000000 --- a/main/java/net/citizensnpcs/commands/NPCCommandSelector.java +++ /dev/null @@ -1,121 +0,0 @@ -package net.citizensnpcs.commands; - -import java.util.List; - -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.CommandMessages; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.command.exception.CommandUsageException; -import net.citizensnpcs.api.command.exception.ServerCommandException; -import net.citizensnpcs.api.command.exception.UnhandledCommandException; -import net.citizensnpcs.api.command.exception.WrappedCommandException; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.Util; - -import org.bukkit.command.CommandSender; -import org.bukkit.conversations.Conversable; -import org.bukkit.conversations.Conversation; -import org.bukkit.conversations.ConversationContext; -import org.bukkit.conversations.ConversationFactory; -import org.bukkit.conversations.NumericPrompt; -import org.bukkit.conversations.Prompt; - -import com.google.common.collect.Lists; - -public class NPCCommandSelector extends NumericPrompt { - private final Callback callback; - private final List choices; - - public NPCCommandSelector(Callback callback, List possible) { - this.callback = callback; - this.choices = possible; - } - - @Override - protected Prompt acceptValidatedInput(ConversationContext context, Number input) { - boolean found = false; - for (NPC npc : choices) { - if (input.intValue() == npc.getId()) { - found = true; - break; - } - } - CommandSender sender = (CommandSender) context.getForWhom(); - if (!found) { - Messaging.sendErrorTr(sender, Messages.SELECTION_PROMPT_INVALID_CHOICE, input); - return this; - } - NPC toSelect = CitizensAPI.getNPCRegistry().getById(input.intValue()); - try { - callback.run(toSelect); - } catch (ServerCommandException ex) { - Messaging.sendTr(sender, CommandMessages.MUST_BE_INGAME); - } catch (CommandUsageException ex) { - Messaging.sendError(sender, ex.getMessage()); - Messaging.sendError(sender, ex.getUsage()); - } catch (UnhandledCommandException ex) { - ex.printStackTrace(); - } catch (WrappedCommandException ex) { - ex.getCause().printStackTrace(); - } catch (CommandException ex) { - Messaging.sendError(sender, ex.getMessage()); - } catch (NumberFormatException ex) { - Messaging.sendErrorTr(sender, CommandMessages.INVALID_NUMBER); - } - return null; - } - - @Override - public String getPromptText(ConversationContext context) { - String text = Messaging.tr(Messages.SELECTION_PROMPT); - for (NPC npc : choices) { - text += "\n - " + npc.getId(); - } - return text; - } - - public static interface Callback { - public void run(NPC npc) throws CommandException; - } - - public static void start(Callback callback, Conversable player, List possible) { - final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false) - .withEscapeSequence("exit").withModality(false) - .withFirstPrompt(new NPCCommandSelector(callback, possible)).buildConversation(player); - conversation.begin(); - } - - public static void startWithCallback(Callback callback, NPCRegistry npcRegistry, CommandSender sender, - CommandContext args, String raw) throws CommandException { - try { - int id = Integer.parseInt(raw); - callback.run(npcRegistry.getById(id)); - return; - } catch (NumberFormatException ex) { - String name = args.getString(1); - List possible = Lists.newArrayList(); - double range = -1; - if (args.hasValueFlag("r")) { - range = Math.abs(args.getFlagDouble("r")); - } - for (NPC test : npcRegistry) { - if (test.getName().equalsIgnoreCase(name)) { - if (range > 0 && test.isSpawned() && !Util.locationWithinRange(args.getSenderLocation(), - test.getEntity().getLocation(), range)) - continue; - possible.add(test); - } - } - if (possible.size() == 1) { - callback.run(possible.get(0)); - } else if (possible.size() > 1) { - NPCCommandSelector.start(callback, (Conversable) sender, possible); - return; - } - } - } -} diff --git a/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/java/net/citizensnpcs/commands/NPCCommands.java deleted file mode 100644 index a9b98da40..000000000 --- a/main/java/net/citizensnpcs/commands/NPCCommands.java +++ /dev/null @@ -1,1997 +0,0 @@ -package net.citizensnpcs.commands; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.UUID; - -import org.apache.commons.lang3.StringUtils; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.DyeColor; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.boss.BarColor; -import org.bukkit.boss.BarFlag; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Ageable; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Guardian; -import org.bukkit.entity.Horse.Color; -import org.bukkit.entity.Horse.Style; -import org.bukkit.entity.Horse.Variant; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Ocelot; -import org.bukkit.entity.Player; -import org.bukkit.entity.Rabbit; -import org.bukkit.entity.Skeleton.SkeletonType; -import org.bukkit.entity.Villager.Profession; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -import net.citizensnpcs.Citizens; -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.ai.speech.SpeechContext; -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.CommandMessages; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.command.exception.NoPermissionsException; -import net.citizensnpcs.api.command.exception.ServerCommandException; -import net.citizensnpcs.api.event.CommandSenderCreateNPCEvent; -import net.citizensnpcs.api.event.DespawnReason; -import net.citizensnpcs.api.event.PlayerCreateNPCEvent; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.trait.Trait; -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.api.util.Colorizer; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.api.util.Paginator; -import net.citizensnpcs.npc.EntityControllers; -import net.citizensnpcs.npc.NPCSelector; -import net.citizensnpcs.npc.Template; -import net.citizensnpcs.npc.skin.SkinnableEntity; -import net.citizensnpcs.trait.Age; -import net.citizensnpcs.trait.Anchors; -import net.citizensnpcs.trait.ArmorStandTrait; -import net.citizensnpcs.trait.BossBarTrait; -import net.citizensnpcs.trait.Controllable; -import net.citizensnpcs.trait.CurrentLocation; -import net.citizensnpcs.trait.Gravity; -import net.citizensnpcs.trait.HorseModifiers; -import net.citizensnpcs.trait.LookClose; -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.ScriptTrait; -import net.citizensnpcs.trait.SheepTrait; -import net.citizensnpcs.trait.SkinLayers; -import net.citizensnpcs.trait.SkinLayers.Layer; -import net.citizensnpcs.trait.SlimeSize; -import net.citizensnpcs.trait.VillagerProfession; -import net.citizensnpcs.trait.WitherTrait; -import net.citizensnpcs.trait.WolfModifiers; -import net.citizensnpcs.trait.ZombieModifier; -import net.citizensnpcs.util.Anchor; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.NMS; -import net.citizensnpcs.util.StringHelper; -import net.citizensnpcs.util.Util; - -@Requirements(selected = true, ownership = true) -public class NPCCommands { - private final NPCRegistry npcRegistry; - private final NPCSelector selector; - - public NPCCommands(Citizens plugin) { - npcRegistry = CitizensAPI.getNPCRegistry(); - selector = plugin.getNPCSelector(); - } - - @Command( - aliases = { "npc" }, - usage = "age [age] (-l)", - desc = "Set the age of a NPC", - help = Messages.COMMAND_AGE_HELP, - flags = "l", - modifiers = { "age" }, - min = 1, - max = 2, - permission = "citizens.npc.age") - public void age(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - if (!npc.isSpawned() || !(npc.getEntity() instanceof Ageable)) - throw new CommandException(Messages.MOBTYPE_CANNOT_BE_AGED); - Age trait = npc.getTrait(Age.class); - - boolean toggleLock = args.hasFlag('l'); - if (toggleLock) { - Messaging.sendTr(sender, trait.toggle() ? Messages.AGE_LOCKED : Messages.AGE_UNLOCKED); - } - if (args.argsLength() <= 1) { - if (!toggleLock) - trait.describe(sender); - return; - } - int age = 0; - try { - age = args.getInteger(1); - if (age > 0) { - throw new CommandException(Messages.INVALID_AGE); - } - Messaging.sendTr(sender, Messages.AGE_SET_NORMAL, npc.getName(), age); - } catch (NumberFormatException ex) { - if (args.getString(1).equalsIgnoreCase("baby")) { - age = -24000; - Messaging.sendTr(sender, Messages.AGE_SET_BABY, npc.getName()); - } else if (args.getString(1).equalsIgnoreCase("adult")) { - age = 0; - Messaging.sendTr(sender, Messages.AGE_SET_ADULT, npc.getName()); - } else - throw new CommandException(Messages.INVALID_AGE); - } - - trait.setAge(age); - } - - @Command( - aliases = { "npc" }, - usage = "anchor (--save [name]|--assume [name]|--remove [name]) (-a)(-c)", - desc = "Changes/Saves/Lists NPC's location anchor(s)", - flags = "ac", - modifiers = { "anchor" }, - min = 1, - max = 3, - permission = "citizens.npc.anchor") - public void anchor(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Anchors trait = npc.getTrait(Anchors.class); - if (args.hasValueFlag("save")) { - if (args.getFlag("save").isEmpty()) - throw new CommandException(Messages.INVALID_ANCHOR_NAME); - - if (args.getSenderLocation() == null) - throw new ServerCommandException(); - - if (args.hasFlag('c')) { - if (trait.addAnchor(args.getFlag("save"), args.getSenderTargetBlockLocation())) { - Messaging.sendTr(sender, Messages.ANCHOR_ADDED); - } else - throw new CommandException(Messages.ANCHOR_ALREADY_EXISTS, args.getFlag("save")); - } else { - if (trait.addAnchor(args.getFlag("save"), args.getSenderLocation())) { - Messaging.sendTr(sender, Messages.ANCHOR_ADDED); - } else - throw new CommandException(Messages.ANCHOR_ALREADY_EXISTS, args.getFlag("save")); - } - } else if (args.hasValueFlag("assume")) { - if (args.getFlag("assume").isEmpty()) - throw new CommandException(Messages.INVALID_ANCHOR_NAME); - - Anchor anchor = trait.getAnchor(args.getFlag("assume")); - if (anchor == null) - throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("assume")); - npc.teleport(anchor.getLocation(), TeleportCause.COMMAND); - } else if (args.hasValueFlag("remove")) { - if (args.getFlag("remove").isEmpty()) - throw new CommandException(Messages.INVALID_ANCHOR_NAME); - if (trait.removeAnchor(trait.getAnchor(args.getFlag("remove")))) - Messaging.sendTr(sender, Messages.ANCHOR_REMOVED); - else - throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("remove")); - } else if (!args.hasFlag('a')) { - Paginator paginator = new Paginator().header("Anchors"); - paginator.addLine("Key: ID Name World Location (X,Y,Z)"); - for (int i = 0; i < trait.getAnchors().size(); i++) { - if (trait.getAnchors().get(i).isLoaded()) { - String line = "" + i + " " + trait.getAnchors().get(i).getName() + " " - + trait.getAnchors().get(i).getLocation().getWorld().getName() + " " - + trait.getAnchors().get(i).getLocation().getBlockX() + ", " - + trait.getAnchors().get(i).getLocation().getBlockY() + ", " - + trait.getAnchors().get(i).getLocation().getBlockZ(); - paginator.addLine(line); - } else { - String[] parts = trait.getAnchors().get(i).getUnloadedValue(); - String line = "" + i + " " + trait.getAnchors().get(i).getName() + " " + parts[0] - + " " + parts[1] + ", " + parts[2] + ", " + parts[3] + " (unloaded)"; - paginator.addLine(line); - } - } - - int page = args.getInteger(1, 1); - if (!paginator.sendPage(sender, page)) - throw new CommandException(Messages.COMMAND_PAGE_MISSING); - } - - // Assume Player's position - if (!args.hasFlag('a')) - return; - if (sender instanceof ConsoleCommandSender) - throw new ServerCommandException(); - npc.teleport(args.getSenderLocation(), TeleportCause.COMMAND); - } - - @Command( - aliases = { "npc" }, - usage = "armorstand --visible [visible] --small [small] --gravity [gravity] --arms [arms] --baseplate [baseplate]", - desc = "Edit armorstand properties", - modifiers = { "armorstand" }, - min = 1, - max = 1) - @Requirements(selected = true, ownership = true, types = EntityType.ARMOR_STAND) - public void armorstand(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - ArmorStandTrait trait = npc.getTrait(ArmorStandTrait.class); - if (args.hasValueFlag("visible")) { - trait.setVisible(Boolean.valueOf(args.getFlag("visible"))); - } - if (args.hasValueFlag("small")) { - trait.setSmall(Boolean.valueOf(args.getFlag("small"))); - } - if (args.hasValueFlag("gravity")) { - trait.setGravity(Boolean.valueOf(args.getFlag("gravity"))); - } - if (args.hasValueFlag("arms")) { - trait.setHasArms(Boolean.valueOf(args.getFlag("arms"))); - } - if (args.hasValueFlag("baseplate")) { - trait.setHasBaseplate(Boolean.valueOf(args.getFlag("baseplate"))); - } - } - - @Command( - aliases = { "npc" }, - usage = "bossbar --color [color] --title [title] --visible [visible] --flags [flags]", - desc = "Edit bossbar properties", - modifiers = { "bossbar" }, - min = 1, - max = 1) - @Requirements(selected = true, ownership = true, types = { EntityType.WITHER, EntityType.ENDER_DRAGON }) - public void bossbar(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - BossBarTrait trait = npc.getTrait(BossBarTrait.class); - if (args.hasValueFlag("color")) { - BarColor color = Util.matchEnum(BarColor.values(), args.getFlag("color")); - trait.setColor(color); - } - if (args.hasValueFlag("title")) { - trait.setTitle(args.getFlag("title")); - } - if (args.hasValueFlag("visible")) { - trait.setVisible(Boolean.parseBoolean(args.getFlag("visible"))); - } - if (args.hasValueFlag("flags")) { - List flags = Lists.newArrayList(); - for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(args.getFlag("flags"))) { - BarFlag flag = Util.matchEnum(BarFlag.values(), s); - if (flag != null) { - flags.add(flag); - } - } - trait.setFlags(flags); - } - } - - @Command( - aliases = { "npc" }, - usage = "collidable", - desc = "Toggles an NPC's collidability", - modifiers = { "collidable" }, - min = 1, - max = 1, - permission = "citizens.npc.collidable") - @Requirements(ownership = true, selected = true, types = { EntityType.PLAYER }) - public void collidable(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - npc.data().setPersistent(NPC.COLLIDABLE_METADATA, !npc.data().get(NPC.COLLIDABLE_METADATA, true)); - Messaging.sendTr(sender, - npc.data().get(NPC.COLLIDABLE_METADATA) ? Messages.COLLIDABLE_SET : Messages.COLLIDABLE_UNSET, - npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "controllable|control (-m(ount),-y,-n,-o)", - desc = "Toggles whether the NPC can be ridden and controlled", - modifiers = { "controllable", "control" }, - min = 1, - max = 1, - flags = "myno") - public void controllable(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - if ((npc.isSpawned() && !sender.hasPermission( - "citizens.npc.controllable." + npc.getEntity().getType().name().toLowerCase().replace("_", ""))) - || !sender.hasPermission("citizens.npc.controllable")) - throw new NoPermissionsException(); - if (!npc.hasTrait(Controllable.class)) { - npc.addTrait(new Controllable(false)); - } - Controllable trait = npc.getTrait(Controllable.class); - boolean enabled = trait.toggle(); - if (args.hasFlag('y')) { - enabled = trait.setEnabled(true); - } else if (args.hasFlag('n')) { - enabled = trait.setEnabled(false); - } - trait.setOwnerRequired(args.hasFlag('o')); - String key = enabled ? Messages.CONTROLLABLE_SET : Messages.CONTROLLABLE_REMOVED; - Messaging.sendTr(sender, key, npc.getName()); - if (enabled && args.hasFlag('m') && sender instanceof Player) { - trait.mount((Player) sender); - } - } - - @Command( - aliases = { "npc" }, - usage = "copy (--name newname)", - desc = "Copies an NPC", - modifiers = { "copy" }, - min = 1, - max = 1, - permission = "citizens.npc.copy") - public void copy(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String name = args.getFlag("name", npc.getFullName()); - NPC copy = npc.clone(); - if (!copy.getFullName().equals(name)) { - copy.setName(name); - } - - if (copy.isSpawned() && args.getSenderLocation() != null) { - Location location = args.getSenderLocation(); - location.getChunk().load(); - copy.teleport(location, TeleportCause.COMMAND); - copy.getTrait(CurrentLocation.class).setLocation(location); - } - - CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, copy) - : new CommandSenderCreateNPCEvent(sender, copy); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - event.getNPC().destroy(); - String reason = "Couldn't create NPC."; - if (!event.getCancelReason().isEmpty()) - reason += " Reason: " + event.getCancelReason(); - throw new CommandException(reason); - } - - Messaging.sendTr(sender, Messages.NPC_COPIED, npc.getName()); - selector.select(sender, copy); - } - - @Command( - aliases = { "npc" }, - usage = "create [name] ((-b,u) --at (x:y:z:world) --type (type) --trait ('trait1, trait2...') --b (behaviours))", - desc = "Create a new NPC", - flags = "bu", - modifiers = { "create" }, - min = 2, - permission = "citizens.npc.create") - @Requirements - public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String name = Colorizer.parseColors(args.getJoinedStrings(1).trim()); - - EntityType type = EntityType.PLAYER; - if (args.hasValueFlag("type")) { - String inputType = args.getFlag("type"); - type = Util.matchEntityType(inputType); - if (type == null) { - throw new CommandException(Messaging.tr(Messages.NPC_CREATE_INVALID_MOBTYPE, inputType)); - } else if (!EntityControllers.controllerExistsForType(type)) { - throw new CommandException(Messaging.tr(Messages.NPC_CREATE_MISSING_MOBTYPE, inputType)); - } - } - - int nameLength = type == EntityType.PLAYER ? 46 : 64; - if (name.length() > nameLength) { - Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG); - name = name.substring(0, nameLength); - } - if (name.length() == 0) - throw new CommandException(); - - if (!sender.hasPermission("citizens.npc.create.*") && !sender.hasPermission("citizens.npc.createall") - && !sender.hasPermission("citizens.npc.create." + type.name().toLowerCase().replace("_", ""))) - throw new NoPermissionsException(); - - npc = npcRegistry.createNPC(type, name); - String msg = "You created [[" + npc.getName() + "]]"; - - int age = 0; - if (args.hasFlag('b')) { - if (!Ageable.class.isAssignableFrom(type.getEntityClass())) - Messaging.sendErrorTr(sender, Messages.MOBTYPE_CANNOT_BE_AGED, - type.name().toLowerCase().replace("_", "-")); - else { - age = -24000; - msg += " as a baby"; - } - } - - // Initialize necessary traits - if (!Setting.SERVER_OWNS_NPCS.asBoolean()) { - npc.getTrait(Owner.class).setOwner(sender); - } - npc.getTrait(MobType.class).setType(type); - - Location spawnLoc = null; - if (sender instanceof Player) { - spawnLoc = args.getSenderLocation(); - } else if (sender instanceof BlockCommandSender) { - spawnLoc = args.getSenderLocation(); - } - CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, npc) - : new CommandSenderCreateNPCEvent(sender, npc); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - npc.destroy(); - String reason = "Couldn't create NPC."; - if (!event.getCancelReason().isEmpty()) - reason += " Reason: " + event.getCancelReason(); - throw new CommandException(reason); - } - - if (args.hasValueFlag("at")) { - spawnLoc = CommandContext.parseLocation(args.getSenderLocation(), args.getFlag("at")); - } - - if (spawnLoc == null) { - npc.destroy(); - throw new CommandException(Messages.INVALID_SPAWN_LOCATION); - } - - if (!args.hasFlag('u')) { - npc.spawn(spawnLoc); - } - - if (args.hasValueFlag("trait")) { - Iterable parts = Splitter.on(',').trimResults().split(args.getFlag("trait")); - StringBuilder builder = new StringBuilder(); - for (String tr : parts) { - Trait trait = CitizensAPI.getTraitFactory().getTrait(tr); - if (trait == null) - continue; - npc.addTrait(trait); - builder.append(StringHelper.wrap(tr) + ", "); - } - if (builder.length() > 0) - builder.delete(builder.length() - 2, builder.length()); - msg += " with traits " + builder.toString(); - } - - if (args.hasValueFlag("template")) { - Iterable parts = Splitter.on(',').trimResults().split(args.getFlag("template")); - StringBuilder builder = new StringBuilder(); - for (String part : parts) { - Template template = Template.byName(part); - if (template == null) - continue; - template.apply(npc); - builder.append(StringHelper.wrap(part) + ", "); - } - if (builder.length() > 0) - builder.delete(builder.length() - 2, builder.length()); - msg += " with templates " + builder.toString(); - } - - // Set age after entity spawns - if (npc.getEntity() instanceof Ageable) { - npc.getTrait(Age.class).setAge(age); - } - selector.select(sender, npc); - Messaging.send(sender, msg + '.'); - } - - @Command( - aliases = { "npc" }, - usage = "despawn (id)", - desc = "Despawn a NPC", - modifiers = { "despawn" }, - min = 1, - max = 2, - permission = "citizens.npc.despawn") - @Requirements - public void despawn(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException { - NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() { - @Override - public void run(NPC npc) throws CommandException { - if (npc == null) { - throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, args.getString(1)); - } - npc.getTrait(Spawned.class).setSpawned(false); - npc.despawn(DespawnReason.REMOVAL); - Messaging.sendTr(sender, Messages.NPC_DESPAWNED, npc.getName()); - } - }; - if (npc == null || args.argsLength() == 2) { - if (args.argsLength() < 2) { - throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED); - } - NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1)); - } else { - callback.run(npc); - } - } - - @Command( - aliases = { "npc" }, - usage = "flyable (true|false)", - desc = "Toggles or sets an NPC's flyable status", - modifiers = { "flyable" }, - min = 1, - max = 2, - permission = "citizens.npc.flyable") - @Requirements( - selected = true, - ownership = true, - excludedTypes = { EntityType.BAT, EntityType.BLAZE, EntityType.ENDER_DRAGON, EntityType.GHAST, - EntityType.WITHER }) - public void flyable(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - boolean flyable = args.argsLength() == 2 ? args.getString(1).equals("true") : !npc.isFlyable(); - npc.setFlyable(flyable); - flyable = npc.isFlyable(); // may not have applied, eg bats always - // flyable - Messaging.sendTr(sender, flyable ? Messages.FLYABLE_SET : Messages.FLYABLE_UNSET); - } - - @Command( - aliases = { "npc" }, - usage = "gamemode [gamemode]", - desc = "Changes the gamemode", - modifiers = { "gamemode" }, - min = 1, - max = 2, - permission = "citizens.npc.gravity") - @Requirements(selected = true, ownership = true, types = { EntityType.PLAYER }) - public void gamemode(CommandContext args, CommandSender sender, NPC npc) { - Player player = (Player) npc.getEntity(); - if (args.argsLength() == 1) { - Messaging.sendTr(sender, Messages.GAMEMODE_DESCRIBE, npc.getName(), - player.getGameMode().name().toLowerCase()); - return; - } - GameMode mode = null; - try { - int value = args.getInteger(1); - mode = GameMode.getByValue(value); - } catch (NumberFormatException ex) { - try { - mode = GameMode.valueOf(args.getString(1)); - } catch (IllegalArgumentException e) { - } - } - if (mode == null) { - Messaging.sendErrorTr(sender, Messages.GAMEMODE_INVALID, args.getString(1)); - return; - } - player.setGameMode(mode); - Messaging.sendTr(sender, Messages.GAMEMODE_SET, mode.name().toLowerCase()); - } - - @Command( - aliases = { "npc" }, - usage = "glowing --color [minecraft chat color]", - desc = "Toggles an NPC's glowing status", - modifiers = { "glowing" }, - min = 1, - max = 1, - permission = "citizens.npc.glowing") - @Requirements(selected = true, ownership = true) - public void glowing(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - if (args.hasValueFlag("color")) { - ChatColor chatColor = Util.matchEnum(ChatColor.values(), args.getFlag("color")); - if (!(npc.getEntity() instanceof Player)) - throw new CommandException(); - if (chatColor == null) { - npc.data().remove(NPC.GLOWING_COLOR_METADATA); - } else { - npc.data().setPersistent(NPC.GLOWING_COLOR_METADATA, chatColor.name()); - } - Messaging.sendTr(sender, Messages.GLOWING_COLOR_SET, npc.getName(), - chatColor == null ? ChatColor.WHITE + "white" : chatColor + Util.prettyEnum(chatColor)); - return; - } - npc.data().setPersistent(NPC.GLOWING_METADATA, !npc.data().get(NPC.GLOWING_METADATA, false)); - boolean glowing = npc.data().get(NPC.GLOWING_METADATA); - Messaging.sendTr(sender, glowing ? Messages.GLOWING_SET : Messages.GLOWING_UNSET, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "gravity", - desc = "Toggles gravity", - modifiers = { "gravity" }, - min = 1, - max = 1, - permission = "citizens.npc.gravity") - public void gravity(CommandContext args, CommandSender sender, NPC npc) { - boolean enabled = npc.getTrait(Gravity.class).toggle(); - String key = !enabled ? Messages.GRAVITY_ENABLED : Messages.GRAVITY_DISABLED; - Messaging.sendTr(sender, key, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "guardian --elder [true|false]", - desc = "Changes guardian modifiers", - modifiers = { "guardian" }, - min = 1, - max = 2, - permission = "citizens.npc.guardian") - @Requirements(selected = true, ownership = true, types = { EntityType.GUARDIAN }) - public void guardian(CommandContext args, CommandSender sender, NPC npc) { - Guardian guardian = (Guardian) npc.getEntity(); - if (args.hasValueFlag("elder")) { - guardian.setElder(args.getFlag("elder", "false").equals("true") ? true : false); - Messaging.sendTr(sender, guardian.isElder() ? Messages.ELDER_SET : Messages.ELDER_UNSET, npc.getName()); - } - } - - @Command( - aliases = { "npc" }, - usage = "horse (--color color) (--type type) (--style style) (-cb)", - desc = "Sets horse modifiers", - help = "Use the -c flag to make the horse have a chest, or the -b flag to stop them from having a chest.", - modifiers = { "horse" }, - min = 1, - max = 1, - flags = "cb", - permission = "citizens.npc.horse") - @Requirements(selected = true, ownership = true, types = { EntityType.HORSE }) - public void horse(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - HorseModifiers horse = npc.getTrait(HorseModifiers.class); - String output = ""; - if (args.hasFlag('c')) { - horse.setCarryingChest(true); - output += Messaging.tr(Messages.HORSE_CHEST_SET) + " "; - } else if (args.hasFlag('b')) { - horse.setCarryingChest(false); - output += Messaging.tr(Messages.HORSE_CHEST_UNSET) + " "; - } - if (args.hasValueFlag("color") || args.hasValueFlag("colour")) { - String colorRaw = args.getFlag("color", args.getFlag("colour")); - Color color = Util.matchEnum(Color.values(), colorRaw); - if (color == null) { - String valid = Util.listValuesPretty(Color.values()); - throw new CommandException(Messages.INVALID_HORSE_COLOR, valid); - } - horse.setColor(color); - output += Messaging.tr(Messages.HORSE_COLOR_SET, Util.prettyEnum(color)); - } - if (args.hasValueFlag("type")) { - Variant variant = Util.matchEnum(Variant.values(), args.getFlag("type")); - if (variant == null) { - String valid = Util.listValuesPretty(Variant.values()); - throw new CommandException(Messages.INVALID_HORSE_VARIANT, valid); - } - horse.setType(variant); - output += Messaging.tr(Messages.HORSE_TYPE_SET, Util.prettyEnum(variant)); - } - if (args.hasValueFlag("style")) { - Style style = Util.matchEnum(Style.values(), args.getFlag("style")); - if (style == null) { - String valid = Util.listValuesPretty(Style.values()); - throw new CommandException(Messages.INVALID_HORSE_STYLE, valid); - } - horse.setStyle(style); - output += Messaging.tr(Messages.HORSE_STYLE_SET, Util.prettyEnum(style)); - } - if (output.isEmpty()) { - Messaging.sendTr(sender, Messages.HORSE_DESCRIBE, Util.prettyEnum(horse.getColor()), - Util.prettyEnum(horse.getType()), Util.prettyEnum(horse.getStyle())); - } else { - sender.sendMessage(output); - } - } - - @Command( - aliases = { "npc" }, - usage = "id", - desc = "Sends the selected NPC's ID to the sender", - modifiers = { "id" }, - min = 1, - max = 1, - permission = "citizens.npc.id") - public void id(CommandContext args, CommandSender sender, NPC npc) { - Messaging.send(sender, npc.getId()); - } - - @Command( - aliases = { "npc" }, - usage = "inventory", - desc = "Show's an NPC's inventory", - modifiers = { "inventory" }, - min = 1, - max = 1, - permission = "citizens.npc.inventory") - public void inventory(CommandContext args, CommandSender sender, NPC npc) { - npc.getTrait(Inventory.class).openInventory((Player) sender); - } - - @Command( - aliases = { "npc" }, - usage = "item [item] (data)", - desc = "Sets the NPC's item", - modifiers = { "item", }, - min = 2, - max = 3, - flags = "", - permission = "citizens.npc.item") - @Requirements( - selected = true, - ownership = true, - types = { EntityType.DROPPED_ITEM, EntityType.ITEM_FRAME, EntityType.FALLING_BLOCK }) - public void item(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Material mat = Material.matchMaterial(args.getString(1)); - if (mat == null) - throw new CommandException(Messages.UNKNOWN_MATERIAL); - int data = args.getInteger(2, 0); - npc.data().setPersistent(NPC.ITEM_ID_METADATA, mat.name()); - npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data); - switch (npc.getEntity().getType()) { - case DROPPED_ITEM: - ((org.bukkit.entity.Item) npc.getEntity()).getItemStack().setType(mat); - break; - case ITEM_FRAME: - ((ItemFrame) npc.getEntity()).getItem().setType(mat); - break; - default: - break; - } - if (npc.isSpawned()) { - npc.despawn(); - npc.spawn(npc.getStoredLocation()); - } - Messaging.sendTr(sender, Messages.ITEM_SET, Util.prettyEnum(mat)); - } - - @Command( - aliases = { "npc" }, - usage = "leashable", - desc = "Toggles leashability", - modifiers = { "leashable" }, - min = 1, - max = 1, - flags = "t", - permission = "citizens.npc.leashable") - public void leashable(CommandContext args, CommandSender sender, NPC npc) { - boolean vulnerable = !npc.data().get(NPC.LEASH_PROTECTED_METADATA, true); - if (args.hasFlag('t')) { - npc.data().set(NPC.LEASH_PROTECTED_METADATA, vulnerable); - } else { - npc.data().setPersistent(NPC.LEASH_PROTECTED_METADATA, vulnerable); - } - String key = vulnerable ? Messages.LEASHABLE_STOPPED : Messages.LEASHABLE_SET; - Messaging.sendTr(sender, key, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "list (page) ((-a) --owner (owner) --type (type) --char (char) --registry (name))", - desc = "List NPCs", - flags = "a", - modifiers = { "list" }, - min = 1, - max = 2, - permission = "citizens.npc.list") - @Requirements - public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - NPCRegistry source = args.hasValueFlag("registry") ? CitizensAPI.getNamedNPCRegistry(args.getFlag("registry")) - : npcRegistry; - if (source == null) - throw new CommandException(); - List npcs = new ArrayList(); - - if (args.hasFlag('a')) { - for (NPC add : source.sorted()) { - npcs.add(add); - } - } else if (args.getValueFlags().size() == 0 && sender instanceof Player) { - for (NPC add : source.sorted()) { - if (!npcs.contains(add) && add.getTrait(Owner.class).isOwnedBy(sender)) { - npcs.add(add); - } - } - } else { - if (args.hasValueFlag("owner")) { - String name = args.getFlag("owner"); - for (NPC add : source.sorted()) { - if (!npcs.contains(add) && add.getTrait(Owner.class).isOwnedBy(name)) { - npcs.add(add); - } - } - } - - if (args.hasValueFlag("type")) { - EntityType type = Util.matchEntityType(args.getFlag("type")); - - if (type == null) - throw new CommandException(Messages.COMMAND_INVALID_MOBTYPE, type); - - for (NPC add : source) { - if (!npcs.contains(add) && add.getTrait(MobType.class).getType() == type) - npcs.add(add); - } - } - } - - Paginator paginator = new Paginator().header("NPCs"); - paginator.addLine("Key: ID Name"); - for (int i = 0; i < npcs.size(); i += 2) { - String line = "" + npcs.get(i).getId() + " " + npcs.get(i).getName(); - if (npcs.size() >= i + 2) - line += " " + "" + npcs.get(i + 1).getId() + " " + npcs.get(i + 1).getName(); - paginator.addLine(line); - } - - int page = args.getInteger(1, 1); - if (!paginator.sendPage(sender, page)) - throw new CommandException(Messages.COMMAND_PAGE_MISSING); - } - - @Command( - aliases = { "npc" }, - usage = "lookclose", - desc = "Toggle whether a NPC will look when a player is near", - modifiers = { "lookclose", "look", "rotate" }, - min = 1, - max = 1, - permission = "citizens.npc.lookclose") - public void lookClose(CommandContext args, CommandSender sender, NPC npc) { - Messaging.sendTr(sender, - npc.getTrait(LookClose.class).toggle() ? Messages.LOOKCLOSE_SET : Messages.LOOKCLOSE_STOPPED, - npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "minecart (--item item_name(:data)) (--offset offset)", - desc = "Sets minecart item", - modifiers = { "minecart" }, - min = 1, - max = 1, - flags = "", - permission = "citizens.npc.minecart") - @Requirements( - selected = true, - ownership = true, - types = { EntityType.MINECART, EntityType.MINECART_CHEST, EntityType.MINECART_COMMAND, - EntityType.MINECART_FURNACE, EntityType.MINECART_HOPPER, EntityType.MINECART_MOB_SPAWNER, - EntityType.MINECART_TNT }) - public void minecart(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - if (args.hasValueFlag("item")) { - String raw = args.getFlag("item"); - int data = 0; - if (raw.contains(":")) { - int dataIndex = raw.indexOf(':'); - data = Integer.parseInt(raw.substring(dataIndex + 1)); - raw = raw.substring(0, dataIndex); - } - Material material = Material.matchMaterial(raw); - if (material == null) - throw new CommandException(); - npc.data().setPersistent(NPC.MINECART_ITEM_METADATA, material.name()); - npc.data().setPersistent(NPC.MINECART_ITEM_DATA_METADATA, data); - } - if (args.hasValueFlag("offset")) { - npc.data().setPersistent(NPC.MINECART_OFFSET_METADATA, args.getFlagInteger("offset")); - } - - Messaging.sendTr(sender, Messages.MINECART_SET, npc.data().get(NPC.MINECART_ITEM_METADATA, ""), - npc.data().get(NPC.MINECART_ITEM_DATA_METADATA, 0), npc.data().get(NPC.MINECART_OFFSET_METADATA, 0)); - } - - @Command( - aliases = { "npc" }, - usage = "mount (--onnpc )", - desc = "Mounts a controllable NPC", - modifiers = { "mount" }, - min = 1, - max = 1, - permission = "citizens.npc.controllable") - public void mount(CommandContext args, Player player, NPC npc) throws CommandException { - if (args.hasValueFlag("onnpc")) { - NPC mount; - try { - UUID uuid = UUID.fromString(args.getFlag("onnpc")); - mount = CitizensAPI.getNPCRegistry().getByUniqueId(uuid); - } catch (IllegalArgumentException ex) { - mount = CitizensAPI.getNPCRegistry().getById(args.getFlagInteger("onnpc")); - } - if (mount == null || !mount.isSpawned()) { - throw new CommandException(Messaging.tr(Messages.MOUNT_NPC_MUST_BE_SPAWNED, args.getFlag("onnpc"))); - } - if (mount.equals(npc)) { - throw new CommandException(); - } - NMS.mount(mount.getEntity(), npc.getEntity()); - return; - } - boolean enabled = npc.hasTrait(Controllable.class) && npc.getTrait(Controllable.class).isEnabled(); - if (!enabled) { - Messaging.sendTr(player, Messages.NPC_NOT_CONTROLLABLE, npc.getName()); - return; - } - boolean success = npc.getTrait(Controllable.class).mount(player); - if (!success) { - Messaging.sendTr(player, Messages.FAILED_TO_MOUNT_NPC, npc.getName()); - } - } - - @Command( - aliases = { "npc" }, - usage = "moveto x:y:z:world | x y z world", - desc = "Teleports a NPC to a given location", - modifiers = "moveto", - min = 1, - permission = "citizens.npc.moveto") - public void moveto(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - // Spawn the NPC if it isn't spawned to prevent NPEs - if (!npc.isSpawned()) { - npc.spawn(npc.getTrait(CurrentLocation.class).getLocation()); - } - if (!npc.isSpawned()) { - throw new CommandException("NPC could not be spawned."); - } - Location current = npc.getEntity().getLocation(); - Location to; - if (args.argsLength() > 1) { - String[] parts = Iterables.toArray(Splitter.on(':').split(args.getJoinedStrings(1, ':')), String.class); - if (parts.length != 4 && parts.length != 3) - throw new CommandException(Messages.MOVETO_FORMAT); - double x = Double.parseDouble(parts[0]); - double y = Double.parseDouble(parts[1]); - double z = Double.parseDouble(parts[2]); - World world = parts.length == 4 ? Bukkit.getWorld(parts[3]) : current.getWorld(); - if (world == null) - throw new CommandException(Messages.WORLD_NOT_FOUND); - to = new Location(world, x, y, z, current.getYaw(), current.getPitch()); - } else { - to = current.clone(); - if (args.hasValueFlag("x")) - to.setX(args.getFlagDouble("x")); - if (args.hasValueFlag("y")) - to.setY(args.getFlagDouble("y")); - if (args.hasValueFlag("z")) - to.setZ(args.getFlagDouble("z")); - if (args.hasValueFlag("yaw")) - to.setYaw((float) args.getFlagDouble("yaw")); - if (args.hasValueFlag("pitch")) - to.setPitch((float) args.getFlagDouble("pitch")); - if (args.hasValueFlag("world")) { - World world = Bukkit.getWorld(args.getFlag("world")); - if (world == null) - throw new CommandException(Messages.WORLD_NOT_FOUND); - to.setWorld(world); - } - } - - npc.teleport(to, TeleportCause.COMMAND); - Messaging.sendTr(sender, Messages.MOVETO_TELEPORTED, npc.getName(), to); - } - - @Command( - aliases = { "npc" }, - modifiers = { "name" }, - usage = "name", - desc = "Toggle nameplate visibility", - min = 1, - max = 1, - permission = "citizens.npc.name") - @Requirements(selected = true, ownership = true, livingEntity = true) - public void name(CommandContext args, CommandSender sender, NPC npc) { - LivingEntity entity = (LivingEntity) npc.getEntity(); - entity.setCustomNameVisible(!entity.isCustomNameVisible()); - npc.data().setPersistent(NPC.NAMEPLATE_VISIBLE_METADATA, entity.isCustomNameVisible()); - Messaging.sendTr(sender, Messages.NAMEPLATE_VISIBILITY_TOGGLED); - } - - @Command(aliases = { "npc" }, desc = "Show basic NPC information", max = 0, permission = "citizens.npc.info") - public void npc(CommandContext args, CommandSender sender, final NPC npc) { - Messaging.send(sender, StringHelper.wrapHeader(npc.getName())); - Messaging.send(sender, " ID: " + npc.getId()); - Messaging.send(sender, " Type: " + npc.getTrait(MobType.class).getType()); - if (npc.isSpawned()) { - Location loc = npc.getEntity().getLocation(); - String format = " Spawned at %d, %d, %d in world %s"; - Messaging.send(sender, - String.format(format, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), loc.getWorld().getName())); - } - Messaging.send(sender, " Traits"); - for (Trait trait : npc.getTraits()) { - if (CitizensAPI.getTraitFactory().isInternalTrait(trait)) - continue; - String message = " - " + trait.getName(); - Messaging.send(sender, message); - } - } - - @Command( - aliases = { "npc" }, - usage = "ocelot (--type type) (-s(itting), -n(ot sitting))", - desc = "Set the ocelot type of an NPC and whether it is sitting", - modifiers = { "ocelot" }, - min = 1, - max = 1, - flags = "sn", - permission = "citizens.npc.ocelot") - @Requirements(selected = true, ownership = true, types = { EntityType.OCELOT }) - public void ocelot(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - OcelotModifiers trait = npc.getTrait(OcelotModifiers.class); - if (args.hasFlag('s')) { - trait.setSitting(true); - } else if (args.hasFlag('n')) { - trait.setSitting(false); - } - if (args.hasValueFlag("type")) { - Ocelot.Type type = Util.matchEnum(Ocelot.Type.values(), args.getFlag("type")); - if (type == null) { - String valid = Util.listValuesPretty(Ocelot.Type.values()); - throw new CommandException(Messages.INVALID_OCELOT_TYPE, valid); - } - trait.setType(type); - } - } - - @Command( - aliases = { "npc" }, - usage = "owner [name]", - desc = "Set the owner of an NPC", - modifiers = { "owner" }, - min = 1, - max = 2, - permission = "citizens.npc.owner") - public void owner(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Owner ownerTrait = npc.getTrait(Owner.class); - if (args.argsLength() == 1) { - Messaging.sendTr(sender, Messages.NPC_OWNER, npc.getName(), ownerTrait.getOwner()); - return; - } - String name = args.getString(1); - if (ownerTrait.isOwnedBy(name)) - throw new CommandException(Messages.ALREADY_OWNER, name, npc.getName()); - ownerTrait.setOwner(name); - boolean serverOwner = name.equalsIgnoreCase(Owner.SERVER); - Messaging.sendTr(sender, serverOwner ? Messages.OWNER_SET_SERVER : Messages.OWNER_SET, npc.getName(), name); - } - - @Command( - aliases = { "npc" }, - usage = "passive (--set [true|false])", - desc = "Sets whether an NPC damages other entities or not", - modifiers = { "passive" }, - min = 1, - max = 1, - permission = "citizens.npc.passive") - public void passive(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - boolean passive = args.hasValueFlag("set") ? Boolean.parseBoolean(args.getFlag("set")) - : npc.data().get(NPC.DAMAGE_OTHERS_METADATA, true); - npc.data().setPersistent(NPC.DAMAGE_OTHERS_METADATA, !passive); - Messaging.sendTr(sender, passive ? Messages.PASSIVE_SET : Messages.PASSIVE_UNSET, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "pathopt --avoid-water|aw [true|false] --stationary-ticks [ticks] --attack-range [range] --distance-margin [margin]", - desc = "Sets an NPC's pathfinding options", - modifiers = { "pathopt", "po", "patho" }, - min = 1, - max = 1, - permission = "citizens.npc.pathfindingoptions") - public void pathfindingOptions(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - boolean found = false; - if (args.hasValueFlag("avoid-water") || args.hasValueFlag("aw")) { - String raw = args.getFlag("avoid-water", args.getFlag("aw")); - boolean avoid = Boolean.parseBoolean(raw); - npc.getNavigator().getDefaultParameters().avoidWater(avoid); - Messaging.sendTr(sender, avoid ? Messages.PATHFINDING_OPTIONS_AVOID_WATER_SET - : Messages.PATHFINDING_OPTIONS_AVOID_WATER_UNSET, npc.getName()); - found = true; - } - if (args.hasValueFlag("stationary-ticks")) { - int ticks = Integer.parseInt(args.getFlag("stationary-ticks")); - if (ticks < 0) - throw new CommandException(); - npc.getNavigator().getDefaultParameters().stationaryTicks(ticks); - Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_STATIONARY_TICKS_SET, npc.getName(), ticks); - found = true; - } - if (args.hasValueFlag("distance-margin")) { - double distance = Double.parseDouble(args.getFlag("distance-margin")); - if (distance < 0) - throw new CommandException(); - npc.getNavigator().getDefaultParameters().distanceMargin(Math.pow(distance, 2)); - Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_DISTANCE_MARGIN_SET, npc.getName(), distance); - found = true; - } - if (args.hasValueFlag("attack-range")) { - double range = Double.parseDouble(args.getFlag("attack-range")); - if (range < 0) - throw new CommandException(); - npc.getNavigator().getDefaultParameters().attackRange(range); - Messaging.sendTr(sender, Messages.PATHFINDING_OPTIONS_ATTACK_RANGE_SET, npc.getName(), range); - found = true; - } - if (!found) { - throw new CommandException(); - } - } - - @Command( - aliases = { "npc" }, - usage = "pathrange [range]", - desc = "Sets an NPC's pathfinding range", - modifiers = { "pathrange", "pathfindingrange", "prange" }, - min = 2, - max = 2, - permission = "citizens.npc.pathfindingrange") - public void pathfindingRange(CommandContext args, CommandSender sender, NPC npc) { - double range = Math.max(1, args.getDouble(1)); - npc.getNavigator().getDefaultParameters().range((float) range); - Messaging.sendTr(sender, Messages.PATHFINDING_RANGE_SET, range); - } - - @Command( - aliases = { "npc" }, - usage = "playerlist (-a,r)", - desc = "Sets whether the NPC is put in the playerlist", - modifiers = { "playerlist" }, - min = 1, - max = 1, - flags = "ar", - permission = "citizens.npc.playerlist") - @Requirements(selected = true, ownership = true, types = EntityType.PLAYER) - public void playerlist(CommandContext args, CommandSender sender, NPC npc) { - boolean remove = !npc.data().get("removefromplayerlist", Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()); - if (args.hasFlag('a')) { - remove = false; - } else if (args.hasFlag('r')) { - remove = true; - } - npc.data().setPersistent("removefromplayerlist", remove); - if (npc.isSpawned()) { - npc.despawn(DespawnReason.PENDING_RESPAWN); - npc.spawn(npc.getTrait(CurrentLocation.class).getLocation()); - NMS.addOrRemoveFromPlayerList(npc.getEntity(), remove); - } - Messaging.sendTr(sender, remove ? Messages.REMOVED_FROM_PLAYERLIST : Messages.ADDED_TO_PLAYERLIST, - npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "pose (--save [name]|--assume [name]|--remove [name]) (-a)", - desc = "Changes/Saves/Lists NPC's head pose(s)", - flags = "a", - modifiers = { "pose" }, - min = 1, - max = 2, - permission = "citizens.npc.pose") - public void pose(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Poses trait = npc.getTrait(Poses.class); - if (args.hasValueFlag("save")) { - if (args.getFlag("save").isEmpty()) - throw new CommandException(Messages.INVALID_POSE_NAME); - - if (args.getSenderLocation() == null) - throw new ServerCommandException(); - - if (trait.addPose(args.getFlag("save"), args.getSenderLocation())) { - Messaging.sendTr(sender, Messages.POSE_ADDED); - } else - throw new CommandException(Messages.POSE_ALREADY_EXISTS, args.getFlag("save")); - } else if (args.hasValueFlag("assume")) { - String pose = args.getFlag("assume"); - if (pose.isEmpty()) - throw new CommandException(Messages.INVALID_POSE_NAME); - - if (!trait.hasPose(pose)) - throw new CommandException(Messages.POSE_MISSING, pose); - trait.assumePose(pose); - } else if (args.hasValueFlag("remove")) { - if (args.getFlag("remove").isEmpty()) - throw new CommandException(Messages.INVALID_POSE_NAME); - if (trait.removePose(args.getFlag("remove"))) { - Messaging.sendTr(sender, Messages.POSE_REMOVED); - } else - throw new CommandException(Messages.POSE_MISSING, args.getFlag("remove")); - } else if (!args.hasFlag('a')) { - trait.describe(sender, args.getInteger(1, 1)); - } - - // Assume Player's pose - if (!args.hasFlag('a')) - return; - if (args.getSenderLocation() == null) - throw new ServerCommandException(); - Location location = args.getSenderLocation(); - trait.assumePose(location); - } - - @Command( - aliases = { "npc" }, - usage = "power", - desc = "Toggle a creeper NPC as powered", - modifiers = { "power" }, - min = 1, - max = 1, - permission = "citizens.npc.power") - @Requirements(selected = true, ownership = true, types = { EntityType.CREEPER }) - public void power(CommandContext args, CommandSender sender, NPC npc) { - Messaging.sendTr(sender, - npc.getTrait(Powered.class).toggle() ? Messages.POWERED_SET : Messages.POWERED_STOPPED); - } - - @Command( - aliases = { "npc" }, - usage = "profession|prof [profession]", - desc = "Set a NPC's profession", - modifiers = { "profession", "prof" }, - min = 2, - max = 2, - permission = "citizens.npc.profession") - @Requirements(selected = true, ownership = true, types = { EntityType.VILLAGER }) - public void profession(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String profession = args.getString(1); - Profession parsed = Util.matchEnum(Profession.values(), profession.toUpperCase()); - if (parsed == null) { - throw new CommandException(Messages.INVALID_PROFESSION, args.getString(1), - StringUtils.join(Profession.values(), ",")); - } - npc.getTrait(VillagerProfession.class).setProfession(parsed); - Messaging.sendTr(sender, Messages.PROFESSION_SET, npc.getName(), profession); - } - - @Command( - aliases = { "npc" }, - usage = "rabbittype [type]", - desc = "Set the Type of a Rabbit NPC", - modifiers = { "rabbittype", "rbtype" }, - min = 2, - permission = "citizens.npc.rabbittype") - @Requirements(selected = true, ownership = true, types = { EntityType.RABBIT }) - public void rabbitType(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Rabbit.Type type; - try { - type = Rabbit.Type.valueOf(args.getString(1).toUpperCase()); - } catch (IllegalArgumentException ex) { - throw new CommandException(Messages.INVALID_RABBIT_TYPE, StringUtils.join(Rabbit.Type.values(), ",")); - } - npc.getTrait(RabbitType.class).setType(type); - Messaging.sendTr(sender, Messages.RABBIT_TYPE_SET, npc.getName(), type.name()); - } - - @Command( - aliases = { "npc" }, - usage = "remove|rem (all|id|name)", - desc = "Remove a NPC", - modifiers = { "remove", "rem" }, - min = 1, - max = 2) - @Requirements - public void remove(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException { - if (args.argsLength() == 2) { - if (args.getString(1).equalsIgnoreCase("all")) { - if (!sender.hasPermission("citizens.admin.remove.all") && !sender.hasPermission("citizens.admin")) - throw new NoPermissionsException(); - npcRegistry.deregisterAll(); - Messaging.sendTr(sender, Messages.REMOVED_ALL_NPCS); - return; - } else { - NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() { - @Override - public void run(NPC npc) throws CommandException { - if (npc == null) - throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED); - if (!(sender instanceof ConsoleCommandSender) && !npc.getTrait(Owner.class).isOwnedBy(sender)) - throw new CommandException(Messages.COMMAND_MUST_BE_OWNER); - if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin")) - throw new NoPermissionsException(); - npc.destroy(); - Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName()); - } - }; - NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1)); - return; - } - } - if (npc == null) - throw new CommandException(Messages.COMMAND_MUST_HAVE_SELECTED); - if (!(sender instanceof ConsoleCommandSender) && !npc.getTrait(Owner.class).isOwnedBy(sender)) - throw new CommandException(Messages.COMMAND_MUST_BE_OWNER); - if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin")) - throw new NoPermissionsException(); - npc.destroy(); - Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "rename [name]", - desc = "Rename a NPC", - modifiers = { "rename" }, - min = 2, - permission = "citizens.npc.rename") - public void rename(CommandContext args, CommandSender sender, NPC npc) { - String oldName = npc.getName(); - String newName = Colorizer.parseColors(args.getJoinedStrings(1)); - int nameLength = npc.getTrait(MobType.class).getType() == EntityType.PLAYER ? 46 : 64; - if (newName.length() > nameLength) { - Messaging.sendErrorTr(sender, Messages.NPC_NAME_TOO_LONG); - newName = newName.substring(0, nameLength); - } - Location prev = npc.isSpawned() ? npc.getEntity().getLocation() : null; - npc.despawn(DespawnReason.PENDING_RESPAWN); - npc.setName(newName); - if (prev != null) { - npc.spawn(prev); - } - - Messaging.sendTr(sender, Messages.NPC_RENAMED, oldName, newName); - } - - @Command( - aliases = { "npc" }, - usage = "respawn [delay in ticks]", - desc = "Sets an NPC's respawn delay in ticks", - modifiers = { "respawn" }, - min = 1, - max = 2, - permission = "citizens.npc.respawn") - public void respawn(CommandContext args, CommandSender sender, NPC npc) { - if (args.argsLength() > 1) { - int delay = args.getInteger(1); - npc.data().setPersistent(NPC.RESPAWN_DELAY_METADATA, delay); - Messaging.sendTr(sender, Messages.RESPAWN_DELAY_SET, delay); - } else { - Messaging.sendTr(sender, Messages.RESPAWN_DELAY_DESCRIBE, npc.data().get(NPC.RESPAWN_DELAY_METADATA, -1)); - } - } - - @Command( - aliases = { "npc" }, - usage = "script --add [files] --remove [files]", - desc = "Controls an NPC's scripts", - modifiers = { "script" }, - min = 1, - max = 1, - permission = "citizens.npc.script") - public void script(CommandContext args, CommandSender sender, NPC npc) { - ScriptTrait trait = npc.getTrait(ScriptTrait.class); - if (args.hasValueFlag("add")) { - List files = new ArrayList(); - for (String file : args.getFlag("add").split(",")) { - if (!trait.validateFile(file)) { - Messaging.sendErrorTr(sender, Messages.INVALID_SCRIPT_FILE, file); - return; - } - files.add(file); - } - trait.addScripts(files); - } - if (args.hasValueFlag("remove")) { - trait.removeScripts(Arrays.asList(args.getFlag("remove").split(","))); - } - Messaging.sendTr(sender, Messages.CURRENT_SCRIPTS, npc.getName(), Joiner.on("]],[[ ").join(trait.getScripts())); - } - - @Command( - aliases = { "npc" }, - usage = "select|sel [id|name] (--r range)", - desc = "Select a NPC with the given ID or name", - modifiers = { "select", "sel" }, - min = 1, - max = 2, - permission = "citizens.npc.select") - @Requirements - public void select(CommandContext args, final CommandSender sender, final NPC npc) throws CommandException { - NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() { - @Override - public void run(NPC toSelect) throws CommandException { - if (toSelect == null) - throw new CommandException(Messages.NPC_NOT_FOUND); - if (npc != null && toSelect.getId() == npc.getId()) - throw new CommandException(Messages.NPC_ALREADY_SELECTED); - selector.select(sender, toSelect); - Messaging.sendWithNPC(sender, Setting.SELECTION_MESSAGE.asString(), toSelect); - } - }; - if (args.argsLength() <= 1) { - if (!(sender instanceof Player)) - throw new ServerCommandException(); - double range = Math.abs(args.getFlagDouble("r", 10)); - Entity player = (Player) sender; - final Location location = args.getSenderLocation(); - List search = player.getNearbyEntities(range, range, range); - Collections.sort(search, new Comparator() { - @Override - public int compare(Entity o1, Entity o2) { - double d = o1.getLocation().distanceSquared(location) - o2.getLocation().distanceSquared(location); - return d > 0 ? 1 : d < 0 ? -1 : 0; - } - }); - for (Entity possibleNPC : search) { - NPC test = npcRegistry.getNPC(possibleNPC); - if (test == null) - continue; - callback.run(test); - break; - } - } else { - NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1)); - } - } - - @Command( - aliases = { "npc" }, - usage = "sheep (--color [color]) (--sheared [sheared])", - desc = "Sets sheep modifiers", - modifiers = { "sheep" }, - min = 1, - max = 1, - permission = "citizens.npc.sheep") - @Requirements(selected = true, ownership = true, types = { EntityType.SHEEP }) - public void sheep(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - SheepTrait trait = npc.getTrait(SheepTrait.class); - boolean hasArg = false; - if (args.hasValueFlag("sheared")) { - trait.setSheared(Boolean.valueOf(args.getFlag("sheared"))); - hasArg = true; - } - if (args.hasValueFlag("color")) { - DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("color")); - if (color != null) { - trait.setColor(color); - Messaging.sendTr(sender, Messages.SHEEP_COLOR_SET, color.toString().toLowerCase()); - } else { - Messaging.sendErrorTr(sender, Messages.INVALID_SHEEP_COLOR, Util.listValuesPretty(DyeColor.values())); - } - hasArg = true; - } - if (!hasArg) { - throw new CommandException(); - } - } - - @Command( - aliases = { "npc" }, - usage = "skeletontype [type]", - desc = "Sets the NPC's skeleton type", - modifiers = { "skeletontype", "sktype" }, - min = 2, - max = 2, - permission = "citizens.npc.skeletontype") - @Requirements(selected = true, ownership = true, types = EntityType.SKELETON) - public void skeletonType(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - SkeletonType type; - try { - type = SkeletonType.valueOf(args.getString(1).toUpperCase()); - } catch (IllegalArgumentException ex) { - throw new CommandException(Messages.INVALID_SKELETON_TYPE, StringUtils.join(SkeletonType.values(), ",")); - } - npc.getTrait(NPCSkeletonType.class).setType(type); - Messaging.sendTr(sender, Messages.SKELETON_TYPE_SET, npc.getName(), type); - } - - @Command( - aliases = { "npc" }, - usage = "skin (-c -p) [name]", - desc = "Sets an NPC's skin name, Use -p to save a skin snapshot that won't change", - modifiers = { "skin" }, - min = 1, - max = 2, - flags = "cp", - permission = "citizens.npc.skin") - @Requirements(types = EntityType.PLAYER, selected = true, ownership = true) - public void skin(final CommandContext args, final CommandSender sender, final NPC npc) throws CommandException { - String skinName = npc.getName(); - if (args.hasFlag('c')) { - npc.data().remove(NPC.PLAYER_SKIN_UUID_METADATA); - } else { - if (args.argsLength() != 2) - throw new CommandException(); - npc.data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, args.getString(1)); - if (args.hasFlag('p')) { - npc.data().setPersistent(NPC.PLAYER_SKIN_USE_LATEST, false); - } - skinName = args.getString(1); - } - Messaging.sendTr(sender, Messages.SKIN_SET, npc.getName(), skinName); - if (npc.isSpawned()) { - SkinnableEntity skinnable = npc.getEntity() instanceof SkinnableEntity ? (SkinnableEntity) npc.getEntity() - : null; - if (skinnable != null) { - skinnable.setSkinName(skinName, args.hasFlag('p')); - } - } - } - - @Command( - aliases = { "npc" }, - usage = "skinlayers (--cape [true|false]) (--hat [true|false]) (--jacket [true|false]) (--sleeves [true|false]) (--pants [true|false])", - desc = "Sets an NPC's skin layers visibility.", - modifiers = { "skinlayers" }, - min = 1, - max = 5, - permission = "citizens.npc.skinlayers") - @Requirements(types = EntityType.PLAYER, selected = true, ownership = true) - public void skinLayers(final CommandContext args, final CommandSender sender, final NPC npc) - throws CommandException { - SkinLayers trait = npc.getTrait(SkinLayers.class); - if (args.hasValueFlag("cape")) { - trait.setVisible(Layer.CAPE, Boolean.valueOf(args.getFlag("cape"))); - } - if (args.hasValueFlag("hat")) { - trait.setVisible(Layer.HAT, Boolean.valueOf(args.getFlag("hat"))); - } - if (args.hasValueFlag("jacket")) { - trait.setVisible(Layer.JACKET, Boolean.valueOf(args.getFlag("jacket"))); - } - if (args.hasValueFlag("sleeves")) { - boolean hasSleeves = Boolean.valueOf(args.getFlag("sleeves")); - trait.setVisible(Layer.LEFT_SLEEVE, hasSleeves); - trait.setVisible(Layer.RIGHT_SLEEVE, hasSleeves); - } - if (args.hasValueFlag("pants")) { - boolean hasPants = Boolean.valueOf(args.getFlag("pants")); - trait.setVisible(Layer.LEFT_PANTS, hasPants); - trait.setVisible(Layer.RIGHT_PANTS, hasPants); - } - Messaging.sendTr(sender, Messages.SKIN_LAYERS_SET, npc.getName(), trait.isVisible(Layer.CAPE), - trait.isVisible(Layer.HAT), trait.isVisible(Layer.JACKET), - trait.isVisible(Layer.LEFT_SLEEVE) || trait.isVisible(Layer.RIGHT_SLEEVE), - trait.isVisible(Layer.LEFT_PANTS) || trait.isVisible(Layer.RIGHT_PANTS)); - } - - @Command( - aliases = { "npc" }, - usage = "size [size]", - desc = "Sets the NPC's size", - modifiers = { "size" }, - min = 1, - max = 2, - permission = "citizens.npc.size") - @Requirements(selected = true, ownership = true, types = { EntityType.MAGMA_CUBE, EntityType.SLIME }) - public void slimeSize(CommandContext args, CommandSender sender, NPC npc) { - SlimeSize trait = npc.getTrait(SlimeSize.class); - if (args.argsLength() <= 1) { - trait.describe(sender); - return; - } - int size = Math.max(-2, args.getInteger(1)); - trait.setSize(size); - Messaging.sendTr(sender, Messages.SIZE_SET, npc.getName(), size); - } - - @Command( - aliases = { "npc" }, - usage = "sound (--death [death sound|d]) (--ambient [ambient sound|d]) (--hurt [hurt sound|d]) (-n(one)) (-d(efault))", - desc = "Sets an NPC's played sounds", - modifiers = { "sound" }, - flags = "dns", - min = 1, - max = 1, - permission = "citizens.npc.sound") - @Requirements(selected = true, ownership = true, livingEntity = true, excludedTypes = { EntityType.PLAYER }) - public void sound(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String ambientSound = npc.data().get(NPC.AMBIENT_SOUND_METADATA); - String deathSound = npc.data().get(NPC.DEATH_SOUND_METADATA); - String hurtSound = npc.data().get(NPC.HURT_SOUND_METADATA); - if (args.getValueFlags().size() == 0 && args.getFlags().size() == 0) { - Messaging.sendTr(sender, Messages.SOUND_INFO, npc.getName(), ambientSound, hurtSound, deathSound); - return; - } - - if (args.hasFlag('n') || args.hasFlag('s')) { - ambientSound = deathSound = hurtSound = ""; - npc.data().setPersistent(NPC.SILENT_METADATA, true); - } - if (args.hasFlag('d')) { - ambientSound = deathSound = hurtSound = null; - } else { - if (args.hasValueFlag("death")) { - deathSound = args.getFlag("death").equals("d") ? null : NMS.getSound(args.getFlag("death")); - } - if (args.hasValueFlag("ambient")) { - ambientSound = args.getFlag("ambient").equals("d") ? null : NMS.getSound(args.getFlag("ambient")); - } - if (args.hasValueFlag("hurt")) { - hurtSound = args.getFlag("hurt").equals("d") ? null : NMS.getSound(args.getFlag("hurt")); - } - } - if (deathSound == null) { - npc.data().remove(NPC.DEATH_SOUND_METADATA); - } else { - npc.data().setPersistent(NPC.DEATH_SOUND_METADATA, deathSound); - } - if (hurtSound == null) { - npc.data().remove(NPC.HURT_SOUND_METADATA); - } else { - npc.data().setPersistent(NPC.HURT_SOUND_METADATA, hurtSound); - } - if (ambientSound == null) { - npc.data().remove(ambientSound); - } else { - npc.data().setPersistent(NPC.AMBIENT_SOUND_METADATA, ambientSound); - } - - if (ambientSound != null && ambientSound.isEmpty()) { - ambientSound = "none"; - } - if (hurtSound != null && hurtSound.isEmpty()) { - hurtSound = "none"; - } - if (deathSound != null && deathSound.isEmpty()) { - deathSound = "none"; - } - if (ambientSound != null || deathSound != null || hurtSound != null) { - npc.data().setPersistent(NPC.SILENT_METADATA, false); - } - Messaging.sendTr(sender, Messages.SOUND_SET, npc.getName(), ambientSound, hurtSound, deathSound); - } - - @Command( - aliases = { "npc" }, - usage = "spawn (id|name)", - desc = "Spawn an existing NPC", - modifiers = { "spawn" }, - min = 1, - max = 2, - permission = "citizens.npc.spawn") - @Requirements(ownership = true) - public void spawn(final CommandContext args, final CommandSender sender, NPC npc) throws CommandException { - NPCCommandSelector.Callback callback = new NPCCommandSelector.Callback() { - @Override - public void run(NPC respawn) throws CommandException { - if (respawn == null) { - if (args.argsLength() > 1) { - throw new CommandException(Messages.NO_NPC_WITH_ID_FOUND, args.getString(1)); - } else { - throw new CommandException(CommandMessages.MUST_HAVE_SELECTED); - } - } - if (respawn.isSpawned()) { - throw new CommandException(Messages.NPC_ALREADY_SPAWNED, respawn.getName()); - } - Location location = respawn.getTrait(CurrentLocation.class).getLocation(); - if (location == null || args.hasValueFlag("location")) { - if (args.getSenderLocation() == null) - throw new CommandException(Messages.NO_STORED_SPAWN_LOCATION); - - location = args.getSenderLocation(); - } - if (respawn.spawn(location)) { - selector.select(sender, respawn); - Messaging.sendTr(sender, Messages.NPC_SPAWNED, respawn.getName()); - } - } - }; - if (args.argsLength() > 1) { - NPCCommandSelector.startWithCallback(callback, npcRegistry, sender, args, args.getString(1)); - } else { - callback.run(npc); - } - } - - @Command( - aliases = { "npc" }, - usage = "speak message to speak --target npcid|player_name --type vocal_type", - desc = "Uses the NPCs SpeechController to talk", - modifiers = { "speak" }, - min = 2, - permission = "citizens.npc.speak") - public void speak(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String type = npc.getTrait(Speech.class).getDefaultVocalChord(); - String message = Colorizer.parseColors(args.getJoinedStrings(1)); - - if (message.length() <= 0) { - Messaging.send(sender, "Default Vocal Chord for " + npc.getName() + ": " - + npc.getTrait(Speech.class).getDefaultVocalChord()); - return; - } - - SpeechContext context = new SpeechContext(message); - - if (args.hasValueFlag("target")) { - if (args.getFlag("target").matches("\\d+")) { - NPC target = CitizensAPI.getNPCRegistry().getById(Integer.valueOf(args.getFlag("target"))); - if (target != null) - context.addRecipient(target.getEntity()); - } else { - Player player = Bukkit.getPlayer(args.getFlag("target")); - if (player != null) { - context.addRecipient((Entity) player); - } - } - } - - if (args.hasValueFlag("type")) { - if (CitizensAPI.getSpeechFactory().isRegistered(args.getFlag("type"))) - type = args.getFlag("type"); - } - - npc.getDefaultSpeechController().speak(context, type); - } - - @Command( - aliases = { "npc" }, - usage = "speed [speed]", - desc = "Sets the movement speed of an NPC as a percentage", - modifiers = { "speed" }, - min = 2, - max = 2, - permission = "citizens.npc.speed") - public void speed(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - float newSpeed = (float) Math.abs(args.getDouble(1)); - if (newSpeed >= Setting.MAX_SPEED.asDouble()) - throw new CommandException(Messages.SPEED_MODIFIER_ABOVE_LIMIT); - npc.getNavigator().getDefaultParameters().speedModifier(newSpeed); - - Messaging.sendTr(sender, Messages.SPEED_MODIFIER_SET, newSpeed); - } - - @Command( - aliases = { "npc" }, - usage = "swim (--set [true|false])", - desc = "Sets an NPC to swim or not", - modifiers = { "swim" }, - min = 1, - max = 1, - permission = "citizens.npc.swim") - public void swim(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - boolean swim = args.hasValueFlag("set") ? Boolean.parseBoolean(args.getFlag("set")) - : !npc.data().get(NPC.SWIMMING_METADATA, true); - npc.data().setPersistent(NPC.SWIMMING_METADATA, swim); - Messaging.sendTr(sender, swim ? Messages.SWIMMING_SET : Messages.SWIMMING_UNSET, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "targetable", - desc = "Toggles an NPC's targetability", - modifiers = { "targetable" }, - min = 1, - max = 1, - permission = "citizens.npc.targetable") - public void targetable(CommandContext args, CommandSender sender, NPC npc) { - boolean targetable = !npc.data().get(NPC.TARGETABLE_METADATA, - npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)); - if (args.hasFlag('t')) { - npc.data().set(NPC.TARGETABLE_METADATA, targetable); - } else { - npc.data().setPersistent(NPC.TARGETABLE_METADATA, targetable); - } - Messaging.sendTr(sender, targetable ? Messages.TARGETABLE_SET : Messages.TARGETABLE_UNSET, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "tp", - desc = "Teleport to a NPC", - modifiers = { "tp", "teleport" }, - min = 1, - max = 1, - permission = "citizens.npc.tp") - public void tp(CommandContext args, Player player, NPC npc) { - Location to = npc.getTrait(CurrentLocation.class).getLocation(); - if (to == null) { - Messaging.sendError(player, Messages.TELEPORT_NPC_LOCATION_NOT_FOUND); - return; - } - player.teleport(to, TeleportCause.COMMAND); - Messaging.sendTr(player, Messages.TELEPORTED_TO_NPC, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "tphere", - desc = "Teleport a NPC to your location", - modifiers = { "tphere", "tph", "move" }, - min = 1, - max = 1, - permission = "citizens.npc.tphere") - public void tphere(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - if (args.getSenderLocation() == null) - throw new ServerCommandException(); - // Spawn the NPC if it isn't spawned to prevent NPEs - if (!npc.isSpawned()) { - npc.spawn(args.getSenderLocation()); - if (!sender.hasPermission("citizens.npc.tphere.multiworld") - && npc.getEntity().getLocation().getWorld() != args.getSenderLocation().getWorld()) { - npc.despawn(DespawnReason.REMOVAL); - throw new CommandException(Messages.CANNOT_TELEPORT_ACROSS_WORLDS); - } - } else { - if (!sender.hasPermission("citizens.npc.tphere.multiworld") - && npc.getEntity().getLocation().getWorld() != args.getSenderLocation().getWorld()) { - npc.despawn(DespawnReason.REMOVAL); - throw new CommandException(Messages.CANNOT_TELEPORT_ACROSS_WORLDS); - } - npc.teleport(args.getSenderLocation(), TeleportCause.COMMAND); - } - Messaging.sendTr(sender, Messages.NPC_TELEPORTED, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "tpto [player name|npc id] [player name|npc id]", - desc = "Teleport an NPC or player to another NPC or player", - modifiers = { "tpto" }, - min = 3, - max = 3, - permission = "citizens.npc.tpto") - @Requirements - public void tpto(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Entity from = null, to = null; - if (npc != null) { - from = npc.getEntity(); - } - boolean firstWasPlayer = false; - try { - int id = args.getInteger(1); - NPC fromNPC = CitizensAPI.getNPCRegistry().getById(id); - if (fromNPC != null) { - from = fromNPC.getEntity(); - } - } catch (NumberFormatException e) { - from = Bukkit.getPlayerExact(args.getString(1)); - firstWasPlayer = true; - } - try { - int id = args.getInteger(2); - NPC toNPC = CitizensAPI.getNPCRegistry().getById(id); - if (toNPC != null) { - to = toNPC.getEntity(); - } - } catch (NumberFormatException e) { - if (!firstWasPlayer) { - to = Bukkit.getPlayerExact(args.getString(2)); - } - } - if (from == null) - throw new CommandException(Messages.FROM_ENTITY_NOT_FOUND); - if (to == null) - throw new CommandException(Messages.TO_ENTITY_NOT_FOUND); - from.teleport(to); - Messaging.sendTr(sender, Messages.TPTO_SUCCESS); - } - - @Command( - aliases = { "npc" }, - usage = "type [type]", - desc = "Sets an NPC's entity type", - modifiers = { "type" }, - min = 2, - max = 2, - permission = "citizens.npc.type") - public void type(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - EntityType type = Util.matchEntityType(args.getString(1)); - if (type == null) - throw new CommandException(Messages.INVALID_ENTITY_TYPE, args.getString(1)); - npc.setBukkitEntityType(type); - Messaging.sendTr(sender, Messages.ENTITY_TYPE_SET, npc.getName(), args.getString(1)); - } - - @Command( - aliases = { "npc" }, - usage = "vulnerable (-t)", - desc = "Toggles an NPC's vulnerability", - modifiers = { "vulnerable" }, - min = 1, - max = 1, - flags = "t", - permission = "citizens.npc.vulnerable") - public void vulnerable(CommandContext args, CommandSender sender, NPC npc) { - boolean vulnerable = !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); - if (args.hasFlag('t')) { - npc.data().set(NPC.DEFAULT_PROTECTED_METADATA, vulnerable); - } else { - npc.data().setPersistent(NPC.DEFAULT_PROTECTED_METADATA, vulnerable); - } - String key = vulnerable ? Messages.VULNERABLE_STOPPED : Messages.VULNERABLE_SET; - Messaging.sendTr(sender, key, npc.getName()); - } - - @Command( - aliases = { "npc" }, - usage = "wither (--charged [charged])", - desc = "Sets wither modifiers", - modifiers = { "wither" }, - min = 1, - max = 1, - permission = "citizens.npc.wither") - @Requirements(selected = true, ownership = true, types = { EntityType.WITHER }) - public void wither(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - WitherTrait trait = npc.getTrait(WitherTrait.class); - boolean hasArg = false; - if (args.hasValueFlag("charged")) { - trait.setCharged(Boolean.valueOf(args.getFlag("charged"))); - hasArg = true; - } - if (!hasArg) { - throw new CommandException(); - } - } - - @Command( - aliases = { "npc" }, - usage = "wolf (-s(itting) a(ngry) t(amed)) --collar [hex rgb color|name]", - desc = "Sets wolf modifiers", - modifiers = { "wolf" }, - min = 1, - max = 1, - flags = "sat", - permission = "citizens.npc.wolf") - @Requirements(selected = true, ownership = true, types = EntityType.WOLF) - public void wolf(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - WolfModifiers trait = npc.getTrait(WolfModifiers.class); - trait.setAngry(args.hasFlag('a')); - trait.setSitting(args.hasFlag('s')); - trait.setTamed(args.hasFlag('t')); - if (args.hasValueFlag("collar")) { - String unparsed = args.getFlag("collar"); - DyeColor color = null; - try { - color = DyeColor.valueOf(unparsed.toUpperCase().replace(' ', '_')); - } catch (IllegalArgumentException e) { - try { - int rgb = Integer.parseInt(unparsed.replace("#", ""), 16); - color = DyeColor.getByColor(org.bukkit.Color.fromRGB(rgb)); - } catch (NumberFormatException ex) { - throw new CommandException(Messages.COLLAR_COLOUR_NOT_RECOGNISED, unparsed); - } - } - if (color == null) - throw new CommandException(Messages.COLLAR_COLOUR_NOT_SUPPORTED, unparsed); - trait.setCollarColor(color); - } - Messaging.sendTr(sender, Messages.WOLF_TRAIT_UPDATED, npc.getName(), args.hasFlag('a'), args.hasFlag('s'), - args.hasFlag('t'), trait.getCollarColor().name()); - } - - @Command( - aliases = { "npc" }, - usage = "zombiemod (-b(aby), -v(illager) --p(rofession) [profession])", - desc = "Sets a zombie NPC to be a baby or villager", - modifiers = { "zombie", "zombiemod" }, - flags = "bv", - min = 1, - max = 1, - permission = "citizens.npc.zombiemodifier") - @Requirements(selected = true, ownership = true, types = { EntityType.ZOMBIE, EntityType.PIG_ZOMBIE }) - public void zombieModifier(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - ZombieModifier trait = npc.getTrait(ZombieModifier.class); - if (args.hasFlag('b')) { - boolean isBaby = trait.toggleBaby(); - Messaging.sendTr(sender, isBaby ? Messages.ZOMBIE_BABY_SET : Messages.ZOMBIE_BABY_UNSET, npc.getName()); - } - if (args.hasFlag('v')) { - boolean isVillager = trait.toggleVillager(); - Messaging.sendTr(sender, isVillager ? Messages.ZOMBIE_VILLAGER_SET : Messages.ZOMBIE_VILLAGER_UNSET, - npc.getName()); - } - if (args.hasValueFlag("profession") || args.hasValueFlag("p")) { - Profession profession = Util.matchEnum(Profession.values(), args.getFlag("profession", args.getFlag("p"))); - if (profession == null) { - throw new CommandException(); - } - trait.setProfession(profession); - Messaging.sendTr(sender, Messages.ZOMBIE_VILLAGER_PROFESSION_SET, npc.getName(), - Util.prettyEnum(profession)); - } - } -} diff --git a/main/java/net/citizensnpcs/commands/TemplateCommands.java b/main/java/net/citizensnpcs/commands/TemplateCommands.java deleted file mode 100644 index dc10b1679..000000000 --- a/main/java/net/citizensnpcs/commands/TemplateCommands.java +++ /dev/null @@ -1,120 +0,0 @@ -package net.citizensnpcs.commands; - -import java.util.List; - -import javax.annotation.Nullable; - -import net.citizensnpcs.Citizens; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.npc.Template; -import net.citizensnpcs.npc.Template.TemplateBuilder; -import net.citizensnpcs.util.Messages; - -import org.bukkit.command.CommandSender; - -import com.google.common.base.Function; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -@Requirements(selected = true, ownership = true) -public class TemplateCommands { - public TemplateCommands(Citizens plugin) { - } - - @Command( - aliases = { "template", "tpl" }, - usage = "apply [template name] (id id2...)", - desc = "Applies a template to the selected NPC", - modifiers = { "apply" }, - min = 2, - permission = "citizens.templates.apply") - @Requirements - public void apply(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Template template = Template.byName(args.getString(1)); - if (template == null) - throw new CommandException(Messages.TEMPLATE_MISSING); - int appliedCount = 0; - if (args.argsLength() == 2) { - if (npc == null) - throw new CommandException(Messaging.tr(Messages.COMMAND_MUST_HAVE_SELECTED)); - template.apply(npc); - appliedCount++; - } else { - String joined = args.getJoinedStrings(2, ','); - List ids = Lists.newArrayList(); - for (String id : Splitter.on(',').trimResults().split(joined)) { - int parsed = Integer.parseInt(id); - ids.add(parsed); - } - Iterable transformed = Iterables.transform(ids, new Function() { - @Override - public NPC apply(@Nullable Integer arg0) { - if (arg0 == null) - return null; - return CitizensAPI.getNPCRegistry().getById(arg0); - } - }); - for (NPC toApply : transformed) { - template.apply(toApply); - appliedCount++; - } - } - Messaging.sendTr(sender, Messages.TEMPLATE_APPLIED, appliedCount); - } - - @Command( - aliases = { "template", "tpl" }, - usage = "create [template name] (-o)", - desc = "Creates a template from the selected NPC", - modifiers = { "create" }, - min = 2, - max = 2, - flags = "o", - permission = "citizens.templates.create") - public void create(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String name = args.getString(1); - if (Template.byName(name) != null) - throw new CommandException(Messages.TEMPLATE_CONFLICT); - - TemplateBuilder.create(name).from(npc).override(args.hasFlag('o')).buildAndSave(); - Messaging.sendTr(sender, Messages.TEMPLATE_CREATED); - } - - @Command( - aliases = { "template", "tpl" }, - usage = "delete [template name]", - desc = "Deletes a template", - modifiers = { "delete" }, - min = 2, - max = 2, - permission = "citizens.templates.delete") - public void delete(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String name = args.getString(1); - if (Template.byName(name) == null) - throw new CommandException(Messages.TEMPLATE_MISSING); - Template.byName(name).delete(); - Messaging.sendTr(sender, Messages.TEMPLATE_DELETED, name); - } - - @Command( - aliases = { "template", "tpl" }, - usage = "list", - desc = "Lists available templates", - modifiers = { "list" }, - min = 1, - max = 1, - permission = "citizens.templates.list") - public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Messaging.sendTr(sender, Messages.TEMPLATE_LIST_HEADER); - for (Template template : Template.allTemplates()) { - Messaging.send(sender, "[[-]] " + template.getName()); - } - } -} diff --git a/main/java/net/citizensnpcs/commands/TraitCommands.java b/main/java/net/citizensnpcs/commands/TraitCommands.java deleted file mode 100644 index a328c5511..000000000 --- a/main/java/net/citizensnpcs/commands/TraitCommands.java +++ /dev/null @@ -1,167 +0,0 @@ -package net.citizensnpcs.commands; - -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; - -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandConfigurable; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.command.exception.NoPermissionsException; -import net.citizensnpcs.api.event.NPCTraitCommandAttachEvent; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.StringHelper; - -@Requirements(selected = true, ownership = true) -public class TraitCommands { - @Command( - aliases = { "trait", "tr" }, - usage = "add [trait name]...", - desc = "Adds traits to the NPC", - modifiers = { "add", "a" }, - min = 2, - permission = "citizens.npc.trait") - public void add(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - List added = Lists.newArrayList(); - List failed = Lists.newArrayList(); - for (String traitName : Splitter.on(',').split(args.getJoinedStrings(1))) { - if (!sender.hasPermission("citizens.npc.trait." + traitName) - && !sender.hasPermission("citizens.npc.trait.*")) { - failed.add(String.format("%s: No permission", traitName)); - continue; - } - - Class clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName); - if (clazz == null) { - failed.add(String.format("%s: Trait not found", traitName)); - continue; - } - if (npc.hasTrait(clazz)) { - failed.add(String.format("%s: Already added", traitName)); - continue; - } - addTrait(npc, clazz, sender); - added.add(StringHelper.wrap(traitName)); - } - if (added.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_ADDED, Joiner.on(", ").join(added)); - if (failed.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_FAILED_TO_ADD, Joiner.on(", ").join(failed)); - } - - private void addTrait(NPC npc, Class clazz, CommandSender sender) { - npc.addTrait(clazz); - Bukkit.getPluginManager().callEvent(new NPCTraitCommandAttachEvent(npc, clazz, sender)); - } - - @Command( - aliases = { "traitc", "trc" }, - usage = "[trait name] (flags)", - desc = "Configures a trait", - modifiers = { "*" }, - min = 1, - flags = "*", - permission = "citizens.npc.trait-configure") - public void configure(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - String traitName = args.getString(0); - if (!sender.hasPermission("citizens.npc.trait-configure." + traitName) - && !sender.hasPermission("citizens.npc.trait-configure.*")) - throw new NoPermissionsException(); - Class clazz = CitizensAPI.getTraitFactory().getTraitClass(args.getString(0)); - if (clazz == null) - throw new CommandException(Messages.TRAIT_NOT_FOUND); - if (!CommandConfigurable.class.isAssignableFrom(clazz)) - throw new CommandException(Messages.TRAIT_NOT_CONFIGURABLE); - if (!npc.hasTrait(clazz)) - throw new CommandException(Messages.TRAIT_NOT_FOUND_ON_NPC); - CommandConfigurable trait = (CommandConfigurable) npc.getTrait(clazz); - trait.configure(args); - } - - @Command( - aliases = { "trait", "tr" }, - usage = "remove [trait name]...", - desc = "Removes traits on the NPC", - modifiers = { "remove", "rem", "r" }, - min = 1, - permission = "citizens.npc.trait") - public void remove(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - List removed = Lists.newArrayList(); - List failed = Lists.newArrayList(); - for (String traitName : Splitter.on(',').split(args.getJoinedStrings(0))) { - if (!sender.hasPermission("citizens.npc.trait." + traitName) - && !sender.hasPermission("citizens.npc.trait.*")) { - failed.add(String.format("%s: No permission", traitName)); - continue; - } - - Class clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName); - if (clazz == null) { - failed.add(String.format("%s: Trait not found", traitName)); - continue; - } - boolean hasTrait = npc.hasTrait(clazz); - if (!hasTrait) { - failed.add(String.format("%s: Trait not attached", traitName)); - continue; - } - npc.removeTrait(clazz); - removed.add(StringHelper.wrap(traitName)); - } - if (removed.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_REMOVED, Joiner.on(", ").join(removed)); - if (failed.size() > 0) - Messaging.sendTr(sender, Messages.FAILED_TO_REMOVE, Joiner.on(", ").join(failed)); - } - - @Command( - aliases = { "trait", "tr" }, - usage = "[trait name], [trait name]...", - desc = "Toggles traits on the NPC", - modifiers = { "*" }, - min = 1, - permission = "citizens.npc.trait") - public void toggle(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - List added = Lists.newArrayList(); - List removed = Lists.newArrayList(); - List failed = Lists.newArrayList(); - for (String traitName : Splitter.on(',').split(args.getJoinedStrings(0))) { - if (!sender.hasPermission("citizens.npc.trait." + traitName) - && !sender.hasPermission("citizens.npc.trait.*")) { - failed.add(String.format("%s: No permission", traitName)); - continue; - } - - Class clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName); - if (clazz == null) { - failed.add(String.format("%s: Trait not found", traitName)); - continue; - } - boolean remove = npc.hasTrait(clazz); - if (remove) { - npc.removeTrait(clazz); - removed.add(StringHelper.wrap(traitName)); - continue; - } - addTrait(npc, clazz, sender); - added.add(StringHelper.wrap(traitName)); - } - if (added.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_ADDED, Joiner.on(", ").join(added)); - if (removed.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_REMOVED, Joiner.on(", ").join(removed)); - if (failed.size() > 0) - Messaging.sendTr(sender, Messages.TRAITS_FAILED_TO_CHANGE, Joiner.on(", ").join(failed)); - } -} diff --git a/main/java/net/citizensnpcs/commands/WaypointCommands.java b/main/java/net/citizensnpcs/commands/WaypointCommands.java deleted file mode 100644 index 29503073c..000000000 --- a/main/java/net/citizensnpcs/commands/WaypointCommands.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.citizensnpcs.commands; - -import net.citizensnpcs.Citizens; -import net.citizensnpcs.api.command.Command; -import net.citizensnpcs.api.command.CommandContext; -import net.citizensnpcs.api.command.Requirements; -import net.citizensnpcs.api.command.exception.CommandException; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.trait.waypoint.Waypoints; -import net.citizensnpcs.util.Messages; - -import org.bukkit.command.CommandSender; - -@Requirements(ownership = true, selected = true) -public class WaypointCommands { - public WaypointCommands(Citizens plugin) { - } - - // TODO: refactor into a policy style system - @Command( - aliases = { "waypoints", "waypoint", "wp" }, - usage = "disableteleport", - desc = "Disables teleportation when stuck (temporary command)", - modifiers = { "disableteleport" }, - min = 1, - max = 1, - permission = "citizens.waypoints.disableteleport") - public void disableTeleporting(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - npc.getNavigator().getDefaultParameters().stuckAction(null); - Messaging.sendTr(sender, Messages.WAYPOINT_TELEPORTING_DISABLED); - } - - @Command( - aliases = { "waypoints", "waypoint", "wp" }, - usage = "provider [provider name] (-d)", - desc = "Sets the current waypoint provider", - modifiers = { "provider" }, - min = 1, - max = 2, - flags = "d", - permission = "citizens.waypoints.provider") - public void provider(CommandContext args, CommandSender sender, NPC npc) throws CommandException { - Waypoints waypoints = npc.getTrait(Waypoints.class); - if (args.argsLength() == 1) { - if (args.hasFlag('d')) { - waypoints.describeProviders(sender); - } else { - Messaging.sendTr(sender, Messages.CURRENT_WAYPOINT_PROVIDER, waypoints.getCurrentProviderName()); - } - return; - } - boolean success = waypoints.setWaypointProvider(args.getString(1)); - if (!success) - throw new CommandException("Provider not found."); - Messaging.sendTr(sender, Messages.WAYPOINT_PROVIDER_SET, args.getString(1)); - } -} diff --git a/main/java/net/citizensnpcs/editor/CopierEditor.java b/main/java/net/citizensnpcs/editor/CopierEditor.java deleted file mode 100644 index 3c8e82464..000000000 --- a/main/java/net/citizensnpcs/editor/CopierEditor.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.citizensnpcs.editor; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.trait.CurrentLocation; -import net.citizensnpcs.util.Messages; - -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -public class CopierEditor extends Editor { - private final String name; - private final NPC npc; - private final Player player; - - public CopierEditor(Player player, NPC npc) { - this.player = player; - this.npc = npc; - this.name = npc.getFullName(); - } - - @Override - public void begin() { - Messaging.sendTr(player, Messages.COPIER_EDITOR_BEGIN); - } - - @Override - public void end() { - Messaging.sendTr(player, Messages.COPIER_EDITOR_END); - } - - @EventHandler - public void onBlockClick(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { - return; - } - NPC copy = npc.clone(); - if (!copy.getFullName().equals(name)) { - copy.setName(name); - } - - if (copy.isSpawned() && player.isOnline()) { - Location location = player.getLocation(); - location.getChunk().load(); - copy.teleport(location, TeleportCause.PLUGIN); - copy.getTrait(CurrentLocation.class).setLocation(location); - } - - Messaging.sendTr(player, Messages.NPC_COPIED, npc.getName()); - } -} diff --git a/main/java/net/citizensnpcs/editor/Editor.java b/main/java/net/citizensnpcs/editor/Editor.java deleted file mode 100644 index a56579ffd..000000000 --- a/main/java/net/citizensnpcs/editor/Editor.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.citizensnpcs.editor; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; - -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; - -public abstract class Editor implements Listener { - public abstract void begin(); - - public abstract void end(); - - private static void enter(Player player, Editor editor) { - editor.begin(); - player.getServer().getPluginManager().registerEvents(editor, - player.getServer().getPluginManager().getPlugin("Citizens")); - EDITING.put(player.getName(), editor); - } - - public static void enterOrLeave(Player player, Editor editor) { - if (editor == null) - return; - Editor edit = EDITING.get(player.getName()); - if (edit == null) { - enter(player, editor); - } else if (edit.getClass() == editor.getClass()) { - leave(player); - } else { - Messaging.sendErrorTr(player, Messages.ALREADY_IN_EDITOR); - } - } - - public static boolean hasEditor(Player player) { - return EDITING.containsKey(player.getName()); - } - - public static void leave(Player player) { - if (!hasEditor(player)) - return; - Editor editor = EDITING.remove(player.getName()); - HandlerList.unregisterAll(editor); - editor.end(); - } - - public static void leaveAll() { - for (Entry entry : EDITING.entrySet()) { - entry.getValue().end(); - HandlerList.unregisterAll(entry.getValue()); - } - EDITING.clear(); - } - - private static final Map EDITING = new HashMap(); -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/editor/EndermanEquipper.java b/main/java/net/citizensnpcs/editor/EndermanEquipper.java deleted file mode 100644 index 64c20e0ee..000000000 --- a/main/java/net/citizensnpcs/editor/EndermanEquipper.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.citizensnpcs.editor; - -import org.bukkit.Material; -import org.bukkit.entity.Enderman; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.material.MaterialData; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.trait.trait.Equipment; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; - -public class EndermanEquipper implements Equipper { - @Override - public void equip(Player equipper, NPC npc) { - ItemStack hand = equipper.getInventory().getItemInMainHand(); - if (!hand.getType().isBlock()) { - Messaging.sendErrorTr(equipper, Messages.EQUIPMENT_EDITOR_INVALID_BLOCK); - return; - } - - MaterialData carried = ((Enderman) npc.getEntity()).getCarriedMaterial(); - if (carried.getItemType() == Material.AIR) { - if (hand.getType() == Material.AIR) { - Messaging.sendErrorTr(equipper, Messages.EQUIPMENT_EDITOR_INVALID_BLOCK); - return; - } - } else { - equipper.getWorld().dropItemNaturally(npc.getEntity().getLocation(), carried.toItemStack(1)); - ((Enderman) npc.getEntity()).setCarriedMaterial(hand.getData()); - } - - ItemStack set = hand.clone(); - if (set.getType() != Material.AIR) { - set.setAmount(1); - hand.setAmount(hand.getAmount() - 1); - equipper.getInventory().setItemInMainHand(hand); - } - npc.getTrait(Equipment.class).set(0, set); - } -} diff --git a/main/java/net/citizensnpcs/editor/EquipmentEditor.java b/main/java/net/citizensnpcs/editor/EquipmentEditor.java deleted file mode 100644 index 8ba1dad89..000000000 --- a/main/java/net/citizensnpcs/editor/EquipmentEditor.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.citizensnpcs.editor; - -import java.util.Map; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.Event.Result; -import org.bukkit.event.EventHandler; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; - -import com.google.common.collect.Maps; - -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.trait.trait.Equipment; -import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; - -public class EquipmentEditor extends Editor { - private final NPC npc; - private final Player player; - - public EquipmentEditor(Player player, NPC npc) { - this.player = player; - this.npc = npc; - } - - @Override - public void begin() { - Messaging.sendTr(player, Messages.EQUIPMENT_EDITOR_BEGIN); - } - - @Override - public void end() { - Messaging.sendTr(player, Messages.EQUIPMENT_EDITOR_END); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerChat(final AsyncPlayerChatEvent event) { - EquipmentSlot slot = null; - if (event.getMessage().equals("helmet") - && event.getPlayer().hasPermission("citizens.npc.edit.equip.any-helmet")) { - slot = EquipmentSlot.HELMET; - } - if (event.getMessage().equals("offhand") - && event.getPlayer().hasPermission("citizens.npc.edit.equip.offhand")) { - slot = EquipmentSlot.OFF_HAND; - } - if (slot == null) { - return; - } - final EquipmentSlot finalSlot = slot; - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - if (!event.getPlayer().isValid()) - return; - ItemStack hand = event.getPlayer().getInventory().getItemInMainHand(); - if (hand.getType() == Material.AIR || hand.getAmount() <= 0) { - return; - } - ItemStack old = npc.getTrait(Equipment.class).get(finalSlot); - if (old != null && old.getType() != Material.AIR) { - event.getPlayer().getWorld().dropItemNaturally(event.getPlayer().getLocation(), old); - } - ItemStack newStack = hand.clone(); - newStack.setAmount(1); - npc.getTrait(Equipment.class).set(finalSlot, newStack); - hand.setAmount(hand.getAmount() - 1); - event.getPlayer().getInventory().setItemInMainHand(hand); - } - }); - event.setCancelled(true); - } - - @EventHandler - public void onPlayerInteract(PlayerInteractEvent event) { - if (event.getAction() == Action.RIGHT_CLICK_AIR && Editor.hasEditor(event.getPlayer())) { - event.setUseItemInHand(Result.DENY); - } - } - - @EventHandler - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - if (!npc.isSpawned() || !event.getPlayer().equals(player) - || event.getHand() != org.bukkit.inventory.EquipmentSlot.HAND - || !npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getRightClicked()))) - return; - - Equipper equipper = EQUIPPERS.get(npc.getEntity().getType()); - if (equipper == null) { - equipper = new GenericEquipper(); - } - equipper.equip(event.getPlayer(), npc); - event.setCancelled(true); - } - - private static final Map EQUIPPERS = Maps.newEnumMap(EntityType.class); - - static { - EQUIPPERS.put(EntityType.PIG, new PigEquipper()); - EQUIPPERS.put(EntityType.SHEEP, new SheepEquipper()); - EQUIPPERS.put(EntityType.ENDERMAN, new EndermanEquipper()); - EQUIPPERS.put(EntityType.HORSE, new HorseEquipper()); - } -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/editor/Equipper.java b/main/java/net/citizensnpcs/editor/Equipper.java deleted file mode 100644 index f24ff64ba..000000000 --- a/main/java/net/citizensnpcs/editor/Equipper.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.citizensnpcs.editor; - -import net.citizensnpcs.api.npc.NPC; - -import org.bukkit.entity.Player; - -public interface Equipper { - public void equip(Player equipper, NPC toEquip); -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/editor/GenericEquipper.java b/main/java/net/citizensnpcs/editor/GenericEquipper.java deleted file mode 100644 index 062fbd3fc..000000000 --- a/main/java/net/citizensnpcs/editor/GenericEquipper.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.citizensnpcs.editor; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.trait.trait.Equipment; -import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.util.Messages; - -public class GenericEquipper implements Equipper { - @Override - public void equip(Player equipper, NPC toEquip) { - ItemStack hand = equipper.getInventory().getItemInMainHand(); - Equipment trait = toEquip.getTrait(Equipment.class); - EquipmentSlot slot = EquipmentSlot.HAND; - Material type = hand == null ? Material.AIR : hand.getType(); - // First, determine the slot to edit - switch (type) { - case SKULL_ITEM: - case PUMPKIN: - case JACK_O_LANTERN: - case LEATHER_HELMET: - case CHAINMAIL_HELMET: - case GOLD_HELMET: - case IRON_HELMET: - case DIAMOND_HELMET: - if (!equipper.isSneaking()) { - slot = EquipmentSlot.HELMET; - } - break; - case ELYTRA: - case LEATHER_CHESTPLATE: - case CHAINMAIL_CHESTPLATE: - case GOLD_CHESTPLATE: - case IRON_CHESTPLATE: - case DIAMOND_CHESTPLATE: - if (!equipper.isSneaking()) { - slot = EquipmentSlot.CHESTPLATE; - } - break; - case LEATHER_LEGGINGS: - case CHAINMAIL_LEGGINGS: - case GOLD_LEGGINGS: - case IRON_LEGGINGS: - case DIAMOND_LEGGINGS: - if (!equipper.isSneaking()) { - slot = EquipmentSlot.LEGGINGS; - } - break; - case LEATHER_BOOTS: - case CHAINMAIL_BOOTS: - case GOLD_BOOTS: - case IRON_BOOTS: - case DIAMOND_BOOTS: - if (!equipper.isSneaking()) { - slot = EquipmentSlot.BOOTS; - } - break; - case AIR: - if (equipper.isSneaking()) { - for (int i = 0; i < 6; i++) { - if (trait.get(i) != null && trait.get(i).getType() != Material.AIR) { - equipper.getWorld().dropItemNaturally(toEquip.getEntity().getLocation(), trait.get(i)); - trait.set(i, null); - } - } - Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_ALL_ITEMS_REMOVED, toEquip.getName()); - } else { - return; - } - break; - default: - break; - } - // Drop any previous equipment on the ground - ItemStack equippedItem = trait.get(slot); - if (equippedItem != null && equippedItem.getType() != Material.AIR) { - equipper.getWorld().dropItemNaturally(toEquip.getEntity().getLocation(), equippedItem); - } - - // Now edit the equipment based on the slot - if (type != Material.AIR) { - // Set the proper slot with one of the item - ItemStack clone = hand.clone(); - clone.setAmount(1); - trait.set(slot, clone); - hand.setAmount(hand.getAmount() - 1); - equipper.getInventory().setItemInMainHand(hand); - } - } -} diff --git a/main/java/net/citizensnpcs/editor/HorseEquipper.java b/main/java/net/citizensnpcs/editor/HorseEquipper.java deleted file mode 100644 index 03e5b3ed2..000000000 --- a/main/java/net/citizensnpcs/editor/HorseEquipper.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.citizensnpcs.editor; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.util.NMS; - -import org.bukkit.entity.Horse; -import org.bukkit.entity.Player; - -public class HorseEquipper implements Equipper { - @Override - public void equip(Player equipper, NPC toEquip) { - Horse horse = (Horse) toEquip.getEntity(); - NMS.openHorseScreen(horse, equipper); - } -} diff --git a/main/java/net/citizensnpcs/editor/PigEquipper.java b/main/java/net/citizensnpcs/editor/PigEquipper.java deleted file mode 100644 index e81b64691..000000000 --- a/main/java/net/citizensnpcs/editor/PigEquipper.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.citizensnpcs.editor; - -import org.bukkit.Material; -import org.bukkit.entity.Pig; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.trait.Saddle; -import net.citizensnpcs.util.Messages; - -public class PigEquipper implements Equipper { - @Override - public void equip(Player equipper, NPC toEquip) { - ItemStack hand = equipper.getInventory().getItemInMainHand(); - Pig pig = (Pig) toEquip.getEntity(); - if (hand.getType() == Material.SADDLE) { - if (!pig.hasSaddle()) { - toEquip.getTrait(Saddle.class).toggle(); - hand.setAmount(0); - Messaging.sendTr(equipper, Messages.SADDLED_SET, toEquip.getName()); - } - } else if (pig.hasSaddle()) { - equipper.getWorld().dropItemNaturally(pig.getLocation(), new ItemStack(Material.SADDLE, 1)); - toEquip.getTrait(Saddle.class).toggle(); - Messaging.sendTr(equipper, Messages.SADDLED_STOPPED, toEquip.getName()); - } - equipper.getInventory().setItemInMainHand(hand); - } -} diff --git a/main/java/net/citizensnpcs/editor/SheepEquipper.java b/main/java/net/citizensnpcs/editor/SheepEquipper.java deleted file mode 100644 index d747f686e..000000000 --- a/main/java/net/citizensnpcs/editor/SheepEquipper.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.citizensnpcs.editor; - -import org.bukkit.DyeColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.entity.Sheep; -import org.bukkit.inventory.ItemStack; -import org.bukkit.material.Dye; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.trait.SheepTrait; -import net.citizensnpcs.trait.WoolColor; -import net.citizensnpcs.util.Messages; - -public class SheepEquipper implements Equipper { - @Override - public void equip(Player equipper, NPC toEquip) { - ItemStack hand = equipper.getInventory().getItemInMainHand(); - Sheep sheep = (Sheep) toEquip.getEntity(); - if (hand.getType() == Material.SHEARS) { - Messaging.sendTr(equipper, toEquip.getTrait(SheepTrait.class).toggleSheared() ? Messages.SHEARED_SET - : Messages.SHEARED_STOPPED, toEquip.getName()); - } else if (hand.getType() == Material.INK_SACK) { - Dye dye = (Dye) hand.getData(); - if (sheep.getColor() == dye.getColor()) - return; - DyeColor color = dye.getColor(); - toEquip.getTrait(WoolColor.class).setColor(color); - Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_SHEEP_COLOURED, toEquip.getName(), - color.name().toLowerCase().replace("_", " ")); - - hand.setAmount(hand.getAmount() - 1); - } else { - toEquip.getTrait(WoolColor.class).setColor(DyeColor.WHITE); - Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_SHEEP_COLOURED, toEquip.getName(), "white"); - } - equipper.getInventory().setItemInMainHand(hand); - } -} diff --git a/main/java/net/citizensnpcs/npc/AbstractEntityController.java b/main/java/net/citizensnpcs/npc/AbstractEntityController.java deleted file mode 100644 index 62113e5aa..000000000 --- a/main/java/net/citizensnpcs/npc/AbstractEntityController.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.citizensnpcs.npc; - -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.util.NMS; - -import org.bukkit.Location; -import org.bukkit.entity.Entity; - -public abstract class AbstractEntityController implements EntityController { - private Entity bukkitEntity; - - public AbstractEntityController() { - } - - public AbstractEntityController(Class clazz) { - NMS.registerEntityClass(clazz); - } - - protected abstract Entity createEntity(Location at, NPC npc); - - @Override - public Entity getBukkitEntity() { - return bukkitEntity; - } - - @Override - public void remove() { - if (bukkitEntity == null) - return; - bukkitEntity.remove(); - bukkitEntity = null; - } - - @Override - public void spawn(Location at, NPC npc) { - bukkitEntity = createEntity(at, npc); - } -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/npc/CitizensNPC.java b/main/java/net/citizensnpcs/npc/CitizensNPC.java deleted file mode 100644 index 33b9f1caf..000000000 --- a/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ /dev/null @@ -1,345 +0,0 @@ -package net.citizensnpcs.npc; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.scoreboard.Team; -import org.bukkit.scoreboard.Team.Option; -import org.bukkit.scoreboard.Team.OptionStatus; - -import com.google.common.base.Preconditions; -import com.google.common.base.Throwables; - -import net.citizensnpcs.NPCNeedsRespawnEvent; -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.ai.Navigator; -import net.citizensnpcs.api.event.DespawnReason; -import net.citizensnpcs.api.event.NPCDespawnEvent; -import net.citizensnpcs.api.event.NPCSpawnEvent; -import net.citizensnpcs.api.npc.AbstractNPC; -import net.citizensnpcs.api.npc.BlockBreaker; -import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.trait.trait.MobType; -import net.citizensnpcs.api.trait.trait.Spawned; -import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.npc.ai.CitizensBlockBreaker; -import net.citizensnpcs.npc.ai.CitizensNavigator; -import net.citizensnpcs.npc.skin.SkinnableEntity; -import net.citizensnpcs.trait.CurrentLocation; -import net.citizensnpcs.util.Messages; -import net.citizensnpcs.util.NMS; -import net.citizensnpcs.util.Util; - -public class CitizensNPC extends AbstractNPC { - private EntityController entityController; - private final CitizensNavigator navigator = new CitizensNavigator(this); - private int updateCounter = 0; - - public CitizensNPC(UUID uuid, int id, String name, EntityController entityController, NPCRegistry registry) { - super(uuid, id, name, registry); - Preconditions.checkNotNull(entityController); - this.entityController = entityController; - } - - @Override - public boolean despawn(DespawnReason reason) { - if (!isSpawned() && reason != DespawnReason.DEATH) { - Messaging.debug("Tried to despawn", getId(), "while already despawned."); - if (reason == DespawnReason.REMOVAL) { - Bukkit.getPluginManager().callEvent(new NPCDespawnEvent(this, reason)); - } - if (reason == DespawnReason.RELOAD) { - unloadEvents(); - } - return false; - } - NPCDespawnEvent event = new NPCDespawnEvent(this, reason); - if (reason == DespawnReason.CHUNK_UNLOAD) { - event.setCancelled(Setting.KEEP_CHUNKS_LOADED.asBoolean()); - } - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - getEntity().getLocation().getChunk(); - Messaging.debug("Couldn't despawn", getId(), "due to despawn event cancellation. Force loaded chunk.", - getEntity().isValid()); - return false; - } - boolean keepSelected = getTrait(Spawned.class).shouldSpawn(); - if (!keepSelected) { - data().remove("selectors"); - } - navigator.onDespawn(); - if (reason == DespawnReason.RELOAD) { - unloadEvents(); - } - for (Trait trait : new ArrayList(traits.values())) { - trait.onDespawn(); - } - Messaging.debug("Despawned", getId(), "DespawnReason.", reason); - entityController.remove(); - - return true; - } - - @Override - public void faceLocation(Location location) { - if (!isSpawned()) - return; - Util.faceLocation(getEntity(), location); - } - - @Override - public BlockBreaker getBlockBreaker(Block targetBlock, BlockBreakerConfiguration config) { - return new CitizensBlockBreaker(getEntity(), targetBlock, config); - } - - @Override - public Entity getEntity() { - return entityController == null ? null : entityController.getBukkitEntity(); - } - - @Override - public Navigator getNavigator() { - return navigator; - } - - @Override - public Location getStoredLocation() { - return isSpawned() ? getEntity().getLocation() : getTrait(CurrentLocation.class).getLocation(); - } - - @Override - public boolean isFlyable() { - updateFlyableState(); - return super.isFlyable(); - } - - @Override - public void load(final DataKey root) { - super.load(root); - - // Spawn the NPC - CurrentLocation spawnLocation = getTrait(CurrentLocation.class); - if (getTrait(Spawned.class).shouldSpawn() && spawnLocation.getLocation() != null) { - spawn(spawnLocation.getLocation()); - } - if (getTrait(Spawned.class).shouldSpawn() && spawnLocation.getLocation() == null) { - Messaging.debug("Tried to spawn", getId(), "on load but world was null"); - } - - navigator.load(root.getRelative("navigator")); - } - - @Override - public void save(DataKey root) { - super.save(root); - if (!data().get(NPC.SHOULD_SAVE_METADATA, true)) - return; - navigator.save(root.getRelative("navigator")); - } - - @Override - public void setBukkitEntityType(EntityType type) { - EntityController controller = EntityControllers.createForType(type); - if (controller == null) - throw new IllegalArgumentException("Unsupported entity type " + type); - setEntityController(controller); - } - - public void setEntityController(EntityController newController) { - Preconditions.checkNotNull(newController); - boolean wasSpawned = isSpawned(); - Location prev = null; - if (wasSpawned) { - prev = getEntity().getLocation(); - despawn(DespawnReason.PENDING_RESPAWN); - } - entityController = newController; - if (wasSpawned) { - spawn(prev); - } - } - - @Override - public void setFlyable(boolean flyable) { - super.setFlyable(flyable); - updateFlyableState(); - } - - @Override - public boolean spawn(Location at) { - Preconditions.checkNotNull(at, "location cannot be null"); - if (isSpawned()) { - Messaging.debug("Tried to spawn", getId(), "while already spawned."); - return false; - } - data().get(NPC.DEFAULT_PROTECTED_METADATA, true); - - at = at.clone(); - getTrait(CurrentLocation.class).setLocation(at); - - entityController.spawn(at, this); - - getEntity().setMetadata(NPC_METADATA_MARKER, new FixedMetadataValue(CitizensAPI.getPlugin(), true)); - - boolean couldSpawn = !Util.isLoaded(at) ? false : NMS.addEntityToWorld(getEntity(), SpawnReason.CUSTOM); - - // send skin packets, if applicable, before other NMS packets are sent - if (couldSpawn) { - SkinnableEntity skinnable = getEntity() instanceof SkinnableEntity ? ((SkinnableEntity) getEntity()) : null; - if (skinnable != null) { - skinnable.getSkinTracker().onSpawnNPC(); - } - } - - getEntity().teleport(at); - - if (!couldSpawn) { - Messaging.debug("Retrying spawn of", getId(), "later due to chunk being unloaded.", - Util.isLoaded(at) ? "Util.isLoaded true" : "Util.isLoaded false"); - // we need to wait for a chunk load before trying to spawn - entityController.remove(); - Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at)); - return false; - } - - NMS.setHeadYaw(getEntity(), at.getYaw()); - - // Set the spawned state - getTrait(CurrentLocation.class).setLocation(at); - getTrait(Spawned.class).setSpawned(true); - - NPCSpawnEvent spawnEvent = new NPCSpawnEvent(this, at); - Bukkit.getPluginManager().callEvent(spawnEvent); - - if (spawnEvent.isCancelled()) { - entityController.remove(); - Messaging.debug("Couldn't spawn", getId(), "due to event cancellation."); - return false; - } - - navigator.onSpawn(); - - // Modify NPC using traits after the entity has been created - Collection onSpawn = traits.values(); - - // work around traits modifying the map during this iteration. - for (Trait trait : onSpawn.toArray(new Trait[onSpawn.size()])) { - try { - trait.onSpawn(); - } catch (Throwable ex) { - Messaging.severeTr(Messages.TRAIT_ONSPAWN_FAILED, trait.getName(), getId()); - ex.printStackTrace(); - } - } - - if (getEntity() instanceof LivingEntity) { - LivingEntity entity = (LivingEntity) getEntity(); - entity.setRemoveWhenFarAway(false); - - if (NMS.getStepHeight(entity) < 1) { - NMS.setStepHeight(entity, 1); - } - if (getEntity() instanceof Player) { - NMS.replaceTrackerEntry((Player) getEntity()); - } - } - - return true; - } - - @Override - public void update() { - try { - super.update(); - if (!isSpawned()) - return; - if (data().get(NPC.SWIMMING_METADATA, true)) { - NMS.trySwim(getEntity()); - } - navigator.run(); - - getEntity().setGlowing(data().get(NPC.GLOWING_METADATA, false)); - if (!getNavigator().isNavigating() && updateCounter++ > Setting.PACKET_UPDATE_DELAY.asInt()) { - updateCounter = 0; - if (getEntity() instanceof LivingEntity) { - OptionStatus nameVisibility = OptionStatus.NEVER; - if (!getEntity().isCustomNameVisible()) { - getEntity().setCustomName(""); - } else { - nameVisibility = OptionStatus.ALWAYS; - getEntity().setCustomName(getFullName()); - } - String teamName = data().get(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA, ""); - if (getEntity() instanceof Player - && Bukkit.getScoreboardManager().getMainScoreboard().getTeam(teamName) != null) { - Team team = Bukkit.getScoreboardManager().getMainScoreboard().getTeam(teamName); - if (!Setting.USE_SCOREBOARD_TEAMS.asBoolean()) { - team.unregister(); - data().remove(NPC.SCOREBOARD_FAKE_TEAM_NAME_METADATA); - } else { - team.setOption(Option.NAME_TAG_VISIBILITY, nameVisibility); - if (data().has(NPC.GLOWING_COLOR_METADATA)) { - if (team.getPrefix() == null || team.getPrefix().length() == 0 - || (data().has("previous-glowing-color") - && !team.getPrefix().equals(data().get("previous-glowing-color")))) { - team.setPrefix(ChatColor.valueOf(data(). get(NPC.GLOWING_COLOR_METADATA)) - .toString()); - data().set("previous-glowing-color", team.getPrefix()); - } - } - } - } - } - Player player = getEntity() instanceof Player ? (Player) getEntity() : null; - NMS.sendPositionUpdate(player, getEntity(), getStoredLocation()); - } - - if (getEntity() instanceof LivingEntity) { - boolean nameplateVisible = data().get(NPC.NAMEPLATE_VISIBLE_METADATA, true); - ((LivingEntity) getEntity()).setCustomNameVisible(nameplateVisible); - - if (data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { - NMS.setKnockbackResistance((LivingEntity) getEntity(), 1D); - } else { - NMS.setKnockbackResistance((LivingEntity) getEntity(), 0D); - } - } - - if (data().has(NPC.SILENT_METADATA)) { - getEntity().setSilent(Boolean.parseBoolean(data().get(NPC.SILENT_METADATA).toString())); - } - } catch (Exception ex) { - Throwable error = Throwables.getRootCause(ex); - Messaging.logTr(Messages.EXCEPTION_UPDATING_NPC, getId(), error.getMessage()); - error.printStackTrace(); - } - } - - private void updateFlyableState() { - EntityType type = isSpawned() ? getEntity().getType() : getTrait(MobType.class).getType(); - if (type == null) - return; - if (Util.isAlwaysFlyable(type)) { - data().setPersistent(NPC.FLYABLE_METADATA, true); - } - } - - private static final String NPC_METADATA_MARKER = "NPC"; -} diff --git a/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java b/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java deleted file mode 100644 index 49cea2d80..000000000 --- a/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java +++ /dev/null @@ -1,251 +0,0 @@ -package net.citizensnpcs.npc; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; - -import gnu.trove.map.hash.TIntObjectHashMap; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.event.DespawnReason; -import net.citizensnpcs.api.event.NPCCreateEvent; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.npc.NPCDataStore; -import net.citizensnpcs.api.npc.NPCRegistry; -import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.npc.ai.NPCHolder; -import net.citizensnpcs.trait.ArmorStandTrait; -import net.citizensnpcs.util.NMS; - -public class CitizensNPCRegistry implements NPCRegistry { - private final NPCCollection npcs = TROVE_EXISTS ? new TroveNPCCollection() : new MapNPCCollection(); - private final NPCDataStore saves; - - public CitizensNPCRegistry(NPCDataStore store) { - saves = store; - } - - @Override - public NPC createNPC(EntityType type, String name) { - return createNPC(type, UUID.randomUUID(), generateUniqueId(), name); - } - - @Override - public NPC createNPC(EntityType type, UUID uuid, int id, String name) { - Preconditions.checkNotNull(name, "name cannot be null"); - Preconditions.checkNotNull(type, "type cannot be null"); - CitizensNPC npc = getByType(type, uuid, id, name); - - if (npc == null) - throw new IllegalStateException("Could not create NPC."); - npcs.put(npc.getId(), npc); - Bukkit.getPluginManager().callEvent(new NPCCreateEvent(npc)); - if (type == EntityType.ARMOR_STAND && !npc.hasTrait(ArmorStandTrait.class)) { - npc.addTrait(ArmorStandTrait.class); - } - return npc; - } - - @Override - public void deregister(NPC npc) { - npcs.remove(npc); - if (saves != null) { - saves.clearData(npc); - } - npc.despawn(DespawnReason.REMOVAL); - } - - @Override - public void deregisterAll() { - Iterator itr = iterator(); - while (itr.hasNext()) { - NPC npc = itr.next(); - itr.remove(); - npc.despawn(DespawnReason.REMOVAL); - for (Trait t : npc.getTraits()) { - t.onRemove(); - } - if (saves != null) { - saves.clearData(npc); - } - } - } - - private int generateUniqueId() { - return saves.createUniqueNPCId(this); - } - - @Override - public NPC getById(int id) { - if (id < 0) - throw new IllegalArgumentException("invalid id"); - return npcs.get(id); - } - - private CitizensNPC getByType(EntityType type, UUID uuid, int id, String name) { - return new CitizensNPC(uuid, id, name, EntityControllers.createForType(type), this); - } - - @Override - public NPC getByUniqueId(UUID uuid) { - return npcs.get(uuid); - } - - @Override - public NPC getByUniqueIdGlobal(UUID uuid) { - NPC npc = getByUniqueId(uuid); - if (npc != null) - return npc; - for (NPCRegistry registry : CitizensAPI.getNPCRegistries()) { - if (registry != this) { - NPC other = registry.getByUniqueId(uuid); - if (other != null) { - return other; - } - } - } - return null; - } - - @Override - public NPC getNPC(Entity entity) { - if (entity == null) - return null; - if (entity instanceof NPCHolder) - return ((NPCHolder) entity).getNPC(); - return NMS.getNPC(entity); - } - - @Override - public boolean isNPC(Entity entity) { - return getNPC(entity) != null; - } - - @Override - public Iterator iterator() { - return npcs.iterator(); - } - - @Override - public Iterable sorted() { - return npcs.sorted(); - } - - public static class MapNPCCollection implements NPCCollection { - private final Map npcs = Maps.newHashMap(); - private final Map uniqueNPCs = Maps.newHashMap(); - - @Override - public NPC get(int id) { - return npcs.get(id); - } - - @Override - public NPC get(UUID uuid) { - return uniqueNPCs.get(uuid); - } - - @Override - public Iterator iterator() { - return npcs.values().iterator(); - } - - @Override - public void put(int id, NPC npc) { - npcs.put(id, npc); - uniqueNPCs.put(npc.getUniqueId(), npc); - } - - @Override - public void remove(NPC npc) { - npcs.remove(npc.getId()); - uniqueNPCs.remove(npc.getUniqueId()); - } - - @Override - public Iterable sorted() { - List vals = new ArrayList(npcs.values()); - Collections.sort(vals, NPC_COMPARATOR); - return vals; - } - } - - public static interface NPCCollection extends Iterable { - public NPC get(int id); - - public NPC get(UUID uuid); - - public void put(int id, NPC npc); - - public void remove(NPC npc); - - public Iterable sorted(); - } - - public static class TroveNPCCollection implements NPCCollection { - private final TIntObjectHashMap npcs = new TIntObjectHashMap(); - private final Map uniqueNPCs = Maps.newHashMap(); - - @Override - public NPC get(int id) { - return npcs.get(id); - } - - @Override - public NPC get(UUID uuid) { - return uniqueNPCs.get(uuid); - } - - @Override - public Iterator iterator() { - return npcs.valueCollection().iterator(); - } - - @Override - public void put(int id, NPC npc) { - npcs.put(id, npc); - uniqueNPCs.put(npc.getUniqueId(), npc); - } - - @Override - public void remove(NPC npc) { - npcs.remove(npc.getId()); - uniqueNPCs.remove(npc.getUniqueId()); - } - - @Override - public Iterable sorted() { - List vals = new ArrayList(npcs.valueCollection()); - Collections.sort(vals, NPC_COMPARATOR); - return vals; - } - } - - private static final Comparator NPC_COMPARATOR = new Comparator() { - @Override - public int compare(NPC o1, NPC o2) { - return o1.getId() - o2.getId(); - } - }; - - private static boolean TROVE_EXISTS = false; - - static { - // allow trove dependency to be optional for debugging purposes - try { - Class.forName("gnu.trove.map.hash.TIntObjectHashMap").newInstance(); - TROVE_EXISTS = true; - } catch (Exception e) { - } - } -} \ No newline at end of file diff --git a/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java deleted file mode 100644 index 8a787de23..000000000 --- a/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ /dev/null @@ -1,177 +0,0 @@ -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 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.toLowerCase()); - if (info == null) - return null; - return (T) create(info); - } - - @Override - public Class 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/main/java/net/citizensnpcs/npc/EntityController.java b/main/java/net/citizensnpcs/npc/EntityController.java deleted file mode 100644 index 65259c6c8..000000000 --- a/main/java/net/citizensnpcs/npc/EntityController.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.citizensnpcs.npc; - -import net.citizensnpcs.api.npc.NPC; - -import org.bukkit.Location; -import org.bukkit.entity.Entity; - -public interface EntityController { - Entity getBukkitEntity(); - - void remove(); - - void spawn(Location at, NPC npc); -} diff --git a/main/java/net/citizensnpcs/npc/EntityControllers.java b/main/java/net/citizensnpcs/npc/EntityControllers.java deleted file mode 100644 index 289a469c3..000000000 --- a/main/java/net/citizensnpcs/npc/EntityControllers.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.citizensnpcs.npc; - -import java.util.Map; - -import org.bukkit.entity.EntityType; - -import com.google.common.base.Throwables; -import com.google.common.collect.Maps; - -public class EntityControllers { - public static boolean controllerExistsForType(EntityType type) { - return TYPES.containsKey(type); - } - - public static EntityController createForType(EntityType type) { - Class controllerClass = TYPES.get(type); - if (controllerClass == null) - throw new IllegalArgumentException("Unknown EntityType: " + type); - try { - return controllerClass.newInstance(); - } catch (Throwable ex) { - Throwables.getRootCause(ex).printStackTrace(); - return null; - } - } - - public static void setEntityControllerForType(EntityType type, Class controller) { - TYPES.put(type, controller); - } - - private static final Map> TYPES = Maps.newEnumMap(EntityType.class); -} diff --git a/main/java/net/citizensnpcs/npc/NPCSelector.java b/main/java/net/citizensnpcs/npc/NPCSelector.java deleted file mode 100644 index bddd5ecdd..000000000 --- a/main/java/net/citizensnpcs/npc/NPCSelector.java +++ /dev/null @@ -1,148 +0,0 @@ -package net.citizensnpcs.npc; - -import java.util.List; -import java.util.UUID; - -import net.citizensnpcs.Settings.Setting; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.event.NPCRemoveEvent; -import net.citizensnpcs.api.event.NPCRightClickEvent; -import net.citizensnpcs.api.event.NPCSelectEvent; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.trait.trait.Owner; -import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.editor.Editor; -import net.citizensnpcs.util.Util; - -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.metadata.MetadataValue; -import org.bukkit.metadata.Metadatable; -import org.bukkit.plugin.Plugin; - -import com.google.common.collect.Lists; - -public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelector { - private UUID consoleSelectedNPC; - private final Plugin plugin; - - public NPCSelector(Plugin plugin) { - this.plugin = plugin; - Bukkit.getPluginManager().registerEvents(this, plugin); - } - - @Override - public NPC getSelected(CommandSender sender) { - if (sender instanceof Player) { - return getSelectedFromMetadatable((Player) sender); - } else if (sender instanceof BlockCommandSender) { - return getSelectedFromMetadatable(((BlockCommandSender) sender).getBlock()); - } else if (sender instanceof ConsoleCommandSender) { - if (consoleSelectedNPC == null) - return null; - return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(consoleSelectedNPC); - } - return null; - } - - private NPC getSelectedFromMetadatable(Metadatable sender) { - List metadata = sender.getMetadata("selected"); - if (metadata.size() == 0) - return null; - return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal((UUID) metadata.get(0).value()); - } - - @EventHandler - public void onNPCRemove(NPCRemoveEvent event) { - NPC npc = event.getNPC(); - List selectors = npc.data().get("selectors"); - if (selectors == null) - return; - for (String value : selectors) { - if (value.equals("console")) { - consoleSelectedNPC = null; - } else if (value.startsWith("@")) { - String[] parts = value.substring(1, value.length()).split(":"); - World world = Bukkit.getWorld(parts[0]); - if (world != null) { - Block block = world.getBlockAt(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), - Integer.parseInt(parts[3])); - removeMetadata(block); - } - } else { - Player search = Bukkit.getPlayerExact(value); - removeMetadata(search); - } - } - npc.data().remove("selectors"); - } - - @EventHandler - public void onNPCRightClick(NPCRightClickEvent event) { - Player player = event.getClicker(); - NPC npc = event.getNPC(); - List selected = player.getMetadata("selected"); - if (selected == null || selected.size() == 0 || selected.get(0).asInt() != npc.getId()) { - if (Util.matchesItemInHand(player, Setting.SELECTION_ITEM.asString()) - && npc.getTrait(Owner.class).isOwnedBy(player)) { - player.removeMetadata("selected", plugin); - select(player, npc); - Messaging.sendWithNPC(player, Setting.SELECTION_MESSAGE.asString(), npc); - if (!Setting.QUICK_SELECT.asBoolean()) - return; - } - } - } - - private void removeMetadata(Metadatable metadatable) { - if (metadatable != null) { - metadatable.removeMetadata("selected", plugin); - } - } - - public void select(CommandSender sender, NPC npc) { - // Remove existing selection if any - List selectors = npc.data().get("selectors"); - if (selectors == null) { - selectors = Lists.newArrayList(); - npc.data().set("selectors", selectors); - } - if (sender instanceof Player) { - Player player = (Player) sender; - setMetadata(npc, player); - selectors.add(sender.getName()); - - // Remove editor if the player has one - Editor.leave(player); - } else if (sender instanceof BlockCommandSender) { - Block block = ((BlockCommandSender) sender).getBlock(); - setMetadata(npc, block); - selectors.add(toName(block)); - } else if (sender instanceof ConsoleCommandSender) { - consoleSelectedNPC = npc.getUniqueId(); - selectors.add("console"); - } - - Bukkit.getPluginManager().callEvent(new NPCSelectEvent(npc, sender)); - } - - private void setMetadata(NPC npc, Metadatable metadatable) { - if (metadatable.hasMetadata("selected")) { - metadatable.removeMetadata("selected", plugin); - } - metadatable.setMetadata("selected", new FixedMetadataValue(plugin, npc.getUniqueId())); - } - - private String toName(Block block) { - return '@' + block.getWorld().getName() + ":" + Integer.toString(block.getX()) + ":" - + Integer.toString(block.getY()) + ":" + Integer.toString(block.getZ()); - } -} diff --git a/main/java/net/citizensnpcs/npc/Template.java b/main/java/net/citizensnpcs/npc/Template.java deleted file mode 100644 index 762628c55..000000000 --- a/main/java/net/citizensnpcs/npc/Template.java +++ /dev/null @@ -1,138 +0,0 @@ -package net.citizensnpcs.npc; - -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.npc.NPC; -import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.api.util.MemoryDataKey; -import net.citizensnpcs.api.util.YamlStorage; -import net.citizensnpcs.api.util.YamlStorage.YamlKey; - -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -public class Template { - private final String name; - private final boolean override; - private final Map replacements; - - private Template(String name, Map replacements, boolean override) { - this.replacements = replacements; - this.override = override; - this.name = name; - } - - @SuppressWarnings("unchecked") - public void apply(NPC npc) { - MemoryDataKey memoryKey = new MemoryDataKey(); - npc.save(memoryKey); - List queue = Lists.newArrayList(new Node("", replacements)); - for (int i = 0; i < queue.size(); i++) { - Node node = queue.get(i); - for (Entry entry : node.map.entrySet()) { - String fullKey = node.headKey.isEmpty() ? entry.getKey() : node.headKey + '.' + entry.getKey(); - if (entry.getValue() instanceof Map) { - queue.add(new Node(fullKey, (Map) entry.getValue())); - continue; - } - boolean overwrite = memoryKey.keyExists(fullKey) | override; - if (!overwrite || fullKey.equals("uuid")) - continue; - memoryKey.setRaw(fullKey, entry.getValue()); - } - } - npc.load(memoryKey); - } - - public void delete() { - templates.load(); - templates.getKey("").removeKey(name); - templates.save(); - } - - public String getName() { - return name; - } - - private static class Node { - String headKey; - Map map; - - private Node(String headKey, Map map) { - this.headKey = headKey; - this.map = map; - } - } - - public static class TemplateBuilder { - private final String name; - private boolean override; - private final Map replacements = Maps.newHashMap(); - - private TemplateBuilder(String name) { - this.name = name; - } - - public Template buildAndSave() { - save(); - return new Template(name, replacements, override); - } - - public TemplateBuilder from(NPC npc) { - replacements.clear(); - MemoryDataKey key = new MemoryDataKey(); - ((CitizensNPC) npc).save(key); - replacements.putAll(key.getValuesDeep()); - return this; - } - - public TemplateBuilder override(boolean override) { - this.override = override; - return this; - } - - public void save() { - templates.load(); - DataKey root = templates.getKey(name); - root.setBoolean("override", override); - root.setRaw("replacements", replacements); - templates.save(); - } - - public static TemplateBuilder create(String name) { - return new TemplateBuilder(name); - } - } - - public static Iterable