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