    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.playerNetServerHandler.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).playerNetServerHandler.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.playerNetServerHandler.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.myEntity.posX * 32.0D);
    259                        int posY = MathHelper.floor_double(this.myEntity.posY * 32.0D);
    260                        int posZ = MathHelper.floor_double(this.myEntity.posZ * 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.playerNetServerHandler.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.playerNetServerHandler.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.playerNetServerHandler.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.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)));
    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.playerNetServerHandler.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    }