    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.util.Random;
    006
    007    public class BlockRedstoneRepeater extends BlockDirectional
    008    {
    009        /** The offsets for the two torches in redstone repeater blocks. */
    010        public static final double[] repeaterTorchOffset = new double[] { -0.0625D, 0.0625D, 0.1875D, 0.3125D};
    011
    012        /** The states in which the redstone repeater blocks can be. */
    013        private static final int[] repeaterState = new int[] {1, 2, 3, 4};
    014
    015        /** Tells whether the repeater is powered or not */
    016        private final boolean isRepeaterPowered;
    017
    018        protected BlockRedstoneRepeater(int par1, boolean par2)
    019        {
    020            super(par1, 6, Material.circuits);
    021            this.isRepeaterPowered = par2;
    022            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
    023        }
    024
    025        /**
    026         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    027         */
    028        public boolean renderAsNormalBlock()
    029        {
    030            return false;
    031        }
    032
    033        /**
    034         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    035         */
    036        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    037        {
    038            return !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? false : super.canPlaceBlockAt(par1World, par2, par3, par4);
    039        }
    040
    041        /**
    042         * Can this block stay at this position.  Similar to canPlaceBlockAt except gets checked often with plants.
    043         */
    044        public boolean canBlockStay(World par1World, int par2, int par3, int par4)
    045        {
    046            return !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? false : super.canBlockStay(par1World, par2, par3, par4);
    047        }
    048
    049        /**
    050         * Ticks the block if it's been scheduled
    051         */
    052        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    053        {
    054            int var6 = par1World.getBlockMetadata(par2, par3, par4);
    055            boolean var7 = this.ignoreTick(par1World, par2, par3, par4, var6);
    056
    057            if (this.isRepeaterPowered && !var7)
    058            {
    059                par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.redstoneRepeaterIdle.blockID, var6);
    060            }
    061            else if (!this.isRepeaterPowered)
    062            {
    063                par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.redstoneRepeaterActive.blockID, var6);
    064
    065                if (!var7)
    066                {
    067                    int var8 = (var6 & 12) >> 2;
    068                    par1World.scheduleBlockUpdate(par2, par3, par4, Block.redstoneRepeaterActive.blockID, repeaterState[var8] * 2);
    069                }
    070            }
    071        }
    072
    073        /**
    074         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    075         */
    076        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
    077        {
    078            return par1 == 0 ? (this.isRepeaterPowered ? 99 : 115) : (par1 == 1 ? (this.isRepeaterPowered ? 147 : 131) : 5);
    079        }
    080
    081        @SideOnly(Side.CLIENT)
    082
    083        /**
    084         * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
    085         * coordinates.  Args: blockAccess, x, y, z, side
    086         */
    087        public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    088        {
    089            return par5 != 0 && par5 != 1;
    090        }
    091
    092        /**
    093         * The type of render function that is called for this block
    094         */
    095        public int getRenderType()
    096        {
    097            return 15;
    098        }
    099
    100        /**
    101         * Returns the block texture based on the side being looked at.  Args: side
    102         */
    103        public int getBlockTextureFromSide(int par1)
    104        {
    105            return this.getBlockTextureFromSideAndMetadata(par1, 0);
    106        }
    107
    108        /**
    109         * Is this block indirectly powering the block on the specified side
    110         */
    111        public boolean isIndirectlyPoweringTo(World par1World, int par2, int par3, int par4, int par5)
    112        {
    113            return this.isPoweringTo(par1World, par2, par3, par4, par5);
    114        }
    115
    116        /**
    117         * Is this block powering the block on the specified side
    118         */
    119        public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    120        {
    121            if (!this.isRepeaterPowered)
    122            {
    123                return false;
    124            }
    125            else
    126            {
    127                int var6 = getDirection(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
    128                return var6 == 0 && par5 == 3 ? true : (var6 == 1 && par5 == 4 ? true : (var6 == 2 && par5 == 2 ? true : var6 == 3 && par5 == 5));
    129            }
    130        }
    131
    132        /**
    133         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    134         * their own) Args: x, y, z, neighbor blockID
    135         */
    136        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    137        {
    138            if (!this.canBlockStay(par1World, par2, par3, par4))
    139            {
    140                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    141                par1World.setBlockWithNotify(par2, par3, par4, 0);
    142                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    143                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    144                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    145                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    146                par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    147                par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
    148            }
    149            else
    150            {
    151                int var6 = par1World.getBlockMetadata(par2, par3, par4);
    152                boolean var7 = this.ignoreTick(par1World, par2, par3, par4, var6);
    153                int var8 = (var6 & 12) >> 2;
    154
    155                if (this.isRepeaterPowered && !var7 || !this.isRepeaterPowered && var7)
    156                {
    157                    par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, repeaterState[var8] * 2);
    158                }
    159            }
    160        }
    161
    162        private boolean ignoreTick(World par1World, int par2, int par3, int par4, int par5)
    163        {
    164            int var6 = getDirection(par5);
    165
    166            switch (var6)
    167            {
    168                case 0:
    169                    return par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 + 1, 3) || par1World.getBlockId(par2, par3, par4 + 1) == Block.redstoneWire.blockID && par1World.getBlockMetadata(par2, par3, par4 + 1) > 0;
    170                case 1:
    171                    return par1World.isBlockIndirectlyProvidingPowerTo(par2 - 1, par3, par4, 4) || par1World.getBlockId(par2 - 1, par3, par4) == Block.redstoneWire.blockID && par1World.getBlockMetadata(par2 - 1, par3, par4) > 0;
    172                case 2:
    173                    return par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 - 1, 2) || par1World.getBlockId(par2, par3, par4 - 1) == Block.redstoneWire.blockID && par1World.getBlockMetadata(par2, par3, par4 - 1) > 0;
    174                case 3:
    175                    return par1World.isBlockIndirectlyProvidingPowerTo(par2 + 1, par3, par4, 5) || par1World.getBlockId(par2 + 1, par3, par4) == Block.redstoneWire.blockID && par1World.getBlockMetadata(par2 + 1, par3, par4) > 0;
    176                default:
    177                    return false;
    178            }
    179        }
    180
    181        /**
    182         * Called upon block activation (right click on the block.)
    183         */
    184        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    185        {
    186            int var10 = par1World.getBlockMetadata(par2, par3, par4);
    187            int var11 = (var10 & 12) >> 2;
    188            var11 = var11 + 1 << 2 & 12;
    189            par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 | var10 & 3);
    190            return true;
    191        }
    192
    193        /**
    194         * Can this block provide power. Only wire currently seems to have this change based on its state.
    195         */
    196        public boolean canProvidePower()
    197        {
    198            return true;
    199        }
    200
    201        /**
    202         * Called when the block is placed in the world.
    203         */
    204        public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
    205        {
    206            int var6 = ((MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 2) % 4;
    207            par1World.setBlockMetadataWithNotify(par2, par3, par4, var6);
    208            boolean var7 = this.ignoreTick(par1World, par2, par3, par4, var6);
    209
    210            if (var7)
    211            {
    212                par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 1);
    213            }
    214        }
    215
    216        /**
    217         * Called whenever the block is added into the world. Args: world, x, y, z
    218         */
    219        public void onBlockAdded(World par1World, int par2, int par3, int par4)
    220        {
    221            par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    222            par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    223            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    224            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    225            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    226            par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
    227        }
    228
    229        /**
    230         * Called right before the block is destroyed by a player.  Args: world, x, y, z, metaData
    231         */
    232        public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5)
    233        {
    234            if (this.isRepeaterPowered)
    235            {
    236                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    237                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    238                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    239                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    240                par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    241                par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
    242            }
    243
    244            super.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
    245        }
    246
    247        /**
    248         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    249         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    250         */
    251        public boolean isOpaqueCube()
    252        {
    253            return false;
    254        }
    255
    256        /**
    257         * Returns the ID of the items to drop on destruction.
    258         */
    259        public int idDropped(int par1, Random par2Random, int par3)
    260        {
    261            return Item.redstoneRepeater.shiftedIndex;
    262        }
    263
    264        @SideOnly(Side.CLIENT)
    265
    266        /**
    267         * A randomly called display update to be able to add particles or other items for display
    268         */
    269        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    270        {
    271            if (this.isRepeaterPowered)
    272            {
    273                int var6 = par1World.getBlockMetadata(par2, par3, par4);
    274                int var7 = getDirection(var6);
    275                double var8 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    276                double var10 = (double)((float)par3 + 0.4F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    277                double var12 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    278                double var14 = 0.0D;
    279                double var16 = 0.0D;
    280
    281                if (par5Random.nextInt(2) == 0)
    282                {
    283                    switch (var7)
    284                    {
    285                        case 0:
    286                            var16 = -0.3125D;
    287                            break;
    288                        case 1:
    289                            var14 = 0.3125D;
    290                            break;
    291                        case 2:
    292                            var16 = 0.3125D;
    293                            break;
    294                        case 3:
    295                            var14 = -0.3125D;
    296                    }
    297                }
    298                else
    299                {
    300                    int var18 = (var6 & 12) >> 2;
    301
    302                    switch (var7)
    303                    {
    304                        case 0:
    305                            var16 = repeaterTorchOffset[var18];
    306                            break;
    307                        case 1:
    308                            var14 = -repeaterTorchOffset[var18];
    309                            break;
    310                        case 2:
    311                            var16 = -repeaterTorchOffset[var18];
    312                            break;
    313                        case 3:
    314                            var14 = repeaterTorchOffset[var18];
    315                    }
    316                }
    317
    318                par1World.spawnParticle("reddust", var8 + var14, var10, var12 + var16, 0.0D, 0.0D, 0.0D);
    319            }
    320        }
    321
    322        @SideOnly(Side.CLIENT)
    323
    324        /**
    325         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    326         */
    327        public int idPicked(World par1World, int par2, int par3, int par4)
    328        {
    329            return Item.redstoneRepeater.shiftedIndex;
    330        }
    331    }