Runnables

This commit is contained in:
fullwall 2012-02-07 17:45:43 +08:00
parent 2a51adcaab
commit 3c1f9fd8c0
7 changed files with 137 additions and 130 deletions

View File

@ -25,7 +25,9 @@ import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -50,8 +52,37 @@ import net.citizensnpcs.util.Messaging;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import com.google.common.collect.Lists;
public class CommandManager {
/*
* Mapping of commands (including aliases) with a description. Root commands
* are stored under a key of null, whereas child commands are cached under
* their respective Method. The child map has the key of the command name
* (one for each alias) with the method.
*/
private final Map<Method, Map<CommandIdentifier, Method>> commands = new HashMap<Method, Map<CommandIdentifier, Method>>();
/*
* Mapping of commands (not including aliases) with a description. This is
* only for top level commands.
*/
// private final Map<CommandIdentifier, String> descs = new
// HashMap<CommandIdentifier, String>();
private final Map<String, List<Command>> subCommands = new HashMap<String, List<Command>>();
// Stores the injector used to getInstance.
private Injector injector;
// Used to store the instances associated with a method.
private final Map<Method, Object> instances = new HashMap<Method, Object>();
private final Map<Method, Requirements> requirements = new HashMap<Method, Requirements>();
private final Map<Method, ServerCommand> serverCommands = new HashMap<Method, ServerCommand>();
/*
* Attempt to execute a command. This version takes a separate command name
* (for the root command) and then a list of following arguments.
@ -168,10 +199,10 @@ public class CommandManager {
return cmds.toArray(new String[cmds.size()]);
}
// Get a list of command descriptions. This is only for root commands.
public Map<CommandIdentifier, String> getCommands() {
return descs;
}
/* // Get a list of command descriptions. This is only for root commands.
public Map<CommandIdentifier, String> getCommands() {
return descs;
}*/
// Get the usage string for a nested command.
private String getNestedUsage(String[] args, int level, Method method, Player player) throws CommandException {
@ -229,6 +260,28 @@ public class CommandManager {
return command.toString();
}
/*
* Checks to see whether there is a command named such at the root level.
* This will check aliases as well.
*/
public boolean hasCommand(String command, String modifier) {
return commands.get(null).containsKey(new CommandIdentifier(command.toLowerCase(), modifier.toLowerCase()))
|| commands.get(null).containsKey(new CommandIdentifier(command.toLowerCase(), "*"));
}
public List<Command> getCommands(String command) {
if (subCommands.containsKey(command))
return subCommands.get(command);
List<Command> cmds = Lists.newArrayList();
for (Entry<CommandIdentifier, Method> entry : commands.get(null).entrySet()) {
if (!entry.getKey().getCommand().equalsIgnoreCase(command)
|| !entry.getValue().isAnnotationPresent(Command.class))
continue;
cmds.add(entry.getValue().getAnnotation(Command.class));
}
return cmds;
}
// Returns whether a player has access to a command.
private boolean hasPermission(Method method, Player player) {
Permission permission = method.getAnnotation(Permission.class);
@ -246,46 +299,6 @@ public class CommandManager {
return player.hasPermission("citizens." + perm);
}
public void setInjector(Injector injector) {
this.injector = injector;
}
// Logger for general errors.
private static final Logger logger = Logger.getLogger(CommandManager.class.getCanonicalName());
/*
* Mapping of commands (including aliases) with a description. Root commands
* are stored under a key of null, whereas child commands are cached under
* their respective Method. The child map has the key of the command name
* (one for each alias) with the method.
*/
private final Map<Method, Map<CommandIdentifier, Method>> commands = new HashMap<Method, Map<CommandIdentifier, Method>>();
// Used to store the instances associated with a method.
private final Map<Method, Object> instances = new HashMap<Method, Object>();
/*
* Mapping of commands (not including aliases) with a description. This is
* only for top level commands.
*/
private final Map<CommandIdentifier, String> descs = new HashMap<CommandIdentifier, String>();
// Stores the injector used to getInstance.
private Injector injector;
private final Map<Method, Requirements> requirements = new HashMap<Method, Requirements>();
private final Map<Method, ServerCommand> serverCommands = new HashMap<Method, ServerCommand>();
/*
* Checks to see whether there is a command named such at the root level.
* This will check aliases as well.
*/
public boolean hasCommand(String command, String modifier) {
return commands.get(null).containsKey(new CommandIdentifier(command.toLowerCase(), modifier.toLowerCase()))
|| commands.get(null).containsKey(new CommandIdentifier(command.toLowerCase(), "*"));
}
/*
* Register an class that contains commands (denoted by Command. If no
* dependency injector is specified, then the methods of the class will be
@ -357,7 +370,7 @@ public class CommandManager {
instances.put(method, obj);
}
// Build a list of commands and their usage details, at least for
/*// Build a list of commands and their usage details, at least for
// root level commands
if (parent == null)
if (cmd.usage().length() == 0)
@ -365,6 +378,7 @@ public class CommandManager {
else
descs.put(new CommandIdentifier(cmd.aliases()[0], cmd.modifiers()[0]),
cmd.usage() + " - " + cmd.desc());
*/
// Look for nested commands -- if there are any, those have
// to be cached too so that they can be quickly looked
@ -378,6 +392,13 @@ public class CommandManager {
}
}
public void setInjector(Injector injector) {
this.injector = injector;
}
// Logger for general errors.
private static final Logger logger = Logger.getLogger(CommandManager.class.getCanonicalName());
public static String joinString(Collection<?> str, String delimiter, int initialIndex) {
if (str.size() == 0)
return "";

View File

@ -11,7 +11,6 @@ import net.citizensnpcs.command.CommandContext;
import net.citizensnpcs.command.annotation.Command;
import net.citizensnpcs.command.annotation.Permission;
import net.citizensnpcs.command.annotation.Requirements;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.CitizensNPCManager;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.util.Messaging;
@ -32,13 +31,8 @@ public class NPCCommands {
this.characterManager = characterManager;
}
@Command(
aliases = { "npc" },
usage = "create [name] (type) (character)",
desc = "Create a new NPC",
modifiers = { "create" },
min = 2,
max = 4)
@Command(aliases = { "npc" }, usage = "create [name] --type (type) --char (character)", desc = "Create a new NPC",
modifiers = { "create" }, min = 2, max = 4)
@Permission("npc.create")
@Requirements
public void createNPC(CommandContext args, Player player, NPC npc) {
@ -48,24 +42,25 @@ public class NPCCommands {
name = name.substring(0, 15);
}
CreatureType type = CreatureType.MONSTER; // Default NPC type
if (args.argsLength() != 2)
if (args.hasValueFlag("type"))
try {
type = CreatureType.valueOf(args.getString(2).toUpperCase().replace('-', '_'));
type = CreatureType.valueOf(args.getFlag("type").toUpperCase().replace('-', '_'));
} catch (IllegalArgumentException ex) {
Messaging.sendError(player, "'" + args.getString(2) + "' is not a valid mob type. Using default NPC.");
Messaging.sendError(player, "'" + args.getFlag("type")
+ "' is not a valid mob type. Using default NPC.");
}
NPC create = npcManager.createNPC(type, name);
String successMsg = ChatColor.GREEN + "You created " + StringHelper.wrap(create.getName());
boolean success = true;
if (args.argsLength() == 4) {
if (characterManager.getInstance(args.getString(3), create) == null) {
if (args.hasValueFlag("char")) {
if (characterManager.getInstance(args.getFlag("char"), create) == null) {
Messaging.sendError(player,
"The character '" + args.getString(3) + "' does not exist. " + create.getName()
"The character '" + args.getFlag("char") + "' does not exist. " + create.getName()
+ " was created at your location without a character.");
success = false;
} else {
create.setCharacter(characterManager.getInstance(args.getString(3), create));
successMsg += " with the character " + StringHelper.wrap(args.getString(3));
create.setCharacter(characterManager.getInstance(args.getFlag("char"), create));
successMsg += " with the character " + StringHelper.wrap(args.getFlag("char"));
}
}
successMsg += " at your location.";
@ -82,27 +77,18 @@ public class NPCCommands {
Messaging.send(player, successMsg);
}
@Command(
aliases = { "npc" },
usage = "despawn",
desc = "Despawn an NPC",
modifiers = { "despawn" },
min = 1,
max = 1)
@Command(aliases = { "npc" }, usage = "despawn", desc = "Despawn an NPC", modifiers = { "despawn" }, min = 1,
max = 1)
@Permission("npc.despawn")
public void despawnNPC(CommandContext args, Player player, NPC npc) {
npc.getTrait(Spawned.class).setSpawned(false);
npc.getTrait(Spawned.class).setSpawned(false); // TODO: move this to
// despawn() / spawn()?
npc.despawn();
Messaging.send(player, ChatColor.GREEN + "You despawned " + StringHelper.wrap(npc.getName()) + ".");
}
@Command(
aliases = { "npc" },
usage = "select [id]",
desc = "Select an NPC",
modifiers = { "select" },
min = 2,
max = 2)
@Command(aliases = { "npc" }, usage = "select [id]", desc = "Selects an NPC with the given ID",
modifiers = { "select" }, min = 2, max = 2)
@Permission("npc.select")
@Requirements(ownership = true)
public void selectNPC(CommandContext args, Player player, NPC npc) {
@ -119,17 +105,12 @@ public class NPCCommands {
Messaging.sendWithNPC(player, Setting.SELECTION_MESSAGE.asString(), toSelect);
}
@Command(
aliases = { "npc" },
usage = "spawn [id]",
desc = "Spawn an existing NPC",
modifiers = { "spawn" },
min = 2,
max = 2)
@Command(aliases = { "npc" }, usage = "spawn [id]", desc = "Spawn an existing NPC", modifiers = { "spawn" },
min = 2, max = 2)
@Permission("npc.spawn")
@Requirements
public void spawnNPC(CommandContext args, Player player, NPC npc) {
CitizensNPC respawn = (CitizensNPC) npcManager.getNPC(args.getInteger(1));
NPC respawn = npcManager.getNPC(args.getInteger(1));
if (respawn == null) {
Messaging.sendError(player, "No NPC with the ID '" + args.getInteger(1) + "' exists.");
return;
@ -144,34 +125,22 @@ public class NPCCommands {
npcManager.selectNPC(player, respawn);
Messaging.send(player, ChatColor.GREEN + "You respawned " + StringHelper.wrap(respawn.getName())
+ " at your location.");
} else
Messaging
.sendError(
player,
respawn.getName()
+ " is already spawned at another location. Use '/npc tphere' to teleport the NPC to your location.");
} else {
Messaging.sendError(player, respawn.getName() + " is already spawned at another location."
+ " Use '/npc tphere' to teleport the NPC to your location.");
}
}
@Command(
aliases = { "npc" },
usage = "tphere",
desc = "Teleport an NPC to your location",
modifiers = { "tphere" },
min = 1,
max = 1)
@Command(aliases = { "npc" }, usage = "tphere", desc = "Teleport an NPC to your location",
modifiers = { "tphere" }, min = 1, max = 1)
@Permission("npc.tphere")
public void teleportNPCToPlayer(CommandContext args, Player player, NPC npc) {
npc.getBukkitEntity().teleport(player, TeleportCause.COMMAND);
Messaging.send(player, StringHelper.wrap(npc.getName()) + " was teleported to your location.");
}
@Command(
aliases = { "npc" },
usage = "tp",
desc = "Teleport to an NPC",
modifiers = { "tp", "teleport" },
min = 1,
max = 1)
@Command(aliases = { "npc" }, usage = "tp", desc = "Teleport to an NPC", modifiers = { "tp", "teleport" }, min = 1,
max = 1)
@Permission("npc.tp")
public void teleportToNPC(CommandContext args, Player player, NPC npc) {
player.teleport(npc.getBukkitEntity(), TeleportCause.COMMAND);
@ -182,12 +151,10 @@ public class NPCCommands {
"lookclose", "look", "rotate" }, min = 1, max = 1)
@Permission("npc.look-close")
public void toggleNPCLookClose(CommandContext args, Player player, NPC npc) {
npc.getTrait(LookClose.class).setLookClose(!npc.getTrait(LookClose.class).shouldLookClose());
String msg = StringHelper.wrap(npc.getName()) + " will ";
if (npc.getTrait(LookClose.class).shouldLookClose())
msg += "now rotate";
else
msg += "no longer";
LookClose trait = npc.getTrait(LookClose.class);
trait.toggle();
String msg = StringHelper.wrap(npc.getName()) + " will "
+ (trait.shouldLookClose() ? "now rotate" : "no longer rotate");
Messaging.send(player, msg += " when a player is nearby.");
}
}

View File

@ -8,7 +8,7 @@ import net.citizensnpcs.api.npc.trait.trait.Spawned;
import net.citizensnpcs.npc.ai.CitizensAI;
import net.citizensnpcs.trait.Inventory;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.StringHelper;
import net.minecraft.server.EntityLiving;
import org.bukkit.Bukkit;
@ -23,7 +23,7 @@ public abstract class CitizensNPC extends AbstractNPC {
protected final NPCInventory inventory;
protected CitizensNPC(CitizensNPCManager manager, int id, String name) {
super(id, name);
super(id, StringHelper.parseColors(name));
this.manager = manager;
inventory = new NPCInventory(this);
}
@ -108,7 +108,9 @@ public abstract class CitizensNPC extends AbstractNPC {
return true;
}
@Override
public void update() {
super.update();
ai.update();
}
}

View File

@ -1,6 +1,6 @@
package net.citizensnpcs.npc;
import net.citizensnpcs.util.StringHelper;
import net.citizensnpcs.api.npc.NPC;
import net.minecraft.server.EntityHuman;
import net.minecraft.server.IInventory;
import net.minecraft.server.ItemStack;
@ -13,14 +13,14 @@ import org.bukkit.inventory.Inventory;
public class NPCInventory implements IInventory {
private final int size = 36;
private final CitizensNPC npc;
private final NPC npc;
private final String name;
private final ItemStack[] contents;
private final Inventory inventory = new CraftInventory(this);
public NPCInventory(CitizensNPC npc) {
public NPCInventory(NPC npc) {
this.npc = npc;
name = StringHelper.parseColors(npc.getFullName());
name = npc.getFullName();
contents = new ItemStack[size];
}

View File

@ -3,7 +3,6 @@ package net.citizensnpcs.npc.entity;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.CitizensNPCManager;
import net.citizensnpcs.resource.lib.EntityHumanNPC;
import net.citizensnpcs.util.StringHelper;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.ItemInWorldManager;
import net.minecraft.server.WorldServer;
@ -29,11 +28,19 @@ public class CitizensHumanNPC extends CitizensNPC {
return;
}
@Override
public void setName(String name) {
super.setName(name);
Location prev = getBukkitEntity().getLocation();
despawn();
spawn(prev);
}
@Override
protected EntityLiving createHandle(Location loc) {
WorldServer ws = ((CraftWorld) loc.getWorld()).getHandle();
EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws,
StringHelper.parseColors(getFullName()), new ItemInWorldManager(ws));
EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws, getFullName(),
new ItemInWorldManager(ws));
handle.removeFromPlayerMap(getFullName());
handle.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
return handle;

View File

@ -3,15 +3,15 @@ package net.citizensnpcs.trait;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import net.citizensnpcs.api.DataKey;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.npc.trait.SaveId;
import net.citizensnpcs.api.npc.trait.Trait;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
@SaveId("inventory")
public class Inventory implements Trait {
private ItemStack[] contents;
@ -83,9 +83,10 @@ public class Inventory implements Trait {
key.setInt("amount", item.getAmount());
key.setLong("data", item.getDurability());
for (Enchantment enchantment : item.getEnchantments().keySet())
for (Enchantment enchantment : item.getEnchantments().keySet()) {
key.getRelative("enchantments").setInt(enchantment.getName().toLowerCase().replace('_', '-'),
item.getEnchantmentLevel(enchantment));
}
}
@Override

View File

@ -2,18 +2,17 @@ package net.citizensnpcs.trait;
import net.citizensnpcs.api.DataKey;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.trait.SaveId;
import net.citizensnpcs.api.npc.trait.Trait;
@SaveId("look-close")
public class LookClose implements Trait {
public class LookClose implements Trait, Runnable {
private final NPC npc;
private boolean shouldLookClose;
public LookClose() {
}
public LookClose(boolean shouldLookClose) {
this.shouldLookClose = shouldLookClose;
public LookClose(NPC npc) {
this.npc = npc;
}
@Override
@ -30,6 +29,12 @@ public class LookClose implements Trait {
key.setBoolean("", shouldLookClose);
}
@Override
public void run() {
// TODO Auto-generated method stub
}
public void setLookClose(boolean shouldLookClose) {
this.shouldLookClose = shouldLookClose;
}
@ -38,6 +43,10 @@ public class LookClose implements Trait {
return shouldLookClose;
}
public void toggle() {
shouldLookClose = !shouldLookClose;
}
@Override
public String toString() {
return "LookClose{" + shouldLookClose + "}";