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.serverForThisPlayer.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).serverForThisPlayer.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.serverForThisPlayer.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.serverForThisPlayer.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.serverForThisPlayer.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.serverForThisPlayer.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.serverForThisPlayer.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.serverForThisPlayer.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 }