    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, 172, 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()
    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 var10 = 0;
    094
    095        if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST, true))
    096        {
    097            var10 = 2;
    098        }
    099
    100        if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST, true))
    101        {
    102            var10 = 0;
    103        }
    104
    105        if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH, true))
    106        {
    107            var10 = 1;
    108        }
    109
    110        if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH, true))
    111        {
    112            var10 = 3;
    113        }
    114
    115        return var10;
    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 var6 = par1World.getBlockMetadata(par2, par3, par4);
    137                int var7 = var6 & 3;
    138                boolean var8 = false;
    139
    140                if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) && var7 == 3)
    141                {
    142                    var8 = true;
    143                }
    144
    145                if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) && var7 == 1)
    146                {
    147                    var8 = true;
    148                }
    149
    150                if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST) && var7 == 0)
    151                {
    152                    var8 = true;
    153                }
    154
    155                if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST) && var7 == 2)
    156                {
    157                    var8 = true;
    158                }
    159
    160                if (var8)
    161                {
    162                    this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
    163                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    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 var10 = par6 & 3;
    172        boolean var11 = (par6 & 4) == 4;
    173        boolean var12 = (par6 & 8) == 8;
    174        boolean var13 = par5 == Block.tripWireSource.blockID;
    175        boolean var14 = false;
    176        boolean var15 = !par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP);
    177        int var16 = Direction.offsetX[var10];
    178        int var17 = Direction.offsetZ[var10];
    179        int var18 = 0;
    180        int[] var19 = new int[42];
    181        int var21;
    182        int var20;
    183        int var23;
    184        int var22;
    185        int var24;
    186
    187        for (var20 = 1; var20 < 42; ++var20)
    188        {
    189            var21 = par2 + var16 * var20;
    190            var22 = par4 + var17 * var20;
    191            var23 = par1World.getBlockId(var21, par3, var22);
    192
    193            if (var23 == Block.tripWireSource.blockID)
    194            {
    195                var24 = par1World.getBlockMetadata(var21, par3, var22);
    196
    197                if ((var24 & 3) == Direction.footInvisibleFaceRemap[var10])
    198                {
    199                    var18 = var20;
    200                }
    201
    202                break;
    203            }
    204
    205            if (var23 != Block.tripWire.blockID && var20 != par8)
    206            {
    207                var19[var20] = -1;
    208                var13 = false;
    209            }
    210            else
    211            {
    212                var24 = var20 == par8 ? par9 : par1World.getBlockMetadata(var21, par3, var22);
    213                boolean var25 = (var24 & 8) != 8;
    214                boolean var26 = (var24 & 1) == 1;
    215                boolean var27 = (var24 & 2) == 2;
    216                var13 &= var27 == var15;
    217                var14 |= var25 && var26;
    218                var19[var20] = var24;
    219
    220                if (var20 == par8)
    221                {
    222                    par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate());
    223                    var13 &= var25;
    224                }
    225            }
    226        }
    227
    228        var13 &= var18 > 1;
    229        var14 &= var13;
    230        var20 = (var13 ? 4 : 0) | (var14 ? 8 : 0);
    231        par6 = var10 | var20;
    232
    233        if (var18 > 0)
    234        {
    235            var21 = par2 + var16 * var18;
    236            var22 = par4 + var17 * var18;
    237            var23 = Direction.footInvisibleFaceRemap[var10];
    238            par1World.setBlockMetadataWithNotify(var21, par3, var22, var23 | var20);
    239            this.notifyNeighborOfChange(par1World, var21, par3, var22, var23);
    240            this.playSoundEffect(par1World, var21, par3, var22, var13, var14, var11, var12);
    241        }
    242
    243        this.playSoundEffect(par1World, par2, par3, par4, var13, var14, var11, var12);
    244
    245        if (par5 > 0)
    246        {
    247            par1World.setBlockMetadataWithNotify(par2, par3, par4, par6);
    248
    249            if (par7)
    250            {
    251                this.notifyNeighborOfChange(par1World, par2, par3, par4, var10);
    252            }
    253        }
    254
    255        if (var11 != var13)
    256        {
    257            for (var21 = 1; var21 < var18; ++var21)
    258            {
    259                var22 = par2 + var16 * var21;
    260                var23 = par4 + var17 * var21;
    261                var24 = var19[var21];
    262
    263                if (var24 >= 0)
    264                {
    265                    if (var13)
    266                    {
    267                        var24 |= 4;
    268                    }
    269                    else
    270                    {
    271                        var24 &= -5;
    272                    }
    273
    274                    par1World.setBlockMetadataWithNotify(var22, par3, var23, var24);
    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.setBlockWithNotify(par2, par3, par4, 0);
    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 var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3;
    353        float var6 = 0.1875F;
    354
    355        if (var5 == 3)
    356        {
    357            this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
    358        }
    359        else if (var5 == 1)
    360        {
    361            this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
    362        }
    363        else if (var5 == 0)
    364        {
    365            this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
    366        }
    367        else if (var5 == 2)
    368        {
    369            this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 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 var7 = (par6 & 4) == 4;
    379        boolean var8 = (par6 & 8) == 8;
    380
    381        if (var7 || var8)
    382        {
    383            this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0);
    384        }
    385
    386        if (var8)
    387        {
    388            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
    389            int var9 = par6 & 3;
    390
    391            if (var9 == 3)
    392            {
    393                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    394            }
    395            else if (var9 == 1)
    396            {
    397                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    398            }
    399            else if (var9 == 0)
    400            {
    401                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    402            }
    403            else if (var9 == 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 boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    418    {
    419        return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8;
    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 boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    427    {
    428        int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    429
    430        if ((var6 & 8) != 8)
    431        {
    432            return false;
    433        }
    434        else
    435        {
    436            int var7 = var6 & 3;
    437            return var7 == 2 && par5 == 2 ? true : (var7 == 0 && par5 == 3 ? true : (var7 == 1 && par5 == 4 ? true : var7 == 3 && par5 == 5));
    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}