001 package net.minecraft.src;
002
003 import java.util.HashSet;
004 import java.util.Iterator;
005 import java.util.List;
006 import java.util.Set;
007
008 import cpw.mods.fml.common.network.FMLNetworkHandler;
009
010 public class EntityTrackerEntry
011 {
012 public Entity myEntity;
013 public int BlocksDistanceThreshold;
014
015 /** check for sync when ticks % updateFrequency==0 */
016 public int updateFrequency;
017 public int lastScaledXPosition;
018 public int lastScaledYPosition;
019 public int lastScaledZPosition;
020 public int lastYaw;
021 public int lastPitch;
022 public int lastHeadMotion;
023 public double motionX;
024 public double motionY;
025 public double motionZ;
026 public int ticks = 0;
027 private double posX;
028 private double posY;
029 private double posZ;
030
031 /** set to true on first sendLocationToClients */
032 private boolean isDataInitialized = false;
033 private boolean trackMotion;
034
035 /**
036 * every 400 ticks a full teleport packet is sent, rather than just a "move me +x" command, so that position
037 * remains fully synced.
038 */
039 private int ticksSinceLastForcedTeleport = 0;
040 private Entity ridingEntity;
041 public boolean playerEntitiesUpdated = false;
042 public Set trackedPlayers = new HashSet();
043
044 public EntityTrackerEntry(Entity par1Entity, int par2, int par3, boolean par4)
045 {
046 this.myEntity = par1Entity;
047 this.BlocksDistanceThreshold = par2;
048 this.updateFrequency = par3;
049 this.trackMotion = par4;
050 this.lastScaledXPosition = MathHelper.floor_double(par1Entity.posX * 32.0D);
051 this.lastScaledYPosition = MathHelper.floor_double(par1Entity.posY * 32.0D);
052 this.lastScaledZPosition = MathHelper.floor_double(par1Entity.posZ * 32.0D);
053 this.lastYaw = MathHelper.floor_float(par1Entity.rotationYaw * 256.0F / 360.0F);
054 this.lastPitch = MathHelper.floor_float(par1Entity.rotationPitch * 256.0F / 360.0F);
055 this.lastHeadMotion = MathHelper.floor_float(par1Entity.func_70079_am() * 256.0F / 360.0F);
056 }
057
058 public boolean equals(Object par1Obj)
059 {
060 return par1Obj instanceof EntityTrackerEntry ? ((EntityTrackerEntry)par1Obj).myEntity.entityId == this.myEntity.entityId : false;
061 }
062
063 public int hashCode()
064 {
065 return this.myEntity.entityId;
066 }
067
068 /**
069 * also sends velocity, rotation, and riding info.
070 */
071 public void sendLocationToAllClients(List par1List)
072 {
073 this.playerEntitiesUpdated = false;
074
075 if (!this.isDataInitialized || this.myEntity.getDistanceSq(this.posX, this.posY, this.posZ) > 16.0D)
076 {
077 this.posX = this.myEntity.posX;
078 this.posY = this.myEntity.posY;
079 this.posZ = this.myEntity.posZ;
080 this.isDataInitialized = true;
081 this.playerEntitiesUpdated = true;
082 this.sendEventsToPlayers(par1List);
083 }
084
085 if (this.ridingEntity != this.myEntity.ridingEntity)
086 {
087 this.ridingEntity = this.myEntity.ridingEntity;
088 this.sendPacketToAllTrackingPlayers(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
089 }
090
091 if (this.myEntity.ridingEntity == null)
092 {
093 ++this.ticksSinceLastForcedTeleport;
094
095 if (this.ticks++ % this.updateFrequency == 0 || this.myEntity.isAirBorne)
096 {
097 int var2 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
098 int var3 = MathHelper.floor_double(this.myEntity.posY * 32.0D);
099 int var4 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
100 int var5 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
101 int var6 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
102 int var7 = var2 - this.lastScaledXPosition;
103 int var8 = var3 - this.lastScaledYPosition;
104 int var9 = var4 - this.lastScaledZPosition;
105 Object var10 = null;
106 boolean var11 = Math.abs(var7) >= 4 || Math.abs(var8) >= 4 || Math.abs(var9) >= 4;
107 boolean var12 = Math.abs(var5 - this.lastYaw) >= 4 || Math.abs(var6 - this.lastPitch) >= 4;
108
109 if (var7 >= -128 && var7 < 128 && var8 >= -128 && var8 < 128 && var9 >= -128 && var9 < 128 && this.ticksSinceLastForcedTeleport <= 400)
110 {
111 if (var11 && var12)
112 {
113 var10 = new Packet33RelEntityMoveLook(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9, (byte)var5, (byte)var6);
114 }
115 else if (var11)
116 {
117 var10 = new Packet31RelEntityMove(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9);
118 }
119 else if (var12)
120 {
121 var10 = new Packet32EntityLook(this.myEntity.entityId, (byte)var5, (byte)var6);
122 }
123 }
124 else
125 {
126 this.ticksSinceLastForcedTeleport = 0;
127 var10 = new Packet34EntityTeleport(this.myEntity.entityId, var2, var3, var4, (byte)var5, (byte)var6);
128 }
129
130 if (this.trackMotion)
131 {
132 double var13 = this.myEntity.motionX - this.motionX;
133 double var15 = this.myEntity.motionY - this.motionY;
134 double var17 = this.myEntity.motionZ - this.motionZ;
135 double var19 = 0.02D;
136 double var21 = var13 * var13 + var15 * var15 + var17 * var17;
137
138 if (var21 > var19 * var19 || var21 > 0.0D && this.myEntity.motionX == 0.0D && this.myEntity.motionY == 0.0D && this.myEntity.motionZ == 0.0D)
139 {
140 this.motionX = this.myEntity.motionX;
141 this.motionY = this.myEntity.motionY;
142 this.motionZ = this.myEntity.motionZ;
143 this.sendPacketToAllTrackingPlayers(new Packet28EntityVelocity(this.myEntity.entityId, this.motionX, this.motionY, this.motionZ));
144 }
145 }
146
147 if (var10 != null)
148 {
149 this.sendPacketToAllTrackingPlayers((Packet)var10);
150 }
151
152 DataWatcher var23 = this.myEntity.getDataWatcher();
153
154 if (var23.hasChanges())
155 {
156 this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var23));
157 }
158
159 int var14 = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
160
161 if (Math.abs(var14 - this.lastHeadMotion) >= 4)
162 {
163 this.sendPacketToAllTrackingPlayers(new Packet35EntityHeadRotation(this.myEntity.entityId, (byte)var14));
164 this.lastHeadMotion = var14;
165 }
166
167 if (var11)
168 {
169 this.lastScaledXPosition = var2;
170 this.lastScaledYPosition = var3;
171 this.lastScaledZPosition = var4;
172 }
173
174 if (var12)
175 {
176 this.lastYaw = var5;
177 this.lastPitch = var6;
178 }
179 }
180
181 this.myEntity.isAirBorne = false;
182 }
183
184 if (this.myEntity.velocityChanged)
185 {
186 this.sendPacketToAllAssociatedPlayers(new Packet28EntityVelocity(this.myEntity));
187 this.myEntity.velocityChanged = false;
188 }
189 }
190
191 /**
192 * if this is a player, then it is not informed
193 */
194 public void sendPacketToAllTrackingPlayers(Packet par1Packet)
195 {
196 Iterator var2 = this.trackedPlayers.iterator();
197
198 while (var2.hasNext())
199 {
200 EntityPlayerMP var3 = (EntityPlayerMP)var2.next();
201 var3.playerNetServerHandler.sendPacketToPlayer(par1Packet);
202 }
203 }
204
205 /**
206 * if this is a player, then it recieves the message also
207 */
208 public void sendPacketToAllAssociatedPlayers(Packet par1Packet)
209 {
210 this.sendPacketToAllTrackingPlayers(par1Packet);
211
212 if (this.myEntity instanceof EntityPlayerMP)
213 {
214 ((EntityPlayerMP)this.myEntity).playerNetServerHandler.sendPacketToPlayer(par1Packet);
215 }
216 }
217
218 public void informAllAssociatedPlayersOfItemDestruction()
219 {
220 Iterator var1 = this.trackedPlayers.iterator();
221
222 while (var1.hasNext())
223 {
224 EntityPlayerMP var2 = (EntityPlayerMP)var1.next();
225 var2.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
226 }
227 }
228
229 public void removeFromWatchingList(EntityPlayerMP par1EntityPlayerMP)
230 {
231 if (this.trackedPlayers.contains(par1EntityPlayerMP))
232 {
233 this.trackedPlayers.remove(par1EntityPlayerMP);
234 }
235 }
236
237 /**
238 * if the player is more than the distance threshold (typically 64) then the player is removed instead
239 */
240 public void tryStartWachingThis(EntityPlayerMP par1EntityPlayerMP)
241 {
242 if (par1EntityPlayerMP != this.myEntity)
243 {
244 double var2 = par1EntityPlayerMP.posX - (double)(this.lastScaledXPosition / 32);
245 double var4 = par1EntityPlayerMP.posZ - (double)(this.lastScaledZPosition / 32);
246
247 if (var2 >= (double)(-this.BlocksDistanceThreshold) && var2 <= (double)this.BlocksDistanceThreshold && var4 >= (double)(-this.BlocksDistanceThreshold) && var4 <= (double)this.BlocksDistanceThreshold)
248 {
249 if (!this.trackedPlayers.contains(par1EntityPlayerMP) && this.isPlayerWatchingThisChunk(par1EntityPlayerMP))
250 {
251 this.trackedPlayers.add(par1EntityPlayerMP);
252 Packet var6 = this.getPacketForThisEntity();
253 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(var6);
254 this.motionX = this.myEntity.motionX;
255 this.motionY = this.myEntity.motionY;
256 this.motionZ = this.myEntity.motionZ;
257
258 int posX = MathHelper.floor_double(this.myEntity.posX * 32.0D);
259 int posY = MathHelper.floor_double(this.myEntity.posY * 32.0D);
260 int posZ = MathHelper.floor_double(this.myEntity.posZ * 32.0D);
261 if (posX != this.lastScaledXPosition || posY != this.lastScaledYPosition || posZ != this.lastScaledZPosition)
262 {
263 FMLNetworkHandler.makeEntitySpawnAdjustment(this.myEntity.entityId, par1EntityPlayerMP, this.lastScaledXPosition, this.lastScaledYPosition, this.lastScaledZPosition);
264 }
265 if (this.trackMotion && !(var6 instanceof Packet24MobSpawn))
266 {
267 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet28EntityVelocity(this.myEntity.entityId, this.myEntity.motionX, this.myEntity.motionY, this.myEntity.motionZ));
268 }
269
270 if (this.myEntity.ridingEntity != null)
271 {
272 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
273 }
274
275 ItemStack[] var7 = this.myEntity.getLastActiveItems();
276
277 if (var7 != null)
278 {
279 for (int var8 = 0; var8 < var7.length; ++var8)
280 {
281 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet5PlayerInventory(this.myEntity.entityId, var8, var7[var8]));
282 }
283 }
284
285 if (this.myEntity instanceof EntityPlayer)
286 {
287 EntityPlayer var11 = (EntityPlayer)this.myEntity;
288
289 if (var11.isPlayerSleeping())
290 {
291 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet17Sleep(this.myEntity, 0, MathHelper.floor_double(this.myEntity.posX), MathHelper.floor_double(this.myEntity.posY), MathHelper.floor_double(this.myEntity.posZ)));
292 }
293 }
294
295 if (this.myEntity instanceof EntityLiving)
296 {
297 EntityLiving var12 = (EntityLiving)this.myEntity;
298 Iterator var9 = var12.getActivePotionEffects().iterator();
299
300 while (var9.hasNext())
301 {
302 PotionEffect var10 = (PotionEffect)var9.next();
303 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.myEntity.entityId, var10));
304 }
305 }
306 }
307 }
308 else if (this.trackedPlayers.contains(par1EntityPlayerMP))
309 {
310 this.trackedPlayers.remove(par1EntityPlayerMP);
311 par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
312 }
313 }
314 }
315
316 private boolean isPlayerWatchingThisChunk(EntityPlayerMP par1EntityPlayerMP)
317 {
318 return par1EntityPlayerMP.getServerForPlayer().getPlayerManager().isPlayerWatchingChunk(par1EntityPlayerMP, this.myEntity.chunkCoordX, this.myEntity.chunkCoordZ);
319 }
320
321 public void sendEventsToPlayers(List par1List)
322 {
323 Iterator var2 = par1List.iterator();
324
325 while (var2.hasNext())
326 {
327 EntityPlayer var3 = (EntityPlayer)var2.next();
328 this.tryStartWachingThis((EntityPlayerMP)var3);
329 }
330 }
331
332 private Packet getPacketForThisEntity()
333 {
334 if (this.myEntity.isDead)
335 {
336 System.out.println("Fetching addPacket for removed entity");
337 }
338
339 Packet pkt = FMLNetworkHandler.getEntitySpawningPacket(this.myEntity);
340
341 if (pkt != null)
342 {
343 return pkt;
344 }
345
346 if (this.myEntity instanceof EntityItem)
347 {
348 EntityItem var8 = (EntityItem)this.myEntity;
349 Packet21PickupSpawn var9 = new Packet21PickupSpawn(var8);
350 var8.posX = (double)var9.xPosition / 32.0D;
351 var8.posY = (double)var9.yPosition / 32.0D;
352 var8.posZ = (double)var9.zPosition / 32.0D;
353 return var9;
354 }
355 else if (this.myEntity instanceof EntityPlayerMP)
356 {
357 return new Packet20NamedEntitySpawn((EntityPlayer)this.myEntity);
358 }
359 else
360 {
361 if (this.myEntity instanceof EntityMinecart)
362 {
363 EntityMinecart var1 = (EntityMinecart)this.myEntity;
364
365 if (var1.minecartType == 0)
366 {
367 return new Packet23VehicleSpawn(this.myEntity, 10);
368 }
369
370 if (var1.minecartType == 1)
371 {
372 return new Packet23VehicleSpawn(this.myEntity, 11);
373 }
374
375 if (var1.minecartType == 2)
376 {
377 return new Packet23VehicleSpawn(this.myEntity, 12);
378 }
379 }
380
381 if (this.myEntity instanceof EntityBoat)
382 {
383 return new Packet23VehicleSpawn(this.myEntity, 1);
384 }
385 else if (!(this.myEntity instanceof IAnimals) && !(this.myEntity instanceof EntityDragon))
386 {
387 if (this.myEntity instanceof EntityFishHook)
388 {
389 EntityPlayer var7 = ((EntityFishHook)this.myEntity).angler;
390 return new Packet23VehicleSpawn(this.myEntity, 90, var7 != null ? var7.entityId : this.myEntity.entityId);
391 }
392 else if (this.myEntity instanceof EntityArrow)
393 {
394 Entity var6 = ((EntityArrow)this.myEntity).shootingEntity;
395 return new Packet23VehicleSpawn(this.myEntity, 60, var6 != null ? var6.entityId : this.myEntity.entityId);
396 }
397 else if (this.myEntity instanceof EntitySnowball)
398 {
399 return new Packet23VehicleSpawn(this.myEntity, 61);
400 }
401 else if (this.myEntity instanceof EntityPotion)
402 {
403 return new Packet23VehicleSpawn(this.myEntity, 73, ((EntityPotion)this.myEntity).getPotionDamage());
404 }
405 else if (this.myEntity instanceof EntityExpBottle)
406 {
407 return new Packet23VehicleSpawn(this.myEntity, 75);
408 }
409 else if (this.myEntity instanceof EntityEnderPearl)
410 {
411 return new Packet23VehicleSpawn(this.myEntity, 65);
412 }
413 else if (this.myEntity instanceof EntityEnderEye)
414 {
415 return new Packet23VehicleSpawn(this.myEntity, 72);
416 }
417 else
418 {
419 Packet23VehicleSpawn var2;
420
421 if (this.myEntity instanceof EntitySmallFireball)
422 {
423 EntitySmallFireball var5 = (EntitySmallFireball)this.myEntity;
424 var2 = null;
425
426 if (var5.shootingEntity != null)
427 {
428 var2 = new Packet23VehicleSpawn(this.myEntity, 64, var5.shootingEntity.entityId);
429 }
430 else
431 {
432 var2 = new Packet23VehicleSpawn(this.myEntity, 64, 0);
433 }
434
435 var2.speedX = (int)(var5.accelerationX * 8000.0D);
436 var2.speedY = (int)(var5.accelerationY * 8000.0D);
437 var2.speedZ = (int)(var5.accelerationZ * 8000.0D);
438 return var2;
439 }
440 else if (this.myEntity instanceof EntityFireball)
441 {
442 EntityFireball var4 = (EntityFireball)this.myEntity;
443 var2 = null;
444
445 if (var4.shootingEntity != null)
446 {
447 var2 = new Packet23VehicleSpawn(this.myEntity, 63, ((EntityFireball)this.myEntity).shootingEntity.entityId);
448 }
449 else
450 {
451 var2 = new Packet23VehicleSpawn(this.myEntity, 63, 0);
452 }
453
454 var2.speedX = (int)(var4.accelerationX * 8000.0D);
455 var2.speedY = (int)(var4.accelerationY * 8000.0D);
456 var2.speedZ = (int)(var4.accelerationZ * 8000.0D);
457 return var2;
458 }
459 else if (this.myEntity instanceof EntityEgg)
460 {
461 return new Packet23VehicleSpawn(this.myEntity, 62);
462 }
463 else if (this.myEntity instanceof EntityTNTPrimed)
464 {
465 return new Packet23VehicleSpawn(this.myEntity, 50);
466 }
467 else if (this.myEntity instanceof EntityEnderCrystal)
468 {
469 return new Packet23VehicleSpawn(this.myEntity, 51);
470 }
471 else if (this.myEntity instanceof EntityFallingSand)
472 {
473 EntityFallingSand var3 = (EntityFallingSand)this.myEntity;
474 return new Packet23VehicleSpawn(this.myEntity, 70, var3.blockID | var3.field_70285_b << 16);
475 }
476 else if (this.myEntity instanceof EntityPainting)
477 {
478 return new Packet25EntityPainting((EntityPainting)this.myEntity);
479 }
480 else if (this.myEntity instanceof EntityXPOrb)
481 {
482 return new Packet26EntityExpOrb((EntityXPOrb)this.myEntity);
483 }
484 else
485 {
486 throw new IllegalArgumentException("Don\'t know how to add " + this.myEntity.getClass() + "!");
487 }
488 }
489 }
490 else
491 {
492 this.lastHeadMotion = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
493 return new Packet24MobSpawn((EntityLiving)this.myEntity);
494 }
495 }
496 }
497
498 public void removePlayerFromTracker(EntityPlayerMP par1EntityPlayerMP)
499 {
500 if (this.trackedPlayers.contains(par1EntityPlayerMP))
501 {
502 this.trackedPlayers.remove(par1EntityPlayerMP);
503 par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
504 }
505 }
506 }