001 package net.minecraft.world; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.Random; 007 import net.minecraft.block.Block; 008 import net.minecraft.entity.Entity; 009 import net.minecraft.util.Direction; 010 import net.minecraft.util.LongHashMap; 011 import net.minecraft.util.MathHelper; 012 013 public class Teleporter 014 { 015 private final WorldServer field_85192_a; 016 017 /** A private Random() function in Teleporter */ 018 private final Random random; 019 private final LongHashMap field_85191_c = new LongHashMap(); 020 private final List field_85190_d = new ArrayList(); 021 022 public Teleporter(WorldServer par1WorldServer) 023 { 024 this.field_85192_a = par1WorldServer; 025 this.random = new Random(par1WorldServer.getSeed()); 026 } 027 028 /** 029 * Place an entity in a nearby portal, creating one if necessary. 030 */ 031 public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) 032 { 033 if (this.field_85192_a.provider.dimensionId != 1) 034 { 035 if (!this.placeInExistingPortal(par1Entity, par2, par4, par6, par8)) 036 { 037 this.func_85188_a(par1Entity); 038 this.placeInExistingPortal(par1Entity, par2, par4, par6, par8); 039 } 040 } 041 else 042 { 043 int var9 = MathHelper.floor_double(par1Entity.posX); 044 int var10 = MathHelper.floor_double(par1Entity.posY) - 1; 045 int var11 = MathHelper.floor_double(par1Entity.posZ); 046 byte var12 = 1; 047 byte var13 = 0; 048 049 for (int var14 = -2; var14 <= 2; ++var14) 050 { 051 for (int var15 = -2; var15 <= 2; ++var15) 052 { 053 for (int var16 = -1; var16 < 3; ++var16) 054 { 055 int var17 = var9 + var15 * var12 + var14 * var13; 056 int var18 = var10 + var16; 057 int var19 = var11 + var15 * var13 - var14 * var12; 058 boolean var20 = var16 < 0; 059 this.field_85192_a.setBlockWithNotify(var17, var18, var19, var20 ? Block.obsidian.blockID : 0); 060 } 061 } 062 } 063 064 par1Entity.setLocationAndAngles((double)var9, (double)var10, (double)var11, par1Entity.rotationYaw, 0.0F); 065 par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D; 066 } 067 } 068 069 /** 070 * Place an entity in a nearby portal which already exists. 071 */ 072 public boolean placeInExistingPortal(Entity par1Entity, double par2, double par4, double par6, float par8) 073 { 074 short var9 = 128; 075 double var10 = -1.0D; 076 int var12 = 0; 077 int var13 = 0; 078 int var14 = 0; 079 int var15 = MathHelper.floor_double(par1Entity.posX); 080 int var16 = MathHelper.floor_double(par1Entity.posZ); 081 long var17 = ChunkCoordIntPair.chunkXZ2Int(var15, var16); 082 boolean var19 = true; 083 double var27; 084 int var48; 085 086 if (this.field_85191_c.containsItem(var17)) 087 { 088 PortalPosition var20 = (PortalPosition)this.field_85191_c.getValueByKey(var17); 089 var10 = 0.0D; 090 var12 = var20.posX; 091 var13 = var20.posY; 092 var14 = var20.posZ; 093 var20.field_85087_d = this.field_85192_a.getTotalWorldTime(); 094 var19 = false; 095 } 096 else 097 { 098 for (var48 = var15 - var9; var48 <= var15 + var9; ++var48) 099 { 100 double var21 = (double)var48 + 0.5D - par1Entity.posX; 101 102 for (int var23 = var16 - var9; var23 <= var16 + var9; ++var23) 103 { 104 double var24 = (double)var23 + 0.5D - par1Entity.posZ; 105 106 for (int var26 = this.field_85192_a.getActualHeight() - 1; var26 >= 0; --var26) 107 { 108 if (this.field_85192_a.getBlockId(var48, var26, var23) == Block.portal.blockID) 109 { 110 while (this.field_85192_a.getBlockId(var48, var26 - 1, var23) == Block.portal.blockID) 111 { 112 --var26; 113 } 114 115 var27 = (double)var26 + 0.5D - par1Entity.posY; 116 double var29 = var21 * var21 + var27 * var27 + var24 * var24; 117 118 if (var10 < 0.0D || var29 < var10) 119 { 120 var10 = var29; 121 var12 = var48; 122 var13 = var26; 123 var14 = var23; 124 } 125 } 126 } 127 } 128 } 129 } 130 131 if (var10 >= 0.0D) 132 { 133 if (var19) 134 { 135 this.field_85191_c.add(var17, new PortalPosition(this, var12, var13, var14, this.field_85192_a.getTotalWorldTime())); 136 this.field_85190_d.add(Long.valueOf(var17)); 137 } 138 139 double var49 = (double)var12 + 0.5D; 140 double var25 = (double)var13 + 0.5D; 141 var27 = (double)var14 + 0.5D; 142 int var50 = -1; 143 144 if (this.field_85192_a.getBlockId(var12 - 1, var13, var14) == Block.portal.blockID) 145 { 146 var50 = 2; 147 } 148 149 if (this.field_85192_a.getBlockId(var12 + 1, var13, var14) == Block.portal.blockID) 150 { 151 var50 = 0; 152 } 153 154 if (this.field_85192_a.getBlockId(var12, var13, var14 - 1) == Block.portal.blockID) 155 { 156 var50 = 3; 157 } 158 159 if (this.field_85192_a.getBlockId(var12, var13, var14 + 1) == Block.portal.blockID) 160 { 161 var50 = 1; 162 } 163 164 int var30 = par1Entity.func_82148_at(); 165 166 if (var50 > -1) 167 { 168 int var31 = Direction.field_71578_g[var50]; 169 int var32 = Direction.offsetX[var50]; 170 int var33 = Direction.offsetZ[var50]; 171 int var34 = Direction.offsetX[var31]; 172 int var35 = Direction.offsetZ[var31]; 173 boolean var36 = !this.field_85192_a.isAirBlock(var12 + var32 + var34, var13, var14 + var33 + var35) || !this.field_85192_a.isAirBlock(var12 + var32 + var34, var13 + 1, var14 + var33 + var35); 174 boolean var37 = !this.field_85192_a.isAirBlock(var12 + var32, var13, var14 + var33) || !this.field_85192_a.isAirBlock(var12 + var32, var13 + 1, var14 + var33); 175 176 if (var36 && var37) 177 { 178 var50 = Direction.footInvisibleFaceRemap[var50]; 179 var31 = Direction.footInvisibleFaceRemap[var31]; 180 var32 = Direction.offsetX[var50]; 181 var33 = Direction.offsetZ[var50]; 182 var34 = Direction.offsetX[var31]; 183 var35 = Direction.offsetZ[var31]; 184 var48 = var12 - var34; 185 var49 -= (double)var34; 186 int var22 = var14 - var35; 187 var27 -= (double)var35; 188 var36 = !this.field_85192_a.isAirBlock(var48 + var32 + var34, var13, var22 + var33 + var35) || !this.field_85192_a.isAirBlock(var48 + var32 + var34, var13 + 1, var22 + var33 + var35); 189 var37 = !this.field_85192_a.isAirBlock(var48 + var32, var13, var22 + var33) || !this.field_85192_a.isAirBlock(var48 + var32, var13 + 1, var22 + var33); 190 } 191 192 float var38 = 0.5F; 193 float var39 = 0.5F; 194 195 if (!var36 && var37) 196 { 197 var38 = 1.0F; 198 } 199 else if (var36 && !var37) 200 { 201 var38 = 0.0F; 202 } 203 else if (var36 && var37) 204 { 205 var39 = 0.0F; 206 } 207 208 var49 += (double)((float)var34 * var38 + var39 * (float)var32); 209 var27 += (double)((float)var35 * var38 + var39 * (float)var33); 210 float var40 = 0.0F; 211 float var41 = 0.0F; 212 float var42 = 0.0F; 213 float var43 = 0.0F; 214 215 if (var50 == var30) 216 { 217 var40 = 1.0F; 218 var41 = 1.0F; 219 } 220 else if (var50 == Direction.footInvisibleFaceRemap[var30]) 221 { 222 var40 = -1.0F; 223 var41 = -1.0F; 224 } 225 else if (var50 == Direction.enderEyeMetaToDirection[var30]) 226 { 227 var42 = 1.0F; 228 var43 = -1.0F; 229 } 230 else 231 { 232 var42 = -1.0F; 233 var43 = 1.0F; 234 } 235 236 double var44 = par1Entity.motionX; 237 double var46 = par1Entity.motionZ; 238 par1Entity.motionX = var44 * (double)var40 + var46 * (double)var43; 239 par1Entity.motionZ = var44 * (double)var42 + var46 * (double)var41; 240 par1Entity.rotationYaw = par8 - (float)(var30 * 90) + (float)(var50 * 90); 241 } 242 else 243 { 244 par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D; 245 } 246 247 par1Entity.setLocationAndAngles(var49, var25, var27, par1Entity.rotationYaw, par1Entity.rotationPitch); 248 return true; 249 } 250 else 251 { 252 return false; 253 } 254 } 255 256 public boolean func_85188_a(Entity par1Entity) 257 { 258 byte var2 = 16; 259 double var3 = -1.0D; 260 int var5 = MathHelper.floor_double(par1Entity.posX); 261 int var6 = MathHelper.floor_double(par1Entity.posY); 262 int var7 = MathHelper.floor_double(par1Entity.posZ); 263 int var8 = var5; 264 int var9 = var6; 265 int var10 = var7; 266 int var11 = 0; 267 int var12 = this.random.nextInt(4); 268 int var13; 269 double var14; 270 double var17; 271 int var16; 272 int var19; 273 int var21; 274 int var20; 275 int var23; 276 int var22; 277 int var25; 278 int var24; 279 int var27; 280 int var26; 281 double var31; 282 double var32; 283 284 for (var13 = var5 - var2; var13 <= var5 + var2; ++var13) 285 { 286 var14 = (double)var13 + 0.5D - par1Entity.posX; 287 288 for (var16 = var7 - var2; var16 <= var7 + var2; ++var16) 289 { 290 var17 = (double)var16 + 0.5D - par1Entity.posZ; 291 label274: 292 293 for (var19 = this.field_85192_a.getActualHeight() - 1; var19 >= 0; --var19) 294 { 295 if (this.field_85192_a.isAirBlock(var13, var19, var16)) 296 { 297 while (var19 > 0 && this.field_85192_a.isAirBlock(var13, var19 - 1, var16)) 298 { 299 --var19; 300 } 301 302 for (var20 = var12; var20 < var12 + 4; ++var20) 303 { 304 var21 = var20 % 2; 305 var22 = 1 - var21; 306 307 if (var20 % 4 >= 2) 308 { 309 var21 = -var21; 310 var22 = -var22; 311 } 312 313 for (var23 = 0; var23 < 3; ++var23) 314 { 315 for (var24 = 0; var24 < 4; ++var24) 316 { 317 for (var25 = -1; var25 < 4; ++var25) 318 { 319 var26 = var13 + (var24 - 1) * var21 + var23 * var22; 320 var27 = var19 + var25; 321 int var28 = var16 + (var24 - 1) * var22 - var23 * var21; 322 323 if (var25 < 0 && !this.field_85192_a.getBlockMaterial(var26, var27, var28).isSolid() || var25 >= 0 && !this.field_85192_a.isAirBlock(var26, var27, var28)) 324 { 325 continue label274; 326 } 327 } 328 } 329 } 330 331 var32 = (double)var19 + 0.5D - par1Entity.posY; 332 var31 = var14 * var14 + var32 * var32 + var17 * var17; 333 334 if (var3 < 0.0D || var31 < var3) 335 { 336 var3 = var31; 337 var8 = var13; 338 var9 = var19; 339 var10 = var16; 340 var11 = var20 % 4; 341 } 342 } 343 } 344 } 345 } 346 } 347 348 if (var3 < 0.0D) 349 { 350 for (var13 = var5 - var2; var13 <= var5 + var2; ++var13) 351 { 352 var14 = (double)var13 + 0.5D - par1Entity.posX; 353 354 for (var16 = var7 - var2; var16 <= var7 + var2; ++var16) 355 { 356 var17 = (double)var16 + 0.5D - par1Entity.posZ; 357 label222: 358 359 for (var19 = this.field_85192_a.getActualHeight() - 1; var19 >= 0; --var19) 360 { 361 if (this.field_85192_a.isAirBlock(var13, var19, var16)) 362 { 363 while (var19 > 0 && this.field_85192_a.isAirBlock(var13, var19 - 1, var16)) 364 { 365 --var19; 366 } 367 368 for (var20 = var12; var20 < var12 + 2; ++var20) 369 { 370 var21 = var20 % 2; 371 var22 = 1 - var21; 372 373 for (var23 = 0; var23 < 4; ++var23) 374 { 375 for (var24 = -1; var24 < 4; ++var24) 376 { 377 var25 = var13 + (var23 - 1) * var21; 378 var26 = var19 + var24; 379 var27 = var16 + (var23 - 1) * var22; 380 381 if (var24 < 0 && !this.field_85192_a.getBlockMaterial(var25, var26, var27).isSolid() || var24 >= 0 && !this.field_85192_a.isAirBlock(var25, var26, var27)) 382 { 383 continue label222; 384 } 385 } 386 } 387 388 var32 = (double)var19 + 0.5D - par1Entity.posY; 389 var31 = var14 * var14 + var32 * var32 + var17 * var17; 390 391 if (var3 < 0.0D || var31 < var3) 392 { 393 var3 = var31; 394 var8 = var13; 395 var9 = var19; 396 var10 = var16; 397 var11 = var20 % 2; 398 } 399 } 400 } 401 } 402 } 403 } 404 } 405 406 int var29 = var8; 407 int var15 = var9; 408 var16 = var10; 409 int var30 = var11 % 2; 410 int var18 = 1 - var30; 411 412 if (var11 % 4 >= 2) 413 { 414 var30 = -var30; 415 var18 = -var18; 416 } 417 418 boolean var33; 419 420 if (var3 < 0.0D) 421 { 422 if (var9 < 70) 423 { 424 var9 = 70; 425 } 426 427 if (var9 > this.field_85192_a.getActualHeight() - 10) 428 { 429 var9 = this.field_85192_a.getActualHeight() - 10; 430 } 431 432 var15 = var9; 433 434 for (var19 = -1; var19 <= 1; ++var19) 435 { 436 for (var20 = 1; var20 < 3; ++var20) 437 { 438 for (var21 = -1; var21 < 3; ++var21) 439 { 440 var22 = var29 + (var20 - 1) * var30 + var19 * var18; 441 var23 = var15 + var21; 442 var24 = var16 + (var20 - 1) * var18 - var19 * var30; 443 var33 = var21 < 0; 444 this.field_85192_a.setBlockWithNotify(var22, var23, var24, var33 ? Block.obsidian.blockID : 0); 445 } 446 } 447 } 448 } 449 450 for (var19 = 0; var19 < 4; ++var19) 451 { 452 this.field_85192_a.editingBlocks = true; 453 454 for (var20 = 0; var20 < 4; ++var20) 455 { 456 for (var21 = -1; var21 < 4; ++var21) 457 { 458 var22 = var29 + (var20 - 1) * var30; 459 var23 = var15 + var21; 460 var24 = var16 + (var20 - 1) * var18; 461 var33 = var20 == 0 || var20 == 3 || var21 == -1 || var21 == 3; 462 this.field_85192_a.setBlockWithNotify(var22, var23, var24, var33 ? Block.obsidian.blockID : Block.portal.blockID); 463 } 464 } 465 466 this.field_85192_a.editingBlocks = false; 467 468 for (var20 = 0; var20 < 4; ++var20) 469 { 470 for (var21 = -1; var21 < 4; ++var21) 471 { 472 var22 = var29 + (var20 - 1) * var30; 473 var23 = var15 + var21; 474 var24 = var16 + (var20 - 1) * var18; 475 this.field_85192_a.notifyBlocksOfNeighborChange(var22, var23, var24, this.field_85192_a.getBlockId(var22, var23, var24)); 476 } 477 } 478 } 479 480 return true; 481 } 482 483 public void func_85189_a(long par1) 484 { 485 if (par1 % 100L == 0L) 486 { 487 Iterator var3 = this.field_85190_d.iterator(); 488 long var4 = par1 - 600L; 489 490 while (var3.hasNext()) 491 { 492 Long var6 = (Long)var3.next(); 493 PortalPosition var7 = (PortalPosition)this.field_85191_c.getValueByKey(var6.longValue()); 494 495 if (var7 == null || var7.field_85087_d < var4) 496 { 497 var3.remove(); 498 this.field_85191_c.remove(var6.longValue()); 499 } 500 } 501 } 502 } 503 }