Re-added bulb trees

This commit is contained in:
Adubbz 2019-02-24 21:52:19 +11:00
parent 890f7308db
commit 6770e18d50
2 changed files with 235 additions and 0 deletions

View File

@ -10,6 +10,7 @@ package biomesoplenty.common.world.gen.feature;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.common.world.gen.feature.tree.BasicTreeFeature;
import biomesoplenty.common.world.gen.feature.tree.BayouTreeFeature;
import biomesoplenty.common.world.gen.feature.tree.BulbTreeFeature;
import biomesoplenty.common.world.gen.feature.tree.TaigaTreeFeature;
import net.minecraft.init.Blocks;
import net.minecraft.world.gen.feature.AbstractTreeFeature;
@ -21,6 +22,7 @@ public class BOPBiomeFeatures
public static final AbstractTreeFeature<NoFeatureConfig> CONIFEROUS_TREE = new TaigaTreeFeature.Builder().log(BOPBlocks.fir_log.getDefaultState()).leaves(BOPBlocks.fir_leaves.getDefaultState()).minHeight(5).maxHeight(28).create();
public static final AbstractTreeFeature<NoFeatureConfig> OAK_TREE = new BasicTreeFeature.Builder().create();
public static final AbstractTreeFeature<NoFeatureConfig> BAYOU_TREE = new BayouTreeFeature.Builder().create();
public static final AbstractTreeFeature<NoFeatureConfig> BULB_TREE = new BulbTreeFeature.Builder().create();
public static final SurfaceBuilderConfig LOAMY_GRASS_DIRT_GRAVEL_SURFACE = new SurfaceBuilderConfig(BOPBlocks.loamy_grass_block.getDefaultState(), BOPBlocks.loamy_dirt.getDefaultState(), Blocks.GRAVEL.getDefaultState());
}

View File

@ -0,0 +1,233 @@
/*******************************************************************************
* Copyright 2014-2019, 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.world.gen.feature.tree;
import biomesoplenty.common.util.biome.GeneratorUtil;
import biomesoplenty.common.util.block.IBlockPosQuery;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import java.util.Random;
import java.util.Set;
public class BulbTreeFeature extends TreeFeatureBase
{
public static class Builder extends BuilderBase<BulbTreeFeature.Builder, BulbTreeFeature>
{
public Builder()
{
this.minHeight = 6;
this.maxHeight = 12;
this.replace = (world, pos) ->
{
Material mat = world.getBlockState(pos).getMaterial();
return mat == Material.AIR || mat == Material.LEAVES;
};
}
@Override
public BulbTreeFeature create()
{
return new BulbTreeFeature(this.updateNeighbours, this.placeOn, this.replace, this.log, this.leaves, this.altLeaves, this.vine, this.hanging, this.trunkFruit, this.minHeight, this.maxHeight);
}
}
protected BulbTreeFeature(boolean notify, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState altLeaves, IBlockState vine, IBlockState hanging, IBlockState trunkFruit, int minHeight, int maxHeight)
{
super(notify, placeOn, replace, log, leaves, altLeaves, vine, hanging, trunkFruit, minHeight, maxHeight);
}
public boolean setCocoa(IWorld world, BlockPos pos, EnumFacing side)
{
IBlockState cocoaState = Blocks.COCOA.getDefaultState().with(BlockDirectional.FACING, side);
if (this.replace.matches(world, pos))
{
this.setBlockState(world, pos, cocoaState);
return true;
}
return false;
}
public boolean checkSpace(IWorld world, BlockPos pos, int baseHeight, int height)
{
for (int y = 0; y <= height; y++)
{
// require 3x3 for the leaves, 1x1 for the trunk
int radius = (y <= baseHeight ? 0 : 1);
for (int x = -radius; x <= radius; x++)
{
for (int z = -radius; z <= radius; z++)
{
BlockPos pos1 = pos.add(x, y, z);
// note, there may be a sapling on the first layer - make sure this.replace matches it!
if (pos1.getY() >= 255 || !this.replace.matches(world, pos1))
{
return false;
}
}
}
}
return true;
}
// generates a 'branch' of a leaf layer
public void generateBranch(IWorld world, Random random, BlockPos pos, EnumFacing direction)
{
EnumFacing sideways = direction.rotateY();
this.setLeaves(world, pos.offset(direction, 1));
this.setLeaves(world, pos.up().offset(direction, 1));
if (random.nextInt(3) > 0)
{
this.setLeaves(world, pos.up().offset(direction, 1).offset(sideways, 1));
}
}
// generates a layer of leafs (2 blocks high)
public void generateLeafLayer(Set<BlockPos> changedBlocks, IWorld world, Random random, BlockPos pos)
{
for (EnumFacing direction : EnumFacing.Plane.HORIZONTAL)
{
this.generateBranch(world, random, pos, direction);
}
// add the trunk in the middle
this.setLog(changedBlocks, world, pos);
this.setLog(changedBlocks, world, pos.up());
}
public void generateTop(Set<BlockPos> changedBlocks, IWorld world, Random random, BlockPos pos, int topHeight)
{
for (int y = 0; y < topHeight; y++)
{
int radius = topHeight - 1 - y;
for (int x = -radius; x <= radius; ++x)
{
for (int z = -radius; z <= radius; ++z)
{
if (Math.abs(x) < radius || Math.abs(z) < radius || random.nextInt(2) == 0)
{
this.setLeaves(world, pos.add(x, y, z));
}
}
}
if (y < topHeight - 1)
{
// add the trunk in the middle
this.setLog(changedBlocks, world, pos.add(0, y, 0));
} else {
// add leaves on top for certain
this.setLeaves(world, pos.add(0, y, 0));
}
}
}
@Override
protected boolean place(Set<BlockPos> changedBlocks, IWorld world, Random random, BlockPos startPos)
{
// Move down until we reach the ground
while (startPos.getY() > 1 && world.isAirBlock(startPos) || world.getBlockState(startPos).getMaterial() == Material.LEAVES) {startPos = startPos.down();}
if (!this.placeOn.matches(world, startPos))
{
// Abandon if we can't place the tree on this block
return false;
}
// Choose heights
int height = GeneratorUtil.nextIntBetween(random, this.minHeight, this.maxHeight);
if (height < 6) {return false;}
int topHeight = 3;
int heightMinusTop = height - topHeight;
int numBranches = heightMinusTop / 5;
int baseHeight = heightMinusTop - (numBranches * 2);
// Start on the space above ground
BlockPos pos = startPos.up();
if (!this.checkSpace(world, pos, baseHeight, height))
{
// Abandon if there isn't enough room
return false;
}
// Generate bottom of tree (trunk only)
for(int i = 0; i < baseHeight; i++)
{
this.setLog(changedBlocks, world, pos);
pos = pos.up();
}
// Generate middle of the tree - 2 steps at a time (trunk and leaves)
for (int i = 0; i < numBranches; i++)
{
this.generateLeafLayer(changedBlocks, world, random, pos);
pos = pos.up(2);
}
// Generate the top of the tree
this.generateTop(changedBlocks, world, random, pos, topHeight);
// Add vines
this.addVines(world, random, startPos, baseHeight, height, 3, 10);
// Add cocoa
// this.addCocoa(world, random, startPos, baseHeight, 3);
return true;
}
protected void addVines(IWorld world, Random rand, BlockPos startPos, int baseHeight, int height, int leavesRadius, int generationAttempts)
{
if (this.vine == null) {return;}
for (int i = 0; i < generationAttempts; i++)
{
// choose a random direction
EnumFacing direction = EnumFacing.Plane.HORIZONTAL.random(rand);
EnumFacing back = direction.getOpposite();
EnumFacing sideways = direction.rotateY();
// choose a random starting point somewhere just outside the boundary of the tree leaves
BlockPos pos = startPos.up(GeneratorUtil.nextIntBetween(rand, baseHeight + 1, height)).offset(direction, leavesRadius + 1).offset(sideways, GeneratorUtil.nextIntBetween(rand, -leavesRadius, leavesRadius));
// move back towards the center until we meet a leaf, then stick a vine on it
for (int l = 0; l < leavesRadius; l++)
{
if (world.getBlockState(pos.offset(back, 1 + l)) == this.leaves) {
this.setVine(world, rand, pos.offset(back, l), back, 4);
break;
}
}
}
}
protected void addCocoa(IWorld world, Random rand, BlockPos startPos, int baseHeight, int generationAttempts)
{
for (int i = 0; i < generationAttempts; i++)
{
// choose a random direction
EnumFacing direction = EnumFacing.Plane.HORIZONTAL.random(rand);
EnumFacing back = direction.getOpposite();
// choose a random point next to the trunk
BlockPos pos = startPos.up(GeneratorUtil.nextIntBetween(rand, 1, baseHeight)).offset(direction, 1);
// stick a cocoa pod on it
this.setCocoa(world, pos, back);
}
}
}