Improved mahogany tree generation

This commit is contained in:
Forstride 2020-10-07 21:03:14 -04:00
parent 91c81c38f1
commit 61968d1721
3 changed files with 143 additions and 33 deletions

View file

@ -8,47 +8,128 @@
package biomesoplenty.common.world.gen.feature.tree;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.common.util.biome.GeneratorUtil;
import biomesoplenty.common.util.block.IBlockPosQuery;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.SaplingBlock;
import net.minecraft.block.material.Material;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.world.IWorld;
import java.util.Random;
import java.util.Set;
public class MahoganyTreeFeature extends BasicTreeFeature
public class MahoganyTreeFeature extends TreeFeatureBase
{
public static class Builder extends BasicTreeFeature.InnerBuilder<MahoganyTreeFeature.Builder, MahoganyTreeFeature>
public static class Builder extends BuilderBase<MahoganyTreeFeature.Builder, MahoganyTreeFeature>
{
public Builder()
{
this.log = BOPBlocks.mahogany_log.defaultBlockState();
this.leaves = BOPBlocks.mahogany_leaves.defaultBlockState();
this.minHeight = 10;
this.maxHeight = 15;
this.leavesLayerHeight = 1;
this.minHeight = 8;
this.maxHeight = 14;
}
@Override
public MahoganyTreeFeature create()
{
return new MahoganyTreeFeature(this.placeOn, this.replace, this.log, this.leaves, this.altLeaves, this.vine, this.hanging, this.trunkFruit, this.minHeight, this.maxHeight, this.leafLayers, this.leavesOffset, this.maxLeavesRadius, this.leavesLayerHeight, this.placeVinesOn, this.hangingChance);
return new MahoganyTreeFeature(this.placeOn, this.replace, this.log, this.leaves, this.altLeaves, this.vine, this.hanging, this.trunkFruit, this.minHeight, this.maxHeight);
}
}
protected MahoganyTreeFeature(IBlockPosQuery placeOn, IBlockPosQuery replace, BlockState log,
BlockState leaves, BlockState altLeaves, BlockState vine, BlockState hanging, BlockState trunkFruit,
int minHeight, int maxHeight, int leafLayers, int leavesOffset, int maxLeavesRadius, int leavesLayerHeight,
IBlockPosQuery placeVinesOn, float hangingChance)
int minHeight, int maxHeight)
{
super(placeOn, replace, log, leaves, altLeaves, vine, hanging, trunkFruit, minHeight, maxHeight, leafLayers, leavesOffset, maxLeavesRadius, leavesLayerHeight, placeVinesOn, hangingChance);
super(placeOn, replace, log, leaves, altLeaves, vine, hanging, trunkFruit, minHeight, maxHeight);
}
@Override
protected void generateTrunk(Set<BlockPos> changedBlocks, MutableBoundingBox boundingBox, IWorld world, BlockPos start, int height)
protected boolean place(Set<BlockPos> changedLogs, Set<BlockPos> changedLeaves, IWorld world, Random random, BlockPos pos, MutableBoundingBox boundingBox)
{
int endHeight = height - this.leafLayers;
int height = random.nextInt(this.maxHeight - this.minHeight) + this.minHeight;
boolean hasSpace = true;
//Generate only if we are above the lowest bedrock level (1) and reach less than the world height
//There must be a gap of 1 between the top leaf block and the world height
if (pos.getY() >= 1 && pos.getY() + height + 1 <= 256)
{
int radius;
for (int y = pos.getY(); y <= pos.getY() + 1 + height; y++)
{
radius = 1;
//Don't check for space on the first level, if we are a sapling then there will
//already be a block here (the sapling itself)
if (y == pos.getY())
{
radius = 0;
}
//At and above the top log block, require a radius of 2 to be empty
if (y >= pos.getY() + 1 + height - 2)
{
radius = 2;
}
for (int x = pos.getX() - radius; x <= pos.getX() + radius && hasSpace; ++x)
{
for (int z = pos.getZ() - radius; z <= pos.getZ() + radius && hasSpace; ++z)
{
if (y >= 0 && y < 256)
{
if (!this.replace.matches(world, new BlockPos(x, y, z)))
{
hasSpace = false;
}
}
else
{
hasSpace = false;
}
}
}
}
if (!hasSpace)
{
return false;
}
else
{
BlockPos soilPos = pos.below();
Block soil = world.getBlockState(soilPos).getBlock();
boolean isSoil = soil.canSustainPlant(world.getBlockState(soilPos), world, soilPos, Direction.UP, (SaplingBlock) Blocks.OAK_SAPLING);
if (this.placeOn.matches(world, soilPos) && isSoil && pos.getY() < 256 - height - 1)
{
soil.onPlantGrow(world.getBlockState(soilPos), world, soilPos, pos);
this.generateTrunk(changedLogs, changedLeaves, boundingBox, world, pos, height);
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
}
protected void generateTrunk(Set<BlockPos> changedLogs, Set<BlockPos> changedLeaves, MutableBoundingBox boundingBox, IWorld world, BlockPos start, int height)
{
int endHeight = height;
for (int layer = 0; layer <= endHeight - 3; layer++)
{
@ -56,37 +137,66 @@ public class MahoganyTreeFeature extends BasicTreeFeature
if (this.replace.matches(world, middlePos))
{
this.placeLog(world, middlePos, changedBlocks, boundingBox);
this.placeLog(world, middlePos, changedLogs, boundingBox);
}
}
//Generate upper branches
BlockPos branchStartPos = start.above(endHeight - 2);
int branchHeight = (this.leafLayers - 1) + 1;
BlockPos branchStartPos = start.above(endHeight - 3);
generateBranch(changedBlocks, boundingBox, world, branchStartPos, Direction.NORTH, branchHeight);
generateBranch(changedBlocks, boundingBox, world, branchStartPos, Direction.EAST, branchHeight);
generateBranch(changedBlocks, boundingBox, world, branchStartPos, Direction.SOUTH, branchHeight);
generateBranch(changedBlocks, boundingBox, world, branchStartPos, Direction.WEST, branchHeight);
generateBranch(changedLogs, changedLeaves, boundingBox, world, branchStartPos, Direction.NORTH);
generateBranch(changedLogs, changedLeaves, boundingBox, world, branchStartPos, Direction.EAST);
generateBranch(changedLogs, changedLeaves, boundingBox, world, branchStartPos, Direction.SOUTH);
generateBranch(changedLogs, changedLeaves, boundingBox, world, branchStartPos, Direction.WEST);
}
private void generateBranch(Set<BlockPos> changedBlocks, MutableBoundingBox boundingBox, IWorld world, BlockPos middle, Direction direction, int height)
private void generateBranch(Set<BlockPos> changedLogs, Set<BlockPos> changedLeaves, MutableBoundingBox boundingBox, IWorld world, BlockPos middle, Direction direction)
{
BlockPos pos;
BlockPos pos = middle;
int length = 1 + world.getRandom().nextInt(2);
if (replace.matches(world, pos = middle.relative(direction))) this.placeLog(world, pos, direction.getAxis(), changedBlocks, boundingBox);
for (int i = 0; i <= height - 1; i++)
for (int i = 0; i <= length - 1; i++)
{
if (replace.matches(world, pos = middle.relative(direction, 2).above(i + 1))) this.placeLog(world, pos, Direction.Axis.Y, changedBlocks, boundingBox);
}
Direction logDirection = direction.getClockWise();
//Extend inner branches outwards to prevent decay
for (int i = -1; i <= 1; i++)
if (replace.matches(world, pos.relative(direction, i+1)))
{
if (replace.matches(world, pos = middle.relative(direction, 3).relative(logDirection, i).above(height - 1))) this.placeLog(world, pos, logDirection.getAxis(), changedBlocks, boundingBox);
this.placeLog(world, pos.relative(direction, i+1), direction.getAxis(), changedLogs, boundingBox);
}
}
int height = world.getRandom().nextInt(3);
for (int i = 0; i <= height; i++)
{
if (replace.matches(world, pos.relative(direction, length+1).above(i+1)))
{
this.placeLog(world, pos.relative(direction, length+1).above(i+1), Direction.Axis.Y, changedLogs, boundingBox);
}
}
pos = pos.relative(direction, length+1).above(height+2);
int radius = 2;
for (int x = -(radius-1); x <= (radius-1); x++)
{
for (int z = -(radius - 1); z <= (radius - 1); z++)
{
this.placeLeaves(world, pos.offset(x,0,z), changedLeaves, boundingBox);
}
}
for (int x = -radius; x <= radius; x++)
{
for (int z = -radius; z <= radius; z++)
{
if ((x == -radius || x == radius) && (z == -radius || z == radius))
{
continue;
}
else
{
this.placeLeaves(world, pos.offset(x,-1,z), changedLeaves, boundingBox);
}
}
}
}
}

View file

@ -15,8 +15,8 @@ import biomesoplenty.common.world.layer.traits.IBOPContextExtended;
public enum RainfallNoiseLayer implements IBOPAreaTransformer0
{
SMALL_ZONES(0.20D),
MEDIUM_ZONES(0.05D),
SMALL_ZONES(0.16D),
MEDIUM_ZONES(0.06D),
LARGE_ZONES(0.01D);
private final double scale;

View file

@ -15,8 +15,8 @@ import biomesoplenty.common.world.layer.traits.IBOPContextExtended;
public enum TemperatureNoiseLayer implements IBOPAreaTransformer0
{
SMALL_ZONES(0.20D),
MEDIUM_ZONES(0.05D),
SMALL_ZONES(0.16D),
MEDIUM_ZONES(0.06D),
LARGE_ZONES(0.01D);
private final double scale;