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 INetworkManager 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 par1, INetworkManager par2, EntityPlayerMP par3)
064        {
065            this.mcServer = par1;
066            this.netManager = par2;
067            par2.setNetHandler(this);
068            this.playerEntity = par3;
069            par3.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                        if (!this.hasMoved) //Fixes teleportation kick while riding entities
203                        {
204                            return;
205                        }
206    
207                        this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
208                        this.lastPosX = this.playerEntity.posX;
209                        this.lastPosY = this.playerEntity.posY;
210                        this.lastPosZ = this.playerEntity.posZ;
211                        var2.updateEntity(this.playerEntity);
212                        return;
213                    }
214    
215                    if (this.playerEntity.isPlayerSleeping())
216                    {
217                        this.playerEntity.onUpdateEntity();
218                        this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
219                        var2.updateEntity(this.playerEntity);
220                        return;
221                    }
222    
223                    var3 = this.playerEntity.posY;
224                    this.lastPosX = this.playerEntity.posX;
225                    this.lastPosY = this.playerEntity.posY;
226                    this.lastPosZ = this.playerEntity.posZ;
227                    var5 = this.playerEntity.posX;
228                    var7 = this.playerEntity.posY;
229                    var9 = this.playerEntity.posZ;
230                    float var11 = this.playerEntity.rotationYaw;
231                    float var12 = this.playerEntity.rotationPitch;
232    
233                    if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D && par1Packet10Flying.stance == -999.0D)
234                    {
235                        par1Packet10Flying.moving = false;
236                    }
237    
238                    if (par1Packet10Flying.moving)
239                    {
240                        var5 = par1Packet10Flying.xPosition;
241                        var7 = par1Packet10Flying.yPosition;
242                        var9 = par1Packet10Flying.zPosition;
243                        var13 = par1Packet10Flying.stance - par1Packet10Flying.yPosition;
244    
245                        if (!this.playerEntity.isPlayerSleeping() && (var13 > 1.65D || var13 < 0.1D))
246                        {
247                            this.kickPlayerFromServer("Illegal stance");
248                            logger.warning(this.playerEntity.username + " had an illegal stance: " + var13);
249                            return;
250                        }
251    
252                        if (Math.abs(par1Packet10Flying.xPosition) > 3.2E7D || Math.abs(par1Packet10Flying.zPosition) > 3.2E7D)
253                        {
254                            this.kickPlayerFromServer("Illegal position");
255                            return;
256                        }
257                    }
258    
259                    if (par1Packet10Flying.rotating)
260                    {
261                        var11 = par1Packet10Flying.yaw;
262                        var12 = par1Packet10Flying.pitch;
263                    }
264    
265                    this.playerEntity.onUpdateEntity();
266                    this.playerEntity.ySize = 0.0F;
267                    this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
268    
269                    if (!this.hasMoved)
270                    {
271                        return;
272                    }
273    
274                    var13 = var5 - this.playerEntity.posX;
275                    double var15 = var7 - this.playerEntity.posY;
276                    double var17 = var9 - this.playerEntity.posZ;
277                    double var19 = Math.min(Math.abs(var13), Math.abs(this.playerEntity.motionX));
278                    double var21 = Math.min(Math.abs(var15), Math.abs(this.playerEntity.motionY));
279                    double var23 = Math.min(Math.abs(var17), Math.abs(this.playerEntity.motionZ));
280                    double var25 = var19 * var19 + var21 * var21 + var23 * var23;
281    
282                    if (var25 > 100.0D && (!this.mcServer.isSinglePlayer() || !this.mcServer.getServerOwner().equals(this.playerEntity.username)))
283                    {
284                        logger.warning(this.playerEntity.username + " moved too quickly! " + var13 + "," + var15 + "," + var17 + " (" + var19 + ", " + var21 + ", " + var23 + ")");
285                        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
286                        return;
287                    }
288    
289                    float var27 = 0.0625F;
290                    boolean var28 = var2.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)var27, (double)var27, (double)var27)).isEmpty();
291    
292                    if (this.playerEntity.onGround && !par1Packet10Flying.onGround && var15 > 0.0D)
293                    {
294                        this.playerEntity.addExhaustion(0.2F);
295                    }
296    
297                    if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
298                    {
299                        return;
300                    }
301    
302                    this.playerEntity.moveEntity(var13, var15, var17);
303                    this.playerEntity.onGround = par1Packet10Flying.onGround;
304                    this.playerEntity.addMovementStat(var13, var15, var17);
305                    double var29 = var15;
306                    var13 = var5 - this.playerEntity.posX;
307                    var15 = var7 - this.playerEntity.posY;
308    
309                    if (var15 > -0.5D || var15 < 0.5D)
310                    {
311                        var15 = 0.0D;
312                    }
313    
314                    var17 = var9 - this.playerEntity.posZ;
315                    var25 = var13 * var13 + var15 * var15 + var17 * var17;
316                    boolean var31 = false;
317    
318                    if (var25 > 0.0625D && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.theItemInWorldManager.isCreative())
319                    {
320                        var31 = true;
321                        logger.warning(this.playerEntity.username + " moved wrongly!");
322                    }
323    
324                    if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
325                    {
326                        return;
327                    }
328    
329                    this.playerEntity.setPositionAndRotation(var5, var7, var9, var11, var12);
330                    boolean var32 = var2.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)var27, (double)var27, (double)var27)).isEmpty();
331    
332                    if (var28 && (var31 || !var32) && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.noClip)
333                    {
334                        this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
335                        return;
336                    }
337    
338                    AxisAlignedBB var33 = this.playerEntity.boundingBox.copy().expand((double)var27, (double)var27, (double)var27).addCoord(0.0D, -0.55D, 0.0D);
339    
340                    if (!this.mcServer.isFlightAllowed() && !this.playerEntity.theItemInWorldManager.isCreative() && !var2.isAABBNonEmpty(var33)  && !this.playerEntity.capabilities.allowFlying)
341                    {
342                        if (var29 >= -0.03125D)
343                        {
344                            ++this.ticksForFloatKick;
345    
346                            if (this.ticksForFloatKick > 80)
347                            {
348                                logger.warning(this.playerEntity.username + " was kicked for floating too long!");
349                                this.kickPlayerFromServer("Flying is not enabled on this server");
350                                return;
351                            }
352                        }
353                    }
354                    else
355                    {
356                        this.ticksForFloatKick = 0;
357                    }
358    
359                    if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
360                    {
361                        return;
362                    }
363    
364                    this.playerEntity.onGround = par1Packet10Flying.onGround;
365                    this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
366                    this.playerEntity.updateFlyingState(this.playerEntity.posY - var3, par1Packet10Flying.onGround);
367                }
368            }
369        }
370    
371        /**
372         * Moves the player to the specified destination and rotation
373         */
374        public void setPlayerLocation(double par1, double par3, double par5, float par7, float par8)
375        {
376            this.hasMoved = false;
377            this.lastPosX = par1;
378            this.lastPosY = par3;
379            this.lastPosZ = par5;
380            this.playerEntity.setPositionAndRotation(par1, par3, par5, par7, par8);
381            this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet13PlayerLookMove(par1, par3 + 1.6200000047683716D, par3, par5, par7, par8, false));
382        }
383    
384        public void handleBlockDig(Packet14BlockDig par1Packet14BlockDig)
385        {
386            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
387    
388            if (par1Packet14BlockDig.status == 4)
389            {
390                this.playerEntity.dropOneItem();
391            }
392            else if (par1Packet14BlockDig.status == 5)
393            {
394                this.playerEntity.stopUsingItem();
395            }
396            else
397            {
398                boolean var3 = var2.provider.dimensionId != 0 || this.mcServer.getConfigurationManager().getOps().isEmpty() || this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username) || this.mcServer.isSinglePlayer();
399                boolean var4 = false;
400    
401                if (par1Packet14BlockDig.status == 0)
402                {
403                    var4 = true;
404                }
405    
406                if (par1Packet14BlockDig.status == 2)
407                {
408                    var4 = true;
409                }
410    
411                int var5 = par1Packet14BlockDig.xPosition;
412                int var6 = par1Packet14BlockDig.yPosition;
413                int var7 = par1Packet14BlockDig.zPosition;
414    
415                if (var4)
416                {
417                    double var8 = this.playerEntity.posX - ((double)var5 + 0.5D);
418                    double var10 = this.playerEntity.posY - ((double)var6 + 0.5D) + 1.5D;
419                    double var12 = this.playerEntity.posZ - ((double)var7 + 0.5D);
420                    double var14 = var8 * var8 + var10 * var10 + var12 * var12;
421    
422                    double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
423                    dist *= dist;
424    
425                    if (var14 > dist)
426                    {
427                        return;
428                    }
429    
430                    if (var6 >= this.mcServer.getBuildLimit())
431                    {
432                        return;
433                    }
434                }
435    
436                ChunkCoordinates var19 = var2.getSpawnPoint();
437                int var9 = MathHelper.abs_int(var5 - var19.posX);
438                int var20 = MathHelper.abs_int(var7 - var19.posZ);
439    
440                if (var9 > var20)
441                {
442                    var20 = var9;
443                }
444    
445                if (par1Packet14BlockDig.status == 0)
446                {
447                    if (var20 <= this.mcServer.func_82357_ak() && !var3)
448                    {
449                        ForgeEventFactory.onPlayerInteract(playerEntity, Action.LEFT_CLICK_BLOCK, var5, var6, var7, 0);
450                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
451                    }
452                    else
453                    {
454                        this.playerEntity.theItemInWorldManager.onBlockClicked(var5, var6, var7, par1Packet14BlockDig.face);
455                    }
456                }
457                else if (par1Packet14BlockDig.status == 2)
458                {
459                    this.playerEntity.theItemInWorldManager.uncheckedTryHarvestBlock(var5, var6, var7);
460    
461                    if (var2.getBlockId(var5, var6, var7) != 0)
462                    {
463                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
464                    }
465                }
466                else if (par1Packet14BlockDig.status == 1)
467                {
468                    this.playerEntity.theItemInWorldManager.destroyBlockInWorldPartially(var5, var6, var7);
469    
470                    if (var2.getBlockId(var5, var6, var7) != 0)
471                    {
472                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
473                    }
474                }
475                else if (par1Packet14BlockDig.status == 3)
476                {
477                    double var11 = this.playerEntity.posX - ((double)var5 + 0.5D);
478                    double var13 = this.playerEntity.posY - ((double)var6 + 0.5D);
479                    double var15 = this.playerEntity.posZ - ((double)var7 + 0.5D);
480                    double var17 = var11 * var11 + var13 * var13 + var15 * var15;
481    
482                    if (var17 < 256.0D)
483                    {
484                        this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
485                    }
486                }
487            }
488        }
489    
490        public void handlePlace(Packet15Place par1Packet15Place)
491        {
492            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
493            ItemStack var3 = this.playerEntity.inventory.getCurrentItem();
494            boolean var4 = false;
495            int var5 = par1Packet15Place.getXPosition();
496            int var6 = par1Packet15Place.getYPosition();
497            int var7 = par1Packet15Place.getZPosition();
498            int var8 = par1Packet15Place.getDirection();
499            boolean var9 = var2.provider.dimensionId != 0 || this.mcServer.getConfigurationManager().getOps().isEmpty() || this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username) || this.mcServer.isSinglePlayer();
500    
501            if (par1Packet15Place.getDirection() == 255)
502            {
503                if (var3 == null)
504                {
505                    return;
506                }
507    
508                PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(playerEntity, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, 0, 0, 0, -1);
509                if (event.useItem != Event.Result.DENY)
510                {
511                    this.playerEntity.theItemInWorldManager.tryUseItem(this.playerEntity, var2, var3);
512                }
513            }
514            else if (par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit() - 1 && (par1Packet15Place.getDirection() == 1 || par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit()))
515            {
516                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat("\u00a77Height limit for building is " + this.mcServer.getBuildLimit()));
517                var4 = true;
518            }
519            else
520            {
521                ChunkCoordinates var10 = var2.getSpawnPoint();
522                int var11 = MathHelper.abs_int(var5 - var10.posX);
523                int var12 = MathHelper.abs_int(var7 - var10.posZ);
524    
525                if (var11 > var12)
526                {
527                    var12 = var11;
528                }
529    
530                double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
531                dist *= dist;
532                if (this.hasMoved && this.playerEntity.getDistanceSq((double)var5 + 0.5D, (double)var6 + 0.5D, (double)var7 + 0.5D) < dist && (var12 > this.mcServer.func_82357_ak() || var9))
533                {
534                    this.playerEntity.theItemInWorldManager.activateBlockOrUseItem(this.playerEntity, var2, var3, var5, var6, var7, var8, par1Packet15Place.getXOffset(), par1Packet15Place.getYOffset(), par1Packet15Place.getZOffset());
535                }
536    
537                var4 = true;
538            }
539    
540            if (var4)
541            {
542                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
543    
544                if (var8 == 0)
545                {
546                    --var6;
547                }
548    
549                if (var8 == 1)
550                {
551                    ++var6;
552                }
553    
554                if (var8 == 2)
555                {
556                    --var7;
557                }
558    
559                if (var8 == 3)
560                {
561                    ++var7;
562                }
563    
564                if (var8 == 4)
565                {
566                    --var5;
567                }
568    
569                if (var8 == 5)
570                {
571                    ++var5;
572                }
573    
574                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
575            }
576    
577            var3 = this.playerEntity.inventory.getCurrentItem();
578    
579            if (var3 != null && var3.stackSize == 0)
580            {
581                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = null;
582                var3 = null;
583            }
584    
585            if (var3 == null || var3.getMaxItemUseDuration() == 0)
586            {
587                this.playerEntity.playerInventoryBeingManipulated = true;
588                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = ItemStack.copyItemStack(this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem]);
589                Slot var13 = this.playerEntity.craftingInventory.getSlotFromInventory(this.playerEntity.inventory, this.playerEntity.inventory.currentItem);
590                this.playerEntity.craftingInventory.updateCraftingResults();
591                this.playerEntity.playerInventoryBeingManipulated = false;
592    
593                if (!ItemStack.areItemStacksEqual(this.playerEntity.inventory.getCurrentItem(), par1Packet15Place.getItemStack()))
594                {
595                    this.sendPacketToPlayer(new Packet103SetSlot(this.playerEntity.craftingInventory.windowId, var13.slotNumber, this.playerEntity.inventory.getCurrentItem()));
596                }
597            }
598        }
599    
600        public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj)
601        {
602            logger.info(this.playerEntity.username + " lost connection: " + par1Str);
603            this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + this.playerEntity.username + " left the game."));
604            this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
605            this.connectionClosed = true;
606    
607            if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
608            {
609                logger.info("Stopping singleplayer server as player logged out");
610                this.mcServer.initiateShutdown();
611            }
612        }
613    
614        /**
615         * Default handler called for packets that don't have their own handlers in NetClientHandler; currentlly does
616         * nothing.
617         */
618        public void unexpectedPacket(Packet par1Packet)
619        {
620            logger.warning(this.getClass() + " wasn\'t prepared to deal with a " + par1Packet.getClass());
621            this.kickPlayerFromServer("Protocol error, unexpected packet");
622        }
623    
624        /**
625         * addToSendQueue. if it is a chat packet, check before sending it
626         */
627        public void sendPacketToPlayer(Packet par1Packet)
628        {
629            if (par1Packet instanceof Packet3Chat)
630            {
631                Packet3Chat var2 = (Packet3Chat)par1Packet;
632                int var3 = this.playerEntity.getChatVisibility();
633    
634                if (var3 == 2)
635                {
636                    return;
637                }
638    
639                if (var3 == 1 && !var2.func_73475_d())
640                {
641                    return;
642                }
643            }
644    
645            this.netManager.addToSendQueue(par1Packet);
646        }
647    
648        public void handleBlockItemSwitch(Packet16BlockItemSwitch par1Packet16BlockItemSwitch)
649        {
650            if (par1Packet16BlockItemSwitch.id >= 0 && par1Packet16BlockItemSwitch.id < InventoryPlayer.func_70451_h())
651            {
652                this.playerEntity.inventory.currentItem = par1Packet16BlockItemSwitch.id;
653            }
654            else
655            {
656                logger.warning(this.playerEntity.username + " tried to set an invalid carried item");
657            }
658        }
659    
660        public void handleChat(Packet3Chat par1Packet3Chat)
661        {
662            par1Packet3Chat = FMLNetworkHandler.handleChatMessage(this, par1Packet3Chat);
663            if (this.playerEntity.getChatVisibility() == 2)
664            {
665                this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
666            }
667            else
668            {
669                String var2 = par1Packet3Chat.message;
670    
671                if (var2.length() > 100)
672                {
673                    this.kickPlayerFromServer("Chat message too long");
674                }
675                else
676                {
677                    var2 = var2.trim();
678    
679                    for (int var3 = 0; var3 < var2.length(); ++var3)
680                    {
681                        if (!ChatAllowedCharacters.isAllowedCharacter(var2.charAt(var3)))
682                        {
683                            this.kickPlayerFromServer("Illegal characters in chat");
684                            return;
685                        }
686                    }
687    
688                    if (var2.startsWith("/"))
689                    {
690                        this.handleSlashCommand(var2);
691                    }
692                    else
693                    {
694                        if (this.playerEntity.getChatVisibility() == 1)
695                        {
696                            this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
697                            return;
698                        }
699    
700                        var2 = "<" + this.playerEntity.username + "> " + var2;
701                        logger.info(var2);
702                        this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(var2, false));
703                    }
704    
705                    this.chatSpamThresholdCount += 20;
706    
707                    if (this.chatSpamThresholdCount > 200 && !this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username))
708                    {
709                        this.kickPlayerFromServer("disconnect.spam");
710                    }
711                }
712            }
713        }
714    
715        /**
716         * Processes a / command
717         */
718        private void handleSlashCommand(String par1Str)
719        {
720            this.mcServer.getCommandManager().executeCommand(this.playerEntity, par1Str);
721        }
722    
723        public void handleAnimation(Packet18Animation par1Packet18Animation)
724        {
725            if (par1Packet18Animation.animate == 1)
726            {
727                this.playerEntity.swingItem();
728            }
729        }
730    
731        /**
732         * runs registerPacket on the given Packet19EntityAction
733         */
734        public void handleEntityAction(Packet19EntityAction par1Packet19EntityAction)
735        {
736            if (par1Packet19EntityAction.state == 1)
737            {
738                this.playerEntity.setSneaking(true);
739            }
740            else if (par1Packet19EntityAction.state == 2)
741            {
742                this.playerEntity.setSneaking(false);
743            }
744            else if (par1Packet19EntityAction.state == 4)
745            {
746                this.playerEntity.setSprinting(true);
747            }
748            else if (par1Packet19EntityAction.state == 5)
749            {
750                this.playerEntity.setSprinting(false);
751            }
752            else if (par1Packet19EntityAction.state == 3)
753            {
754                this.playerEntity.wakeUpPlayer(false, true, true);
755                this.hasMoved = false;
756            }
757        }
758    
759        public void handleKickDisconnect(Packet255KickDisconnect par1Packet255KickDisconnect)
760        {
761            this.netManager.networkShutdown("disconnect.quitting", new Object[0]);
762        }
763    
764        /**
765         * returns 0 for memoryMapped connections
766         */
767        public int packetSize()
768        {
769            return this.netManager.packetSize();
770        }
771    
772        public void handleUseEntity(Packet7UseEntity par1Packet7UseEntity)
773        {
774            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
775            Entity var3 = var2.getEntityByID(par1Packet7UseEntity.targetEntity);
776    
777            if (var3 != null)
778            {
779                boolean var4 = this.playerEntity.canEntityBeSeen(var3);
780                double var5 = 36.0D;
781    
782                if (!var4)
783                {
784                    var5 = 9.0D;
785                }
786    
787                if (this.playerEntity.getDistanceSqToEntity(var3) < var5)
788                {
789                    if (par1Packet7UseEntity.isLeftClick == 0)
790                    {
791                        this.playerEntity.interactWith(var3);
792                    }
793                    else if (par1Packet7UseEntity.isLeftClick == 1)
794                    {
795                        this.playerEntity.attackTargetEntityWithCurrentItem(var3);
796                    }
797                }
798            }
799        }
800    
801        public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand)
802        {
803            if (par1Packet205ClientCommand.forceRespawn == 1)
804            {
805                if (this.playerEntity.playerConqueredTheEnd)
806                {
807                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, 0, true);
808                }
809                else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled())
810                {
811                    if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
812                    {
813                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
814                        this.mcServer.deleteWorldAndStopServer();
815                    }
816                    else
817                    {
818                        BanEntry var2 = new BanEntry(this.playerEntity.username);
819                        var2.setBanReason("Death in Hardcore");
820                        this.mcServer.getConfigurationManager().getBannedPlayers().put(var2);
821                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
822                    }
823                }
824                else
825                {
826                    if (this.playerEntity.getHealth() > 0)
827                    {
828                        return;
829                    }
830    
831                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, playerEntity.dimension, false);
832                }
833            }
834        }
835    
836        /**
837         * packet.processPacket is only called if this returns true
838         */
839        public boolean canProcessPackets()
840        {
841            return true;
842        }
843    
844        /**
845         * respawns the player
846         */
847        public void handleRespawn(Packet9Respawn par1Packet9Respawn) {}
848    
849        public void handleCloseWindow(Packet101CloseWindow par1Packet101CloseWindow)
850        {
851            this.playerEntity.closeInventory();
852        }
853    
854        public void handleWindowClick(Packet102WindowClick par1Packet102WindowClick)
855        {
856            if (this.playerEntity.craftingInventory.windowId == par1Packet102WindowClick.window_Id && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
857            {
858                ItemStack var2 = this.playerEntity.craftingInventory.slotClick(par1Packet102WindowClick.inventorySlot, par1Packet102WindowClick.mouseClick, par1Packet102WindowClick.holdingShift, this.playerEntity);
859    
860                if (ItemStack.areItemStacksEqual(par1Packet102WindowClick.itemStack, var2))
861                {
862                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, true));
863                    this.playerEntity.playerInventoryBeingManipulated = true;
864                    this.playerEntity.craftingInventory.updateCraftingResults();
865                    this.playerEntity.sendInventoryToPlayer();
866                    this.playerEntity.playerInventoryBeingManipulated = false;
867                }
868                else
869                {
870                    this.field_72586_s.addKey(this.playerEntity.craftingInventory.windowId, Short.valueOf(par1Packet102WindowClick.action));
871                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, false));
872                    this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, false);
873                    ArrayList var3 = new ArrayList();
874    
875                    for (int var4 = 0; var4 < this.playerEntity.craftingInventory.inventorySlots.size(); ++var4)
876                    {
877                        var3.add(((Slot)this.playerEntity.craftingInventory.inventorySlots.get(var4)).getStack());
878                    }
879    
880                    this.playerEntity.sendContainerAndContentsToPlayer(this.playerEntity.craftingInventory, var3);
881                }
882            }
883        }
884    
885        public void handleEnchantItem(Packet108EnchantItem par1Packet108EnchantItem)
886        {
887            if (this.playerEntity.craftingInventory.windowId == par1Packet108EnchantItem.windowId && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
888            {
889                this.playerEntity.craftingInventory.enchantItem(this.playerEntity, par1Packet108EnchantItem.enchantment);
890                this.playerEntity.craftingInventory.updateCraftingResults();
891            }
892        }
893    
894        /**
895         * Handle a creative slot packet.
896         */
897        public void handleCreativeSetSlot(Packet107CreativeSetSlot par1Packet107CreativeSetSlot)
898        {
899            if (this.playerEntity.theItemInWorldManager.isCreative())
900            {
901                boolean var2 = par1Packet107CreativeSetSlot.slot < 0;
902                ItemStack var3 = par1Packet107CreativeSetSlot.itemStack;
903                boolean var4 = par1Packet107CreativeSetSlot.slot >= 1 && par1Packet107CreativeSetSlot.slot < 36 + InventoryPlayer.func_70451_h();
904                boolean var5 = var3 == null || var3.itemID < Item.itemsList.length && var3.itemID >= 0 && Item.itemsList[var3.itemID] != null;
905                boolean var6 = var3 == null || var3.getItemDamage() >= 0 && var3.getItemDamage() >= 0 && var3.stackSize <= 64 && var3.stackSize > 0;
906    
907                if (var4 && var5 && var6)
908                {
909                    if (var3 == null)
910                    {
911                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, (ItemStack)null);
912                    }
913                    else
914                    {
915                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, var3);
916                    }
917    
918                    this.playerEntity.inventorySlots.setPlayerIsPresent(this.playerEntity, true);
919                }
920                else if (var2 && var5 && var6 && this.creativeItemCreationSpamThresholdTally < 200)
921                {
922                    this.creativeItemCreationSpamThresholdTally += 20;
923                    EntityItem var7 = this.playerEntity.dropPlayerItem(var3);
924    
925                    if (var7 != null)
926                    {
927                        var7.func_70288_d();
928                    }
929                }
930            }
931        }
932    
933        public void handleTransaction(Packet106Transaction par1Packet106Transaction)
934        {
935            Short var2 = (Short)this.field_72586_s.lookup(this.playerEntity.craftingInventory.windowId);
936    
937            if (var2 != null && par1Packet106Transaction.shortWindowId == var2.shortValue() && this.playerEntity.craftingInventory.windowId == par1Packet106Transaction.windowId && !this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
938            {
939                this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, true);
940            }
941        }
942    
943        /**
944         * Updates Client side signs
945         */
946        public void handleUpdateSign(Packet130UpdateSign par1Packet130UpdateSign)
947        {
948            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
949    
950            if (var2.blockExists(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition))
951            {
952                TileEntity var3 = var2.getBlockTileEntity(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition);
953    
954                if (var3 instanceof TileEntitySign)
955                {
956                    TileEntitySign var4 = (TileEntitySign)var3;
957    
958                    if (!var4.isEditable())
959                    {
960                        this.mcServer.logWarning("Player " + this.playerEntity.username + " just tried to change non-editable sign");
961                        return;
962                    }
963                }
964    
965                int var6;
966                int var8;
967    
968                for (var8 = 0; var8 < 4; ++var8)
969                {
970                    boolean var5 = true;
971    
972                    if (par1Packet130UpdateSign.signLines[var8].length() > 15)
973                    {
974                        var5 = false;
975                    }
976                    else
977                    {
978                        for (var6 = 0; var6 < par1Packet130UpdateSign.signLines[var8].length(); ++var6)
979                        {
980                            if (ChatAllowedCharacters.allowedCharacters.indexOf(par1Packet130UpdateSign.signLines[var8].charAt(var6)) < 0)
981                            {
982                                var5 = false;
983                            }
984                        }
985                    }
986    
987                    if (!var5)
988                    {
989                        par1Packet130UpdateSign.signLines[var8] = "!?";
990                    }
991                }
992    
993                if (var3 instanceof TileEntitySign)
994                {
995                    var8 = par1Packet130UpdateSign.xPosition;
996                    int var9 = par1Packet130UpdateSign.yPosition;
997                    var6 = par1Packet130UpdateSign.zPosition;
998                    TileEntitySign var7 = (TileEntitySign)var3;
999                    System.arraycopy(par1Packet130UpdateSign.signLines, 0, var7.signText, 0, 4);
1000                    var7.onInventoryChanged();
1001                    var2.markBlockNeedsUpdate(var8, var9, var6);
1002                }
1003            }
1004        }
1005    
1006        /**
1007         * Handle a keep alive packet.
1008         */
1009        public void handleKeepAlive(Packet0KeepAlive par1Packet0KeepAlive)
1010        {
1011            if (par1Packet0KeepAlive.randomId == this.keepAliveRandomID)
1012            {
1013                int var2 = (int)(System.nanoTime() / 1000000L - this.keepAliveTimeSent);
1014                this.playerEntity.ping = (this.playerEntity.ping * 3 + var2) / 4;
1015            }
1016        }
1017    
1018        /**
1019         * determine if it is a server handler
1020         */
1021        public boolean isServerHandler()
1022        {
1023            return true;
1024        }
1025    
1026        /**
1027         * Handle a player abilities packet.
1028         */
1029        public void handlePlayerAbilities(Packet202PlayerAbilities par1Packet202PlayerAbilities)
1030        {
1031            this.playerEntity.capabilities.isFlying = par1Packet202PlayerAbilities.getFlying() && this.playerEntity.capabilities.allowFlying;
1032        }
1033    
1034        public void handleAutoComplete(Packet203AutoComplete par1Packet203AutoComplete)
1035        {
1036            StringBuilder var2 = new StringBuilder();
1037            String var4;
1038    
1039            for (Iterator var3 = this.mcServer.getPossibleCompletions(this.playerEntity, par1Packet203AutoComplete.getText()).iterator(); var3.hasNext(); var2.append(var4))
1040            {
1041                var4 = (String)var3.next();
1042    
1043                if (var2.length() > 0)
1044                {
1045                    var2.append("\u0000");
1046                }
1047            }
1048    
1049            this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet203AutoComplete(var2.toString()));
1050        }
1051    
1052        public void handleClientInfo(Packet204ClientInfo par1Packet204ClientInfo)
1053        {
1054            this.playerEntity.updateClientInfo(par1Packet204ClientInfo);
1055        }
1056    
1057        public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload)
1058        {
1059            FMLNetworkHandler.handlePacket250Packet(par1Packet250CustomPayload, netManager, this);
1060        }
1061    
1062        public void handleVanilla250Packet(Packet250CustomPayload par1Packet250CustomPayload)
1063        {
1064            DataInputStream var2;
1065            ItemStack var3;
1066            ItemStack var4;
1067    
1068            if ("MC|BEdit".equals(par1Packet250CustomPayload.channel))
1069            {
1070                try
1071                {
1072                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1073                    var3 = Packet.readItemStack(var2);
1074    
1075                    if (!ItemWritableBook.validBookTagPages(var3.getTagCompound()))
1076                    {
1077                        throw new IOException("Invalid book tag!");
1078                    }
1079    
1080                    var4 = this.playerEntity.inventory.getCurrentItem();
1081    
1082                    if (var3 != null && var3.itemID == Item.writableBook.shiftedIndex && var3.itemID == var4.itemID)
1083                    {
1084                        var4.setTagCompound(var3.getTagCompound());
1085                    }
1086                }
1087                catch (Exception var12)
1088                {
1089                    var12.printStackTrace();
1090                }
1091            }
1092            else if ("MC|BSign".equals(par1Packet250CustomPayload.channel))
1093            {
1094                try
1095                {
1096                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1097                    var3 = Packet.readItemStack(var2);
1098    
1099                    if (!ItemEditableBook.validBookTagContents(var3.getTagCompound()))
1100                    {
1101                        throw new IOException("Invalid book tag!");
1102                    }
1103    
1104                    var4 = this.playerEntity.inventory.getCurrentItem();
1105    
1106                    if (var3 != null && var3.itemID == Item.writtenBook.shiftedIndex && var4.itemID == Item.writableBook.shiftedIndex)
1107                    {
1108                        var4.setTagCompound(var3.getTagCompound());
1109                        var4.itemID = Item.writtenBook.shiftedIndex;
1110                    }
1111                }
1112                catch (Exception var11)
1113                {
1114                    var11.printStackTrace();
1115                }
1116            }
1117            else
1118            {
1119                int var14;
1120    
1121                if ("MC|TrSel".equals(par1Packet250CustomPayload.channel))
1122                {
1123                    try
1124                    {
1125                        var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1126                        var14 = var2.readInt();
1127                        Container var15 = this.playerEntity.craftingInventory;
1128    
1129                        if (var15 instanceof ContainerMerchant)
1130                        {
1131                            ((ContainerMerchant)var15).setCurrentRecipeIndex(var14);
1132                        }
1133                    }
1134                    catch (Exception var10)
1135                    {
1136                        var10.printStackTrace();
1137                    }
1138                }
1139                else
1140                {
1141                    int var18;
1142    
1143                    if ("MC|AdvCdm".equals(par1Packet250CustomPayload.channel))
1144                    {
1145                        if (!this.mcServer.func_82356_Z())
1146                        {
1147                            this.playerEntity.sendChatToPlayer(this.playerEntity.translateString("advMode.notEnabled", new Object[0]));
1148                        }
1149                        else if (this.playerEntity.canCommandSenderUseCommand(2, "") && this.playerEntity.capabilities.isCreativeMode)
1150                        {
1151                            try
1152                            {
1153                                var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1154                                var14 = var2.readInt();
1155                                var18 = var2.readInt();
1156                                int var5 = var2.readInt();
1157                                String var6 = Packet.readString(var2, 256);
1158                                TileEntity var7 = this.playerEntity.worldObj.getBlockTileEntity(var14, var18, var5);
1159    
1160                                if (var7 != null && var7 instanceof TileEntityCommandBlock)
1161                                {
1162                                    ((TileEntityCommandBlock)var7).func_82352_b(var6);
1163                                    this.playerEntity.worldObj.markBlockNeedsUpdate(var14, var18, var5);
1164                                    this.playerEntity.sendChatToPlayer("Command set: " + var6);
1165                                }
1166                            }
1167                            catch (Exception var9)
1168                            {
1169                                var9.printStackTrace();
1170                            }
1171                        }
1172                        else
1173                        {
1174                            this.playerEntity.sendChatToPlayer(this.playerEntity.translateString("advMode.notAllowed", new Object[0]));
1175                        }
1176                    }
1177                    else if ("MC|Beacon".equals(par1Packet250CustomPayload.channel))
1178                    {
1179                        if (this.playerEntity.craftingInventory instanceof ContainerBeacon)
1180                        {
1181                            try
1182                            {
1183                                var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1184                                var14 = var2.readInt();
1185                                var18 = var2.readInt();
1186                                ContainerBeacon var17 = (ContainerBeacon)this.playerEntity.craftingInventory;
1187                                Slot var19 = var17.getSlot(0);
1188    
1189                                if (var19.getHasStack())
1190                                {
1191                                    var19.decrStackSize(1);
1192                                    TileEntityBeacon var20 = var17.func_82863_d();
1193                                    var20.func_82128_d(var14);
1194                                    var20.func_82127_e(var18);
1195                                    var20.onInventoryChanged();
1196                                }
1197                            }
1198                            catch (Exception var8)
1199                            {
1200                                var8.printStackTrace();
1201                            }
1202                        }
1203                    }
1204                    else if ("MC|ItemName".equals(par1Packet250CustomPayload.channel) && this.playerEntity.craftingInventory instanceof ContainerRepair)
1205                    {
1206                        ContainerRepair var13 = (ContainerRepair)this.playerEntity.craftingInventory;
1207    
1208                        if (par1Packet250CustomPayload.data != null && par1Packet250CustomPayload.data.length >= 1)
1209                        {
1210                            String var16 = ChatAllowedCharacters.filerAllowedCharacters(new String(par1Packet250CustomPayload.data));
1211    
1212                            if (var16.length() <= 30)
1213                            {
1214                                var13.func_82850_a(var16);
1215                            }
1216                        }
1217                        else
1218                        {
1219                            var13.func_82850_a("");
1220                        }
1221                    }
1222                }
1223            }
1224        }
1225    
1226        @Override
1227    
1228        /**
1229         * Contains logic for handling packets containing arbitrary unique item data. Currently this is only for maps.
1230         */
1231        public void handleMapData(Packet131MapData par1Packet131MapData)
1232        {
1233            FMLNetworkHandler.handlePacket131Packet(this, par1Packet131MapData);
1234        }
1235    
1236        // modloader compat -- yuk!
1237        @Override
1238        public EntityPlayerMP getPlayer()
1239        {
1240            return playerEntity;
1241        }
1242    }