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.List;
008    import java.util.Map;
009    import java.util.Random;
010    
011    public class BlockRedstoneTorch extends BlockTorch
012    {
013        /** Whether the redstone torch is currently active or not. */
014        private boolean torchActive = false;
015    
016        /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */
017        private static Map redstoneUpdateInfoCache = new HashMap();
018    
019        /**
020         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
021         */
022        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
023        {
024            return par1 == 1 ? Block.redstoneWire.getBlockTextureFromSideAndMetadata(par1, par2) : super.getBlockTextureFromSideAndMetadata(par1, par2);
025        }
026    
027        private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5)
028        {
029            if (!redstoneUpdateInfoCache.containsKey(par1World))
030            {
031                redstoneUpdateInfoCache.put(par1World, new ArrayList());
032            }
033    
034            List var6 = (List)redstoneUpdateInfoCache.get(par1World);
035    
036            if (par5)
037            {
038                var6.add(new RedstoneUpdateInfo(par2, par3, par4, par1World.getTotalWorldTime()));
039            }
040    
041            int var7 = 0;
042    
043            for (int var8 = 0; var8 < var6.size(); ++var8)
044            {
045                RedstoneUpdateInfo var9 = (RedstoneUpdateInfo)var6.get(var8);
046    
047                if (var9.x == par2 && var9.y == par3 && var9.z == par4)
048                {
049                    ++var7;
050    
051                    if (var7 >= 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         * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
116         * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
117         * Y, Z, side
118         */
119        public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
120        {
121            if (!this.torchActive)
122            {
123                return false;
124            }
125            else
126            {
127                int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
128                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)));
129            }
130        }
131    
132        /**
133         * Returns true or false based on whether the block the torch is attached to is providing indirect power.
134         */
135        private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4)
136        {
137            int var5 = par1World.getBlockMetadata(par2, par3, par4);
138            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))));
139        }
140    
141        /**
142         * Ticks the block if it's been scheduled
143         */
144        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
145        {
146            boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4);
147            List var7 = (List)redstoneUpdateInfoCache.get(par1World);
148    
149            while (var7 != null && !var7.isEmpty() && par1World.getTotalWorldTime() - ((RedstoneUpdateInfo)var7.get(0)).updateTime > 60L)
150            {
151                var7.remove(0);
152            }
153    
154            if (this.torchActive)
155            {
156                if (var6)
157                {
158                    par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneIdle.blockID, par1World.getBlockMetadata(par2, par3, par4));
159    
160                    if (this.checkForBurnout(par1World, par2, par3, par4, true))
161                    {
162                        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);
163    
164                        for (int var8 = 0; var8 < 5; ++var8)
165                        {
166                            double var9 = (double)par2 + par5Random.nextDouble() * 0.6D + 0.2D;
167                            double var11 = (double)par3 + par5Random.nextDouble() * 0.6D + 0.2D;
168                            double var13 = (double)par4 + par5Random.nextDouble() * 0.6D + 0.2D;
169                            par1World.spawnParticle("smoke", var9, var11, var13, 0.0D, 0.0D, 0.0D);
170                        }
171                    }
172                }
173            }
174            else if (!var6 && !this.checkForBurnout(par1World, par2, par3, par4, false))
175            {
176                par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneActive.blockID, par1World.getBlockMetadata(par2, par3, par4));
177            }
178        }
179    
180        /**
181         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
182         * their own) Args: x, y, z, neighbor blockID
183         */
184        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
185        {
186            super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
187            par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
188        }
189    
190        /**
191         * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
192         * side
193         */
194        public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
195        {
196            return par5 == 0 ? this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5) : false;
197        }
198    
199        /**
200         * Returns the ID of the items to drop on destruction.
201         */
202        public int idDropped(int par1, Random par2Random, int par3)
203        {
204            return Block.torchRedstoneActive.blockID;
205        }
206    
207        /**
208         * Can this block provide power. Only wire currently seems to have this change based on its state.
209         */
210        public boolean canProvidePower()
211        {
212            return true;
213        }
214    
215        @SideOnly(Side.CLIENT)
216    
217        /**
218         * A randomly called display update to be able to add particles or other items for display
219         */
220        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
221        {
222            if (this.torchActive)
223            {
224                int var6 = par1World.getBlockMetadata(par2, par3, par4);
225                double var7 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
226                double var9 = (double)((float)par3 + 0.7F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
227                double var11 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
228                double var13 = 0.2199999988079071D;
229                double var15 = 0.27000001072883606D;
230    
231                if (var6 == 1)
232                {
233                    par1World.spawnParticle("reddust", var7 - var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
234                }
235                else if (var6 == 2)
236                {
237                    par1World.spawnParticle("reddust", var7 + var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
238                }
239                else if (var6 == 3)
240                {
241                    par1World.spawnParticle("reddust", var7, var9 + var13, var11 - var15, 0.0D, 0.0D, 0.0D);
242                }
243                else if (var6 == 4)
244                {
245                    par1World.spawnParticle("reddust", var7, var9 + var13, var11 + var15, 0.0D, 0.0D, 0.0D);
246                }
247                else
248                {
249                    par1World.spawnParticle("reddust", var7, var9, var11, 0.0D, 0.0D, 0.0D);
250                }
251            }
252        }
253    
254        @SideOnly(Side.CLIENT)
255    
256        /**
257         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
258         */
259        public int idPicked(World par1World, int par2, int par3, int par4)
260        {
261            return Block.torchRedstoneActive.blockID;
262        }
263    }