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
204            EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(par1Entity, par2, par3, par4);
205            this.trackedEntities.add(entitytrackerentry);
206            this.trackedEntityIDs.addKey(par1Entity.entityId, entitytrackerentry);
207            entitytrackerentry.sendEventsToPlayers(this.theWorld.playerEntities);
208        }
209        catch (Throwable throwable)
210        {
211            CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Adding entity to track");
212            CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity To Track");
213            crashreportcategory.addCrashSection("Tracking range", par2 + " blocks");
214            crashreportcategory.addCrashSectionCallable("Update interval", new CallableEntityTracker(this, par3));
215            par1Entity.func_85029_a(crashreportcategory);
216            CrashReportCategory crashreportcategory1 = crashreport.makeCategory("Entity That Is Already Tracked");
217            ((EntityTrackerEntry)this.trackedEntityIDs.lookup(par1Entity.entityId)).myEntity.func_85029_a(crashreportcategory1);
218
219            try
220            {
221                throw new ReportedException(crashreport);
222            }
223            catch (ReportedException reportedexception)
224            {
225                System.err.println("\"Silently\" catching entity tracking error.");
226                reportedexception.printStackTrace();
227            }
228        }
229    }
230
231    public void removeEntityFromAllTrackingPlayers(Entity par1Entity)
232    {
233        if (par1Entity instanceof EntityPlayerMP)
234        {
235            EntityPlayerMP entityplayermp = (EntityPlayerMP)par1Entity;
236            Iterator iterator = this.trackedEntities.iterator();
237
238            while (iterator.hasNext())
239            {
240                EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
241                entitytrackerentry.removeFromWatchingList(entityplayermp);
242            }
243        }
244
245        EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry)this.trackedEntityIDs.removeObject(par1Entity.entityId);
246
247        if (entitytrackerentry1 != null)
248        {
249            this.trackedEntities.remove(entitytrackerentry1);
250            entitytrackerentry1.informAllAssociatedPlayersOfItemDestruction();
251        }
252    }
253
254    public void updateTrackedEntities()
255    {
256        ArrayList arraylist = new ArrayList();
257        Iterator iterator = this.trackedEntities.iterator();
258
259        while (iterator.hasNext())
260        {
261            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
262            entitytrackerentry.sendLocationToAllClients(this.theWorld.playerEntities);
263
264            if (entitytrackerentry.playerEntitiesUpdated && entitytrackerentry.myEntity instanceof EntityPlayerMP)
265            {
266                arraylist.add((EntityPlayerMP)entitytrackerentry.myEntity);
267            }
268        }
269
270        for (int i = 0; i < arraylist.size(); ++i)
271        {
272            EntityPlayerMP entityplayermp = (EntityPlayerMP)arraylist.get(i);
273            Iterator iterator1 = this.trackedEntities.iterator();
274
275            while (iterator1.hasNext())
276            {
277                EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry)iterator1.next();
278
279                if (entitytrackerentry1.myEntity != entityplayermp)
280                {
281                    entitytrackerentry1.tryStartWachingThis(entityplayermp);
282                }
283            }
284        }
285    }
286
287    /**
288     * does not send the packet to the entity if the entity is a player
289     */
290    public void sendPacketToAllPlayersTrackingEntity(Entity par1Entity, Packet par2Packet)
291    {
292        EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)this.trackedEntityIDs.lookup(par1Entity.entityId);
293
294        if (entitytrackerentry != null)
295        {
296            entitytrackerentry.sendPacketToAllTrackingPlayers(par2Packet);
297        }
298    }
299
300    /**
301     * sends to the entity if the entity is a player
302     */
303    public void sendPacketToAllAssociatedPlayers(Entity par1Entity, Packet par2Packet)
304    {
305        EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)this.trackedEntityIDs.lookup(par1Entity.entityId);
306
307        if (entitytrackerentry != null)
308        {
309            entitytrackerentry.sendPacketToAllAssociatedPlayers(par2Packet);
310        }
311    }
312
313    public void removePlayerFromTrackers(EntityPlayerMP par1EntityPlayerMP)
314    {
315        Iterator iterator = this.trackedEntities.iterator();
316
317        while (iterator.hasNext())
318        {
319            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
320            entitytrackerentry.removePlayerFromTracker(par1EntityPlayerMP);
321        }
322    }
323
324    public void func_85172_a(EntityPlayerMP par1EntityPlayerMP, Chunk par2Chunk)
325    {
326        Iterator iterator = this.trackedEntities.iterator();
327
328        while (iterator.hasNext())
329        {
330            EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry)iterator.next();
331
332            if (entitytrackerentry.myEntity != par1EntityPlayerMP && entitytrackerentry.myEntity.chunkCoordX == par2Chunk.xPosition && entitytrackerentry.myEntity.chunkCoordZ == par2Chunk.zPosition)
333            {
334                entitytrackerentry.tryStartWachingThis(par1EntityPlayerMP);
335            }
336        }
337    }
338}