diff --git a/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java b/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java index 1f7d8e1..037c44d 100644 --- a/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java +++ b/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java @@ -16,6 +16,7 @@ import net.minecraft.command.ICommand; import net.minecraft.server.MinecraftServer; import cpw.mods.fml.common.LoaderState.ModState; +import org.ultramine.commands.CommandRegistry; public class FMLServerStartingEvent extends FMLStateEvent { @@ -43,4 +44,9 @@ CommandHandler ch = (CommandHandler) getServer().getCommandManager(); ch.registerCommand(command); } + + public CommandRegistry getCommandRegistry() + { + return ((CommandHandler) getServer().getCommandManager()).getRegistry(); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/command/CommandHandler.java b/src/main/java/net/minecraft/command/CommandHandler.java index b47cd0c..75bbf63 100644 --- a/src/main/java/net/minecraft/command/CommandHandler.java +++ b/src/main/java/net/minecraft/command/CommandHandler.java @@ -1,13 +1,7 @@ package net.minecraft.command; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; @@ -16,12 +10,12 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; +import org.ultramine.commands.CommandRegistry; public class CommandHandler implements ICommandManager { private static final Logger logger = LogManager.getLogger(); - private final Map commandMap = new HashMap(); - private final Set commandSet = new HashSet(); + private final CommandRegistry registry = new CommandRegistry(); private static final String __OBFID = "CL_00001765"; public int executeCommand(ICommandSender par1ICommandSender, String par2Str) @@ -36,7 +30,7 @@ String[] astring = par2Str.split(" "); String s1 = astring[0]; astring = dropFirstString(astring); - ICommand icommand = (ICommand)this.commandMap.get(s1); + ICommand icommand = registry.get(s1); int i = this.getUsernameIndex(icommand, astring); int j = 0; ChatComponentTranslation chatcomponenttranslation; @@ -125,27 +119,12 @@ public ICommand registerCommand(ICommand par1ICommand) { - List list = par1ICommand.getCommandAliases(); - this.commandMap.put(par1ICommand.getCommandName(), par1ICommand); - this.commandSet.add(par1ICommand); + return registry.registerVanillaCommand(par1ICommand); + } - if (list != null) - { - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) - { - String s = (String)iterator.next(); - ICommand icommand1 = (ICommand)this.commandMap.get(s); - - if (icommand1 == null || !icommand1.getCommandName().equals(s)) - { - this.commandMap.put(s, par1ICommand); - } - } - } - - return par1ICommand; + public CommandRegistry getRegistry() + { + return registry; } private static String[] dropFirstString(String[] par0ArrayOfStr) @@ -167,26 +146,13 @@ if (astring.length == 1) { - ArrayList arraylist = new ArrayList(); - Iterator iterator = this.commandMap.entrySet().iterator(); - - while (iterator.hasNext()) - { - Entry entry = (Entry)iterator.next(); - - if (CommandBase.doesStringStartWith(s1, (String)entry.getKey()) && ((ICommand)entry.getValue()).canCommandSenderUseCommand(par1ICommandSender)) - { - arraylist.add(entry.getKey()); - } - } - - return arraylist; + return registry.filterPossibleCommandsNames(par1ICommandSender, s1); } else { if (astring.length > 1) { - ICommand icommand = (ICommand)this.commandMap.get(s1); + ICommand icommand = registry.get(s1); if (icommand != null) { @@ -200,25 +166,12 @@ public List getPossibleCommands(ICommandSender par1ICommandSender) { - ArrayList arraylist = new ArrayList(); - Iterator iterator = this.commandSet.iterator(); - - while (iterator.hasNext()) - { - ICommand icommand = (ICommand)iterator.next(); - - if (icommand.canCommandSenderUseCommand(par1ICommandSender)) - { - arraylist.add(icommand); - } - } - - return arraylist; + return registry.getPossibleCommands(par1ICommandSender); } public Map getCommands() { - return this.commandMap; + return registry.getCommandMap(); } private int getUsernameIndex(ICommand par1ICommand, String[] par2ArrayOfStr) diff --git a/src/main/java/org/ultramine/commands/Command.java b/src/main/java/org/ultramine/commands/Command.java index f971742..bd805e8 100644 --- a/src/main/java/org/ultramine/commands/Command.java +++ b/src/main/java/org/ultramine/commands/Command.java @@ -11,6 +11,7 @@ { public String name(); public String group(); + public String completion() default ""; public String[] aliases() default {}; public String[] permissions() default {}; public boolean isUsableFromServer() default true; diff --git a/src/main/java/org/ultramine/commands/CommandRegistry.java b/src/main/java/org/ultramine/commands/CommandRegistry.java new file mode 100644 index 0000000..bd0a818 --- /dev/null +++ b/src/main/java/org/ultramine/commands/CommandRegistry.java @@ -0,0 +1,113 @@ +package org.ultramine.commands; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraftforge.common.MinecraftForge; +import org.ultramine.commands.completion.CompletionStringParser; +import org.ultramine.commands.completion.RegisterCompletersEvent; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +public class CommandRegistry +{ + private Map commandMap; + private SortedSet registeredCommands; + private CompletionStringParser completionStringParser; + + public CommandRegistry() + { + commandMap = new HashMap(); + registeredCommands = new TreeSet(); + completionStringParser = new CompletionStringParser(); + + MinecraftForge.EVENT_BUS.post(new RegisterCompletersEvent(completionStringParser)); + } + + public IExtendedCommand registerCommand(IExtendedCommand command) + { + List aliases = command.getCommandAliases(); + commandMap.put(command.getCommandName(), command); + registeredCommands.add(command); + + if (aliases != null) + { + for (String alias : aliases) + { + IExtendedCommand cmd = commandMap.get(alias); + if (cmd == null || !cmd.getCommandName().equals(alias)) + commandMap.put(alias, cmd); + } + } + + return command; + } + + public IExtendedCommand registerVanillaCommand(ICommand command) + { + return registerCommand(new VanillaCommandWrapper(command)); + } + + public void registerCommands(Class cls) + { + for (Method method : cls.getMethods()) + { + if (method.isAnnotationPresent(Command.class) && Modifier.isStatic(method.getModifiers())) + { + Command data = method.getAnnotation(Command.class); + ICommandHandler handler = new MethodBasedCommandHandler(method); + + IExtendedCommand cmd = new HandlerBasedCommand(data.name(), data.group(), handler) + .withAliases(data.aliases()) + .withPermissions(data.permissions()) + .withUsableFromServer(data.isUsableFromServer()) + .withCompletionHandler(completionStringParser.parse(data.completion())); + + registerCommand(cmd); + } + } + } + + public IExtendedCommand get(String name) + { + return commandMap.get(name); + } + + public Map getCommandMap() + { + return commandMap; + } + + public List filterPossibleCommandsNames(ICommandSender sender, String filter) + { + List result = new ArrayList(); + + for (Map.Entry entry : commandMap.entrySet()) + { + if (CommandBase.doesStringStartWith(filter, entry.getKey()) && entry.getValue().canCommandSenderUseCommand(sender)) + result.add(entry.getKey()); + } + + return result; + } + + public List getPossibleCommands(ICommandSender sender) + { + List result = new ArrayList(); + + for (IExtendedCommand command : registeredCommands) + { + if (command.canCommandSenderUseCommand(sender)) + result.add(command); + } + + return result; + } + + public CompletionStringParser getCompletionStringParser() + { + return completionStringParser; + } +} diff --git a/src/main/java/org/ultramine/commands/HandlerBasedCommand.java b/src/main/java/org/ultramine/commands/HandlerBasedCommand.java new file mode 100644 index 0000000..35d4145 --- /dev/null +++ b/src/main/java/org/ultramine/commands/HandlerBasedCommand.java @@ -0,0 +1,131 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommandSender; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.ultramine.commands.completion.CommandCompletionHandler; +import org.ultramine.server.PermissionHandler; + +import java.util.Arrays; +import java.util.List; + +public class HandlerBasedCommand implements IExtendedCommand +{ + private static final Logger logger = LogManager.getLogger(); + + private String name; + private String usage; + private String group; + private String description; + + private ICommandHandler handler; + private CommandCompletionHandler completionHandler; + + private List aliases; + private String[] permissions; + private boolean isUsableFromServer = true; + + public HandlerBasedCommand(String name, String group, ICommandHandler handler) + { + this.name = name; + this.group = group; + this.handler = handler; + this.usage = "command." + name + ".usage"; + this.description = "command." + name + ".description"; + } + + public HandlerBasedCommand withAliases(String... aliases) + { + this.aliases = Arrays.asList(aliases); + return this; + } + + public HandlerBasedCommand withCompletionHandler(CommandCompletionHandler completionHandler) + { + this.completionHandler = completionHandler; + return this; + } + + public HandlerBasedCommand withPermissions(String[] permissions) + { + this.permissions = permissions; + return this; + } + + public HandlerBasedCommand withUsableFromServer(boolean isUsableFromServer) + { + this.isUsableFromServer = isUsableFromServer; + return this; + } + + @Override + public String getCommandName() + { + return name; + } + + @Override + public String getCommandUsage(ICommandSender var1) + { + return usage; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public String getGroup() + { + return group; + } + + @Override + public List getCommandAliases() + { + return aliases; + } + + @Override + public void processCommand(ICommandSender var1, String[] var2) + { + handler.processCommand(var1, var2); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender var1) + { + return (isUsableFromServer && var1.getCommandSenderName().equals("Server")) || PermissionHandler.getInstance().hasAny(var1, permissions); + } + + @Override + public List addTabCompletionOptions(ICommandSender var1, String[] var2) + { + if (completionHandler == null) + return null; + + return completionHandler.getCompletionOptions(var2); + } + + @Override + public boolean isUsernameIndex(String[] var1, int var2) + { + return completionHandler != null && completionHandler.isUsernameIndex(var2); + } + + @Override + public int compareTo(Object o) + { + if (o instanceof IExtendedCommand) + { + int result = getGroup().compareTo(((IExtendedCommand) o).getGroup()); + if (result == 0) + result = getCommandName().compareTo(((IExtendedCommand) o).getCommandName()); + + return result; + } + return -1; + } +} diff --git a/src/main/java/org/ultramine/commands/ICommandHandler.java b/src/main/java/org/ultramine/commands/ICommandHandler.java new file mode 100644 index 0000000..76618fd --- /dev/null +++ b/src/main/java/org/ultramine/commands/ICommandHandler.java @@ -0,0 +1,8 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommandSender; + +public interface ICommandHandler +{ + public void processCommand(ICommandSender var1, String[] var2); +} diff --git a/src/main/java/org/ultramine/commands/MethodBasedCommand.java b/src/main/java/org/ultramine/commands/MethodBasedCommand.java deleted file mode 100644 index 1fb2ef3..0000000 --- a/src/main/java/org/ultramine/commands/MethodBasedCommand.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.ultramine.commands; - -import net.minecraft.command.CommandException; -import net.minecraft.command.CommandNotFoundException; -import net.minecraft.command.ICommand; -import net.minecraft.command.ICommandSender; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.ultramine.commands.completion.CommandCompletionHandler; -import org.ultramine.server.PermissionHandler; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class MethodBasedCommand implements IExtendedCommand -{ - private static final Logger logger = LogManager.getLogger(); - - private String name; - private String usage; - private String group; - private String description; - - private Method method; - private CommandCompletionHandler completionHandler; - - private List aliases = new ArrayList(); - private String[] permissions; - private boolean isUsableFromServer = true; - - public MethodBasedCommand(String name, String group, Method method) - { - this.name = name; - this.group = group; - this.method = method; - this.usage = "command." + name + ".usage"; - this.description = "command." + name + ".description"; - } - - public MethodBasedCommand withAliases(String... aliases) - { - this.aliases = Arrays.asList(aliases); - return this; - } - - public MethodBasedCommand withCompletionHandler(CommandCompletionHandler completionHandler) - { - this.completionHandler = completionHandler; - return this; - } - - public MethodBasedCommand withPermissions(String[] permissions) - { - this.permissions = permissions; - return this; - } - - public MethodBasedCommand withUsableFromServer(boolean isUsableFromServer) - { - this.isUsableFromServer = isUsableFromServer; - return this; - } - - @Override - public String getCommandName() - { - return name; - } - - @Override - public String getCommandUsage(ICommandSender var1) - { - return usage; - } - - @Override - public String getDescription() - { - return description; - } - - @Override - public String getGroup() - { - return group; - } - - @Override - public List getCommandAliases() - { - return aliases; - } - - @Override - public void processCommand(ICommandSender var1, String[] var2) - { - try - { - method.invoke(null, new CommandContext(var1, var2)); - } - catch (IllegalAccessException e) - { - logger.error("Error while invoking method for command " + name, e); - throw new CommandNotFoundException(); - } - catch (InvocationTargetException e) - { - if (e.getCause() == null) - { - logger.error("Error while invoking method for command " + name, e); - throw new CommandNotFoundException(); - } - else if (e.getCause() instanceof CommandException) - throw (CommandException) e.getCause(); - else - throw new RuntimeException("Error while invoking method for command " + name, e.getCause()); - } - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender var1) - { - return (isUsableFromServer && var1.getCommandSenderName().equals("Server")) || PermissionHandler.getInstance().hasAny(var1, permissions); - } - - @Override - public List addTabCompletionOptions(ICommandSender var1, String[] var2) - { - if (completionHandler == null) - return null; - - return completionHandler.getCompletionOptions(var2); - } - - @Override - public boolean isUsernameIndex(String[] var1, int var2) - { - return completionHandler != null && completionHandler.isUsernameIndex(var2); - } - - @Override - public int compareTo(Object o) - { - return getCommandName().compareTo(((ICommand)o).getCommandName()); - } -} diff --git a/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java b/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java new file mode 100644 index 0000000..ff76804 --- /dev/null +++ b/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java @@ -0,0 +1,47 @@ +package org.ultramine.commands; + +import net.minecraft.command.CommandException; +import net.minecraft.command.CommandNotFoundException; +import net.minecraft.command.ICommandSender; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class MethodBasedCommandHandler implements ICommandHandler +{ + private static final Logger logger = LogManager.getLogger(); + private Method method; + + public MethodBasedCommandHandler(Method method) + { + this.method = method; + } + + @Override + public void processCommand(ICommandSender var1, String[] var2) + { + try + { + method.invoke(null, new CommandContext(var1, var2)); + } + catch (IllegalAccessException e) + { + logger.error("Error while executing command from method", e); + throw new CommandNotFoundException(); + } + catch (InvocationTargetException e) + { + if (e.getCause() == null) + { + logger.error("Error while executing command from method", e); + throw new CommandNotFoundException(); + } + else if (e.getCause() instanceof CommandException) + throw (CommandException) e.getCause(); + else + throw new RuntimeException("Error while executing command from method", e.getCause()); + } + } +} diff --git a/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java b/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java index f121bab..0042803 100644 --- a/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java +++ b/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java @@ -64,7 +64,15 @@ @Override public int compareTo(Object o) { - return wrappedCommand.compareTo(o); + if (o instanceof IExtendedCommand) + { + int result = getGroup().compareTo(((IExtendedCommand) o).getGroup()); + if (result == 0) + result = getCommandName().compareTo(((IExtendedCommand) o).getCommandName()); + + return result; + } + return -1; } @Override diff --git a/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java b/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java index 355fcdb..7bc1573 100644 --- a/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java +++ b/src/main/java/org/ultramine/commands/completion/CompletionStringParser.java @@ -4,6 +4,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -50,7 +51,7 @@ { for (Method handler : cls.getMethods()) { - if (handler.isAnnotationPresent(ArgumentCompleter.class)) + if (handler.isAnnotationPresent(ArgumentCompleter.class) && Modifier.isStatic(handler.getModifiers())) { ArgumentCompleter data = handler.getAnnotation(ArgumentCompleter.class); registerHandler(data.value(), new WrappedHandler(handler, data.isUsername())); diff --git a/src/main/java/org/ultramine/commands/completion/RegisterCompletersEvent.java b/src/main/java/org/ultramine/commands/completion/RegisterCompletersEvent.java new file mode 100644 index 0000000..ff10119 --- /dev/null +++ b/src/main/java/org/ultramine/commands/completion/RegisterCompletersEvent.java @@ -0,0 +1,19 @@ +package org.ultramine.commands.completion; + +import cpw.mods.fml.common.eventhandler.Event; +import org.ultramine.commands.completion.CompletionStringParser; + +public class RegisterCompletersEvent extends Event +{ + private final CompletionStringParser completionStringParser; + + public RegisterCompletersEvent(CompletionStringParser completionStringParser) + { + this.completionStringParser = completionStringParser; + } + + public CompletionStringParser getCompletionStringParser() + { + return completionStringParser; + } +} diff --git a/src/main/java/org/ultramine/server/UltramineServerModContainer.java b/src/main/java/org/ultramine/server/UltramineServerModContainer.java index e82c8c2..fccf776 100644 --- a/src/main/java/org/ultramine/server/UltramineServerModContainer.java +++ b/src/main/java/org/ultramine/server/UltramineServerModContainer.java @@ -19,6 +19,8 @@ import cpw.mods.fml.common.network.NetworkCheckHandler; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.relauncher.Side; +import org.ultramine.commands.completion.DefaultCompleters; +import org.ultramine.commands.completion.RegisterCompletersEvent; public class UltramineServerModContainer extends DummyModContainer { @@ -78,6 +80,12 @@ } @Subscribe + public void registerCommandCompleters(RegisterCompletersEvent event) + { + event.getCompletionStringParser().registerHandlers(DefaultCompleters.class); + } + + @Subscribe public void serverStarting(FMLServerStartingEvent e) { switch (e.getSide())