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 sendVelocityUpdates;
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.sendVelocityUpdates = 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 instanceof EntityItemFrame && this.ticks % 10 == 0)
092 {
093 EntityItemFrame var23 = (EntityItemFrame)this.myEntity;
094 ItemStack var24 = var23.func_82335_i();
095
096 if (var24 != null && var24.getItem() instanceof ItemMap)
097 {
098 MapData var26 = Item.map.getMapData(var24, this.myEntity.worldObj);
099 Iterator var27 = par1List.iterator();
100
101 while (var27.hasNext())
102 {
103 EntityPlayer var29 = (EntityPlayer)var27.next();
104 EntityPlayerMP var30 = (EntityPlayerMP)var29;
105 var26.updateVisiblePlayers(var30, var24);
106
107 if (var30.playerNetServerHandler.packetSize() <= 5)
108 {
109 Packet var31 = Item.map.createMapDataPacket(var24, this.myEntity.worldObj, var30);
110
111 if (var31 != null)
112 {
113 var30.playerNetServerHandler.sendPacketToPlayer(var31);
114 }
115 }
116 }
117 }
118
119 DataWatcher var28 = this.myEntity.getDataWatcher();
120
121 if (var28.hasChanges())
122 {
123 this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var28, false));
124 }
125 }
126 else if (this.ticks++ % this.updateFrequency == 0 || this.myEntity.isAirBorne)
127 {
128 int var2;
129 int var3;
130
131 if (this.myEntity.ridingEntity == null)
132 {
133 ++this.ticksSinceLastForcedTeleport;
134 var2 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
135 var3 = MathHelper.floor_double(this.myEntity.posY * 32.0D);
136 int var4 = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
137 int var5 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
138 int var6 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
139 int var7 = var2 - this.lastScaledXPosition;
140 int var8 = var3 - this.lastScaledYPosition;
141 int var9 = var4 - this.lastScaledZPosition;
142 Object var10 = null;
143 boolean var11 = Math.abs(var7) >= 4 || Math.abs(var8) >= 4 || Math.abs(var9) >= 4 || this.ticks % 60 == 0;
144 boolean var12 = Math.abs(var5 - this.lastYaw) >= 4 || Math.abs(var6 - this.lastPitch) >= 4;
145
146 if (var7 >= -128 && var7 < 128 && var8 >= -128 && var8 < 128 && var9 >= -128 && var9 < 128 && this.ticksSinceLastForcedTeleport <= 400)
147 {
148 if (var11 && var12)
149 {
150 var10 = new Packet33RelEntityMoveLook(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9, (byte)var5, (byte)var6);
151 }
152 else if (var11)
153 {
154 var10 = new Packet31RelEntityMove(this.myEntity.entityId, (byte)var7, (byte)var8, (byte)var9);
155 }
156 else if (var12)
157 {
158 var10 = new Packet32EntityLook(this.myEntity.entityId, (byte)var5, (byte)var6);
159 }
160 }
161 else
162 {
163 this.ticksSinceLastForcedTeleport = 0;
164 var10 = new Packet34EntityTeleport(this.myEntity.entityId, var2, var3, var4, (byte)var5, (byte)var6);
165 }
166
167 if (this.sendVelocityUpdates)
168 {
169 double var13 = this.myEntity.motionX - this.motionX;
170 double var15 = this.myEntity.motionY - this.motionY;
171 double var17 = this.myEntity.motionZ - this.motionZ;
172 double var19 = 0.02D;
173 double var21 = var13 * var13 + var15 * var15 + var17 * var17;
174
175 if (var21 > var19 * var19 || var21 > 0.0D && this.myEntity.motionX == 0.0D && this.myEntity.motionY == 0.0D && this.myEntity.motionZ == 0.0D)
176 {
177 this.motionX = this.myEntity.motionX;
178 this.motionY = this.myEntity.motionY;
179 this.motionZ = this.myEntity.motionZ;
180 this.sendPacketToAllTrackingPlayers(new Packet28EntityVelocity(this.myEntity.entityId, this.motionX, this.motionY, this.motionZ));
181 }
182 }
183
184 if (var10 != null)
185 {
186 this.sendPacketToAllTrackingPlayers((Packet)var10);
187 }
188
189 DataWatcher var32 = this.myEntity.getDataWatcher();
190
191 if (var32.hasChanges())
192 {
193 this.sendPacketToAllAssociatedPlayers(new Packet40EntityMetadata(this.myEntity.entityId, var32, false));
194 }
195
196 if (var11)
197 {
198 this.lastScaledXPosition = var2;
199 this.lastScaledYPosition = var3;
200 this.lastScaledZPosition = var4;
201 }
202
203 if (var12)
204 {
205 this.lastYaw = var5;
206 this.lastPitch = var6;
207 }
208 }
209 else
210 {
211 var2 = MathHelper.floor_float(this.myEntity.rotationYaw * 256.0F / 360.0F);
212 var3 = MathHelper.floor_float(this.myEntity.rotationPitch * 256.0F / 360.0F);
213 boolean var25 = Math.abs(var2 - this.lastYaw) >= 4 || Math.abs(var3 - this.lastPitch) >= 4;
214
215 if (var25)
216 {
217 this.sendPacketToAllTrackingPlayers(new Packet32EntityLook(this.myEntity.entityId, (byte)var2, (byte)var3));
218 this.lastYaw = var2;
219 this.lastPitch = var3;
220 }
221
222 this.lastScaledXPosition = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posX);
223 this.lastScaledYPosition = MathHelper.floor_double(this.myEntity.posY * 32.0D);
224 this.lastScaledZPosition = this.myEntity.myEntitySize.multiplyBy32AndRound(this.myEntity.posZ);
225 }
226
227 var2 = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
228
229 if (Math.abs(var2 - this.lastHeadMotion) >= 4)
230 {
231 this.sendPacketToAllTrackingPlayers(new Packet35EntityHeadRotation(this.myEntity.entityId, (byte)var2));
232 this.lastHeadMotion = var2;
233 }
234
235 this.myEntity.isAirBorne = false;
236 }
237
238 if (this.myEntity.velocityChanged)
239 {
240 this.sendPacketToAllAssociatedPlayers(new Packet28EntityVelocity(this.myEntity));
241 this.myEntity.velocityChanged = false;
242 }
243 }
244
245 /**
246 * if this is a player, then it is not informed
247 */
248 public void sendPacketToAllTrackingPlayers(Packet par1Packet)
249 {
250 Iterator var2 = this.trackedPlayers.iterator();
251
252 while (var2.hasNext())
253 {
254 EntityPlayerMP var3 = (EntityPlayerMP)var2.next();
255 var3.playerNetServerHandler.sendPacketToPlayer(par1Packet);
256 }
257 }
258
259 /**
260 * if this is a player, then it recieves the message also
261 */
262 public void sendPacketToAllAssociatedPlayers(Packet par1Packet)
263 {
264 this.sendPacketToAllTrackingPlayers(par1Packet);
265
266 if (this.myEntity instanceof EntityPlayerMP)
267 {
268 ((EntityPlayerMP)this.myEntity).playerNetServerHandler.sendPacketToPlayer(par1Packet);
269 }
270 }
271
272 public void informAllAssociatedPlayersOfItemDestruction()
273 {
274 Iterator var1 = this.trackedPlayers.iterator();
275
276 while (var1.hasNext())
277 {
278 EntityPlayerMP var2 = (EntityPlayerMP)var1.next();
279 var2.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
280 }
281 }
282
283 public void removeFromWatchingList(EntityPlayerMP par1EntityPlayerMP)
284 {
285 if (this.trackedPlayers.contains(par1EntityPlayerMP))
286 {
287 par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
288 this.trackedPlayers.remove(par1EntityPlayerMP);
289 }
290 }
291
292 /**
293 * if the player is more than the distance threshold (typically 64) then the player is removed instead
294 */
295 public void tryStartWachingThis(EntityPlayerMP par1EntityPlayerMP)
296 {
297 if (par1EntityPlayerMP != this.myEntity)
298 {
299 double var2 = par1EntityPlayerMP.posX - (double)(this.lastScaledXPosition / 32);
300 double var4 = par1EntityPlayerMP.posZ - (double)(this.lastScaledZPosition / 32);
301
302 if (var2 >= (double)(-this.BlocksDistanceThreshold) && var2 <= (double)this.BlocksDistanceThreshold && var4 >= (double)(-this.BlocksDistanceThreshold) && var4 <= (double)this.BlocksDistanceThreshold)
303 {
304 if (!this.trackedPlayers.contains(par1EntityPlayerMP) && this.isPlayerWatchingThisChunk(par1EntityPlayerMP))
305 {
306 this.trackedPlayers.add(par1EntityPlayerMP);
307 Packet var6 = this.getPacketForThisEntity();
308 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(var6);
309
310 if (this.myEntity instanceof EntityItemFrame)
311 {
312 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet40EntityMetadata(this.myEntity.entityId, this.myEntity.getDataWatcher(), true));
313 }
314
315 this.motionX = this.myEntity.motionX;
316 this.motionY = this.myEntity.motionY;
317 this.motionZ = this.myEntity.motionZ;
318
319 int posX = MathHelper.floor_double(this.myEntity.posX * 32.0D);
320 int posY = MathHelper.floor_double(this.myEntity.posY * 32.0D);
321 int posZ = MathHelper.floor_double(this.myEntity.posZ * 32.0D);
322 if (posX != this.lastScaledXPosition || posY != this.lastScaledYPosition || posZ != this.lastScaledZPosition)
323 {
324 FMLNetworkHandler.makeEntitySpawnAdjustment(this.myEntity.entityId, par1EntityPlayerMP, this.lastScaledXPosition, this.lastScaledYPosition, this.lastScaledZPosition);
325 }
326 if (this.sendVelocityUpdates && !(var6 instanceof Packet24MobSpawn))
327 {
328 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet28EntityVelocity(this.myEntity.entityId, this.myEntity.motionX, this.myEntity.motionY, this.myEntity.motionZ));
329 }
330
331 if (this.myEntity.ridingEntity != null)
332 {
333 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet39AttachEntity(this.myEntity, this.myEntity.ridingEntity));
334 }
335
336 if (this.myEntity instanceof EntityLiving)
337 {
338 for (int var7 = 0; var7 < 5; ++var7)
339 {
340 ItemStack var8 = ((EntityLiving)this.myEntity).getCurrentItemOrArmor(var7);
341
342 if (var8 != null)
343 {
344 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet5PlayerInventory(this.myEntity.entityId, var7, var8));
345 }
346 }
347 }
348
349 if (this.myEntity instanceof EntityPlayer)
350 {
351 EntityPlayer var11 = (EntityPlayer)this.myEntity;
352
353 if (var11.isPlayerSleeping())
354 {
355 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)));
356 }
357 }
358
359 if (this.myEntity instanceof EntityLiving)
360 {
361 EntityLiving var10 = (EntityLiving)this.myEntity;
362 Iterator var12 = var10.getActivePotionEffects().iterator();
363
364 while (var12.hasNext())
365 {
366 PotionEffect var9 = (PotionEffect)var12.next();
367 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.myEntity.entityId, var9));
368 }
369 }
370 }
371 }
372 else if (this.trackedPlayers.contains(par1EntityPlayerMP))
373 {
374 this.trackedPlayers.remove(par1EntityPlayerMP);
375 par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
376 }
377 }
378 }
379
380 private boolean isPlayerWatchingThisChunk(EntityPlayerMP par1EntityPlayerMP)
381 {
382 return par1EntityPlayerMP.getServerForPlayer().getPlayerManager().isPlayerWatchingChunk(par1EntityPlayerMP, this.myEntity.chunkCoordX, this.myEntity.chunkCoordZ);
383 }
384
385 public void sendEventsToPlayers(List par1List)
386 {
387 Iterator var2 = par1List.iterator();
388
389 while (var2.hasNext())
390 {
391 EntityPlayer var3 = (EntityPlayer)var2.next();
392 this.tryStartWachingThis((EntityPlayerMP)var3);
393 }
394 }
395
396 private Packet getPacketForThisEntity()
397 {
398 if (this.myEntity.isDead)
399 {
400 System.out.println("Fetching addPacket for removed entity");
401 }
402
403 Packet pkt = FMLNetworkHandler.getEntitySpawningPacket(this.myEntity);
404
405 if (pkt != null)
406 {
407 return pkt;
408 }
409
410 if (this.myEntity instanceof EntityItem)
411 {
412 EntityItem var9 = (EntityItem)this.myEntity;
413 Packet21PickupSpawn var10 = new Packet21PickupSpawn(var9);
414 var9.posX = (double)var10.xPosition / 32.0D;
415 var9.posY = (double)var10.yPosition / 32.0D;
416 var9.posZ = (double)var10.zPosition / 32.0D;
417 return var10;
418 }
419 else if (this.myEntity instanceof EntityPlayerMP)
420 {
421 return new Packet20NamedEntitySpawn((EntityPlayer)this.myEntity);
422 }
423 else
424 {
425 if (this.myEntity instanceof EntityMinecart)
426 {
427 EntityMinecart var1 = (EntityMinecart)this.myEntity;
428
429 if (var1.minecartType == 0)
430 {
431 return new Packet23VehicleSpawn(this.myEntity, 10);
432 }
433
434 if (var1.minecartType == 1)
435 {
436 return new Packet23VehicleSpawn(this.myEntity, 11);
437 }
438
439 if (var1.minecartType == 2)
440 {
441 return new Packet23VehicleSpawn(this.myEntity, 12);
442 }
443 }
444
445 if (this.myEntity instanceof EntityBoat)
446 {
447 return new Packet23VehicleSpawn(this.myEntity, 1);
448 }
449 else if (!(this.myEntity instanceof IAnimals) && !(this.myEntity instanceof EntityDragon))
450 {
451 if (this.myEntity instanceof EntityFishHook)
452 {
453 EntityPlayer var8 = ((EntityFishHook)this.myEntity).angler;
454 return new Packet23VehicleSpawn(this.myEntity, 90, var8 != null ? var8.entityId : this.myEntity.entityId);
455 }
456 else if (this.myEntity instanceof EntityArrow)
457 {
458 Entity var7 = ((EntityArrow)this.myEntity).shootingEntity;
459 return new Packet23VehicleSpawn(this.myEntity, 60, var7 != null ? var7.entityId : this.myEntity.entityId);
460 }
461 else if (this.myEntity instanceof EntitySnowball)
462 {
463 return new Packet23VehicleSpawn(this.myEntity, 61);
464 }
465 else if (this.myEntity instanceof EntityPotion)
466 {
467 return new Packet23VehicleSpawn(this.myEntity, 73, ((EntityPotion)this.myEntity).getPotionDamage());
468 }
469 else if (this.myEntity instanceof EntityExpBottle)
470 {
471 return new Packet23VehicleSpawn(this.myEntity, 75);
472 }
473 else if (this.myEntity instanceof EntityEnderPearl)
474 {
475 return new Packet23VehicleSpawn(this.myEntity, 65);
476 }
477 else if (this.myEntity instanceof EntityEnderEye)
478 {
479 return new Packet23VehicleSpawn(this.myEntity, 72);
480 }
481 else
482 {
483 Packet23VehicleSpawn var2;
484
485 if (this.myEntity instanceof EntityFireball)
486 {
487 EntityFireball var6 = (EntityFireball)this.myEntity;
488 var2 = null;
489 byte var3 = 63;
490
491 if (this.myEntity instanceof EntitySmallFireball)
492 {
493 var3 = 64;
494 }
495 else if (this.myEntity instanceof EntityWitherSkull)
496 {
497 var3 = 66;
498 }
499
500 if (var6.shootingEntity != null)
501 {
502 var2 = new Packet23VehicleSpawn(this.myEntity, var3, ((EntityFireball)this.myEntity).shootingEntity.entityId);
503 }
504 else
505 {
506 var2 = new Packet23VehicleSpawn(this.myEntity, var3, 0);
507 }
508
509 var2.speedX = (int)(var6.accelerationX * 8000.0D);
510 var2.speedY = (int)(var6.accelerationY * 8000.0D);
511 var2.speedZ = (int)(var6.accelerationZ * 8000.0D);
512 return var2;
513 }
514 else if (this.myEntity instanceof EntityEgg)
515 {
516 return new Packet23VehicleSpawn(this.myEntity, 62);
517 }
518 else if (this.myEntity instanceof EntityTNTPrimed)
519 {
520 return new Packet23VehicleSpawn(this.myEntity, 50);
521 }
522 else if (this.myEntity instanceof EntityEnderCrystal)
523 {
524 return new Packet23VehicleSpawn(this.myEntity, 51);
525 }
526 else if (this.myEntity instanceof EntityFallingSand)
527 {
528 EntityFallingSand var5 = (EntityFallingSand)this.myEntity;
529 return new Packet23VehicleSpawn(this.myEntity, 70, var5.blockID | var5.field_70285_b << 16);
530 }
531 else if (this.myEntity instanceof EntityPainting)
532 {
533 return new Packet25EntityPainting((EntityPainting)this.myEntity);
534 }
535 else if (this.myEntity instanceof EntityItemFrame)
536 {
537 EntityItemFrame var4 = (EntityItemFrame)this.myEntity;
538 var2 = new Packet23VehicleSpawn(this.myEntity, 71, var4.field_82332_a);
539 var2.xPosition = MathHelper.floor_float((float)(var4.xPosition * 32));
540 var2.yPosition = MathHelper.floor_float((float)(var4.yPosition * 32));
541 var2.zPosition = MathHelper.floor_float((float)(var4.zPosition * 32));
542 return var2;
543 }
544 else if (this.myEntity instanceof EntityXPOrb)
545 {
546 return new Packet26EntityExpOrb((EntityXPOrb)this.myEntity);
547 }
548 else
549 {
550 throw new IllegalArgumentException("Don\'t know how to add " + this.myEntity.getClass() + "!");
551 }
552 }
553 }
554 else
555 {
556 this.lastHeadMotion = MathHelper.floor_float(this.myEntity.func_70079_am() * 256.0F / 360.0F);
557 return new Packet24MobSpawn((EntityLiving)this.myEntity);
558 }
559 }
560 }
561
562 public void removePlayerFromTracker(EntityPlayerMP par1EntityPlayerMP)
563 {
564 if (this.trackedPlayers.contains(par1EntityPlayerMP))
565 {
566 this.trackedPlayers.remove(par1EntityPlayerMP);
567 par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.myEntity.entityId));
568 }
569 }
570 }