001    package net.minecraft.block;
002    
003    import net.minecraft.block.material.Material;
004    import net.minecraft.creativetab.CreativeTabs;
005    import net.minecraft.entity.player.EntityPlayer;
006    import net.minecraft.util.AxisAlignedBB;
007    import net.minecraft.world.IBlockAccess;
008    import net.minecraft.world.World;
009    
010    import net.minecraftforge.common.ForgeDirection;
011    import static net.minecraftforge.common.ForgeDirection.*;
012    
013    public 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    }