BiomesOPlenty/src/main/java/biomesoplenty/common/block/BlockBOPDirt.java

233 lines
9.3 KiB
Java

/*******************************************************************************
* Copyright 2014-2016, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.block;
import java.util.Locale;
import java.util.Random;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.common.item.ItemBOPBlock;
import biomesoplenty.api.enums.IPagedVariants;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.color.IBlockColor;
import net.minecraft.client.renderer.color.IItemColor;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class BlockBOPDirt extends Block implements IBOPBlock, ISustainsPlantType
{
// add properties
public enum BOPDirtType implements IStringSerializable, IPagedVariants
{
LOAMY, SANDY, SILTY;
@Override
public String getName()
{
return this.name().toLowerCase(Locale.ENGLISH);
}
@Override
public String toString()
{
return this.getName();
}
}
public static final PropertyEnum VARIANT = PropertyEnum.create("variant", BOPDirtType.class);
public static final PropertyBool COARSE = PropertyBool.create("coarse");
@Override
protected BlockStateContainer createBlockState() {return new BlockStateContainer(this, COARSE, VARIANT);}
// implement IBOPBlock
@Override
public Class<? extends ItemBlock> getItemClass() { return ItemBOPBlock.class; }
@Override
public IProperty[] getPresetProperties() { return new IProperty[] {COARSE, VARIANT}; }
@Override
public IProperty[] getNonRenderingProperties() { return null; }
@Override
public String getStateName(IBlockState state)
{
return (Boolean.TRUE.equals(state.getValue(COARSE)) ? "coarse_" : "") + ((BOPDirtType) state.getValue(VARIANT)).getName() + "_dirt";
}
@Override
@SideOnly(Side.CLIENT)
public IBlockColor getBlockColor() { return null; }
@Override
@SideOnly(Side.CLIENT)
public IItemColor getItemColor() { return null; }
public BlockBOPDirt() {
super(Material.GROUND);
// set some defaults
this.setTickRandomly(true);
this.setHardness(0.5F);
this.setHarvestLevel("shovel", 0);
this.setSoundType(SoundType.GROUND);
this.setDefaultState( this.blockState.getBaseState().withProperty(COARSE, Boolean.valueOf(false)).withProperty(VARIANT, BOPDirtType.LOAMY) );
}
@Override
public IBlockState getStateFromMeta(int meta)
{
// both variant and coarseness saved in meta, first bit coarseness, other bits variant
return this.getDefaultState().withProperty(COARSE, Boolean.valueOf((meta & 8) > 0)).withProperty(VARIANT, BOPDirtType.values()[Math.min(2, meta & 7)]);
}
@Override
public int getMetaFromState(IBlockState state)
{
// both variant and coarseness saved in meta, first bit coarseness, other bits variant
return (Boolean.TRUE.equals(state.getValue(COARSE)) ? 8 : 0) | ((BOPDirtType) state.getValue(VARIANT)).ordinal();
}
// our blocks usually drop their current state as opposed to a single 'default' state
@Override
public int damageDropped(IBlockState state)
{
return this.getMetaFromState(state);
}
@Override
public boolean canSustainPlantType(IBlockAccess world, BlockPos pos, EnumPlantType plantType)
{
// Note: EnumPlantType will be changed at runtime by other mods using a Forge functionality.
// switch() does NOT work with enums in that case, but will crash when encountering
// a value not known beforehand.
// support desert, plains and cave plants
if (plantType == EnumPlantType.Desert || plantType == EnumPlantType.Plains || plantType == EnumPlantType.Cave)
{
return true;
}
// support beach plants if there's water alongside
if (plantType == EnumPlantType.Beach)
{
return (
world.getBlockState(pos.east()).getMaterial() == Material.WATER ||
world.getBlockState(pos.west()).getMaterial() == Material.WATER ||
world.getBlockState(pos.north()).getMaterial() == Material.WATER ||
world.getBlockState(pos.south()).getMaterial() == Material.WATER
);
}
// don't support nether plants, water plants, or crops (require farmland), or anything else by default
return false;
}
@Override
public boolean canSustainPlant(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable)
{
if (plantable == Blocks.MELON_STEM || plantable == Blocks.PUMPKIN_STEM)
{
return true;
}
return this.canSustainPlantType(world, pos, plantable.getPlantType(world, pos.offset(direction)));
}
@Override
public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) {
IBlockState grassState = getGrassBlockState(state);
if (grassState != null)
{
pullGrassFromNeighbors(world, pos, grassState, rand, 4, 1, 3, 1);
}
}
// BOPGrass variants spread randomly to BOPDirt on the grass's updateTick
// However, vanilla grass does not. This function fixes this by 'pulling' grass from nearby vanilla grass blocks at the same rate as it would spread to vanilla dirt
public void pullGrassFromNeighbors(World world, BlockPos pos, IBlockState grassState, Random rand, int tries, int xzSpread, int downSpread, int upSpread)
{
IBlockState upState = world.getBlockState(pos.up());
// if there's not enough light then there's no chance of this block becoming grassy
if (world.getLightFromNeighbors(pos.up()) < 4 || upState.getLightOpacity(world, pos.up()) > 2) {return;}
int numNearbyGrassSpreadingBlocks = 0;
BlockPos pos1;
for (int dy = -downSpread; dy <= upSpread; dy++)
{
for (int dx = -xzSpread; dx <= xzSpread; dx++)
{
for (int dz = -xzSpread; dz <= xzSpread; dz++)
{
// count only vanilla grass blocks with enough light (BOP Grass 'pushes' itself onto dirt, no need to 'pull' it)
pos1 = pos.add(dx, dy, dz);
if (world.getBlockState(pos1).getBlock() == Blocks.GRASS && world.getLightFromNeighbors(pos1.up()) >= 9)
{
numNearbyGrassSpreadingBlocks++;
}
}
}
}
if (numNearbyGrassSpreadingBlocks == 0) {return;}
// each grass block gets 4 tries to spread grass, chance of this block being chosen each time is 1 / volume of blocks close enough
// overall chance of spread = 1 - chance of not spreading
int vol = (xzSpread * 2 + 1) * (xzSpread * 2 + 1) * (upSpread + downSpread + 1);
double chanceOfSpread = 1.0D - Math.pow(1.0D - 1.0D / vol, tries * numNearbyGrassSpreadingBlocks);
if (rand.nextDouble() < chanceOfSpread)
{
world.setBlockState(pos, grassState);
}
}
// get the blockstate which corresponds to the type of grass which grows on this dirt
public static IBlockState getGrassBlockState(IBlockState state)
{
// no grass grows on coarse dirt
if (Boolean.TRUE.equals(state.getValue(COARSE)))
{
return null;
}
switch ((BOPDirtType) state.getValue(VARIANT))
{
case LOAMY:
return BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BlockBOPGrass.BOPGrassType.LOAMY);
case SANDY:
return BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BlockBOPGrass.BOPGrassType.SANDY);
case SILTY:
return BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BlockBOPGrass.BOPGrassType.SILTY);
default:
// return vanilla grass as a backup
return Blocks.GRASS.getDefaultState();
}
}
public Block getGrassBlock(IBlockState state)
{
return getGrassBlockState(state).getBlock();
}
public int getGrassBlockMeta(IBlockState state)
{
return this.getGrassBlock(state).getMetaFromState(getGrassBlockState(state));
}
}