001 package org.bukkit.command;
002
003 import java.util.ArrayList;
004 import java.util.logging.Level;
005
006 import org.bukkit.Bukkit;
007 import org.bukkit.entity.Player;
008 import org.bukkit.event.player.PlayerCommandPreprocessEvent;
009 import org.bukkit.event.server.RemoteServerCommandEvent;
010 import org.bukkit.event.server.ServerCommandEvent;
011
012 public class FormattedCommandAlias extends Command {
013 private final String[] formatStrings;
014
015 public FormattedCommandAlias(String alias, String[] formatStrings) {
016 super(alias);
017 this.formatStrings = formatStrings;
018 }
019
020 @Override
021 public boolean execute(CommandSender sender, String commandLabel, String[] args) {
022 boolean result = false;
023 ArrayList<String> commands = new ArrayList<String>();
024 for (String formatString : formatStrings) {
025 try {
026 commands.add(buildCommand(formatString, args));
027 } catch (Throwable throwable) {
028 if (throwable instanceof IllegalArgumentException) {
029 sender.sendMessage(throwable.getMessage());
030 } else {
031 sender.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command");
032 }
033 return false;
034 }
035 }
036
037 for (String command : commands) {
038 result |= Bukkit.dispatchCommand(sender, command);
039 }
040
041 return result;
042 }
043
044 private String buildCommand(String formatString, String[] args) {
045 int index = formatString.indexOf("$");
046 while (index != -1) {
047 int start = index;
048
049 if (index > 0 && formatString.charAt(start - 1) == '\\') {
050 formatString = formatString.substring(0, start - 1) + formatString.substring(start);
051 index = formatString.indexOf("$", index);
052 continue;
053 }
054
055 boolean required = false;
056 if (formatString.charAt(index + 1) == '$') {
057 required = true;
058 // Move index past the second $
059 index++;
060 }
061
062 // Move index past the $
063 index++;
064 int argStart = index;
065 while (index < formatString.length() && inRange(((int) formatString.charAt(index)) - 48, 0, 9)) {
066 // Move index past current digit
067 index++;
068 }
069
070 // No numbers found
071 if (argStart == index) {
072 throw new IllegalArgumentException("Invalid replacement token");
073 }
074
075 int position = Integer.valueOf(formatString.substring(argStart, index));
076
077 // Arguments are not 0 indexed
078 if (position == 0) {
079 throw new IllegalArgumentException("Invalid replacement token");
080 }
081
082 // Convert position to 0 index
083 position--;
084
085 boolean rest = false;
086 if (index < formatString.length() && formatString.charAt(index) == '-') {
087 rest = true;
088 // Move index past the -
089 index++;
090 }
091
092 int end = index;
093
094 if (required && position >= args.length) {
095 throw new IllegalArgumentException("Missing required argument " + (position + 1));
096 }
097
098 StringBuilder replacement = new StringBuilder();
099 if (rest && position < args.length) {
100 for (int i = position; i < args.length; i++) {
101 if (i != position) {
102 replacement.append(' ');
103 }
104 replacement.append(args[i]);
105 }
106 } else if (position < args.length) {
107 replacement.append(args[position]);
108 }
109
110 formatString = formatString.substring(0, start) + replacement.toString() + formatString.substring(end);
111 // Move index past the replaced data so we don't process it again
112 index = start + replacement.length();
113
114 // Move to the next replacement token
115 index = formatString.indexOf("$", index);
116 }
117
118 return formatString;
119 }
120
121 private static boolean inRange(int i, int j, int k) {
122 return i >= j && i <= k;
123 }
124 }