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