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 }