001    package net.minecraft.src;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.DataInputStream;
005    import java.io.IOException;
006    import java.util.ArrayList;
007    import java.util.Iterator;
008    import java.util.Random;
009    import java.util.logging.Logger;
010    
011    import cpw.mods.fml.common.network.FMLNetworkHandler;
012    import net.minecraft.server.MinecraftServer;
013    import net.minecraftforge.event.Event;
014    import net.minecraftforge.event.ForgeEventFactory;
015    import net.minecraftforge.event.entity.player.PlayerInteractEvent;
016    import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
017    
018    public class NetServerHandler extends NetHandler
019    {
020        /** The logging system. */
021        public static Logger logger = Logger.getLogger("Minecraft");
022    
023        /** The underlying network manager for this server handler. */
024        public NetworkManager netManager;
025    
026        /** This is set to true whenever a player disconnects from the server. */
027        public boolean connectionClosed = false;
028    
029        /** Reference to the MinecraftServer object. */
030        private MinecraftServer mcServer;
031    
032        /** Reference to the EntityPlayerMP object. */
033        private EntityPlayerMP playerEntity;
034    
035        /** incremented each tick */
036        private int currentTicks;
037    
038        /**
039         * player is kicked if they float for over 80 ticks without flying enabled
040         */
041        public int ticksForFloatKick;
042        private boolean field_72584_h;
043        private int keepAliveRandomID;
044        private long keepAliveTimeSent;
045        private static Random randomGenerator = new Random();
046        private long ticksOfLastKeepAlive;
047        private int chatSpamThresholdCount = 0;
048        private int creativeItemCreationSpamThresholdTally = 0;
049    
050        /** The last known x position for this connection. */
051        private double lastPosX;
052    
053        /** The last known y position for this connection. */
054        private double lastPosY;
055    
056        /** The last known z position for this connection. */
057        private double lastPosZ;
058    
059        /** is true when the player has moved since his last movement packet */
060        private boolean hasMoved = true;
061        private IntHashMap field_72586_s = new IntHashMap();
062    
063        public NetServerHandler(MinecraftServer par1MinecraftServer, NetworkManager par2NetworkManager, EntityPlayerMP par3EntityPlayerMP)
064        {
065            this.mcServer = par1MinecraftServer;
066            this.netManager = par2NetworkManager;
067            par2NetworkManager.setNetHandler(this);
068            this.playerEntity = par3EntityPlayerMP;
069            par3EntityPlayerMP.playerNetServerHandler = this;
070        }
071    
072        /**
073         * run once each game tick
074         */
075        public void networkTick()
076        {
077            this.field_72584_h = false;
078            ++this.currentTicks;
079            this.mcServer.theProfiler.startSection("packetflow");
080            this.netManager.processReadPackets();
081            this.mcServer.theProfiler.endStartSection("keepAlive");
082    
083            if ((long)this.currentTicks - this.ticksOfLastKeepAlive > 20L)
084            {
085                this.ticksOfLastKeepAlive = (long)this.currentTicks;
086                this.keepAliveTimeSent = System.nanoTime() / 1000000L;
087                this.keepAliveRandomID = randomGenerator.nextInt();
088                this.sendPacketToPlayer(new Packet0KeepAlive(this.keepAliveRandomID));
089            }
090    
091            if (this.chatSpamThresholdCount > 0)
092            {
093                --this.chatSpamThresholdCount;
094            }
095    
096            if (this.creativeItemCreationSpamThresholdTally > 0)
097            {
098                --this.creativeItemCreationSpamThresholdTally;
099            }
100    
101            this.mcServer.theProfiler.endStartSection("playerTick");
102    
103            if (!this.field_72584_h && !this.playerEntity.playerConqueredTheEnd)
104            {
105                this.playerEntity.onUpdateEntity();
106    
107                if (this.playerEntity.ridingEntity == null)
108                {
109                    this.playerEntity.setLocationAndAngles(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
110                }
111            }
112    
113            this.mcServer.theProfiler.endSection();
114        }
115    
116        public void kickPlayerFromServer(String par1Str)
117        {
118            if (!this.connectionClosed)
119            {
120                this.playerEntity.mountEntityAndWakeUp();
121                this.sendPacketToPlayer(new Packet255KickDisconnect(par1Str));
122                this.netManager.serverShutdown();
123                this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + this.playerEntity.username + " left the game."));
124                this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
125                this.connectionClosed = true;
126            }
127        }
128    
129        public void handleFlying(Packet10Flying par1Packet10Flying)
130        {
131            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
132            this.field_72584_h = true;
133    
134            if (!this.playerEntity.playerConqueredTheEnd)
135            {
136                double var3;
137    
138                if (!this.hasMoved)
139                {
140                    var3 = par1Packet10Flying.yPosition - this.lastPosY;
141    
142                    if (par1Packet10Flying.xPosition == this.lastPosX && var3 * var3 < 0.01D && par1Packet10Flying.zPosition == this.lastPosZ)
143                    {
144                        this.hasMoved = true;
145                    }
146                }
147    
148                if (this.hasMoved)
149                {
150                    double var5;
151                    double var7;
152                    double var9;
153                    double var13;
154    
155                    if (this.playerEntity.ridingEntity != null)
156                    {
157                        float var34 = this.playerEntity.rotationYaw;
158                        float var4 = this.playerEntity.rotationPitch;
159                        this.playerEntity.ridingEntity.updateRiderPosition();
160                        var5 = this.playerEntity.posX;
161                        var7 = this.playerEntity.posY;
162                        var9 = this.playerEntity.posZ;
163                        double var35 = 0.0D;
164                        var13 = 0.0D;
165    
166                        if (par1Packet10Flying.rotating)
167                        {
168                            var34 = par1Packet10Flying.yaw;
169                            var4 = par1Packet10Flying.pitch;
170                        }
171    
172                        if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D && par1Packet10Flying.stance == -999.0D)
173                        {
174                            if (Math.abs(par1Packet10Flying.xPosition) > 1.0D || Math.abs(par1Packet10Flying.zPosition) > 1.0D)
175                            {
176                                System.err.println(this.playerEntity.username + " was caught trying to crash the server with an invalid position.");
177                                this.kickPlayerFromServer("Nope!");
178                                return;
179                            }
180    
181                            var35 = par1Packet10Flying.xPosition;
182                            var13 = par1Packet10Flying.zPosition;
183                        }
184    
185                        this.playerEntity.onGround = par1Packet10Flying.onGround;
186                        this.playerEntity.onUpdateEntity();
187                        this.playerEntity.moveEntity(var35, 0.0D, var13);
188                        this.playerEntity.setPositionAndRotation(var5, var7, var9, var34, var4);
189                        this.playerEntity.motionX = var35;
190                        this.playerEntity.motionZ = var13;
191    
192                        if (this.playerEntity.ridingEntity != null)
193                        {
194                            var2.uncheckedUpdateEntity(this.playerEntity.ridingEntity, true);
195                        }
196    
197                        if (this.playerEntity.ridingEntity != null)
198                        {
199                            this.playerEntity.ridingEntity.updateRiderPosition();
200                        }
201    
202                        this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
203                        this.lastPosX = this.playerEntity.posX;
204                        this.lastPosY = this.playerEntity.posY;
205                        this.lastPosZ = this.playerEntity.posZ;
206                        var2.updateEntity(this.playerEntity);
207                        return;
208                    }
209    
210                    if (this.playerEntity.isPlayerSleeping())
211                    {
212                        this.playerEntity.onUpdateEntity();
213                        this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
214                        var2.updateEntity(this.playerEntity);
215                        return;
216                    }
217    
218                    var3 = this.playerEntity.posY;
219                    this.lastPosX = this.playerEntity.posX;
220                    this.lastPosY = this.playerEntity.posY;
221                    this.lastPosZ = this.playerEntity.posZ;
222                    var5 = this.playerEntity.posX;
223                    var7 = this.playerEntity.posY;
224                    var9 = this.playerEntity.posZ;
225                    float var11 = this.playerEntity.rotationYaw;
226                    float var12 = this.playerEntity.rotationPitch;
227    
228                    if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D && par1Packet10Flying.stance == -999.0D)
229                    {
230                        par1Packet10Flying.moving = false;
231                    }
232    
233                    if (par1Packet10Flying.moving)
234                    {
235                        var5 = par1Packet10Flying.xPosition;
236                        var7 = par1Packet10Flying.yPosition;
237                        var9 = par1Packet10Flying.zPosition;
238                        var13 = par1Packet10Flying.stance - par1Packet10Flying.yPosition;
239    
240                        if (!this.playerEntity.isPlayerSleeping() && (var13 > 1.65D || var13 < 0.1D))
241                        {
242                            this.kickPlayerFromServer("Illegal stance");
243                            logger.warning(this.playerEntity.username + " had an illegal stance: " + var13);
244                            return;
245                        }
246    
247                        if (Math.abs(par1Packet10Flying.xPosition) > 3.2E7D || Math.abs(par1Packet10Flying.zPosition) > 3.2E7D)
248                        {
249                            this.kickPlayerFromServer("Illegal position");
250                            return;
251                        }
252                    }
253    
254                    if (par1Packet10Flying.rotating)
255                    {
256                        var11 = par1Packet10Flying.yaw;
257                        var12 = par1Packet10Flying.pitch;
258                    }
259    
260                    this.playerEntity.onUpdateEntity();
261                    this.playerEntity.ySize = 0.0F;
262                    this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
263    
264                    if (!this.hasMoved)
265                    {
266                        return;
267                    }
268    
269                    var13 = var5 - this.playerEntity.posX;
270                    double var15 = var7 - this.playerEntity.posY;
271                    double var17 = var9 - this.playerEntity.posZ;
272                    double var19 = Math.min(Math.abs(var13), Math.abs(this.playerEntity.motionX));
273                    double var21 = Math.min(Math.abs(var15), Math.abs(this.playerEntity.motionY));
274                    double var23 = Math.min(Math.abs(var17), Math.abs(this.playerEntity.motionZ));
275                    double var25 = var19 * var19 + var21 * var21 + var23 * var23;
276    
277                    if (var25 > 100.0D && (!this.mcServer.isSinglePlayer() || !this.mcServer.getServerOwner().equals(this.playerEntity.username)))
278                    {
279                        logger.warning(this.playerEntity.username + " moved too quickly! " + var13 + "," + var15 + "," + var17 + " (" + var19 + ", " + var21 + ", " + var23 + ")");
280                        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
281                        return;
282                    }
283    
284                    float var27 = 0.0625F;
285                    boolean var28 = var2.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)var27, (double)var27, (double)var27)).isEmpty();
286    
287                    if (this.playerEntity.onGround && !par1Packet10Flying.onGround && var15 > 0.0D)
288                    {
289                        this.playerEntity.addExhaustion(0.2F);
290                    }
291    
292                    this.playerEntity.moveEntity(var13, var15, var17);
293                    this.playerEntity.onGround = par1Packet10Flying.onGround;
294                    this.playerEntity.addMovementStat(var13, var15, var17);
295                    double var29 = var15;
296                    var13 = var5 - this.playerEntity.posX;
297                    var15 = var7 - this.playerEntity.posY;
298    
299                    if (var15 > -0.5D || var15 < 0.5D)
300                    {
301                        var15 = 0.0D;
302                    }
303    
304                    var17 = var9 - this.playerEntity.posZ;
305                    var25 = var13 * var13 + var15 * var15 + var17 * var17;
306                    boolean var31 = false;
307    
308                    if (var25 > 0.0625D && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.theItemInWorldManager.isCreative())
309                    {
310                        var31 = true;
311                        logger.warning(this.playerEntity.username + " moved wrongly!");
312                    }
313    
314                    this.playerEntity.setPositionAndRotation(var5, var7, var9, var11, var12);
315                    boolean var32 = var2.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)var27, (double)var27, (double)var27)).isEmpty();
316    
317                    if (var28 && (var31 || !var32) && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.noClip)
318                    {
319                        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
320                        return;
321                    }
322    
323                    AxisAlignedBB var33 = this.playerEntity.boundingBox.copy().expand((double)var27, (double)var27, (double)var27).addCoord(0.0D, -0.55D, 0.0D);
324    
325                    if (!this.mcServer.isFlightAllowed() && !this.playerEntity.theItemInWorldManager.isCreative() && !var2.isAABBNonEmpty(var33)  && !this.playerEntity.capabilities.allowFlying)
326                    {
327                        if (var29 >= -0.03125D)
328                        {
329                            ++this.ticksForFloatKick;
330    
331                            if (this.ticksForFloatKick > 80)
332                            {
333                                logger.warning(this.playerEntity.username + " was kicked for floating too long!");
334                                this.kickPlayerFromServer("Flying is not enabled on this server");
335                                return;
336                            }
337                        }
338                    }
339                    else
340                    {
341                        this.ticksForFloatKick = 0;
342                    }
343    
344                    this.playerEntity.onGround = par1Packet10Flying.onGround;
345                    this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
346                    this.playerEntity.updateFlyingState(this.playerEntity.posY - var3, par1Packet10Flying.onGround);
347                }
348            }
349        }
350    
351        /**
352         * Moves the player to the specified destination and rotation
353         */
354        public void setPlayerLocation(double par1, double par3, double par5, float par7, float par8)
355        {
356            this.hasMoved = false;
357            this.lastPosX = par1;
358            this.lastPosY = par3;
359            this.lastPosZ = par5;
360            this.playerEntity.setPositionAndRotation(par1, par3, par5, par7, par8);
361            this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet13PlayerLookMove(par1, par3 + 1.6200000047683716D, par3, par5, par7, par8, false));
362        }
363    
364        public void handleBlockDig(Packet14BlockDig par1Packet14BlockDig)
365        {
366            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
367    
368            if (par1Packet14BlockDig.status == 4)
369            {
370                this.playerEntity.dropOneItem();
371            }
372            else if (par1Packet14BlockDig.status == 5)
373            {
374                this.playerEntity.stopUsingItem();
375            }
376            else
377            {
378                boolean var3 = var2.actionsAllowed = var2.provider.dimensionId != 0 || this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username) || this.mcServer.isSinglePlayer();
379                boolean var4 = false;
380    
381                if (par1Packet14BlockDig.status == 0)
382                {
383                    var4 = true;
384                }
385    
386                if (par1Packet14BlockDig.status == 2)
387                {
388                    var4 = true;
389                }
390    
391                int var5 = par1Packet14BlockDig.xPosition;
392                int var6 = par1Packet14BlockDig.yPosition;
393                int var7 = par1Packet14BlockDig.zPosition;
394    
395                if (var4)
396                {
397                    double var8 = this.playerEntity.posX - ((double)var5 + 0.5D);
398                    double var10 = this.playerEntity.posY - ((double)var6 + 0.5D) + 1.5D;
399                    double var12 = this.playerEntity.posZ - ((double)var7 + 0.5D);
400                    double var14 = var8 * var8 + var10 * var10 + var12 * var12;
401    
402                    double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
403                    dist *= dist;
404    
405                    if (var14 > dist)
406                    {
407                        return;
408                    }
409    
410                    if (var6 >= this.mcServer.getBuildLimit())
411                    {
412                        return;
413                    }
414                }
415    
416                ChunkCoordinates var19 = var2.getSpawnPoint();
417                int var9 = MathHelper.abs_int(var5 - var19.posX);
418                int var20 = MathHelper.abs_int(var7 - var19.posZ);
419    
420                if (var9 > var20)
421                {
422                    var20 = var9;
423                }
424    
425                if (par1Packet14BlockDig.status == 0)
426                {
427                    if (var20 <= mcServer.spawnProtectionSize && !var3)
428                    {
429                        ForgeEventFactory.onPlayerInteract(playerEntity, Action.LEFT_CLICK_BLOCK, var5, var6, var7, 0);
430                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
431                    }
432                    else
433                    {
434                        this.playerEntity.theItemInWorldManager.onBlockClicked(var5, var6, var7, par1Packet14BlockDig.face);
435                    }
436                }
437                else if (par1Packet14BlockDig.status == 2)
438                {
439                    this.playerEntity.theItemInWorldManager.uncheckedTryHarvestBlock(var5, var6, var7);
440    
441                    if (var2.getBlockId(var5, var6, var7) != 0)
442                    {
443                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
444                    }
445                }
446                else if (par1Packet14BlockDig.status == 1)
447                {
448                    this.playerEntity.theItemInWorldManager.destroyBlockInWorldPartially(var5, var6, var7);
449    
450                    if (var2.getBlockId(var5, var6, var7) != 0)
451                    {
452                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
453                    }
454                }
455                else if (par1Packet14BlockDig.status == 3)
456                {
457                    double var11 = this.playerEntity.posX - ((double)var5 + 0.5D);
458                    double var13 = this.playerEntity.posY - ((double)var6 + 0.5D);
459                    double var15 = this.playerEntity.posZ - ((double)var7 + 0.5D);
460                    double var17 = var11 * var11 + var13 * var13 + var15 * var15;
461    
462                    if (var17 < 256.0D)
463                    {
464                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
465                    }
466                }
467    
468                var2.actionsAllowed = false;
469            }
470        }
471    
472        public void handlePlace(Packet15Place par1Packet15Place)
473        {
474            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
475            ItemStack var3 = this.playerEntity.inventory.getCurrentItem();
476            boolean var4 = false;
477            int var5 = par1Packet15Place.getXPosition();
478            int var6 = par1Packet15Place.getYPosition();
479            int var7 = par1Packet15Place.getZPosition();
480            int var8 = par1Packet15Place.getDirection();
481            boolean var9 = var2.actionsAllowed = var2.provider.dimensionId != 0 || this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username) || this.mcServer.isSinglePlayer();
482    
483            if (par1Packet15Place.getDirection() == 255)
484            {
485                if (var3 == null)
486                {
487                    return;
488                }
489    
490                PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(playerEntity, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, 0, 0, 0, -1);
491                if (event.useItem != Event.Result.DENY)
492                {
493                    this.playerEntity.theItemInWorldManager.tryUseItem(this.playerEntity, var2, var3);
494                }
495            }
496            else if (par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit() - 1 && (par1Packet15Place.getDirection() == 1 || par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit()))
497            {
498                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat("\u00a77Height limit for building is " + this.mcServer.getBuildLimit()));
499                var4 = true;
500            }
501            else
502            {
503                ChunkCoordinates var10 = var2.getSpawnPoint();
504                int var11 = MathHelper.abs_int(var5 - var10.posX);
505                int var12 = MathHelper.abs_int(var7 - var10.posZ);
506    
507                if (var11 > var12)
508                {
509                    var12 = var11;
510                }
511    
512                double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
513                dist *= dist;
514                if (this.hasMoved && this.playerEntity.getDistanceSq((double)var5 + 0.5D, (double)var6 + 0.5D, (double)var7 + 0.5D) < dist && (var12 > mcServer.spawnProtectionSize || var9))
515                {
516                    this.playerEntity.theItemInWorldManager.activateBlockOrUseItem(this.playerEntity, var2, var3, var5, var6, var7, var8, par1Packet15Place.getXOffset(), par1Packet15Place.getYOffset(), par1Packet15Place.getZOffset());
517                }
518    
519                var4 = true;
520            }
521    
522            if (var4)
523            {
524                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
525    
526                if (var8 == 0)
527                {
528                    --var6;
529                }
530    
531                if (var8 == 1)
532                {
533                    ++var6;
534                }
535    
536                if (var8 == 2)
537                {
538                    --var7;
539                }
540    
541                if (var8 == 3)
542                {
543                    ++var7;
544                }
545    
546                if (var8 == 4)
547                {
548                    --var5;
549                }
550    
551                if (var8 == 5)
552                {
553                    ++var5;
554                }
555    
556                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
557            }
558    
559            var3 = this.playerEntity.inventory.getCurrentItem();
560    
561            if (var3 != null && var3.stackSize == 0)
562            {
563                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = null;
564                var3 = null;
565            }
566    
567            if (var3 == null || var3.getMaxItemUseDuration() == 0)
568            {
569                this.playerEntity.playerInventoryBeingManipulated = true;
570                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = ItemStack.copyItemStack(this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem]);
571                Slot var13 = this.playerEntity.craftingInventory.getSlotFromInventory(this.playerEntity.inventory, this.playerEntity.inventory.currentItem);
572                this.playerEntity.craftingInventory.updateCraftingResults();
573                this.playerEntity.playerInventoryBeingManipulated = false;
574    
575                if (!ItemStack.areItemStacksEqual(this.playerEntity.inventory.getCurrentItem(), par1Packet15Place.getItemStack()))
576                {
577                    this.sendPacketToPlayer(new Packet103SetSlot(this.playerEntity.craftingInventory.windowId, var13.slotNumber, this.playerEntity.inventory.getCurrentItem()));
578                }
579            }
580    
581            var2.actionsAllowed = false;
582        }
583    
584        public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj)
585        {
586            logger.info(this.playerEntity.username + " lost connection: " + par1Str);
587            this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + this.playerEntity.username + " left the game."));
588            this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
589            this.connectionClosed = true;
590    
591            if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
592            {
593                logger.info("Stopping singleplayer server as player logged out");
594                this.mcServer.initiateShutdown();
595            }
596        }
597    
598        /**
599         * Default handler called for packets that don't have their own handlers in NetClientHandler; currentlly does
600         * nothing.
601         */
602        public void unexpectedPacket(Packet par1Packet)
603        {
604            logger.warning(this.getClass() + " wasn\'t prepared to deal with a " + par1Packet.getClass());
605            this.kickPlayerFromServer("Protocol error, unexpected packet");
606        }
607    
608        /**
609         * addToSendQueue. if it is a chat packet, check before sending it
610         */
611        public void sendPacketToPlayer(Packet par1Packet)
612        {
613            if (par1Packet instanceof Packet3Chat)
614            {
615                Packet3Chat var2 = (Packet3Chat)par1Packet;
616                int var3 = this.playerEntity.getChatVisibility();
617    
618                if (var3 == 2)
619                {
620                    return;
621                }
622    
623                if (var3 == 1 && !var2.func_73475_d())
624                {
625                    return;
626                }
627            }
628    
629            this.netManager.addToSendQueue(par1Packet);
630        }
631    
632        public void handleBlockItemSwitch(Packet16BlockItemSwitch par1Packet16BlockItemSwitch)
633        {
634            if (par1Packet16BlockItemSwitch.id >= 0 && par1Packet16BlockItemSwitch.id < InventoryPlayer.func_70451_h())
635            {
636                this.playerEntity.inventory.currentItem = par1Packet16BlockItemSwitch.id;
637            }
638            else
639            {
640                logger.warning(this.playerEntity.username + " tried to set an invalid carried item");
641            }
642        }
643    
644        public void handleChat(Packet3Chat par1Packet3Chat)
645        {
646            par1Packet3Chat = FMLNetworkHandler.handleChatMessage(this, par1Packet3Chat);
647            if (this.playerEntity.getChatVisibility() == 2)
648            {
649                this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
650            }
651            else
652            {
653                String var2 = par1Packet3Chat.message;
654    
655                if (var2.length() > 100)
656                {
657                    this.kickPlayerFromServer("Chat message too long");
658                }
659                else
660                {
661                    var2 = var2.trim();
662    
663                    for (int var3 = 0; var3 < var2.length(); ++var3)
664                    {
665                        if (!ChatAllowedCharacters.isAllowedCharacter(var2.charAt(var3)))
666                        {
667                            this.kickPlayerFromServer("Illegal characters in chat");
668                            return;
669                        }
670                    }
671    
672                    if (var2.startsWith("/"))
673                    {
674                        this.handleSlashCommand(var2);
675                    }
676                    else
677                    {
678                        if (this.playerEntity.getChatVisibility() == 1)
679                        {
680                            this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
681                            return;
682                        }
683    
684                        var2 = "<" + this.playerEntity.username + "> " + var2;
685                        logger.info(var2);
686                        this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(var2, false));
687                    }
688    
689                    this.chatSpamThresholdCount += 20;
690    
691                    if (this.chatSpamThresholdCount > 200 && !this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username))
692                    {
693                        this.kickPlayerFromServer("disconnect.spam");
694                    }
695                }
696            }
697        }
698    
699        /**
700         * Processes a / command
701         */
702        private void handleSlashCommand(String par1Str)
703        {
704            this.mcServer.getCommandManager().executeCommand(this.playerEntity, par1Str);
705        }
706    
707        public void handleAnimation(Packet18Animation par1Packet18Animation)
708        {
709            if (par1Packet18Animation.animate == 1)
710            {
711                this.playerEntity.swingItem();
712            }
713        }
714    
715        /**
716         * runs registerPacket on the given Packet19EntityAction
717         */
718        public void handleEntityAction(Packet19EntityAction par1Packet19EntityAction)
719        {
720            if (par1Packet19EntityAction.state == 1)
721            {
722                this.playerEntity.setSneaking(true);
723            }
724            else if (par1Packet19EntityAction.state == 2)
725            {
726                this.playerEntity.setSneaking(false);
727            }
728            else if (par1Packet19EntityAction.state == 4)
729            {
730                this.playerEntity.setSprinting(true);
731            }
732            else if (par1Packet19EntityAction.state == 5)
733            {
734                this.playerEntity.setSprinting(false);
735            }
736            else if (par1Packet19EntityAction.state == 3)
737            {
738                this.playerEntity.wakeUpPlayer(false, true, true);
739                this.hasMoved = false;
740            }
741        }
742    
743        public void handleKickDisconnect(Packet255KickDisconnect par1Packet255KickDisconnect)
744        {
745            this.netManager.networkShutdown("disconnect.quitting", new Object[0]);
746        }
747    
748        /**
749         * returns 0 for memoryMapped connections
750         */
751        public int packetSize()
752        {
753            return this.netManager.packetSize();
754        }
755    
756        public void handleUseEntity(Packet7UseEntity par1Packet7UseEntity)
757        {
758            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
759            Entity var3 = var2.getEntityByID(par1Packet7UseEntity.targetEntity);
760    
761            if (var3 != null)
762            {
763                boolean var4 = this.playerEntity.canEntityBeSeen(var3);
764                double var5 = 36.0D;
765    
766                if (!var4)
767                {
768                    var5 = 9.0D;
769                }
770    
771                if (this.playerEntity.getDistanceSqToEntity(var3) < var5)
772                {
773                    if (par1Packet7UseEntity.isLeftClick == 0)
774                    {
775                        this.playerEntity.interactWith(var3);
776                    }
777                    else if (par1Packet7UseEntity.isLeftClick == 1)
778                    {
779                        this.playerEntity.attackTargetEntityWithCurrentItem(var3);
780                    }
781                }
782            }
783        }
784    
785        public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand)
786        {
787            if (par1Packet205ClientCommand.forceRespawn == 1)
788            {
789                if (this.playerEntity.playerConqueredTheEnd)
790                {
791                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, 0, true);
792                }
793                else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled())
794                {
795                    if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
796                    {
797                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
798                        this.mcServer.deleteWorldAndStopServer();
799                    }
800                    else
801                    {
802                        BanEntry var2 = new BanEntry(this.playerEntity.username);
803                        var2.setBanReason("Death in Hardcore");
804                        this.mcServer.getConfigurationManager().getBannedPlayers().put(var2);
805                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
806                    }
807                }
808                else
809                {
810                    if (this.playerEntity.getHealth() > 0)
811                    {
812                        return;
813                    }
814    
815                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, playerEntity.dimension, false);
816                }
817            }
818        }
819    
820        /**
821         * packet.processPacket is only called if this returns true
822         */
823        public boolean canProcessPackets()
824        {
825            return true;
826        }
827    
828        /**
829         * respawns the player
830         */
831        public void handleRespawn(Packet9Respawn par1Packet9Respawn) {}
832    
833        public void handleCloseWindow(Packet101CloseWindow par1Packet101CloseWindow)
834        {
835            this.playerEntity.closeInventory();
836        }
837    
838        public void handleWindowClick(Packet102WindowClick par1Packet102WindowClick)
839        {
840            if (this.playerEntity.craftingInventory.windowId == par1Packet102WindowClick.window_Id && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
841            {
842                ItemStack var2 = this.playerEntity.craftingInventory.slotClick(par1Packet102WindowClick.inventorySlot, par1Packet102WindowClick.mouseClick, par1Packet102WindowClick.holdingShift, this.playerEntity);
843    
844                if (ItemStack.areItemStacksEqual(par1Packet102WindowClick.itemStack, var2))
845                {
846                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, true));
847                    this.playerEntity.playerInventoryBeingManipulated = true;
848                    this.playerEntity.craftingInventory.updateCraftingResults();
849                    this.playerEntity.sendInventoryToPlayer();
850                    this.playerEntity.playerInventoryBeingManipulated = false;
851                }
852                else
853                {
854                    this.field_72586_s.addKey(this.playerEntity.craftingInventory.windowId, Short.valueOf(par1Packet102WindowClick.action));
855                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, false));
856                    this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, false);
857                    ArrayList var3 = new ArrayList();
858    
859                    for (int var4 = 0; var4 < this.playerEntity.craftingInventory.inventorySlots.size(); ++var4)
860                    {
861                        var3.add(((Slot)this.playerEntity.craftingInventory.inventorySlots.get(var4)).getStack());
862                    }
863    
864                    this.playerEntity.sendContainerAndContentsToPlayer(this.playerEntity.craftingInventory, var3);
865                }
866            }
867        }
868    
869        public void handleEnchantItem(Packet108EnchantItem par1Packet108EnchantItem)
870        {
871            if (this.playerEntity.craftingInventory.windowId == par1Packet108EnchantItem.windowId && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
872            {
873                this.playerEntity.craftingInventory.enchantItem(this.playerEntity, par1Packet108EnchantItem.enchantment);
874                this.playerEntity.craftingInventory.updateCraftingResults();
875            }
876        }
877    
878        /**
879         * Handle a creative slot packet.
880         */
881        public void handleCreativeSetSlot(Packet107CreativeSetSlot par1Packet107CreativeSetSlot)
882        {
883            if (this.playerEntity.theItemInWorldManager.isCreative())
884            {
885                boolean var2 = par1Packet107CreativeSetSlot.slot < 0;
886                ItemStack var3 = par1Packet107CreativeSetSlot.itemStack;
887                boolean var4 = par1Packet107CreativeSetSlot.slot >= 1 && par1Packet107CreativeSetSlot.slot < 36 + InventoryPlayer.func_70451_h();
888                boolean var5 = var3 == null || var3.itemID < Item.itemsList.length && var3.itemID >= 0 && Item.itemsList[var3.itemID] != null;
889                boolean var6 = var3 == null || var3.getItemDamage() >= 0 && var3.getItemDamage() >= 0 && var3.stackSize <= 64 && var3.stackSize > 0;
890    
891                if (var4 && var5 && var6)
892                {
893                    if (var3 == null)
894                    {
895                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, (ItemStack)null);
896                    }
897                    else
898                    {
899                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, var3);
900                    }
901    
902                    this.playerEntity.inventorySlots.setPlayerIsPresent(this.playerEntity, true);
903                }
904                else if (var2 && var5 && var6 && this.creativeItemCreationSpamThresholdTally < 200)
905                {
906                    this.creativeItemCreationSpamThresholdTally += 20;
907                    EntityItem var7 = this.playerEntity.dropPlayerItem(var3);
908    
909                    if (var7 != null)
910                    {
911                        var7.func_70288_d();
912                    }
913                }
914            }
915        }
916    
917        public void handleTransaction(Packet106Transaction par1Packet106Transaction)
918        {
919            Short var2 = (Short)this.field_72586_s.lookup(this.playerEntity.craftingInventory.windowId);
920    
921            if (var2 != null && par1Packet106Transaction.shortWindowId == var2.shortValue() && this.playerEntity.craftingInventory.windowId == par1Packet106Transaction.windowId && !this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
922            {
923                this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, true);
924            }
925        }
926    
927        /**
928         * Updates Client side signs
929         */
930        public void handleUpdateSign(Packet130UpdateSign par1Packet130UpdateSign)
931        {
932            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
933    
934            if (var2.blockExists(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition))
935            {
936                TileEntity var3 = var2.getBlockTileEntity(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition);
937    
938                if (var3 instanceof TileEntitySign)
939                {
940                    TileEntitySign var4 = (TileEntitySign)var3;
941    
942                    if (!var4.isEditable())
943                    {
944                        this.mcServer.logWarning("Player " + this.playerEntity.username + " just tried to change non-editable sign");
945                        return;
946                    }
947                }
948    
949                int var6;
950                int var8;
951    
952                for (var8 = 0; var8 < 4; ++var8)
953                {
954                    boolean var5 = true;
955    
956                    if (par1Packet130UpdateSign.signLines[var8].length() > 15)
957                    {
958                        var5 = false;
959                    }
960                    else
961                    {
962                        for (var6 = 0; var6 < par1Packet130UpdateSign.signLines[var8].length(); ++var6)
963                        {
964                            if (ChatAllowedCharacters.allowedCharacters.indexOf(par1Packet130UpdateSign.signLines[var8].charAt(var6)) < 0)
965                            {
966                                var5 = false;
967                            }
968                        }
969                    }
970    
971                    if (!var5)
972                    {
973                        par1Packet130UpdateSign.signLines[var8] = "!?";
974                    }
975                }
976    
977                if (var3 instanceof TileEntitySign)
978                {
979                    var8 = par1Packet130UpdateSign.xPosition;
980                    int var9 = par1Packet130UpdateSign.yPosition;
981                    var6 = par1Packet130UpdateSign.zPosition;
982                    TileEntitySign var7 = (TileEntitySign)var3;
983                    System.arraycopy(par1Packet130UpdateSign.signLines, 0, var7.signText, 0, 4);
984                    var7.onInventoryChanged();
985                    var2.markBlockNeedsUpdate(var8, var9, var6);
986                }
987            }
988        }
989    
990        /**
991         * Handle a keep alive packet.
992         */
993        public void handleKeepAlive(Packet0KeepAlive par1Packet0KeepAlive)
994        {
995            if (par1Packet0KeepAlive.randomId == this.keepAliveRandomID)
996            {
997                int var2 = (int)(System.nanoTime() / 1000000L - this.keepAliveTimeSent);
998                this.playerEntity.ping = (this.playerEntity.ping * 3 + var2) / 4;
999            }
1000        }
1001    
1002        /**
1003         * determine if it is a server handler
1004         */
1005        public boolean isServerHandler()
1006        {
1007            return true;
1008        }
1009    
1010        /**
1011         * Handle a player abilities packet.
1012         */
1013        public void handlePlayerAbilities(Packet202PlayerAbilities par1Packet202PlayerAbilities)
1014        {
1015            this.playerEntity.capabilities.isFlying = par1Packet202PlayerAbilities.getFlying() && this.playerEntity.capabilities.allowFlying;
1016        }
1017    
1018        public void handleAutoComplete(Packet203AutoComplete par1Packet203AutoComplete)
1019        {
1020            StringBuilder var2 = new StringBuilder();
1021            String var4;
1022    
1023            for (Iterator var3 = this.mcServer.getPossibleCompletions(this.playerEntity, par1Packet203AutoComplete.getText()).iterator(); var3.hasNext(); var2.append(var4))
1024            {
1025                var4 = (String)var3.next();
1026    
1027                if (var2.length() > 0)
1028                {
1029                    var2.append("\u0000");
1030                }
1031            }
1032    
1033            this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet203AutoComplete(var2.toString()));
1034        }
1035    
1036        public void handleClientInfo(Packet204ClientInfo par1Packet204ClientInfo)
1037        {
1038            this.playerEntity.updateClientInfo(par1Packet204ClientInfo);
1039        }
1040    
1041        public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload)
1042        {
1043            FMLNetworkHandler.handlePacket250Packet(par1Packet250CustomPayload, netManager, this);
1044        }
1045    
1046        public void handleVanilla250Packet(Packet250CustomPayload par1Packet250CustomPayload)
1047        {
1048            DataInputStream var2;
1049            ItemStack var3;
1050            ItemStack var4;
1051    
1052            if ("MC|BEdit".equals(par1Packet250CustomPayload.channel))
1053            {
1054                try
1055                {
1056                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1057                    var3 = Packet.readItemStack(var2);
1058    
1059                    if (!ItemWritableBook.validBookTagPages(var3.getTagCompound()))
1060                    {
1061                        throw new IOException("Invalid book tag!");
1062                    }
1063    
1064                    var4 = this.playerEntity.inventory.getCurrentItem();
1065    
1066                    if (var3 != null && var3.itemID == Item.writableBook.shiftedIndex && var3.itemID == var4.itemID)
1067                    {
1068                        var4.setTagCompound(var3.getTagCompound());
1069                    }
1070                }
1071                catch (Exception var7)
1072                {
1073                    var7.printStackTrace();
1074                }
1075            }
1076            else if ("MC|BSign".equals(par1Packet250CustomPayload.channel))
1077            {
1078                try
1079                {
1080                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1081                    var3 = Packet.readItemStack(var2);
1082    
1083                    if (!ItemEditableBook.validBookTagContents(var3.getTagCompound()))
1084                    {
1085                        throw new IOException("Invalid book tag!");
1086                    }
1087    
1088                    var4 = this.playerEntity.inventory.getCurrentItem();
1089    
1090                    if (var3 != null && var3.itemID == Item.writtenBook.shiftedIndex && var4.itemID == Item.writableBook.shiftedIndex)
1091                    {
1092                        var4.setTagCompound(var3.getTagCompound());
1093                        var4.itemID = Item.writtenBook.shiftedIndex;
1094                    }
1095                }
1096                catch (Exception var6)
1097                {
1098                    var6.printStackTrace();
1099                }
1100            }
1101            else if ("MC|TrSel".equals(par1Packet250CustomPayload.channel))
1102            {
1103                try
1104                {
1105                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1106                    int var8 = var2.readInt();
1107                    Container var9 = this.playerEntity.craftingInventory;
1108    
1109                    if (var9 instanceof ContainerMerchant)
1110                    {
1111                        ((ContainerMerchant)var9).setCurrentRecipeIndex(var8);
1112                    }
1113                }
1114                catch (Exception var5)
1115                {
1116                    var5.printStackTrace();
1117                }
1118            }
1119        }
1120    
1121        @Override
1122    
1123        /**
1124         * Contains logic for handling packets containing arbitrary unique item data. Currently this is only for maps.
1125         */
1126        public void handleMapData(Packet131MapData par1Packet131MapData)
1127        {
1128            FMLNetworkHandler.handlePacket131Packet(this, par1Packet131MapData);
1129        }
1130    
1131        // modloader compat -- yuk!
1132        @Override
1133        public EntityPlayerMP getPlayer()
1134        {
1135            return playerEntity;
1136        }
1137    }