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}