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