diff --git a/src/main/java/org/ultramine/commands/IExtendedCommand.java b/src/main/java/org/ultramine/commands/IExtendedCommand.java new file mode 100644 index 0000000..e17eb1e --- /dev/null +++ b/src/main/java/org/ultramine/commands/IExtendedCommand.java @@ -0,0 +1,7 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommand; + +public interface IExtendedCommand extends ICommand +{ +} diff --git a/src/main/java/org/ultramine/commands/completion/ArgumentCompleter.java b/src/main/java/org/ultramine/commands/completion/ArgumentCompleter.java new file mode 100644 index 0000000..290a1ce --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/ArgumentCompleter.java @@ -0,0 +1,14 @@ +package org.ultramine.commands.completion; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ArgumentCompleter +{ + String value(); + boolean isUsername() default false; +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/completion/CommandCompletionHandler.java b/src/main/java/org/ultramine/commands/completion/CommandCompletionHandler.java new file mode 100644 index 0000000..7a9d4ff --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/CommandCompletionHandler.java @@ -0,0 +1,89 @@ +package org.ultramine.commands.completion; + +import java.util.ArrayList; +import java.util.List; + +public class CommandCompletionHandler +{ + private List completers = new ArrayList(); + private int usernameArgIndex = -1; + private boolean isInfinite = false; + + public List getCompletionOptions(String[] args) + { + if (completers.size() == 0) + return null; + + ArgumentCompleter completer; + if (completers.size() < args.length) + completer = isInfinite ? completers.get(completers.size() - 1) : IGNORED; + else + completer = completers.get(args.length - 1); + + if (completer != IGNORED) + return completer.getCompletionOptions(args); + else + return null; + } + + public boolean isUsernameIndex(int checkArgNum) + { + return checkArgNum == usernameArgIndex; + } + + public void addNextArgument(IArgumentCompletionHandler handler, String[] params) + { + if (usernameArgIndex == -1 && handler.isUsername()) + usernameArgIndex = completers.size(); + + completers.add(new ArgumentCompleter(handler, params)); + } + + public void ignoreNextArgument() + { + completers.add(IGNORED); + } + + public void makeInfinite() + { + isInfinite = true; + } + + private static ArgumentCompleter IGNORED = new ArgumentCompleter(null, null); + private static class ArgumentCompleter + { + private IArgumentCompletionHandler handler; + private String[] params; + + private ArgumentCompleter(IArgumentCompletionHandler handler, String[] params) + { + this.handler = handler; + this.params = params; + } + + List getCompletionOptions(String[] args) + { + String[] params = new String[this.params.length]; + for (int i = 0; i < this.params.length; i++) + { + String param = this.params[i]; + if (param.startsWith("&")) + { + try + { + int argNum = Integer.valueOf(param.substring(1)); + params[i] = args[argNum]; + } + catch (Exception ignored) + { + params[i] = param; + } + } + else + params[i] = param; + } + + return handler.handleCompletion(args[args.length - 1], params); + } + } +} diff --git a/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java b/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java new file mode 100644 index 0000000..355fcdb --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java @@ -0,0 +1,95 @@ +package org.ultramine.commands.completion; + +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CompletionStringParser +{ + private static final Pattern argumentPattern = Pattern.compile("<\\s*([^<>\\s]*)\\s*([^<>]*)>"); + private Map handlers = new HashMap(); + + public CommandCompletionHandler parse(String completionString) + { + CommandCompletionHandler result = new CommandCompletionHandler(); + Matcher matcher = argumentPattern.matcher(completionString); + + while (matcher.find()) + { + String handlerName = matcher.group(1); + + if (handlerName.isEmpty() || !handlers.containsKey(handlerName)) + { + result.ignoreNextArgument(); + } + else + { + String[] params = StringUtils.split(matcher.group(2)); + result.addNextArgument(handlers.get(handlerName), params); + } + } + + if (completionString.endsWith("...")) + result.makeInfinite(); + + return result; + } + + public void registerHandler(String name, IArgumentCompletionHandler handler) + { + handlers.put(name, handler); + } + + public void registerHandlers(Class cls) + { + for (Method handler : cls.getMethods()) + { + if (handler.isAnnotationPresent(ArgumentCompleter.class)) + { + ArgumentCompleter data = handler.getAnnotation(ArgumentCompleter.class); + registerHandler(data.value(), new WrappedHandler(handler, data.isUsername())); + } + } + } + + private static class WrappedHandler implements IArgumentCompletionHandler + { + private Method method; + private boolean isUsername; + + private WrappedHandler(Method method, boolean isUsername) + { + this.method = method; + this.isUsername = isUsername; + } + + @Override + public List handleCompletion(String val, String[] args) + { + try + { + return (List) method.invoke(null, val, args); + } + catch (IllegalAccessException ignored) + { + } + catch (InvocationTargetException ignored) + { + } + + return null; + } + + @Override + public boolean isUsername() + { + return isUsername; + } + } +} diff --git a/src/main/java/org/ultramine/commands/completion/DefaultCompleters.java b/src/main/java/org/ultramine/commands/completion/DefaultCompleters.java new file mode 100644 index 0000000..7af8a11 --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/DefaultCompleters.java @@ -0,0 +1,69 @@ +package org.ultramine.commands.completion; + +import net.minecraft.block.Block; +import net.minecraft.command.CommandBase; +import net.minecraft.entity.EntityList; +import net.minecraft.item.Item; +import net.minecraft.server.MinecraftServer; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultCompleters +{ + @ArgumentCompleter(value = "player", isUsername = true) + public static List player(String val, String[] args) + { + return getListOfStringsMatchingWord(val, MinecraftServer.getServer().getAllUsernames()); + } + + @ArgumentCompleter("item") + public static List item(String val, String[] args) + { + return getListOfStringsFromIterableMatchingWord(val, Item.itemRegistry.getKeys()); + } + + @ArgumentCompleter("block") + public static List block(String val, String[] args) + { + return getListOfStringsFromIterableMatchingWord(val, Block.blockRegistry.getKeys()); + } + + @ArgumentCompleter("entity") + public static List entity(String val, String[] args) + { + return getListOfStringsFromIterableMatchingWord(val, EntityList.func_151515_b()); + } + + @ArgumentCompleter("list") + public static List list(String val, String[] args) + { + return getListOfStringsMatchingWord(val, args); + } + + public static List getListOfStringsMatchingWord(String filter, String[] strings) + { + List result = new ArrayList(); + + for (String str : strings) + { + if (CommandBase.doesStringStartWith(filter, str)) + result.add(str); + } + + return result; + } + + public static List getListOfStringsFromIterableMatchingWord(String filter, Iterable iterable) + { + List result = new ArrayList(); + + for (String str : iterable) + { + if (CommandBase.doesStringStartWith(filter, str)) + result.add(str); + } + + return result; + } +} diff --git a/src/main/java/org/ultramine/commands/completion/IArgumentCompletionHandler.java b/src/main/java/org/ultramine/commands/completion/IArgumentCompletionHandler.java new file mode 100644 index 0000000..6e601df --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/IArgumentCompletionHandler.java @@ -0,0 +1,9 @@ +package org.ultramine.commands.completion; + +import java.util.List; + +public interface IArgumentCompletionHandler +{ + List handleCompletion(String val, String[] args); + boolean isUsername(); +} \ No newline at end of file