Add loamy/silty/sandy grass blocks

This commit is contained in:
Cheeserolls 2015-03-26 20:53:02 +00:00
parent 953c6477fc
commit 10da2ae8b9
20 changed files with 343 additions and 79 deletions

View file

@ -11,8 +11,13 @@ package biomesoplenty.common.block;
import java.util.Random;
import biomesoplenty.api.block.BOPBlock;
import biomesoplenty.api.block.BOPBlocks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBush;
import net.minecraft.block.BlockDirt;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.BlockTallGrass;
import net.minecraft.block.IGrowable;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyEnum;
@ -26,12 +31,17 @@ import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraft.util.IStringSerializable;
import net.minecraft.world.ColorizerGrass;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeColorHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class BlockBOPGrass extends BOPBlock
// TODO: add snowiness?
public class BlockBOPGrass extends BOPBlock implements IGrowable
{
public static final PropertyEnum VARIANT_PROP = PropertyEnum.create("variant", BOPGrassType.class);
@ -40,7 +50,7 @@ public class BlockBOPGrass extends BOPBlock
super(Material.grass);
this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT_PROP, BOPGrassType.SPECTRALMOSS));
this.setHardness(0.6F);
this.setHarvestLevel("shovel", 0); // TODO: this means that ONLY a shovel can harvest this block... correct?
this.setHarvestLevel("shovel", 0); // TODO: I think this just determines which tool speeds up digging - need to investigate more
this.setStepSound(Block.soundTypeGrass);
this.setTickRandomly(true);
}
@ -48,14 +58,14 @@ public class BlockBOPGrass extends BOPBlock
@Override
public IBlockState getStateFromMeta(int meta)
{
// only one property to worry about, the variant, so just map [0 => SPECTRALMOSS, 1 => SMOLDERINGGRASS]
// only one property to worry about, the variant, so just map according to integer index in BOPGrassType
return this.getDefaultState().withProperty(VARIANT_PROP, BOPGrassType.values()[meta]);
}
@Override
public int getMetaFromState(IBlockState state)
{
// only one property to worry about, the variant, so just map [0 => SPECTRALMOSS, 1 => SMOLDERINGGRASS]
// only one property to worry about, the variant, so just map according to integer index in BOPGrassType
return ((BOPGrassType) state.getValue(VARIANT_PROP)).ordinal();
}
@ -77,21 +87,88 @@ public class BlockBOPGrass extends BOPBlock
return ((BOPGrassType) state.getValue(VARIANT_PROP)).getName();
}
@Override
@SideOnly(Side.CLIENT)
public int getBlockColor()
{
return ColorizerGrass.getGrassColor(0.5D, 1.0D);
}
@Override
@SideOnly(Side.CLIENT)
public int getRenderColor(IBlockState state)
{
return this.getBlockColor();
}
@Override
@SideOnly(Side.CLIENT)
public int colorMultiplier(IBlockAccess worldIn, BlockPos pos, int renderPass)
{
return BiomeColorHelper.getGrassColorAtPos(worldIn, pos);
}
@Override
@SideOnly(Side.CLIENT)
public EnumWorldBlockLayer getBlockLayer()
{
return EnumWorldBlockLayer.CUTOUT_MIPPED;
}
@Override
public boolean canSustainPlant(IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable)
{
IBlockState state = world.getBlockState(pos);
net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.offset(direction));
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
// smoldering grass supports no plants
case SMOLDERING:
return false;
default:
switch (plantType)
{
// support desert and plains plants
case Desert: case Plains: return true;
// support cave plants
case Cave: return isSideSolid(world, pos, EnumFacing.UP);
// support beach plants if there's water alongside
case Beach:
return (
world.getBlockState(pos.east()).getBlock().getMaterial() == Material.water ||
world.getBlockState(pos.west()).getBlock().getMaterial() == Material.water ||
world.getBlockState(pos.north()).getBlock().getMaterial() == Material.water ||
world.getBlockState(pos.south()).getBlock().getMaterial() == Material.water
);
// don't support nether plants, water plants, or crops (require farmland), or anything else by default
default:
return false;
}
}
}
@Override
public boolean isFireSource(World world, BlockPos pos, EnumFacing side)
{
IBlockState state = world.getBlockState(pos);
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
// spectralmoss burns from below in the end
// spectral moss burns from below in the end
// TODO: 1.7 code had dimension=-1 here - check -1 corresponds to end
case SPECTRALMOSS:
if ((world.provider instanceof net.minecraft.world.WorldProviderEnd) && side == EnumFacing.UP) {return true;}
break;
// smolderinggrass always burns
case SMOLDERINGGRASS:
// smoldering grass always burns
case SMOLDERING:
return false;
default:
break;
}
return super.isFireSource(world, pos, side);
}
@ -102,7 +179,7 @@ public class BlockBOPGrass extends BOPBlock
IBlockState state = this.getStateFromMeta(meta);
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
// spectralmoss makes a hideous noise and throws a big fuss of particles around when placed in the nether
// spectral moss makes a hideous noise and throws a big fuss of particles around when placed in the nether
case SPECTRALMOSS:
if (world.provider instanceof net.minecraft.world.WorldProviderHell)
{
@ -115,7 +192,7 @@ public class BlockBOPGrass extends BOPBlock
}
break;
case SMOLDERINGGRASS:
default:
break;
}
return state;
@ -126,11 +203,9 @@ public class BlockBOPGrass extends BOPBlock
public void randomDisplayTick(World worldIn, BlockPos pos, IBlockState state, Random rand) {
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS:
break;
// smolderinggrass throws up random flame and smoke particles
case SMOLDERINGGRASS:
// smoldering grass throws up random flame and smoke particles
case SMOLDERING:
if (rand.nextInt(4)==0)
{
worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, (double)((float)pos.getX() + rand.nextFloat()), (double)((float)pos.getY() + 1.1F), (double)((float)pos.getZ() + rand.nextFloat()), 0.0D, 0.0D, 0.0D);
@ -140,6 +215,10 @@ public class BlockBOPGrass extends BOPBlock
worldIn.spawnParticle(EnumParticleTypes.FLAME, (double)((float)pos.getX() + rand.nextFloat()), (double)((float)pos.getY() + 1.1F), (double)((float)pos.getZ() + rand.nextFloat()), 0.0D, 0.0D, 0.0D);
}
break;
default:
break;
}
super.randomDisplayTick(worldIn, pos, state, rand);
}
@ -151,58 +230,169 @@ public class BlockBOPGrass extends BOPBlock
{
case SPECTRALMOSS:
// spectral moss in the nether catches on fire and turns to smoldering grass
// elsewhere it should behave like grass spreading to nearby end_stone blocks
if (world.provider instanceof net.minecraft.world.WorldProviderHell)
{
world.setBlockState(pos.up(), Blocks.fire.getDefaultState()); // might need to set fire AGE value... not sure
world.setBlockState(pos, this.getDefaultState().withProperty(VARIANT_PROP, BOPGrassType.SMOLDERINGGRASS));
}
else
{
// if this block is covered, then turn it back to end_stone (IE kill the moss)
if (world.getLightFromNeighbors(pos.up()) < 4 && world.getBlockState(pos.up()).getBlock().getLightOpacity(world, pos.up()) > 2)
{
world.setBlockState(pos, Blocks.end_stone.getDefaultState());
}
else
{
// if there's enough light from above, spread the moss randomly to nearby end_stone blocks
if (world.getLightFromNeighbors(pos.up()) >= 9)
{
for (int i = 0; i < 4; ++i) // try 4 times
{
// pick a random nearby position
BlockPos pos1 = pos.add(rand.nextInt(3) - 1, rand.nextInt(5) - 3, rand.nextInt(3) - 1);
Block blockAbove = world.getBlockState(pos1.up()).getBlock();
IBlockState iblockstate1 = world.getBlockState(pos1);
// if there's enough light and it isn't covered, turn it to moss
if (iblockstate1.getBlock() == Blocks.end_stone && world.getLightFromNeighbors(pos1.up()) >= 4 && blockAbove.getLightOpacity(world, pos1.up()) <= 2)
{
world.setBlockState(pos1, this.getDefaultState().withProperty(VARIANT_PROP, BOPGrassType.SPECTRALMOSS) );
}
}
}
}
world.setBlockState(pos, this.getDefaultState().withProperty(VARIANT_PROP, BOPGrassType.SMOLDERING));
}
break;
case SMOLDERINGGRASS:
default:
break;
}
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SMOLDERING:
// smoldering grass doesn't spread to nearby dirt
break;
default:
// the other BOP grass types all do
this.spreadGrass(world, pos, state, rand, 4, 1, 3, 1);
break;
}
}
// spread grass to suitable nearby grass blocks
// tries - number of times to try and spread to a random nearby block
// xzSpread - how far can the grass spread in the x and z directions
// downSpread - how far can the grass spread downwards
// upSpread - how far can the grass spread upwards
// TODO: let grass spread across different dirt types? onto vanilla dirt too (and vice verca)?
@SideOnly(Side.CLIENT)
public void spreadGrass(World world, BlockPos pos, IBlockState state, Random rand, int tries, int xzSpread, int downSpread, int upSpread)
{
// the type of grass which is spreading
BOPGrassType grassType = (BOPGrassType)state.getValue(VARIANT_PROP);
// the type of dirt this grass grows on
IBlockState dirtBlockState = grassType.getDirtBlockState();
// if this block is covered, then turn it back to dirt (IE kill the grass)
if (world.getLightFromNeighbors(pos.up()) < 4 && world.getBlockState(pos.up()).getBlock().getLightOpacity(world, pos.up()) > 2)
{
world.setBlockState(pos, dirtBlockState);
}
else
{
// if there's enough light from above, spread the grass randomly to nearby blocks of the correct dirt type
if (world.getLightFromNeighbors(pos.up()) >= 9)
{
for (int i = 0; i < tries; ++i)
{
// pick a random nearby position, and get the block, block state, and block above
BlockPos pos1 = pos.add(rand.nextInt(xzSpread * 2 + 1) - xzSpread, rand.nextInt(downSpread + upSpread + 1) - downSpread, rand.nextInt(xzSpread * 2 + 1) - xzSpread);
IBlockState iblockstate1 = world.getBlockState(pos1);
Block block1 = iblockstate1.getBlock();
Block blockAbove = world.getBlockState(pos1.up()).getBlock();
// see if the randomly chosen nearby block is the right type for this grass (same block and meta as dirtBlockState)
// TODO: is it ok to just compare the equality of the states? IE iblockstate1==dirtBlockState ?
if (block1==grassType.getDirtBlock() && block1.getMetaFromState(iblockstate1)==grassType.getDirtBlockMeta())
{
// if there's enough light and it isn't covered, turn the block to the relevant grass block
if (world.getLightFromNeighbors(pos1.up()) >= 4 && blockAbove.getLightOpacity(world, pos1.up()) <= 2)
{
world.setBlockState(pos1, this.getDefaultState().withProperty(VARIANT_PROP, grassType));
}
}
}
}
}
}
@Override
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient) {
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS: case SMOLDERING:
return false;
default:
return true;
}
}
@Override
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state) {
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS: case SMOLDERING:
return false;
default:
return true;
}
}
// This is called when bonemeal is applied on the block
// The algorithm is functionally exactly the same as in the vanilla BlockGrass grow function, but has been rewritten to make its behavior clearer
@Override
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state) {
BlockPos startPos = pos.up();
BlockPos currPos;
// 128 looks like a lot of tries, but many locations will be duplicated and many tries will be abandoned because the random walk hits a snag
for (int i = 0; i < 128; i++) {
// go on a random walk away from the start position - abandon if we hit a block which can't spread the growth
// note walkLength increases gradually with i - so we attempt walks of different lengths
int walkLength = i / 16;
currPos = startPos;
boolean walkOk = true;
for (int j = 0; j < walkLength; j++)
{
// shift a random distance
currPos = currPos.add(rand.nextInt(3) - 1, (rand.nextInt(3) - 1) * rand.nextInt(3) / 2, rand.nextInt(3) - 1);
if (worldIn.getBlockState(currPos.down()).getBlock() != BOPBlocks.grass || worldIn.getBlockState(currPos).getBlock().isNormalCube())
{
// this block can't spread the growth
walkOk = false;
break;
}
}
// try and grow something at currPos
if (walkOk && worldIn.isAirBlock(currPos)) {
if (rand.nextInt(8)==0) {
// with 1/8 probability, plant a flower
worldIn.getBiomeGenForCoords(currPos).plantFlower(worldIn, rand, currPos);
}
else
{
// otherwise plant tall grass
IBlockState tallgrassState = Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, BlockTallGrass.EnumType.GRASS);
if (Blocks.tallgrass.canBlockStay(worldIn, currPos, tallgrassState))
{
worldIn.setBlockState(currPos, tallgrassState);
}
}
}
}
}
/* TODO: don't understand the intention here.. grass turns to dirt when a plant grows???
@Override
public void onPlantGrow(World world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
{
world.setBlock(x, y, z, BOPCBlocks.newBopDirt, world.getBlockMetadata(x, y, z) * 2, 2);
}
*/
@Override
public AxisAlignedBB getCollisionBoundingBox(World world, BlockPos pos, IBlockState state)
{
float heightOffset = 0.0F;
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS:
// smoldering grass is a tiny bit lower than usual
case SMOLDERING:
heightOffset = 0.02F;
break;
// smoldering grass is a tiny bit lower than usual
case SMOLDERINGGRASS:
heightOffset = 0.02F;
default:
break;
}
return new AxisAlignedBB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) ((float) (pos.getY() + 1) - heightOffset), (double) (pos.getZ() + 1));
@ -213,13 +403,14 @@ public class BlockBOPGrass extends BOPBlock
{
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS:
break;
// smoldering grass sets you on fire for 2 seconds
case SMOLDERINGGRASS:
case SMOLDERING:
entity.setFire(2);
break;
default:
break;
}
}
@ -227,39 +418,21 @@ public class BlockBOPGrass extends BOPBlock
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
case SPECTRALMOSS:
return Item.getItemFromBlock(Blocks.end_stone);
case SMOLDERINGGRASS:
return Item.getItemFromBlock(Blocks.dirt);
}
return super.getItemDropped(state, rand, fortune);
return Item.getItemFromBlock( ((BOPGrassType) state.getValue(VARIANT_PROP)).getDirtBlock() );
}
// goes hand in hand with getItemDropped() above to determine precisely what is dropped
@Override
public int damageDropped(IBlockState state)
{
switch ((BOPGrassType) state.getValue(VARIANT_PROP))
{
// end stone doesn't have any variants
case SPECTRALMOSS:
return 0;
// make sure dirt item dropped is plain dirt (not any other variant)
case SMOLDERINGGRASS:
return BlockDirt.DirtType.DIRT.getMetadata();
}
return super.damageDropped(state);
return ((BOPGrassType) state.getValue(VARIANT_PROP)).getDirtBlockMeta();
}
// enum representing the 2 variants of grass
// enum representing the variants of grass
public static enum BOPGrassType implements IStringSerializable
{
SPECTRALMOSS, SMOLDERINGGRASS;
SPECTRALMOSS, SMOLDERING, LOAMY, SANDY, SILTY;
@Override
public String getName()
@ -268,10 +441,9 @@ public class BlockBOPGrass extends BOPBlock
{
case SPECTRALMOSS:
return "spectral_moss";
case SMOLDERINGGRASS:
return "smoldering_grass_block";
default:
return this.name().toLowerCase() + "_grass_block";
}
return this.name().toLowerCase();
}
@Override
@ -279,6 +451,32 @@ public class BlockBOPGrass extends BOPBlock
{
return getName();
}
// get the blockstate which corresponds to the type of dirt which this grass variant grows on
// this is used to determine what drops when you break the grass block, and also which nearby blocks this grass can spread to
public IBlockState getDirtBlockState()
{
switch(this)
{
case SPECTRALMOSS:
return Blocks.end_stone.getDefaultState();
case LOAMY: // TODO:
case SANDY: // TODO:
case SILTY: // TODO:
case SMOLDERING: default:
return Blocks.dirt.getStateFromMeta(BlockDirt.DirtType.DIRT.getMetadata());
}
}
public Block getDirtBlock()
{
return this.getDirtBlockState().getBlock();
}
public int getDirtBlockMeta()
{
return this.getDirtBlock().getMetaFromState(this.getDirtBlockState());
}
}
}

View file

@ -1,6 +1,9 @@
{
"variants": {
"variant=smoldering_grass_block": { "model": "biomesoplenty:smoldering_grass_block" },
"variant=spectral_moss": { "model": "biomesoplenty:spectral_moss" }
"variant=spectral_moss": { "model": "biomesoplenty:spectral_moss" },
"variant=loamy_grass_block": { "model": "biomesoplenty:loamy_grass_block" },
"variant=sandy_grass_block": { "model": "biomesoplenty:sandy_grass_block" },
"variant=silty_grass_block": { "model": "biomesoplenty:silty_grass_block" }
}
}

View file

@ -13,6 +13,9 @@ tile.bone_segment.large.name=Large Bone Segment
tile.grass.spectral_moss.name=Spectral Moss
tile.grass.smoldering_grass_block.name=Smoldering Grass Block
tile.grass.loamy_grass_block.name=Loamy Grass Block
tile.grass.sandy_grass_block.name=Sandy Grass Block
tile.grass.silty_grass_block.name=Silty Grass Block
tile.coral.pink.name=Pink Coral
tile.coral.orange.name=Orange Coral

View file

@ -0,0 +1,10 @@
{
"parent": "block/grass",
"textures": {
"particle": "biomesoplenty:blocks/dirt_loamy",
"bottom": "biomesoplenty:blocks/dirt_loamy",
"top": "biomesoplenty:blocks/grass_top",
"side": "biomesoplenty:blocks/grass_loamy_side",
"overlay": "biomesoplenty:blocks/grass_side_overlay"
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "block/grass",
"textures": {
"particle": "biomesoplenty:blocks/dirt_sandy",
"bottom": "biomesoplenty:blocks/dirt_sandy",
"top": "biomesoplenty:blocks/grass_top",
"side": "biomesoplenty:blocks/grass_sandy_side",
"overlay": "biomesoplenty:blocks/grass_side_overlay"
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "block/grass",
"textures": {
"particle": "biomesoplenty:blocks/dirt_silty",
"bottom": "biomesoplenty:blocks/dirt_silty",
"top": "biomesoplenty:blocks/grass_top",
"side": "biomesoplenty:blocks/grass_silty_side",
"overlay": "biomesoplenty:blocks/grass_side_overlay"
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "biomesoplenty:block/loamy_grass_block",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "biomesoplenty:block/sandy_grass_block",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "biomesoplenty:block/silty_grass_block",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B