    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}