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 }