001    package net.minecraft.src;
002    
003    import java.util.HashSet;
004    import java.util.Iterator;
005    import java.util.List;
006    import java.util.Set;
007    
008    import cpw.mods.fml.common.network.FMLNetworkHandler;
009    
010    public class EntityTrackerEntry
011    {
012        public Entity myEntity;
013        public int BlocksDistanceThreshold;
014    
015        /** check for sync when ticks % updateFrequency==0 */
016        public int updateFrequency;
017        public int lastScaledXPosition;
018        public int lastScaledYPosition;
019        public int lastScaledZPosition;
020        public int lastYaw;
021        public int lastPitch;
022        public int lastHeadMotion;
023        public double motionX;
024        public double motionY;
025        public double motionZ;
026        public int ticks = 0;
027        private double posX;
028        private double posY;
029        private double posZ;
030    
031        /** set to true on first sendLocationToClients */
032        private boolean isDataInitialized = false;
033        private boolean sendVelocityUpdates;
034    
035        /**
036         * every 400 ticks a  full teleport packet is sent, rather than just a "move me +x" command, so that position
037         * remains fully synced.
038         */
039        private int ticksSinceLastForcedTeleport = 0;
040        private Entity field_85178_v;
041        private boolean ridingEntity = false;
042        public boolean playerEntitiesUpdated = false;
043        public Set trackedPlayers = new HashSet();
044    
045        public EntityTrackerEntry(Entity par1Entity, int par2, int par3, boolean par4)
046        {
047            this.myEntity = par1Entity;
048            this.BlocksDistanceThreshold = par2;
049            this.updateFrequency = par3;
050            this.sendVelocityUpdates = par4;
051            this.lastScaledXPosition = MathHelper.floor_double(par1Entity.posX * 32.0D);
052            this.lastScaledYPosition = MathHelper.floor_double(par1Entity.posY * 32.0D);
053            this.lastScaledZPosition = MathHelper.floor_double(par1Entity.posZ * 32.0D);
054            this.lastYaw = MathHelper.floor_float(par1Entity.rotationYaw * 256.0F / 360.0F);
055            this.lastPitch = MathHelper.floor_float(par1Entity.rotationPitch * 256.0F / 360.0F);
056            this.lastHeadMotion = MathHelper.floor_float(par1Entity.func_70079_am() * 256.0F / 360.0F);
057        }
058    
059        public boolean equals(Object par1Obj)
060        {
061            return par1Obj instanceof EntityTrackerEntry ? ((EntityTrackerEntry)par1Obj).myEntity.entityId == this.myEntity.entityId : false;
062        }
063    
064        public int hashCode()
065        {
066            return this.myEntity.entityId;
067        }
068    
069        /**
070         * also sends velocity, rotation, and riding info.
071         */
072        public void sendLocationToAllClients(List par1List)
073        {
074            this.playerEntitiesUpdated = false;
075    
076            if (!this.isDataInitialized || this.myEntity.getDistanceSq(this.posX, this.posY, this.posZ) > 16.0D)
077            {
078                this.posX = this.myEntity.posX;
079                this.posY = this.myEntity.posY;
080                this.posZ = this.myEntity.posZ;
081                this.isDataInitialized = true;
082                this.playerEntitiesUpdated = true;
083                this.sendEventsToPlayers(par1List);
084            }
085    
086            if (this.field_85178_v != this.myEntity.ridingEntity)
087            {
088                this.field_85178_v = this.myEntity.ridingEntity;
089                this.sendPacketToAllTrackingPlayers(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
090            }
091    
092            if (this.myEntity instanceof EntityItemFrame && this.ticks % 10 == 0)
093            {
094                EntityItemFrame var23 = (EntityItemFrame)this.myEntity;
095                ItemStack var24 = var23.func_82335_i();
096    
097                if (var24 != null && var24.getItem() instanceof ItemMap)
098                {
099                    MapData var26 = Item.map.getMapData(var24, this.myEntity.worldObj);
100                    Iterator var29 = par1List.iterator();
101    
102                    while (var29.hasNext())
103                    {
104                        EntityPlayer var30 = (EntityPlayer)var29.next();
105                        EntityPlayerMP var31 = (EntityPlayerMP)var30;
106                        var26.updateVisiblePlayers(var31, var24);
107    
108                        if (var31.playerNetServerHandler.packetSize() <= 5)
109                        {
110                            Packet var32 = Item.map.createMapDataPacket(var24, this.myEntity.worldObj, var31);
111    
112                            if (var32 != null)
113                            {
114                                var31.playerNetServerHandler.sendPacketToPlayer(var32);
115                            }
116                        }
117                    }
118                }
119    
120                DataWatcher var28 = this.myEntity.getDataWatcher();
121    
122                if (var28.hasChanges())
123                {
124                    this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var28, false));
125                }
126            }
127            else if (this.ticks++ % this.updateFrequency == 0 || this.myEntity.isAirBorne)
128            {
129                int var2;
130                int var3;
131    
132                if (this.myEntity.ridingEntity == null)
133                {
134                    ++this.ticksSinceLastForcedTeleport;
135                    var2 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
136                    var3 = MathHelper.floor_double(this.myEntity.posY * 32.0D);
137                    int var4 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
138                    int var5 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
139                    int var6 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
140                    int var7 = var2 - this.lastScaledXPosition;
141                    int var8 = var3 - this.lastScaledYPosition;
142                    int var9 = var4 - this.lastScaledZPosition;
143                    Object var10 = null;
144                    boolean var11 = Math.abs(var7) >= 4 || Math.abs(var8) >= 4 || Math.abs(var9) >= 4 || this.ticks % 60 == 0;
145                    boolean var12 = Math.abs(var5 - this.lastYaw) >= 4 || Math.abs(var6 - this.lastPitch) >= 4;
146    
147                    if (var7 >= -128 && var7 < 128 && var8 >= -128 && var8 < 128 && var9 >= -128 && var9 < 128 && this.ticksSinceLastForcedTeleport <= 400 && !this.ridingEntity)
148                    {
149                        if (var11 && var12)
150                        {
151                            var10 = new Packet33RelEntityMoveLook(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9, (byte)var5, (byte)var6);
152                        }
153                        else if (var11)
154                        {
155                            var10 = new Packet31RelEntityMove(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9);
156                        }
157                        else if (var12)
158                        {
159                            var10 = new Packet32EntityLook(this.myEntity.entityId, (byte)var5, (byte)var6);
160                        }
161                    }
162                    else
163                    {
164                        this.ticksSinceLastForcedTeleport = 0;
165                        var10 = new Packet34EntityTeleport(this.myEntity.entityId, var2, var3, var4, (byte)var5, (byte)var6);
166                    }
167    
168                    if (this.sendVelocityUpdates)
169                    {
170                        double var13 = this.myEntity.motionX - this.motionX;
171                        double var15 = this.myEntity.motionY - this.motionY;
172                        double var17 = this.myEntity.motionZ - this.motionZ;
173                        double var19 = 0.02D;
174                        double var21 = var13 * var13 + var15 * var15 + var17 * var17;
175    
176                        if (var21 > var19 * var19 || var21 > 0.0D && this.myEntity.motionX == 0.0D && this.myEntity.motionY == 0.0D && this.myEntity.motionZ == 0.0D)
177                        {
178                            this.motionX = this.myEntity.motionX;
179                            this.motionY = this.myEntity.motionY;
180                            this.motionZ = this.myEntity.motionZ;
181                            this.sendPacketToAllTrackingPlayers(new Packet28EntityVelocity(this.myEntity.entityId, this.motionX, this.motionY, this.motionZ));
182                        }
183                    }
184    
185                    if (var10 != null)
186                    {
187                        this.sendPacketToAllTrackingPlayers((Packet)var10);
188                    }
189    
190                    DataWatcher var33 = this.myEntity.getDataWatcher();
191    
192                    if (var33.hasChanges())
193                    {
194                        this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var33, false));
195                    }
196    
197                    if (var11)
198                    {
199                        this.lastScaledXPosition = var2;
200                        this.lastScaledYPosition = var3;
201                        this.lastScaledZPosition = var4;
202                    }
203    
204                    if (var12)
205                    {
206                        this.lastYaw = var5;
207                        this.lastPitch = var6;
208                    }
209    
210                    this.ridingEntity = false;
211                }
212                else
213                {
214                    var2 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
215                    var3 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
216                    boolean var25 = Math.abs(var2 - this.lastYaw) >= 4 || Math.abs(var3 - this.lastPitch) >= 4;
217    
218                    if (var25)
219                    {
220                        this.sendPacketToAllTrackingPlayers(new Packet32EntityLook(this.myEntity.entityId, (byte)var2, (byte)var3));
221                        this.lastYaw = var2;
222                        this.lastPitch = var3;
223                    }
224    
225                    this.lastScaledXPosition = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
226                    this.lastScaledYPosition = MathHelper.floor_double(this.myEntity.posY * 32.0D);
227                    this.lastScaledZPosition = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
228                    DataWatcher var27 = this.myEntity.getDataWatcher();
229    
230                    if (var27.hasChanges())
231                    {
232                        this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var27, false));
233                    }
234    
235                    this.ridingEntity = true;
236                }
237    
238                var2 = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
239    
240                if (Math.abs(var2 - this.lastHeadMotion) >= 4)
241                {
242                    this.sendPacketToAllTrackingPlayers(new Packet35EntityHeadRotation(this.myEntity.entityId, (byte)var2));
243                    this.lastHeadMotion = var2;
244                }
245    
246                this.myEntity.isAirBorne = false;
247            }
248    
249            if (this.myEntity.velocityChanged)
250            {
251                this.sendPacketToAllAssociatedPlayers(new Packet28EntityVelocity(this.myEntity));
252                this.myEntity.velocityChanged = false;
253            }
254        }
255    
256        /**
257         * if this is a player, then it is not informed
258         */
259        public void sendPacketToAllTrackingPlayers(Packet par1Packet)
260        {
261            Iterator var2 = this.trackedPlayers.iterator();
262    
263            while (var2.hasNext())
264            {
265                EntityPlayerMP var3 = (EntityPlayerMP)var2.next();
266                var3.playerNetServerHandler.sendPacketToPlayer(par1Packet);
267            }
268        }
269    
270        /**
271         * if this is a player, then it recieves the message also
272         */
273        public void sendPacketToAllAssociatedPlayers(Packet par1Packet)
274        {
275            this.sendPacketToAllTrackingPlayers(par1Packet);
276    
277            if (this.myEntity instanceof EntityPlayerMP)
278            {
279                ((EntityPlayerMP)this.myEntity).playerNetServerHandler.sendPacketToPlayer(par1Packet);
280            }
281        }
282    
283        public void informAllAssociatedPlayersOfItemDestruction()
284        {
285            Iterator var1 = this.trackedPlayers.iterator();
286    
287            while (var1.hasNext())
288            {
289                EntityPlayerMP var2 = (EntityPlayerMP)var1.next();
290                var2.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
291            }
292        }
293    
294        public void removeFromWatchingList(EntityPlayerMP par1EntityPlayerMP)
295        {
296            if (this.trackedPlayers.contains(par1EntityPlayerMP))
297            {
298                par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
299                this.trackedPlayers.remove(par1EntityPlayerMP);
300            }
301        }
302    
303        /**
304         * if the player is more than the distance threshold (typically 64) then the player is removed instead
305         */
306        public void tryStartWachingThis(EntityPlayerMP par1EntityPlayerMP)
307        {
308            if (par1EntityPlayerMP != this.myEntity)
309            {
310                double var2 = par1EntityPlayerMP.posX - (double)(this.lastScaledXPosition / 32);
311                double var4 = par1EntityPlayerMP.posZ - (double)(this.lastScaledZPosition / 32);
312    
313                if (var2 >= (double)(-this.BlocksDistanceThreshold) && var2 <= (double)this.BlocksDistanceThreshold && var4 >= (double)(-this.BlocksDistanceThreshold) && var4 <= (double)this.BlocksDistanceThreshold)
314                {
315                    if (!this.trackedPlayers.contains(par1EntityPlayerMP) && this.isPlayerWatchingThisChunk(par1EntityPlayerMP))
316                    {
317                        this.trackedPlayers.add(par1EntityPlayerMP);
318                        Packet var6 = this.getPacketForThisEntity();
319                        par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(var6);
320    
321                        if (this.myEntity instanceof EntityItemFrame)
322                        {
323                            par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet40EntityMetadata(this.myEntity.entityId, this.myEntity.getDataWatcher(), true));
324                        }
325    
326                        this.motionX = this.myEntity.motionX;
327                        this.motionY = this.myEntity.motionY;
328                        this.motionZ = this.myEntity.motionZ;
329    
330                        int posX = MathHelper.floor_double(this.myEntity.posX * 32.0D);
331                        int posY = MathHelper.floor_double(this.myEntity.posY * 32.0D);
332                        int posZ = MathHelper.floor_double(this.myEntity.posZ * 32.0D);
333                        if (posX != this.lastScaledXPosition || posY != this.lastScaledYPosition || posZ != this.lastScaledZPosition)
334                        {
335                            FMLNetworkHandler.makeEntitySpawnAdjustment(this.myEntity.entityId, par1EntityPlayerMP, this.lastScaledXPosition, this.lastScaledYPosition, this.lastScaledZPosition);
336                        }
337                        if (this.sendVelocityUpdates && !(var6 instanceof Packet24MobSpawn))
338                        {
339                            par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet28EntityVelocity(this.myEntity.entityId, this.myEntity.motionX, this.myEntity.motionY, this.myEntity.motionZ));
340                        }
341    
342                        if (this.myEntity.ridingEntity != null)
343                        {
344                            par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
345                        }
346    
347                        if (this.myEntity instanceof EntityLiving)
348                        {
349                            for (int var7 = 0; var7 < 5; ++var7)
350                            {
351                                ItemStack var8 = ((EntityLiving)this.myEntity).getCurrentItemOrArmor(var7);
352    
353                                if (var8 != null)
354                                {
355                                    par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet5PlayerInventory(this.myEntity.entityId, var7, var8));
356                                }
357                            }
358                        }
359    
360                        if (this.myEntity instanceof EntityPlayer)
361                        {
362                            EntityPlayer var11 = (EntityPlayer)this.myEntity;
363    
364                            if (var11.isPlayerSleeping())
365                            {
366                                par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet17Sleep(this.myEntity, 0, MathHelper.floor_double(this.myEntity.posX), MathHelper.floor_double(this.myEntity.posY), MathHelper.floor_double(this.myEntity.posZ)));
367                            }
368                        }
369    
370                        if (this.myEntity instanceof EntityLiving)
371                        {
372                            EntityLiving var10 = (EntityLiving)this.myEntity;
373                            Iterator var12 = var10.getActivePotionEffects().iterator();
374    
375                            while (var12.hasNext())
376                            {
377                                PotionEffect var9 = (PotionEffect)var12.next();
378                                par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.myEntity.entityId, var9));
379                            }
380                        }
381                    }
382                }
383                else if (this.trackedPlayers.contains(par1EntityPlayerMP))
384                {
385                    this.trackedPlayers.remove(par1EntityPlayerMP);
386                    par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
387                }
388            }
389        }
390    
391        private boolean isPlayerWatchingThisChunk(EntityPlayerMP par1EntityPlayerMP)
392        {
393            return par1EntityPlayerMP.getServerForPlayer().getPlayerManager().isPlayerWatchingChunk(par1EntityPlayerMP, this.myEntity.chunkCoordX, this.myEntity.chunkCoordZ);
394        }
395    
396        public void sendEventsToPlayers(List par1List)
397        {
398            for (int var2 = 0; var2 < par1List.size(); ++var2)
399            {
400                this.tryStartWachingThis((EntityPlayerMP)par1List.get(var2));
401            }
402        }
403    
404        private Packet getPacketForThisEntity()
405        {
406            if (this.myEntity.isDead)
407            {
408                System.out.println("Fetching addPacket for removed entity");
409            }
410    
411            Packet pkt = FMLNetworkHandler.getEntitySpawningPacket(this.myEntity);
412    
413            if (pkt != null)
414            {
415                return pkt;
416            }
417    
418            if (this.myEntity instanceof EntityItem)
419            {
420                EntityItem var9 = (EntityItem)this.myEntity;
421                Packet21PickupSpawn var10 = new Packet21PickupSpawn(var9);
422                var9.posX = (double)var10.xPosition / 32.0D;
423                var9.posY = (double)var10.yPosition / 32.0D;
424                var9.posZ = (double)var10.zPosition / 32.0D;
425                return var10;
426            }
427            else if (this.myEntity instanceof EntityPlayerMP)
428            {
429                return new Packet20NamedEntitySpawn((EntityPlayer)this.myEntity);
430            }
431            else
432            {
433                if (this.myEntity instanceof EntityMinecart)
434                {
435                    EntityMinecart var1 = (EntityMinecart)this.myEntity;
436    
437                    if (var1.minecartType == 0)
438                    {
439                        return new Packet23VehicleSpawn(this.myEntity, 10);
440                    }
441    
442                    if (var1.minecartType == 1)
443                    {
444                        return new Packet23VehicleSpawn(this.myEntity, 11);
445                    }
446    
447                    if (var1.minecartType == 2)
448                    {
449                        return new Packet23VehicleSpawn(this.myEntity, 12);
450                    }
451                }
452    
453                if (this.myEntity instanceof EntityBoat)
454                {
455                    return new Packet23VehicleSpawn(this.myEntity, 1);
456                }
457                else if (!(this.myEntity instanceof IAnimals) && !(this.myEntity instanceof EntityDragon))
458                {
459                    if (this.myEntity instanceof EntityFishHook)
460                    {
461                        EntityPlayer var8 = ((EntityFishHook)this.myEntity).angler;
462                        return new Packet23VehicleSpawn(this.myEntity, 90, var8 != null ? var8.entityId : this.myEntity.entityId);
463                    }
464                    else if (this.myEntity instanceof EntityArrow)
465                    {
466                        Entity var7 = ((EntityArrow)this.myEntity).shootingEntity;
467                        return new Packet23VehicleSpawn(this.myEntity, 60, var7 != null ? var7.entityId : this.myEntity.entityId);
468                    }
469                    else if (this.myEntity instanceof EntitySnowball)
470                    {
471                        return new Packet23VehicleSpawn(this.myEntity, 61);
472                    }
473                    else if (this.myEntity instanceof EntityPotion)
474                    {
475                        return new Packet23VehicleSpawn(this.myEntity, 73, ((EntityPotion)this.myEntity).getPotionDamage());
476                    }
477                    else if (this.myEntity instanceof EntityExpBottle)
478                    {
479                        return new Packet23VehicleSpawn(this.myEntity, 75);
480                    }
481                    else if (this.myEntity instanceof EntityEnderPearl)
482                    {
483                        return new Packet23VehicleSpawn(this.myEntity, 65);
484                    }
485                    else if (this.myEntity instanceof EntityEnderEye)
486                    {
487                        return new Packet23VehicleSpawn(this.myEntity, 72);
488                    }
489                    else
490                    {
491                        Packet23VehicleSpawn var2;
492    
493                        if (this.myEntity instanceof EntityFireball)
494                        {
495                            EntityFireball var6 = (EntityFireball)this.myEntity;
496                            var2 = null;
497                            byte var3 = 63;
498    
499                            if (this.myEntity instanceof EntitySmallFireball)
500                            {
501                                var3 = 64;
502                            }
503                            else if (this.myEntity instanceof EntityWitherSkull)
504                            {
505                                var3 = 66;
506                            }
507    
508                            if (var6.shootingEntity != null)
509                            {
510                                var2 = new Packet23VehicleSpawn(this.myEntity, var3, ((EntityFireball)this.myEntity).shootingEntity.entityId);
511                            }
512                            else
513                            {
514                                var2 = new Packet23VehicleSpawn(this.myEntity, var3, 0);
515                            }
516    
517                            var2.speedX = (int)(var6.accelerationX * 8000.0D);
518                            var2.speedY = (int)(var6.accelerationY * 8000.0D);
519                            var2.speedZ = (int)(var6.accelerationZ * 8000.0D);
520                            return var2;
521                        }
522                        else if (this.myEntity instanceof EntityEgg)
523                        {
524                            return new Packet23VehicleSpawn(this.myEntity, 62);
525                        }
526                        else if (this.myEntity instanceof EntityTNTPrimed)
527                        {
528                            return new Packet23VehicleSpawn(this.myEntity, 50);
529                        }
530                        else if (this.myEntity instanceof EntityEnderCrystal)
531                        {
532                            return new Packet23VehicleSpawn(this.myEntity, 51);
533                        }
534                        else if (this.myEntity instanceof EntityFallingSand)
535                        {
536                            EntityFallingSand var5 = (EntityFallingSand)this.myEntity;
537                            return new Packet23VehicleSpawn(this.myEntity, 70, var5.blockID | var5.field_70285_b << 16);
538                        }
539                        else if (this.myEntity instanceof EntityPainting)
540                        {
541                            return new Packet25EntityPainting((EntityPainting)this.myEntity);
542                        }
543                        else if (this.myEntity instanceof EntityItemFrame)
544                        {
545                            EntityItemFrame var4 = (EntityItemFrame)this.myEntity;
546                            var2 = new Packet23VehicleSpawn(this.myEntity, 71, var4.field_82332_a);
547                            var2.xPosition = MathHelper.floor_float((float)(var4.xPosition * 32));
548                            var2.yPosition = MathHelper.floor_float((float)(var4.yPosition * 32));
549                            var2.zPosition = MathHelper.floor_float((float)(var4.zPosition * 32));
550                            return var2;
551                        }
552                        else if (this.myEntity instanceof EntityXPOrb)
553                        {
554                            return new Packet26EntityExpOrb((EntityXPOrb)this.myEntity);
555                        }
556                        else
557                        {
558                            throw new IllegalArgumentException("Don\'t know how to add " + this.myEntity.getClass() + "!");
559                        }
560                    }
561                }
562                else
563                {
564                    this.lastHeadMotion = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
565                    return new Packet24MobSpawn((EntityLiving)this.myEntity);
566                }
567            }
568        }
569    
570        public void removePlayerFromTracker(EntityPlayerMP par1EntityPlayerMP)
571        {
572            if (this.trackedPlayers.contains(par1EntityPlayerMP))
573            {
574                this.trackedPlayers.remove(par1EntityPlayerMP);
575                par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
576            }
577        }
578    }