diff --git a/src/net/citizensnpcs/Citizens.java b/src/net/citizensnpcs/Citizens.java index 9a26255ba..c3ff5838a 100644 --- a/src/net/citizensnpcs/Citizens.java +++ b/src/net/citizensnpcs/Citizens.java @@ -19,6 +19,7 @@ import net.citizensnpcs.api.npc.trait.InstanceFactory; import net.citizensnpcs.api.npc.trait.Trait; import net.citizensnpcs.api.npc.trait.trait.SpawnLocation; import net.citizensnpcs.command.CommandManager; +import net.citizensnpcs.command.Injector; import net.citizensnpcs.command.command.NPCCommands; import net.citizensnpcs.command.exception.CommandUsageException; import net.citizensnpcs.command.exception.MissingNestedCommandException; @@ -167,6 +168,14 @@ public class Citizens extends JavaPlugin { return saves; } + public CitizensNPCManager getNPCManager() { + return npcManager; + } + + public InstanceFactory getCharacterManager() { + return characterManager; + } + private void saveNPCs() { for (NPC npc : npcManager.getAllNPCs()) ((CitizensNPC) npc).save(); @@ -213,6 +222,7 @@ public class Citizens extends JavaPlugin { private void registerPermissions() { Map children = new HashMap(); + children.put("citizens.npc.create", true); children.put("citizens.npc.spawn", true); children.put("citizens.npc.despawn", true); children.put("citizens.npc.select", true); @@ -222,6 +232,8 @@ public class Citizens extends JavaPlugin { } private void registerCommands() { + cmdManager.setInjector(new Injector(this)); + cmdManager.register(NPCCommands.class); } diff --git a/src/net/citizensnpcs/command/CommandManager.java b/src/net/citizensnpcs/command/CommandManager.java index 15e5ef7e5..f938708b1 100644 --- a/src/net/citizensnpcs/command/CommandManager.java +++ b/src/net/citizensnpcs/command/CommandManager.java @@ -58,23 +58,23 @@ public class CommandManager { * their respective {@link Method}. The child map has the key of the command * name (one for each alias) with the method. */ - private Map> commands = new HashMap>(); + private final Map> commands = new HashMap>(); // Used to store the instances associated with a method. - private Map instances = new HashMap(); + private final Map instances = new HashMap(); /* * Mapping of commands (not including aliases) with a description. This is * only for top level commands. */ - private Map descs = new HashMap(); + private final Map descs = new HashMap(); // Stores the injector used to getInstance. private Injector injector; - private Map requirements = new HashMap(); + private final Map requirements = new HashMap(); - private Map serverCommands = new HashMap(); + private final Map serverCommands = new HashMap(); /* * Register an class that contains commands (denoted by {@link Command}. If @@ -82,33 +82,21 @@ public class CommandManager { * be registered to be called statically. Otherwise, new instances will be * created of the command classes and methods will not be called statically. */ - public void register(Class cls) { - registerMethods(cls, null); + public void register(Class clazz) { + registerMethods(clazz, null); } /* * Register the methods of a class. This will automatically construct * instances as necessary. */ - private void registerMethods(Class cls, Method parent) { - try { - if (getInjector() == null) - registerMethods(cls, parent, null); - else { - Object obj = getInjector().getInstance(cls); - registerMethods(cls, parent, obj); - } - } catch (InvocationTargetException e) { - logger.log(Level.SEVERE, "Failed to register commands", e); - } catch (IllegalAccessException e) { - logger.log(Level.SEVERE, "Failed to register commands", e); - } catch (InstantiationException e) { - logger.log(Level.SEVERE, "Failed to register commands", e); - } + private void registerMethods(Class clazz, Method parent) { + Object obj = injector.getInstance(clazz); + registerMethods(clazz, parent, obj); } // Register the methods of a class. - private void registerMethods(Class cls, Method parent, Object obj) { + private void registerMethods(Class clazz, Method parent, Object obj) { Map map; // Make a new hash map to cache the commands for this class @@ -120,7 +108,7 @@ public class CommandManager { commands.put(parent, map); } - for (Method method : cls.getMethods()) { + for (Method method : clazz.getMethods()) { if (!method.isAnnotationPresent(Command.class)) continue; boolean isStatic = Modifier.isStatic(method.getModifiers()); @@ -157,7 +145,6 @@ public class CommandManager { continue; instances.put(method, obj); - Messaging.log("Put instance."); } // Build a list of commands and their usage details, at least for @@ -379,19 +366,6 @@ public class CommandManager { return false; } - /* - * Get the injector used to create new instances. This can be null, in which - * case only classes will be registered statically. - */ - public Injector getInjector() { - return injector; - } - - // Set the injector for creating new instances. - public void setInjector(Injector injector) { - this.injector = injector; - } - // Returns whether a player has permission. private boolean hasPermission(Player player, String perm) { return ((Player) player).hasPermission("citizens." + perm); @@ -408,4 +382,8 @@ public class CommandManager { } return cmds.toArray(new String[cmds.size()]); } + + public void setInjector(Injector injector) { + this.injector = injector; + } } \ No newline at end of file diff --git a/src/net/citizensnpcs/command/Injector.java b/src/net/citizensnpcs/command/Injector.java index 76e82c73d..3a4a01e6e 100644 --- a/src/net/citizensnpcs/command/Injector.java +++ b/src/net/citizensnpcs/command/Injector.java @@ -6,10 +6,46 @@ package net.citizensnpcs.command; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; -public interface Injector { +import net.citizensnpcs.util.Messaging; - public Object getInstance(Class cls) throws InvocationTargetException, IllegalAccessException, - InstantiationException; +public class Injector { + + private Object[] args; + private Class[] argClasses; + + public Injector(Object... args) { + this.args = args; + argClasses = new Class[args.length]; + for (int i = 0; i < args.length; ++i) { + argClasses[i] = args[i].getClass(); + } + } + + public Object getInstance(Class clazz) { + try { + Constructor ctr = clazz.getConstructor(argClasses); + ctr.setAccessible(true); + return ctr.newInstance(args); + } catch (NoSuchMethodException e) { + Messaging.log(Level.SEVERE, "Error initializing commands class " + clazz + ": "); + e.printStackTrace(); + return null; + } catch (InvocationTargetException e) { + Messaging.log(Level.SEVERE, "Error initializing commands class " + clazz + ": "); + e.printStackTrace(); + return null; + } catch (InstantiationException e) { + Messaging.log(Level.SEVERE, "Error initializing commands class " + clazz + ": "); + e.printStackTrace(); + return null; + } catch (IllegalAccessException e) { + Messaging.log(Level.SEVERE, "Error initializing commands class " + clazz + ": "); + e.printStackTrace(); + return null; + } + } } \ No newline at end of file diff --git a/src/net/citizensnpcs/command/command/NPCCommands.java b/src/net/citizensnpcs/command/command/NPCCommands.java index 3717e8709..451a4d155 100644 --- a/src/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/net/citizensnpcs/command/command/NPCCommands.java @@ -1,30 +1,66 @@ package net.citizensnpcs.command.command; +import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.Citizens; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.command.CommandContext; import net.citizensnpcs.command.annotation.Command; import net.citizensnpcs.command.annotation.Permission; import net.citizensnpcs.npc.CitizensNPC; -import net.citizensnpcs.npc.CitizensNPCManager; +import net.citizensnpcs.util.Messaging; +import net.citizensnpcs.util.StringHelper; // TODO add requirements public class NPCCommands { + private final Citizens plugin; + + public NPCCommands(Citizens plugin) { + this.plugin = plugin; + } @Command( aliases = { "npc" }, - usage = "spawn [name]", - desc = "Spawn an NPC", - modifiers = { "spawn", "create" }, + usage = "create [name] (character)", + desc = "Create a new NPC", + modifiers = { "create" }, + min = 2, + max = 3) + @Permission("npc.create") + public void createNPC(CommandContext args, Player player, NPC npc) { + CitizensNPC create = (CitizensNPC) plugin.getNPCManager().createNPC(args.getString(1)); + String msg = ChatColor.GREEN + "You created " + StringHelper.wrap(create.getName()); + if (args.argsLength() == 3 && plugin.getCharacterManager().getInstance(args.getString(2)) != null) { + create.setCharacter(plugin.getCharacterManager().getInstance(args.getString(2))); + msg += " with the character " + StringHelper.wrap(args.getString(2)); + } + msg += " at your location."; + + create.spawn(player.getLocation()); + plugin.getNPCManager().selectNPC(player, create); + Messaging.send(player, msg); + } + + @Command( + aliases = { "npc" }, + usage = "spawn [id]", + desc = "Spawn an existing NPC", + modifiers = { "spawn" }, min = 2, max = 2) @Permission("npc.spawn") - public static void spawnNPC(CommandContext args, Player player, NPC npc) { - CitizensNPC create = (CitizensNPC) CitizensAPI.getNPCManager().createNPC(args.getString(1)); - create.spawn(player.getLocation()); - create.save(); + public void spawnNPC(CommandContext args, Player player, NPC npc) { + CitizensNPC respawn = (CitizensNPC) plugin.getNPCManager().getNPC(args.getInteger(1)); + if (respawn == null) { + Messaging.sendError(player, "No NPC with the ID '" + args.getInteger(1) + "' exists."); + return; + } + + respawn.spawn(player.getLocation()); + plugin.getNPCManager().selectNPC(player, respawn); + Messaging.send(player, ChatColor.GREEN + "You respawned " + StringHelper.wrap(respawn.getName()) + + " at your location."); } @Command( @@ -35,8 +71,10 @@ public class NPCCommands { min = 1, max = 1) @Permission("npc.despawn") - public static void despawnNPC(CommandContext args, Player player, NPC npc) { - CitizensNPC despawn = (CitizensNPC) ((CitizensNPCManager) CitizensAPI.getNPCManager()).getSelectedNPC(player); + public void despawnNPC(CommandContext args, Player player, NPC npc) { + CitizensNPC despawn = (CitizensNPC) plugin.getNPCManager().getSelectedNPC(player); despawn.despawn(); + plugin.getNPCManager().deselectNPC(player); + Messaging.send(player, ChatColor.GREEN + "You despawned " + StringHelper.wrap(despawn.getName()) + "."); } } \ No newline at end of file diff --git a/src/net/citizensnpcs/npc/CitizensNPC.java b/src/net/citizensnpcs/npc/CitizensNPC.java index 8f49306e0..d576ee89c 100644 --- a/src/net/citizensnpcs/npc/CitizensNPC.java +++ b/src/net/citizensnpcs/npc/CitizensNPC.java @@ -41,6 +41,7 @@ public class CitizensNPC extends AbstractNPC { getHandle().die(); spawned = false; + save(); } @Override @@ -90,6 +91,7 @@ public class CitizensNPC extends AbstractNPC { addTrait(new SpawnLocation(loc)); spawned = true; + save(); } @Override diff --git a/src/net/citizensnpcs/npc/CitizensNPCManager.java b/src/net/citizensnpcs/npc/CitizensNPCManager.java index 6c9e3db24..629679a95 100644 --- a/src/net/citizensnpcs/npc/CitizensNPCManager.java +++ b/src/net/citizensnpcs/npc/CitizensNPCManager.java @@ -144,6 +144,10 @@ public class CitizensNPCManager implements NPCManager { selected.put(player.getName(), npc.getId()); } + public void deselectNPC(Player player) { + selected.remove(player.getName()); + } + public boolean npcIsSelectedByPlayer(Player player, NPC npc) { if (!selected.containsKey(player.getName())) return false;