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