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.creativetab.CreativeTabs;
011import net.minecraft.world.IBlockAccess;
012import net.minecraft.world.World;
013
014public class BlockRedstoneTorch extends BlockTorch
015{
016    /** Whether the redstone torch is currently active or not. */
017    private boolean torchActive = false;
018
019    /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */
020    private static Map redstoneUpdateInfoCache = new HashMap();
021
022    /**
023     * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
024     */
025    public int getBlockTextureFromSideAndMetadata(int par1, int par2)
026    {
027        return par1 == 1 ? Block.redstoneWire.getBlockTextureFromSideAndMetadata(par1, par2) : super.getBlockTextureFromSideAndMetadata(par1, par2);
028    }
029
030    private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5)
031    {
032        if (!redstoneUpdateInfoCache.containsKey(par1World))
033        {
034            redstoneUpdateInfoCache.put(par1World, new ArrayList());
035        }
036
037        List var6 = (List)redstoneUpdateInfoCache.get(par1World);
038
039        if (par5)
040        {
041            var6.add(new RedstoneUpdateInfo(par2, par3, par4, par1World.getTotalWorldTime()));
042        }
043
044        int var7 = 0;
045
046        for (int var8 = 0; var8 < var6.size(); ++var8)
047        {
048            RedstoneUpdateInfo var9 = (RedstoneUpdateInfo)var6.get(var8);
049
050            if (var9.x == par2 && var9.y == par3 && var9.z == par4)
051            {
052                ++var7;
053
054                if (var7 >= 8)
055                {
056                    return true;
057                }
058            }
059        }
060
061        return false;
062    }
063
064    protected BlockRedstoneTorch(int par1, int par2, boolean par3)
065    {
066        super(par1, par2);
067        this.torchActive = par3;
068        this.setTickRandomly(true);
069        this.setCreativeTab((CreativeTabs)null);
070    }
071
072    /**
073     * How many world ticks before ticking
074     */
075    public int tickRate()
076    {
077        return 2;
078    }
079
080    /**
081     * Called whenever the block is added into the world. Args: world, x, y, z
082     */
083    public void onBlockAdded(World par1World, int par2, int par3, int par4)
084    {
085        if (par1World.getBlockMetadata(par2, par3, par4) == 0)
086        {
087            super.onBlockAdded(par1World, par2, par3, par4);
088        }
089
090        if (this.torchActive)
091        {
092            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
093            par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
094            par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
095            par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
096            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
097            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
098        }
099    }
100
101    /**
102     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
103     */
104    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
105    {
106        if (this.torchActive)
107        {
108            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
109            par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
110            par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
111            par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
112            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
113            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
114        }
115    }
116
117    /**
118     * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
119     * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
120     * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
121     */
122    public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
123    {
124        if (!this.torchActive)
125        {
126            return false;
127        }
128        else
129        {
130            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
131            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)));
132        }
133    }
134
135    /**
136     * Returns true or false based on whether the block the torch is attached to is providing indirect power.
137     */
138    private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4)
139    {
140        int var5 = par1World.getBlockMetadata(par2, par3, par4);
141        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))));
142    }
143
144    /**
145     * Ticks the block if it's been scheduled
146     */
147    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
148    {
149        boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4);
150        List var7 = (List)redstoneUpdateInfoCache.get(par1World);
151
152        while (var7 != null && !var7.isEmpty() && par1World.getTotalWorldTime() - ((RedstoneUpdateInfo)var7.get(0)).updateTime > 60L)
153        {
154            var7.remove(0);
155        }
156
157        if (this.torchActive)
158        {
159            if (var6)
160            {
161                par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneIdle.blockID, par1World.getBlockMetadata(par2, par3, par4));
162
163                if (this.checkForBurnout(par1World, par2, par3, par4, true))
164                {
165                    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);
166
167                    for (int var8 = 0; var8 < 5; ++var8)
168                    {
169                        double var9 = (double)par2 + par5Random.nextDouble() * 0.6D + 0.2D;
170                        double var11 = (double)par3 + par5Random.nextDouble() * 0.6D + 0.2D;
171                        double var13 = (double)par4 + par5Random.nextDouble() * 0.6D + 0.2D;
172                        par1World.spawnParticle("smoke", var9, var11, var13, 0.0D, 0.0D, 0.0D);
173                    }
174                }
175            }
176        }
177        else if (!var6 && !this.checkForBurnout(par1World, par2, par3, par4, false))
178        {
179            par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneActive.blockID, par1World.getBlockMetadata(par2, par3, par4));
180        }
181    }
182
183    /**
184     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
185     * their own) Args: x, y, z, neighbor blockID
186     */
187    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
188    {
189        super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
190        par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
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 boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
198    {
199        return par5 == 0 ? this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5) : false;
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 var6 = par1World.getBlockMetadata(par2, par3, par4);
228            double var7 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
229            double var9 = (double)((float)par3 + 0.7F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
230            double var11 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D;
231            double var13 = 0.2199999988079071D;
232            double var15 = 0.27000001072883606D;
233
234            if (var6 == 1)
235            {
236                par1World.spawnParticle("reddust", var7 - var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
237            }
238            else if (var6 == 2)
239            {
240                par1World.spawnParticle("reddust", var7 + var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D);
241            }
242            else if (var6 == 3)
243            {
244                par1World.spawnParticle("reddust", var7, var9 + var13, var11 - var15, 0.0D, 0.0D, 0.0D);
245            }
246            else if (var6 == 4)
247            {
248                par1World.spawnParticle("reddust", var7, var9 + var13, var11 + var15, 0.0D, 0.0D, 0.0D);
249            }
250            else
251            {
252                par1World.spawnParticle("reddust", var7, var9, var11, 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}