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