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 }