content: package thebetweenlands.common.block.plant;
  
  import java.util.List;
  import java.util.Random;
  
  import javax.annotation.Nullable;
  
  import com.google.common.collect.ImmutableList;
  
  import net.minecraft.block.Block;
  import net.minecraft.block.BlockBush;
  import net.minecraft.block.SoundType;
  import net.minecraft.block.material.Material;
  import net.minecraft.block.state.IBlockState;
  import net.minecraft.entity.player.EntityPlayer;
  import net.minecraft.init.Blocks;
  import net.minecraft.item.Item;
  import net.minecraft.item.ItemStack;
  import net.minecraft.util.EnumFacing;
  import net.minecraft.util.EnumHand;
  import net.minecraft.util.math.AxisAlignedBB;
  import net.minecraft.util.math.BlockPos;
  import net.minecraft.world.IBlockAccess;
  import net.minecraft.world.World;
  import net.minecraft.world.biome.BiomeColorHelper;
  import net.minecraftforge.common.IShearable;
  import net.minecraftforge.fml.relauncher.Side;
  import net.minecraftforge.fml.relauncher.SideOnly;
  import thebetweenlands.api.block.IFarmablePlant;
  import thebetweenlands.api.block.ISickleHarvestable;
  import thebetweenlands.client.tab.BLCreativeTabs;
  import thebetweenlands.common.block.ITintedBlock;
  import thebetweenlands.common.block.SoilHelper;
  import thebetweenlands.common.block.farming.BlockGenericDugSoil;
  import thebetweenlands.common.item.misc.ItemMisc.EnumItemMisc;
  import thebetweenlands.common.registries.ItemRegistry;
  
  public class BlockPlant extends BlockBush implements IShearable, ISickleHarvestable, IFarmablePlant, ITintedBlock {
  	protected static final AxisAlignedBB PLANT_AABB = new AxisAlignedBB(0.1D, 0.0D, 0.1D, 0.9D, 0.8D, 0.9D);
  
  	protected ItemStack sickleHarvestableDrop;
  	protected boolean isReplaceable = false;
  
  	public BlockPlant() {
  		super(Material.PLANTS);
  		this.setHardness(0.0F);
  		this.setSoundType(SoundType.PLANT);
  		this.setCreativeTab(BLCreativeTabs.PLANTS);
  	}
  
  	public BlockPlant setSickleDrop(ItemStack drop) {
  		this.sickleHarvestableDrop = drop;
  		return this;
  	}
  
  	public BlockPlant setReplaceable(boolean replaceable) {
  		this.isReplaceable = replaceable;
  		return this;
  	}
  
  	@Override
  	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
  		return PLANT_AABB;
  	}
  
  	@Override
  	public boolean canPlaceBlockAt(World worldIn, BlockPos pos) {
  		return super.canPlaceBlockAt(worldIn, pos) && worldIn.isAirBlock(pos.up()) && this.canBlockStay(worldIn, pos, worldIn.getBlockState(pos));
  	}
  
  	@Override
  	public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos) {
  		return this.isReplaceable;
  	}
  
  	@Override
  	public boolean isPassable(IBlockAccess worldIn, BlockPos pos) {
  		return true;
  	}
  
  	@Override
  	protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state) {
  		if (!this.canBlockStay(worldIn, pos, state)) {
  			this.dropBlockAsItem(worldIn, pos, state, 0);
  			worldIn.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
  		}
  	}
  
  	@Override
  	@Nullable
  	public Item getItemDropped(IBlockState state, Random rand, int fortune) {
  		return null;
  	}
  
  	@Override
  	public int damageDropped(IBlockState state) {
  		return 0;
  	}
  
  	@Override
  	@SideOnly(Side.CLIENT)
  	public Block.EnumOffsetType getOffsetType() {
  		return Block.EnumOffsetType.XZ;
  	}
  
  	@Override
  	protected boolean canSustainBush(IBlockState state) {
  		return SoilHelper.canSustainPlant(state);
  	}
  
  	@Override
  	public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos) {
  		return item.getItem() == ItemRegistry.SYRMORITE_SHEARS || item.getItem() == ItemRegistry.SILT_CRAB_CLAW;
  	}
  
  	@Override
  	public List<ItemStack> onSheared(ItemStack item, IBlockAccess world, BlockPos pos, int fortune) {
  		return ImmutableList.of(new ItemStack(Item.getItemFromBlock(this)));
  	}
  
  	@Override
  	public boolean isHarvestable(ItemStack item, IBlockAccess world, BlockPos pos) {
  		return true;
  	}
  
  	@Override
  	public List<ItemStack> getHarvestableDrops(ItemStack item, IBlockAccess world, BlockPos pos, int fortune) {
  		return this.sickleHarvestableDrop != null ? ImmutableList.of(this.sickleHarvestableDrop.copy()) : ImmutableList.of();
  	}
  
  	@Override
  	public boolean canSpreadTo(World world, BlockPos pos, IBlockState state, BlockPos targetPos, Random rand) {
  		return world.isAirBlock(targetPos) && this.canPlaceBlockAt(world, targetPos);
  	}
  	
  	@Override
  	public float getSpreadChance(World world, BlockPos pos, IBlockState state, BlockPos taretPos, Random rand) {
  		return 0.25F;
  	}
  
  	@Override
  	public void spreadTo(World world, BlockPos pos, IBlockState state, BlockPos targetPos, Random rand) {
  		world.setBlockState(targetPos, this.getDefaultState());
  	}
  
  	@Override
  	public void decayPlant(World world, BlockPos pos, IBlockState state, Random rand) {
  		world.setBlockToAir(pos);
  	}
  
  	@Override
  	public int getCompostCost(World world, BlockPos pos, IBlockState state, Random rand) {
  		return 4;
  	}
  
  	@Override
  	public boolean isFarmable(World world, BlockPos pos, IBlockState state) {
  		return true;
  	}
  	
  	@Override
  	public int getColorMultiplier(IBlockState state, IBlockAccess worldIn, BlockPos pos, int tintIndex) {
  		return worldIn != null && pos != null ? BiomeColorHelper.getGrassColorAtPos(worldIn, pos) : -1;
  	}
  	
  	@Override
      public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
          ItemStack heldItem = playerIn.getHeldItem(hand);
          if(!heldItem.isEmpty() && EnumItemMisc.COMPOST.isItemOf(heldItem)) {
          	pos = pos.down();
          	for(int i = 0; i < 3; i++) {
          		state = world.getBlockState(pos);
          		if(state.getBlock() instanceof BlockGenericDugSoil) {
          			return state.getBlock().onBlockActivated(world, pos, state, playerIn, hand, EnumFacing.UP, 0.5f, 1.0f, 0.5f);
          		} else if(!this.isSamePlant(state)) {
          			break;
          		}
          		pos = pos.down();
          	}
          }
          return false;
      }
  	
  	/**
  	 * Returns true if the specified block should be considered as the same plant
  	 * @param blockState
  	 * @return
  	 */
  	protected boolean isSamePlant(IBlockState blockState) {
  		return blockState.getBlock() == this;
  	}
  }