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