content: package thebetweenlands.common.block.plant;
  
  import java.util.List;
  import java.util.Random;
  
  import javax.annotation.Nonnull;
  import javax.annotation.Nullable;
  
  import com.google.common.collect.ImmutableList;
  
  import net.minecraft.block.Block;
  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.item.Item;
  import net.minecraft.item.ItemBlock;
  import net.minecraft.item.ItemStack;
  import net.minecraft.util.BlockRenderLayer;
  import net.minecraft.util.EnumFacing;
  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.fluids.Fluid;
  import net.minecraftforge.fluids.IFluidBlock;
  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.SoilHelper;
  import thebetweenlands.common.block.terrain.BlockSwampWater;
  import thebetweenlands.common.registries.BlockRegistry;
  import thebetweenlands.common.registries.BlockRegistry.ICustomItemBlock;
  import thebetweenlands.common.registries.BlockRegistry.IStateMappedBlock;
  import thebetweenlands.common.registries.FluidRegistry;
  import thebetweenlands.common.registries.ItemRegistry;
  import thebetweenlands.util.AdvancedStateMap;
  
  public class BlockPlantUnderwater extends BlockSwampWater implements net.minecraftforge.common.IPlantable, IStateMappedBlock, IShearable, ISickleHarvestable, IFarmablePlant {
  	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 BlockPlantUnderwater() {
  		this(FluidRegistry.SWAMP_WATER, Material.WATER);
  		this.setHardness(0.5F);
  	}
  
  	public BlockPlantUnderwater(Fluid fluid, Material materialIn) {
  		super(fluid, materialIn);
  		this.setSoundType(SoundType.PLANT);
  		this.setHardness(1.5F);
  		this.setResistance(10.0F);
  		this.setUnderwaterBlock(true);
  		this.setDefaultState(this.blockState.getBaseState().withProperty(LEVEL, 0));
  		this.setCreativeTab(BLCreativeTabs.PLANTS);
  	}
  
  	public BlockPlantUnderwater setSickleDrop(ItemStack drop) {
  		this.sickleHarvestableDrop = drop;
  		return this;
  	}
  
  	public BlockPlantUnderwater setReplaceable(boolean replaceable) {
  		this.isReplaceable = replaceable;
  		return this;
  	}
  	
  	/**
  	 * Removes the plant. Usually sets the block to water
  	 * @param world
  	 * @param pos
  	 * @param player
  	 * @param canHarvest
  	 * @return
  	 */
  	protected boolean removePlant(World world, BlockPos pos, @Nullable EntityPlayer player, boolean canHarvest) {
  		return world.setBlockState(pos, BlockRegistry.SWAMP_WATER.getDefaultState(), world.isRemote ? 11 : 3);
  	}
  
  	@Override
  	public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos) {
  		return this.isReplaceable;
  	}
  
  	@Override
  	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
  		return PLANT_AABB;
  	}
  
  	@Override
  	public boolean isBlockNormalCube(IBlockState blockState) {
  		return false;
  	}
  
  	@Override
  	public boolean isOpaqueCube(IBlockState blockState) {
  		return false;
  	}
  
  	@Override
  	@SideOnly(Side.CLIENT)
  	public BlockRenderLayer getRenderLayer() {
  		return BlockRenderLayer.TRANSLUCENT;
  	}
  
  	@Override
  	public net.minecraftforge.common.EnumPlantType getPlantType(net.minecraft.world.IBlockAccess world, BlockPos pos) {
  		return net.minecraftforge.common.EnumPlantType.Plains;
  	}
  
  	@Override
  	public IBlockState getPlant(net.minecraft.world.IBlockAccess world, BlockPos pos) {
  		IBlockState state = world.getBlockState(pos);
  		if (state.getBlock() != this) return getDefaultState();
  		return state;
  	}
  
  	@Override
  	@SideOnly(Side.CLIENT)
  	public Block.EnumOffsetType getOffsetType() {
  		return Block.EnumOffsetType.NONE;
  	}
  
  	@Override
  	public AxisAlignedBB getCollisionBoundingBox(@Nonnull IBlockState blockState, @Nonnull IBlockAccess worldIn, @Nonnull BlockPos pos) {
  		return NULL_AABB;
  	}
  
  
  	@Override
  	@SideOnly(Side.CLIENT)
  	public void setStateMapper(AdvancedStateMap.Builder builder) {
  		super.setStateMapper(builder);
  		builder.ignore(LEVEL);
  	}
  
  	@Override
  	public void neighborChanged(@Nonnull IBlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Block neighborBlock, @Nonnull BlockPos neighbourPos) {
  		super.neighborChanged(state, world, pos, neighborBlock, neighbourPos);
  		this.checkAndDropBlock(world, pos, state);
  	}
  
  	@Override
  	public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) {
  		super.updateTick(worldIn, pos, state, rand);
  		this.checkAndDropBlock(worldIn, pos, state);
  	}
  
  	protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state) {
  		if (!this.canBlockStay(worldIn, pos, state)) {
  			this.dropBlockAsItem(worldIn, pos, state, 0);
  			this.removePlant(worldIn, pos, null, false);
  		}
  	}
  
  	public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state) {
  		if (state.getBlock() == this) //Forge: This function is called during world gen and placement, before this block is set, so if we are not 'here' then assume it's the pre-check.
  		{
  			IBlockState soil = worldIn.getBlockState(pos.down());
  			return soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this) || 
  					this.canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this);
  		}
  		return this.canSustainPlant(worldIn.getBlockState(pos.down()));
  	}
  
  	protected boolean canSustainPlant(IBlockState state) {
  		return SoilHelper.canSustainUnderwaterPlant(state);
  	}
  
  	@Override
  	public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) {
  		this.onBlockHarvested(world, pos, state, player);
  		return this.removePlant(world, pos, player, willHarvest);
  	}
  
  	@Override
  	public boolean canPlaceBlockAt(World worldIn, BlockPos pos) {
  		IBlockState soil = worldIn.getBlockState(pos.down());
  		IBlockState state = worldIn.getBlockState(pos);
  		if(state.getBlock() instanceof IFluidBlock && ((IFluidBlock)state.getBlock()).getFluid() == this.getFluid()) {
  			return super.canPlaceBlockAt(worldIn, pos) && 
  					(soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this) || this.canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this));
  		}
  		return false;
  	}
  
  	@Override
  	public boolean canSustainPlant(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable) {
  		return super.canSustainPlant(state, world, pos, direction, plantable) || (plantable instanceof BlockPlantUnderwater && ((BlockPlantUnderwater)plantable).canSustainPlant(state)) || SoilHelper.canSustainUnderwaterPlant(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
  	@Nullable
  	public Item getItemDropped(IBlockState state, Random rand, int fortune) {
  		return null;
  	}
  
  	@Override
  	public int quantityDropped(Random par1Random) {
  		return 0;
  	}
  
  	@SideOnly(Side.CLIENT)
  	@Override
  	public boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer) {
  		return layer == BlockRenderLayer.TRANSLUCENT || layer == BlockRenderLayer.CUTOUT;
  	}
  
  	@Override
  	public int getColorMultiplier(IBlockState state, IBlockAccess worldIn, BlockPos pos, int tintIndex) {
  		if(tintIndex == 1) {
  			return worldIn != null && pos != null ? BiomeColorHelper.getGrassColorAtPos(worldIn, pos) : -1;
  		}
  		return super.getColorMultiplier(state, worldIn, pos, tintIndex);
  	}
  
  	@Override
  	public boolean isFarmable(World world, BlockPos pos, IBlockState state) {
  		return true;
  	}
  
  	@Override
  	public boolean canSpreadTo(World world, BlockPos pos, IBlockState state, BlockPos targetPos, Random rand) {
  		Block block = world.getBlockState(targetPos).getBlock();
  		if(block instanceof BlockSwampWater && ((BlockSwampWater)block).isSourceBlock(world, targetPos)) {
  			return this.canPlaceBlockAt(world, targetPos);
  		}
  		return false;
  	}
  
  	@Override
  	public float getSpreadChance(World world, BlockPos pos, IBlockState state, BlockPos taretPos, Random rand) {
  		return 0.25F;
  	}
  	
  	@Override
  	public int getCompostCost(World world, BlockPos pos, IBlockState state, Random rand) {
  		return 4;
  	}
  
  	@Override
  	public void decayPlant(World world, BlockPos pos, IBlockState state, Random rand) {
  		world.setBlockState(pos, BlockRegistry.SWAMP_WATER.getDefaultState());
  	}
  
  	@Override
  	public void spreadTo(World world, BlockPos pos, IBlockState state, BlockPos targetPos, Random rand) {
  		world.setBlockState(targetPos, this.getDefaultState());
  	}
  	
  	@Override
  	public ItemBlock getItemBlock() {
  		return ICustomItemBlock.getDefaultItemBlock(this);
  	}
  }
  