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