}
private void generateCaveBranch(CuboidBlockMaterialBuffer blockData, Vector3f chunk, Vector3f target, double horizontalScale, double verticalScale,
double horizontalAngle, double verticalAngle, int startingNode, int nodeAmount, Random random) {
final Vector3f middle = new Vector3f(chunk.getX() + 8, 0, chunk.getZ() + 8);
double horizontalOffset = 0;
double verticalOffset = 0;
random = new Random(random.nextLong());
if (nodeAmount <= 0) {
final int size = (OVERLAP - 1) * 16;
nodeAmount = size - random.nextInt(size / 4);
}
final int intersectionNode = random.nextInt(nodeAmount / 2) + nodeAmount / 4;
final boolean extraVerticalScale = random.nextInt(6) == 0;
final boolean lastNode;
if (startingNode == -1) {
startingNode = nodeAmount / 2;
lastNode = true;
} else {
lastNode = false;
}
for (; startingNode < nodeAmount; startingNode++) {
final double horizontalSize = 1.5 + TrigMath.sin((float) (startingNode * Math.PI / nodeAmount)) * horizontalScale;
final double verticalSize = horizontalSize * verticalScale;
target = target.add(Vector3f.createDirection((float) horizontalAngle, (float) verticalAngle));
if (extraVerticalScale) {
verticalAngle *= 0.92;
} else {
verticalAngle *= 0.7;
}
verticalAngle += verticalOffset * 0.1;
horizontalAngle += horizontalOffset * 0.1;
verticalOffset *= 0.9;
horizontalOffset *= 0.75;
verticalOffset += (random.nextDouble() - random.nextDouble()) * random.nextDouble() * 2;
horizontalOffset += (random.nextDouble() - random.nextDouble()) * random.nextDouble() * 4;
if (!lastNode) {
if (startingNode == intersectionNode && horizontalScale > 1) {
generateCaveBranch(blockData, chunk, target, random.nextDouble() * 0.5f + 0.5f, 1, horizontalAngle - ((float) Math.PI / 2), verticalAngle / 3, startingNode, nodeAmount, new Random(random.nextLong()));
generateCaveBranch(blockData, chunk, target, random.nextDouble() * 0.5f + 0.5f, 1, horizontalAngle + ((float) Math.PI / 2), verticalAngle / 3, startingNode, nodeAmount, new Random(random.nextLong()));
return;
}
if (random.nextInt(4) == 0) {
continue;
}
}
final double xOffset = target.getX() - middle.getX();
final double zOffset = target.getZ() - middle.getZ();
final double nodesLeft = nodeAmount - startingNode;
final double offsetHorizontalScale = horizontalScale + 18;
if ((xOffset * xOffset + zOffset * zOffset) - nodesLeft * nodesLeft > offsetHorizontalScale * offsetHorizontalScale) {
return;
}
if (target.getX() < middle.getX() - 16 - horizontalSize * 2
|| target.getZ() < middle.getZ() - 16 - horizontalSize * 2
|| target.getX() > middle.getX() + 16 + horizontalSize * 2
|| target.getZ() > middle.getZ() + 16 + horizontalSize * 2) {
continue;
}
final Vector3f start = new Vector3f(GenericMath.floor(target.getX() - horizontalSize) - chunk.getFloorX() - 1,
GenericMath.floor(target.getY() - verticalSize) - 1, GenericMath.floor(target.getZ() - horizontalSize) - chunk.getFloorZ() - 1);
final Vector3f end = new Vector3f(GenericMath.floor(target.getX() + horizontalSize) - chunk.getFloorX() + 1,
GenericMath.floor(target.getY() + verticalSize) + 1, GenericMath.floor(target.getZ() + horizontalSize) - chunk.getFloorZ() + 1);
final NetherCaveNode node = new NetherCaveNode(blockData, chunk, start, end, target, verticalSize, horizontalSize);
if (node.canPlace()) {
node.place();