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