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        /**
083         * called before onBlockPlacedBy by ItemBlock and ItemReed
084         */
085        public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8)
086        {
087            byte var9 = 0;
088    
089            if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST, true))
090            {
091                var9 = 2;
092            }
093    
094            if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST, true))
095            {
096                var9 = 0;
097            }
098    
099            if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH, true))
100            {
101                var9 = 1;
102            }
103    
104            if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH, true))
105            {
106                var9 = 3;
107            }
108    
109            this.func_72143_a(par1World, par2, par3, par4, this.blockID, var9, false, -1, 0);
110        }
111    
112        /**
113         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
114         * their own) Args: x, y, z, neighbor blockID
115         */
116        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
117        {
118            if (par5 != this.blockID)
119            {
120                if (this.func_72144_l(par1World, par2, par3, par4))
121                {
122                    int var6 = par1World.getBlockMetadata(par2, par3, par4);
123                    int var7 = var6 & 3;
124                    boolean var8 = false;
125    
126                    if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) && var7 == 3)
127                    {
128                        var8 = true;
129                    }
130    
131                    if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) && var7 == 1)
132                    {
133                        var8 = true;
134                    }
135    
136                    if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST) && var7 == 0)
137                    {
138                        var8 = true;
139                    }
140    
141                    if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST) && var7 == 2)
142                    {
143                        var8 = true;
144                    }
145    
146                    if (var8)
147                    {
148                        this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
149                        par1World.setBlockWithNotify(par2, par3, par4, 0);
150                    }
151                }
152            }
153        }
154    
155        public void func_72143_a(World par1World, int par2, int par3, int par4, int par5, int par6, boolean par7, int par8, int par9)
156        {
157            int var10 = par6 & 3;
158            boolean var11 = (par6 & 4) == 4;
159            boolean var12 = (par6 & 8) == 8;
160            boolean var13 = par5 == Block.tripWireSource.blockID;
161            boolean var14 = false;
162            boolean var15 = !par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP);
163            int var16 = Direction.offsetX[var10];
164            int var17 = Direction.offsetZ[var10];
165            int var18 = 0;
166            int[] var19 = new int[42];
167            int var21;
168            int var20;
169            int var23;
170            int var22;
171            int var24;
172    
173            for (var20 = 1; var20 < 42; ++var20)
174            {
175                var21 = par2 + var16 * var20;
176                var22 = par4 + var17 * var20;
177                var23 = par1World.getBlockId(var21, par3, var22);
178    
179                if (var23 == Block.tripWireSource.blockID)
180                {
181                    var24 = par1World.getBlockMetadata(var21, par3, var22);
182    
183                    if ((var24 & 3) == Direction.footInvisibleFaceRemap[var10])
184                    {
185                        var18 = var20;
186                    }
187    
188                    break;
189                }
190    
191                if (var23 != Block.tripWire.blockID && var20 != par8)
192                {
193                    var19[var20] = -1;
194                    var13 = false;
195                }
196                else
197                {
198                    var24 = var20 == par8 ? par9 : par1World.getBlockMetadata(var21, par3, var22);
199                    boolean var25 = (var24 & 8) != 8;
200                    boolean var26 = (var24 & 1) == 1;
201                    boolean var27 = (var24 & 2) == 2;
202                    var13 &= var27 == var15;
203                    var14 |= var25 && var26;
204                    var19[var20] = var24;
205    
206                    if (var20 == par8)
207                    {
208                        par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate());
209                        var13 &= var25;
210                    }
211                }
212            }
213    
214            var13 &= var18 > 1;
215            var14 &= var13;
216            var20 = (var13 ? 4 : 0) | (var14 ? 8 : 0);
217            par6 = var10 | var20;
218    
219            if (var18 > 0)
220            {
221                var21 = par2 + var16 * var18;
222                var22 = par4 + var17 * var18;
223                var23 = Direction.footInvisibleFaceRemap[var10];
224                par1World.setBlockMetadataWithNotify(var21, par3, var22, var23 | var20);
225                this.notifyNeighborOfChange(par1World, var21, par3, var22, var23);
226                this.playSoundEffect(par1World, var21, par3, var22, var13, var14, var11, var12);
227            }
228    
229            this.playSoundEffect(par1World, par2, par3, par4, var13, var14, var11, var12);
230    
231            if (par5 > 0)
232            {
233                par1World.setBlockMetadataWithNotify(par2, par3, par4, par6);
234    
235                if (par7)
236                {
237                    this.notifyNeighborOfChange(par1World, par2, par3, par4, var10);
238                }
239            }
240    
241            if (var11 != var13)
242            {
243                for (var21 = 1; var21 < var18; ++var21)
244                {
245                    var22 = par2 + var16 * var21;
246                    var23 = par4 + var17 * var21;
247                    var24 = var19[var21];
248    
249                    if (var24 >= 0)
250                    {
251                        if (var13)
252                        {
253                            var24 |= 4;
254                        }
255                        else
256                        {
257                            var24 &= -5;
258                        }
259    
260                        par1World.setBlockMetadataWithNotify(var22, par3, var23, var24);
261                    }
262                }
263            }
264        }
265    
266        /**
267         * Ticks the block if it's been scheduled
268         */
269        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
270        {
271            this.func_72143_a(par1World, par2, par3, par4, this.blockID, par1World.getBlockMetadata(par2, par3, par4), true, -1, 0);
272        }
273    
274        /**
275         * only of the conditions are right
276         */
277        private void playSoundEffect(World par1World, int par2, int par3, int par4, boolean par5, boolean par6, boolean par7, boolean par8)
278        {
279            if (par6 && !par8)
280            {
281                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.6F);
282            }
283            else if (!par6 && par8)
284            {
285                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.5F);
286            }
287            else if (par5 && !par7)
288            {
289                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.7F);
290            }
291            else if (!par5 && par7)
292            {
293                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));
294            }
295        }
296    
297        private void notifyNeighborOfChange(World par1World, int par2, int par3, int par4, int par5)
298        {
299            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
300    
301            if (par5 == 3)
302            {
303                par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
304            }
305            else if (par5 == 1)
306            {
307                par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
308            }
309            else if (par5 == 0)
310            {
311                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
312            }
313            else if (par5 == 2)
314            {
315                par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
316            }
317        }
318    
319        private boolean func_72144_l(World par1World, int par2, int par3, int par4)
320        {
321            if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
322            {
323                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
324                par1World.setBlockWithNotify(par2, par3, par4, 0);
325                return false;
326            }
327            else
328            {
329                return true;
330            }
331        }
332    
333        /**
334         * Updates the blocks bounds based on its current state. Args: world, x, y, z
335         */
336        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
337        {
338            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3;
339            float var6 = 0.1875F;
340    
341            if (var5 == 3)
342            {
343                this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
344            }
345            else if (var5 == 1)
346            {
347                this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
348            }
349            else if (var5 == 0)
350            {
351                this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
352            }
353            else if (var5 == 2)
354            {
355                this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
356            }
357        }
358    
359        /**
360         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
361         */
362        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
363        {
364            boolean var7 = (par6 & 4) == 4;
365            boolean var8 = (par6 & 8) == 8;
366    
367            if (var7 || var8)
368            {
369                this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0);
370            }
371    
372            if (var8)
373            {
374                par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
375                int var9 = par6 & 3;
376    
377                if (var9 == 3)
378                {
379                    par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
380                }
381                else if (var9 == 1)
382                {
383                    par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
384                }
385                else if (var9 == 0)
386                {
387                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
388                }
389                else if (var9 == 2)
390                {
391                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
392                }
393            }
394    
395            super.breakBlock(par1World, par2, par3, par4, par5, par6);
396        }
397    
398        /**
399         * Is this block powering the block on the specified side
400         */
401        public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
402        {
403            return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8;
404        }
405    
406        /**
407         * Is this block indirectly powering the block on the specified side
408         */
409        public boolean isIndirectlyPoweringTo(World par1World, int par2, int par3, int par4, int par5)
410        {
411            int var6 = par1World.getBlockMetadata(par2, par3, par4);
412    
413            if ((var6 & 8) != 8)
414            {
415                return false;
416            }
417            else
418            {
419                int var7 = var6 & 3;
420                return var7 == 2 && par5 == 2 ? true : (var7 == 0 && par5 == 3 ? true : (var7 == 1 && par5 == 4 ? true : var7 == 3 && par5 == 5));
421            }
422        }
423    
424        /**
425         * Can this block provide power. Only wire currently seems to have this change based on its state.
426         */
427        public boolean canProvidePower()
428        {
429            return true;
430        }
431    }