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