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