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