    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}