    001    package net.minecraft.block;
    002
    003    import java.util.List;
    004    import java.util.Random;
    005    import net.minecraft.block.material.Material;
    006    import net.minecraft.creativetab.CreativeTabs;
    007    import net.minecraft.entity.Entity;
    008    import net.minecraft.entity.player.EntityPlayer;
    009    import net.minecraft.entity.projectile.EntityArrow;
    010    import net.minecraft.util.AxisAlignedBB;
    011    import net.minecraft.world.IBlockAccess;
    012    import net.minecraft.world.World;
    013
    014    import net.minecraftforge.common.ForgeDirection;
    015    import static net.minecraftforge.common.ForgeDirection.*;
    016
    017    public class BlockButton extends Block
    018    {
    019        /** Whether this button is sensible to arrows, used by wooden buttons. */
    020        protected boolean sensible;
    021
    022        protected BlockButton(int par1, int par2, boolean par3)
    023        {
    024            super(par1, par2, Material.circuits);
    025            this.setTickRandomly(true);
    026            this.setCreativeTab(CreativeTabs.tabRedstone);
    027            this.sensible = par3;
    028        }
    029
    030        /**
    031         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    032         * cleared to be reused)
    033         */
    034        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    035        {
    036            return null;
    037        }
    038
    039        /**
    040         * How many world ticks before ticking
    041         */
    042        public int tickRate()
    043        {
    044            return this.sensible ? 30 : 20;
    045        }
    046
    047        /**
    048         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    049         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    050         */
    051        public boolean isOpaqueCube()
    052        {
    053            return false;
    054        }
    055
    056        /**
    057         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    058         */
    059        public boolean renderAsNormalBlock()
    060        {
    061            return false;
    062        }
    063
    064        /**
    065         * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
    066         */
    067        public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5)
    068        {
    069            ForgeDirection dir = ForgeDirection.getOrientation(par5);
    070            return (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) ||
    071                   (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) ||
    072                   (dir == WEST  && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) ||
    073                   (dir == EAST  && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST));
    074        }
    075
    076        /**
    077         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    078         */
    079        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    080        {
    081            return (par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) ||
    082                   (par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) ||
    083                   (par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) ||
    084                   (par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH));
    085        }
    086
    087        public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
    088        {
    089            int var10 = par1World.getBlockMetadata(par2, par3, par4);
    090            int var11 = var10 & 8;
    091            var10 &= 7;
    092
    093
    094            ForgeDirection dir = ForgeDirection.getOrientation(par5);
    095
    096            if (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
    097            {
    098                var10 = 4;
    099            }
    100            else if (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
    101            {
    102                var10 = 3;
    103            }
    104            else if (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
    105            {
    106                var10 = 2;
    107            }
    108            else if (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
    109            {
    110                var10 = 1;
    111            }
    112            else
    113            {
    114                var10 = this.getOrientation(par1World, par2, par3, par4);
    115            }
    116
    117            return var10 + var11;
    118        }
    119
    120        /**
    121         * Get side which this button is facing.
    122         */
    123        private int getOrientation(World par1World, int par2, int par3, int par4)
    124        {
    125            if (par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) return 1;
    126            if (par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) return 2;
    127            if (par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) return 3;
    128            if (par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) return 4;
    129            return 1;
    130        }
    131
    132        /**
    133         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    134         * their own) Args: x, y, z, neighbor blockID
    135         */
    136        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    137        {
    138            if (this.redundantCanPlaceBlockAt(par1World, par2, par3, par4))
    139            {
    140                int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
    141                boolean var7 = false;
    142
    143                if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1)
    144                {
    145                    var7 = true;
    146                }
    147
    148                if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2)
    149                {
    150                    var7 = true;
    151                }
    152
    153                if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3)
    154                {
    155                    var7 = true;
    156                }
    157
    158                if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4)
    159                {
    160                    var7 = true;
    161                }
    162
    163                if (var7)
    164                {
    165                    this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    166                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    167                }
    168            }
    169        }
    170
    171        /**
    172         * This method is redundant, check it out...
    173         */
    174        private boolean redundantCanPlaceBlockAt(World par1World, int par2, int par3, int par4)
    175        {
    176            if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
    177            {
    178                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    179                par1World.setBlockWithNotify(par2, par3, par4, 0);
    180                return false;
    181            }
    182            else
    183            {
    184                return true;
    185            }
    186        }
    187
    188        /**
    189         * Updates the blocks bounds based on its current state. Args: world, x, y, z
    190         */
    191        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    192        {
    193            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    194            this.func_82534_e(var5);
    195        }
    196
    197        private void func_82534_e(int par1)
    198        {
    199            int var2 = par1 & 7;
    200            boolean var3 = (par1 & 8) > 0;
    201            float var4 = 0.375F;
    202            float var5 = 0.625F;
    203            float var6 = 0.1875F;
    204            float var7 = 0.125F;
    205
    206            if (var3)
    207            {
    208                var7 = 0.0625F;
    209            }
    210
    211            if (var2 == 1)
    212            {
    213                this.setBlockBounds(0.0F, var4, 0.5F - var6, var7, var5, 0.5F + var6);
    214            }
    215            else if (var2 == 2)
    216            {
    217                this.setBlockBounds(1.0F - var7, var4, 0.5F - var6, 1.0F, var5, 0.5F + var6);
    218            }
    219            else if (var2 == 3)
    220            {
    221                this.setBlockBounds(0.5F - var6, var4, 0.0F, 0.5F + var6, var5, var7);
    222            }
    223            else if (var2 == 4)
    224            {
    225                this.setBlockBounds(0.5F - var6, var4, 1.0F - var7, 0.5F + var6, var5, 1.0F);
    226            }
    227        }
    228
    229        /**
    230         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
    231         */
    232        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
    233
    234        /**
    235         * Called upon block activation (right click on the block.)
    236         */
    237        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    238        {
    239            int var10 = par1World.getBlockMetadata(par2, par3, par4);
    240            int var11 = var10 & 7;
    241            int var12 = 8 - (var10 & 8);
    242
    243            if (var12 == 0)
    244            {
    245                return true;
    246            }
    247            else
    248            {
    249                par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12);
    250                par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    251                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F);
    252                this.func_82536_d(par1World, par2, par3, par4, var11);
    253                par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
    254                return true;
    255            }
    256        }
    257
    258        /**
    259         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
    260         */
    261        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    262        {
    263            if ((par6 & 8) > 0)
    264            {
    265                int var7 = par6 & 7;
    266                this.func_82536_d(par1World, par2, par3, par4, var7);
    267            }
    268
    269            super.breakBlock(par1World, par2, par3, par4, par5, par6);
    270        }
    271
    272        /**
    273         * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
    274         * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
    275         * Y, Z, side
    276         */
    277        public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    278        {
    279            return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0;
    280        }
    281
    282        /**
    283         * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
    284         * side
    285         */
    286        public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    287        {
    288            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    289
    290            if ((var6 & 8) == 0)
    291            {
    292                return false;
    293            }
    294            else
    295            {
    296                int var7 = var6 & 7;
    297                return var7 == 5 && par5 == 1 ? true : (var7 == 4 && par5 == 2 ? true : (var7 == 3 && par5 == 3 ? true : (var7 == 2 && par5 == 4 ? true : var7 == 1 && par5 == 5)));
    298            }
    299        }
    300
    301        /**
    302         * Can this block provide power. Only wire currently seems to have this change based on its state.
    303         */
    304        public boolean canProvidePower()
    305        {
    306            return true;
    307        }
    308
    309        /**
    310         * Ticks the block if it's been scheduled
    311         */
    312        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    313        {
    314            if (!par1World.isRemote)
    315            {
    316                int var6 = par1World.getBlockMetadata(par2, par3, par4);
    317
    318                if ((var6 & 8) != 0)
    319                {
    320                    if (this.sensible)
    321                    {
    322                        this.func_82535_o(par1World, par2, par3, par4);
    323                    }
    324                    else
    325                    {
    326                        par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 & 7);
    327                        int var7 = var6 & 7;
    328                        this.func_82536_d(par1World, par2, par3, par4, var7);
    329                        par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F);
    330                        par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    331                    }
    332                }
    333            }
    334        }
    335
    336        /**
    337         * Sets the block's bounds for rendering it as an item
    338         */
    339        public void setBlockBoundsForItemRender()
    340        {
    341            float var1 = 0.1875F;
    342            float var2 = 0.125F;
    343            float var3 = 0.125F;
    344            this.setBlockBounds(0.5F - var1, 0.5F - var2, 0.5F - var3, 0.5F + var1, 0.5F + var2, 0.5F + var3);
    345        }
    346
    347        /**
    348         * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
    349         */
    350        public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
    351        {
    352            if (!par1World.isRemote)
    353            {
    354                if (this.sensible)
    355                {
    356                    if ((par1World.getBlockMetadata(par2, par3, par4) & 8) == 0)
    357                    {
    358                        this.func_82535_o(par1World, par2, par3, par4);
    359                    }
    360                }
    361            }
    362        }
    363
    364        protected void func_82535_o(World par1World, int par2, int par3, int par4)
    365        {
    366            int var5 = par1World.getBlockMetadata(par2, par3, par4);
    367            int var6 = var5 & 7;
    368            boolean var7 = (var5 & 8) != 0;
    369            this.func_82534_e(var5);
    370            List var9 = par1World.getEntitiesWithinAABB(EntityArrow.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)par3 + this.maxY, (double)par4 + this.maxZ));
    371            boolean var8 = !var9.isEmpty();
    372
    373            if (var8 && !var7)
    374            {
    375                par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 | 8);
    376                this.func_82536_d(par1World, par2, par3, par4, var6);
    377                par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    378                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F);
    379            }
    380
    381            if (!var8 && var7)
    382            {
    383                par1World.setBlockMetadataWithNotify(par2, par3, par4, var6);
    384                this.func_82536_d(par1World, par2, par3, par4, var6);
    385                par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    386                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F);
    387            }
    388
    389            if (var8)
    390            {
    391                par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
    392            }
    393        }
    394
    395        private void func_82536_d(World par1World, int par2, int par3, int par4, int par5)
    396        {
    397            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
    398
    399            if (par5 == 1)
    400            {
    401                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    402            }
    403            else if (par5 == 2)
    404            {
    405                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    406            }
    407            else if (par5 == 3)
    408            {
    409                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    410            }
    411            else if (par5 == 4)
    412            {
    413                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    414            }
    415            else
    416            {
    417                par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    418            }
    419        }
    420    }