From 24ec6d2a3222fa2e042e828e554584ff2eec1428 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 6 Aug 2016 12:00:33 +0200 Subject: First Commit --- CmdMgrTest.java | 58 ++++ com/nemez/cmdmgr/Command.java | 13 + com/nemez/cmdmgr/CommandManager.java | 396 ++++++++++++++++++++++ com/nemez/cmdmgr/component/ArgumentComponent.java | 11 + com/nemez/cmdmgr/component/ByteComponent.java | 28 ++ com/nemez/cmdmgr/component/ChainComponent.java | 47 +++ com/nemez/cmdmgr/component/ConstantComponent.java | 33 ++ com/nemez/cmdmgr/component/DoubleComponent.java | 28 ++ com/nemez/cmdmgr/component/FloatComponent.java | 28 ++ com/nemez/cmdmgr/component/ICommandComponent.java | 9 + com/nemez/cmdmgr/component/IntegerComponent.java | 28 ++ com/nemez/cmdmgr/component/LongComponent.java | 28 ++ com/nemez/cmdmgr/component/ShortComponent.java | 28 ++ com/nemez/cmdmgr/component/StringComponent.java | 19 ++ com/nemez/cmdmgr/util/BranchStack.java | 33 ++ com/nemez/cmdmgr/util/Executable.java | 249 ++++++++++++++ com/nemez/cmdmgr/util/ExecutableDefinition.java | 81 +++++ com/nemez/cmdmgr/util/HelpPageCommand.java | 16 + com/nemez/cmdmgr/util/Property.java | 7 + plugin.yml | 11 + test.cmd | 34 ++ 21 files changed, 1185 insertions(+) create mode 100644 CmdMgrTest.java create mode 100644 com/nemez/cmdmgr/Command.java create mode 100644 com/nemez/cmdmgr/CommandManager.java create mode 100644 com/nemez/cmdmgr/component/ArgumentComponent.java create mode 100644 com/nemez/cmdmgr/component/ByteComponent.java create mode 100644 com/nemez/cmdmgr/component/ChainComponent.java create mode 100644 com/nemez/cmdmgr/component/ConstantComponent.java create mode 100644 com/nemez/cmdmgr/component/DoubleComponent.java create mode 100644 com/nemez/cmdmgr/component/FloatComponent.java create mode 100644 com/nemez/cmdmgr/component/ICommandComponent.java create mode 100644 com/nemez/cmdmgr/component/IntegerComponent.java create mode 100644 com/nemez/cmdmgr/component/LongComponent.java create mode 100644 com/nemez/cmdmgr/component/ShortComponent.java create mode 100644 com/nemez/cmdmgr/component/StringComponent.java create mode 100644 com/nemez/cmdmgr/util/BranchStack.java create mode 100644 com/nemez/cmdmgr/util/Executable.java create mode 100644 com/nemez/cmdmgr/util/ExecutableDefinition.java create mode 100644 com/nemez/cmdmgr/util/HelpPageCommand.java create mode 100644 com/nemez/cmdmgr/util/Property.java create mode 100644 plugin.yml create mode 100644 test.cmd diff --git a/CmdMgrTest.java b/CmdMgrTest.java new file mode 100644 index 0000000..039eeaa --- /dev/null +++ b/CmdMgrTest.java @@ -0,0 +1,58 @@ + +import java.io.File; + +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.CommandManager; + +public class CmdMgrTest extends JavaPlugin { + + public void onEnable() { + CommandManager.registerCommand(new File("plugins/test.cmd"), this, this); + } + + public void onDisable() { + + } + + @Command(hook="home_set") + public boolean executeSetHome(CommandSender sender, String name) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home set " + name); + return true; + } + + @Command(hook="home_set_coords") + public boolean executeSetHomeBasedOnCoords(CommandSender sender, String name, int x, int y, int z) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home set " + name + " " + x + " " + y + " " + z); + return true; + } + + @Command(hook="home_del") + public void executeDelHome(CommandSender sender, String name) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home del " + name); + } + + @Command(hook="home_list") + public void executeListHomes(CommandSender sender) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home list"); + } + + @Command(hook="home_tp") + public void executeTeleportHome(CommandSender sender, String name) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home " + name); + } + + @Command(hook="noskope") + public boolean executeMagik(CommandSender sender) { + sender.sendMessage("You executed:"); + sender.sendMessage("/home yolo swag"); + return true; + } +} diff --git a/com/nemez/cmdmgr/Command.java b/com/nemez/cmdmgr/Command.java new file mode 100644 index 0000000..3cb61df --- /dev/null +++ b/com/nemez/cmdmgr/Command.java @@ -0,0 +1,13 @@ +package com.nemez.cmdmgr; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Command { + + String hook(); +} diff --git a/com/nemez/cmdmgr/CommandManager.java b/com/nemez/cmdmgr/CommandManager.java new file mode 100644 index 0000000..978bf90 --- /dev/null +++ b/com/nemez/cmdmgr/CommandManager.java @@ -0,0 +1,396 @@ +package com.nemez.cmdmgr; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; + +import org.bukkit.plugin.java.JavaPlugin; + +import com.nemez.cmdmgr.component.ArgumentComponent; +import com.nemez.cmdmgr.component.ByteComponent; +import com.nemez.cmdmgr.component.ChainComponent; +import com.nemez.cmdmgr.component.ConstantComponent; +import com.nemez.cmdmgr.component.DoubleComponent; +import com.nemez.cmdmgr.component.FloatComponent; +import com.nemez.cmdmgr.component.ICommandComponent; +import com.nemez.cmdmgr.component.IntegerComponent; +import com.nemez.cmdmgr.component.LongComponent; +import com.nemez.cmdmgr.component.ShortComponent; +import com.nemez.cmdmgr.component.StringComponent; +import com.nemez.cmdmgr.util.BranchStack; +import com.nemez.cmdmgr.util.Executable; +import com.nemez.cmdmgr.util.HelpPageCommand; +import com.nemez.cmdmgr.util.Property; + +/** + * Example command.cmd + * + * command home: + * set [string:name]: + * run home_set name + * help Set a new home + * perm home.set + * del [string:name]: + * run home_del name + * help Delete home\n&CCannot be undone! + * perm home.del + * list: + * run home_list + * help Show all homes + * perm home.list + * [string:name]: + * run home_tp name + * help Teleport to specified home + * perm home.tp + * + * Generated in-game command structure: + * (will only show commands the user has permission to execute) + * + * /home set + * /home del + * /home list + * /home + * /home help + * + * Java code: + * + * @Command(hook="home_set") + * public void executeHomeSet(String name) { + * ... + * } + * + * @Command(hook="home_del") + * public void executeHomeDelete(String name) { + * ... + * } + * + * @Command(hook="home_list") + * public void executeHomeList() { + * ... + * } + * + * @Command(hook="home_tp") + * public void executeHomeTeleport(String name) { + * ... + * } + */ + +public class CommandManager { + + public static boolean debugOutput = false; + + public static boolean registerCommand(String cmdSourceCode, Object commandHandler, JavaPlugin plugin) { + if (cmdSourceCode == null || commandHandler == null || plugin == null) { + return false; + } + Method[] methods = commandHandler.getClass().getMethods(); + ArrayList finalMethods = new ArrayList(); + + for (Method m : methods) { + if (m.getAnnotationsByType(Command.class).length > 0 && (m.getModifiers() & Modifier.STATIC) == 0) { + finalMethods.add(m); + } + } + return parse(cmdSourceCode, finalMethods, plugin, commandHandler); + } + + public static boolean registerCommand(File sourceFile, Object commandHandler, JavaPlugin plugin) { + StringBuilder src = new StringBuilder(); + String buf = ""; + try { + BufferedReader reader = new BufferedReader(new FileReader(sourceFile)); + while ((buf = reader.readLine()) != null) { + src.append(buf); + } + reader.close(); + } catch (Exception e) { + // TODO log this crap into the console... + return false; + } + return registerCommand(src.toString(), commandHandler, plugin); + } + + private static boolean parse(String source, ArrayList methods, JavaPlugin plugin, Object methodContainer) { + char[] chars = source.toCharArray(); + StringBuilder buffer = new StringBuilder(); + String cmdName = null; + boolean insideType = false; + boolean gettingName = false; + char previous = '\0'; + ChainComponent currentChain = new ChainComponent(); + BranchStack stack = new BranchStack(); + ArgumentComponent currentArgComp = null; + Property currentProp = Property.NONE; + int bracketCounter = 0; + int line = 0; + + for (int i = 0; i < chars.length; i++) { + char current = chars[i]; + + if (current == '\n') { + line++; + } + + if (current == ':') { + if (insideType) { + if (currentArgComp != null) { + // error + System.err.println("already processing a type"); + return false; + }else{ + currentArgComp = resolveComponentType(buffer.toString()); + buffer = new StringBuilder(); + if (currentArgComp == null) { + // error - invalid type + System.err.println("invalid type"); + return false; + } + } + }else{ + // error + System.err.println("where do you think a colon belongs..."); + return false; + } + }else if (current == ';') { + if (previous == '\\') { + buffer.append(';'); + }else{ + if (stack.get() == null) { + // error + System.err.println("stack is empty..."); + return false; + } + if (currentProp == Property.HELP) { + stack.get().help = buffer.toString(); + }else if (currentProp == Property.EXECUTE) { + stack.get().execute = buffer.toString(); + }else if (currentProp == Property.PERMISSION) { + stack.get().permission = buffer.toString().trim(); + }else{ + // what? + System.err.println("okay, this is my fault"); + return false; + } + currentProp = Property.NONE; + buffer = new StringBuilder(); + } + }else if (current == '{') { + bracketCounter++; + if (gettingName && cmdName == null) { + cmdName = buffer.toString().trim(); + }else{ + if (currentArgComp == null) { + if (buffer.toString().trim().length() > 0) { + currentChain.append(new ConstantComponent(buffer.toString().trim())); + } + }else{ + currentChain.append(currentArgComp); + currentArgComp = null; + } + } + buffer = new StringBuilder(); + ChainComponent top = stack.get(); + if (top != null) { + top.append(currentChain); + } + stack.push(currentChain); + currentChain = new ChainComponent(); + }else if (current == '}') { + bracketCounter--; + ChainComponent popped = stack.pop(); + if (popped == null) { + // error + System.err.println("outta stacks!"); + return false; + } + if (bracketCounter == 0) { + postProcess(cmdName, popped, methods, plugin, methodContainer); // \o/ + buffer = new StringBuilder(); + cmdName = null; + insideType = false; + gettingName = false; + previous = '\0'; + currentChain = new ChainComponent(); + stack = new BranchStack(); + currentArgComp = null; + currentProp = Property.NONE; + continue; + } + currentChain = new ChainComponent(); + }else if (current == ' ') { + if (currentProp != Property.NONE) { + buffer.append(' '); + }else{ + if (buffer.toString().equals("command") && !gettingName && cmdName == null) { + gettingName = true; + }else if (buffer.toString().equals("help")) { + currentProp = Property.HELP; + }else if (buffer.toString().equals("run")) { + currentProp = Property.EXECUTE; + }else if (buffer.toString().equals("perm")) { + currentProp = Property.PERMISSION; + }else{ + if (gettingName && cmdName == null) { + cmdName = buffer.toString().trim(); + }else{ + if (currentArgComp == null) { + if (buffer.toString().trim().length() > 0) { + currentChain.append(new ConstantComponent(buffer.toString().trim())); + } + }else{ + currentChain.append(currentArgComp); + currentArgComp = null; + } + } + } + buffer = new StringBuilder(); + } + }else if (current == '[') { + if (currentProp != Property.NONE) { + buffer.append('['); + }else if (insideType) { + // error + System.err.println("dont declare a type inside of a type please"); + return false; + }else{ + insideType = true; + } + }else if (current == ']') { + if (currentProp != Property.NONE) { + buffer.append(']'); + }else if (insideType) { + insideType = false; + if (currentArgComp == null) { + // error + System.err.println("type without a type?"); + return false; + }else{ + currentArgComp.argName = buffer.toString(); + buffer = new StringBuilder(); + } + }else{ + // error + System.err.println("a square bracket doesnt belong here"); + return false; + } + }else if (current == '&' && currentProp == Property.HELP) { + if (previous == '\\') { + buffer.append('&'); + }else{ + buffer.append('§'); + } + }else if (current == 'n' && currentProp == Property.HELP) { + if (previous == '\\') { + buffer.append('\n'); + }else{ + buffer.append('n'); + } + }else if (current == 't' && currentProp == Property.HELP) { + if (previous == '\\') { + buffer.append('\t'); + }else{ + buffer.append('t'); + } + }else if (current == '\\' && currentProp == Property.HELP) { + if (previous == '\\') { + buffer.append('\\'); + } + }else if (current != '\r' && current != '\n' && current != '\t') { + buffer.append(current); + } + previous = current; + } + + return true; + } + + private static ArgumentComponent resolveComponentType(String type) { + switch (type) { + case "string": + return new StringComponent(); + case "int": + case "integer": + return new IntegerComponent(); + case "short": + return new ShortComponent(); + case "long": + return new LongComponent(); + case "byte": + return new ByteComponent(); + case "float": + return new FloatComponent(); + case "double": + return new DoubleComponent(); + } + return null; + } + + private static void postProcess(String cmdName, ChainComponent components, ArrayList methods, JavaPlugin plugin, Object methodContainer) { + Executable cmd = new Executable(cmdName, constructHelpPages(cmdName, components)); + cmd.register(methods, plugin, methodContainer); + } + + private static ArrayList constructHelpPages(String cmdName, ChainComponent root) { + String[] rawLines = constructHelpPagesRecursive(root).split("\r"); + ArrayList pages = new ArrayList(); + ArrayList lines = new ArrayList(); + HelpPageCommand[] page = new HelpPageCommand[5]; + + for (int i = 0; i < rawLines.length; i++) { + if (rawLines[i].length() > 0 && !rawLines[i].equals("\0null\0null\0null\0")) { + lines.add(rawLines[i]); + } + } + + boolean firstPass = true; + int i; + for (i = 0; i < lines.size(); i++) { + if (i % 5 == 0 && !firstPass) { + pages.add(page); + page = new HelpPageCommand[5]; + } + String[] cmd = lines.get(i).split("\0"); + page[i % 5] = new HelpPageCommand(cmd[1], "/" + cmdName + " " + cmd[0], cmd[3], cmd[2]); + firstPass = false; + } + if (i % 5 == 0) { + pages.add(page); + page = new HelpPageCommand[5]; + } + page[i % 5] = new HelpPageCommand(cmdName + ".help", "/" + cmdName + " help ", "Shows help.", null); + pages.add(page); + + return pages; + } + + private static String constructHelpPagesRecursive(ICommandComponent component) { + String data = ""; + + if (component instanceof ChainComponent) { + ChainComponent comp = (ChainComponent) component; + ArrayList leaves = new ArrayList(); + String chain = ""; + data += "\r"; + for (ICommandComponent c : comp.getComponents()) { + String temp = constructHelpPagesRecursive(c); + if (c instanceof ChainComponent) { + temp = temp.replaceAll("\r", "\r" + chain); + leaves.add(temp); + }else{ + chain += temp; + } + } + data += chain + "\0" + comp.permission + "\0" + comp.execute + "\0" + comp.help + "\0"; + for (String s : leaves) { + data += s; + } + }else{ + data += component.getComponentInfo() + " "; + } + + return data; + } +} diff --git a/com/nemez/cmdmgr/component/ArgumentComponent.java b/com/nemez/cmdmgr/component/ArgumentComponent.java new file mode 100644 index 0000000..a1058ff --- /dev/null +++ b/com/nemez/cmdmgr/component/ArgumentComponent.java @@ -0,0 +1,11 @@ +package com.nemez.cmdmgr.component; + +public abstract class ArgumentComponent implements ICommandComponent { + + public String argName; + + @Override + public String argName() { + return argName; + } +} diff --git a/com/nemez/cmdmgr/component/ByteComponent.java b/com/nemez/cmdmgr/component/ByteComponent.java new file mode 100644 index 0000000..4b92b5a --- /dev/null +++ b/com/nemez/cmdmgr/component/ByteComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class ByteComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Byte.parseByte(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Byte.parseByte(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":i8>"; + } +} diff --git a/com/nemez/cmdmgr/component/ChainComponent.java b/com/nemez/cmdmgr/component/ChainComponent.java new file mode 100644 index 0000000..a701ec8 --- /dev/null +++ b/com/nemez/cmdmgr/component/ChainComponent.java @@ -0,0 +1,47 @@ +package com.nemez.cmdmgr.component; + +import java.util.ArrayList; + +public class ChainComponent implements ICommandComponent { + + private ArrayList components; + public String permission; + public String help; + public String execute; + + public ChainComponent() { + components = new ArrayList(); + } + + public void append(ICommandComponent comp) { + components.add(comp); + } + + @Override + public Object get(String input) { + return components; + } + + @Override + public boolean valid(String input) { + return true; + } + + @Override + public String argName() { + return null; + } + + @Override + public String getComponentInfo() { + return "chain[" + components.size() + "]"; + } + + public int capacity() { + return components.size(); + } + + public ArrayList getComponents() { + return components; + } +} diff --git a/com/nemez/cmdmgr/component/ConstantComponent.java b/com/nemez/cmdmgr/component/ConstantComponent.java new file mode 100644 index 0000000..d3f2490 --- /dev/null +++ b/com/nemez/cmdmgr/component/ConstantComponent.java @@ -0,0 +1,33 @@ +package com.nemez.cmdmgr.component; + +public class ConstantComponent implements ICommandComponent { + + private String component; + + public ConstantComponent(String comp) { + component = comp; + } + + @Override + public Object get(String input) { + if (input.equals(component)) { + return input; + } + return null; + } + + @Override + public boolean valid(String input) { + return input.equals(component); + } + + @Override + public String argName() { + return null; + } + + @Override + public String getComponentInfo() { + return component; + } +} diff --git a/com/nemez/cmdmgr/component/DoubleComponent.java b/com/nemez/cmdmgr/component/DoubleComponent.java new file mode 100644 index 0000000..44bd638 --- /dev/null +++ b/com/nemez/cmdmgr/component/DoubleComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class DoubleComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Double.parseDouble(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Double.parseDouble(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":fp64>"; + } +} diff --git a/com/nemez/cmdmgr/component/FloatComponent.java b/com/nemez/cmdmgr/component/FloatComponent.java new file mode 100644 index 0000000..95ef5e4 --- /dev/null +++ b/com/nemez/cmdmgr/component/FloatComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class FloatComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Float.parseFloat(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Float.parseFloat(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":fp32>"; + } +} diff --git a/com/nemez/cmdmgr/component/ICommandComponent.java b/com/nemez/cmdmgr/component/ICommandComponent.java new file mode 100644 index 0000000..ede0978 --- /dev/null +++ b/com/nemez/cmdmgr/component/ICommandComponent.java @@ -0,0 +1,9 @@ +package com.nemez.cmdmgr.component; + +public interface ICommandComponent { + + public Object get(String input); + public boolean valid(String input); + public String argName(); + public String getComponentInfo(); +} diff --git a/com/nemez/cmdmgr/component/IntegerComponent.java b/com/nemez/cmdmgr/component/IntegerComponent.java new file mode 100644 index 0000000..aef1974 --- /dev/null +++ b/com/nemez/cmdmgr/component/IntegerComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class IntegerComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Integer.parseInt(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":i32>"; + } +} diff --git a/com/nemez/cmdmgr/component/LongComponent.java b/com/nemez/cmdmgr/component/LongComponent.java new file mode 100644 index 0000000..486fd98 --- /dev/null +++ b/com/nemez/cmdmgr/component/LongComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class LongComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Long.parseLong(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Long.parseLong(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":i64>"; + } +} \ No newline at end of file diff --git a/com/nemez/cmdmgr/component/ShortComponent.java b/com/nemez/cmdmgr/component/ShortComponent.java new file mode 100644 index 0000000..f4570b1 --- /dev/null +++ b/com/nemez/cmdmgr/component/ShortComponent.java @@ -0,0 +1,28 @@ +package com.nemez.cmdmgr.component; + +public class ShortComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + try { + return Short.parseShort(input); + } catch (NumberFormatException e) { + return null; + } + } + + @Override + public boolean valid(String input) { + try { + Short.parseShort(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":i16>"; + } +} \ No newline at end of file diff --git a/com/nemez/cmdmgr/component/StringComponent.java b/com/nemez/cmdmgr/component/StringComponent.java new file mode 100644 index 0000000..f276a33 --- /dev/null +++ b/com/nemez/cmdmgr/component/StringComponent.java @@ -0,0 +1,19 @@ +package com.nemez.cmdmgr.component; + +public class StringComponent extends ArgumentComponent { + + @Override + public Object get(String input) { + return input; + } + + @Override + public boolean valid(String input) { + return true; + } + + @Override + public String getComponentInfo() { + return "<" + argName + ":str>"; + } +} diff --git a/com/nemez/cmdmgr/util/BranchStack.java b/com/nemez/cmdmgr/util/BranchStack.java new file mode 100644 index 0000000..aac8efb --- /dev/null +++ b/com/nemez/cmdmgr/util/BranchStack.java @@ -0,0 +1,33 @@ +package com.nemez.cmdmgr.util; + +import java.util.ArrayList; + +import com.nemez.cmdmgr.component.ChainComponent; + +public class BranchStack { + + private ArrayList components; + + public BranchStack() { + components = new ArrayList(); + } + + public void push(ChainComponent comp) { + components.add(comp); + } + + public ChainComponent pop() { + if (components.size() > 0) { + ChainComponent toPop = components.remove(components.size() - 1); + return toPop; + } + return null; + } + + public ChainComponent get() { + if (components.size() > 0) { + return components.get(components.size() - 1); + } + return null; + } +} diff --git a/com/nemez/cmdmgr/util/Executable.java b/com/nemez/cmdmgr/util/Executable.java new file mode 100644 index 0000000..d93f7e5 --- /dev/null +++ b/com/nemez/cmdmgr/util/Executable.java @@ -0,0 +1,249 @@ +package com.nemez.cmdmgr.util; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; + +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.java.JavaPlugin; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.component.ByteComponent; +import com.nemez.cmdmgr.component.ConstantComponent; +import com.nemez.cmdmgr.component.DoubleComponent; +import com.nemez.cmdmgr.component.FloatComponent; +import com.nemez.cmdmgr.component.ICommandComponent; +import com.nemez.cmdmgr.component.IntegerComponent; +import com.nemez.cmdmgr.component.LongComponent; +import com.nemez.cmdmgr.component.ShortComponent; +import com.nemez.cmdmgr.component.StringComponent; + +public class Executable implements CommandExecutor { + + private ArrayList commands; + private ArrayList help; + private String name; + + public Executable(String name, ArrayList help) { + this.help = help; + this.name = name; + this.commands = new ArrayList(); + } + + public void register(ArrayList methods, JavaPlugin plugin, Object methodContainer) { + for (HelpPageCommand[] page : help) { + for (HelpPageCommand cmd : page) { + if (cmd != null) { + processLine(cmd.usage.split("\\ "), cmd.permission, cmd.method, methods, methodContainer); + } + } + } + + PluginCommand plcmd = plugin.getCommand(name); + if (plcmd == null) { + System.out.println("the fuck"); + }else{ + plcmd.setExecutor(this); + } + } + + private void processLine(String[] line, String permission, String method, ArrayList methods, Object methodContainer) { + ArrayList command = new ArrayList(); + if (method == null && line[1].equals("help")) { + command.add(new ConstantComponent("help")); + IntegerComponent pageID = new IntegerComponent(); + pageID.argName = "page"; + command.add(pageID); + ExecutableDefinition def = new ExecutableDefinition(command, permission, null, methodContainer); + commands.add(def); + return; + } + HashMap methodParams = new HashMap(); + method = method.trim() + " "; + String[] methodArray = method.split(" "); + Method target = null; + + for (String s : line) { + if (s.contains("/")) { + continue; + } + if (s.contains(":")) { + String[] type = s.split(":"); + String paramName = ""; + switch (type[1].substring(0, type[1].length() - 1)) { + case "i8": + ByteComponent comp1 = new ByteComponent(); + comp1.argName = type[0].substring(1); + paramName = comp1.argName; + command.add(comp1); + break; + case "i16": + ShortComponent comp2 = new ShortComponent(); + comp2.argName = type[0].substring(1); + paramName = comp2.argName; + command.add(comp2); + break; + case "i32": + IntegerComponent comp3 = new IntegerComponent(); + comp3.argName = type[0].substring(1); + paramName = comp3.argName; + command.add(comp3); + break; + case "i64": + LongComponent comp4 = new LongComponent(); + comp4.argName = type[0].substring(1); + paramName = comp4.argName; + command.add(comp4); + break; + case "fp32": + FloatComponent comp5 = new FloatComponent(); + comp5.argName = type[0].substring(1); + paramName = comp5.argName; + command.add(comp5); + break; + case "fp64": + DoubleComponent comp6 = new DoubleComponent(); + comp6.argName = type[0].substring(1); + paramName = comp6.argName; + command.add(comp6); + break; + case "str": + StringComponent comp7 = new StringComponent(); + comp7.argName = type[0].substring(1); + paramName = comp7.argName; + command.add(comp7); + break; + default: + System.err.println("impossible just happened!"); + return; + } + int index = 0; + for (int i = 1; i < methodArray.length; i++) { + if (methodArray[i] != null && !methodArray[i].trim().equals("")) { + if (methodArray[i].trim().equals(paramName)) { + methodParams.put(index, command.get(command.size() - 1)); + } + index++; + } + } + }else{ + command.add(new ConstantComponent(s)); + } + } + + for (Method m : methods) { + Command[] annotations = m.getAnnotationsByType(Command.class); + if (annotations == null || annotations.length != 1) { + System.err.println("Method not found! (" + methodArray[0] + ")"); + return; + }else{ + if (annotations[0].hook().equals(methodArray[0])) { + Class[] params = m.getParameterTypes(); + if (params.length -1 != methodParams.size()) { + System.err.println("error again! :D"); + return; + }else{ + for (int i = 0; i < params.length; i++) { + if (i == 0) { + if (params[0] != CommandSender.class) { + System.err.println("you're missing the 'CommandSender' argument... it must be first btw"); + return; + } + }else{ + ICommandComponent comp = methodParams.get(i - 1); + if (comp instanceof ByteComponent && params[i] == byte.class) { + + }else if (comp instanceof ShortComponent && params[i] == short.class) { + + }else if (comp instanceof IntegerComponent && params[i] == int.class) { + + }else if (comp instanceof LongComponent && params[i] == long.class) { + + }else if (comp instanceof FloatComponent && params[i] == float.class) { + + }else if (comp instanceof DoubleComponent && params[i] == double.class) { + + }else if (comp instanceof StringComponent && params[i] == String.class) { + + }else{ + System.err.println("error yet again, this time you messed up the method inputs"); + return; + } + } + } + target = m; + break; + } + } + } + } + if (target == null) { + System.err.println("Method not found! (" + methodArray[0] + ")"); + return; + } + ExecutableDefinition def = new ExecutableDefinition(command, permission, target, methodContainer); + commands.add(def); + } + + @Override + public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String name, String[] args) { + ArrayList defs = new ArrayList(); + defs.addAll(commands); + for (int i = 0; i < args.length; i++) { + for (int j = 0; j < defs.size(); j++) { + if (!defs.get(j).valid(i, args[i])) { + defs.remove(j); + j--; + } + } + } + if (args.length == 0 || defs.size() == 0) { + printPage(sender, 1); + }else{ + ExecutableDefinition def = defs.get(0); + if (!sender.hasPermission(def.getPermission())) { + sender.sendMessage("§cYou do not have permission to execute this command."); + return true; + } + if (def.getLength() != args.length) { + printPage(sender, 1); + return true; + } + ArrayList arguments = new ArrayList(); + for (int i = 0; i < args.length; i++) { + if (def.isArgument(i)) { + arguments.add(def.get(i, args[i])); + } + } + if (def.isHelp() || args[0].equals("help")) { + try { + int page = Integer.parseInt(args[1]); + printPage(sender, page); + } catch (Exception e) { + printPage(sender, 1); + } + }else if (!def.invoke(arguments, sender)) { + printPage(sender, 1); + } + } + return true; + } + + private void printPage(CommandSender sender, int page) { + page--; + if (page < 0 || page >= help.size()) { + sender.sendMessage("§cNon-existant page (" + (page + 1) + ").\nThere are " + help.size() + " pages."); + }else{ + HelpPageCommand[] pageData = help.get(page); + sender.sendMessage("§a### Help Page " + (page + 1) + "/" + (help.size()) + " ###"); + for (HelpPageCommand c : pageData) { + if (c != null) { + sender.sendMessage("§6" + c.usage); + sender.sendMessage("§b" + c.description); + } + } + } + } +} diff --git a/com/nemez/cmdmgr/util/ExecutableDefinition.java b/com/nemez/cmdmgr/util/ExecutableDefinition.java new file mode 100644 index 0000000..f04b65a --- /dev/null +++ b/com/nemez/cmdmgr/util/ExecutableDefinition.java @@ -0,0 +1,81 @@ +package com.nemez.cmdmgr.util; + +import java.lang.reflect.Method; +import java.util.ArrayList; + +import org.bukkit.command.CommandSender; + +import com.nemez.cmdmgr.component.ArgumentComponent; +import com.nemez.cmdmgr.component.ICommandComponent; + +public class ExecutableDefinition { + + private ArrayList components; + private String permission; + private Method target; + private Object methodContainer; + + public ExecutableDefinition(ArrayList cmd, String perm, Method method, Object methodContainer) { + this.components = cmd; + this.permission = perm; + this.target = method; + this.methodContainer = methodContainer; + } + + public boolean valid(int index, String arg) { + if (index < 0 || index >= components.size()) { + return false; + } + return components.get(index).valid(arg); + } + + public Object get(int index, String arg) { + if (index < 0 || index >= components.size()) { + return null; + } + return components.get(index).get(arg); + } + + public boolean isArgument(int index) { + if (index < 0 || index >= components.size()) { + return false; + } + return components.get(index) instanceof ArgumentComponent; + } + + public boolean isHelp() { + return target == null && components.get(0).valid("help") && components.get(1).getComponentInfo().equals(""); + } + + public String getPermission() { + return permission; + } + + public int getLength() { + return components.size(); + } + + public boolean invoke(ArrayList args, CommandSender sender) { + if (target == null) { + return false; + } + Object[] arguments = new Object[args.size() + 1]; + for (int i = 1; i < arguments.length; i++) { + arguments[i] = args.get(i - 1); + } + arguments[0] = sender; + try { + if (target.getReturnType() == void.class) { + target.invoke(methodContainer, arguments); + return true; + }else if (target.getReturnType() == boolean.class) { + return (boolean) target.invoke(methodContainer, arguments); + } + } catch (Exception e) { + System.err.println("M8 you're missing a function..."); + e.printStackTrace(); + return true; + } + return false; + } +} diff --git a/com/nemez/cmdmgr/util/HelpPageCommand.java b/com/nemez/cmdmgr/util/HelpPageCommand.java new file mode 100644 index 0000000..e82682e --- /dev/null +++ b/com/nemez/cmdmgr/util/HelpPageCommand.java @@ -0,0 +1,16 @@ +package com.nemez.cmdmgr.util; + +public class HelpPageCommand { + + public String permission; + public String usage; + public String description; + public String method; + + public HelpPageCommand(String perm, String usage, String description, String method) { + this.permission = perm; + this.usage = usage; + this.description = description; + this.method = method; + } +} diff --git a/com/nemez/cmdmgr/util/Property.java b/com/nemez/cmdmgr/util/Property.java new file mode 100644 index 0000000..5703bea --- /dev/null +++ b/com/nemez/cmdmgr/util/Property.java @@ -0,0 +1,7 @@ +package com.nemez.cmdmgr.util; + +public enum Property { + + NONE, PERMISSION, HELP, EXECUTE; + +} diff --git a/plugin.yml b/plugin.yml new file mode 100644 index 0000000..64a4c97 --- /dev/null +++ b/plugin.yml @@ -0,0 +1,11 @@ +name: CommandManagerTest +main: CmdMgrTest +version: 13.37 +author: Nemes +commands: + home: + description: I dont get displayed, but the one below me is important + usage: /home + permission: home.blabla.idk.might.be.important + permission-message: yeah if this ever got displayed xD + \ No newline at end of file diff --git a/test.cmd b/test.cmd new file mode 100644 index 0000000..1b60081 --- /dev/null +++ b/test.cmd @@ -0,0 +1,34 @@ + +command home { + + set [string:name] { + [int:x] [int:y] [int:z] { + run home_set_coords name x y z; + perm home.set.xyz; + help Sets a new home at coordinates XYZ; + } + run home_set name; + perm home.set; + help Sets a new home; + } + del [string:name] { + run home_del name; + help Deletes a home\n&cCannot be undone!; + perm home.del; + } + list { + help Shows all homes; + run home_list; + perm home.list; + } + [string:name] { + perm home.tp; + help Teleports to a home; + run home_tp name; + } + yolo swag { + perm yo.mamma; + help Reks you; + run noskope; + } +} \ No newline at end of file -- cgit v1.2.3