    001package net.minecraft.block;
    002
    003import java.util.Random;
    004import net.minecraft.block.material.Material;
    005import net.minecraft.creativetab.CreativeTabs;
    006import net.minecraft.util.AxisAlignedBB;
    007import net.minecraft.world.World;
    008
    009import net.minecraftforge.common.EnumPlantType;
    010import net.minecraftforge.common.ForgeDirection;
    011import net.minecraftforge.common.IPlantable;
    012import static net.minecraftforge.common.EnumPlantType.*;
    013
    014public class BlockFlower extends Block implements IPlantable
    015{
    016    protected BlockFlower(int par1, Material par2Material)
    017    {
    018        super(par1, par2Material);
    019        this.setTickRandomly(true);
    020        float f = 0.2F;
    021        this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3.0F, 0.5F + f);
    022        this.setCreativeTab(CreativeTabs.tabDecorations);
    023    }
    024
    025    protected BlockFlower(int par1)
    026    {
    027        this(par1, Material.plants);
    028    }
    029
    030    /**
    031     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    032     */
    033    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    034    {
    035        return super.canPlaceBlockAt(par1World, par2, par3, par4) && canBlockStay(par1World, par2, par3, par4);
    036    }
    037
    038    /**
    039     * Gets passed in the blockID of the block below and supposed to return true if its allowed to grow on the type of
    040     * blockID passed in. Args: blockID
    041     */
    042    protected boolean canThisPlantGrowOnThisBlockID(int par1)
    043    {
    044        return par1 == Block.grass.blockID || par1 == Block.dirt.blockID || par1 == Block.tilledField.blockID;
    045    }
    046
    047    /**
    048     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    049     * their own) Args: x, y, z, neighbor blockID
    050     */
    051    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    052    {
    053        super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
    054        this.checkFlowerChange(par1World, par2, par3, par4);
    055    }
    056
    057    /**
    058     * Ticks the block if it's been scheduled
    059     */
    060    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    061    {
    062        this.checkFlowerChange(par1World, par2, par3, par4);
    063    }
    064
    065    protected final void checkFlowerChange(World par1World, int par2, int par3, int par4)
    066    {
    067        if (!this.canBlockStay(par1World, par2, par3, par4))
    068        {
    069            this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    070            par1World.setBlockToAir(par2, par3, par4);
    071        }
    072    }
    073
    074    /**
    075     * Can this block stay at this position.  Similar to canPlaceBlockAt except gets checked often with plants.
    076     */
    077    public boolean canBlockStay(World par1World, int par2, int par3, int par4)
    078    {
    079        Block soil = blocksList[par1World.getBlockId(par2, par3 - 1, par4)];
    080        return (par1World.getFullBlockLightValue(par2, par3, par4) >= 8 || par1World.canBlockSeeTheSky(par2, par3, par4)) &&
    081                (soil != null && soil.canSustainPlant(par1World, par2, par3 - 1, par4, ForgeDirection.UP, this));
    082    }
    083
    084    /**
    085     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    086     * cleared to be reused)
    087     */
    088    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    089    {
    090        return null;
    091    }
    092
    093    /**
    094     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    095     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    096     */
    097    public boolean isOpaqueCube()
    098    {
    099        return false;
    100    }
    101
    102    /**
    103     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    104     */
    105    public boolean renderAsNormalBlock()
    106    {
    107        return false;
    108    }
    109
    110    /**
    111     * The type of render function that is called for this block
    112     */
    113    public int getRenderType()
    114    {
    115        return 1;
    116    }
    117
    118    @Override
    119    public EnumPlantType getPlantType(World world, int x, int y, int z)
    120    {
    121        if (blockID == crops.blockID        ) return Crop;
    122        if (blockID == deadBush.blockID     ) return Desert;
    123        if (blockID == waterlily.blockID    ) return Water;
    124        if (blockID == mushroomRed.blockID  ) return Cave;
    125        if (blockID == mushroomBrown.blockID) return Cave;
    126        if (blockID == netherStalk.blockID  ) return Nether;
    127        if (blockID == sapling.blockID      ) return Plains;
    128        if (blockID == melonStem.blockID    ) return Crop;
    129        if (blockID == pumpkinStem.blockID  ) return Crop;
    130        if (blockID == tallGrass.blockID    ) return Plains;
    131        return Plains;
    132    }
    133
    134    @Override
    135    public int getPlantID(World world, int x, int y, int z)
    136    {
    137        return blockID;
    138    }
    139
    140    @Override
    141    public int getPlantMetadata(World world, int x, int y, int z)
    142    {
    143        return world.getBlockMetadata(x, y, z);
    144    }
    145}