Skip to content

Commit

Permalink
added some nice seasonal behavior to plants
Browse files Browse the repository at this point in the history
tallgrass has a chance to sprout from grass blocks, grow to double blocks, shrink back down to single blocks, and despawn in a continuous cycle based on ambient temperature

players are prevented from planting flowers outside of valid temp/rainfall zones (no planting orchids in a desert), also any flowers planted in for example the summer in a location that the pant can't survive in the winter will simply die (despawn) when they get too cold
  • Loading branch information
Konlii committed Feb 25, 2019
1 parent a0522e1 commit 44b84aa
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 129 deletions.
5 changes: 5 additions & 0 deletions src/main/java/net/dries007/tfc/ConfigTFC.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public static class GeneralCFG
@Config.Comment("Number of ticks required for a torch to burn out (72000 = 1 in game hour), default is 72 hours. Set to -1 to disable torch burnout.")
@Config.RangeInt(min = 20)
public int torchTime = 200; // todo: change to 72000

@Config.Comment("Growth rate for tallgrass")
@Config.RangeDouble(min = 0, max = 1)
@Config.LangKey("config." + MOD_ID + ".general.grassGrowthRate")
public double grassGrowthRate = 0.01;
}

public static class ClientCFG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,6 @@ public static void registerColorHandlerItems(ColorHandlerEvent.Item event)
itemColors.registerItemColorHandler((stack, tintIndex) ->
event.getBlockColors().colorMultiplier(((ItemBlock) stack.getItem()).getBlock().getStateFromMeta(stack.getMetadata()), null, null, tintIndex),
BlocksTFC.DOUBLE_TALL_GRASS);

itemColors.registerItemColorHandler((stack, tintIndex) ->
event.getBlockColors().colorMultiplier(((ItemBlock) stack.getItem()).getBlock().getStateFromMeta(stack.getMetadata()), null, null, tintIndex),
BlocksTFC.getAllPlantBlocks().toArray(new BlockPlantTFC[0]));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import net.dries007.tfc.api.types.Plant;
import net.dries007.tfc.world.classic.CalenderTFC;
import net.dries007.tfc.world.classic.ClimateTFC;
import net.dries007.tfc.world.classic.chunkdata.ChunkDataTFC;

public class BlockCreepingPlantTFC extends BlockPlantTFC
{
Expand All @@ -53,6 +55,7 @@ public static BlockCreepingPlantTFC get(Plant plant, Plant.PlantType type)
{
return BlockCreepingPlantTFC.TABLE.get(plant).get(type);
}

public final Plant plant;
public final Plant.PlantType type;

Expand Down Expand Up @@ -146,6 +149,20 @@ public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, Bloc
return i == 1 ? axisalignedbb : FULL_BLOCK_AABB;
}

@Override
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
{
for (EnumFacing face : EnumFacing.values())
{
IBlockState blockState = worldIn.getBlockState(pos.offset(face));
if (blockState.getBlockFaceShape(worldIn, pos.offset(face), face.getOpposite()) == BlockFaceShape.SOLID || blockState.getBlock() instanceof BlockFence)
{
return plant.isValidLocation(ClimateTFC.getHeightAdjustedBiomeTemp(worldIn, pos), ChunkDataTFC.getRainfall(worldIn, pos));
}
}
return false;
}

@Override
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
{
Expand Down Expand Up @@ -227,23 +244,6 @@ public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Bloc
}
}

@Override
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
{
return worldIn.getBlockState(pos.down()).getBlockFaceShape(worldIn, pos, EnumFacing.UP) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.up()).getBlockFaceShape(worldIn, pos, EnumFacing.DOWN) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.north()).getBlockFaceShape(worldIn, pos, EnumFacing.SOUTH) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.east()).getBlockFaceShape(worldIn, pos, EnumFacing.WEST) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.south()).getBlockFaceShape(worldIn, pos, EnumFacing.NORTH) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.west()).getBlockFaceShape(worldIn, pos, EnumFacing.EAST) == BlockFaceShape.SOLID ||
worldIn.getBlockState(pos.down()).getBlock() instanceof BlockFence ||
worldIn.getBlockState(pos.up()).getBlock() instanceof BlockFence ||
worldIn.getBlockState(pos.north()).getBlock() instanceof BlockFence ||
worldIn.getBlockState(pos.east()).getBlock() instanceof BlockFence ||
worldIn.getBlockState(pos.south()).getBlock() instanceof BlockFence ||
worldIn.getBlockState(pos.west()).getBlock() instanceof BlockFence;
}

@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, Bloc
public void onBlockAdded(World world, BlockPos pos, IBlockState state)
{
world.setBlockState(pos, this.blockState.getBaseState().withProperty(HALF, state.getValue(HALF)).withProperty(GROWTHSTAGE, CalenderTFC.getMonthOfYear().id()));
this.checkAndDropBlock(world, pos, state);
}

private boolean onHarvest(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
Expand All @@ -250,4 +251,34 @@ public String getName()
return this == UPPER ? "upper" : "lower";
}
}

@Override
public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random)
{
int currentStage = state.getValue(GROWTHSTAGE);
int expectedStage = CalenderTFC.getMonthOfYear().id();

if (currentStage != expectedStage && random.nextDouble() < 0.5)
{
worldIn.setBlockState(pos, state.withProperty(GROWTHSTAGE, expectedStage));
}
this.updateTick(worldIn, pos, state, random);
}

@Override
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
{
if (!canBlockStay(worldIn, pos, state))
{
worldIn.setBlockToAir(pos);
if (state.getValue(HALF) == EnumBlockHalf.UPPER)
{
worldIn.setBlockToAir(pos.down());
}
else
{
worldIn.setBlockToAir(pos.up());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.NonNullList;
Expand All @@ -34,6 +33,7 @@
import net.dries007.tfc.api.capability.size.Weight;
import net.dries007.tfc.objects.blocks.BlocksTFC;
import net.dries007.tfc.objects.items.ItemsTFC;
import net.dries007.tfc.world.classic.ClimateTFC;

public class BlockDoubleTallGrassTFC extends BlockTallGrassTFC implements net.minecraftforge.common.IShearable
{
Expand All @@ -44,14 +44,15 @@ public BlockDoubleTallGrassTFC()
super();
this.setTickRandomly(true);
this.setDefaultState(this.blockState.getBaseState().withProperty(TYPE, EnumGrassType.STANDARD).withProperty(HALF, EnumBlockHalf.LOWER));
this.setTranslationKey("doubleTallGrass");
}

@Override
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
{
return super.canPlaceBlockAt(worldIn, pos) && worldIn.isAirBlock(pos.up());
}

@Override
protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state)
{
if (!this.canBlockStay(worldIn, pos, state))
Expand All @@ -71,11 +72,12 @@ protected void checkAndDropBlock(World worldIn, BlockPos pos, IBlockState state)

if (block1 == this)
{
worldIn.setBlockState(blockpos1, Blocks.AIR.getDefaultState(), 3);
worldIn.setBlockState(blockpos1, BlocksTFC.TALL_GRASS.getBlockState().getBaseState().withProperty(TYPE, getBiomePlantType(worldIn, blockpos1)));
}
}
}

@Override
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
{
if (state.getBlock() != this)
Expand All @@ -97,6 +99,7 @@ public void placeAt(World worldIn, BlockPos lowerPos, EnumGrassType type, int fl
worldIn.setBlockState(lowerPos.up(), this.getDefaultState().withProperty(HALF, EnumBlockHalf.UPPER), flags);
}

@Override
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
{
if (state.getValue(HALF) == EnumBlockHalf.UPPER)
Expand All @@ -113,17 +116,12 @@ public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, Block
}

@Override
public void randomTick(World world, BlockPos pos, IBlockState state, Random random)
{
world.setBlockState(pos, this.blockState.getBaseState().withProperty(TYPE, getBiomePlantType(world, pos)).withProperty(HALF, state.getValue(HALF)));
this.checkAndDropBlock(world, pos, state);
}

public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
worldIn.setBlockState(pos.up(), this.getDefaultState().withProperty(HALF, EnumBlockHalf.UPPER), 2);
}

@Override
public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
{
super.onBlockHarvested(worldIn, pos, state, player);
Expand All @@ -141,61 +139,114 @@ public Weight getWeight(@Nonnull ItemStack stack)
return Weight.MEDIUM;
}

@Override
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
{
return false;
}

@Override
public boolean canShrink(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
{
return ClimateTFC.getHeightAdjustedBiomeTemp(worldIn, pos) < 20 || ClimateTFC.getHeightAdjustedBiomeTemp(worldIn, pos) > 35;
}

@Override
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state)
{
return false;
}

@Override
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state)
{
}

@Override
public void shrink(World worldIn, Random rand, BlockPos pos, IBlockState state)
{
if (state.getValue(HALF) == EnumBlockHalf.UPPER)
{
worldIn.setBlockToAir(pos);
}
else if (BlocksTFC.TALL_GRASS.canPlaceBlockAt(worldIn, pos))
{
worldIn.setBlockState(pos, BlocksTFC.TALL_GRASS.getBlockState().getBaseState().withProperty(TYPE, getBiomePlantType(worldIn, pos)));
}
}

@Override
public IBlockState getStateFromMeta(int meta)
{
return (meta & 8) > 0 ? this.getDefaultState().withProperty(HALF, EnumBlockHalf.UPPER) : this.getDefaultState().withProperty(HALF, EnumBlockHalf.LOWER).withProperty(TYPE, EnumGrassType.byMetadata(meta & 7));
}

@Override
public int getMetaFromState(IBlockState state)
{
return state.getValue(HALF) == EnumBlockHalf.UPPER ? 8 : (state.getValue(TYPE)).getMeta();
}

@Override
public void onBlockAdded(World world, BlockPos chunkPos, IBlockState state)
public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random)
{
world.setBlockState(chunkPos, this.blockState.getBaseState().withProperty(TYPE, getBiomePlantType(world, chunkPos)).withProperty(HALF, state.getValue(HALF)));
if (canShrink(worldIn, pos, state, worldIn.isRemote) && random.nextDouble() < getGrowthRate())
{
shrink(worldIn, random, pos, state);
}
else
{
worldIn.setBlockState(pos, this.blockState.getBaseState().withProperty(TYPE, getBiomePlantType(worldIn, pos)).withProperty(HALF, state.getValue(HALF)));
}

this.updateTick(worldIn, pos, state, random);
}

@Override
public void onBlockAdded(World world, BlockPos pos, IBlockState state)
{
world.setBlockState(pos, this.blockState.getBaseState().withProperty(TYPE, getBiomePlantType(world, pos)).withProperty(HALF, state.getValue(HALF)));
this.checkAndDropBlock(world, pos, state);
}

@Override
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
{
if (!worldIn.isRemote && stack.getItem() == Items.SHEARS)
{
if (!worldIn.isRemote && stack.getItem() == Items.SHEARS)
if (state.getValue(HALF) == EnumBlockHalf.UPPER)
{
spawnAsEntity(worldIn, pos, new ItemStack(BlocksTFC.TALL_GRASS, 1));
}
else
{
player.addStat(StatList.getBlockStats(this));
spawnAsEntity(worldIn, pos, new ItemStack(BlocksTFC.DOUBLE_TALL_GRASS, 1, (state.getValue(TYPE)).getMeta()));
spawnAsEntity(worldIn, pos, new ItemStack(BlocksTFC.DOUBLE_TALL_GRASS, 1));
}
else if (!worldIn.isRemote && stack.getItem().getHarvestLevel(stack, "knife", player, state) != -1)
}
else if (!worldIn.isRemote && stack.getItem().getHarvestLevel(stack, "knife", player, state) != -1)
{
if (state.getValue(HALF) == EnumBlockHalf.UPPER)
{
player.addStat(StatList.getBlockStats(this));
spawnAsEntity(worldIn, pos, new ItemStack(ItemsTFC.HAY, 1));
}
else
{
super.harvestBlock(worldIn, player, pos, state, te, stack);
spawnAsEntity(worldIn, pos, new ItemStack(ItemsTFC.HAY, 2));
}
}
else
{
super.harvestBlock(worldIn, player, pos, state, te, stack);
}
}

@Override
protected BlockStateContainer createBlockState()
{
return new BlockStateContainer(this, new IProperty[] {HALF, TYPE});
}

@Override
public Block.EnumOffsetType getOffsetType()
{
return Block.EnumOffsetType.XZ;
Expand All @@ -210,9 +261,17 @@ public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos)
@Override
public NonNullList<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos, int fortune)
{
return NonNullList.withSize(1, new ItemStack(BlocksTFC.DOUBLE_TALL_GRASS, 1));
if (world.getBlockState(pos).getValue(HALF) == EnumBlockHalf.UPPER)
{
return NonNullList.withSize(1, new ItemStack(BlocksTFC.TALL_GRASS, 1));
}
else
{
return NonNullList.withSize(1, new ItemStack(BlocksTFC.DOUBLE_TALL_GRASS, 1));
}
}

@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{
return FULL_BLOCK_AABB;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import net.dries007.tfc.api.types.Plant;
import net.dries007.tfc.objects.blocks.BlocksTFC;
import net.dries007.tfc.world.classic.CalenderTFC;
import net.dries007.tfc.world.classic.ClimateTFC;
import net.dries007.tfc.world.classic.chunkdata.ChunkDataTFC;

public class BlockPlantTFC extends BlockBush implements IItemSize
{
Expand Down Expand Up @@ -132,21 +134,41 @@ public net.minecraftforge.common.EnumPlantType getPlantType(net.minecraft.world.
@Override
public void randomTick(World worldIn, BlockPos pos, IBlockState state, Random random)
{
super.randomTick(worldIn, pos, state, random);
// Check the current time against the current stage
int currentStage = state.getValue(GROWTHSTAGE);
int expectedStage = CalenderTFC.getMonthOfYear().id();
// If it is late and should grow, and some randomness

if (currentStage != expectedStage && random.nextDouble() < 0.5)
{
// Update to the next stage
worldIn.setBlockState(pos, state.withProperty(GROWTHSTAGE, expectedStage));
}

this.updateTick(worldIn, pos, state, random);
}

@Override
public void onBlockAdded(World world, BlockPos pos, IBlockState state)
{
world.setBlockState(pos, this.blockState.getBaseState().withProperty(GROWTHSTAGE, CalenderTFC.getMonthOfYear().id()));
this.checkAndDropBlock(world, pos, state);
}

@Override
public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state)
{
if (state.getBlock() == this)
{
IBlockState soil = worldIn.getBlockState(pos.down());
return soil.getBlock().canSustainPlant(soil, worldIn, pos.down(), net.minecraft.util.EnumFacing.UP, this) && plant.isValidLocation(ClimateTFC.getHeightAdjustedBiomeTemp(worldIn, pos), ChunkDataTFC.getRainfall(worldIn, pos));
}
return this.canSustainBush(worldIn.getBlockState(pos.down()));
}

@Override
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
{
if (!canBlockStay(worldIn, pos, state))
{
worldIn.setBlockToAir(pos);
}
}
}
Loading

0 comments on commit 44b84aa

Please sign in to comment.