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