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