    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}