001package net.minecraft.command; 002 003import java.util.Collections; 004import java.util.HashMap; 005import java.util.Iterator; 006import java.util.List; 007import java.util.Map; 008import java.util.regex.Matcher; 009import java.util.regex.Pattern; 010import net.minecraft.entity.player.EntityPlayerMP; 011import net.minecraft.server.MinecraftServer; 012import net.minecraft.util.ChunkCoordinates; 013import net.minecraft.util.MathHelper; 014import net.minecraft.world.EnumGameType; 015 016public class PlayerSelector 017{ 018 /** 019 * This matches the at-tokens introduced for command blocks, including their arguments, if any. 020 */ 021 private static final Pattern tokenPattern = Pattern.compile("^@([parf])(?:\\[([\\w=,!-]*)\\])?$"); 022 023 /** 024 * This matches things like "-1,,4", and is used for getting x,y,z,range from the token's argument list. 025 */ 026 private static final Pattern intListPattern = Pattern.compile("\\G([-!]?\\w*)(?:$|,)"); 027 028 /** 029 * This matches things like "rm=4,c=2" and is used for handling named token arguments. 030 */ 031 private static final Pattern keyValueListPattern = Pattern.compile("\\G(\\w+)=([-!]?\\w*)(?:$|,)"); 032 033 /** 034 * Returns the one player that matches the given at-token. Returns null if more than one player matches. 035 */ 036 public static EntityPlayerMP matchOnePlayer(ICommandSender par0ICommandSender, String par1Str) 037 { 038 EntityPlayerMP[] aentityplayermp = matchPlayers(par0ICommandSender, par1Str); 039 return aentityplayermp != null && aentityplayermp.length == 1 ? aentityplayermp[0] : null; 040 } 041 042 /** 043 * Returns a nicely-formatted string listing the matching players. 044 */ 045 public static String matchPlayersAsString(ICommandSender par0ICommandSender, String par1Str) 046 { 047 EntityPlayerMP[] aentityplayermp = matchPlayers(par0ICommandSender, par1Str); 048 049 if (aentityplayermp != null && aentityplayermp.length != 0) 050 { 051 String[] astring = new String[aentityplayermp.length]; 052 053 for (int i = 0; i < astring.length; ++i) 054 { 055 astring[i] = aentityplayermp[i].func_96090_ax(); 056 } 057 058 return CommandBase.joinNiceString(astring); 059 } 060 else 061 { 062 return null; 063 } 064 } 065 066 /** 067 * Returns an array of all players matched by the given at-token. 068 */ 069 public static EntityPlayerMP[] matchPlayers(ICommandSender par0ICommandSender, String par1Str) 070 { 071 Matcher matcher = tokenPattern.matcher(par1Str); 072 073 if (matcher.matches()) 074 { 075 Map map = getArgumentMap(matcher.group(2)); 076 String s1 = matcher.group(1); 077 int i = getDefaultMinimumRange(s1); 078 int j = getDefaultMaximumRange(s1); 079 int k = getDefaultMinimumLevel(s1); 080 int l = getDefaultMaximumLevel(s1); 081 int i1 = getDefaultCount(s1); 082 int j1 = EnumGameType.NOT_SET.getID(); 083 ChunkCoordinates chunkcoordinates = par0ICommandSender.getPlayerCoordinates(); 084 Map map1 = func_96560_a(map); 085 String s2 = null; 086 String s3 = null; 087 088 if (map.containsKey("rm")) 089 { 090 i = MathHelper.parseIntWithDefault((String)map.get("rm"), i); 091 } 092 093 if (map.containsKey("r")) 094 { 095 j = MathHelper.parseIntWithDefault((String)map.get("r"), j); 096 } 097 098 if (map.containsKey("lm")) 099 { 100 k = MathHelper.parseIntWithDefault((String)map.get("lm"), k); 101 } 102 103 if (map.containsKey("l")) 104 { 105 l = MathHelper.parseIntWithDefault((String)map.get("l"), l); 106 } 107 108 if (map.containsKey("x")) 109 { 110 chunkcoordinates.posX = MathHelper.parseIntWithDefault((String)map.get("x"), chunkcoordinates.posX); 111 } 112 113 if (map.containsKey("y")) 114 { 115 chunkcoordinates.posY = MathHelper.parseIntWithDefault((String)map.get("y"), chunkcoordinates.posY); 116 } 117 118 if (map.containsKey("z")) 119 { 120 chunkcoordinates.posZ = MathHelper.parseIntWithDefault((String)map.get("z"), chunkcoordinates.posZ); 121 } 122 123 if (map.containsKey("m")) 124 { 125 j1 = MathHelper.parseIntWithDefault((String)map.get("m"), j1); 126 } 127 128 if (map.containsKey("c")) 129 { 130 i1 = MathHelper.parseIntWithDefault((String)map.get("c"), i1); 131 } 132 133 if (map.containsKey("team")) 134 { 135 s3 = (String)map.get("team"); 136 } 137 138 if (map.containsKey("name")) 139 { 140 s2 = (String)map.get("name"); 141 } 142 143 List list; 144 145 if (!s1.equals("p") && !s1.equals("a")) 146 { 147 if (!s1.equals("r")) 148 { 149 return null; 150 } 151 else 152 { 153 list = MinecraftServer.getServer().getConfigurationManager().findPlayers(chunkcoordinates, i, j, 0, j1, k, l, map1, s2, s3); 154 Collections.shuffle(list); 155 list = list.subList(0, Math.min(i1, list.size())); 156 return list != null && !list.isEmpty() ? (EntityPlayerMP[])list.toArray(new EntityPlayerMP[0]) : new EntityPlayerMP[0]; 157 } 158 } 159 else 160 { 161 list = MinecraftServer.getServer().getConfigurationManager().findPlayers(chunkcoordinates, i, j, i1, j1, k, l, map1, s2, s3); 162 return list != null && !list.isEmpty() ? (EntityPlayerMP[])list.toArray(new EntityPlayerMP[0]) : new EntityPlayerMP[0]; 163 } 164 } 165 else 166 { 167 return null; 168 } 169 } 170 171 public static Map func_96560_a(Map par0Map) 172 { 173 HashMap hashmap = new HashMap(); 174 Iterator iterator = par0Map.keySet().iterator(); 175 176 while (iterator.hasNext()) 177 { 178 String s = (String)iterator.next(); 179 180 if (s.startsWith("score_") && s.length() > "score_".length()) 181 { 182 String s1 = s.substring("score_".length()); 183 hashmap.put(s1, Integer.valueOf(MathHelper.parseIntWithDefault((String)par0Map.get(s), 1))); 184 } 185 } 186 187 return hashmap; 188 } 189 190 /** 191 * Returns whether the given pattern can match more than one player. 192 */ 193 public static boolean matchesMultiplePlayers(String par0Str) 194 { 195 Matcher matcher = tokenPattern.matcher(par0Str); 196 197 if (matcher.matches()) 198 { 199 Map map = getArgumentMap(matcher.group(2)); 200 String s1 = matcher.group(1); 201 int i = getDefaultCount(s1); 202 203 if (map.containsKey("c")) 204 { 205 i = MathHelper.parseIntWithDefault((String)map.get("c"), i); 206 } 207 208 return i != 1; 209 } 210 else 211 { 212 return false; 213 } 214 } 215 216 /** 217 * Returns whether the given token (parameter 1) has exactly the given arguments (parameter 2). 218 */ 219 public static boolean hasTheseArguments(String par0Str, String par1Str) 220 { 221 Matcher matcher = tokenPattern.matcher(par0Str); 222 223 if (matcher.matches()) 224 { 225 String s2 = matcher.group(1); 226 return par1Str == null || par1Str.equals(s2); 227 } 228 else 229 { 230 return false; 231 } 232 } 233 234 /** 235 * Returns whether the given token has any arguments set. 236 */ 237 public static boolean hasArguments(String par0Str) 238 { 239 return hasTheseArguments(par0Str, (String)null); 240 } 241 242 /** 243 * Gets the default minimum range (argument rm). 244 */ 245 private static final int getDefaultMinimumRange(String par0Str) 246 { 247 return 0; 248 } 249 250 /** 251 * Gets the default maximum range (argument r). 252 */ 253 private static final int getDefaultMaximumRange(String par0Str) 254 { 255 return 0; 256 } 257 258 /** 259 * Gets the default maximum experience level (argument l) 260 */ 261 private static final int getDefaultMaximumLevel(String par0Str) 262 { 263 return Integer.MAX_VALUE; 264 } 265 266 /** 267 * Gets the default minimum experience level (argument lm) 268 */ 269 private static final int getDefaultMinimumLevel(String par0Str) 270 { 271 return 0; 272 } 273 274 /** 275 * Gets the default number of players to return (argument c, 0 for infinite) 276 */ 277 private static final int getDefaultCount(String par0Str) 278 { 279 return par0Str.equals("a") ? 0 : 1; 280 } 281 282 /** 283 * Parses the given argument string, turning it into a HashMap<String, String> of name->value. 284 */ 285 private static Map getArgumentMap(String par0Str) 286 { 287 HashMap hashmap = new HashMap(); 288 289 if (par0Str == null) 290 { 291 return hashmap; 292 } 293 else 294 { 295 Matcher matcher = intListPattern.matcher(par0Str); 296 int i = 0; 297 int j; 298 299 for (j = -1; matcher.find(); j = matcher.end()) 300 { 301 String s1 = null; 302 303 switch (i++) 304 { 305 case 0: 306 s1 = "x"; 307 break; 308 case 1: 309 s1 = "y"; 310 break; 311 case 2: 312 s1 = "z"; 313 break; 314 case 3: 315 s1 = "r"; 316 } 317 318 if (s1 != null && matcher.group(1).length() > 0) 319 { 320 hashmap.put(s1, matcher.group(1)); 321 } 322 } 323 324 if (j < par0Str.length()) 325 { 326 matcher = keyValueListPattern.matcher(j == -1 ? par0Str : par0Str.substring(j)); 327 328 while (matcher.find()) 329 { 330 hashmap.put(matcher.group(1), matcher.group(2)); 331 } 332 } 333 334 return hashmap; 335 } 336 } 337}