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 trackMotion;
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.trackMotion = 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.ridingEntity == null)
092            {
093                ++this.ticksSinceLastForcedTeleport;
094    
095                if (this.ticks++ % this.updateFrequency == 0 || this.myEntity.isAirBorne)
096                {
097                    int var2 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
098                    int var3 = MathHelper.floor_double(this.myEntity.posY * 32.0D);
099                    int var4 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
100                    int var5 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
101                    int var6 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
102                    int var7 = var2 - this.lastScaledXPosition;
103                    int var8 = var3 - this.lastScaledYPosition;
104                    int var9 = var4 - this.lastScaledZPosition;
105                    Object var10 = null;
106                    boolean var11 = Math.abs(var7) >= 4 || Math.abs(var8) >= 4 || Math.abs(var9) >= 4;
107                    boolean var12 = Math.abs(var5 - this.lastYaw) >= 4 || Math.abs(var6 - this.lastPitch) >= 4;
108    
109                    if (var7 >= -128 && var7 < 128 && var8 >= -128 && var8 < 128 && var9 >= -128 && var9 < 128 && this.ticksSinceLastForcedTeleport <= 400)
110                    {
111                        if (var11 && var12)
112                        {
113                            var10 = new Packet33RelEntityMoveLook(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9, (byte)var5, (byte)var6);
114                        }
115                        else if (var11)
116                        {
117                            var10 = new Packet31RelEntityMove(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9);
118                        }
119                        else if (var12)
120                        {
121                            var10 = new Packet32EntityLook(this.myEntity.entityId, (byte)var5, (byte)var6);
122                        }
123                    }
124                    else
125                    {
126                        this.ticksSinceLastForcedTeleport = 0;
127                        var10 = new Packet34EntityTeleport(this.myEntity.entityId, var2, var3, var4, (byte)var5, (byte)var6);
128                    }
129    
130                    if (this.trackMotion)
131                    {
132                        double var13 = this.myEntity.motionX - this.motionX;
133                        double var15 = this.myEntity.motionY - this.motionY;
134                        double var17 = this.myEntity.motionZ - this.motionZ;
135                        double var19 = 0.02D;
136                        double var21 = var13 * var13 + var15 * var15 + var17 * var17;
137    
138                        if (var21 > var19 * var19 || var21 > 0.0D && this.myEntity.motionX == 0.0D && this.myEntity.motionY == 0.0D && this.myEntity.motionZ == 0.0D)
139                        {
140                            this.motionX = this.myEntity.motionX;
141                            this.motionY = this.myEntity.motionY;
142                            this.motionZ = this.myEntity.motionZ;
143                            this.sendPacketToAllTrackingPlayers(new Packet28EntityVelocity(this.myEntity.entityId, this.motionX, this.motionY, this.motionZ));
144                        }
145                    }
146    
147                    if (var10 != null)
148                    {
149                        this.sendPacketToAllTrackingPlayers((Packet)var10);
150                    }
151    
152                    DataWatcher var23 = this.myEntity.getDataWatcher();
153    
154                    if (var23.hasChanges())
155                    {
156                        this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var23));
157                    }
158    
159                    int var14 = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
160    
161                    if (Math.abs(var14 - this.lastHeadMotion) >= 4)
162                    {
163                        this.sendPacketToAllTrackingPlayers(new Packet35EntityHeadRotation(this.myEntity.entityId, (byte)var14));
164                        this.lastHeadMotion = var14;
165                    }
166    
167                    if (var11)
168                    {
169                        this.lastScaledXPosition = var2;
170                        this.lastScaledYPosition = var3;
171                        this.lastScaledZPosition = var4;
172                    }
173    
174                    if (var12)
175                    {
176                        this.lastYaw = var5;
177                        this.lastPitch = var6;
178                    }
179                }
180    
181                this.myEntity.isAirBorne = false;
182            }
183    
184            if (this.myEntity.velocityChanged)
185            {
186                this.sendPacketToAllAssociatedPlayers(new Packet28EntityVelocity(this.myEntity));
187                this.myEntity.velocityChanged = false;
188            }
189        }
190    
191        /**
192         * if this is a player, then it is not informed
193         */
194        public void sendPacketToAllTrackingPlayers(Packet par1Packet)
195        {
196            Iterator var2 = this.trackedPlayers.iterator();
197    
198            while (var2.hasNext())
199            {
200                EntityPlayerMP var3 = (EntityPlayerMP)var2.next();
201                var3.serverForThisPlayer.sendPacketToPlayer(par1Packet);
202            }
203        }
204    
205        /**
206         * if this is a player, then it recieves the message also
207         */
208        public void sendPacketToAllAssociatedPlayers(Packet par1Packet)
209        {
210            this.sendPacketToAllTrackingPlayers(par1Packet);
211    
212            if (this.myEntity instanceof EntityPlayerMP)
213            {
214                ((EntityPlayerMP)this.myEntity).serverForThisPlayer.sendPacketToPlayer(par1Packet);
215            }
216        }
217    
218        public void informAllAssociatedPlayersOfItemDestruction()
219        {
220            Iterator var1 = this.trackedPlayers.iterator();
221    
222            while (var1.hasNext())
223            {
224                EntityPlayerMP var2 = (EntityPlayerMP)var1.next();
225                var2.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
226            }
227        }
228    
229        public void removeFromWatchingList(EntityPlayerMP par1EntityPlayerMP)
230        {
231            if (this.trackedPlayers.contains(par1EntityPlayerMP))
232            {
233                this.trackedPlayers.remove(par1EntityPlayerMP);
234            }
235        }
236    
237        /**
238         * if the player is more than the distance threshold (typically 64) then the player is removed instead
239         */
240        public void tryStartWachingThis(EntityPlayerMP par1EntityPlayerMP)
241        {
242            if (par1EntityPlayerMP != this.myEntity)
243            {
244                double var2 = par1EntityPlayerMP.posX - (double)(this.lastScaledXPosition / 32);
245                double var4 = par1EntityPlayerMP.posZ - (double)(this.lastScaledZPosition / 32);
246    
247                if (var2 >= (double)(-this.BlocksDistanceThreshold) && var2 <= (double)this.BlocksDistanceThreshold && var4 >= (double)(-this.BlocksDistanceThreshold) && var4 <= (double)this.BlocksDistanceThreshold)
248                {
249                    if (!this.trackedPlayers.contains(par1EntityPlayerMP) && this.isPlayerWatchingThisChunk(par1EntityPlayerMP))
250                    {
251                        this.trackedPlayers.add(par1EntityPlayerMP);
252                        Packet var6 = this.getPacketForThisEntity();
253                        par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(var6);
254                        this.motionX = this.myEntity.motionX;
255                        this.motionY = this.myEntity.motionY;
256                        this.motionZ = this.myEntity.motionZ;
257    
258                        int posX = MathHelper.floor_double(this.motionX * 32.0D);
259                        int posY = MathHelper.floor_double(this.motionY * 32.0D);
260                        int posZ = MathHelper.floor_double(this.motionZ * 32.0D);
261                        if (posX != this.lastScaledXPosition || posY != this.lastScaledYPosition || posZ != this.lastScaledZPosition)
262                        {
263                            FMLNetworkHandler.makeEntitySpawnAdjustment(this.myEntity.entityId, par1EntityPlayerMP, this.lastScaledXPosition, this.lastScaledYPosition, this.lastScaledZPosition);
264                        }
265                        if (this.trackMotion && !(var6 instanceof Packet24MobSpawn))
266                        {
267                            par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(new Packet28EntityVelocity(this.myEntity.entityId, this.myEntity.motionX, this.myEntity.motionY, this.myEntity.motionZ));
268                        }
269    
270                        if (this.myEntity.ridingEntity != null)
271                        {
272                            par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
273                        }
274    
275                        ItemStack[] var7 = this.myEntity.getLastActiveItems();
276    
277                        if (var7 != null)
278                        {
279                            for (int var8 = 0; var8 < var7.length; ++var8)
280                            {
281                                par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(new Packet5PlayerInventory(this.myEntity.entityId, var8, var7[var8]));
282                            }
283                        }
284    
285                        if (this.myEntity instanceof EntityPlayer)
286                        {
287                            EntityPlayer var11 = (EntityPlayer)this.myEntity;
288    
289                            if (var11.isPlayerSleeping())
290                            {
291                                par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(new Packet17Sleep(this.myEntity, 0, MathHelper.floor_double(this.myEntity.posX), MathHelper.floor_double(this.myEntity.posY), MathHelper.floor_double(this.myEntity.posZ)));
292                            }
293                        }
294    
295                        if (this.myEntity instanceof EntityLiving)
296                        {
297                            EntityLiving var12 = (EntityLiving)this.myEntity;
298                            Iterator var9 = var12.getActivePotionEffects().iterator();
299    
300                            while (var9.hasNext())
301                            {
302                                PotionEffect var10 = (PotionEffect)var9.next();
303                                par1EntityPlayerMP.serverForThisPlayer.sendPacketToPlayer(new Packet41EntityEffect(this.myEntity.entityId, var10));
304                            }
305                        }
306                    }
307                }
308                else if (this.trackedPlayers.contains(par1EntityPlayerMP))
309                {
310                    this.trackedPlayers.remove(par1EntityPlayerMP);
311                    par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
312                }
313            }
314        }
315    
316        private boolean isPlayerWatchingThisChunk(EntityPlayerMP par1EntityPlayerMP)
317        {
318            return par1EntityPlayerMP.getServerForPlayer().getPlayerManager().isPlayerWatchingChunk(par1EntityPlayerMP, this.myEntity.chunkCoordX, this.myEntity.chunkCoordZ);
319        }
320    
321        public void sendEventsToPlayers(List par1List)
322        {
323            Iterator var2 = par1List.iterator();
324    
325            while (var2.hasNext())
326            {
327                EntityPlayer var3 = (EntityPlayer)var2.next();
328                this.tryStartWachingThis((EntityPlayerMP)var3);
329            }
330        }
331    
332        private Packet getPacketForThisEntity()
333        {
334            if (this.myEntity.isDead)
335            {
336                System.out.println("Fetching addPacket for removed entity");
337            }
338    
339            Packet pkt = FMLNetworkHandler.getEntitySpawningPacket(this.myEntity);
340            
341            if (pkt != null)
342            {
343                return pkt;
344            }
345            
346            if (this.myEntity instanceof EntityItem)
347            {
348                EntityItem var8 = (EntityItem)this.myEntity;
349                Packet21PickupSpawn var9 = new Packet21PickupSpawn(var8);
350                var8.posX = (double)var9.xPosition / 32.0D;
351                var8.posY = (double)var9.yPosition / 32.0D;
352                var8.posZ = (double)var9.zPosition / 32.0D;
353                return var9;
354            }
355            else if (this.myEntity instanceof EntityPlayerMP)
356            {
357                return new Packet20NamedEntitySpawn((EntityPlayer)this.myEntity);
358            }
359            else
360            {
361                if (this.myEntity instanceof EntityMinecart)
362                {
363                    EntityMinecart var1 = (EntityMinecart)this.myEntity;
364    
365                    if (var1.minecartType == 0)
366                    {
367                        return new Packet23VehicleSpawn(this.myEntity, 10);
368                    }
369    
370                    if (var1.minecartType == 1)
371                    {
372                        return new Packet23VehicleSpawn(this.myEntity, 11);
373                    }
374    
375                    if (var1.minecartType == 2)
376                    {
377                        return new Packet23VehicleSpawn(this.myEntity, 12);
378                    }
379                }
380    
381                if (this.myEntity instanceof EntityBoat)
382                {
383                    return new Packet23VehicleSpawn(this.myEntity, 1);
384                }
385                else if (!(this.myEntity instanceof IAnimals) && !(this.myEntity instanceof EntityDragon))
386                {
387                    if (this.myEntity instanceof EntityFishHook)
388                    {
389                        EntityPlayer var7 = ((EntityFishHook)this.myEntity).angler;
390                        return new Packet23VehicleSpawn(this.myEntity, 90, var7 != null ? var7.entityId : this.myEntity.entityId);
391                    }
392                    else if (this.myEntity instanceof EntityArrow)
393                    {
394                        Entity var6 = ((EntityArrow)this.myEntity).shootingEntity;
395                        return new Packet23VehicleSpawn(this.myEntity, 60, var6 != null ? var6.entityId : this.myEntity.entityId);
396                    }
397                    else if (this.myEntity instanceof EntitySnowball)
398                    {
399                        return new Packet23VehicleSpawn(this.myEntity, 61);
400                    }
401                    else if (this.myEntity instanceof EntityPotion)
402                    {
403                        return new Packet23VehicleSpawn(this.myEntity, 73, ((EntityPotion)this.myEntity).getPotionDamage());
404                    }
405                    else if (this.myEntity instanceof EntityExpBottle)
406                    {
407                        return new Packet23VehicleSpawn(this.myEntity, 75);
408                    }
409                    else if (this.myEntity instanceof EntityEnderPearl)
410                    {
411                        return new Packet23VehicleSpawn(this.myEntity, 65);
412                    }
413                    else if (this.myEntity instanceof EntityEnderEye)
414                    {
415                        return new Packet23VehicleSpawn(this.myEntity, 72);
416                    }
417                    else
418                    {
419                        Packet23VehicleSpawn var2;
420    
421                        if (this.myEntity instanceof EntitySmallFireball)
422                        {
423                            EntitySmallFireball var5 = (EntitySmallFireball)this.myEntity;
424                            var2 = null;
425    
426                            if (var5.shootingEntity != null)
427                            {
428                                var2 = new Packet23VehicleSpawn(this.myEntity, 64, var5.shootingEntity.entityId);
429                            }
430                            else
431                            {
432                                var2 = new Packet23VehicleSpawn(this.myEntity, 64, 0);
433                            }
434    
435                            var2.speedX = (int)(var5.accelerationX * 8000.0D);
436                            var2.speedY = (int)(var5.accelerationY * 8000.0D);
437                            var2.speedZ = (int)(var5.accelerationZ * 8000.0D);
438                            return var2;
439                        }
440                        else if (this.myEntity instanceof EntityFireball)
441                        {
442                            EntityFireball var4 = (EntityFireball)this.myEntity;
443                            var2 = null;
444    
445                            if (var4.shootingEntity != null)
446                            {
447                                var2 = new Packet23VehicleSpawn(this.myEntity, 63, ((EntityFireball)this.myEntity).shootingEntity.entityId);
448                            }
449                            else
450                            {
451                                var2 = new Packet23VehicleSpawn(this.myEntity, 63, 0);
452                            }
453    
454                            var2.speedX = (int)(var4.accelerationX * 8000.0D);
455                            var2.speedY = (int)(var4.accelerationY * 8000.0D);
456                            var2.speedZ = (int)(var4.accelerationZ * 8000.0D);
457                            return var2;
458                        }
459                        else if (this.myEntity instanceof EntityEgg)
460                        {
461                            return new Packet23VehicleSpawn(this.myEntity, 62);
462                        }
463                        else if (this.myEntity instanceof EntityTNTPrimed)
464                        {
465                            return new Packet23VehicleSpawn(this.myEntity, 50);
466                        }
467                        else if (this.myEntity instanceof EntityEnderCrystal)
468                        {
469                            return new Packet23VehicleSpawn(this.myEntity, 51);
470                        }
471                        else if (this.myEntity instanceof EntityFallingSand)
472                        {
473                            EntityFallingSand var3 = (EntityFallingSand)this.myEntity;
474                            return new Packet23VehicleSpawn(this.myEntity, 70, var3.blockID | var3.field_70285_b << 16);
475                        }
476                        else if (this.myEntity instanceof EntityPainting)
477                        {
478                            return new Packet25EntityPainting((EntityPainting)this.myEntity);
479                        }
480                        else if (this.myEntity instanceof EntityXPOrb)
481                        {
482                            return new Packet26EntityExpOrb((EntityXPOrb)this.myEntity);
483                        }
484                        else
485                        {
486                            throw new IllegalArgumentException("Don\'t know how to add " + this.myEntity.getClass() + "!");
487                        }
488                    }
489                }
490                else
491                {
492                    this.lastHeadMotion = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
493                    return new Packet24MobSpawn((EntityLiving)this.myEntity);
494                }
495            }
496        }
497    
498        public void removePlayerFromTracker(EntityPlayerMP par1EntityPlayerMP)
499        {
500            if (this.trackedPlayers.contains(par1EntityPlayerMP))
501            {
502                this.trackedPlayers.remove(par1EntityPlayerMP);
503                par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
504            }
505        }
506    }