001    package net.minecraft.src;
002    
003    import java.util.Random;
004    
005    import net.minecraftforge.common.ForgeDirection;
006    import static net.minecraftforge.common.ForgeDirection.*;
007    
008    public class BlockTripWireSource extends Block
009    {
010        public BlockTripWireSource(int par1)
011        {
012            super(par1, 172, Material.circuits);
013            this.setCreativeTab(CreativeTabs.tabRedstone);
014            this.setTickRandomly(true);
015        }
016    
017        /**
018         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
019         * cleared to be reused)
020         */
021        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
022        {
023            return null;
024        }
025    
026        /**
027         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
028         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
029         */
030        public boolean isOpaqueCube()
031        {
032            return false;
033        }
034    
035        /**
036         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
037         */
038        public boolean renderAsNormalBlock()
039        {
040            return false;
041        }
042    
043        /**
044         * The type of render function that is called for this block
045         */
046        public int getRenderType()
047        {
048            return 29;
049        }
050    
051        /**
052         * How many world ticks before ticking
053         */
054        public int tickRate()
055        {
056            return 10;
057        }
058    
059        /**
060         * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
061         */
062        public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5)
063        {
064            ForgeDirection dir = ForgeDirection.getOrientation(par5);
065            return (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) ||
066                   (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) ||
067                   (dir == WEST  && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST )) ||
068                   (dir == EAST  && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST ));
069        }
070    
071        /**
072         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
073         */
074        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
075        {
076            return par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) ||
077                   par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) ||
078                   par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST ) ||
079                   par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST );
080        }
081    
082        public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
083        {
084            byte var10 = 0;
085    
086            if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST, true))
087            {
088                var10 = 2;
089            }
090    
091            if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST, true))
092            {
093                var10 = 0;
094            }
095    
096            if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH, true))
097            {
098                var10 = 1;
099            }
100    
101            if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH, true))
102            {
103                var10 = 3;
104            }
105    
106            return var10;
107        }
108    
109        public void func_85105_g(World par1World, int par2, int par3, int par4, int par5)
110        {
111            this.func_72143_a(par1World, par2, par3, par4, this.blockID, par5, false, -1, 0);
112        }
113    
114        /**
115         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
116         * their own) Args: x, y, z, neighbor blockID
117         */
118        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
119        {
120            if (par5 != this.blockID)
121            {
122                if (this.func_72144_l(par1World, par2, par3, par4))
123                {
124                    int var6 = par1World.getBlockMetadata(par2, par3, par4);
125                    int var7 = var6 & 3;
126                    boolean var8 = false;
127    
128                    if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) && var7 == 3)
129                    {
130                        var8 = true;
131                    }
132    
133                    if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) && var7 == 1)
134                    {
135                        var8 = true;
136                    }
137    
138                    if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST) && var7 == 0)
139                    {
140                        var8 = true;
141                    }
142    
143                    if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST) && var7 == 2)
144                    {
145                        var8 = true;
146                    }
147    
148                    if (var8)
149                    {
150                        this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
151                        par1World.setBlockWithNotify(par2, par3, par4, 0);
152                    }
153                }
154            }
155        }
156    
157        public void func_72143_a(World par1World, int par2, int par3, int par4, int par5, int par6, boolean par7, int par8, int par9)
158        {
159            int var10 = par6 & 3;
160            boolean var11 = (par6 & 4) == 4;
161            boolean var12 = (par6 & 8) == 8;
162            boolean var13 = par5 == Block.tripWireSource.blockID;
163            boolean var14 = false;
164            boolean var15 = !par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP);
165            int var16 = Direction.offsetX[var10];
166            int var17 = Direction.offsetZ[var10];
167            int var18 = 0;
168            int[] var19 = new int[42];
169            int var21;
170            int var20;
171            int var23;
172            int var22;
173            int var24;
174    
175            for (var20 = 1; var20 < 42; ++var20)
176            {
177                var21 = par2 + var16 * var20;
178                var22 = par4 + var17 * var20;
179                var23 = par1World.getBlockId(var21, par3, var22);
180    
181                if (var23 == Block.tripWireSource.blockID)
182                {
183                    var24 = par1World.getBlockMetadata(var21, par3, var22);
184    
185                    if ((var24 & 3) == Direction.footInvisibleFaceRemap[var10])
186                    {
187                        var18 = var20;
188                    }
189    
190                    break;
191                }
192    
193                if (var23 != Block.tripWire.blockID && var20 != par8)
194                {
195                    var19[var20] = -1;
196                    var13 = false;
197                }
198                else
199                {
200                    var24 = var20 == par8 ? par9 : par1World.getBlockMetadata(var21, par3, var22);
201                    boolean var25 = (var24 & 8) != 8;
202                    boolean var26 = (var24 & 1) == 1;
203                    boolean var27 = (var24 & 2) == 2;
204                    var13 &= var27 == var15;
205                    var14 |= var25 && var26;
206                    var19[var20] = var24;
207    
208                    if (var20 == par8)
209                    {
210                        par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate());
211                        var13 &= var25;
212                    }
213                }
214            }
215    
216            var13 &= var18 > 1;
217            var14 &= var13;
218            var20 = (var13 ? 4 : 0) | (var14 ? 8 : 0);
219            par6 = var10 | var20;
220    
221            if (var18 > 0)
222            {
223                var21 = par2 + var16 * var18;
224                var22 = par4 + var17 * var18;
225                var23 = Direction.footInvisibleFaceRemap[var10];
226                par1World.setBlockMetadataWithNotify(var21, par3, var22, var23 | var20);
227                this.notifyNeighborOfChange(par1World, var21, par3, var22, var23);
228                this.playSoundEffect(par1World, var21, par3, var22, var13, var14, var11, var12);
229            }
230    
231            this.playSoundEffect(par1World, par2, par3, par4, var13, var14, var11, var12);
232    
233            if (par5 > 0)
234            {
235                par1World.setBlockMetadataWithNotify(par2, par3, par4, par6);
236    
237                if (par7)
238                {
239                    this.notifyNeighborOfChange(par1World, par2, par3, par4, var10);
240                }
241            }
242    
243            if (var11 != var13)
244            {
245                for (var21 = 1; var21 < var18; ++var21)
246                {
247                    var22 = par2 + var16 * var21;
248                    var23 = par4 + var17 * var21;
249                    var24 = var19[var21];
250    
251                    if (var24 >= 0)
252                    {
253                        if (var13)
254                        {
255                            var24 |= 4;
256                        }
257                        else
258                        {
259                            var24 &= -5;
260                        }
261    
262                        par1World.setBlockMetadataWithNotify(var22, par3, var23, var24);
263                    }
264                }
265            }
266        }
267    
268        /**
269         * Ticks the block if it's been scheduled
270         */
271        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
272        {
273            this.func_72143_a(par1World, par2, par3, par4, this.blockID, par1World.getBlockMetadata(par2, par3, par4), true, -1, 0);
274        }
275    
276        /**
277         * only of the conditions are right
278         */
279        private void playSoundEffect(World par1World, int par2, int par3, int par4, boolean par5, boolean par6, boolean par7, boolean par8)
280        {
281            if (par6 && !par8)
282            {
283                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.6F);
284            }
285            else if (!par6 && par8)
286            {
287                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.5F);
288            }
289            else if (par5 && !par7)
290            {
291                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.7F);
292            }
293            else if (!par5 && par7)
294            {
295                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.bowhit", 0.4F, 1.2F / (par1World.rand.nextFloat() * 0.2F + 0.9F));
296            }
297        }
298    
299        private void notifyNeighborOfChange(World par1World, int par2, int par3, int par4, int par5)
300        {
301            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
302    
303            if (par5 == 3)
304            {
305                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
306            }
307            else if (par5 == 1)
308            {
309                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
310            }
311            else if (par5 == 0)
312            {
313                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
314            }
315            else if (par5 == 2)
316            {
317                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
318            }
319        }
320    
321        private boolean func_72144_l(World par1World, int par2, int par3, int par4)
322        {
323            if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
324            {
325                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
326                par1World.setBlockWithNotify(par2, par3, par4, 0);
327                return false;
328            }
329            else
330            {
331                return true;
332            }
333        }
334    
335        /**
336         * Updates the blocks bounds based on its current state. Args: world, x, y, z
337         */
338        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
339        {
340            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3;
341            float var6 = 0.1875F;
342    
343            if (var5 == 3)
344            {
345                this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
346            }
347            else if (var5 == 1)
348            {
349                this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
350            }
351            else if (var5 == 0)
352            {
353                this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
354            }
355            else if (var5 == 2)
356            {
357                this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
358            }
359        }
360    
361        /**
362         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
363         */
364        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
365        {
366            boolean var7 = (par6 & 4) == 4;
367            boolean var8 = (par6 & 8) == 8;
368    
369            if (var7 || var8)
370            {
371                this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0);
372            }
373    
374            if (var8)
375            {
376                par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
377                int var9 = par6 & 3;
378    
379                if (var9 == 3)
380                {
381                    par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
382                }
383                else if (var9 == 1)
384                {
385                    par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
386                }
387                else if (var9 == 0)
388                {
389                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
390                }
391                else if (var9 == 2)
392                {
393                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
394                }
395            }
396    
397            super.breakBlock(par1World, par2, par3, par4, par5, par6);
398        }
399    
400        /**
401         * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
402         * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
403         * Y, Z, side
404         */
405        public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
406        {
407            return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8;
408        }
409    
410        /**
411         * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
412         * side
413         */
414        public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
415        {
416            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
417    
418            if ((var6 & 8) != 8)
419            {
420                return false;
421            }
422            else
423            {
424                int var7 = var6 & 3;
425                return var7 == 2 && par5 == 2 ? true : (var7 == 0 && par5 == 3 ? true : (var7 == 1 && par5 == 4 ? true : var7 == 3 && par5 == 5));
426            }
427        }
428    
429        /**
430         * Can this block provide power. Only wire currently seems to have this change based on its state.
431         */
432        public boolean canProvidePower()
433        {
434            return true;
435        }
436    }