001    import java.util.ArrayList;
002    import java.util.Date;
003    import java.util.List;
004    import java.util.Map;
005    import java.util.Map.Entry;
006    import java.util.logging.Level;
007    import java.util.logging.Logger;
008    import java.util.regex.Matcher;
009    import java.util.regex.Pattern;
010    import net.minecraft.server.MinecraftServer;
011    
012    /**
013     * Player.java - Interface for eo so mods don't have to update often.
014     * 
015     * @author James
016     */
017    public class Player extends HumanEntity implements MessageReceiver {
018        private static final Logger log = Logger.getLogger("Minecraft");
019        private int id = -1;
020        private String prefix = "";
021        private String[] commands = new String[]{""};
022        private ArrayList<String> groups = new ArrayList<String>();
023        private String[] ips = new String[]{""};
024        private boolean ignoreRestrictions = false;
025        private boolean admin = false;
026        private boolean canModifyWorld = false;
027        private boolean muted = false;
028        private PlayerInventory inventory;
029        private List<String> onlyOneUseKits = new ArrayList<String>();
030        private Pattern badChatPattern = Pattern.compile("[^ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[\\\\\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9\u00FF\u00D6\u00DC\u00F8\u00A3\u00D8\u00D7\u0192\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA\u00BF\u00AE\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB]");
031    
032        /**
033         * Creates an empty player. Add the player by calling {@link #setUser(es)}
034         */
035        public Player() {
036        }
037        
038        /**
039         * Returns the entity we're wrapping.
040         * @return
041         */
042        public fy getEntity() {
043            return (fy)entity;
044        }
045        
046        /**
047         * Returns if the player is still connected
048         * @return
049         */
050        public boolean isConnected() {
051            return !getEntity().a.c;
052        }
053    
054        /**
055         * Kicks player with the specified reason
056         * 
057         * @param reason
058         */
059        public void kick(String reason) {
060            getEntity().a.a(reason);
061        }
062        
063        /**
064         * Sends player a notification
065         * 
066         * @param message
067         */
068        public void notify(String message) {
069            if (message.length() > 0)
070                sendMessage(Colors.Rose + message);
071        }
072    
073        /**
074         * Sends a message to the player
075         * 
076         * @param message
077         */
078        public void sendMessage(String message) {
079            getEntity().a.msg(message);
080        }
081    
082        /**
083         * Gives an item to the player
084         * 
085         * @param item
086         */
087        public void giveItem(Item item) {
088            giveItem(item.getItemId(), item.getAmount());
089        }
090    
091        /**
092         * Makes player send message.
093         * 
094         * @param message
095         */
096        public void chat(String message) {
097            if (message.length() > 100) {
098                kick("Chat message too long");
099                return;
100            }
101            message = message.trim();
102            Matcher m = badChatPattern.matcher(message);
103            if (m.find()) {
104                kick("Illegal characters '" + m.group() + "' hex: " + Integer.toHexString(message.charAt(m.start())) + " in chat");
105                return;
106            }
107            if (message.startsWith("/")) {
108                command(message);
109            } else {
110                if (isMuted()) {
111                    sendMessage(Colors.Rose + "You are currently muted.");
112                    return;
113                }
114                if ((Boolean) etc.getLoader().callHook(PluginLoader.Hook.CHAT, new Object[]{this, message})) {
115                    return;
116                }
117    
118                String chat = "<" + getColor() + getName() + Colors.White + "> " + message;
119                log.log(Level.INFO, "<" + getName() + "> " + message);
120                etc.getServer().messageAll(chat);
121            }
122        }
123    
124        /**
125         * Makes player use command.
126         * 
127         * @param command
128         * 
129         */
130        public void command(String command) {
131            try {
132                if (etc.getInstance().isLogging()) {
133                    log.info("Command used by " + getName() + " " + command);
134                }
135                String[] split = command.split(" ");
136                if ((Boolean) etc.getLoader().callHook(PluginLoader.Hook.COMMAND, new Object[]{this, split})) {
137                    return; // No need to go on, commands were parsed.
138                }
139                if (!canUseCommand(split[0]) && !split[0].startsWith("/#")) {
140                    if (etc.getInstance().showUnknownCommand()) {
141                        sendMessage(Colors.Rose + "Unknown command.");
142                    }
143                    return;
144                }
145                
146                // Remove '/' before checking.
147                if (ServerConsoleCommands.parseServerConsoleCommand(this, split[0].substring(1), split)) {
148                    // Command parsed successfully...
149                } else if (split[0].equalsIgnoreCase("/help")) {
150                    // Meh, not the greatest way, but not the worst either.
151                    List<String> availableCommands = new ArrayList<String>();
152                    for (Entry<String, String> entry : etc.getInstance().getCommands().entrySet()) {
153                        if (canUseCommand(entry.getKey())) {
154                            if (entry.getKey().equals("/kit") && !etc.getDataSource().hasKits()) {
155                                continue;
156                            }
157                            if (entry.getKey().equals("/listwarps") && !etc.getDataSource().hasWarps()) {
158                                continue;
159                            }
160    
161                            availableCommands.add(entry.getKey() + " " + entry.getValue());
162                        }
163                    }
164    
165                    sendMessage(Colors.Blue + "Available commands (Page " + (split.length == 2 ? split[1] : "1") + " of " + (int) Math.ceil((double) availableCommands.size() / (double) 7) + ") [] = required <> = optional:");
166                    if (split.length == 2) {
167                        try {
168                            int amount = Integer.parseInt(split[1]);
169    
170                            if (amount > 0) {
171                                amount = (amount - 1) * 7;
172                            } else {
173                                amount = 0;
174                            }
175    
176                            for (int i = amount; i < amount + 7; i++) {
177                                if (availableCommands.size() > i) {
178                                    sendMessage(Colors.Rose + availableCommands.get(i));
179                                }
180                            }
181                        } catch (NumberFormatException ex) {
182                            sendMessage(Colors.Rose + "Not a valid page number.");
183                        }
184                    } else {
185                        for (int i = 0; i < 7; i++) {
186                            if (availableCommands.size() > i) {
187                                sendMessage(Colors.Rose + availableCommands.get(i));
188                            }
189                        }
190                    }
191                } else if (split[0].equalsIgnoreCase("/mute")) {
192                    if (split.length != 2) {
193                        sendMessage(Colors.Rose + "Correct usage is: /mute [player]");
194                        return;
195                    }
196    
197                    Player player = etc.getServer().matchPlayer(split[1]);
198    
199                    if (player != null) {
200                        if (player.toggleMute()) {
201                            sendMessage(Colors.Rose + "player was muted");
202                        } else {
203                            sendMessage(Colors.Rose + "player was unmuted");
204                        }
205                    } else {
206                        sendMessage(Colors.Rose + "Can't find player " + split[1]);
207                    }
208                } else if ((split[0].equalsIgnoreCase("/msg") || split[0].equalsIgnoreCase("/tell")) || split[0].equalsIgnoreCase("/m")) {
209                    if (split.length < 3) {
210                        sendMessage(Colors.Rose + "Correct usage is: /msg [player] [message]");
211                        return;
212                    }
213                    if (isMuted()) {
214                        sendMessage(Colors.Rose + "You are currently muted.");
215                        return;
216                    }
217    
218                    Player player = etc.getServer().matchPlayer(split[1]);
219    
220                    if (player != null) {
221                        if (player.getName().equals(getName())) {
222                            sendMessage(Colors.Rose + "You can't message yourself!");
223                            return;
224                        }
225    
226                        player.sendMessage("(MSG) " + getColor() + "<" + getName() + "> " + Colors.White + etc.combineSplit(2, split, " "));
227                        sendMessage("(MSG) " + getColor() + "<" + getName() + "> " + Colors.White + etc.combineSplit(2, split, " "));
228                    } else {
229                        sendMessage(Colors.Rose + "Couldn't find player " + split[1]);
230                    }
231                } else if (split[0].equalsIgnoreCase("/kit") && etc.getDataSource().hasKits()) {
232                    if (split.length != 2 && split.length != 3) {
233                        sendMessage(Colors.Rose + "Available kits" + Colors.White + ": " + etc.getDataSource().getKitNames(this));
234                        return;
235                    }
236    
237                    Player toGive = this;
238                    if (split.length > 2 && canIgnoreRestrictions()) {
239                        toGive = etc.getServer().matchPlayer(split[2]);
240                    }
241    
242                    Kit kit = etc.getDataSource().getKit(split[1]);
243                    if (toGive != null) {
244                        if (kit != null) {
245                            if (!isInGroup(kit.Group) && !kit.Group.equals("")) {
246                                sendMessage(Colors.Rose + "That kit does not exist.");
247                            } else if (onlyOneUseKits.contains(kit.Name)) {
248                                sendMessage(Colors.Rose + "You can only get this kit once per login.");
249                            } else if (MinecraftServer.b.containsKey(getName() + " " + kit.Name)) {
250                                sendMessage(Colors.Rose + "You can't get this kit again for a while.");
251                            } else {
252                                if (!canIgnoreRestrictions()) {
253                                    if (kit.Delay >= 0) {
254                                        MinecraftServer.b.put(getName() + " " + kit.Name, kit.Delay);
255                                    } else {
256                                        onlyOneUseKits.add(kit.Name);
257                                    }
258                                }
259    
260                                log.info(getName() + " got a kit!");
261                                toGive.sendMessage(Colors.Rose + "Enjoy this kit!");
262                                for (Map.Entry<String, Integer> entry : kit.IDs.entrySet()) {
263                                    try {
264                                        int itemId = 0;
265                                        try {
266                                            itemId = Integer.parseInt(entry.getKey());
267                                        } catch (NumberFormatException n) {
268                                            itemId = etc.getDataSource().getItem(entry.getKey());
269                                        }
270    
271                                        toGive.giveItem(itemId, kit.IDs.get(entry.getKey()));
272                                    } catch (Exception e1) {
273                                        log.info("Got an exception while giving out a kit (Kit name \"" + kit.Name + "\"). Are you sure all the Ids are numbers?");
274                                        sendMessage(Colors.Rose + "The server encountered a problem while giving the kit :(");
275                                    }
276                                }
277                            }
278                        } else {
279                            sendMessage(Colors.Rose + "That kit does not exist.");
280                        }
281                    } else {
282                        sendMessage(Colors.Rose + "That user does not exist.");
283                    }
284                } else if (split[0].equalsIgnoreCase("/tp")) {
285                    if (split.length < 2) {
286                        sendMessage(Colors.Rose + "Correct usage is: /tp [player]");
287                        return;
288                    }
289    
290                    Player player = etc.getServer().matchPlayer(split[1]);
291    
292                    if (player != null) {
293                        if (getName().equalsIgnoreCase(player.getName())) {
294                            sendMessage(Colors.Rose + "You're already here!");
295                            return;
296                        }
297    
298                        log.info(getName() + " teleported to " + player.getName());
299                        teleportTo(player);
300                    } else {
301                        sendMessage(Colors.Rose + "Can't find user " + split[1] + ".");
302                    }
303                } else if ((split[0].equalsIgnoreCase("/tphere") || split[0].equalsIgnoreCase("/s"))) {
304                    if (split.length < 2) {
305                        sendMessage(Colors.Rose + "Correct usage is: /tphere [player]");
306                        return;
307                    }
308    
309                    Player player = etc.getServer().matchPlayer(split[1]);
310    
311                    if (player != null) {
312                        if (getName().equalsIgnoreCase(player.getName())) {
313                            sendMessage(Colors.Rose + "Wow look at that! You teleported yourself to yourself!");
314                            return;
315                        }
316    
317                        log.info(getName() + " teleported " + player.getName() + " to their self.");
318                        player.teleportTo(this);
319                    } else {
320                        sendMessage(Colors.Rose + "Can't find user " + split[1] + ".");
321                    }
322                } else if (split[0].equalsIgnoreCase("/playerlist") || split[0].equalsIgnoreCase("/who")) {
323                    sendMessage(Colors.Rose + "Player list (" + etc.getMCServer().f.b.size() + "/" + etc.getInstance().getPlayerLimit() + "): " + Colors.White + etc.getMCServer().f.c());
324                } else if (split[0].equalsIgnoreCase("/item") || split[0].equalsIgnoreCase("/i") || split[0].equalsIgnoreCase("/give")) {
325                    if (split.length < 2) {
326                        if (canIgnoreRestrictions()) {
327                            sendMessage(Colors.Rose + "Correct usage is: /item [itemid] <amount> <player> (optional)");
328                        } else {
329                            sendMessage(Colors.Rose + "Correct usage is: /item [itemid] <amount>");
330                        }
331                        return;
332                    }
333    
334                    Player toGive = this;
335                    if (split.length == 4 && canIgnoreRestrictions()) {
336                        toGive = etc.getServer().matchPlayer(split[3]);
337                    }
338    
339                    if (toGive != null) {
340                        try {
341                            int itemId = 0;
342                            try {
343                                itemId = Integer.parseInt(split[1]);
344                            } catch (NumberFormatException n) {
345                                itemId = etc.getDataSource().getItem(split[1]);
346                            }
347                            int amount = 1;
348                            if (split.length > 2) {
349                                amount = Integer.parseInt(split[2]);
350                            }
351    
352                            String itemIdstr = Integer.toString(itemId);
353                            if (amount <= 0 && !isAdmin()) {
354                                amount = 1;
355                            }
356    
357                            if (amount > 64 && !canIgnoreRestrictions()) {
358                                amount = 64;
359                            }
360                            if (amount > 1024) {
361                                amount = 1024; // 16 stacks worth. More than enough.
362                            }
363                            
364                            boolean allowedItem = false;
365                            if ((!etc.getInstance().getAllowedItems().isEmpty()) && (!canIgnoreRestrictions()) && (etc.getInstance().getAllowedItems().contains(itemId))) {
366                                allowedItem = true;
367                            } else allowedItem = true;
368                            if ((!etc.getInstance().getDisallowedItems().isEmpty()) && (!canIgnoreRestrictions()) && (etc.getInstance().getDisallowedItems().contains(itemId)))
369                                allowedItem = false;
370                            
371                            if (Item.isValidItem(itemId)) {
372                                if (allowedItem || canIgnoreRestrictions()) {
373                                    log.log(Level.INFO, "Giving " + toGive.getName() + " some " + itemId);
374                                    toGive.giveItem(itemId, amount);
375    
376                                    if (toGive.getName().equalsIgnoreCase(getName())) {
377                                        sendMessage(Colors.Rose + "There you go c:");
378                                    } else {
379                                        sendMessage(Colors.Rose + "Gift given! :D");
380                                        toGive.sendMessage(Colors.Rose + "Enjoy your gift! :D");
381                                    }
382                                } else if (!allowedItem && !canIgnoreRestrictions()) {
383                                    sendMessage(Colors.Rose + "You are not allowed to spawn that item.");
384                                }
385                            } else {
386                                sendMessage(Colors.Rose + "No item with ID " + split[1]);
387                            }
388                        } catch (NumberFormatException localNumberFormatException) {
389                            sendMessage(Colors.Rose + "Improper ID and/or amount.");
390                        }
391                    } else {
392                        sendMessage(Colors.Rose + "Can't find user " + split[3]);
393                    }
394                } else if (split[0].equalsIgnoreCase("/tempban")) {
395                    // /tempban MINUTES HOURS DAYS
396                    if (split.length == 1) {
397                        return;
398                    }
399                    int minutes = 0, hours = 0, days = 0;
400                    if (split.length >= 2) {
401                        minutes = Integer.parseInt(split[1]);
402                    }
403                    if (split.length >= 3) {
404                        hours = Integer.parseInt(split[2]);
405                    }
406                    if (split.length >= 4) {
407                        days = Integer.parseInt(split[3]);
408                    }
409                    Date date = new Date();
410                    // date.
411                } else if (split[0].equalsIgnoreCase("/banlist")) {
412                    byte type = 0;
413                    if (split.length == 2) {
414                        if (split[1].equalsIgnoreCase("ips")) {
415                            type = 1;
416                        }
417                    }
418                    if (type == 0) { // Regular user bans
419                        sendMessage(Colors.Blue + "Ban list:" + Colors.White + " " + etc.getMCServer().f.getBans());
420                    } else { // IP bans
421                        sendMessage(Colors.Blue + "IP Ban list:" + Colors.White + " " + etc.getMCServer().f.getIpBans());
422                    }
423                } else if (split[0].equalsIgnoreCase("/banip")) {
424                    if (split.length < 2) {
425                        sendMessage(Colors.Rose + "Correct usage is: /banip [player] <reason> (optional) NOTE: this permabans IPs.");
426                        return;
427                    }
428    
429                    Player player = etc.getServer().matchPlayer(split[1]);
430    
431                    if (player != null) {
432                        if (!hasControlOver(player)) {
433                            sendMessage(Colors.Rose + "You can't ban that user.");
434                            return;
435                        }
436    
437                        // adds player to ban list
438                        etc.getMCServer().f.c(player.getIP());
439                        etc.getLoader().callHook(PluginLoader.Hook.IPBAN, new Object[]{this, player, split.length >= 3 ? etc.combineSplit(2, split, " ") : ""});
440    
441                        log.log(Level.INFO, "IP Banning " + player.getName() + " (IP: " + player.getIP() + ")");
442                        sendMessage(Colors.Rose + "IP Banning " + player.getName() + " (IP: " + player.getIP() + ")");
443    
444                        if (split.length > 2) {
445                            player.kick("IP Banned by " + getName() + ": " + etc.combineSplit(2, split, " "));
446                        } else {
447                            player.kick("IP Banned by " + getName() + ".");
448                        }
449                    } else {
450                        sendMessage(Colors.Rose + "Can't find user " + split[1] + ".");
451                    }
452                } else if (split[0].equalsIgnoreCase("/ban")) {
453                    if (split.length < 2) {
454                        sendMessage(Colors.Rose + "Correct usage is: /ban [player] <reason> (optional)");
455                        return;
456                    }
457    
458                    Player player = etc.getServer().matchPlayer(split[1]);
459    
460                    if (player != null) {
461                        if (!hasControlOver(player)) {
462                            sendMessage(Colors.Rose + "You can't ban that user.");
463                            return;
464                        }
465    
466                        // adds player to ban list
467                        etc.getServer().ban(player.getName());
468    
469                        etc.getLoader().callHook(PluginLoader.Hook.BAN, new Object[]{this, player, split.length >= 3 ? etc.combineSplit(2, split, " ") : ""});
470    
471                        if (split.length > 2) {
472                            player.kick("Banned by " + getName() + ": " + etc.combineSplit(2, split, " "));
473                        } else {
474                            player.kick("Banned by " + getName() + ".");
475                        }
476                        log.log(Level.INFO, "Banning " + player.getName());
477                        sendMessage(Colors.Rose + "Banning " + player.getName());
478                    } else {
479                        // sendMessage(Colors.Rose + "Can't find user " + split[1] + ".");
480                        etc.getServer().ban(split[1]);
481                        log.log(Level.INFO, "Banning " + split[1]);
482                        sendMessage(Colors.Rose + "Banning " + split[1]);
483                    }
484                } else if (split[0].equalsIgnoreCase("/unban")) {
485                    if (split.length != 2) {
486                        sendMessage(Colors.Rose + "Correct usage is: /unban [player]");
487                        return;
488                    }
489                    etc.getServer().unban(split[1]);
490                    sendMessage(Colors.Rose + "Unbanned " + split[1]);
491                } else if (split[0].equalsIgnoreCase("/unbanip")) {
492                    if (split.length != 2) {
493                        sendMessage(Colors.Rose + "Correct usage is: /unbanip [ip]");
494                        return;
495                    }
496                    etc.getMCServer().f.d(split[1]);
497                    sendMessage(Colors.Rose + "Unbanned " + split[1]);
498                } else if (split[0].equalsIgnoreCase("/kick")) {
499                    if (split.length < 2) {
500                        sendMessage(Colors.Rose + "Correct usage is: /kick [player] <reason> (optional)");
501                        return;
502                    }
503    
504                    Player player = etc.getServer().matchPlayer(split[1]);
505    
506                    if (player != null) {
507                        if (!hasControlOver(player)) {
508                            sendMessage(Colors.Rose + "You can't kick that user.");
509                            return;
510                        }
511    
512                        etc.getLoader().callHook(PluginLoader.Hook.KICK, new Object[]{this, player, split.length >= 3 ? etc.combineSplit(2, split, " ") : ""});
513    
514                        if (split.length > 2) {
515                            player.kick("Kicked by " + getName() + ": " + etc.combineSplit(2, split, " "));
516                        } else {
517                            player.kick("Kicked by " + getName() + ".");
518                        }
519                        log.log(Level.INFO, "Kicking " + player.getName());
520                        sendMessage(Colors.Rose + "Kicking " + player.getName());
521                    } else {
522                        sendMessage(Colors.Rose + "Can't find user " + split[1] + ".");
523                    }
524                } else if (split[0].equalsIgnoreCase("/me")) {
525                    if (isMuted()) {
526                        sendMessage(Colors.Rose + "You are currently muted.");
527                        return;
528                    }
529                    if (split.length == 1) {
530                        return;
531                    }
532                    String paramString2 = "* " + getColor() + getName() + Colors.White + " " + command.substring(command.indexOf(" ")).trim();
533                    log.info("* " + getName() + " " + command.substring(command.indexOf(" ")).trim());
534                    etc.getServer().messageAll(paramString2);
535                } else if (split[0].equalsIgnoreCase("/sethome")) {
536                    // player.k, player.l, player.m
537                    // x, y, z
538                    Warp home = new Warp();
539                    home.Location = getLocation();
540                    home.Group = ""; // no group neccessary, lol.
541                    home.Name = getName();
542                    etc.getInstance().changeHome(home);
543                    sendMessage(Colors.Rose + "Your home has been set.");
544                } else if (split[0].equalsIgnoreCase("/spawn")) {
545                    teleportTo(etc.getServer().getSpawnLocation());
546                } else if (split[0].equalsIgnoreCase("/setspawn")) {
547                    etc.getMCServer().e.m = (int) Math.ceil(getX());
548                    etc.getMCServer().e.o = (int) Math.ceil(getZ());
549                    // Too lazy to actually update this considering it's not even
550                    // used anyways.
551                    // this.d.e.n = (int) Math.ceil(e.m); //Not that the Y axis
552                    // really matters since it tries to get the highest point iirc.
553    
554                    log.info("Spawn position changed.");
555                    sendMessage(Colors.Rose + "You have set the spawn to your current position.");
556                } else if (split[0].equalsIgnoreCase("/home")) {
557                    Warp home = null;
558                    if (split.length > 1 && isAdmin()) {
559                        home = etc.getDataSource().getHome(split[1]);
560                    } else {
561                        home = etc.getDataSource().getHome(getName());
562                    }
563    
564                    if (home != null) {
565                        teleportTo(home.Location);
566                    } else if (split.length > 1 && isAdmin()) {
567                        sendMessage(Colors.Rose + "That player home does not exist");
568                    } else {
569                        teleportTo(etc.getServer().getSpawnLocation());
570                    }
571                } else if (split[0].equalsIgnoreCase("/warp")) {
572                    if (split.length < 2) {
573                        sendMessage(Colors.Rose + "Correct usage is: /warp [warpname]");
574                        return;
575                    }
576                    Player toWarp = this;
577                    Warp warp = null;
578                    if (split.length == 3 && canIgnoreRestrictions()) {
579                        warp = etc.getDataSource().getWarp(split[1]);
580                        toWarp = etc.getServer().matchPlayer(split[2]);
581                    } else {
582                        warp = etc.getDataSource().getWarp(split[1]);
583                    }
584                    if (toWarp != null) {
585                        if (warp != null) {
586                            if (!isInGroup(warp.Group) && !warp.Group.equals("")) {
587                                sendMessage(Colors.Rose + "Warp not found.");
588                            } else {
589                                toWarp.teleportTo(warp.Location);
590                                toWarp.sendMessage(Colors.Rose + "Woosh!");
591                            }
592                        } else {
593                            sendMessage(Colors.Rose + "Warp not found");
594                        }
595                    } else {
596                        sendMessage(Colors.Rose + "Player not found.");
597                    }
598                } else if (split[0].equalsIgnoreCase("/listwarps") && etc.getDataSource().hasWarps()) {
599                    if (split.length != 2 && split.length != 3) {
600                        sendMessage(Colors.Rose + "Available warps: " + Colors.White + etc.getDataSource().getWarpNames(this));
601                        return;
602                    }
603                } else if (split[0].equalsIgnoreCase("/setwarp")) {
604                    if (split.length < 2) {
605                        if (canIgnoreRestrictions()) {
606                            sendMessage(Colors.Rose + "Correct usage is: /setwarp [warpname] [group]");
607                        } else {
608                            sendMessage(Colors.Rose + "Correct usage is: /setwarp [warpname]");
609                        }
610                        return;
611                    }
612                    if (split[1].contains(":")) {
613                        sendMessage("You can't set a warp with \":\" in its name");
614                        return;
615                    }
616                    Warp warp = new Warp();
617                    warp.Name = split[1];
618                    warp.Location = getLocation();
619                    if (split.length == 3) {
620                        warp.Group = split[2];
621                    } else {
622                        warp.Group = "";
623                    }
624                    etc.getInstance().setWarp(warp);
625                    sendMessage(Colors.Rose + "Created warp point " + split[1] + ".");
626                } else if (split[0].equalsIgnoreCase("/removewarp")) {
627                    if (split.length < 2) {
628                        sendMessage(Colors.Rose + "Correct usage is: /removewarp [warpname]");
629                        return;
630                    }
631                    Warp warp = etc.getDataSource().getWarp(split[1]);
632                    if (warp != null) {
633                        etc.getDataSource().removeWarp(warp);
634                        sendMessage(Colors.Blue + "Warp removed.");
635                    } else {
636                        sendMessage(Colors.Rose + "That warp does not exist");
637                    }
638                } else if (split[0].equalsIgnoreCase("/lighter")) {
639                    if (MinecraftServer.b.containsKey(getName() + " lighter")) {
640                        log.info(getName() + " failed to iron!");
641                        sendMessage(Colors.Rose + "You can't create another lighter again so soon");
642                    } else {
643                        if (!canIgnoreRestrictions()) {
644                            MinecraftServer.b.put(getName() + " lighter", Integer.valueOf(6000));
645                        }
646                        log.info(getName() + " created a lighter!");
647                        giveItem(259, 1);
648                    }
649                } else if ((command.startsWith("/#")) && (etc.getMCServer().f.g(getName()))) {
650                    String str = command.substring(2);
651                    log.info(getName() + " issued server command: " + str);
652                    etc.getMCServer().a(str, getEntity().a);
653                } else if (split[0].equalsIgnoreCase("/time")) {
654                    if (split.length == 2) {
655                        if (split[1].equalsIgnoreCase("day")) {
656                            etc.getServer().setRelativeTime(0);
657                        } else if (split[1].equalsIgnoreCase("night")) {
658                            etc.getServer().setRelativeTime(13000);
659                        } else if (split[1].equalsIgnoreCase("check")) {
660                            sendMessage(Colors.Rose + "The time is " + etc.getServer().getRelativeTime() + "! (RAW: " + etc.getServer().getTime() + ")");
661                        } else {
662                            try {
663                                etc.getServer().setRelativeTime(Long.parseLong(split[1]));
664                            } catch (NumberFormatException ex) {
665                                sendMessage(Colors.Rose + "Please enter numbers, not letters.");
666                            }
667                        }
668                    } else if (split.length == 3) {
669                        if (split[1].equalsIgnoreCase("raw")) {
670                            try {
671                                etc.getServer().setTime(Long.parseLong(split[2]));
672                            } catch (NumberFormatException ex) {
673                                sendMessage(Colors.Rose + "Please enter numbers, not letters.");
674                            }
675                        }
676                    } else {
677                        sendMessage(Colors.Rose + "Correct usage is: /time [time|'day|night|check|raw'] (rawtime)");
678                        return;
679                    }
680                } else if (split[0].equalsIgnoreCase("/getpos")) {
681                    sendMessage("Pos X: " + getX() + " Y: " + getY() + " Z: " + getZ());
682                    sendMessage("Rotation: " + getRotation() + " Pitch: " + getPitch());
683    
684                    double degreeRotation = ((getRotation() - 90) % 360);
685                    if (degreeRotation < 0) {
686                        degreeRotation += 360.0;
687                    }
688                    sendMessage("Compass: " + etc.getCompassPointForDirection(degreeRotation) + " (" + (Math.round(degreeRotation * 10) / 10.0) + ")");
689                } else if (split[0].equalsIgnoreCase("/compass")) {
690                    double degreeRotation = ((getRotation() - 90) % 360);
691                    if (degreeRotation < 0) {
692                        degreeRotation += 360.0;
693                    }
694    
695                    sendMessage(Colors.Rose + "Compass: " + etc.getCompassPointForDirection(degreeRotation));
696                } else if (split[0].equalsIgnoreCase("/motd")) {
697                    for (String str : etc.getInstance().getMotd()) {
698                        sendMessage(str);
699                    }
700                } else if (split[0].equalsIgnoreCase("/spawnmob")) {
701                    if (split.length == 1) {
702                        sendMessage(Colors.Rose + "Correct usage is: /spawnmob [name] <amount>");
703                        return;
704                    }
705                    if (!Mob.isValid(split[1])) {
706                        sendMessage(Colors.Rose + "Invalid mob. Name has to start with a capital like so: Pig");
707                        return;
708                    }
709    
710                    if (split.length == 2) {
711                        Mob mob = new Mob(split[1], getLocation());
712                        mob.spawn();
713                    } else if (split.length == 3) {
714                        try {
715                            int mobnumber = Integer.parseInt(split[2]);
716                            for (int i = 0; i < mobnumber; i++) {
717                                Mob mob = new Mob(split[1], getLocation());
718                                mob.spawn();
719                            }
720                        } catch (NumberFormatException nfe) {
721                            if (!Mob.isValid(split[2])) {
722                                sendMessage(Colors.Rose + "Invalid mob name or number of mobs.");
723                                sendMessage(Colors.Rose + "Mob names have to start with a capital like so: Pig");
724                            } else {
725                                Mob mob = new Mob(split[1], getLocation());
726                                mob.spawn(new Mob(split[2]));
727                            }
728                        }
729                    } else if (split.length == 4) {
730                        try {
731                            int mobnumber = Integer.parseInt(split[3]);
732                            if (!Mob.isValid(split[2])) {
733                                sendMessage(Colors.Rose + "Invalid rider. Name has to start with a capital like so: Pig");
734                            } else {
735                                for (int i = 0; i < mobnumber; i++) {
736                                    Mob mob = new Mob(split[1], getLocation());
737                                    mob.spawn(new Mob(split[2]));
738                                }
739                            }
740                        } catch (NumberFormatException nfe) {
741                            sendMessage(Colors.Rose + "Invalid number of mobs.");
742                        }
743                    }
744                } else if (split[0].equalsIgnoreCase("/clearinventory")) {
745                    Player target = this;
746                    if (split.length >= 2 && isAdmin()) {
747                        target = etc.getServer().matchPlayer(split[1]);
748                    }
749                    if (target != null) {
750                        Inventory inv = target.getInventory();
751                        inv.clearContents();
752                        inv.update();
753                        if (!target.getName().equals(getName())) {
754                            sendMessage(Colors.Rose + "Cleared " + target.getName() + "'s inventory.");
755                        }
756                    } else {
757                        sendMessage(Colors.Rose + "Target not found");
758                    }
759                } else if (split[0].equals("/mspawn")) {
760                    if (split.length != 2) {
761                        sendMessage(Colors.Rose + "You must specify what to change the mob spawner to.");
762                        return;
763                    }
764                    if (!Mob.isValid(split[1])) {
765                        sendMessage(Colors.Rose + "Invalid mob specified.");
766                        return;
767                    }
768    
769                    HitBlox hb = new HitBlox(this);
770                    Block block = hb.getTargetBlock();
771                    if (block.getType() == 52) { // mob spawner
772                        MobSpawner ms = (MobSpawner) etc.getServer().getComplexBlock(block.getX(), block.getY(), block.getZ());
773                        if (ms != null)
774                            ms.setSpawn(split[1]);
775                    } else {
776                        sendMessage(Colors.Rose + "You are not targeting a mob spawner.");
777                    }
778                } else {
779                    log.info(getName() + " tried command " + command);
780                    if (etc.getInstance().showUnknownCommand()) {
781                        sendMessage(Colors.Rose + "Unknown command");
782                    }
783                }
784            } catch (Throwable ex) { // Might as well try and catch big exceptions
785                // before the server crashes from a stack
786                // overflow or something
787                log.log(Level.SEVERE, "Exception in command handler (Report this to hey0 unless you did something dumb like enter letters as numbers):", ex);
788                if (isAdmin()) {
789                    sendMessage(Colors.Rose + "Exception occured. Check the server for more info.");
790                }
791            }
792        }
793    
794        /**
795         * Gives an item to the player
796         * 
797         * @param itemId
798         * @param amount
799         */
800        public void giveItem(int itemId, int amount) {
801            inventory.giveItem(itemId, amount);
802            inventory.update();
803        }
804    
805        /**
806         * Gives the player this item by dropping it in front of them
807         * 
808         * @param item
809         */
810        public void giveItemDrop(Item item) {
811            giveItemDrop(item.getItemId(), item.getAmount());
812        }
813    
814        /**
815         * Gives the player this item by dropping it in front of them
816         * 
817         * @param itemId
818         * @param amount
819         */
820        public void giveItemDrop(int itemId, int amount) {
821            fy player = getEntity();
822            if (amount == -1) {
823                player.a(new jl(itemId, 255,0));
824            } else {
825                int temp = amount;
826                do {
827                    if (temp - 64 >= 64) {
828                        player.a(new jl(itemId, 64,0));
829                    } else {
830                        player.a(new jl(itemId, temp,0));
831                    }
832                    temp -= 64;
833                } while (temp > 0);
834            }
835        }
836    
837        /**
838         * Returns true if this player can use the specified command
839         * 
840         * @param command
841         * @return
842         */
843        public boolean canUseCommand(String command) {
844            for (String str : commands) {
845                if (str.equalsIgnoreCase(command)) {
846                    return true;
847                }
848            }
849    
850            for (String str : groups) {
851                Group g = etc.getDataSource().getGroup(str);
852                if (g != null) {
853                    if (recursiveUseCommand(g, command)) {
854                        return true;
855                    }
856                }
857            }
858    
859            if (hasNoGroups()) {
860                Group def = etc.getInstance().getDefaultGroup();
861                if (def != null) {
862                    if (recursiveUseCommand(def, command)) {
863                        return true;
864                    }
865                }
866            }
867    
868            return false;
869        }
870    
871        private boolean recursiveUseCommand(Group g, String command) {
872            for (String str : g.Commands) {
873                if (str.equalsIgnoreCase(command) || str.equals("*")) {
874                    return true;
875                }
876            }
877    
878            if (g.InheritedGroups != null) {
879                for (String str : g.InheritedGroups) {
880                    Group g2 = etc.getDataSource().getGroup(str);
881                    if (g2 != null) {
882                        if (recursiveUseCommand(g2, command)) {
883                            return true;
884                        }
885                    }
886                }
887            }
888            return false;
889        }
890    
891        /**
892         * Checks to see if this player is in the specified group
893         * 
894         * @param group
895         * @return
896         */
897        public boolean isInGroup(String group) {
898            if (group != null) {
899                if (etc.getInstance().getDefaultGroup() != null) {
900                    if (group.equalsIgnoreCase(etc.getInstance().getDefaultGroup().Name)) {
901                        return true;
902                    }
903                }
904            }
905            for (String str : groups) {
906                if (recursiveUserInGroup(etc.getDataSource().getGroup(str), group)) {
907                    return true;
908                }
909            }
910            return false;
911        }
912    
913        private boolean recursiveUserInGroup(Group g, String group) {
914            if (g == null || group == null) {
915                return false;
916            }
917    
918            if (g.Name.equalsIgnoreCase(group)) {
919                return true;
920            }
921    
922            if (g.InheritedGroups != null) {
923                for (String str : g.InheritedGroups) {
924                    if (g.Name.equalsIgnoreCase(str)) {
925                        return true;
926                    }
927    
928                    Group g2 = etc.getDataSource().getGroup(str);
929                    if (g2 != null) {
930                        if (recursiveUserInGroup(g2, group)) {
931                            return true;
932                        }
933                    }
934                }
935            }
936            return false;
937        }
938    
939        /**
940         * Returns true if this player has control over the other player
941         * 
942         * @param player
943         * @return true if player has control
944         */
945        public boolean hasControlOver(Player player) {
946            boolean isInGroup = false;
947    
948            if (player.hasNoGroups()) {
949                return true;
950            }
951            for (String str : player.getGroups()) {
952                if (isInGroup(str)) {
953                    isInGroup = true;
954                } else {
955                    continue;
956                }
957                break;
958            }
959    
960            return isInGroup;
961        }
962    
963        /**
964         * Returns the player's current location
965         * 
966         * @return
967         */
968        public Location getLocation() {
969            Location loc = new Location();
970            loc.x = getX();
971            loc.y = getY();
972            loc.z = getZ();
973            loc.rotX = getRotation();
974            loc.rotY = getPitch();
975            return loc;
976        }
977    
978        /**
979         * Returns the IP of this player
980         * 
981         * @return
982         */
983        public String getIP() {
984            return getEntity().a.b.b().toString().split(":")[0].substring(1);
985        }
986    
987        /**
988         * Returns true if this player is an admin.
989         * 
990         * @return
991         */
992        public boolean isAdmin() {
993            if (admin) {
994                return true;
995            }
996    
997            for (String str : groups) {
998                Group group = etc.getDataSource().getGroup(str);
999                if (group != null) {
1000                    if (group.Administrator) {
1001                        return true;
1002                    }
1003                }
1004            }
1005            return false;
1006        }
1007    
1008        /**
1009         * Don't use this! Use isAdmin
1010         * 
1011         * @return
1012         */
1013        public boolean getAdmin() {
1014            return admin;
1015        }
1016    
1017        /**
1018         * Sets whether or not this player is an administrator
1019         * 
1020         * @param admin
1021         */
1022        public void setAdmin(boolean admin) {
1023            this.admin = admin;
1024        }
1025    
1026        /**
1027         * Returns false if this player can not modify terrain, edit chests, etc.
1028         * 
1029         * @return
1030         */
1031        public boolean canBuild() {
1032            if (canModifyWorld) {
1033                return true;
1034            }
1035    
1036            for (String str : groups) {
1037                Group group = etc.getDataSource().getGroup(str);
1038                if (group != null) {
1039                    if (group.CanModifyWorld) {
1040                        return true;
1041                    }
1042                }
1043            }
1044    
1045            if (hasNoGroups()) {
1046                if (etc.getInstance().getDefaultGroup().CanModifyWorld) {
1047                    return true;
1048                }
1049            }
1050    
1051            return false;
1052        }
1053    
1054        /**
1055         * Don't use this, use canBuild()
1056         * 
1057         * @return
1058         */
1059        public boolean canModifyWorld() {
1060            return canModifyWorld;
1061        }
1062    
1063        /**
1064         * Sets whether or not this player can modify the world terrain
1065         * 
1066         * @param canModifyWorld
1067         */
1068        public void setCanModifyWorld(boolean canModifyWorld) {
1069            this.canModifyWorld = canModifyWorld;
1070        }
1071    
1072        /**
1073         * Set allowed commands
1074         * 
1075         * @return
1076         */
1077        public String[] getCommands() {
1078            return commands;
1079        }
1080    
1081        /**
1082         * Sets this player's allowed commands
1083         * 
1084         * @param commands
1085         */
1086        public void setCommands(String[] commands) {
1087            this.commands = commands;
1088        }
1089    
1090        /**
1091         * Returns this player's groups
1092         * 
1093         * @return
1094         */
1095        public String[] getGroups() {
1096            String[] strGroups = new String[groups.size()];
1097            groups.toArray(strGroups);
1098            return strGroups;
1099        }
1100    
1101        /**
1102         * Sets this player's groups
1103         * 
1104         * @param groups
1105         */
1106        public void setGroups(String[] groups) {
1107            this.groups.clear();
1108            for (String s : groups) {
1109                if (s.length() > 0) {
1110                    this.groups.add(s);
1111                }
1112            }
1113        }
1114    
1115        /**
1116         * Adds the player to the specified group
1117         * 
1118         * @param group group to add player to
1119         */
1120        public void addGroup(String group) {
1121            this.groups.add(group);
1122        }
1123    
1124        /**
1125         * Removes specified group from list of groups
1126         * @param group group to remove
1127         */
1128        public void removeGroup(String group) {
1129            this.groups.remove(group);
1130        }
1131    
1132        /**
1133         * Returns the sql ID.
1134         * 
1135         * @return
1136         */
1137        public int getSqlId() {
1138            return id;
1139        }
1140    
1141        /**
1142         * Sets the sql ID. Don't touch this.
1143         * 
1144         * @param id
1145         */
1146        public void setSqlId(int id) {
1147            this.id = id;
1148        }
1149    
1150        /**
1151         * If the user can ignore restrictions this will return true. Things like
1152         * item amounts and such are unlimited, etc.
1153         * 
1154         * @return
1155         */
1156        public boolean canIgnoreRestrictions() {
1157            if (admin || ignoreRestrictions) {
1158                return true;
1159            }
1160    
1161            for (String str : groups) {
1162                Group group = etc.getDataSource().getGroup(str);
1163                if (group != null) {
1164                    if (group.Administrator || group.IgnoreRestrictions) {
1165                        return true;
1166                    }
1167                }
1168            }
1169            return false;
1170        }
1171    
1172        /**
1173         * Don't use. Use canIgnoreRestrictions()
1174         * 
1175         * @return
1176         */
1177        public boolean ignoreRestrictions() {
1178            return ignoreRestrictions;
1179        }
1180    
1181        /**
1182         * Sets ignore restrictions
1183         * 
1184         * @param ignoreRestrictions
1185         */
1186        public void setIgnoreRestrictions(boolean ignoreRestrictions) {
1187            this.ignoreRestrictions = ignoreRestrictions;
1188        }
1189    
1190        /**
1191         * Returns allowed IPs
1192         * 
1193         * @return
1194         */
1195        public String[] getIps() {
1196            return ips;
1197        }
1198    
1199        /**
1200         * Sets allowed IPs
1201         * 
1202         * @param ips
1203         */
1204        public void setIps(String[] ips) {
1205            this.ips = ips;
1206        }
1207    
1208        /**
1209         * Returns the correct color/prefix for this player
1210         * 
1211         * @return
1212         */
1213        public String getColor() {
1214            if (prefix != null) {
1215                if (!prefix.equals("")) {
1216                    return "§" + prefix;
1217                }
1218            }
1219            if (groups.size() > 0) {
1220                Group group = etc.getDataSource().getGroup(groups.get(0));
1221                if (group != null) {
1222                    return "§" + group.Prefix;
1223                }
1224            }
1225            Group def = etc.getInstance().getDefaultGroup();
1226            return def != null ? "§" + def.Prefix : "";
1227        }
1228    
1229        /**
1230         * Returns the prefix. NOTE: Don't use this, use getColor() instead.
1231         * 
1232         * @return
1233         */
1234        public String getPrefix() {
1235            return prefix;
1236        }
1237    
1238        /**
1239         * Sets the prefix
1240         * 
1241         * @param prefix
1242         */
1243        public void setPrefix(String prefix) {
1244            this.prefix = prefix;
1245        }
1246    
1247        /**
1248         * Gets the actual user class.
1249         * 
1250         * @return
1251         */
1252        public fy getUser() {
1253            return getEntity();
1254        }
1255    
1256        /**
1257         * Sets the user. Don't use this.
1258         * 
1259         * @param er
1260         */
1261        public void setUser(fy player) {
1262            this.entity = player;
1263            this.inventory = new PlayerInventory(this);
1264        }
1265    
1266        public void teleportTo(double x, double y, double z, float rotation, float pitch) {
1267            fy player = getEntity();
1268            
1269            // If player is in vehicle - eject them before they are teleported.
1270            if (player.k != null) {
1271                player.e(player.k);
1272            }
1273            player.a.a(x, y, z, rotation, pitch);
1274        }
1275    
1276        /**
1277         * Returns true if the player is muted
1278         * 
1279         * @return
1280         */
1281        public boolean isMuted() {
1282            return muted;
1283        }
1284    
1285        /**
1286         * Toggles mute
1287         * 
1288         * @return
1289         */
1290        public boolean toggleMute() {
1291            muted = !muted;
1292            return muted;
1293        }
1294    
1295        /**
1296         * Checks to see if this player is in any groups
1297         * 
1298         * @return true if this player is in any group
1299         */
1300        public boolean hasNoGroups() {
1301            if (groups.isEmpty()) {
1302                return true;
1303            }
1304            if (groups.size() == 1) {
1305                return groups.get(0).equals("");
1306            }
1307            return false;
1308        }
1309    
1310        /**
1311         * Returns item id in player's hand
1312         * 
1313         * @return
1314         */
1315        public int getItemInHand() {
1316            return getEntity().a.getItemInHand();
1317        }
1318    
1319        /**
1320         * Returns this player's inventory
1321         * 
1322         * @return inventory
1323         */
1324        public Inventory getInventory() {
1325            return inventory;
1326        }
1327    
1328        /**
1329         * Returns whether or not this Player is currently sneaking (crouching)
1330         * 
1331         * @return true if sneaking
1332         */
1333        public boolean getSneaking() {
1334            return getEntity().am;
1335        }
1336    
1337        /**
1338         * Force this Player to be sneaking or not
1339         * 
1340         * @param sneaking true if sneaking
1341         */
1342        public void setSneaking(boolean sneaking) {
1343            getEntity().am = sneaking;
1344        }
1345    
1346        /**
1347         * Returns a String representation of this Player
1348         * 
1349         * @return String representation of this Player
1350         */
1351        @Override
1352        public String toString() {
1353            return String.format("Player[id=%d, name=%s]", id, getName());
1354        }
1355    
1356        /**
1357         * Tests the given object to see if it equals this object
1358         * 
1359         * @param obj the object to test
1360         * @return true if the two objects match
1361         */
1362        @Override
1363        public boolean equals(Object obj) {
1364            if (obj == null) {
1365                return false;
1366            }
1367            if (getClass() != obj.getClass()) {
1368                return false;
1369            }
1370            final Player other = (Player) obj;
1371            return getName().equals( other.getName());
1372        }
1373    
1374        /**
1375         * Returns a unique hashcode for this Player
1376         * 
1377         * @return hashcode
1378         */
1379        @Override
1380        public int hashCode() {
1381            int hash = 7;
1382            hash = 71 * hash + this.id;
1383            return hash;
1384        }
1385    }