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