001package net.minecraft.block;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.Random;
006import net.minecraft.block.material.Material;
007import net.minecraft.client.renderer.texture.IconRegister;
008import net.minecraft.creativetab.CreativeTabs;
009import net.minecraft.entity.Entity;
010import net.minecraft.util.AxisAlignedBB;
011import net.minecraft.world.IBlockAccess;
012import net.minecraft.world.World;
013
014public abstract class BlockBasePressurePlate extends Block
015{
016    private String field_94356_a;
017
018    protected BlockBasePressurePlate(int par1, String par2Str, Material par3Material)
019    {
020        super(par1, par3Material);
021        this.field_94356_a = par2Str;
022        this.setCreativeTab(CreativeTabs.tabRedstone);
023        this.setTickRandomly(true);
024        this.func_94353_c_(this.func_94355_d(15));
025    }
026
027    /**
028     * Updates the blocks bounds based on its current state. Args: world, x, y, z
029     */
030    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
031    {
032        this.func_94353_c_(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
033    }
034
035    protected void func_94353_c_(int par1)
036    {
037        boolean flag = this.func_94350_c(par1) > 0;
038        float f = 0.0625F;
039
040        if (flag)
041        {
042            this.setBlockBounds(f, 0.0F, f, 1.0F - f, 0.03125F, 1.0F - f);
043        }
044        else
045        {
046            this.setBlockBounds(f, 0.0F, f, 1.0F - f, 0.0625F, 1.0F - f);
047        }
048    }
049
050    /**
051     * How many world ticks before ticking
052     */
053    public int tickRate(World par1World)
054    {
055        return 20;
056    }
057
058    /**
059     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
060     * cleared to be reused)
061     */
062    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
063    {
064        return null;
065    }
066
067    /**
068     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
069     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
070     */
071    public boolean isOpaqueCube()
072    {
073        return false;
074    }
075
076    /**
077     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
078     */
079    public boolean renderAsNormalBlock()
080    {
081        return false;
082    }
083
084    public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
085    {
086        return true;
087    }
088
089    /**
090     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
091     */
092    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
093    {
094        return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4));
095    }
096
097    /**
098     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
099     * their own) Args: x, y, z, neighbor blockID
100     */
101    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
102    {
103        boolean flag = false;
104
105        if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4)))
106        {
107            flag = true;
108        }
109
110        if (flag)
111        {
112            this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
113            par1World.setBlockToAir(par2, par3, par4);
114        }
115    }
116
117    /**
118     * Ticks the block if it's been scheduled
119     */
120    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
121    {
122        if (!par1World.isRemote)
123        {
124            int l = this.func_94350_c(par1World.getBlockMetadata(par2, par3, par4));
125
126            if (l > 0)
127            {
128                this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4, l);
129            }
130        }
131    }
132
133    /**
134     * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
135     */
136    public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
137    {
138        if (!par1World.isRemote)
139        {
140            int l = this.func_94350_c(par1World.getBlockMetadata(par2, par3, par4));
141
142            if (l == 0)
143            {
144                this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4, l);
145            }
146        }
147    }
148
149    /**
150     * Checks if there are mobs on the plate. If a mob is on the plate and it is off, it turns it on, and vice versa.
151     */
152    protected void setStateIfMobInteractsWithPlate(World par1World, int par2, int par3, int par4, int par5)
153    {
154        int i1 = this.func_94351_d(par1World, par2, par3, par4);
155        boolean flag = par5 > 0;
156        boolean flag1 = i1 > 0;
157
158        if (par5 != i1)
159        {
160            par1World.setBlockMetadataWithNotify(par2, par3, par4, this.func_94355_d(i1), 2);
161            this.func_94354_b_(par1World, par2, par3, par4);
162            par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
163        }
164
165        if (!flag1 && flag)
166        {
167            par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F);
168        }
169        else if (flag1 && !flag)
170        {
171            par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F);
172        }
173
174        if (flag1)
175        {
176            par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
177        }
178    }
179
180    protected AxisAlignedBB func_94352_a(int par1, int par2, int par3)
181    {
182        float f = 0.125F;
183        return AxisAlignedBB.getAABBPool().getAABB((double)((float)par1 + f), (double)par2, (double)((float)par3 + f), (double)((float)(par1 + 1) - f), (double)par2 + 0.25D, (double)((float)(par3 + 1) - f));
184    }
185
186    /**
187     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
188     */
189    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
190    {
191        if (this.func_94350_c(par6) > 0)
192        {
193            this.func_94354_b_(par1World, par2, par3, par4);
194        }
195
196        super.breakBlock(par1World, par2, par3, par4, par5, par6);
197    }
198
199    protected void func_94354_b_(World par1World, int par2, int par3, int par4)
200    {
201        par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
202        par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
203    }
204
205    /**
206     * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
207     * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
208     * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
209     */
210    public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
211    {
212        return this.func_94350_c(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
213    }
214
215    /**
216     * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
217     * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
218     */
219    public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
220    {
221        return par5 == 1 ? this.func_94350_c(par1IBlockAccess.getBlockMetadata(par2, par3, par4)) : 0;
222    }
223
224    /**
225     * Can this block provide power. Only wire currently seems to have this change based on its state.
226     */
227    public boolean canProvidePower()
228    {
229        return true;
230    }
231
232    /**
233     * Sets the block's bounds for rendering it as an item
234     */
235    public void setBlockBoundsForItemRender()
236    {
237        float f = 0.5F;
238        float f1 = 0.125F;
239        float f2 = 0.5F;
240        this.setBlockBounds(0.5F - f, 0.5F - f1, 0.5F - f2, 0.5F + f, 0.5F + f1, 0.5F + f2);
241    }
242
243    /**
244     * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
245     * and stop pistons
246     */
247    public int getMobilityFlag()
248    {
249        return 1;
250    }
251
252    protected abstract int func_94351_d(World world, int i, int j, int k);
253
254    protected abstract int func_94350_c(int i);
255
256    protected abstract int func_94355_d(int i);
257
258    @SideOnly(Side.CLIENT)
259
260    /**
261     * When this method is called, your block should register all the icons it needs with the given IconRegister. This
262     * is the only chance you get to register icons.
263     */
264    public void registerIcons(IconRegister par1IconRegister)
265    {
266        this.blockIcon = par1IconRegister.registerIcon(this.field_94356_a);
267    }
268}