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}