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