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}