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    }