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