    001package net.minecraft.block;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.Random;
    006import net.minecraft.block.material.Material;
    007import net.minecraft.entity.Entity;
    008import net.minecraft.item.ItemMonsterPlacer;
    009import net.minecraft.util.AxisAlignedBB;
    010import net.minecraft.world.IBlockAccess;
    011import net.minecraft.world.World;
    012
    013public class BlockPortal extends BlockBreakable
    014{
    015    public BlockPortal(int par1)
    016    {
    017        super(par1, "portal", Material.portal, false);
    018        this.setTickRandomly(true);
    019    }
    020
    021    /**
    022     * Ticks the block if it's been scheduled
    023     */
    024    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    025    {
    026        super.updateTick(par1World, par2, par3, par4, par5Random);
    027
    028        if (par1World.provider.isSurfaceWorld() && par5Random.nextInt(2000) < par1World.difficultySetting)
    029        {
    030            int l;
    031
    032            for (l = par3; !par1World.doesBlockHaveSolidTopSurface(par2, l, par4) && l > 0; --l)
    033            {
    034                ;
    035            }
    036
    037            if (l > 0 && !par1World.isBlockNormalCube(par2, l + 1, par4))
    038            {
    039                Entity entity = ItemMonsterPlacer.spawnCreature(par1World, 57, (double)par2 + 0.5D, (double)l + 1.1D, (double)par4 + 0.5D);
    040
    041                if (entity != null)
    042                {
    043                    entity.timeUntilPortal = entity.getPortalCooldown();
    044                }
    045            }
    046        }
    047    }
    048
    049    /**
    050     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    051     * cleared to be reused)
    052     */
    053    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    054    {
    055        return null;
    056    }
    057
    058    /**
    059     * Updates the blocks bounds based on its current state. Args: world, x, y, z
    060     */
    061    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    062    {
    063        float f;
    064        float f1;
    065
    066        if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) != this.blockID && par1IBlockAccess.getBlockId(par2 + 1, par3, par4) != this.blockID)
    067        {
    068            f = 0.125F;
    069            f1 = 0.5F;
    070            this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1);
    071        }
    072        else
    073        {
    074            f = 0.5F;
    075            f1 = 0.125F;
    076            this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1);
    077        }
    078    }
    079
    080    /**
    081     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    082     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    083     */
    084    public boolean isOpaqueCube()
    085    {
    086        return false;
    087    }
    088
    089    /**
    090     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    091     */
    092    public boolean renderAsNormalBlock()
    093    {
    094        return false;
    095    }
    096
    097    /**
    098     * Checks to see if this location is valid to create a portal and will return True if it does. Args: world, x, y, z
    099     */
    100    public boolean tryToCreatePortal(World par1World, int par2, int par3, int par4)
    101    {
    102        byte b0 = 0;
    103        byte b1 = 0;
    104
    105        if (par1World.getBlockId(par2 - 1, par3, par4) == Block.obsidian.blockID || par1World.getBlockId(par2 + 1, par3, par4) == Block.obsidian.blockID)
    106        {
    107            b0 = 1;
    108        }
    109
    110        if (par1World.getBlockId(par2, par3, par4 - 1) == Block.obsidian.blockID || par1World.getBlockId(par2, par3, par4 + 1) == Block.obsidian.blockID)
    111        {
    112            b1 = 1;
    113        }
    114
    115        if (b0 == b1)
    116        {
    117            return false;
    118        }
    119        else
    120        {
    121            if (par1World.getBlockId(par2 - b0, par3, par4 - b1) == 0)
    122            {
    123                par2 -= b0;
    124                par4 -= b1;
    125            }
    126
    127            int l;
    128            int i1;
    129
    130            for (l = -1; l <= 2; ++l)
    131            {
    132                for (i1 = -1; i1 <= 3; ++i1)
    133                {
    134                    boolean flag = l == -1 || l == 2 || i1 == -1 || i1 == 3;
    135
    136                    if (l != -1 && l != 2 || i1 != -1 && i1 != 3)
    137                    {
    138                        int j1 = par1World.getBlockId(par2 + b0 * l, par3 + i1, par4 + b1 * l);
    139
    140                        if (flag)
    141                        {
    142                            if (j1 != Block.obsidian.blockID)
    143                            {
    144                                return false;
    145                            }
    146                        }
    147                        else if (j1 != 0 && j1 != Block.fire.blockID)
    148                        {
    149                            return false;
    150                        }
    151                    }
    152                }
    153            }
    154
    155            for (l = 0; l < 2; ++l)
    156            {
    157                for (i1 = 0; i1 < 3; ++i1)
    158                {
    159                    par1World.setBlockAndMetadataWithNotify(par2 + b0 * l, par3 + i1, par4 + b1 * l, Block.portal.blockID, 0, 2);
    160                }
    161            }
    162
    163            return true;
    164        }
    165    }
    166
    167    /**
    168     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    169     * their own) Args: x, y, z, neighbor blockID
    170     */
    171    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    172    {
    173        byte b0 = 0;
    174        byte b1 = 1;
    175
    176        if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID)
    177        {
    178            b0 = 1;
    179            b1 = 0;
    180        }
    181
    182        int i1;
    183
    184        for (i1 = par3; par1World.getBlockId(par2, i1 - 1, par4) == this.blockID; --i1)
    185        {
    186            ;
    187        }
    188
    189        if (par1World.getBlockId(par2, i1 - 1, par4) != Block.obsidian.blockID)
    190        {
    191            par1World.func_94571_i(par2, par3, par4);
    192        }
    193        else
    194        {
    195            int j1;
    196
    197            for (j1 = 1; j1 < 4 && par1World.getBlockId(par2, i1 + j1, par4) == this.blockID; ++j1)
    198            {
    199                ;
    200            }
    201
    202            if (j1 == 3 && par1World.getBlockId(par2, i1 + j1, par4) == Block.obsidian.blockID)
    203            {
    204                boolean flag = par1World.getBlockId(par2 - 1, par3, par4) == this.blockID || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID;
    205                boolean flag1 = par1World.getBlockId(par2, par3, par4 - 1) == this.blockID || par1World.getBlockId(par2, par3, par4 + 1) == this.blockID;
    206
    207                if (flag && flag1)
    208                {
    209                    par1World.func_94571_i(par2, par3, par4);
    210                }
    211                else
    212                {
    213                    if ((par1World.getBlockId(par2 + b0, par3, par4 + b1) != Block.obsidian.blockID || par1World.getBlockId(par2 - b0, par3, par4 - b1) != this.blockID) && (par1World.getBlockId(par2 - b0, par3, par4 - b1) != Block.obsidian.blockID || par1World.getBlockId(par2 + b0, par3, par4 + b1) != this.blockID))
    214                    {
    215                        par1World.func_94571_i(par2, par3, par4);
    216                    }
    217                }
    218            }
    219            else
    220            {
    221                par1World.func_94571_i(par2, par3, par4);
    222            }
    223        }
    224    }
    225
    226    @SideOnly(Side.CLIENT)
    227
    228    /**
    229     * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
    230     * coordinates.  Args: blockAccess, x, y, z, side
    231     */
    232    public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    233    {
    234        if (par1IBlockAccess.getBlockId(par2, par3, par4) == this.blockID)
    235        {
    236            return false;
    237        }
    238        else
    239        {
    240            boolean flag = par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 - 2, par3, par4) != this.blockID;
    241            boolean flag1 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID && par1IBlockAccess.getBlockId(par2 + 2, par3, par4) != this.blockID;
    242            boolean flag2 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 - 2) != this.blockID;
    243            boolean flag3 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID && par1IBlockAccess.getBlockId(par2, par3, par4 + 2) != this.blockID;
    244            boolean flag4 = flag || flag1;
    245            boolean flag5 = flag2 || flag3;
    246            return flag4 && par5 == 4 ? true : (flag4 && par5 == 5 ? true : (flag5 && par5 == 2 ? true : flag5 && par5 == 3));
    247        }
    248    }
    249
    250    /**
    251     * Returns the quantity of items to drop on block destruction.
    252     */
    253    public int quantityDropped(Random par1Random)
    254    {
    255        return 0;
    256    }
    257
    258    /**
    259     * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
    260     */
    261    public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
    262    {
    263        if (par5Entity.ridingEntity == null && par5Entity.riddenByEntity == null)
    264        {
    265            par5Entity.setInPortal();
    266        }
    267    }
    268
    269    @SideOnly(Side.CLIENT)
    270
    271    /**
    272     * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
    273     */
    274    public int getRenderBlockPass()
    275    {
    276        return 1;
    277    }
    278
    279    @SideOnly(Side.CLIENT)
    280
    281    /**
    282     * A randomly called display update to be able to add particles or other items for display
    283     */
    284    public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    285    {
    286        if (par5Random.nextInt(100) == 0)
    287        {
    288            par1World.playSound((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "portal.portal", 0.5F, par5Random.nextFloat() * 0.4F + 0.8F, false);
    289        }
    290
    291        for (int l = 0; l < 4; ++l)
    292        {
    293            double d0 = (double)((float)par2 + par5Random.nextFloat());
    294            double d1 = (double)((float)par3 + par5Random.nextFloat());
    295            double d2 = (double)((float)par4 + par5Random.nextFloat());
    296            double d3 = 0.0D;
    297            double d4 = 0.0D;
    298            double d5 = 0.0D;
    299            int i1 = par5Random.nextInt(2) * 2 - 1;
    300            d3 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
    301            d4 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
    302            d5 = ((double)par5Random.nextFloat() - 0.5D) * 0.5D;
    303
    304            if (par1World.getBlockId(par2 - 1, par3, par4) != this.blockID && par1World.getBlockId(par2 + 1, par3, par4) != this.blockID)
    305            {
    306                d0 = (double)par2 + 0.5D + 0.25D * (double)i1;
    307                d3 = (double)(par5Random.nextFloat() * 2.0F * (float)i1);
    308            }
    309            else
    310            {
    311                d2 = (double)par4 + 0.5D + 0.25D * (double)i1;
    312                d5 = (double)(par5Random.nextFloat() * 2.0F * (float)i1);
    313            }
    314
    315            par1World.spawnParticle("portal", d0, d1, d2, d3, d4, d5);
    316        }
    317    }
    318
    319    @SideOnly(Side.CLIENT)
    320
    321    /**
    322     * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    323     */
    324    public int idPicked(World par1World, int par2, int par3, int par4)
    325    {
    326        return 0;
    327    }
    328}