001package net.minecraft.world;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005import java.util.List;
006import java.util.Random;
007import net.minecraft.block.Block;
008import net.minecraft.entity.Entity;
009import net.minecraft.util.Direction;
010import net.minecraft.util.LongHashMap;
011import net.minecraft.util.MathHelper;
012
013public class Teleporter
014{
015    private final WorldServer worldServerInstance;
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.worldServerInstance = 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.worldServerInstance.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.worldServerInstance.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.worldServerInstance.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.worldServerInstance.getActualHeight() - 1; var26 >= 0; --var26)
107                    {
108                        if (this.worldServerInstance.getBlockId(var48, var26, var23) == Block.portal.blockID)
109                        {
110                            while (this.worldServerInstance.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.worldServerInstance.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.worldServerInstance.getBlockId(var12 - 1, var13, var14) == Block.portal.blockID)
145            {
146                var50 = 2;
147            }
148
149            if (this.worldServerInstance.getBlockId(var12 + 1, var13, var14) == Block.portal.blockID)
150            {
151                var50 = 0;
152            }
153
154            if (this.worldServerInstance.getBlockId(var12, var13, var14 - 1) == Block.portal.blockID)
155            {
156                var50 = 3;
157            }
158
159            if (this.worldServerInstance.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.worldServerInstance.isAirBlock(var12 + var32 + var34, var13, var14 + var33 + var35) || !this.worldServerInstance.isAirBlock(var12 + var32 + var34, var13 + 1, var14 + var33 + var35);
174                boolean var37 = !this.worldServerInstance.isAirBlock(var12 + var32, var13, var14 + var33) || !this.worldServerInstance.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.worldServerInstance.isAirBlock(var48 + var32 + var34, var13, var22 + var33 + var35) || !this.worldServerInstance.isAirBlock(var48 + var32 + var34, var13 + 1, var22 + var33 + var35);
189                    var37 = !this.worldServerInstance.isAirBlock(var48 + var32, var13, var22 + var33) || !this.worldServerInstance.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.worldServerInstance.getActualHeight() - 1; var19 >= 0; --var19)
294                {
295                    if (this.worldServerInstance.isAirBlock(var13, var19, var16))
296                    {
297                        while (var19 > 0 && this.worldServerInstance.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.worldServerInstance.getBlockMaterial(var26, var27, var28).isSolid() || var25 >= 0 && !this.worldServerInstance.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.worldServerInstance.getActualHeight() - 1; var19 >= 0; --var19)
360                    {
361                        if (this.worldServerInstance.isAirBlock(var13, var19, var16))
362                        {
363                            while (var19 > 0 && this.worldServerInstance.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.worldServerInstance.getBlockMaterial(var25, var26, var27).isSolid() || var24 >= 0 && !this.worldServerInstance.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.worldServerInstance.getActualHeight() - 10)
428            {
429                var9 = this.worldServerInstance.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.worldServerInstance.setBlockWithNotify(var22, var23, var24, var33 ? Block.obsidian.blockID : 0);
445                    }
446                }
447            }
448        }
449
450        for (var19 = 0; var19 < 4; ++var19)
451        {
452            this.worldServerInstance.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.worldServerInstance.setBlockWithNotify(var22, var23, var24, var33 ? Block.obsidian.blockID : Block.portal.blockID);
463                }
464            }
465
466            this.worldServerInstance.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.worldServerInstance.notifyBlocksOfNeighborChange(var22, var23, var24, this.worldServerInstance.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}