Starting to convert commands to a smarter system :3

This commit is contained in:
Sauilitired
2015-07-26 20:50:54 +02:00
parent 6b229ac504
commit e1c8dcc4be
57 changed files with 1443 additions and 726 deletions

View File

@@ -0,0 +1,84 @@
package com.intellectualsites.commands;
import com.intellectualcrafters.plot.object.PlotId;
import org.bukkit.entity.Player;
public abstract class Argument<T> {
private final String name;
private final T example;
public Argument(String name, T example) {
this.name = name;
this.example = example;
}
public abstract T parse(String in);
@Override
public final String toString() {
return this.getName();
}
public final String getName() {
return this.name;
}
public final T getExample() {
return this.example;
}
public static final Argument<Integer> Integer = new Argument<java.lang.Integer>("int", 16) {
@Override
public Integer parse(String in) {
Integer value = null;
try {
value = java.lang.Integer.parseInt(in);
} catch(final Exception ignored) {}
return value;
}
};
public static final Argument<Boolean> Boolean = new Argument<java.lang.Boolean>("boolean", true) {
@Override
public Boolean parse(String in) {
Boolean value = null;
if (in.equalsIgnoreCase("true") || in.equalsIgnoreCase("Yes") || in.equalsIgnoreCase("1")) {
value = true;
} else if (in.equalsIgnoreCase("false") || in.equalsIgnoreCase("No") || in.equalsIgnoreCase("0")) {
value = false;
}
return value;
}
};
public static final Argument<String> String = new Argument<java.lang.String>("String", "Example") {
@Override
public String parse(String in) {
return in;
}
};
public static Argument<String> PlayerName = new Argument<java.lang.String>("PlayerName", "Dinnerbone") {
@Override
public String parse(String in) {
return in.length() < 16 ? in : null;
}
};
public static Argument<PlotId> PlotID = new Argument<com.intellectualcrafters.plot.object.PlotId>("PlotID", new PlotId(3, -32)) {
@Override
public PlotId parse(String in) {
PlotId plotID;
try {
String[] parts = in.split(";");
int i1 = java.lang.Integer.parseInt(parts[0]);
int i2 = java.lang.Integer.parseInt(parts[1]);
plotID = new PlotId(i1, i2);
} catch(final Exception e) {
return null;
}
return plotID;
}
};
}

View File

@@ -0,0 +1,140 @@
package com.intellectualsites.commands;
import com.intellectualcrafters.plot.commands.CommandCategory;
import com.intellectualsites.commands.callers.CommandCaller;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
public abstract class Command extends CommandManager {
private Class requiredType = Object.class;
private String command, usage = "", description = "", permission = "";
private String[] aliases = new String[0];
private CommandCategory category;
protected Argument[] requiredArguments;
public Command() {
super(null, new ArrayList<Command>());
}
public Command(String command) {
super(null, new ArrayList<Command>());
this.command = command;
}
public Command(String command, String usage) {
super(null, new ArrayList<Command>());
this.command = command;
this.usage = usage;
}
public Command(String command, String usage, String description) {
super(null, new ArrayList<Command>());
this.command = command;
this.usage = usage;
this.description = description;
}
public Command(String command, String usage, String description, String permission) {
super(null, new ArrayList<Command>());
this.command = command;
this.usage = usage;
this.description = description;
this.permission = permission;
}
public Command(String command, String[] aliases, String usage) {
super(null, new ArrayList<Command>());
this.command = command;
this.aliases = aliases;
this.usage = usage;
}
public Command(String command, String[] aliases) {
super(null, new ArrayList<Command>());
this.command = command;
this.aliases = aliases;
}
public Command(String command, String usage, String description, String permission, String[] aliases, Class requiredType) {
super(null, new ArrayList<Command>());
this.command = command;
this.usage = usage;
this.description = description;
this.permission = permission;
this.aliases = aliases;
this.requiredType = requiredType;
}
final public Class getRequiredType() {
return this.requiredType;
}
final protected void create() {
Annotation annotation = getClass().getAnnotation(CommandDeclaration.class);
if (annotation == null) {
throw new RuntimeException("Command does not have a CommandDeclaration");
}
CommandDeclaration declaration = (CommandDeclaration) annotation;
this.command = declaration.command();
this.usage = declaration.usage();
this.description = declaration.description();
this.usage = declaration.usage();
this.permission = declaration.permission();
this.aliases = declaration.aliases();
this.requiredType = declaration.requiredType();
this.category = declaration.category();
}
@Override
final public String toString() {
return this.command;
}
@Override
final public int hashCode() {
return this.command.hashCode();
}
public abstract boolean onCommand(CommandCaller caller, String[] arguments);
final public int handle(CommandCaller caller, String[] args) {
if (args.length == 0) {
return super.handle(caller, "");
}
StringBuilder builder = new StringBuilder();
for (String s : args) {
builder.append(s).append(" ");
}
String s = builder.substring(0, builder.length() - 1);
return super.handle(caller, s);
}
final public String getCommand() {
return this.command;
}
final public String getUsage() {
return this.usage;
}
final public String getPermission() {
return this.permission;
}
final public String getDescription() {
return this.description;
}
final public String[] getAliases() {
return this.aliases;
}
final public Argument[] getRequiredArguments() {
return this.requiredArguments;
}
final public CommandCategory getCategory() {
return this.category;
}
}

View File

@@ -0,0 +1,27 @@
package com.intellectualsites.commands;
import com.intellectualcrafters.plot.commands.CommandCategory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandDeclaration {
String command();
String[] aliases() default "";
String permission() default "";
String usage() default "";
String description() default "";
Class requiredType() default Object.class;
CommandCategory category();
}

View File

@@ -0,0 +1,31 @@
package com.intellectualsites.commands;
import java.lang.reflect.Field;
public class CommandHandlingOutput {
public static int CALLER_OF_WRONG_TYPE = -6;
public static int NOT_COMMAND = -5;
public static int NOT_FOUND = -4;
public static int NOT_PERMITTED = -3;
public static int ERROR = -2;
public static int WRONG_USAGE = -1;
public static int SUCCESS = 1;
public static String nameField(int code) {
Field[] fields = CommandHandlingOutput.class.getDeclaredFields();
for (final Field field : fields) {
if (field.getGenericType() == Integer.TYPE) {
try {
if ((Integer) field.get(CommandHandlingOutput.class) == code) {
return field.getName();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return "null??";
}
}

View File

@@ -0,0 +1,115 @@
package com.intellectualsites.commands;
import com.intellectualsites.commands.callers.CommandCaller;
import com.intellectualsites.commands.util.StringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("unused")
public class CommandManager {
protected final List<Command> commands;
private final Character initialCharacter;
public CommandManager() {
this('/', new ArrayList<Command>());
}
public CommandManager(Character initialCharacter, List<Command> commands) {
this.commands = Collections.synchronizedList(commands);
this.initialCharacter = initialCharacter;
}
final public void addCommand(final Command command) {
this.commands.add(command);
}
final public boolean createCommand(final Command command) {
try {
command.create();
} catch(final Exception e) {
e.printStackTrace();
return false;
}
if (command.getCommand() != null) {
commands.add(command);
return true;
}
return false;
}
final public List<Command> getCommands() {
return this.commands;
}
final public int handle(CommandCaller caller, String input) {
if (initialCharacter != null && !StringUtil.startsWith(initialCharacter, input)) {
return CommandHandlingOutput.NOT_COMMAND;
}
input = initialCharacter == null ? input : StringUtil.replaceFirst(initialCharacter, input);
String[] parts = input.split(" ");
String[] args;
String command = parts[0];
if (parts.length == 1) {
args = new String[0];
} else {
args = new String[parts.length - 1];
System.arraycopy(parts, 1, args, 0, args.length);
}
Command cmd = null;
for (Command c1 : this.commands) {
if (c1.getCommand().equalsIgnoreCase(command) || StringUtil.inArray(command, c1.getAliases(), false)) {
cmd = c1;
break;
}
}
if (cmd == null) {
return CommandHandlingOutput.NOT_FOUND;
}
if (!cmd.getRequiredType().isInstance(caller.getSuperCaller())) {
return CommandHandlingOutput.CALLER_OF_WRONG_TYPE;
}
if (!caller.hasPermission(cmd.getPermission())) {
return CommandHandlingOutput.NOT_PERMITTED;
}
Argument[] requiredArguments = cmd.getRequiredArguments();
if (requiredArguments != null && requiredArguments.length > 0) {
boolean success = true;
if (args.length < requiredArguments.length) {
success = false;
} else {
for (int i = 0; i < requiredArguments.length; i++) {
if (requiredArguments[i].parse(args[i]) == null) {
success = false;
break;
}
}
}
if (!success) {
String usage = cmd.getUsage();
caller.sendRequiredArgumentsList(this, cmd, requiredArguments);
return CommandHandlingOutput.WRONG_USAGE;
}
}
try {
boolean a = cmd.onCommand(caller, args);
if (!a) {
String usage = cmd.getUsage();
if (usage != null && !usage.isEmpty()) {
caller.message(usage);
}
return CommandHandlingOutput.WRONG_USAGE;
}
} catch(final Throwable t) {
t.printStackTrace();
return CommandHandlingOutput.ERROR;
}
return CommandHandlingOutput.SUCCESS;
}
final public char getInitialCharacter() {
return this.initialCharacter;
}
}

View File

@@ -0,0 +1,19 @@
package com.intellectualsites.commands.callers;
import com.intellectualcrafters.plot.config.C;
import com.intellectualsites.commands.Argument;
import com.intellectualsites.commands.Command;
import com.intellectualsites.commands.CommandManager;
public interface CommandCaller<T> {
boolean hasPermission(String permission);
void message(String message);
T getSuperCaller();
void message(C c, String ... args);
void sendRequiredArgumentsList(CommandManager manager, Command cmd, Argument[] required);
}

View File

@@ -0,0 +1,29 @@
package com.intellectualsites.commands.callers;
import com.intellectualsites.commands.Argument;
import com.intellectualsites.commands.Command;
import com.intellectualsites.commands.CommandManager;
public class SystemCaller implements CommandCaller {
public boolean hasPermission(String permission) {
return true;
}
public void message(String message) {
System.out.println(message);
}
public Object getSuperCaller() {
return new Object();
}
public void sendRequiredArgumentsList(CommandManager manager, Command cmd, Argument[] required) {
StringBuilder builder = new StringBuilder();
builder.append(manager.getInitialCharacter()).append(cmd.getCommand()).append(" requires ");
for (Argument argument : required) {
builder.append(argument.getName()).append(" (").append(argument.getExample()).append("), ");
}
message(builder.substring(0, builder.length() - 2));
}
}

View File

@@ -0,0 +1,48 @@
package com.intellectualsites.commands.test;
import com.intellectualsites.commands.*;
import com.intellectualsites.commands.callers.CommandCaller;
import com.intellectualsites.commands.callers.SystemCaller;
public class CommandTest {
public static void main(String[] args) {
CommandCaller caller = new SystemCaller();
CommandManager manager = new CommandManager();
if(!manager.createCommand(new TestCommand())) {
System.out.println("Failed to create command :(");
}
manager.handle(caller, "/test banana cow grass");
}
@CommandDeclaration(command = "test", usage = "/test [word]")
public static class TestCommand extends Command {
TestCommand() {
requiredArguments = new Argument[] {
Argument.String, Argument.String, Argument.String
};
addCommand(new Command("banana", new String[0]) {
@Override
public boolean onCommand(CommandCaller caller, String[] arguments) {
if (getCommands().isEmpty()) {
addCommand(new Command("cow") {
@Override
public boolean onCommand(CommandCaller caller, String[] arguments) {
caller.message("I eat " + arguments[0]);
return true;
}
});
}
handle(caller, arguments);
return true;
}
});
}
@Override
public boolean onCommand(CommandCaller caller, String[] arguments) {
handle(caller, arguments);
return true;
}
}
}

View File

@@ -0,0 +1,52 @@
package com.intellectualsites.commands.util;
public class StringUtil {
public static final String[] emptyArray = new String[0];
public static boolean startsWith(char c, String s) {
return !(s == null || s.isEmpty()) && s.toCharArray()[0] == c;
}
public static String replaceFirst(char c, String s) {
if (s == null) {
return "";
}
if (s.isEmpty()) {
return s;
}
char[] chars = s.toCharArray();
char[] newChars = new char[chars.length];
int used = 0;
boolean found = false;
for (char cc : chars) {
if (!found && c == cc) {
found = true;
} else {
newChars[used++] = cc;
}
}
if (found) {
chars = new char[newChars.length - 1];
System.arraycopy(newChars, 0, chars, 0, chars.length);
return String.valueOf(chars);
}
return s;
}
public static boolean inArray(String s, String[] a, boolean matchCase) {
for (String aS : a) {
if (matchCase) {
if (s.equals(aS)) {
return true;
}
} else {
if (s.equalsIgnoreCase(aS)) {
return true;
}
}
}
return false;
}
}