Make ore algorithm readable

This commit is contained in:
Astrash 2023-10-20 10:55:23 +11:00
parent 4e5b02ef42
commit 805f99f57a

View File

@ -58,53 +58,56 @@ public class VanillaOre implements Structure {
@Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
float f = random.nextFloat() * (float) Math.PI;
double g = size / 8.0F;
int i = (int) FastMath.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
double startX = (double) location.getX() + FastMath.sin(f) * g;
double endX = (double) location.getX() - FastMath.sin(f) * g;
double startZ = (double) location.getZ() + FastMath.cos(f) * g;
double endZ = (double) location.getZ() - FastMath.cos(f) * g;
float randomRadian = random.nextFloat() * (float) Math.PI;
double eigthSize = size / 8.0F;
// Place points to form a line segment
double startX = (double) location.getX() + FastMath.sin(randomRadian) * eigthSize;
double endX = (double) location.getX() - FastMath.sin(randomRadian) * eigthSize;
double startZ = (double) location.getZ() + FastMath.cos(randomRadian) * eigthSize;
double endZ = (double) location.getZ() - FastMath.cos(randomRadian) * eigthSize;
double startY = location.getY() + random.nextInt(3) - 2;
double endY = location.getY() + random.nextInt(3) - 2;
int x = (int) (location.getX() - FastMath.ceil(g) - i);
int y = location.getY() - 2 - i;
int z = (int) (location.getZ() - FastMath.ceil(g) - i);
int horizontalSize = (int) (2 * (FastMath.ceil(g) + i));
int verticalSize = 2 * (2 + i);
int i1 = 0;
BitSet bitSet = new BitSet(horizontalSize * verticalSize * horizontalSize);
int sizeInt = (int) size;
double[] points = new double[sizeInt * 4];
int j1 = (int) size;
double[] ds = new double[j1 * 4];
for(int k1 = 0; k1 < j1; ++k1) {
float f1 = (float) k1 / (float) j1;
double d1 = lerp(f1, startX, endX);
double e1 = lerp(f1, startY, endY);
double g1 = lerp(f1, startZ, endZ);
double h1 = random.nextDouble() * (double) j1 / 16.0;
double l1 = ((FastMath.sin((float) Math.PI * f1) + 1.0F) * h1 + 1.0) / 2.0;
ds[k1 * 4] = d1;
ds[k1 * 4 + 1] = e1;
ds[k1 * 4 + 2] = g1;
ds[k1 * 4 + 3] = l1;
// Compute initial point positions and radius
for(int i = 0; i < sizeInt; ++i) {
float t = (float) i / (float) sizeInt;
double xt = lerp(t, startX, endX);
double yt = lerp(t, startY, endY);
double zt = lerp(t, startZ, endZ);
double roll = random.nextDouble() * size / 16.0;
// Taper radius closer to line ends
double radius = ((FastMath.sin((float) Math.PI * t) + 1.0F) * roll + 1.0) / 2.0;
points[i * 4] = xt;
points[i * 4 + 1] = yt;
points[i * 4 + 2] = zt;
points[i * 4 + 3] = radius;
}
for(int k1 = 0; k1 < j1 - 1; ++k1) {
if(!(ds[k1 * 4 + 3] <= 0.0)) {
for(int m1 = k1 + 1; m1 < j1; ++m1) {
if(!(ds[m1 * 4 + 3] <= 0.0)) {
double d1 = ds[k1 * 4] - ds[m1 * 4];
double e1 = ds[k1 * 4 + 1] - ds[m1 * 4 + 1];
double g1 = ds[k1 * 4 + 2] - ds[m1 * 4 + 2];
double h1 = ds[k1 * 4 + 3] - ds[m1 * 4 + 3];
if(h1 * h1 > d1 * d1 + e1 * e1 + g1 * g1) {
if(h1 > 0.0) {
ds[m1 * 4 + 3] = -1.0;
// Compare every point to every other point
for(int a = 0; a < sizeInt - 1; ++a) {
double radiusA = points[a * 4 + 3];
if(radiusA > 0.0) {
for(int b = a + 1; b < sizeInt; ++b) {
double radiusB = points[b * 4 + 3];
if(radiusB > 0.0) {
double dxt = points[a * 4] - points[b * 4];
double dyt = points[a * 4 + 1] - points[b * 4 + 1];
double dzt = points[a * 4 + 2] - points[b * 4 + 2];
double dRadius = radiusA - radiusB;
// If the radius difference is greater than the distance between the two points
if(dRadius * dRadius > dxt * dxt + dyt * dyt + dzt * dzt) {
// Set smaller of two radii to -1
if(dRadius > 0.0) {
points[b * 4 + 3] = -1.0;
} else {
ds[k1 * 4 + 3] = -1.0;
points[a * 4 + 3] = -1.0;
}
}
}
@ -112,37 +115,54 @@ public class VanillaOre implements Structure {
}
}
for(int m1 = 0; m1 < j1; ++m1) {
double d1 = ds[m1 * 4 + 3];
if(!(d1 < 0.0)) {
double e1 = ds[m1 * 4];
double g1 = ds[m1 * 4 + 1];
double h1 = ds[m1 * 4 + 2];
int n1 = (int) FastMath.max(FastMath.floor(e1 - d1), x);
int o1 = (int) FastMath.max(FastMath.floor(g1 - d1), y);
int p1 = (int) FastMath.max(FastMath.floor(h1 - d1), z);
int q1 = (int) FastMath.max(FastMath.floor(e1 + d1), n1);
int r1 = (int) FastMath.max(FastMath.floor(g1 + d1), o1);
int s1 = (int) FastMath.max(FastMath.floor(h1 + d1), p1);
int outset = (int) FastMath.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
int x = (int) (location.getX() - FastMath.ceil(eigthSize) - outset);
int y = location.getY() - 2 - outset;
int z = (int) (location.getZ() - FastMath.ceil(eigthSize) - outset);
for(int t1 = n1; t1 <= q1; ++t1) {
double u1 = ((double) t1 + 0.5 - e1) / d1;
if(u1 * u1 < 1.0) {
for(int v1 = o1; v1 <= r1; ++v1) {
double w1 = ((double) v1 + 0.5 - g1) / d1;
if(u1 * u1 + w1 * w1 < 1.0) {
for(int aa = p1; aa <= s1; ++aa) {
double ab = ((double) aa + 0.5 - h1) / d1;
if(u1 * u1 + w1 * w1 + ab * ab < 1.0 && !(v1 < world.getMinHeight() || v1 >= world.getMaxHeight())) {
int ac = t1 - x + (v1 - y) * horizontalSize + (aa - z) * horizontalSize * verticalSize;
if(!bitSet.get(ac)) {
bitSet.set(ac);
int horizontalSize = (int) (2 * (FastMath.ceil(eigthSize) + outset));
int verticalSize = 2 * (2 + outset);
BlockType block = world.getBlockState(t1, v1, aa).getBlockType();
int sphereCount = 0;
BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize);
if(shouldPlace(block, random, world, t1, v1, aa)) {
world.setBlockState(t1, v1, aa, getMaterial(block), isApplyGravity());
++i1;
// Generate a sphere at each point
for(int i = 0; i < sizeInt; ++i) {
double radius = points[i * 4 + 3];
if(radius > 0.0) {
double xt = points[i * 4];
double yt = points[i * 4 + 1];
double zt = points[i * 4 + 2];
int xLowerBound = (int) FastMath.max(FastMath.floor(xt - radius), x);
int xUpperBound = (int) FastMath.max(FastMath.floor(xt + radius), xLowerBound);
int yLowerBound = (int) FastMath.max(FastMath.floor(yt - radius), y);
int yUpperBound = (int) FastMath.max(FastMath.floor(yt + radius), yLowerBound);
int zLowerBound = (int) FastMath.max(FastMath.floor(zt - radius), z);
int zUpperBound = (int) FastMath.max(FastMath.floor(zt + radius), zLowerBound);
// Iterate over coordinates within bounds
for(int xi = xLowerBound; xi <= xUpperBound; ++xi) {
double dx = ((double) xi + 0.5 - xt) / radius;
if(dx * dx < 1.0) {
for(int yi = yLowerBound; yi <= yUpperBound; ++yi) {
double dy = ((double) yi + 0.5 - yt) / radius;
if(dx * dx + dy * dy < 1.0) {
for(int zi = zLowerBound; zi <= zUpperBound; ++zi) {
double dz = ((double) zi + 0.5 - zt) / radius;
// If position is inside the sphere
if(dx * dx + dy * dy + dz * dz < 1.0 && !(yi < world.getMinHeight() || yi >= world.getMaxHeight())) {
int index = xi - x + (yi - y) * horizontalSize + (zi - z) * horizontalSize * verticalSize;
if(!visited.get(index)) { // Skip blocks that have already been visited
visited.set(index);
BlockType block = world.getBlockState(xi, yi, zi).getBlockType();
if(shouldPlace(block, random, world, xi, yi, zi)) {
world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
++sphereCount;
break;
}
}
@ -155,8 +175,7 @@ public class VanillaOre implements Structure {
}
}
return i1 > 0;
return sphereCount > 0;
}
public boolean shouldPlace(BlockType type, Random random, WritableWorld world, int x, int y, int z) {