Re-added bulb trees
This commit is contained in:
parent
890f7308db
commit
6770e18d50
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue