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 }