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&lt;String, String&gt; of name-&gt;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}