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        public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
083        {
084            int var11 = par9 & 8;
085            int var10 = par9 & 7;
086            var10 = -1;
087    
088            if (par5 == 0 && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN))
089            {
090                var10 = par1World.rand.nextBoolean() ? 0 : 7;
091            }
092    
093            if (par5 == 1 && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP))
094            {
095                var10 = 5 + par1World.rand.nextInt(2);
096            }
097    
098            if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
099            {
100                var10 = 4;
101            }
102    
103            if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
104            {
105                var10 = 3;
106            }
107    
108            if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
109            {
110                var10 = 2;
111            }
112    
113            if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
114            {
115                var10 = 1;
116            }
117    
118            return var10 + var11;
119        }
120    
121        /**
122         * only used in ComponentScatteredFeatureJunglePyramid.addComponentParts"
123         */
124        public static int invertMetadata(int par0)
125        {
126            switch (par0)
127            {
128                case 0:
129                    return 0;
130                case 1:
131                    return 5;
132                case 2:
133                    return 4;
134                case 3:
135                    return 3;
136                case 4:
137                    return 2;
138                case 5:
139                    return 1;
140                default:
141                    return -1;
142            }
143        }
144    
145        /**
146         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
147         * their own) Args: x, y, z, neighbor blockID
148         */
149        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
150        {
151            if (this.checkIfAttachedToBlock(par1World, par2, par3, par4))
152            {
153                int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
154                boolean var7 = false;
155    
156                if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1)
157                {
158                    var7 = true;
159                }
160    
161                if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2)
162                {
163                    var7 = true;
164                }
165    
166                if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3)
167                {
168                    var7 = true;
169                }
170    
171                if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4)
172                {
173                    var7 = true;
174                }
175    
176                if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 5)
177                {
178                    var7 = true;
179                }
180    
181                if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 6)
182                {
183                    var7 = true;
184                }
185    
186                if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 0)
187                {
188                    var7 = true;
189                }
190    
191                if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 7)
192                {
193                    var7 = true;
194                }
195    
196                if (var7)
197                {
198                    this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
199                    par1World.setBlockWithNotify(par2, par3, par4, 0);
200                }
201            }
202        }
203    
204        /**
205         * Checks if the block is attached to another block. If it is not, it returns false and drops the block as an item.
206         * If it is it returns true.
207         */
208        private boolean checkIfAttachedToBlock(World par1World, int par2, int par3, int par4)
209        {
210            if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
211            {
212                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
213                par1World.setBlockWithNotify(par2, par3, par4, 0);
214                return false;
215            }
216            else
217            {
218                return true;
219            }
220        }
221    
222        /**
223         * Updates the blocks bounds based on its current state. Args: world, x, y, z
224         */
225        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
226        {
227            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7;
228            float var6 = 0.1875F;
229    
230            if (var5 == 1)
231            {
232                this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
233            }
234            else if (var5 == 2)
235            {
236                this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
237            }
238            else if (var5 == 3)
239            {
240                this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
241            }
242            else if (var5 == 4)
243            {
244                this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
245            }
246            else if (var5 != 5 && var5 != 6)
247            {
248                if (var5 == 0 || var5 == 7)
249                {
250                    var6 = 0.25F;
251                    this.setBlockBounds(0.5F - var6, 0.4F, 0.5F - var6, 0.5F + var6, 1.0F, 0.5F + var6);
252                }
253            }
254            else
255            {
256                var6 = 0.25F;
257                this.setBlockBounds(0.5F - var6, 0.0F, 0.5F - var6, 0.5F + var6, 0.6F, 0.5F + var6);
258            }
259        }
260    
261        /**
262         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
263         */
264        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
265    
266        /**
267         * Called upon block activation (right click on the block.)
268         */
269        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
270        {
271            if (par1World.isRemote)
272            {
273                return true;
274            }
275            else
276            {
277                int var10 = par1World.getBlockMetadata(par2, par3, par4);
278                int var11 = var10 & 7;
279                int var12 = 8 - (var10 & 8);
280                par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12);
281                par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
282                par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, var12 > 0 ? 0.6F : 0.5F);
283                par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
284    
285                if (var11 == 1)
286                {
287                    par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
288                }
289                else if (var11 == 2)
290                {
291                    par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
292                }
293                else if (var11 == 3)
294                {
295                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
296                }
297                else if (var11 == 4)
298                {
299                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
300                }
301                else if (var11 != 5 && var11 != 6)
302                {
303                    if (var11 == 0 || var11 == 7)
304                    {
305                        par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
306                    }
307                }
308                else
309                {
310                    par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
311                }
312    
313                return true;
314            }
315        }
316    
317        /**
318         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
319         */
320        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
321        {
322            if ((par6 & 8) > 0)
323            {
324                par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
325                int var7 = par6 & 7;
326    
327                if (var7 == 1)
328                {
329                    par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
330                }
331                else if (var7 == 2)
332                {
333                    par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
334                }
335                else if (var7 == 3)
336                {
337                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
338                }
339                else if (var7 == 4)
340                {
341                    par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
342                }
343                else if (var7 != 5 && var7 != 6)
344                {
345                    if (var7 == 0 || var7 == 7)
346                    {
347                        par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
348                    }
349                }
350                else
351                {
352                    par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
353                }
354            }
355    
356            super.breakBlock(par1World, par2, par3, par4, par5, par6);
357        }
358    
359        /**
360         * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
361         * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
362         * Y, Z, side
363         */
364        public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
365        {
366            return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0;
367        }
368    
369        /**
370         * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
371         * side
372         */
373        public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
374        {
375            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
376    
377            if ((var6 & 8) == 0)
378            {
379                return false;
380            }
381            else
382            {
383                int var7 = var6 & 7;
384                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))))));
385            }
386        }
387    
388        /**
389         * Can this block provide power. Only wire currently seems to have this change based on its state.
390         */
391        public boolean canProvidePower()
392        {
393            return true;
394        }
395    }