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