001 package net.minecraft.block;
002
003 import cpw.mods.fml.relauncher.Side;
004 import cpw.mods.fml.relauncher.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 import net.minecraft.creativetab.CreativeTabs;
011 import net.minecraft.world.IBlockAccess;
012 import net.minecraft.world.World;
013
014 public 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 }