General system stability improvements to enhance the user's experience. Closes #1439
This commit is contained in:
parent
fa5fbc23c8
commit
a8ef891b37
|
@ -10,7 +10,6 @@ package biomesoplenty.common.world.gen.feature.tree;
|
||||||
import biomesoplenty.common.util.block.IBlockPosQuery;
|
import biomesoplenty.common.util.block.IBlockPosQuery;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
@ -19,6 +18,7 @@ import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.gen.IWorldGenerationReader;
|
import net.minecraft.world.gen.IWorldGenerationReader;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
public Builder()
|
public Builder()
|
||||||
{
|
{
|
||||||
this.minHeight = 5;
|
this.minHeight = 5;
|
||||||
this.maxHeight = 17;
|
this.maxHeight = 12;
|
||||||
this.trunkWidth = 1;
|
this.trunkWidth = 1;
|
||||||
this.foliageHeight = 4;
|
this.foliageHeight = 5;
|
||||||
this.foliageDensity = 1.0F;
|
this.foliageDensity = 1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,26 +52,15 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Random random;
|
|
||||||
private IWorld world;
|
|
||||||
private BlockPos origin;
|
|
||||||
|
|
||||||
private int height;
|
|
||||||
private int trunkHeight;
|
|
||||||
private double trunkHeightScale = 0.618;
|
private double trunkHeightScale = 0.618;
|
||||||
private double branchSlope = 0.381;
|
private double branchSlope = 0.381;
|
||||||
private double widthScale = 1;
|
private double widthScale = 1;
|
||||||
private int trunkWidth = 1;
|
private int trunkWidth = 1;
|
||||||
//private int heightVariance = 12;
|
|
||||||
|
|
||||||
//Configurable fields
|
//Configurable fields
|
||||||
private boolean updateNeighbours;
|
|
||||||
private int foliageHeight;
|
private int foliageHeight;
|
||||||
private double foliageDensity;
|
private double foliageDensity;
|
||||||
|
|
||||||
private List<FoliageCoords> foliageCoords;
|
|
||||||
|
|
||||||
|
|
||||||
protected BigTreeFeature(boolean notify, IBlockPosQuery placeOn, IBlockPosQuery replace, BlockState log, BlockState leaves, BlockState altLeaves, BlockState vine, BlockState hanging, BlockState trunkFruit, int minHeight, int maxHeight, int trunkWidth, int foliageHeight, double foliageDensity)
|
protected BigTreeFeature(boolean notify, IBlockPosQuery placeOn, IBlockPosQuery replace, BlockState log, BlockState leaves, BlockState altLeaves, BlockState vine, BlockState hanging, BlockState trunkFruit, int minHeight, int maxHeight, int trunkWidth, int foliageHeight, double foliageDensity)
|
||||||
{
|
{
|
||||||
super(notify, placeOn, replace, log, leaves, altLeaves, vine, hanging, trunkFruit, minHeight, maxHeight);
|
super(notify, placeOn, replace, log, leaves, altLeaves, vine, hanging, trunkFruit, minHeight, maxHeight);
|
||||||
|
@ -80,75 +69,6 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
this.trunkWidth = trunkWidth;
|
this.trunkWidth = trunkWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void prepare()
|
|
||||||
{
|
|
||||||
// Populate the list of foliage cluster locations.
|
|
||||||
// Designed to be overridden in child classes to change basic
|
|
||||||
// tree properties (trunk width, branch angle, foliage density, etc..).
|
|
||||||
|
|
||||||
trunkHeight = (int) (height * trunkHeightScale);
|
|
||||||
|
|
||||||
if (trunkHeight >= height)
|
|
||||||
{
|
|
||||||
trunkHeight = height - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define foliage clusters per y
|
|
||||||
int clustersPerY = (int) (1.382 + Math.pow(foliageDensity * height / 13.0, 2));
|
|
||||||
if (clustersPerY < 1) {
|
|
||||||
clustersPerY = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int trunkTop = origin.getY() + trunkHeight;
|
|
||||||
int relativeY = height - foliageHeight;
|
|
||||||
|
|
||||||
foliageCoords = Lists.newArrayList();
|
|
||||||
foliageCoords.add(new FoliageCoords(origin.up(relativeY), trunkTop));
|
|
||||||
|
|
||||||
for (; relativeY >= 0; relativeY--)
|
|
||||||
{
|
|
||||||
float treeShape = treeShape(relativeY);
|
|
||||||
|
|
||||||
if (treeShape < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < clustersPerY; i++)
|
|
||||||
{
|
|
||||||
final double radius = widthScale * treeShape * (random.nextFloat() + 0.328);
|
|
||||||
final double angle = random.nextFloat() * 2 * Math.PI;
|
|
||||||
|
|
||||||
final double x = radius * Math.sin(angle) + 0.5;
|
|
||||||
final double z = radius * Math.cos(angle) + 0.5;
|
|
||||||
|
|
||||||
final BlockPos checkStart = origin.add(x, relativeY - 1, z);
|
|
||||||
final BlockPos checkEnd = checkStart.up(foliageHeight);
|
|
||||||
|
|
||||||
// check the center column of the cluster for obstructions.
|
|
||||||
if (checkLine(checkStart, checkEnd) == -1)
|
|
||||||
{
|
|
||||||
// If the cluster can be created, check the branch path for obstructions.
|
|
||||||
final int dx = origin.getX() - checkStart.getX();
|
|
||||||
final int dz = origin.getZ() - checkStart.getZ();
|
|
||||||
|
|
||||||
final double height = checkStart.getY() - Math.sqrt(dx * dx + dz * dz) * branchSlope;
|
|
||||||
final int branchTop = height > trunkTop ? trunkTop : (int) height;
|
|
||||||
final BlockPos checkBranchBase = new BlockPos(origin.getX(), branchTop, origin.getZ());
|
|
||||||
|
|
||||||
// Now check the branch path
|
|
||||||
if (checkLine(checkBranchBase, checkStart) == -1)
|
|
||||||
{
|
|
||||||
// If the branch path is clear, add the position to the list of foliage positions
|
|
||||||
foliageCoords.add(new FoliageCoords(checkStart, checkBranchBase.getY()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void crossection(BlockPos pos, float radius)
|
|
||||||
{
|
|
||||||
// Create a circular cross section.
|
// Create a circular cross section.
|
||||||
//
|
//
|
||||||
// Used to nearly everything in the foliage, branches, and trunk.
|
// Used to nearly everything in the foliage, branches, and trunk.
|
||||||
|
@ -159,152 +79,131 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
// radius is the radius of the section from the center
|
// radius is the radius of the section from the center
|
||||||
// direction is the direction the cross section is pointed, 0 for x, 1
|
// direction is the direction the cross section is pointed, 0 for x, 1
|
||||||
// for y, 2 for z material is the index number for the material to use
|
// for y, 2 for z material is the index number for the material to use
|
||||||
|
private void crossSection(IWorld world, BlockPos pos, float radius, MutableBoundingBox boundingBox, Set<BlockPos> changedBlocks)
|
||||||
final int r = (int) (radius + 0.618);
|
{
|
||||||
|
final int r = (int)((double)radius + trunkHeightScale);
|
||||||
|
|
||||||
for (int dx = -r; dx <= r; dx++)
|
for (int dx = -r; dx <= r; dx++)
|
||||||
{
|
{
|
||||||
for (int dz = -r; dz <= r; dz++)
|
for (int dz = -r; dz <= r; dz++)
|
||||||
{
|
{
|
||||||
if (Math.pow(Math.abs(dx) + 0.5, 2) + Math.pow(Math.abs(dz) + 0.5, 2) <= radius * radius)
|
if (Math.pow((double)Math.abs(dx) + 0.5D, 2.0D) + Math.pow((double)Math.abs(dz) + 0.5D, 2.0D) <= (double)(radius * radius))
|
||||||
{
|
{
|
||||||
BlockPos checkedPos = pos.add(dx, 0, dz);
|
BlockPos blockpos = pos.add(dx, 0, dz);
|
||||||
if (this.replace.matches(world, checkedPos))
|
if (this.isAirOrLeaves(world, blockpos))
|
||||||
{
|
{
|
||||||
if (this.altLeaves != Blocks.AIR.getDefaultState())
|
// Mojang sets leaves via the method used for logs. Probably intentional?
|
||||||
{
|
this.setLogState(changedBlocks, world, blockpos, this.leaves, boundingBox);
|
||||||
int rand = new Random().nextInt(4);
|
|
||||||
|
|
||||||
if (rand == 0)
|
|
||||||
{
|
|
||||||
this.setAltLeaves(world, checkedPos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.setLeaves(this.world, checkedPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.setLeaves(this.world, checkedPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float treeShape(int y)
|
}
|
||||||
{
|
|
||||||
// Take the y position relative to the base of the tree.
|
// Take the y position relative to the base of the tree.
|
||||||
// Return the distance the foliage should be from the trunk axis.
|
// Return the distance the foliage should be from the trunk axis.
|
||||||
// Return a negative number if foliage should not be created at this
|
// Return a negative number if foliage should not be created at this
|
||||||
// height. This method is intended for overriding in child classes,
|
// height. This method is intended for overriding in child classes,
|
||||||
// allowing different shaped trees. This method should return a
|
// allowing different shaped trees. This method should return a
|
||||||
// consistent value for each y (don't randomize).
|
// consistent value for each y (don't randomize).
|
||||||
|
private float treeShape(int height, int y)
|
||||||
if (y < height * 0.3f) {
|
{
|
||||||
return -1f;
|
if ((float)y < (float)height * 0.3F)
|
||||||
|
{
|
||||||
|
return -1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
final float radius = height / 2.0f;
|
float radius = (float)height / 2.0F;
|
||||||
final float adjacent = radius - y;
|
float adjacent = radius - (float)y;
|
||||||
|
|
||||||
float distance = MathHelper.sqrt(radius * radius - adjacent * adjacent);
|
float distance = MathHelper.sqrt(radius * radius - adjacent * adjacent);
|
||||||
|
|
||||||
if (adjacent == 0) {
|
if (adjacent == 0.0F)
|
||||||
|
{
|
||||||
distance = radius;
|
distance = radius;
|
||||||
} else if (Math.abs(adjacent) >= radius) {
|
}
|
||||||
return 0f;
|
else if (Math.abs(adjacent) >= radius)
|
||||||
|
{
|
||||||
|
return 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alter this factor to change the overall width of the tree.
|
return distance * 0.5F;
|
||||||
return distance * 0.5f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Take the y position relative to the base of the foliage cluster.
|
// Take the y position relative to the base of the foliage cluster.
|
||||||
// Return the radius of the cluster at this y
|
// Return the radius of the cluster at this y
|
||||||
// Return a negative number if no foliage should be created at this
|
// Return a negative number if no foliage should be created at this
|
||||||
// level. This method is intended for overriding in child classes,
|
// level. This method is intended for overriding in child classes,
|
||||||
// allowing foliage of different sizes and shapes.
|
// allowing foliage of different sizes and shapes.
|
||||||
|
private float foliageShape(int y)
|
||||||
protected float foliageShape(int y)
|
|
||||||
{
|
{
|
||||||
if (y < 0 || y >= foliageHeight)
|
if (y >= 0 && y < 5)
|
||||||
{
|
{
|
||||||
return -1f;
|
return y != 0 && y != 4 ? 3.0F : 2.0F;
|
||||||
}
|
|
||||||
//The following has been replaced as recommended by
|
|
||||||
//http://www.reddit.com/r/Minecraft/comments/1m97cw/while_you_are_all_crying_over_the_name_change_of/ccfgc3k
|
|
||||||
//The change should fix the decaying leaves
|
|
||||||
else if (y == 0 || y == foliageHeight - 1)
|
|
||||||
{
|
|
||||||
return 2f;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 3f;
|
return -1.0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void foliageCluster(BlockPos blockPos)
|
|
||||||
{
|
|
||||||
// Generate a cluster of foliage, with the base at blockPos
|
// Generate a cluster of foliage, with the base at blockPos
|
||||||
// The shape of the cluster is derived from foliageShape
|
// The shape of the cluster is derived from foliageShape
|
||||||
// crossection is called to make each level.
|
// crossection is called to make each level.
|
||||||
|
private void foliageCluster(IWorld world, BlockPos pos, MutableBoundingBox boundingBox, Set<BlockPos> changedBlocks)
|
||||||
for (int y = 0; y < foliageHeight; y++)
|
|
||||||
{
|
{
|
||||||
crossection(blockPos.up(y), foliageShape(y));
|
for (int y = 0; y < 5; y++)
|
||||||
|
{
|
||||||
|
this.crossSection(world, pos.up(y), this.foliageShape(y), boundingBox, changedBlocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void limb(Set<BlockPos> changedBlocks, MutableBoundingBox boundingBox, BlockPos startPos, BlockPos endPos, BlockState state)
|
// Check from coordinates start to end (both inclusive) for blocks
|
||||||
|
// other than air and foliage If a block other than air and foliage is
|
||||||
|
// found, return the number of steps taken.
|
||||||
|
// If no block other than air and foliage is found, return -1.
|
||||||
|
// Examples:
|
||||||
|
// If the third block searched is stone, return 2
|
||||||
|
// If the first block searched is lava, return 0
|
||||||
|
private int checkLineAndOptionallySet(Set<BlockPos> changedBlocks, IWorld world, BlockPos startPos, BlockPos endPos, boolean set, MutableBoundingBox boundingBox)
|
||||||
{
|
{
|
||||||
// Create a limb from the start position to the end position.
|
if (!set && Objects.equals(startPos, endPos)) {
|
||||||
// Used for creating the branches and trunk.
|
return -1;
|
||||||
// Similar to checkLine, however it is setting rather than checking
|
} else {
|
||||||
|
|
||||||
//The distance between the two points, may be negative if the second pos is smaller
|
//The distance between the two points, may be negative if the second pos is smaller
|
||||||
BlockPos delta = endPos.add(-startPos.getX(), -startPos.getY(), -startPos.getZ());
|
BlockPos delta = endPos.add(-startPos.getX(), -startPos.getY(), -startPos.getZ());
|
||||||
|
|
||||||
int steps = getSteps(delta);
|
int steps = this.getGreatestDistance(delta);
|
||||||
|
|
||||||
//How much should be incremented with each iteration relative
|
//How much should be incremented with each iteration relative
|
||||||
//to the greatest distance which will have a value of 1.0F.
|
//to the greatest distance which will have a value of 1.0F.
|
||||||
float dx = delta.getX() / (float) steps;
|
float dx = (float)delta.getX() / (float)steps;
|
||||||
float dy = delta.getY() / (float) steps;
|
float dy = (float)delta.getY() / (float)steps;
|
||||||
float dz = delta.getZ() / (float) steps;
|
float dz = (float)delta.getZ() / (float)steps;
|
||||||
|
|
||||||
//Iterates over all values between the start pos and end pos
|
//Iterates over all values between the start pos and end pos
|
||||||
for (int i = 0; i <= steps; i++)
|
for (int j = 0; j <= steps; ++j)
|
||||||
{
|
{
|
||||||
//A delta position between the start pos and end pos. Increments are added to the x, y and z coords
|
BlockPos deltaPos = startPos.add((double)(0.5F + (float)j * dx), (double)(0.5F + (float)j * dy), (double)(0.5F + (float)j * dz));
|
||||||
//so that they meet their corresponding values in the end pos when j reaches the greatest distance. 0.5F
|
if (set)
|
||||||
//is added to ensure the final point is reached.
|
|
||||||
BlockPos blockPos = startPos.add(.5f + i * dx, .5f + i * dy, .5f + i * dz);
|
|
||||||
Direction.Axis logAxis = getLogAxis(startPos, blockPos);
|
|
||||||
|
|
||||||
this.setLog(changedBlocks, this.world, blockPos, logAxis, boundingBox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getSteps(BlockPos pos)
|
|
||||||
{
|
{
|
||||||
final int absX = MathHelper.abs(pos.getX());
|
this.setLog(changedBlocks, world, deltaPos, this.getLogAxis(startPos, deltaPos), boundingBox);
|
||||||
final int absY = MathHelper.abs(pos.getY());
|
}
|
||||||
final int absZ = MathHelper.abs(pos.getZ());
|
else if (!this.func_214587_a(world, deltaPos))
|
||||||
|
{
|
||||||
//Determine which axis has the greatest distance from the origin (0, 0, 0)
|
return j;
|
||||||
if (absZ > absX && absZ > absY) {
|
}
|
||||||
return absZ;
|
|
||||||
} else if (absY > absX) {
|
|
||||||
return absY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return absX;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute greatest distance in the BlockPos object.
|
||||||
|
*/
|
||||||
private int getGreatestDistance(BlockPos posIn)
|
private int getGreatestDistance(BlockPos posIn)
|
||||||
{
|
{
|
||||||
int i = MathHelper.abs(posIn.getX());
|
int i = MathHelper.abs(posIn.getX());
|
||||||
|
@ -339,204 +238,143 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
return axis;
|
return axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeFoliage()
|
private void makeFoliage(IWorld worldIn, int height, BlockPos pos, List<FoliageCoordinates> coordinates, MutableBoundingBox boundingBox, Set<BlockPos> changedBlocks)
|
||||||
{
|
{
|
||||||
// Create the tree foliage.
|
for (FoliageCoordinates coordinate : coordinates)
|
||||||
// Call foliageCluster at the correct locations
|
|
||||||
|
|
||||||
for (FoliageCoords foliageCoord : foliageCoords)
|
|
||||||
{
|
{
|
||||||
foliageCluster(foliageCoord);
|
if (this.trimBranches(height, coordinate.getBranchBase() - pos.getY()))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean trimBranches(int localY)
|
|
||||||
{
|
{
|
||||||
// For larger trees, randomly "prune" the branches so there
|
this.foliageCluster(worldIn, coordinate, boundingBox, changedBlocks);
|
||||||
// aren't too many.
|
|
||||||
// Return true if the branch should be created.
|
|
||||||
// This method is intended for overriding in child classes, allowing
|
|
||||||
// decent amounts of branches on very large trees.
|
|
||||||
// Can also be used to disable branches on some tree types, or
|
|
||||||
// make branches more sparse.
|
|
||||||
return localY >= height * 0.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void makeTrunk(Set<BlockPos> changedBlocks, MutableBoundingBox boundingBox)
|
|
||||||
{
|
|
||||||
// Create the trunk of the tree.
|
|
||||||
BlockPos start = origin;
|
|
||||||
BlockPos end = origin.up(trunkHeight);
|
|
||||||
BlockState materialState = this.log;
|
|
||||||
|
|
||||||
limb(changedBlocks, boundingBox, start, end, materialState);
|
|
||||||
|
|
||||||
if (trunkWidth == 2)
|
|
||||||
{
|
|
||||||
limb(changedBlocks, boundingBox, start.east(), end.east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.east().south(), end.east().south(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.south(), end.south(), materialState);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trunkWidth == 4)
|
|
||||||
{
|
|
||||||
limb(changedBlocks, boundingBox, start.east(), end.east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.east().south(), end.east().south(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.south(), end.south(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.north(), end.north(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.north().east(), end.north().east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.east().east(), end.east().east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.south().east().east(), end.south().east().east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.south().south().east(), end.south().south().east(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.south().south(), end.south().south(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.west().south(), end.west().south(), materialState);
|
|
||||||
limb(changedBlocks, boundingBox, start.west(), end.west(), materialState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void makeBranches(Set<BlockPos> changedBlocks, MutableBoundingBox boundingBox)
|
|
||||||
{
|
|
||||||
for (FoliageCoords endCoord : foliageCoords)
|
|
||||||
{
|
|
||||||
int branchBase = endCoord.getBranchBase();
|
|
||||||
BlockPos baseCoord = new BlockPos(this.origin.getX(), branchBase, this.origin.getZ());
|
|
||||||
|
|
||||||
if (this.trimBranches(branchBase - this.origin.getY()))
|
|
||||||
{
|
|
||||||
this.limb(changedBlocks, boundingBox, baseCoord, endCoord, this.log);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int checkLine(BlockPos startPos, BlockPos endPos)
|
private boolean trimBranches(int height, int localY)
|
||||||
{
|
{
|
||||||
// Check from coordinates start to end (both inclusive) for blocks
|
return (double)localY >= (double)height * 0.2D;
|
||||||
// other than air and foliage If a block other than air and foliage is
|
|
||||||
// found, return the number of steps taken.
|
|
||||||
// If no block other than air and foliage is found, return -1.
|
|
||||||
// Examples:
|
|
||||||
// If the third block searched is stone, return 2
|
|
||||||
// If the first block searched is lava, return 0
|
|
||||||
|
|
||||||
//The distance between the two points, may be negative if the second pos is smaller
|
|
||||||
BlockPos delta = endPos.add(-startPos.getX(), -startPos.getY(), -startPos.getZ());
|
|
||||||
|
|
||||||
int steps = this.getGreatestDistance(delta);
|
|
||||||
|
|
||||||
//How much should be incremented with each iteration relative
|
|
||||||
//to the greatest distance which will have a value of 1.0F.
|
|
||||||
float dx = (float)delta.getX() / (float)steps;
|
|
||||||
float dy = (float)delta.getY() / (float)steps;
|
|
||||||
float dz = (float)delta.getZ() / (float)steps;
|
|
||||||
|
|
||||||
//Check if both positions are the same
|
|
||||||
if (steps == 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Iterates over all values between the start pos and end pos
|
private void makeTrunk(Set<BlockPos> changedBlocks, IWorld world, BlockPos pos, int height, MutableBoundingBox boundingBox)
|
||||||
for (int i = 0; i <= steps; i++)
|
|
||||||
{
|
{
|
||||||
//A delta position between the start pos and end pos. Increments are added to the x, y and z coords
|
this.checkLineAndOptionallySet(changedBlocks, world, pos, pos.up(height), true, boundingBox);
|
||||||
//so that they meet their corresponding values in the end pos when j reaches the greatest distance. 0.5F
|
|
||||||
//is added to ensure the final point is reached.
|
|
||||||
BlockPos deltaPos = startPos.add((double)(0.5F + (float)i * dx), (double)(0.5F + (float)i * dy), (double)(0.5F + (float)i * dz));
|
|
||||||
|
|
||||||
if (!this.replace.matches(world, deltaPos))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//The line is unobstructed
|
private void makeBranches(Set<BlockPos> changedBlocks, IWorld world, int height, BlockPos origin, List<FoliageCoordinates> coordinates, MutableBoundingBox boundingBox)
|
||||||
return -1;
|
{
|
||||||
|
for (FoliageCoordinates coordinate : coordinates)
|
||||||
|
{
|
||||||
|
int branchBase = coordinate.getBranchBase();
|
||||||
|
BlockPos baseCoord = new BlockPos(origin.getX(), branchBase, origin.getZ());
|
||||||
|
if (!baseCoord.equals(coordinate) && this.trimBranches(height, branchBase - origin.getY()))
|
||||||
|
{
|
||||||
|
this.checkLineAndOptionallySet(changedBlocks, world, baseCoord, coordinate, true, boundingBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean place(Set<BlockPos> changedBlocks, IWorldGenerationReader world, Random random, BlockPos startPos, MutableBoundingBox boundingBox)
|
protected boolean place(Set<BlockPos> changedBlocks, IWorld world, Random rand, BlockPos pos, MutableBoundingBox boundingBox)
|
||||||
{
|
{
|
||||||
this.world = (IWorld)world; // We want an IWorld
|
Random random = new Random(rand.nextLong());
|
||||||
this.origin = startPos;
|
int height = this.checkLocation(changedBlocks, world, pos, this.minHeight + random.nextInt(this.maxHeight), boundingBox);
|
||||||
|
if (height == -1) {
|
||||||
this.random = new Random(random.nextLong());
|
|
||||||
|
|
||||||
this.height = random.nextInt(this.maxHeight - this.minHeight) + this.minHeight;
|
|
||||||
|
|
||||||
if (!this.checkLocation())
|
|
||||||
{
|
|
||||||
this.world = null; //Fix vanilla Mem leak, holds latest world
|
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
this.setDirtAt(world, pos.down(), pos);
|
||||||
|
int trunkHeight = (int)((double)height * this.trunkHeightScale);
|
||||||
|
|
||||||
|
if (trunkHeight >= height) {
|
||||||
|
trunkHeight = height - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Define foliage clusters per y
|
||||||
prepare();
|
int clustersPerY = (int)(1.382D + Math.pow(this.foliageDensity * (double)height / 13.0D, 2.0D));
|
||||||
makeFoliage();
|
|
||||||
makeTrunk(changedBlocks, boundingBox);
|
if (clustersPerY < 1)
|
||||||
makeBranches(changedBlocks, boundingBox);
|
{
|
||||||
} catch (RuntimeException e) {
|
clustersPerY = 1;
|
||||||
// TODO: deal with this.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.world = null; //Fix vanilla Mem leak, holds latest world
|
int trunkTop = pos.getY() + trunkHeight;
|
||||||
|
int relativeY = height - this.foliageHeight;
|
||||||
|
|
||||||
|
List<FoliageCoordinates> foliageCoords = Lists.newArrayList();
|
||||||
|
foliageCoords.add(new FoliageCoordinates(pos.up(relativeY), trunkTop));
|
||||||
|
|
||||||
|
for(; relativeY >= 0; --relativeY)
|
||||||
|
{
|
||||||
|
float treeShape = this.treeShape(height, relativeY);
|
||||||
|
|
||||||
|
if (treeShape < 0.0F)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < clustersPerY; ++i)
|
||||||
|
{
|
||||||
|
final double radius = 1.0D * treeShape * (random.nextFloat() + 0.328D);
|
||||||
|
final double angle = random.nextFloat() * 2.0F * Math.PI;
|
||||||
|
|
||||||
|
final double x = radius * Math.sin(angle) + 0.5D;
|
||||||
|
final double z = radius * Math.cos(angle) + 0.5D;
|
||||||
|
|
||||||
|
final BlockPos checkStart = pos.add(x, relativeY - 1, z);
|
||||||
|
final BlockPos checkEnd = checkStart.up(5);
|
||||||
|
|
||||||
|
// check the center column of the cluster for obstructions.
|
||||||
|
if (this.checkLineAndOptionallySet(changedBlocks, world, checkStart, checkEnd, false, boundingBox) == -1)
|
||||||
|
{
|
||||||
|
// If the cluster can be created, check the branch path for obstructions.
|
||||||
|
final int dx = pos.getX() - checkStart.getX();
|
||||||
|
final int dz = pos.getZ() - checkStart.getZ();
|
||||||
|
|
||||||
|
final double branchHeight = checkStart.getY() - Math.sqrt(dx * dx + dz * dz) * this.branchSlope;
|
||||||
|
final int branchTop = branchHeight > trunkTop ? trunkTop : (int)branchHeight;
|
||||||
|
final BlockPos checkBranchBase = new BlockPos(pos.getX(), branchTop, pos.getZ());
|
||||||
|
|
||||||
|
// Now check the branch path
|
||||||
|
if (this.checkLineAndOptionallySet(changedBlocks, world, checkBranchBase, checkStart, false, boundingBox) == -1)
|
||||||
|
{
|
||||||
|
// If the branch path is clear, add the position to the list of foliage positions
|
||||||
|
foliageCoords.add(new FoliageCoordinates(checkStart, checkBranchBase.getY()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeFoliage(world, height, pos, foliageCoords, boundingBox, changedBlocks);
|
||||||
|
this.makeTrunk(changedBlocks, world, pos, trunkHeight, boundingBox);
|
||||||
|
this.makeBranches(changedBlocks, world, height, pos, foliageCoords, boundingBox);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int checkLocation(Set<BlockPos> changedBlocks, IWorld world, BlockPos pos, int height, MutableBoundingBox boundingBox)
|
||||||
private boolean checkLocation()
|
|
||||||
{
|
{
|
||||||
BlockPos startPos = this.origin.down();
|
if (!this.isSoilOrFarm(world, pos.down(), getSapling()))
|
||||||
|
|
||||||
int start = 0;
|
|
||||||
int end = trunkWidth - 1;
|
|
||||||
|
|
||||||
if (trunkWidth == 4)
|
|
||||||
{
|
{
|
||||||
start = -1;
|
return -1;
|
||||||
end = trunkWidth - 2;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (int x = start; x <= end; x++)
|
|
||||||
{
|
{
|
||||||
for (int z = start; z <= end; z++)
|
int step = this.checkLineAndOptionallySet(changedBlocks, world, pos, pos.up(height - 1), false, boundingBox);
|
||||||
|
|
||||||
|
if (step == -1)
|
||||||
{
|
{
|
||||||
if (!this.placeOn.matches(world, startPos.add(x,0,z)))
|
return height;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return step < 6 ? -1 : step;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Examine center column for how tall the tree can be.
|
static class FoliageCoordinates extends BlockPos
|
||||||
int allowedHeight = checkLine(this.origin, this.origin.up(height - 1));
|
|
||||||
|
|
||||||
if (trunkWidth == 2 || trunkWidth == 4)
|
|
||||||
{
|
|
||||||
allowedHeight = Math.min(checkLine(this.origin.east(), this.origin.east().up(height - 1)), allowedHeight);
|
|
||||||
allowedHeight = Math.min(checkLine(this.origin.east().south(), this.origin.east().south().up(height - 1)), allowedHeight);
|
|
||||||
allowedHeight = Math.min(checkLine(this.origin.south(), this.origin.south().up(height - 1)), allowedHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the set height is good, go with that
|
|
||||||
if (allowedHeight == -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space is too short, tell the build to abort
|
|
||||||
if (allowedHeight < this.minHeight) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
height = allowedHeight;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FoliageCoords extends BlockPos
|
|
||||||
{
|
{
|
||||||
private final int branchBase;
|
private final int branchBase;
|
||||||
|
|
||||||
public FoliageCoords(BlockPos pos, int branchBase)
|
public FoliageCoordinates(BlockPos pos, int branchBase)
|
||||||
{
|
{
|
||||||
super(pos.getX(), pos.getY(), pos.getZ());
|
super(pos.getX(), pos.getY(), pos.getZ());
|
||||||
this.branchBase = branchBase;
|
this.branchBase = branchBase;
|
||||||
|
@ -544,7 +382,7 @@ public class BigTreeFeature extends TreeFeatureBase
|
||||||
|
|
||||||
public int getBranchBase()
|
public int getBranchBase()
|
||||||
{
|
{
|
||||||
return branchBase;
|
return this.branchBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue