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