diff --git a/src/main/java/net/minecraft/command/CommandHandler.java b/src/main/java/net/minecraft/command/CommandHandler.java index 75bbf63..1938f58 100644 --- a/src/main/java/net/minecraft/command/CommandHandler.java +++ b/src/main/java/net/minecraft/command/CommandHandler.java @@ -2,6 +2,8 @@ import java.util.List; import java.util.Map; +import java.util.Set; + import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; @@ -16,6 +18,8 @@ { private static final Logger logger = LogManager.getLogger(); private final CommandRegistry registry = new CommandRegistry(); + private final Map commandMap = registry.getCommandMap(); + private final Set commandSet = registry.getCommandSet(); private static final String __OBFID = "CL_00001765"; public int executeCommand(ICommandSender par1ICommandSender, String par2Str) diff --git a/src/main/java/org/ultramine/commands/CommandRegistry.java b/src/main/java/org/ultramine/commands/CommandRegistry.java index 22848b6..27b86e1 100644 --- a/src/main/java/org/ultramine/commands/CommandRegistry.java +++ b/src/main/java/org/ultramine/commands/CommandRegistry.java @@ -1,10 +1,14 @@ package org.ultramine.commands; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; import org.ultramine.commands.syntax.ArgumentsPatternParser; +import org.ultramine.server.util.MapWrapper; +import org.ultramine.server.util.SetWrapper; import org.ultramine.server.util.TranslitTable; import cpw.mods.fml.common.Loader; @@ -12,51 +16,200 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; public class CommandRegistry { - private final Map commandMap; - private final SortedSet registeredCommands; - private final ArgumentsPatternParser argumentsPatternParser; + private final Map nameInfos = new HashMap<>(); + private final SortedSet registeredCommands = new TreeSet<>(); + private final ArgumentsPatternParser argumentsPatternParser = new ArgumentsPatternParser(); + // vanilla compatibility + @SuppressWarnings("unchecked") + private final Map commandMap = (Map) new MapWrapper(Maps.transformValues(nameInfos, NameInfo::getCurrent)) + { + @Override + public IExtendedCommand put(String key, Object value) + { + if(value instanceof IExtendedCommand) + return addName(key, (IExtendedCommand) value); + else + registerVanillaCommand((ICommand) value); + return null; + } + + @Override + public void putAll(Map m) + { + for(Map.Entry ent : m.entrySet()) + put(ent.getKey(), ent.getValue()); + } + + @Override + public IExtendedCommand remove(Object key) + { + return key == null || key.getClass() != String.class ? null : remove((String) key); + } + + private IExtendedCommand remove(String key) + { + return null; // TODO remove ? + } + }; + @SuppressWarnings("unchecked") + private final Set commandSet = new SetWrapper((Set) registeredCommands) + { + @Override + public boolean add(Object o) + { + return false; + } + + @Override + public boolean remove(Object o) + { + return false; + } + + @Override + public boolean addAll(Collection c) + { + return false; + } + + @Override + public boolean retainAll(Collection c) + { + return false; + } + + @Override + public boolean removeAll(Collection c) + { + return false; + } + }; public CommandRegistry() { - commandMap = new HashMap(); - registeredCommands = new TreeSet(); - argumentsPatternParser = new ArgumentsPatternParser(); } - public IExtendedCommand registerCommand(IExtendedCommand command) + public static class NameInfo { - @SuppressWarnings("unchecked") - List aliases = command.getCommandAliases(); - commandMap.put(command.getCommandName(), command); - commandMap.put(TranslitTable.translitENRU(command.getCommandName()), command); - registeredCommands.add(command); + private final List available = new ArrayList<>(); + private final String name; + private IExtendedCommand current; - if (aliases != null) + private NameInfo(String name) { - for (String alias : aliases) - { - commandMap.put(alias, command); - commandMap.put(TranslitTable.translitENRU(alias), command); - } + this.name = name; } - return command; + public String getName() + { + return name; + } + + IExtendedCommand add(IExtendedCommand command) + { + available.remove(command); + available.add(command); + IExtendedCommand old = current; + current = command; + return old; + } + + void remove(IExtendedCommand command) + { + available.remove(command); + if(current == command) + current = available.get(available.size() - 1); + } + + boolean switchTo(IExtendedCommand command) + { + if(current != command && available.remove(command)) + { + available.add(command); + current = command; + return true; + } + + return false; + } + + public IExtendedCommand getCurrent() + { + return current; + } + } + + @SuppressWarnings("unchecked") + private Iterable getDefaultNames(IExtendedCommand command) + { + List aliases = command.getCommandAliases(); + if(aliases == null) + aliases = Collections.emptyList(); + return Iterables.concat( + Collections.singletonList(command.getCommandName()), + aliases + ); + } + + private Iterable getAllNames(IExtendedCommand command) + { + Iterable names = getDefaultNames(command); + return Iterables.concat( + names, + Iterables.transform(names, TranslitTable::translitENRU) + ); + } + + private IExtendedCommand addName(String name, IExtendedCommand command) + { + return nameInfos.computeIfAbsent(name, NameInfo::new).add(command); + } + + private void removeName(String name, IExtendedCommand command) + { + nameInfos.computeIfAbsent(name, NameInfo::new).remove(command); + } + + public void registerCommand(IExtendedCommand command) + { + registeredCommands.add(command); + + addName(command.getGroup() + ":" + command.getCommandName(), command); + for(String name : getAllNames(command)) + addName(name, command); + } + + public void unregisterCommand(IExtendedCommand command) + { + if(registeredCommands.remove(command)) + for(String name : getAllNames(command)) + removeName(name, command); } public IExtendedCommand registerVanillaCommand(ICommand command) { ModContainer active = Loader.instance().activeModContainer(); - return registerCommand(new VanillaCommandWrapper(command, active != null ? active.getModId().toLowerCase() : "vanilla")); + IExtendedCommand exCommand = new VanillaCommandWrapper(command, active != null ? active.getModId().toLowerCase() : "vanilla"); + registerCommand(exCommand); + return exCommand; } public void registerCommands(Class cls) { - List builders = new ArrayList(); - Map> actions = new HashMap>(); + List builders = new ArrayList<>(); + Map> actions = new HashMap<>(); for (Method method : cls.getMethods()) { @@ -79,7 +232,7 @@ Action data = method.getAnnotation(Action.class); if (!actions.containsKey(data.command())) - actions.put(data.command(), new HashMap()); + actions.put(data.command(), new HashMap<>()); actions.get(data.command()).put(data.name(), new MethodBasedCommandHandler(method)); } @@ -107,6 +260,11 @@ return commandMap; } + public Set getCommandSet() + { + return commandSet; + } + public List filterPossibleCommandsNames(ICommandSender sender, String filter) { List result = new ArrayList(); diff --git a/src/main/java/org/ultramine/server/util/MapWrapper.java b/src/main/java/org/ultramine/server/util/MapWrapper.java new file mode 100644 index 0000000..dcf9ad6 --- /dev/null +++ b/src/main/java/org/ultramine/server/util/MapWrapper.java @@ -0,0 +1,168 @@ +package org.ultramine.server.util; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class MapWrapper implements Map +{ + private final Map wrapped; + + public MapWrapper(Map wrapped) + { + this.wrapped = wrapped; + } + + @Override + public int size() + { + return wrapped.size(); + } + + @Override + public boolean isEmpty() + { + return wrapped.isEmpty(); + } + + @Override + public boolean containsKey(Object key) + { + return wrapped.containsKey(key); + } + + @Override + public boolean containsValue(Object value) + { + return wrapped.containsValue(value); + } + + @Override + public V get(Object key) + { + return wrapped.get(key); + } + + @Override + public V put(K key, V value) + { + return wrapped.put(key, value); + } + + @Override + public V remove(Object key) + { + return wrapped.remove(key); + } + + @Override + public void putAll(Map m) + { + wrapped.putAll(m); + } + + @Override + public void clear() + { + wrapped.clear(); + } + + @Override + public Set keySet() + { + return wrapped.keySet(); + } + + @Override + public Collection values() + { + return wrapped.values(); + } + + @Override + public Set> entrySet() + { + return wrapped.entrySet(); + } + + @Override + public boolean equals(Object o) + { + return wrapped.equals(o); + } + + @Override + public int hashCode() + { + return wrapped.hashCode(); + } + + @Override + public V getOrDefault(Object key, V defaultValue) + { + return wrapped.getOrDefault(key, defaultValue); + } + + @Override + public void forEach(BiConsumer action) + { + wrapped.forEach(action); + } + + @Override + public void replaceAll(BiFunction function) + { + wrapped.replaceAll(function); + } + + @Override + public V putIfAbsent(K key, V value) + { + return wrapped.putIfAbsent(key, value); + } + + @Override + public boolean remove(Object key, Object value) + { + return wrapped.remove(key, value); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) + { + return wrapped.replace(key, oldValue, newValue); + } + + @Override + public V replace(K key, V value) + { + return wrapped.replace(key, value); + } + + @Override + public V computeIfAbsent(K key, Function mappingFunction) + { + return wrapped.computeIfAbsent(key, mappingFunction); + } + + @Override + public V computeIfPresent(K key, BiFunction remappingFunction) + { + return wrapped.computeIfPresent(key, remappingFunction); + } + + @Override + public V compute(K key, BiFunction remappingFunction) + { + return wrapped.compute(key, remappingFunction); + } + + @Override + public V merge(K key, V value, BiFunction remappingFunction) + { + return wrapped.merge(key, value, remappingFunction); + } +} diff --git a/src/main/java/org/ultramine/server/util/SetWrapper.java b/src/main/java/org/ultramine/server/util/SetWrapper.java new file mode 100644 index 0000000..17f6a38 --- /dev/null +++ b/src/main/java/org/ultramine/server/util/SetWrapper.java @@ -0,0 +1,139 @@ +package org.ultramine.server.util; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public class SetWrapper implements Set +{ + private final Set wrapped; + + public SetWrapper(Set wrapped) + { + this.wrapped = wrapped; + } + + @Override + public int size() + { + return wrapped.size(); + } + + @Override + public boolean isEmpty() + { + return wrapped.isEmpty(); + } + + @Override + public boolean contains(Object o) + { + return wrapped.contains(o); + } + + @Override + public Iterator iterator() + { + return wrapped.iterator(); + } + + @Override + public Object[] toArray() + { + return wrapped.toArray(); + } + + @Override + public T1[] toArray(T1[] a) + { + return wrapped.toArray(a); + } + + @Override + public boolean add(T t) + { + return wrapped.add(t); + } + + @Override + public boolean remove(Object o) + { + return wrapped.remove(o); + } + + @Override + public boolean containsAll(Collection c) + { + return wrapped.containsAll(c); + } + + @Override + public boolean addAll(Collection c) + { + return wrapped.addAll(c); + } + + @Override + public boolean retainAll(Collection c) + { + return wrapped.retainAll(c); + } + + @Override + public boolean removeAll(Collection c) + { + return wrapped.removeAll(c); + } + + @Override + public void clear() + { + wrapped.clear(); + } + + @Override + public boolean equals(Object o) + { + return wrapped.equals(o); + } + + @Override + public int hashCode() + { + return wrapped.hashCode(); + } + + @Override + public Spliterator spliterator() + { + return wrapped.spliterator(); + } + + @Override + public boolean removeIf(Predicate filter) + { + return wrapped.removeIf(filter); + } + + @Override + public Stream stream() + { + return wrapped.stream(); + } + + @Override + public Stream parallelStream() + { + return wrapped.parallelStream(); + } + + @Override + public void forEach(Consumer action) + { + wrapped.forEach(action); + } +}