001    package net.minecraft.src;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.DataInputStream;
005    import java.io.IOException;
006    import java.util.ArrayList;
007    import java.util.Iterator;
008    import java.util.Random;
009    import java.util.logging.Logger;
010    
011    import cpw.mods.fml.common.network.FMLNetworkHandler;
012    import net.minecraft.server.MinecraftServer;
013    import net.minecraftforge.event.Event;
014    import net.minecraftforge.event.ForgeEventFactory;
015    import net.minecraftforge.event.entity.player.PlayerInteractEvent;
016    import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
017    
018    public class NetServerHandler extends NetHandler
019    {
020        /** The logging system. */
021        public static Logger logger = Logger.getLogger("Minecraft");
022    
023        /** The underlying network manager for this server handler. */
024        public NetworkManager netManager;
025    
026        /** This is set to true whenever a player disconnects from the server. */
027        public boolean connectionClosed = false;
028    
029        /** Reference to the MinecraftServer object. */
030        private MinecraftServer mcServer;
031    
032        /** Reference to the EntityPlayerMP object. */
033        private EntityPlayerMP playerEntity;
034    
035        /** incremented each tick */
036        private int currentTicks;
037    
038        /**
039         * player is kicked if they float for over 80 ticks without flying enabled
040         */
041        public int ticksForFloatKick;
042        private boolean field_72584_h;
043        private int keepAliveRandomID;
044        private long keepAliveTimeSent;
045        private static Random randomGenerator = new Random();
046        private long ticksOfLastKeepAlive;
047        private int chatSpamThresholdCount = 0;
048        private int creativeItemCreationSpamThresholdTally = 0;
049    
050        /** The last known x position for this connection. */
051        private double lastPosX;
052    
053        /** The last known y position for this connection. */
054        private double lastPosY;
055    
056        /** The last known z position for this connection. */
057        private double lastPosZ;
058    
059        /** is true when the player has moved since his last movement packet */
060        private boolean hasMoved = true;
061        private IntHashMap field_72586_s = new IntHashMap();
062    
063        public NetServerHandler(MinecraftServer par1MinecraftServer, NetworkManager par2NetworkManager, EntityPlayerMP par3EntityPlayerMP)
064        {
065            this.mcServer = par1MinecraftServer;
066            this.netManager = par2NetworkManager;
067            par2NetworkManager.setNetHandler(this);
068            this.playerEntity = par3EntityPlayerMP;
069            par3EntityPlayerMP.playerNetServerHandler = this;
070        }
071    
072        /**
073         * run once each game tick
074         */
075        public void networkTick()
076        {
077            this.field_72584_h = false;
078            ++this.currentTicks;
079            this.mcServer.theProfiler.startSection("packetflow");
080            this.netManager.processReadPackets();
081            this.mcServer.theProfiler.endStartSection("keepAlive");
082    
083            if ((long)this.currentTicks - this.ticksOfLastKeepAlive > 20L)
084            {
085                this.ticksOfLastKeepAlive = (long)this.currentTicks;
086                this.keepAliveTimeSent = System.nanoTime() / 1000000L;
087                this.keepAliveRandomID = randomGenerator.nextInt();
088                this.sendPacketToPlayer(new Packet0KeepAlive(this.keepAliveRandomID));
089            }
090    
091            if (this.chatSpamThresholdCount > 0)
092            {
093                --this.chatSpamThresholdCount;
094            }
095    
096            if (this.creativeItemCreationSpamThresholdTally > 0)
097            {
098                --this.creativeItemCreationSpamThresholdTally;
099            }
100    
101            this.mcServer.theProfiler.endStartSection("playerTick");
102    
103            if (!this.field_72584_h && !this.playerEntity.playerConqueredTheEnd)
104            {
105                this.playerEntity.onUpdateEntity();
106    
107                if (this.playerEntity.ridingEntity == null)
108                {
109                    this.playerEntity.setLocationAndAngles(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
110                }
111            }
112    
113            this.mcServer.theProfiler.endSection();
114        }
115    
116        public void kickPlayerFromServer(String par1Str)
117        {
118            if (!this.connectionClosed)
119            {
120                this.playerEntity.mountEntityAndWakeUp();
121                this.sendPacketToPlayer(new Packet255KickDisconnect(par1Str));
122                this.netManager.serverShutdown();
123                this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + this.playerEntity.username + " left the game."));
124                this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
125                this.connectionClosed = true;
126            }
127        }
128    
129        public void handleFlying(Packet10Flying par1Packet10Flying)
130        {
131            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
132            this.field_72584_h = true;
133    
134            if (!this.playerEntity.playerConqueredTheEnd)
135            {
136                double var3;
137    
138                if (!this.hasMoved)
139                {
140                    var3 = par1Packet10Flying.yPosition - this.lastPosY;
141    
142                    if (par1Packet10Flying.xPosition == this.lastPosX && var3 * var3 < 0.01D && par1Packet10Flying.zPosition == this.lastPosZ)
143                    {
144                        this.hasMoved = true;
145                    }
146                }
147    
148                if (this.hasMoved)
149                {
150                    double var5;
151                    double var7;
152                    double var9;
153                    double var13;
154    
155                    if (this.playerEntity.ridingEntity != null)
156                    {
157                        float var34 = this.playerEntity.rotationYaw;
158                        float var4 = this.playerEntity.rotationPitch;
159                        this.playerEntity.ridingEntity.updateRiderPosition();
160                        var5 = this.playerEntity.posX;
161                        var7 = this.playerEntity.posY;
162                        var9 = this.playerEntity.posZ;
163                        double var35 = 0.0D;
164                        var13 = 0.0D;
165    
166                        if (par1Packet10Flying.rotating)
167                        {
168                            var34 = par1Packet10Flying.yaw;
169                            var4 = par1Packet10Flying.pitch;
170                        }
171    
172                        if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D && par1Packet10Flying.stance == -999.0D)
173                        {
174                            if (Math.abs(par1Packet10Flying.xPosition) > 1.0D || Math.abs(par1Packet10Flying.zPosition) > 1.0D)
175                            {
176                                System.err.println(this.playerEntity.username + " was caught trying to crash the server with an invalid position.");
177                                this.kickPlayerFromServer("Nope!");
178                                return;
179                            }
180    
181                            var35 = par1Packet10Flying.xPosition;
182                            var13 = par1Packet10Flying.zPosition;
183                        }
184    
185                        this.playerEntity.onGround = par1Packet10Flying.onGround;
186                        this.playerEntity.onUpdateEntity();
187                        this.playerEntity.moveEntity(var35, 0.0D, var13);
188                        this.playerEntity.setPositionAndRotation(var5, var7, var9, var34, var4);
189                        this.playerEntity.motionX = var35;
190                        this.playerEntity.motionZ = var13;
191    
192                        if (this.playerEntity.ridingEntity != null)
193                        {
194                            var2.uncheckedUpdateEntity(this.playerEntity.ridingEntity, true);
195                        }
196    
197                        if (this.playerEntity.ridingEntity != null)
198                        {
199                            this.playerEntity.ridingEntity.updateRiderPosition();
200                        }
201    
202                        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.actionsAllowed = var2.provider.dimensionId != 0 || 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 <= mcServer.spawnProtectionSize && !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                var2.actionsAllowed = false;
489            }
490        }
491    
492        public void handlePlace(Packet15Place par1Packet15Place)
493        {
494            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
495            ItemStack var3 = this.playerEntity.inventory.getCurrentItem();
496            boolean var4 = false;
497            int var5 = par1Packet15Place.getXPosition();
498            int var6 = par1Packet15Place.getYPosition();
499            int var7 = par1Packet15Place.getZPosition();
500            int var8 = par1Packet15Place.getDirection();
501            boolean var9 = var2.actionsAllowed = var2.provider.dimensionId != 0 || this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username) || this.mcServer.isSinglePlayer();
502    
503            if (par1Packet15Place.getDirection() == 255)
504            {
505                if (var3 == null)
506                {
507                    return;
508                }
509    
510                PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(playerEntity, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, 0, 0, 0, -1);
511                if (event.useItem != Event.Result.DENY)
512                {
513                    this.playerEntity.theItemInWorldManager.tryUseItem(this.playerEntity, var2, var3);
514                }
515            }
516            else if (par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit() - 1 && (par1Packet15Place.getDirection() == 1 || par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit()))
517            {
518                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat("\u00a77Height limit for building is " + this.mcServer.getBuildLimit()));
519                var4 = true;
520            }
521            else
522            {
523                ChunkCoordinates var10 = var2.getSpawnPoint();
524                int var11 = MathHelper.abs_int(var5 - var10.posX);
525                int var12 = MathHelper.abs_int(var7 - var10.posZ);
526    
527                if (var11 > var12)
528                {
529                    var12 = var11;
530                }
531    
532                double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
533                dist *= dist;
534                if (this.hasMoved && this.playerEntity.getDistanceSq((double)var5 + 0.5D, (double)var6 + 0.5D, (double)var7 + 0.5D) < dist && (var12 > mcServer.spawnProtectionSize || var9))
535                {
536                    this.playerEntity.theItemInWorldManager.activateBlockOrUseItem(this.playerEntity, var2, var3, var5, var6, var7, var8, par1Packet15Place.getXOffset(), par1Packet15Place.getYOffset(), par1Packet15Place.getZOffset());
537                }
538    
539                var4 = true;
540            }
541    
542            if (var4)
543            {
544                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
545    
546                if (var8 == 0)
547                {
548                    --var6;
549                }
550    
551                if (var8 == 1)
552                {
553                    ++var6;
554                }
555    
556                if (var8 == 2)
557                {
558                    --var7;
559                }
560    
561                if (var8 == 3)
562                {
563                    ++var7;
564                }
565    
566                if (var8 == 4)
567                {
568                    --var5;
569                }
570    
571                if (var8 == 5)
572                {
573                    ++var5;
574                }
575    
576                this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(var5, var6, var7, var2));
577            }
578    
579            var3 = this.playerEntity.inventory.getCurrentItem();
580    
581            if (var3 != null && var3.stackSize == 0)
582            {
583                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = null;
584                var3 = null;
585            }
586    
587            if (var3 == null || var3.getMaxItemUseDuration() == 0)
588            {
589                this.playerEntity.playerInventoryBeingManipulated = true;
590                this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = ItemStack.copyItemStack(this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem]);
591                Slot var13 = this.playerEntity.craftingInventory.getSlotFromInventory(this.playerEntity.inventory, this.playerEntity.inventory.currentItem);
592                this.playerEntity.craftingInventory.updateCraftingResults();
593                this.playerEntity.playerInventoryBeingManipulated = false;
594    
595                if (!ItemStack.areItemStacksEqual(this.playerEntity.inventory.getCurrentItem(), par1Packet15Place.getItemStack()))
596                {
597                    this.sendPacketToPlayer(new Packet103SetSlot(this.playerEntity.craftingInventory.windowId, var13.slotNumber, this.playerEntity.inventory.getCurrentItem()));
598                }
599            }
600    
601            var2.actionsAllowed = false;
602        }
603    
604        public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj)
605        {
606            logger.info(this.playerEntity.username + " lost connection: " + par1Str);
607            this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat("\u00a7e" + this.playerEntity.username + " left the game."));
608            this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
609            this.connectionClosed = true;
610    
611            if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
612            {
613                logger.info("Stopping singleplayer server as player logged out");
614                this.mcServer.initiateShutdown();
615            }
616        }
617    
618        /**
619         * Default handler called for packets that don't have their own handlers in NetClientHandler; currentlly does
620         * nothing.
621         */
622        public void unexpectedPacket(Packet par1Packet)
623        {
624            logger.warning(this.getClass() + " wasn\'t prepared to deal with a " + par1Packet.getClass());
625            this.kickPlayerFromServer("Protocol error, unexpected packet");
626        }
627    
628        /**
629         * addToSendQueue. if it is a chat packet, check before sending it
630         */
631        public void sendPacketToPlayer(Packet par1Packet)
632        {
633            if (par1Packet instanceof Packet3Chat)
634            {
635                Packet3Chat var2 = (Packet3Chat)par1Packet;
636                int var3 = this.playerEntity.getChatVisibility();
637    
638                if (var3 == 2)
639                {
640                    return;
641                }
642    
643                if (var3 == 1 && !var2.func_73475_d())
644                {
645                    return;
646                }
647            }
648    
649            this.netManager.addToSendQueue(par1Packet);
650        }
651    
652        public void handleBlockItemSwitch(Packet16BlockItemSwitch par1Packet16BlockItemSwitch)
653        {
654            if (par1Packet16BlockItemSwitch.id >= 0 && par1Packet16BlockItemSwitch.id < InventoryPlayer.func_70451_h())
655            {
656                this.playerEntity.inventory.currentItem = par1Packet16BlockItemSwitch.id;
657            }
658            else
659            {
660                logger.warning(this.playerEntity.username + " tried to set an invalid carried item");
661            }
662        }
663    
664        public void handleChat(Packet3Chat par1Packet3Chat)
665        {
666            par1Packet3Chat = FMLNetworkHandler.handleChatMessage(this, par1Packet3Chat);
667            if (this.playerEntity.getChatVisibility() == 2)
668            {
669                this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
670            }
671            else
672            {
673                String var2 = par1Packet3Chat.message;
674    
675                if (var2.length() > 100)
676                {
677                    this.kickPlayerFromServer("Chat message too long");
678                }
679                else
680                {
681                    var2 = var2.trim();
682    
683                    for (int var3 = 0; var3 < var2.length(); ++var3)
684                    {
685                        if (!ChatAllowedCharacters.isAllowedCharacter(var2.charAt(var3)))
686                        {
687                            this.kickPlayerFromServer("Illegal characters in chat");
688                            return;
689                        }
690                    }
691    
692                    if (var2.startsWith("/"))
693                    {
694                        this.handleSlashCommand(var2);
695                    }
696                    else
697                    {
698                        if (this.playerEntity.getChatVisibility() == 1)
699                        {
700                            this.sendPacketToPlayer(new Packet3Chat("Cannot send chat message."));
701                            return;
702                        }
703    
704                        var2 = "<" + this.playerEntity.username + "> " + var2;
705                        logger.info(var2);
706                        this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(var2, false));
707                    }
708    
709                    this.chatSpamThresholdCount += 20;
710    
711                    if (this.chatSpamThresholdCount > 200 && !this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username))
712                    {
713                        this.kickPlayerFromServer("disconnect.spam");
714                    }
715                }
716            }
717        }
718    
719        /**
720         * Processes a / command
721         */
722        private void handleSlashCommand(String par1Str)
723        {
724            this.mcServer.getCommandManager().executeCommand(this.playerEntity, par1Str);
725        }
726    
727        public void handleAnimation(Packet18Animation par1Packet18Animation)
728        {
729            if (par1Packet18Animation.animate == 1)
730            {
731                this.playerEntity.swingItem();
732            }
733        }
734    
735        /**
736         * runs registerPacket on the given Packet19EntityAction
737         */
738        public void handleEntityAction(Packet19EntityAction par1Packet19EntityAction)
739        {
740            if (par1Packet19EntityAction.state == 1)
741            {
742                this.playerEntity.setSneaking(true);
743            }
744            else if (par1Packet19EntityAction.state == 2)
745            {
746                this.playerEntity.setSneaking(false);
747            }
748            else if (par1Packet19EntityAction.state == 4)
749            {
750                this.playerEntity.setSprinting(true);
751            }
752            else if (par1Packet19EntityAction.state == 5)
753            {
754                this.playerEntity.setSprinting(false);
755            }
756            else if (par1Packet19EntityAction.state == 3)
757            {
758                this.playerEntity.wakeUpPlayer(false, true, true);
759                this.hasMoved = false;
760            }
761        }
762    
763        public void handleKickDisconnect(Packet255KickDisconnect par1Packet255KickDisconnect)
764        {
765            this.netManager.networkShutdown("disconnect.quitting", new Object[0]);
766        }
767    
768        /**
769         * returns 0 for memoryMapped connections
770         */
771        public int packetSize()
772        {
773            return this.netManager.packetSize();
774        }
775    
776        public void handleUseEntity(Packet7UseEntity par1Packet7UseEntity)
777        {
778            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
779            Entity var3 = var2.getEntityByID(par1Packet7UseEntity.targetEntity);
780    
781            if (var3 != null)
782            {
783                boolean var4 = this.playerEntity.canEntityBeSeen(var3);
784                double var5 = 36.0D;
785    
786                if (!var4)
787                {
788                    var5 = 9.0D;
789                }
790    
791                if (this.playerEntity.getDistanceSqToEntity(var3) < var5)
792                {
793                    if (par1Packet7UseEntity.isLeftClick == 0)
794                    {
795                        this.playerEntity.interactWith(var3);
796                    }
797                    else if (par1Packet7UseEntity.isLeftClick == 1)
798                    {
799                        this.playerEntity.attackTargetEntityWithCurrentItem(var3);
800                    }
801                }
802            }
803        }
804    
805        public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand)
806        {
807            if (par1Packet205ClientCommand.forceRespawn == 1)
808            {
809                if (this.playerEntity.playerConqueredTheEnd)
810                {
811                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, 0, true);
812                }
813                else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled())
814                {
815                    if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner()))
816                    {
817                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
818                        this.mcServer.deleteWorldAndStopServer();
819                    }
820                    else
821                    {
822                        BanEntry var2 = new BanEntry(this.playerEntity.username);
823                        var2.setBanReason("Death in Hardcore");
824                        this.mcServer.getConfigurationManager().getBannedPlayers().put(var2);
825                        this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
826                    }
827                }
828                else
829                {
830                    if (this.playerEntity.getHealth() > 0)
831                    {
832                        return;
833                    }
834    
835                    this.playerEntity = this.mcServer.getConfigurationManager().respawnPlayer(this.playerEntity, playerEntity.dimension, false);
836                }
837            }
838        }
839    
840        /**
841         * packet.processPacket is only called if this returns true
842         */
843        public boolean canProcessPackets()
844        {
845            return true;
846        }
847    
848        /**
849         * respawns the player
850         */
851        public void handleRespawn(Packet9Respawn par1Packet9Respawn) {}
852    
853        public void handleCloseWindow(Packet101CloseWindow par1Packet101CloseWindow)
854        {
855            this.playerEntity.closeInventory();
856        }
857    
858        public void handleWindowClick(Packet102WindowClick par1Packet102WindowClick)
859        {
860            if (this.playerEntity.craftingInventory.windowId == par1Packet102WindowClick.window_Id && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
861            {
862                ItemStack var2 = this.playerEntity.craftingInventory.slotClick(par1Packet102WindowClick.inventorySlot, par1Packet102WindowClick.mouseClick, par1Packet102WindowClick.holdingShift, this.playerEntity);
863    
864                if (ItemStack.areItemStacksEqual(par1Packet102WindowClick.itemStack, var2))
865                {
866                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, true));
867                    this.playerEntity.playerInventoryBeingManipulated = true;
868                    this.playerEntity.craftingInventory.updateCraftingResults();
869                    this.playerEntity.sendInventoryToPlayer();
870                    this.playerEntity.playerInventoryBeingManipulated = false;
871                }
872                else
873                {
874                    this.field_72586_s.addKey(this.playerEntity.craftingInventory.windowId, Short.valueOf(par1Packet102WindowClick.action));
875                    this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet106Transaction(par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, false));
876                    this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, false);
877                    ArrayList var3 = new ArrayList();
878    
879                    for (int var4 = 0; var4 < this.playerEntity.craftingInventory.inventorySlots.size(); ++var4)
880                    {
881                        var3.add(((Slot)this.playerEntity.craftingInventory.inventorySlots.get(var4)).getStack());
882                    }
883    
884                    this.playerEntity.sendContainerAndContentsToPlayer(this.playerEntity.craftingInventory, var3);
885                }
886            }
887        }
888    
889        public void handleEnchantItem(Packet108EnchantItem par1Packet108EnchantItem)
890        {
891            if (this.playerEntity.craftingInventory.windowId == par1Packet108EnchantItem.windowId && this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
892            {
893                this.playerEntity.craftingInventory.enchantItem(this.playerEntity, par1Packet108EnchantItem.enchantment);
894                this.playerEntity.craftingInventory.updateCraftingResults();
895            }
896        }
897    
898        /**
899         * Handle a creative slot packet.
900         */
901        public void handleCreativeSetSlot(Packet107CreativeSetSlot par1Packet107CreativeSetSlot)
902        {
903            if (this.playerEntity.theItemInWorldManager.isCreative())
904            {
905                boolean var2 = par1Packet107CreativeSetSlot.slot < 0;
906                ItemStack var3 = par1Packet107CreativeSetSlot.itemStack;
907                boolean var4 = par1Packet107CreativeSetSlot.slot >= 1 && par1Packet107CreativeSetSlot.slot < 36 + InventoryPlayer.func_70451_h();
908                boolean var5 = var3 == null || var3.itemID < Item.itemsList.length && var3.itemID >= 0 && Item.itemsList[var3.itemID] != null;
909                boolean var6 = var3 == null || var3.getItemDamage() >= 0 && var3.getItemDamage() >= 0 && var3.stackSize <= 64 && var3.stackSize > 0;
910    
911                if (var4 && var5 && var6)
912                {
913                    if (var3 == null)
914                    {
915                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, (ItemStack)null);
916                    }
917                    else
918                    {
919                        this.playerEntity.inventorySlots.putStackInSlot(par1Packet107CreativeSetSlot.slot, var3);
920                    }
921    
922                    this.playerEntity.inventorySlots.setPlayerIsPresent(this.playerEntity, true);
923                }
924                else if (var2 && var5 && var6 && this.creativeItemCreationSpamThresholdTally < 200)
925                {
926                    this.creativeItemCreationSpamThresholdTally += 20;
927                    EntityItem var7 = this.playerEntity.dropPlayerItem(var3);
928    
929                    if (var7 != null)
930                    {
931                        var7.func_70288_d();
932                    }
933                }
934            }
935        }
936    
937        public void handleTransaction(Packet106Transaction par1Packet106Transaction)
938        {
939            Short var2 = (Short)this.field_72586_s.lookup(this.playerEntity.craftingInventory.windowId);
940    
941            if (var2 != null && par1Packet106Transaction.shortWindowId == var2.shortValue() && this.playerEntity.craftingInventory.windowId == par1Packet106Transaction.windowId && !this.playerEntity.craftingInventory.isPlayerNotUsingContainer(this.playerEntity))
942            {
943                this.playerEntity.craftingInventory.setPlayerIsPresent(this.playerEntity, true);
944            }
945        }
946    
947        /**
948         * Updates Client side signs
949         */
950        public void handleUpdateSign(Packet130UpdateSign par1Packet130UpdateSign)
951        {
952            WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
953    
954            if (var2.blockExists(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition))
955            {
956                TileEntity var3 = var2.getBlockTileEntity(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition);
957    
958                if (var3 instanceof TileEntitySign)
959                {
960                    TileEntitySign var4 = (TileEntitySign)var3;
961    
962                    if (!var4.isEditable())
963                    {
964                        this.mcServer.logWarning("Player " + this.playerEntity.username + " just tried to change non-editable sign");
965                        return;
966                    }
967                }
968    
969                int var6;
970                int var8;
971    
972                for (var8 = 0; var8 < 4; ++var8)
973                {
974                    boolean var5 = true;
975    
976                    if (par1Packet130UpdateSign.signLines[var8].length() > 15)
977                    {
978                        var5 = false;
979                    }
980                    else
981                    {
982                        for (var6 = 0; var6 < par1Packet130UpdateSign.signLines[var8].length(); ++var6)
983                        {
984                            if (ChatAllowedCharacters.allowedCharacters.indexOf(par1Packet130UpdateSign.signLines[var8].charAt(var6)) < 0)
985                            {
986                                var5 = false;
987                            }
988                        }
989                    }
990    
991                    if (!var5)
992                    {
993                        par1Packet130UpdateSign.signLines[var8] = "!?";
994                    }
995                }
996    
997                if (var3 instanceof TileEntitySign)
998                {
999                    var8 = par1Packet130UpdateSign.xPosition;
1000                    int var9 = par1Packet130UpdateSign.yPosition;
1001                    var6 = par1Packet130UpdateSign.zPosition;
1002                    TileEntitySign var7 = (TileEntitySign)var3;
1003                    System.arraycopy(par1Packet130UpdateSign.signLines, 0, var7.signText, 0, 4);
1004                    var7.onInventoryChanged();
1005                    var2.markBlockNeedsUpdate(var8, var9, var6);
1006                }
1007            }
1008        }
1009    
1010        /**
1011         * Handle a keep alive packet.
1012         */
1013        public void handleKeepAlive(Packet0KeepAlive par1Packet0KeepAlive)
1014        {
1015            if (par1Packet0KeepAlive.randomId == this.keepAliveRandomID)
1016            {
1017                int var2 = (int)(System.nanoTime() / 1000000L - this.keepAliveTimeSent);
1018                this.playerEntity.ping = (this.playerEntity.ping * 3 + var2) / 4;
1019            }
1020        }
1021    
1022        /**
1023         * determine if it is a server handler
1024         */
1025        public boolean isServerHandler()
1026        {
1027            return true;
1028        }
1029    
1030        /**
1031         * Handle a player abilities packet.
1032         */
1033        public void handlePlayerAbilities(Packet202PlayerAbilities par1Packet202PlayerAbilities)
1034        {
1035            this.playerEntity.capabilities.isFlying = par1Packet202PlayerAbilities.getFlying() && this.playerEntity.capabilities.allowFlying;
1036        }
1037    
1038        public void handleAutoComplete(Packet203AutoComplete par1Packet203AutoComplete)
1039        {
1040            StringBuilder var2 = new StringBuilder();
1041            String var4;
1042    
1043            for (Iterator var3 = this.mcServer.getPossibleCompletions(this.playerEntity, par1Packet203AutoComplete.getText()).iterator(); var3.hasNext(); var2.append(var4))
1044            {
1045                var4 = (String)var3.next();
1046    
1047                if (var2.length() > 0)
1048                {
1049                    var2.append("\u0000");
1050                }
1051            }
1052    
1053            this.playerEntity.playerNetServerHandler.sendPacketToPlayer(new Packet203AutoComplete(var2.toString()));
1054        }
1055    
1056        public void handleClientInfo(Packet204ClientInfo par1Packet204ClientInfo)
1057        {
1058            this.playerEntity.updateClientInfo(par1Packet204ClientInfo);
1059        }
1060    
1061        public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload)
1062        {
1063            FMLNetworkHandler.handlePacket250Packet(par1Packet250CustomPayload, netManager, this);
1064        }
1065    
1066        public void handleVanilla250Packet(Packet250CustomPayload par1Packet250CustomPayload)
1067        {
1068            DataInputStream var2;
1069            ItemStack var3;
1070            ItemStack var4;
1071    
1072            if ("MC|BEdit".equals(par1Packet250CustomPayload.channel))
1073            {
1074                try
1075                {
1076                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1077                    var3 = Packet.readItemStack(var2);
1078    
1079                    if (!ItemWritableBook.validBookTagPages(var3.getTagCompound()))
1080                    {
1081                        throw new IOException("Invalid book tag!");
1082                    }
1083    
1084                    var4 = this.playerEntity.inventory.getCurrentItem();
1085    
1086                    if (var3 != null && var3.itemID == Item.writableBook.shiftedIndex && var3.itemID == var4.itemID)
1087                    {
1088                        var4.setTagCompound(var3.getTagCompound());
1089                    }
1090                }
1091                catch (Exception var7)
1092                {
1093                    var7.printStackTrace();
1094                }
1095            }
1096            else if ("MC|BSign".equals(par1Packet250CustomPayload.channel))
1097            {
1098                try
1099                {
1100                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1101                    var3 = Packet.readItemStack(var2);
1102    
1103                    if (!ItemEditableBook.validBookTagContents(var3.getTagCompound()))
1104                    {
1105                        throw new IOException("Invalid book tag!");
1106                    }
1107    
1108                    var4 = this.playerEntity.inventory.getCurrentItem();
1109    
1110                    if (var3 != null && var3.itemID == Item.writtenBook.shiftedIndex && var4.itemID == Item.writableBook.shiftedIndex)
1111                    {
1112                        var4.setTagCompound(var3.getTagCompound());
1113                        var4.itemID = Item.writtenBook.shiftedIndex;
1114                    }
1115                }
1116                catch (Exception var6)
1117                {
1118                    var6.printStackTrace();
1119                }
1120            }
1121            else if ("MC|TrSel".equals(par1Packet250CustomPayload.channel))
1122            {
1123                try
1124                {
1125                    var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
1126                    int var8 = var2.readInt();
1127                    Container var9 = this.playerEntity.craftingInventory;
1128    
1129                    if (var9 instanceof ContainerMerchant)
1130                    {
1131                        ((ContainerMerchant)var9).setCurrentRecipeIndex(var8);
1132                    }
1133                }
1134                catch (Exception var5)
1135                {
1136                    var5.printStackTrace();
1137                }
1138            }
1139        }
1140    
1141        @Override
1142    
1143        /**
1144         * Contains logic for handling packets containing arbitrary unique item data. Currently this is only for maps.
1145         */
1146        public void handleMapData(Packet131MapData par1Packet131MapData)
1147        {
1148            FMLNetworkHandler.handlePacket131Packet(this, par1Packet131MapData);
1149        }
1150    
1151        // modloader compat -- yuk!
1152        @Override
1153        public EntityPlayerMP getPlayer()
1154        {
1155            return playerEntity;
1156        }
1157    }