Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
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}