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