    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.ArrayList;
    006    import java.util.HashMap;
    007    import java.util.Iterator;
    008    import java.util.List;
    009    import java.util.Map;
    010    import java.util.Random;
    011
    012    public class BlockRedstoneTorch extends BlockTorch
    013    {
    014        /** Whether the redstone torch is currently active or not. */
    015        private boolean torchActive = false;
    016
    017        /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */
    018        private static Map redstoneUpdateInfoCache = new HashMap();
    019
    020        /**
    021         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    022         */
    023        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
    024        {
    025            return par1 == 1 ? Block.redstoneWire.getBlockTextureFromSideAndMetadata(par1, par2) : super.getBlockTextureFromSideAndMetadata(par1, par2);
    026        }
    027
    028        private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5)
    029        {
    030            if (!redstoneUpdateInfoCache.containsKey(par1World))
    031            {
    032                redstoneUpdateInfoCache.put(par1World, new ArrayList());
    033            }
    034
    035            if (par5)
    036            {
    037                ((List)redstoneUpdateInfoCache.get(par1World)).add(new RedstoneUpdateInfo(par2, par3, par4, par1World.getWorldTime()));
    038            }
    039
    040            int var6 = 0;
    041            Iterator var7 = ((List)redstoneUpdateInfoCache.get(par1World)).iterator();
    042
    043            while (var7.hasNext())
    044            {
    045                RedstoneUpdateInfo var8 = (RedstoneUpdateInfo)var7.next();
    046
    047                if (var8.x == par2 && var8.y == par3 && var8.z == par4)
    048                {
    049                    ++var6;
    050
    051                    if (var6 >= 8)
    052                    {
    053                        return true;
    054                    }
    055                }
    056            }
    057
    058            return false;
    059        }
    060
    061        protected BlockRedstoneTorch(int par1, int par2, boolean par3)
    062        {
    063            super(par1, par2);
    064            this.torchActive = par3;
    065            this.setTickRandomly(true);
    066            this.setCreativeTab((CreativeTabs)null);
    067        }
    068
    069        /**
    070         * How many world ticks before ticking
    071         */
    072        public int tickRate()
    073        {
    074            return 2;
    075        }
    076
    077        /**
    078         * Called whenever the block is added into the world. Args: world, x, y, z
    079         */
    080        public void onBlockAdded(World par1World, int par2, int par3, int par4)
    081        {
    082            if (par1World.getBlockMetadata(par2, par3, par4) == 0)
    083            {
    084                super.onBlockAdded(par1World, par2, par3, par4);
    085            }
    086
    087            if (this.torchActive)
    088            {
    089                par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    090                par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
    091                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    092                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    093                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    094                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    095            }
    096        }
    097
    098        /**
    099         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
    100         */
    101        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    102        {
    103            if (this.torchActive)
    104            {
    105                par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
    106                par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
    107                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
    108                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
    109                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
    110                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
    111            }
    112        }
    113
    114        /**
    115         * Is this block powering the block on the specified side
    116         */
    117        public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    118        {
    119            if (!this.torchActive)
    120            {
    121                return false;
    122            }
    123            else
    124            {
    125                int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    126                return var6 == 5 && par5 == 1 ? false : (var6 == 3 && par5 == 3 ? false : (var6 == 4 && par5 == 2 ? false : (var6 == 1 && par5 == 5 ? false : var6 != 2 || par5 != 4)));
    127            }
    128        }
    129
    130        /**
    131         * Returns true or false based on whether the block the torch is attached to is providing indirect power.
    132         */
    133        private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4)
    134        {
    135            int var5 = par1World.getBlockMetadata(par2, par3, par4);
    136            return var5 == 5 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3 - 1, par4, 0) ? true : (var5 == 3 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 - 1, 2) ? true : (var5 == 4 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 + 1, 3) ? true : (var5 == 1 && par1World.isBlockIndirectlyProvidingPowerTo(par2 - 1, par3, par4, 4) ? true : var5 == 2 && par1World.isBlockIndirectlyProvidingPowerTo(par2 + 1, par3, par4, 5))));
    137        }
    138
    139        /**
    140         * Ticks the block if it's been scheduled
    141         */
    142        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    143        {
    144            boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4);
    145            List var7 = (List)redstoneUpdateInfoCache.get(par1World);
    146
    147            while (var7 != null && !var7.isEmpty() && par1World.getWorldTime() - ((RedstoneUpdateInfo)var7.get(0)).updateTime > 60L)
    148            {
    149                var7.remove(0);
    150            }
    151
    152            if (this.torchActive)
    153            {
    154                if (var6)
    155                {
    156                    par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneIdle.blockID, par1World.getBlockMetadata(par2, par3, par4));
    157
    158                    if (this.checkForBurnout(par1World, par2, par3, par4, true))
    159                    {
    160                        par1World.playSoundEffect((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "random.fizz", 0.5F, 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F);
    161
    162                        for (int var8 = 0; var8 < 5; ++var8)
    163                        {
    164                            double var9 = (double)par2 + par5Random.nextDouble() * 0.6D + 0.2D;
    165                            double var11 = (double)par3 + par5Random.nextDouble() * 0.6D + 0.2D;
    166                            double var13 = (double)par4 + par5Random.nextDouble() * 0.6D + 0.2D;
    167                            par1World.spawnParticle("smoke", var9, var11, var13, 0.0D, 0.0D, 0.0D);
    168                        }
    169                    }
    170                }
    171            }
    172            else if (!var6 && !this.checkForBurnout(par1World, par2, par3, par4, false))
    173            {
    174                par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneActive.blockID, par1World.getBlockMetadata(par2, par3, par4));
    175            }
    176        }
    177
    178        /**
    179         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    180         * their own) Args: x, y, z, neighbor blockID
    181         */
    182        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    183        {
    184            super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
    185            par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
    186        }
    187
    188        /**
    189         * Is this block indirectly powering the block on the specified side
    190         */
    191        public boolean isIndirectlyPoweringTo(World par1World, int par2, int par3, int par4, int par5)
    192        {
    193            return par5 == 0 ? this.isPoweringTo(par1World, par2, par3, par4, par5) : false;
    194        }
    195
    196        /**
    197         * Returns the ID of the items to drop on destruction.
    198         */
    199        public int idDropped(int par1, Random par2Random, int par3)
    200        {
    201            return Block.torchRedstoneActive.blockID;
    202        }
    203
    204        /**
    205         * Can this block provide power. Only wire currently seems to have this change based on its state.
    206         */
    207        public boolean canProvidePower()
    208        {
    209            return true;
    210        }
    211
    212        @SideOnly(Side.CLIENT)
    213
    214        /**
    215         * A randomly called display update to be able to add particles or other items for display
    216         */
    217        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    218        {
    219            if (this.torchActive)
    220            {
    221                int var6 = par1World.getBlockMetadata(par2, par3, par4);
    222                double var7 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    223                double var9 = (double)((float)par3 + 0.7F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    224                double var11 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
    225                double var13 = 0.2199999988079071D;
    226                double var15 = 0.27000001072883606D;
    227
    228                if (var6 == 1)
    229                {
    230                    par1World.spawnParticle("reddust", var7 - var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
    231                }
    232                else if (var6 == 2)
    233                {
    234                    par1World.spawnParticle("reddust", var7 + var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
    235                }
    236                else if (var6 == 3)
    237                {
    238                    par1World.spawnParticle("reddust", var7, var9 + var13, var11 - var15, 0.0D, 0.0D, 0.0D);
    239                }
    240                else if (var6 == 4)
    241                {
    242                    par1World.spawnParticle("reddust", var7, var9 + var13, var11 + var15, 0.0D, 0.0D, 0.0D);
    243                }
    244                else
    245                {
    246                    par1World.spawnParticle("reddust", var7, var9, var11, 0.0D, 0.0D, 0.0D);
    247                }
    248            }
    249        }
    250
    251        @SideOnly(Side.CLIENT)
    252
    253        /**
    254         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    255         */
    256        public int idPicked(World par1World, int par2, int par3, int par4)
    257        {
    258            return Block.torchRedstoneActive.blockID;
    259        }
    260
    261        /**
    262         * Called when the time changes.
    263         */
    264        public void onTimeChanged(World par1World, long par2, long par4)
    265        {
    266            List var6 = (List)redstoneUpdateInfoCache.get(par1World);
    267            RedstoneUpdateInfo var8;
    268
    269            if (var6 != null)
    270            {
    271                for (Iterator var7 = var6.iterator(); var7.hasNext(); var8.updateTime += par2)
    272                {
    273                    var8 = (RedstoneUpdateInfo)var7.next();
    274                }
    275            }
    276        }
    277    }