General system stability improvements to enhance the user's experience. Closes #1439

This commit is contained in:
Adubbz 2019-08-23 22:09:07 +10:00
parent fa5fbc23c8
commit a8ef891b37
1 changed files with 195 additions and 357 deletions

View File

@ -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;
} }
} }
} }