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