Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 228 lines 8.5 kB view raw
1package org.bukkit.command; 2 3import com.legacyminecraft.poseidon.PoseidonConfig; 4import com.legacyminecraft.poseidon.commands.PoseidonCommand; 5import com.legacyminecraft.poseidon.commands.TPSCommand; 6import org.bukkit.Server; 7import org.bukkit.command.defaults.*; 8import uk.betacraft.uberbukkit.command.*; 9 10import java.util.*; 11 12import static org.bukkit.util.Java15Compat.Arrays_copyOfRange; 13 14public class SimpleCommandMap implements CommandMap { 15 protected final Map<String, Command> knownCommands = new HashMap<>(); 16 protected final Set<String> aliases = new HashSet<>(); 17 private final Server server; 18 protected static final Set<VanillaCommand> fallbackCommands = new HashSet<>(); 19 20 static { 21 fallbackCommands.add(new ListCommand()); 22 fallbackCommands.add(new StopCommand()); 23 fallbackCommands.add(new SaveCommand()); 24 fallbackCommands.add(new SaveOnCommand()); 25 fallbackCommands.add(new SaveOffCommand()); 26 fallbackCommands.add(new OpCommand()); 27 fallbackCommands.add(new DeopCommand()); 28 fallbackCommands.add(new BanIpCommand()); 29 fallbackCommands.add(new PardonIpCommand()); 30 fallbackCommands.add(new BanCommand()); 31 fallbackCommands.add(new PardonCommand()); 32 fallbackCommands.add(new KickCommand()); 33 fallbackCommands.add(new TeleportCommand()); 34 fallbackCommands.add(new GiveCommand()); 35 fallbackCommands.add(new TimeCommand()); 36 fallbackCommands.add(new SayCommand()); 37 fallbackCommands.add(new WhitelistCommand()); 38 fallbackCommands.add(new TellCommand()); 39 fallbackCommands.add(new MeCommand()); 40 fallbackCommands.add(new KillCommand()); 41 fallbackCommands.add(new HelpCommand()); 42 } 43 44 public SimpleCommandMap(final Server server) { 45 this.server = server; 46 setDefaultCommands(server); 47 } 48 49 private void setDefaultCommands(final Server server) { 50 register("uberbukkit", new UberBukkitCommand()); 51 register("uberbukkit", new FlushInvCommand()); 52 register("uberbukkit", new UuidLookupCommand()); 53 register("uberbukkit", new CrackedAllowlistCommand()); 54 55 register("bukkit", new VersionCommand("version")); 56 register("bukkit", new ReloadCommand("reload")); 57 register("bukkit", new PluginsCommand("plugins")); 58 59 register("poseidon", new PoseidonCommand("poseidon")); 60 if (PoseidonConfig.getInstance().getConfigBoolean("command.tps.enabled")) 61 register("poseidon", new TPSCommand("tps")); 62 } 63 64 /** 65 * {@inheritDoc} 66 */ 67 public void registerAll(String fallbackPrefix, List<Command> commands) { 68 if (commands != null) { 69 for (Command c : commands) { 70 register(fallbackPrefix, c); 71 } 72 } 73 } 74 75 /** 76 * {@inheritDoc} 77 */ 78 public boolean register(String fallbackPrefix, Command command) { 79 return register(command.getName(), fallbackPrefix, command); 80 } 81 82 /** 83 * {@inheritDoc} 84 */ 85 public boolean register(String label, String fallbackPrefix, Command command) { 86 boolean registeredPassedLabel = register(label, fallbackPrefix, command, false); 87 88 Iterator iterator = command.getAliases().iterator(); 89 while (iterator.hasNext()) { 90 if (!register((String) iterator.next(), fallbackPrefix, command, true)) { 91 iterator.remove(); 92 } 93 } 94 95 // Register to us so further updates of the commands label and aliases are postponed until its reregistered 96 command.register(this); 97 98 return registeredPassedLabel; 99 } 100 101 /** 102 * Registers a command with the given name is possible, otherwise uses fallbackPrefix to create a unique name if its not an alias 103 * 104 * @param name the name of the command, without the '/'-prefix. 105 * @param fallbackPrefix a prefix which is prepended to the command with a ':' one or more times to make the command unique 106 * @param command the command to register 107 * @return true if command was registered with the passed in label, false otherwise. 108 * If isAlias was true a return of false indicates no command was registerd 109 * If isAlias was false a return of false indicates the fallbackPrefix was used one or more times to create a unique name for the command 110 */ 111 private synchronized boolean register(String label, String fallbackPrefix, Command command, boolean isAlias) { 112 String lowerLabel = label.trim().toLowerCase(); 113 114 if (isAlias && knownCommands.containsKey(lowerLabel)) { 115 // Request is for an alias and it conflicts with a existing command or previous alias ignore it 116 // Note: This will mean it gets removed from the commands list of active aliases 117 return false; 118 } 119 120 String lowerPrefix = fallbackPrefix.trim().toLowerCase(); 121 boolean registerdPassedLabel = true; 122 123 // If the command exists but is an alias we overwrite it, otherwise we rename it based on the fallbackPrefix 124 while (knownCommands.containsKey(lowerLabel) && !aliases.contains(lowerLabel)) { 125 lowerLabel = lowerPrefix + ":" + lowerLabel; 126 registerdPassedLabel = false; 127 } 128 129 if (isAlias) { 130 aliases.add(lowerLabel); 131 } else { 132 // Ensure lowerLabel isn't listed as a alias anymore and update the commands registered name 133 aliases.remove(lowerLabel); 134 command.setLabel(lowerLabel); 135 } 136 knownCommands.put(lowerLabel, command); 137 138 return registerdPassedLabel; 139 } 140 141 protected Command getFallback(String label) { 142 for (VanillaCommand cmd : fallbackCommands) { 143 if (cmd.matches(label)) { 144 return cmd; 145 } 146 } 147 148 return null; 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 public boolean dispatch(CommandSender sender, String commandLine) throws CommandException { 155 String[] args = commandLine.split(" "); 156 157 if (args.length == 0) { 158 return false; 159 } 160 161 String sentCommandLabel = args[0].toLowerCase(); 162 Command target = getCommand(sentCommandLabel); 163 if (target == null) { 164 target = getFallback(commandLine.toLowerCase()); 165 } 166 if (target == null) { 167 return false; 168 } 169 170 try { 171 // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) 172 target.execute(sender, sentCommandLabel, Arrays_copyOfRange(args, 1, args.length)); 173 } catch (CommandException ex) { 174 throw ex; 175 } catch (Throwable ex) { 176 throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); 177 } 178 179 // return true as command was handled 180 return true; 181 } 182 183 public synchronized void clearCommands() { 184 for (Map.Entry<String, Command> entry : knownCommands.entrySet()) { 185 entry.getValue().unregister(this); 186 } 187 knownCommands.clear(); 188 aliases.clear(); 189 setDefaultCommands(server); 190 } 191 192 public Command getCommand(String name) { 193 return knownCommands.get(name.toLowerCase()); 194 } 195 196 public void registerServerAliases() { 197 Map<String, String[]> values = server.getCommandAliases(); 198 199 for (String alias : values.keySet()) { 200 String[] targetNames = values.get(alias); 201 List<Command> targets = new ArrayList<Command>(); 202 String bad = ""; 203 204 for (String name : targetNames) { 205 Command command = getCommand(name); 206 207 if (command == null) { 208 bad += name + ", "; 209 } else { 210 targets.add(command); 211 } 212 } 213 214 // We register these as commands so they have absolute priority. 215 216 if (targets.size() > 0) { 217 knownCommands.put(alias.toLowerCase(), new MultipleCommandAlias(alias.toLowerCase(), targets.toArray(new Command[0]))); 218 } else { 219 knownCommands.remove(alias.toLowerCase()); 220 } 221 222 if (bad.length() > 0) { 223 bad = bad.substring(0, bad.length() - 2); 224 server.getLogger().warning("The following command(s) could not be aliased under '" + alias + "' because they do not exist: " + bad); 225 } 226 } 227 } 228}