mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-24 00:01:36 +01:00
initial command commit, needs lots of work
This commit is contained in:
parent
573cc38497
commit
653e37ad24
Binary file not shown.
@ -2,7 +2,11 @@ package net.citizensnpcs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
@ -14,6 +18,15 @@ import net.citizensnpcs.api.npc.trait.DefaultInstanceFactory;
|
||||
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.command.NPCCommands;
|
||||
import net.citizensnpcs.command.exception.CommandUsageException;
|
||||
import net.citizensnpcs.command.exception.MissingNestedCommandException;
|
||||
import net.citizensnpcs.command.exception.NoPermissionsException;
|
||||
import net.citizensnpcs.command.exception.RequirementMissingException;
|
||||
import net.citizensnpcs.command.exception.ServerCommandException;
|
||||
import net.citizensnpcs.command.exception.UnhandledCommandException;
|
||||
import net.citizensnpcs.command.exception.WrappedCommandException;
|
||||
import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.citizensnpcs.npc.CitizensNPCManager;
|
||||
import net.citizensnpcs.storage.Storage;
|
||||
@ -21,6 +34,7 @@ import net.citizensnpcs.storage.database.DatabaseStorage;
|
||||
import net.citizensnpcs.storage.flatfile.YamlStorage;
|
||||
import net.citizensnpcs.util.ByIdArray;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
import net.citizensnpcs.util.StringHelper;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -32,21 +46,66 @@ import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class Citizens extends JavaPlugin {
|
||||
private static CitizensNPCManager npcManager;
|
||||
private static final InstanceFactory<Character> characterManager = DefaultInstanceFactory.create();
|
||||
private static final InstanceFactory<Trait> traitManager = DefaultInstanceFactory.create();
|
||||
private static Storage saves;
|
||||
|
||||
private CitizensNPCManager npcManager;
|
||||
private final InstanceFactory<Character> characterManager = new DefaultInstanceFactory<Character>();
|
||||
private final InstanceFactory<Trait> traitManager = new DefaultInstanceFactory<Trait>();
|
||||
private final CommandManager cmdManager = new CommandManager();
|
||||
private Settings config;
|
||||
private Storage saves;
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String cmdName, String[] args) {
|
||||
if (args[0].equals("spawn")) {
|
||||
NPC npc = npcManager.createNPC(ChatColor.GREEN + "aPunch");
|
||||
npc.spawn(((Player) sender).getLocation());
|
||||
((CitizensNPC) npc).save(saves);
|
||||
} else if (args[0].equals("despawn")) {
|
||||
for (NPC npc : npcManager.getSpawnedNPCs())
|
||||
npc.remove();
|
||||
Player player = null;
|
||||
if (sender instanceof Player)
|
||||
player = (Player) sender;
|
||||
|
||||
try {
|
||||
// must put command into split.
|
||||
String[] split = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = cmd.getName().toLowerCase();
|
||||
|
||||
String modifier = "";
|
||||
if (args.length > 0)
|
||||
modifier = args[0];
|
||||
|
||||
// No command found!
|
||||
if (!cmdManager.hasCommand(split[0], modifier)) {
|
||||
if (!modifier.isEmpty()) {
|
||||
boolean value = handleMistake(sender, split[0], modifier);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
NPC npc = null;
|
||||
if (player != null && npcManager.hasNPCSelected(player))
|
||||
npc = npcManager.getSelectedNPC(player);
|
||||
|
||||
try {
|
||||
cmdManager.execute(split, player, player == null ? sender : player, npc);
|
||||
} catch (ServerCommandException ex) {
|
||||
sender.sendMessage("You must be in-game to execute that command.");
|
||||
} catch (NoPermissionsException ex) {
|
||||
Messaging.sendError(player, "You don't have permission to execute that command.");
|
||||
} catch (MissingNestedCommandException ex) {
|
||||
Messaging.sendError(player, ex.getUsage());
|
||||
} catch (CommandUsageException ex) {
|
||||
Messaging.sendError(player, ex.getMessage());
|
||||
Messaging.sendError(player, ex.getUsage());
|
||||
} catch (RequirementMissingException ex) {
|
||||
Messaging.sendError(player, ex.getMessage());
|
||||
} catch (WrappedCommandException e) {
|
||||
throw e.getCause();
|
||||
} catch (UnhandledCommandException e) {
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Messaging.sendError(player, "That is not a valid number.");
|
||||
} catch (Throwable excp) {
|
||||
excp.printStackTrace();
|
||||
Messaging.sendError(player, "Please report this error: [See console]");
|
||||
Messaging.sendError(player, excp.getClass().getName() + ": " + excp.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -81,6 +140,8 @@ public class Citizens extends JavaPlugin {
|
||||
// Register events
|
||||
getServer().getPluginManager().registerEvents(new EventListen(npcManager), this);
|
||||
|
||||
// Register commands and permissions
|
||||
registerCommands();
|
||||
registerPermissions();
|
||||
|
||||
Messaging.log("v" + getDescription().getVersion() + " enabled.");
|
||||
@ -102,16 +163,20 @@ public class Citizens extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public static Storage getNPCStorage() {
|
||||
return saves;
|
||||
}
|
||||
|
||||
private void saveNPCs() {
|
||||
for (NPC npc : npcManager.getAllNPCs())
|
||||
((CitizensNPC) npc).save(saves);
|
||||
saves.save();
|
||||
((CitizensNPC) npc).save();
|
||||
getNPCStorage().save();
|
||||
}
|
||||
|
||||
private void setupNPCs() throws NPCLoadException {
|
||||
traitManager.register("location", SpawnLocation.class);
|
||||
|
||||
for (DataKey key : saves.getKey("npc").getIntegerSubKeys()) {
|
||||
for (DataKey key : getNPCStorage().getKey("npc").getIntegerSubKeys()) {
|
||||
int id = Integer.parseInt(key.name());
|
||||
if (!key.keyExists("name"))
|
||||
throw new NPCLoadException("Could not find a name for the NPC with ID '" + id + "'.");
|
||||
@ -148,9 +213,43 @@ public class Citizens extends JavaPlugin {
|
||||
|
||||
private void registerPermissions() {
|
||||
Map<String, Boolean> children = new HashMap<String, Boolean>();
|
||||
children.put("citizens.npc.spawn", true);
|
||||
children.put("citizens.npc.despawn", true);
|
||||
children.put("citizens.npc.select", true);
|
||||
|
||||
Permission perm = new Permission("citizens.*", PermissionDefault.OP, children);
|
||||
getServer().getPluginManager().addPermission(perm);
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
cmdManager.register(NPCCommands.class);
|
||||
}
|
||||
|
||||
private boolean handleMistake(CommandSender sender, String command, String modifier) {
|
||||
String[] modifiers = cmdManager.getAllCommandModifiers(command);
|
||||
Map<Integer, String> values = new TreeMap<Integer, String>();
|
||||
int i = 0;
|
||||
for (String string : modifiers) {
|
||||
values.put(StringHelper.getLevenshteinDistance(modifier, string), modifiers[i]);
|
||||
++i;
|
||||
}
|
||||
int best = 0;
|
||||
boolean stop = false;
|
||||
Set<String> possible = new HashSet<String>();
|
||||
for (Entry<Integer, String> entry : values.entrySet()) {
|
||||
if (!stop) {
|
||||
best = entry.getKey();
|
||||
stop = true;
|
||||
} else if (entry.getKey() > best)
|
||||
break;
|
||||
possible.add(entry.getValue());
|
||||
}
|
||||
if (possible.size() > 0) {
|
||||
sender.sendMessage(ChatColor.GRAY + "Unknown command. Did you mean:");
|
||||
for (String string : possible)
|
||||
sender.sendMessage(StringHelper.wrap(" /") + command + " " + StringHelper.wrap(string));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -25,10 +25,10 @@ import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
|
||||
public class EventListen implements Listener {
|
||||
private final List<Integer> toRespawn = new ArrayList<Integer>();
|
||||
private final CitizensNPCManager manager;
|
||||
private final CitizensNPCManager npcManager;
|
||||
|
||||
public EventListen(CitizensNPCManager manager) {
|
||||
this.manager = manager;
|
||||
public EventListen(CitizensNPCManager npcManager) {
|
||||
this.npcManager = npcManager;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -38,7 +38,7 @@ public class EventListen implements Listener {
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
Iterator<Integer> itr = toRespawn.iterator();
|
||||
while (itr.hasNext()) {
|
||||
NPC npc = manager.getNPC(itr.next());
|
||||
NPC npc = npcManager.getNPC(itr.next());
|
||||
npc.spawn(npc.getTrait(SpawnLocation.class).getLocation());
|
||||
itr.remove();
|
||||
}
|
||||
@ -49,7 +49,7 @@ public class EventListen implements Listener {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
for (NPC npc : manager.getSpawnedNPCs()) {
|
||||
for (NPC npc : npcManager.getSpawnedNPCs()) {
|
||||
Location loc = npc.getBukkitEntity().getLocation();
|
||||
if (event.getWorld().equals(loc.getWorld()) && event.getChunk().getX() == loc.getChunk().getX()
|
||||
&& event.getChunk().getZ() == loc.getChunk().getZ()) {
|
||||
@ -65,14 +65,14 @@ public class EventListen implements Listener {
|
||||
*/
|
||||
@EventHandler
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if (!manager.isNPC(event.getEntity()))
|
||||
if (!npcManager.isNPC(event.getEntity()))
|
||||
return;
|
||||
|
||||
event.setCancelled(true); // TODO implement damage handlers
|
||||
if (event instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event;
|
||||
if (e.getDamager() instanceof Player) {
|
||||
NPC npc = manager.getNPC(event.getEntity());
|
||||
NPC npc = npcManager.getNPC(event.getEntity());
|
||||
if (npc.getCharacter() != null)
|
||||
npc.getCharacter().onLeftClick(npc, (Player) e.getDamager());
|
||||
}
|
||||
@ -81,15 +81,15 @@ public class EventListen implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityTarget(EntityTargetEvent event) {
|
||||
if (manager.isNPC(event.getTarget()))
|
||||
if (event.isCancelled() || !manager.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player))
|
||||
if (npcManager.isNPC(event.getTarget()))
|
||||
if (event.isCancelled() || !npcManager.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player))
|
||||
return;
|
||||
|
||||
NPC npc = manager.getNPC(event.getEntity());
|
||||
NPC npc = npcManager.getNPC(event.getEntity());
|
||||
Player player = (Player) event.getTarget();
|
||||
if (!manager.hasSelected(player, npc)) {
|
||||
if (manager.canSelect(player, npc)) {
|
||||
manager.selectNPC(player, npc);
|
||||
if (!npcManager.npcIsSelectedByPlayer(player, npc)) {
|
||||
if (npcManager.canSelectNPC(player, npc)) {
|
||||
npcManager.selectNPC(player, npc);
|
||||
Messaging.sendWithNPC(player, Setting.SELECTION_MESSAGE.getString(), npc);
|
||||
if (!Setting.QUICK_SELECT.getBoolean())
|
||||
return;
|
||||
@ -104,7 +104,7 @@ public class EventListen implements Listener {
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
if (!manager.isNPC(event.getRightClicked()))
|
||||
if (!npcManager.isNPC(event.getRightClicked()))
|
||||
return;
|
||||
|
||||
Bukkit.getPluginManager().callEvent(
|
||||
|
118
src/net/citizensnpcs/command/CommandContext.java
Normal file
118
src/net/citizensnpcs/command/CommandContext.java
Normal file
@ -0,0 +1,118 @@
|
||||
// $Id$
|
||||
/*
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
public class CommandContext {
|
||||
protected String[] args;
|
||||
protected Set<Character> flags = new HashSet<Character>();
|
||||
|
||||
public CommandContext(String args) {
|
||||
this(args.split(" "));
|
||||
}
|
||||
|
||||
public CommandContext(String[] args) {
|
||||
int i = 1;
|
||||
for (; i < args.length; i++) {
|
||||
if (args[i].length() == 0) {
|
||||
// Ignore this
|
||||
} else if (args[i].charAt(0) == '-' && args[i].matches("^-[a-zA-Z]+$")) {
|
||||
for (int k = 1; k < args[i].length(); k++)
|
||||
flags.add(args[i].charAt(k));
|
||||
args[i] = "";
|
||||
}
|
||||
}
|
||||
this.args = Iterables.toArray(Splitter.on(" ").omitEmptyStrings().split(Joiner.on(" ").skipNulls().join(args)),
|
||||
String.class);
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
public boolean matches(String command) {
|
||||
return args[0].equalsIgnoreCase(command);
|
||||
}
|
||||
|
||||
public String getString(int index) {
|
||||
return args[index + 1];
|
||||
}
|
||||
|
||||
public String getString(int index, String def) {
|
||||
return index + 1 < args.length ? args[index + 1] : def;
|
||||
}
|
||||
|
||||
public String getJoinedStrings(int initialIndex) {
|
||||
initialIndex = initialIndex + 1;
|
||||
StringBuilder buffer = new StringBuilder(args[initialIndex]);
|
||||
for (int i = initialIndex + 1; i < args.length; i++)
|
||||
buffer.append(" ").append(args[i]);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public int getInteger(int index) throws NumberFormatException {
|
||||
return Integer.parseInt(args[index + 1]);
|
||||
}
|
||||
|
||||
public int getInteger(int index, int def) throws NumberFormatException {
|
||||
return index + 1 < args.length ? Integer.parseInt(args[index + 1]) : def;
|
||||
}
|
||||
|
||||
public double getDouble(int index) throws NumberFormatException {
|
||||
return Double.parseDouble(args[index + 1]);
|
||||
}
|
||||
|
||||
public double getDouble(int index, double def) throws NumberFormatException {
|
||||
return index + 1 < args.length ? Double.parseDouble(args[index + 1]) : def;
|
||||
}
|
||||
|
||||
public String[] getSlice(int index) {
|
||||
String[] slice = new String[args.length - index];
|
||||
System.arraycopy(args, index, slice, 0, args.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public String[] getPaddedSlice(int index, int padding) {
|
||||
String[] slice = new String[args.length - index + padding];
|
||||
System.arraycopy(args, index, slice, padding, args.length - index);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public boolean hasFlag(char ch) {
|
||||
return flags.contains(ch);
|
||||
}
|
||||
|
||||
public Set<Character> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return args.length;
|
||||
}
|
||||
|
||||
public int argsLength() {
|
||||
return args.length - 1;
|
||||
}
|
||||
}
|
48
src/net/citizensnpcs/command/CommandIdentifier.java
Normal file
48
src/net/citizensnpcs/command/CommandIdentifier.java
Normal file
@ -0,0 +1,48 @@
|
||||
package net.citizensnpcs.command;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
public class CommandIdentifier {
|
||||
private final String modifier;
|
||||
private final String command;
|
||||
|
||||
public CommandIdentifier(String command, String modifier) {
|
||||
this.command = command;
|
||||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(command, modifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CommandIdentifier other = (CommandIdentifier) obj;
|
||||
if (command == null) {
|
||||
if (other.command != null)
|
||||
return false;
|
||||
} else if (!command.equals(other.command))
|
||||
return false;
|
||||
if (modifier == null) {
|
||||
if (other.modifier != null)
|
||||
return false;
|
||||
} else if (!modifier.equals(other.modifier))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getModifier() {
|
||||
return modifier;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
}
|
411
src/net/citizensnpcs/command/CommandManager.java
Normal file
411
src/net/citizensnpcs/command/CommandManager.java
Normal file
@ -0,0 +1,411 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.citizensnpcs.command.annotation.Command;
|
||||
import net.citizensnpcs.command.annotation.Requirements;
|
||||
import net.citizensnpcs.command.annotation.NestedCommand;
|
||||
import net.citizensnpcs.command.annotation.Permission;
|
||||
import net.citizensnpcs.command.annotation.ServerCommand;
|
||||
import net.citizensnpcs.command.exception.CommandException;
|
||||
import net.citizensnpcs.command.exception.CommandUsageException;
|
||||
import net.citizensnpcs.command.exception.MissingNestedCommandException;
|
||||
import net.citizensnpcs.command.exception.NoPermissionsException;
|
||||
import net.citizensnpcs.command.exception.ServerCommandException;
|
||||
import net.citizensnpcs.command.exception.UnhandledCommandException;
|
||||
import net.citizensnpcs.command.exception.WrappedCommandException;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CommandManager {
|
||||
|
||||
// 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 {@link Method}. The child map has the key of the command
|
||||
* name (one for each alias) with the method.
|
||||
*/
|
||||
private Map<Method, Map<CommandIdentifier, Method>> commands = new HashMap<Method, Map<CommandIdentifier, Method>>();
|
||||
|
||||
// Used to store the instances associated with a method.
|
||||
private 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 Map<CommandIdentifier, String> descs = new HashMap<CommandIdentifier, String>();
|
||||
|
||||
// Stores the injector used to getInstance.
|
||||
private Injector injector;
|
||||
|
||||
private Map<Method, Requirements> requirements = new HashMap<Method, Requirements>();
|
||||
|
||||
private Map<Method, ServerCommand> serverCommands = new HashMap<Method, ServerCommand>();
|
||||
|
||||
/*
|
||||
* Register an class that contains commands (denoted by {@link Command}. If
|
||||
* no dependency injector is specified, then the methods of the class will
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Register the methods of a class.
|
||||
private void registerMethods(Class<?> cls, Method parent, Object obj) {
|
||||
Map<CommandIdentifier, Method> map;
|
||||
|
||||
// Make a new hash map to cache the commands for this class
|
||||
// as looking up methods via reflection is fairly slow
|
||||
if (commands.containsKey(parent))
|
||||
map = commands.get(parent);
|
||||
else {
|
||||
map = new HashMap<CommandIdentifier, Method>();
|
||||
commands.put(parent, map);
|
||||
}
|
||||
|
||||
for (Method method : cls.getMethods()) {
|
||||
if (!method.isAnnotationPresent(Command.class))
|
||||
continue;
|
||||
boolean isStatic = Modifier.isStatic(method.getModifiers());
|
||||
|
||||
Command cmd = method.getAnnotation(Command.class);
|
||||
String[] modifiers = cmd.modifiers();
|
||||
|
||||
// Cache the aliases too
|
||||
for (String alias : cmd.aliases())
|
||||
for (String modifier : modifiers)
|
||||
map.put(new CommandIdentifier(alias, modifier), method);
|
||||
|
||||
Requirements cmdRequirements = null;
|
||||
if (method.getDeclaringClass().isAnnotationPresent(Requirements.class))
|
||||
cmdRequirements = method.getDeclaringClass().getAnnotation(Requirements.class);
|
||||
|
||||
if (method.isAnnotationPresent(Requirements.class))
|
||||
cmdRequirements = method.getAnnotation(Requirements.class);
|
||||
|
||||
if (requirements != null)
|
||||
requirements.put(method, cmdRequirements);
|
||||
|
||||
ServerCommand serverCommand = null;
|
||||
if (method.isAnnotationPresent(ServerCommand.class))
|
||||
serverCommand = method.getAnnotation(ServerCommand.class);
|
||||
|
||||
if (serverCommand != null)
|
||||
serverCommands.put(method, serverCommand);
|
||||
|
||||
// We want to be able invoke with an instance
|
||||
if (!isStatic) {
|
||||
// Can't register this command if we don't have an instance
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
instances.put(method, obj);
|
||||
Messaging.log("Put instance.");
|
||||
}
|
||||
|
||||
// Build a list of commands and their usage details, at least for
|
||||
// root level commands
|
||||
if (parent == null)
|
||||
if (cmd.usage().length() == 0)
|
||||
descs.put(new CommandIdentifier(cmd.aliases()[0], cmd.modifiers()[0]), cmd.desc());
|
||||
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
|
||||
// up when processing commands
|
||||
if (method.isAnnotationPresent(NestedCommand.class)) {
|
||||
NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class);
|
||||
|
||||
for (Class<?> nestedCls : nestedCmd.value())
|
||||
registerMethods(nestedCls, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(), "*"));
|
||||
}
|
||||
|
||||
// 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 command.
|
||||
private String getUsage(String[] args, int level, Command cmd) {
|
||||
StringBuilder command = new StringBuilder();
|
||||
|
||||
command.append("/");
|
||||
|
||||
for (int i = 0; i <= level; i++)
|
||||
command.append(args[i] + " ");
|
||||
|
||||
// removed arbitrary positioning of flags.
|
||||
command.append(cmd.usage());
|
||||
|
||||
return command.toString();
|
||||
}
|
||||
|
||||
// Get the usage string for a nested command.
|
||||
private String getNestedUsage(String[] args, int level, Method method, Player player) throws CommandException {
|
||||
StringBuilder command = new StringBuilder();
|
||||
|
||||
command.append("/");
|
||||
|
||||
for (int i = 0; i <= level; i++)
|
||||
command.append(args[i] + " ");
|
||||
|
||||
Map<CommandIdentifier, Method> map = commands.get(method);
|
||||
boolean found = false;
|
||||
|
||||
command.append("<");
|
||||
|
||||
Set<String> allowedCommands = new HashSet<String>();
|
||||
|
||||
for (Map.Entry<CommandIdentifier, Method> entry : map.entrySet()) {
|
||||
Method childMethod = entry.getValue();
|
||||
found = true;
|
||||
|
||||
if (hasPermission(childMethod, player)) {
|
||||
Command childCmd = childMethod.getAnnotation(Command.class);
|
||||
|
||||
allowedCommands.add(childCmd.aliases()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (allowedCommands.size() > 0)
|
||||
command.append(joinString(allowedCommands, "|", 0));
|
||||
else {
|
||||
if (!found)
|
||||
command.append("?");
|
||||
else
|
||||
throw new NoPermissionsException();
|
||||
}
|
||||
|
||||
command.append(">");
|
||||
|
||||
return command.toString();
|
||||
}
|
||||
|
||||
public static String joinString(Collection<?> str, String delimiter, int initialIndex) {
|
||||
if (str.size() == 0)
|
||||
return "";
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object o : str) {
|
||||
if (i >= initialIndex) {
|
||||
if (i > 0)
|
||||
buffer.append(delimiter);
|
||||
buffer.append(o.toString());
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to execute a command. This version takes a separate command name
|
||||
* (for the root command) and then a list of following arguments.
|
||||
*/
|
||||
public void execute(String cmd, String[] args, Player player, Object... methodArgs) throws CommandException {
|
||||
String[] newArgs = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, newArgs, 1, args.length);
|
||||
newArgs[0] = cmd;
|
||||
Object[] newMethodArgs = new Object[methodArgs.length + 1];
|
||||
System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length);
|
||||
|
||||
executeMethod(null, newArgs, player, newMethodArgs, 0);
|
||||
}
|
||||
|
||||
// Attempt to execute a command.
|
||||
public void execute(String[] args, Player player, Object... methodArgs) throws CommandException {
|
||||
Object[] newMethodArgs = new Object[methodArgs.length + 1];
|
||||
System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length);
|
||||
executeMethod(null, args, player, newMethodArgs, 0);
|
||||
}
|
||||
|
||||
// Attempt to execute a command.
|
||||
public void executeMethod(Method parent, String[] args, Player player, Object[] methodArgs, int level)
|
||||
throws CommandException {
|
||||
String cmdName = args[level];
|
||||
String modifier = "";
|
||||
if (args.length > level + 1)
|
||||
modifier = args[level + 1];
|
||||
|
||||
Map<CommandIdentifier, Method> map = commands.get(parent);
|
||||
Method method = map.get(new CommandIdentifier(cmdName.toLowerCase(), modifier.toLowerCase()));
|
||||
if (method == null)
|
||||
method = map.get(new CommandIdentifier(cmdName.toLowerCase(), "*"));
|
||||
|
||||
if (method != null && methodArgs != null && serverCommands.get(method) == null
|
||||
&& methodArgs[1] instanceof ConsoleCommandSender)
|
||||
throw new ServerCommandException();
|
||||
|
||||
if (method == null)
|
||||
if (parent == null)
|
||||
throw new UnhandledCommandException();
|
||||
else
|
||||
throw new MissingNestedCommandException("Unknown command: " + cmdName, getNestedUsage(args, level - 1,
|
||||
parent, player));
|
||||
|
||||
if (methodArgs[1] instanceof Player)
|
||||
if (!hasPermission(method, player))
|
||||
throw new NoPermissionsException();
|
||||
|
||||
int argsCount = args.length - 1 - level;
|
||||
|
||||
if (method.isAnnotationPresent(NestedCommand.class))
|
||||
if (argsCount == 0)
|
||||
throw new MissingNestedCommandException("Sub-command required.", getNestedUsage(args, level, method,
|
||||
player));
|
||||
else
|
||||
executeMethod(method, args, player, methodArgs, level + 1);
|
||||
else if (methodArgs[1] instanceof Player) {
|
||||
Requirements cmdRequirements = requirements.get(method);
|
||||
|
||||
// TODO add requirements
|
||||
if (cmdRequirements != null)
|
||||
Messaging.debug("");
|
||||
else
|
||||
Messaging.debug("No annotation present.");
|
||||
}
|
||||
|
||||
Command cmd = method.getAnnotation(Command.class);
|
||||
|
||||
String[] newArgs = new String[args.length - level];
|
||||
System.arraycopy(args, level, newArgs, 0, args.length - level);
|
||||
|
||||
CommandContext context = new CommandContext(newArgs);
|
||||
|
||||
if (context.argsLength() < cmd.min())
|
||||
throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd));
|
||||
|
||||
if (cmd.max() != -1 && context.argsLength() > cmd.max())
|
||||
throw new CommandUsageException("Too many arguments.", getUsage(args, level, cmd));
|
||||
|
||||
for (char flag : context.getFlags())
|
||||
if (cmd.flags().indexOf(String.valueOf(flag)) == -1)
|
||||
throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, level, cmd));
|
||||
|
||||
methodArgs[0] = context;
|
||||
Object instance = instances.get(method);
|
||||
try {
|
||||
method.invoke(instance, methodArgs);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.SEVERE, "Failed to execute command", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.SEVERE, "Failed to execute command", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof CommandException)
|
||||
throw (CommandException) e.getCause();
|
||||
|
||||
throw new WrappedCommandException(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether a player has access to a command.
|
||||
private boolean hasPermission(Method method, Player player) {
|
||||
Permission permission = method.getAnnotation(Permission.class);
|
||||
if (permission == null)
|
||||
return true;
|
||||
|
||||
if (hasPermission(player, permission.value()))
|
||||
return true;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public String[] getAllCommandModifiers(String command) {
|
||||
Set<String> cmds = new HashSet<String>();
|
||||
for (Map<CommandIdentifier, Method> enclosing : commands.values()) {
|
||||
for (CommandIdentifier identifier : enclosing.keySet()) {
|
||||
if (identifier.getCommand().equals(command)) {
|
||||
cmds.add(identifier.getModifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmds.toArray(new String[cmds.size()]);
|
||||
}
|
||||
}
|
15
src/net/citizensnpcs/command/Injector.java
Normal file
15
src/net/citizensnpcs/command/Injector.java
Normal file
@ -0,0 +1,15 @@
|
||||
// $Id$
|
||||
/*
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public interface Injector {
|
||||
|
||||
public Object getInstance(Class<?> cls) throws InvocationTargetException, IllegalAccessException,
|
||||
InstantiationException;
|
||||
}
|
40
src/net/citizensnpcs/command/annotation/Command.java
Normal file
40
src/net/citizensnpcs/command/annotation/Command.java
Normal file
@ -0,0 +1,40 @@
|
||||
// $Id$
|
||||
/*
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
String[] aliases();
|
||||
|
||||
String usage() default "";
|
||||
|
||||
String desc();
|
||||
|
||||
String[] modifiers() default "";
|
||||
|
||||
int min() default 0;
|
||||
|
||||
int max() default -1;
|
||||
|
||||
String flags() default "";
|
||||
}
|
29
src/net/citizensnpcs/command/annotation/NestedCommand.java
Normal file
29
src/net/citizensnpcs/command/annotation/NestedCommand.java
Normal file
@ -0,0 +1,29 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NestedCommand {
|
||||
|
||||
Class<?>[] value();
|
||||
}
|
29
src/net/citizensnpcs/command/annotation/Permission.java
Normal file
29
src/net/citizensnpcs/command/annotation/Permission.java
Normal file
@ -0,0 +1,29 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Permission {
|
||||
|
||||
String value();
|
||||
}
|
12
src/net/citizensnpcs/command/annotation/Requirements.java
Normal file
12
src/net/citizensnpcs/command/annotation/Requirements.java
Normal file
@ -0,0 +1,12 @@
|
||||
package net.citizensnpcs.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Requirements {
|
||||
|
||||
boolean requireSelected() default false;
|
||||
|
||||
boolean requireOwnership() default false;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package net.citizensnpcs.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ServerCommand {
|
||||
}
|
42
src/net/citizensnpcs/command/command/NPCCommands.java
Normal file
42
src/net/citizensnpcs/command/command/NPCCommands.java
Normal file
@ -0,0 +1,42 @@
|
||||
package net.citizensnpcs.command.command;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
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;
|
||||
|
||||
// TODO add requirements
|
||||
public class NPCCommands {
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "spawn [name]",
|
||||
desc = "Spawn an NPC",
|
||||
modifiers = { "spawn", "create" },
|
||||
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();
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "despawn",
|
||||
desc = "Despawn an NPC",
|
||||
modifiers = { "despawn" },
|
||||
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);
|
||||
despawn.despawn();
|
||||
}
|
||||
}
|
36
src/net/citizensnpcs/command/exception/CommandException.java
Normal file
36
src/net/citizensnpcs/command/exception/CommandException.java
Normal file
@ -0,0 +1,36 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class CommandException extends Exception {
|
||||
private static final long serialVersionUID = 870638193072101739L;
|
||||
|
||||
public CommandException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class CommandUsageException extends CommandException {
|
||||
private static final long serialVersionUID = -6761418114414516542L;
|
||||
|
||||
protected String usage;
|
||||
|
||||
public CommandUsageException(String message, String usage) {
|
||||
super(message);
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class MissingNestedCommandException extends CommandUsageException {
|
||||
private static final long serialVersionUID = -4382896182979285355L;
|
||||
|
||||
public MissingNestedCommandException(String message, String usage) {
|
||||
super(message, usage);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class NoPermissionsException extends CommandException {
|
||||
private static final long serialVersionUID = -602374621030168291L;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class RequirementMissingException extends CommandException {
|
||||
|
||||
private static final long serialVersionUID = -4299721983654504028L;
|
||||
|
||||
public RequirementMissingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class ServerCommandException extends CommandException {
|
||||
private static final long serialVersionUID = 9120268556899197316L;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class UnhandledCommandException extends CommandException {
|
||||
private static final long serialVersionUID = 3370887306593968091L;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.citizensnpcs.command.exception;
|
||||
|
||||
public class WrappedCommandException extends CommandException {
|
||||
private static final long serialVersionUID = -4075721444847778918L;
|
||||
|
||||
public WrappedCommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.citizensnpcs.npc;
|
||||
|
||||
import net.citizensnpcs.Citizens;
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.event.NPCDespawnEvent;
|
||||
@ -10,7 +11,6 @@ import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.npc.ai.CitizensNavigator;
|
||||
import net.citizensnpcs.resources.lib.CraftNPC;
|
||||
import net.citizensnpcs.storage.Storage;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -31,7 +31,7 @@ public class CitizensNPC extends AbstractNPC {
|
||||
@Override
|
||||
public void despawn() {
|
||||
if (!isSpawned()) {
|
||||
Messaging.debug("The NPC is already despawned.");
|
||||
Messaging.debug("The NPC with the ID '" + getId() + "' is already despawned.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ public class CitizensNPC extends AbstractNPC {
|
||||
@Override
|
||||
public void spawn(Location loc) {
|
||||
if (isSpawned()) {
|
||||
Messaging.debug("The NPC is already spawned.");
|
||||
Messaging.debug("The NPC with the ID '" + getId() + "' is already spawned.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -101,8 +101,8 @@ public class CitizensNPC extends AbstractNPC {
|
||||
Messaging.log(formatted);
|
||||
}
|
||||
|
||||
public void save(Storage saves) {
|
||||
DataKey key = saves.getKey("npc." + getId());
|
||||
public void save() {
|
||||
DataKey key = Citizens.getNPCStorage().getKey("npc." + getId());
|
||||
key.setString("name", getFullName());
|
||||
if (!key.keyExists("spawned"))
|
||||
key.setBoolean("spawned", true);
|
||||
|
@ -7,10 +7,10 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCManager;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.resources.lib.CraftNPC;
|
||||
import net.citizensnpcs.storage.Storage;
|
||||
@ -89,10 +89,11 @@ public class CitizensNPCManager implements NPCManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NPC> getNPCs(Class<? extends Trait> trait) {
|
||||
public Collection<NPC> getNPCs(Class<? extends Character> character) {
|
||||
List<NPC> npcs = new ArrayList<NPC>();
|
||||
for (NPC npc : getAllNPCs()) {
|
||||
if (npc.hasTrait(trait))
|
||||
if (npc.getCharacter() != null
|
||||
&& CitizensAPI.getCharacterManager().getInstance(npc.getCharacter().getName()) != null)
|
||||
npcs.add(npc);
|
||||
}
|
||||
return npcs;
|
||||
@ -143,16 +144,25 @@ public class CitizensNPCManager implements NPCManager {
|
||||
selected.put(player.getName(), npc.getId());
|
||||
}
|
||||
|
||||
public boolean hasSelected(Player player, NPC npc) {
|
||||
public boolean npcIsSelectedByPlayer(Player player, NPC npc) {
|
||||
if (!selected.containsKey(player.getName()))
|
||||
return false;
|
||||
return selected.get(player.getName()) == npc.getId();
|
||||
}
|
||||
|
||||
public boolean canSelect(Player player, NPC npc) {
|
||||
if (player.hasPermission("citizens.npc.select")) {
|
||||
public boolean hasNPCSelected(Player player) {
|
||||
return selected.containsKey(player.getName());
|
||||
}
|
||||
|
||||
public boolean canSelectNPC(Player player, NPC npc) {
|
||||
if (player.hasPermission("citizens.npc.select"))
|
||||
return player.getItemInHand().getTypeId() == Setting.SELECTION_ITEM.getInt();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public NPC getSelectedNPC(Player player) {
|
||||
if (!selected.containsKey(player.getName()))
|
||||
return null;
|
||||
return getNPC(selected.get(player.getName()));
|
||||
}
|
||||
}
|
@ -45,4 +45,8 @@ public class Messaging {
|
||||
|
||||
send(player, send);
|
||||
}
|
||||
|
||||
public static void sendError(Player player, Object msg) {
|
||||
send(player, "" + ChatColor.RED + msg);
|
||||
}
|
||||
}
|
59
src/net/citizensnpcs/util/StringHelper.java
Normal file
59
src/net/citizensnpcs/util/StringHelper.java
Normal file
@ -0,0 +1,59 @@
|
||||
package net.citizensnpcs.util;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class StringHelper {
|
||||
|
||||
public static int getLevenshteinDistance(String s, String t) {
|
||||
if (s == null || t == null)
|
||||
throw new IllegalArgumentException("Strings must not be null");
|
||||
|
||||
int n = s.length(); // length of s
|
||||
int m = t.length(); // length of t
|
||||
|
||||
if (n == 0)
|
||||
return m;
|
||||
else if (m == 0)
|
||||
return n;
|
||||
|
||||
int p[] = new int[n + 1]; // 'previous' cost array, horizontally
|
||||
int d[] = new int[n + 1]; // cost array, horizontally
|
||||
int _d[]; // placeholder to assist in swapping p and d
|
||||
|
||||
// indexes into strings s and t
|
||||
int i; // iterates through s
|
||||
int j; // iterates through t
|
||||
|
||||
char t_j; // jth character of t
|
||||
|
||||
int cost; // cost
|
||||
|
||||
for (i = 0; i <= n; i++)
|
||||
p[i] = i;
|
||||
|
||||
for (j = 1; j <= m; j++) {
|
||||
t_j = t.charAt(j - 1);
|
||||
d[0] = j;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
cost = s.charAt(i - 1) == t_j ? 0 : 1;
|
||||
// minimum of cell to the left+1, to the top+1, diagonally left
|
||||
// and up +cost
|
||||
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
|
||||
}
|
||||
|
||||
// copy current distance counts to 'previous row' distance counts
|
||||
_d = p;
|
||||
p = d;
|
||||
d = _d;
|
||||
}
|
||||
|
||||
// our last action in the above loop was to switch d and p, so p now
|
||||
// actually has the most recent cost counts
|
||||
return p[n];
|
||||
}
|
||||
|
||||
public static String wrap(Object string) {
|
||||
return ChatColor.YELLOW + string.toString() + ChatColor.GREEN;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user