    001package net.minecraft.entity;
    002
    003import java.util.ArrayList;
    004import java.util.HashSet;
    005import java.util.Iterator;
    006import java.util.Set;
    007
    008import cpw.mods.fml.common.registry.EntityRegistry;
    009import net.minecraft.crash.CrashReport;
    010import net.minecraft.crash.CrashReportCategory;
    011import net.minecraft.entity.boss.EntityDragon;
    012import net.minecraft.entity.boss.EntityWither;
    013import net.minecraft.entity.item.EntityBoat;
    014import net.minecraft.entity.item.EntityEnderCrystal;
    015import net.minecraft.entity.item.EntityEnderEye;
    016import net.minecraft.entity.item.EntityEnderPearl;
    017import net.minecraft.entity.item.EntityExpBottle;
    018import net.minecraft.entity.item.EntityFallingSand;
    019import net.minecraft.entity.item.EntityFireworkRocket;
    020import net.minecraft.entity.item.EntityItem;
    021import net.minecraft.entity.item.EntityItemFrame;
    022import net.minecraft.entity.item.EntityMinecart;
    023import net.minecraft.entity.item.EntityPainting;
    024import net.minecraft.entity.item.EntityTNTPrimed;
    025import net.minecraft.entity.item.EntityXPOrb;
    026import net.minecraft.entity.passive.EntityBat;
    027import net.minecraft.entity.passive.EntitySquid;
    028import net.minecraft.entity.passive.IAnimals;
    029import net.minecraft.entity.player.EntityPlayerMP;
    030import net.minecraft.entity.projectile.EntityArrow;
    031import net.minecraft.entity.projectile.EntityEgg;
    032import net.minecraft.entity.projectile.EntityFireball;
    033import net.minecraft.entity.projectile.EntityFishHook;
    034import net.minecraft.entity.projectile.EntityPotion;
    035import net.minecraft.entity.projectile.EntitySmallFireball;
    036import net.minecraft.entity.projectile.EntitySnowball;
    037import net.minecraft.network.packet.Packet;
    038import net.minecraft.util.IntHashMap;
    039import net.minecraft.util.ReportedException;
    040import net.minecraft.world.WorldServer;
    041import net.minecraft.world.chunk.Chunk;
    042
    043public class EntityTracker
    044{
    045    private final WorldServer theWorld;
    046    private Set trackedEntities = new HashSet();
    047    private IntHashMap trackedEntityIDs = new IntHashMap();
    048    private int entityViewDistance;
    049
    050    public EntityTracker(WorldServer par1WorldServer)
    051    {
    052        this.theWorld = par1WorldServer;
    053        this.entityViewDistance = par1WorldServer.getMinecraftServer().getConfigurationManager().getEntityViewDistance();
    054    }
    055
    056    /**
    057     * if entity is a player sends all tracked events to the player, otherwise, adds with a visibility and update arate
    058     * based on the class type
    059     */
    060    public void addEntityToTracker(Entity par1Entity)
    061    {
    062        if (EntityRegistry.instance().tryTrackingEntity(this, par1Entity))
    063        {
    064            return;
    065        }
    066
    067        if (par1Entity instanceof EntityPlayerMP)
    068        {
    069            this.addEntityToTracker(par1Entity, 512, 2);
    070            EntityPlayerMP entityplayermp = (EntityPlayerMP)par1Entity;
    071            Iterator iterator = this.trackedEntities.iterator();
    072
    073            while (iterator.hasNext())
    074            {
    075                EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
    076
    077                if (entitytrackerentry.myEntity != entityplayermp)
    078                {
    079                    entitytrackerentry.tryStartWachingThis(entityplayermp);
    080                }
    081            }
    082        }
    083        else if (par1Entity instanceof EntityFishHook)
    084        {
    085            this.addEntityToTracker(par1Entity, 64, 5, true);
    086        }
    087        else if (par1Entity instanceof EntityArrow)
    088        {
    089            this.addEntityToTracker(par1Entity, 64, 20, false);
    090        }
    091        else if (par1Entity instanceof EntitySmallFireball)
    092        {
    093            this.addEntityToTracker(par1Entity, 64, 10, false);
    094        }
    095        else if (par1Entity instanceof EntityFireball)
    096        {
    097            this.addEntityToTracker(par1Entity, 64, 10, false);
    098        }
    099        else if (par1Entity instanceof EntitySnowball)
    100        {
    101            this.addEntityToTracker(par1Entity, 64, 10, true);
    102        }
    103        else if (par1Entity instanceof EntityEnderPearl)
    104        {
    105            this.addEntityToTracker(par1Entity, 64, 10, true);
    106        }
    107        else if (par1Entity instanceof EntityEnderEye)
    108        {
    109            this.addEntityToTracker(par1Entity, 64, 4, true);
    110        }
    111        else if (par1Entity instanceof EntityEgg)
    112        {
    113            this.addEntityToTracker(par1Entity, 64, 10, true);
    114        }
    115        else if (par1Entity instanceof EntityPotion)
    116        {
    117            this.addEntityToTracker(par1Entity, 64, 10, true);
    118        }
    119        else if (par1Entity instanceof EntityExpBottle)
    120        {
    121            this.addEntityToTracker(par1Entity, 64, 10, true);
    122        }
    123        else if (par1Entity instanceof EntityFireworkRocket)
    124        {
    125            this.addEntityToTracker(par1Entity, 64, 10, true);
    126        }
    127        else if (par1Entity instanceof EntityItem)
    128        {
    129            this.addEntityToTracker(par1Entity, 64, 20, true);
    130        }
    131        else if (par1Entity instanceof EntityMinecart)
    132        {
    133            this.addEntityToTracker(par1Entity, 80, 3, true);
    134        }
    135        else if (par1Entity instanceof EntityBoat)
    136        {
    137            this.addEntityToTracker(par1Entity, 80, 3, true);
    138        }
    139        else if (par1Entity instanceof EntitySquid)
    140        {
    141            this.addEntityToTracker(par1Entity, 64, 3, true);
    142        }
    143        else if (par1Entity instanceof EntityWither)
    144        {
    145            this.addEntityToTracker(par1Entity, 80, 3, false);
    146        }
    147        else if (par1Entity instanceof EntityBat)
    148        {
    149            this.addEntityToTracker(par1Entity, 80, 3, false);
    150        }
    151        else if (par1Entity instanceof IAnimals)
    152        {
    153            this.addEntityToTracker(par1Entity, 80, 3, true);
    154        }
    155        else if (par1Entity instanceof EntityDragon)
    156        {
    157            this.addEntityToTracker(par1Entity, 160, 3, true);
    158        }
    159        else if (par1Entity instanceof EntityTNTPrimed)
    160        {
    161            this.addEntityToTracker(par1Entity, 160, 10, true);
    162        }
    163        else if (par1Entity instanceof EntityFallingSand)
    164        {
    165            this.addEntityToTracker(par1Entity, 160, 20, true);
    166        }
    167        else if (par1Entity instanceof EntityPainting)
    168        {
    169            this.addEntityToTracker(par1Entity, 160, Integer.MAX_VALUE, false);
    170        }
    171        else if (par1Entity instanceof EntityXPOrb)
    172        {
    173            this.addEntityToTracker(par1Entity, 160, 20, true);
    174        }
    175        else if (par1Entity instanceof EntityEnderCrystal)
    176        {
    177            this.addEntityToTracker(par1Entity, 256, Integer.MAX_VALUE, false);
    178        }
    179        else if (par1Entity instanceof EntityItemFrame)
    180        {
    181            this.addEntityToTracker(par1Entity, 160, Integer.MAX_VALUE, false);
    182        }
    183    }
    184
    185    public void addEntityToTracker(Entity par1Entity, int par2, int par3)
    186    {
    187        this.addEntityToTracker(par1Entity, par2, par3, false);
    188    }
    189
    190    public void addEntityToTracker(Entity par1Entity, int par2, int par3, boolean par4)
    191    {
    192        if (par2 > this.entityViewDistance)
    193        {
    194            par2 = this.entityViewDistance;
    195        }
    196
    197        try
    198        {
    199            if (this.trackedEntityIDs.containsItem(par1Entity.entityId))
    200            {
    201                throw new IllegalStateException("Entity is already tracked!");
    202            }
    203            else
    204            {
    205                EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(par1Entity, par2, par3, par4);
    206                this.trackedEntities.add(entitytrackerentry);
    207                this.trackedEntityIDs.addKey(par1Entity.entityId, entitytrackerentry);
    208                entitytrackerentry.sendEventsToPlayers(this.theWorld.playerEntities);
    209            }
    210        }
    211        catch (Throwable throwable)
    212        {
    213            CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Adding entity to track");
    214            CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity To Track");
    215            crashreportcategory.addCrashSection("Tracking range", par2 + " blocks");
    216            crashreportcategory.addCrashSectionCallable("Update interval", new CallableEntityTracker(this, par3));
    217            par1Entity.func_85029_a(crashreportcategory);
    218            throw new ReportedException(crashreport);
    219        }
    220    }
    221
    222    public void removeEntityFromAllTrackingPlayers(Entity par1Entity)
    223    {
    224        if (par1Entity instanceof EntityPlayerMP)
    225        {
    226            EntityPlayerMP entityplayermp = (EntityPlayerMP)par1Entity;
    227            Iterator iterator = this.trackedEntities.iterator();
    228
    229            while (iterator.hasNext())
    230            {
    231                EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
    232                entitytrackerentry.removeFromWatchingList(entityplayermp);
    233            }
    234        }
    235
    236        EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry)this.trackedEntityIDs.removeObject(par1Entity.entityId);
    237
    238        if (entitytrackerentry1 != null)
    239        {
    240            this.trackedEntities.remove(entitytrackerentry1);
    241            entitytrackerentry1.informAllAssociatedPlayersOfItemDestruction();
    242        }
    243    }
    244
    245    public void updateTrackedEntities()
    246    {
    247        ArrayList arraylist = new ArrayList();
    248        Iterator iterator = this.trackedEntities.iterator();
    249
    250        while (iterator.hasNext())
    251        {
    252            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
    253            entitytrackerentry.sendLocationToAllClients(this.theWorld.playerEntities);
    254
    255            if (entitytrackerentry.playerEntitiesUpdated && entitytrackerentry.myEntity instanceof EntityPlayerMP)
    256            {
    257                arraylist.add((EntityPlayerMP)entitytrackerentry.myEntity);
    258            }
    259        }
    260
    261        for (int i = 0; i < arraylist.size(); ++i)
    262        {
    263            EntityPlayerMP entityplayermp = (EntityPlayerMP)arraylist.get(i);
    264            Iterator iterator1 = this.trackedEntities.iterator();
    265
    266            while (iterator1.hasNext())
    267            {
    268                EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry)iterator1.next();
    269
    270                if (entitytrackerentry1.myEntity != entityplayermp)
    271                {
    272                    entitytrackerentry1.tryStartWachingThis(entityplayermp);
    273                }
    274            }
    275        }
    276    }
    277
    278    /**
    279     * does not send the packet to the entity if the entity is a player
    280     */
    281    public void sendPacketToAllPlayersTrackingEntity(Entity par1Entity, Packet par2Packet)
    282    {
    283        EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)this.trackedEntityIDs.lookup(par1Entity.entityId);
    284
    285        if (entitytrackerentry != null)
    286        {
    287            entitytrackerentry.sendPacketToAllTrackingPlayers(par2Packet);
    288        }
    289    }
    290
    291    /**
    292     * sends to the entity if the entity is a player
    293     */
    294    public void sendPacketToAllAssociatedPlayers(Entity par1Entity, Packet par2Packet)
    295    {
    296        EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)this.trackedEntityIDs.lookup(par1Entity.entityId);
    297
    298        if (entitytrackerentry != null)
    299        {
    300            entitytrackerentry.sendPacketToAllAssociatedPlayers(par2Packet);
    301        }
    302    }
    303
    304    public void removePlayerFromTrackers(EntityPlayerMP par1EntityPlayerMP)
    305    {
    306        Iterator iterator = this.trackedEntities.iterator();
    307
    308        while (iterator.hasNext())
    309        {
    310            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
    311            entitytrackerentry.removePlayerFromTracker(par1EntityPlayerMP);
    312        }
    313    }
    314
    315    public void func_85172_a(EntityPlayerMP par1EntityPlayerMP, Chunk par2Chunk)
    316    {
    317        Iterator iterator = this.trackedEntities.iterator();
    318
    319        while (iterator.hasNext())
    320        {
    321            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
    322
    323            if (entitytrackerentry.myEntity != par1EntityPlayerMP && entitytrackerentry.myEntity.chunkCoordX == par2Chunk.xPosition && entitytrackerentry.myEntity.chunkCoordZ == par2Chunk.zPosition)
    324            {
    325                entitytrackerentry.tryStartWachingThis(par1EntityPlayerMP);
    326            }
    327        }
    328    }
    329}