Bukkit-API  1.7.9-R0.2
The inofficial Bukkit-API
SimpleCommandMap.java
1 package org.bukkit.command;
2 
3 import static org.bukkit.util.Java15Compat.Arrays_copyOfRange;
4 
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.regex.Pattern;
13 
14 import org.apache.commons.lang.Validate;
15 import org.bukkit.Server;
16 import org.bukkit.command.defaults.*;
17 import org.bukkit.entity.Player;
18 import org.bukkit.util.StringUtil;
19 
20 public class SimpleCommandMap implements CommandMap {
21  private static final Pattern PATTERN_ON_SPACE = Pattern.compile(" ", Pattern.LITERAL);
22  protected final Map<String, Command> knownCommands = new HashMap<String, Command>();
23  private final Server server;
24 
25  public SimpleCommandMap(final Server server) {
26  this.server = server;
27  setDefaultCommands();
28  }
29 
30  private void setDefaultCommands() {
31  register("bukkit", new SaveCommand());
32  register("bukkit", new SaveOnCommand());
33  register("bukkit", new SaveOffCommand());
34  register("bukkit", new StopCommand());
35  register("bukkit", new VersionCommand("version"));
36  register("bukkit", new ReloadCommand("reload"));
37  register("bukkit", new PluginsCommand("plugins"));
38  register("bukkit", new TimingsCommand("timings"));
39  }
40 
41  public void setFallbackCommands() {
42  register("bukkit", new ListCommand());
43  register("bukkit", new OpCommand());
44  register("bukkit", new DeopCommand());
45  register("bukkit", new BanIpCommand());
46  register("bukkit", new PardonIpCommand());
47  register("bukkit", new BanCommand());
48  register("bukkit", new PardonCommand());
49  register("bukkit", new KickCommand());
50  register("bukkit", new TeleportCommand());
51  register("bukkit", new GiveCommand());
52  register("bukkit", new TimeCommand());
53  register("bukkit", new SayCommand());
54  register("bukkit", new WhitelistCommand());
55  register("bukkit", new TellCommand());
56  register("bukkit", new MeCommand());
57  register("bukkit", new KillCommand());
58  register("bukkit", new GameModeCommand());
59  register("bukkit", new HelpCommand());
60  register("bukkit", new ExpCommand());
61  register("bukkit", new ToggleDownfallCommand());
62  register("bukkit", new BanListCommand());
63  register("bukkit", new DefaultGameModeCommand());
64  register("bukkit", new SeedCommand());
65  register("bukkit", new DifficultyCommand());
66  register("bukkit", new WeatherCommand());
67  register("bukkit", new SpawnpointCommand());
68  register("bukkit", new ClearCommand());
69  register("bukkit", new GameRuleCommand());
70  register("bukkit", new EnchantCommand());
71  register("bukkit", new TestForCommand());
72  register("bukkit", new EffectCommand());
73  register("bukkit", new ScoreboardCommand());
74  register("bukkit", new PlaySoundCommand());
75  register("bukkit", new SpreadPlayersCommand());
76  register("bukkit", new SetWorldSpawnCommand());
77  register("bukkit", new SetIdleTimeoutCommand());
78  register("bukkit", new AchievementCommand());
79  }
80 
81  /**
82  * {@inheritDoc}
83  */
84  public void registerAll(String fallbackPrefix, List<Command> commands) {
85  if (commands != null) {
86  for (Command c : commands) {
87  register(fallbackPrefix, c);
88  }
89  }
90  }
91 
92  /**
93  * {@inheritDoc}
94  */
95  public boolean register(String fallbackPrefix, Command command) {
96  return register(command.getName(), fallbackPrefix, command);
97  }
98 
99  /**
100  * {@inheritDoc}
101  */
102  public boolean register(String label, String fallbackPrefix, Command command) {
103  label = label.toLowerCase().trim();
104  fallbackPrefix = fallbackPrefix.toLowerCase().trim();
105  boolean registered = register(label, command, false, fallbackPrefix);
106 
107  Iterator<String> iterator = command.getAliases().iterator();
108  while (iterator.hasNext()) {
109  if (!register(iterator.next(), command, true, fallbackPrefix)) {
110  iterator.remove();
111  }
112  }
113 
114  // If we failed to register under the real name, we need to set the command label to the direct address
115  if (!registered) {
116  command.setLabel(fallbackPrefix + ":" + label);
117  }
118 
119  // Register to us so further updates of the commands label and aliases are postponed until its reregistered
120  command.register(this);
121 
122  return registered;
123  }
124 
125  /**
126  * Registers a command with the given name is possible. Also uses
127  * fallbackPrefix to create a unique name.
128  *
129  * @param label the name of the command, without the '/'-prefix.
130  * @param command the command to register
131  * @param isAlias whether the command is an alias
132  * @param fallbackPrefix a prefix which is prepended to the command for a
133  * unique address
134  * @return true if command was registered, false otherwise.
135  */
136  private synchronized boolean register(String label, Command command, boolean isAlias, String fallbackPrefix) {
137  knownCommands.put(fallbackPrefix + ":" + label, command);
138  if ((command instanceof VanillaCommand || isAlias) && knownCommands.containsKey(label)) {
139  // Request is for an alias/fallback command and it conflicts with
140  // a existing command or previous alias ignore it
141  // Note: This will mean it gets removed from the commands list of active aliases
142  return false;
143  }
144 
145  boolean registered = true;
146 
147  // If the command exists but is an alias we overwrite it, otherwise we return
148  Command conflict = knownCommands.get(label);
149  if (conflict != null && conflict.getLabel().equals(label)) {
150  return false;
151  }
152 
153  if (!isAlias) {
154  command.setLabel(label);
155  }
156  knownCommands.put(label, command);
157 
158  return registered;
159  }
160 
161  /**
162  * {@inheritDoc}
163  */
164  public boolean dispatch(CommandSender sender, String commandLine) throws CommandException {
165  String[] args = PATTERN_ON_SPACE.split(commandLine);
166 
167  if (args.length == 0) {
168  return false;
169  }
170 
171  String sentCommandLabel = args[0].toLowerCase();
172  Command target = getCommand(sentCommandLabel);
173 
174  if (target == null) {
175  return false;
176  }
177 
178  try {
179  // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false)
180  target.execute(sender, sentCommandLabel, Arrays_copyOfRange(args, 1, args.length));
181  } catch (CommandException ex) {
182  throw ex;
183  } catch (Throwable ex) {
184  throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex);
185  }
186 
187  // return true as command was handled
188  return true;
189  }
190 
191  public synchronized void clearCommands() {
192  for (Map.Entry<String, Command> entry : knownCommands.entrySet()) {
193  entry.getValue().unregister(this);
194  }
195  knownCommands.clear();
196  setDefaultCommands();
197  }
198 
199  public Command getCommand(String name) {
200  Command target = knownCommands.get(name.toLowerCase());
201  return target;
202  }
203 
204  public List<String> tabComplete(CommandSender sender, String cmdLine) {
205  Validate.notNull(sender, "Sender cannot be null");
206  Validate.notNull(cmdLine, "Command line cannot null");
207 
208  int spaceIndex = cmdLine.indexOf(' ');
209 
210  if (spaceIndex == -1) {
211  ArrayList<String> completions = new ArrayList<String>();
212  Map<String, Command> knownCommands = this.knownCommands;
213 
214  final String prefix = (sender instanceof Player ? "/" : "");
215 
216  for (Map.Entry<String, Command> commandEntry : knownCommands.entrySet()) {
217  Command command = commandEntry.getValue();
218 
219  if (!command.testPermissionSilent(sender)) {
220  continue;
221  }
222 
223  String name = commandEntry.getKey(); // Use the alias, not command name
224 
225  if (StringUtil.startsWithIgnoreCase(name, cmdLine)) {
226  completions.add(prefix + name);
227  }
228  }
229 
230  Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
231  return completions;
232  }
233 
234  String commandName = cmdLine.substring(0, spaceIndex);
235  Command target = getCommand(commandName);
236 
237  if (target == null) {
238  return null;
239  }
240 
241  if (!target.testPermissionSilent(sender)) {
242  return null;
243  }
244 
245  String argLine = cmdLine.substring(spaceIndex + 1, cmdLine.length());
246  String[] args = PATTERN_ON_SPACE.split(argLine, -1);
247 
248  try {
249  return target.tabComplete(sender, commandName, args);
250  } catch (CommandException ex) {
251  throw ex;
252  } catch (Throwable ex) {
253  throw new CommandException("Unhandled exception executing tab-completer for '" + cmdLine + "' in " + target, ex);
254  }
255  }
256 
257  public Collection<Command> getCommands() {
258  return Collections.unmodifiableCollection(knownCommands.values());
259  }
260 
261  public void registerServerAliases() {
262  Map<String, String[]> values = server.getCommandAliases();
263 
264  for (String alias : values.keySet()) {
265  if (alias.contains(":") || alias.contains(" ")) {
266  server.getLogger().warning("Could not register alias " + alias + " because it contains illegal characters");
267  continue;
268  }
269 
270  String[] commandStrings = values.get(alias);
271  List<String> targets = new ArrayList<String>();
272  StringBuilder bad = new StringBuilder();
273 
274  for (String commandString : commandStrings) {
275  String[] commandArgs = commandString.split(" ");
276  Command command = getCommand(commandArgs[0]);
277 
278  if (command == null) {
279  if (bad.length() > 0) {
280  bad.append(", ");
281  }
282  bad.append(commandString);
283  } else {
284  targets.add(commandString);
285  }
286  }
287 
288  if (bad.length() > 0) {
289  server.getLogger().warning("Could not register alias " + alias + " because it contains commands that do not exist: " + bad);
290  continue;
291  }
292 
293  // We register these as commands so they have absolute priority.
294  if (targets.size() > 0) {
295  knownCommands.put(alias.toLowerCase(), new FormattedCommandAlias(alias.toLowerCase(), targets.toArray(new String[targets.size()])));
296  } else {
297  knownCommands.remove(alias.toLowerCase());
298  }
299  }
300  }
301 }
abstract boolean execute(CommandSender sender, String commandLabel, String[] args)
boolean dispatch(CommandSender sender, String commandLine)
List< String > tabComplete(CommandSender sender, String[] args)
void registerAll(String fallbackPrefix, List< Command > commands)
boolean testPermissionSilent(CommandSender target)
static boolean startsWithIgnoreCase(final String string, final String prefix)
Definition: StringUtil.java:50
List< String > tabComplete(CommandSender sender, String cmdLine)
Map< String, String[]> getCommandAliases()
Logger getLogger()