From 3a6a923553eaf00145b5e162c9e37019e166ad98 Mon Sep 17 00:00:00 2001 From: Cubitect Date: Fri, 4 Jun 2021 00:10:43 +0200 Subject: [PATCH] Split end city validity and terrain checks --- finders.c | 100 ++++++++++++++++++++++++++++-------------------------- finders.h | 8 ++++- layers.c | 52 ++++++++++++++-------------- 3 files changed, 85 insertions(+), 75 deletions(-) diff --git a/finders.c b/finders.c index 94b5fcd..2c808f2 100644 --- a/finders.c +++ b/finders.c @@ -1795,23 +1795,10 @@ int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn, return isViableFeatureBiome(mc, structureType, biomeID); } - -/* Given bordering noise columns and a fractional position between those, - * determine the surface block height (i.e. where the interpolated noise > 0). - * Note that the noise columns should be of size: ncolxz[ colheight+1 ] - */ -int getSurfaceHeight( - const double ncol00[], const double ncol01[], - const double ncol10[], const double ncol11[], int colheight, - int blockspercell, double dx, double dz); - -void sampleNoiseColumnEnd(double column[33], const SurfaceNoise *sn, - const EndNoise *en, int x, int z); - -int isViableEndCityPos(int mc, EndNoise *en, SurfaceNoise *sn, +int isViableEndStructurePos(int structureType, int mc, EndNoise *en, int64_t seed, int blockX, int blockZ) { - if (mc < MC_1_9) + if (structureType != End_City || mc < MC_1_9) return 0; setEndSeed(en, seed); @@ -1819,84 +1806,99 @@ int isViableEndCityPos(int mc, EndNoise *en, SurfaceNoise *sn, // end biomes vary only on a per-chunk scale (1:16) // voronoi shouldn't matter as the check will be near the chunk center int id; - int chunkX = blockX >> 4, chunkZ = blockZ >> 4; + int chunkX = blockX >> 4; + int chunkZ = blockZ >> 4; mapEndBiome(en, &id, chunkX, chunkZ, 1, 1); - if (!isViableFeatureBiome(mc, End_City, id)) - return 0; + return isViableFeatureBiome(mc, End_City, id) ? id : 0; +} - if (!sn) - return 1; +/* Given bordering noise columns and a fractional position between those, + * determine the surface block height (i.e. where the interpolated noise > 0). + * Note that the noise columns should be of size: ncolxz[ colheight+1 ] + */ +int getSurfaceHeight( + const double ncol00[], const double ncol01[], + const double ncol10[], const double ncol11[], + int colymin, int colymax, int blockspercell, double dx, double dz); - initSurfaceNoiseEnd(sn, seed); +void sampleNoiseColumnEnd(double column[], const SurfaceNoise *sn, + const EndNoise *en, int x, int z, int colymin, int colymax); +int isViableEndCityTerrain(const EndNoise *en, const SurfaceNoise *sn, + int blockX, int blockZ) +{ + int chunkX = blockX >> 4; + int chunkZ = blockZ >> 4; blockX = (chunkX << 4) + 7; blockZ = (chunkZ << 4) + 7; int cellx = (blockX >> 3); int cellz = (blockZ >> 3); - double ncol[3][3][33]; + // TODO: make sure upper bound is ok + const int y0 = 15, y1 = 18; // only check range that could yield h >= 60 + double ncol[3][3][y1-y0+1]; - sampleNoiseColumnEnd(ncol[0][0], sn, en, cellx, cellz); - sampleNoiseColumnEnd(ncol[0][1], sn, en, cellx, cellz+1); - sampleNoiseColumnEnd(ncol[1][0], sn, en, cellx+1, cellz); - sampleNoiseColumnEnd(ncol[1][1], sn, en, cellx+1, cellz+1); + sampleNoiseColumnEnd(ncol[0][0], sn, en, cellx, cellz, y0, y1); + sampleNoiseColumnEnd(ncol[0][1], sn, en, cellx, cellz+1, y0, y1); + sampleNoiseColumnEnd(ncol[1][0], sn, en, cellx+1, cellz, y0, y1); + sampleNoiseColumnEnd(ncol[1][1], sn, en, cellx+1, cellz+1, y0, y1); int h00, h01, h10, h11; h00 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, (blockX & 7) / 8.0, (blockZ & 7) / 8.0); + y0, y1, 4, (blockX & 7) / 8.0, (blockZ & 7) / 8.0); int64_t cs; setSeed(&cs, chunkX + chunkZ * 10387313LL); switch (nextInt(&cs, 4)) { case 0: // (++) 0 - sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2); - sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2); - sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0); - sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1); - sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+2); + sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2, y0, y1); + sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2, y0, y1); + sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0, y0, y1); + sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1, y0, y1); + sampleNoiseColumnEnd(ncol[2][2], sn, en, cellx+2, cellz+2, y0, y1); h01 = getSurfaceHeight(ncol[0][1], ncol[0][2], ncol[1][1], ncol[1][2], - 32, 4, ((blockX ) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); + y0, y1, 4, ((blockX ) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); h10 = getSurfaceHeight(ncol[1][0], ncol[1][1], ncol[2][0], ncol[2][1], - 32, 4, ((blockX + 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); + y0, y1, 4, ((blockX + 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); h11 = getSurfaceHeight(ncol[1][1], ncol[1][2], ncol[2][1], ncol[2][2], - 32, 4, ((blockX + 5) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); + y0, y1, 4, ((blockX + 5) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); break; case 1: // (-+) 90 - sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2); - sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2); + sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2, y0, y1); + sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2, y0, y1); h01 = getSurfaceHeight(ncol[0][1], ncol[0][2], ncol[1][1], ncol[1][2], - 32, 4, ((blockX ) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); + y0, y1, 4, ((blockX ) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); h10 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, ((blockX - 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); + y0, y1, 4, ((blockX - 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); h11 = getSurfaceHeight(ncol[0][1], ncol[0][2], ncol[1][1], ncol[1][2], - 32, 4, ((blockX - 5) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); + y0, y1, 4, ((blockX - 5) & 7) / 8.0, ((blockZ + 5) & 7) / 8.0); break; case 2: // (--) 180 h01 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, ((blockX ) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); + y0, y1, 4, ((blockX ) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); h10 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, ((blockX - 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); + y0, y1, 4, ((blockX - 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); h11 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, ((blockX - 5) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); + y0, y1, 4, ((blockX - 5) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); break; case 3: // (+-) 270 - sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0); - sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1); + sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0, y0, y1); + sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1, y0, y1); h01 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], - 32, 4, ((blockX ) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); + y0, y1, 4, ((blockX ) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); h10 = getSurfaceHeight(ncol[1][0], ncol[1][1], ncol[2][0], ncol[2][1], - 32, 4, ((blockX + 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); + y0, y1, 4, ((blockX + 5) & 7) / 8.0, ((blockZ ) & 7) / 8.0); h11 = getSurfaceHeight(ncol[1][0], ncol[1][1], ncol[2][0], ncol[2][1], - 32, 4, ((blockX + 5) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); + y0, y1, 4, ((blockX + 5) & 7) / 8.0, ((blockZ - 5) & 7) / 8.0); break; default: return 0; // error } - + //printf("%d %d %d %d\n", h00, h01, h10, h11); if (h01 < h00) h00 = h01; if (h10 < h00) h00 = h10; if (h11 < h00) h00 = h11; diff --git a/finders.h b/finders.h index 93a3a1a..a851bae 100644 --- a/finders.h +++ b/finders.h @@ -627,13 +627,19 @@ int isViableStructurePos(int structureType, int mc, LayerStack *g, int64_t seed, int blockX, int blockZ); int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn, int64_t seed, int blockX, int blockZ); -int isViableEndCityPos(int mc, EndNoise *en, SurfaceNoise *sn, +int isViableEndStructurePos(int structureType, int mc, EndNoise *en, int64_t seed, int blockX, int blockZ); /* Checks if the specified structure type could generate in the given biome. */ int isViableFeatureBiome(int mc, int structureType, int biomeID); +/* End Cities require a sufficiently high surface in addition to a biome check. + * The world seed should be applied to the EndNoise and SurfaceNoise before + * calling this function. (Use initSurfaceNoiseEnd() for initialization.) + */ +int isViableEndCityTerrain(const EndNoise *en, const SurfaceNoise *sn, + int blockX, int blockZ); //============================================================================== // Finding Properties of Structures diff --git a/layers.c b/layers.c index 98a6d6d..8176ba9 100644 --- a/layers.c +++ b/layers.c @@ -946,42 +946,43 @@ float getEndHeightNoise(const EndNoise *en, int x, int z) return ret; } -void sampleNoiseColumnEnd(double column[33], const SurfaceNoise *sn, - const EndNoise *en, int x, int z) +void sampleNoiseColumnEnd(double column[], const SurfaceNoise *sn, + const EndNoise *en, int x, int z, int colymin, int colymax) { double depth = getEndHeightNoise(en, x, z) - 8.0f; int y; - for (y = 0; y <= 32; y++) + for (y = colymin; y <= colymax; y++) { double noise = sampleSurfaceNoise(sn, x, y, z); noise += depth; // falloff for the End is just the depth // clamp top and bottom slides from End settings noise = clampedLerp((32 + 46 - y) / 64.0, -3000, noise); noise = clampedLerp((y - 1) / 7.0, -30, noise); - column[y] = noise; + column[y - colymin] = noise; } } /* Given bordering noise columns and a fractional position between those, * determine the surface block height (i.e. where the interpolated noise > 0). - * Note that the noise columns should be of size: ncolxz[ colheight+1 ] + * Note that the noise columns should be of size: ncolxz[ colymax-colymin+1 ] */ int getSurfaceHeight( const double ncol00[], const double ncol01[], - const double ncol10[], const double ncol11[], int colheight, - int blockspercell, double dx, double dz) + const double ncol10[], const double ncol11[], + int colymin, int colymax, int blockspercell, double dx, double dz) { int y, celly; - for (celly = colheight-1; celly >= 0; celly--) + for (celly = colymax-1; celly >= colymin; celly--) { - double v000 = ncol00[celly]; - double v001 = ncol01[celly]; - double v100 = ncol10[celly]; - double v101 = ncol11[celly]; - double v010 = ncol00[celly+1]; - double v011 = ncol01[celly+1]; - double v110 = ncol10[celly+1]; - double v111 = ncol11[celly+1]; + int idx = celly - colymin; + double v000 = ncol00[idx]; + double v001 = ncol01[idx]; + double v100 = ncol10[idx]; + double v101 = ncol11[idx]; + double v010 = ncol00[idx+1]; + double v011 = ncol01[idx+1]; + double v110 = ncol10[idx+1]; + double v111 = ncol11[idx+1]; for (y = blockspercell - 1; y >= 0; y--) { @@ -1013,16 +1014,17 @@ int getSurfaceHeightEnd(int mc, int64_t seed, int x, int z) double dx = (x & 7) / 8.0; double dz = (z & 7) / 8.0; - double ncol00[33]; - double ncol01[33]; - double ncol10[33]; - double ncol11[33]; - sampleNoiseColumnEnd(ncol00, &sn, &en, cellx, cellz); - sampleNoiseColumnEnd(ncol01, &sn, &en, cellx, cellz+1); - sampleNoiseColumnEnd(ncol10, &sn, &en, cellx+1, cellz); - sampleNoiseColumnEnd(ncol11, &sn, &en, cellx+1, cellz+1); + const int y0 = 0, y1 = 32, yn = y1-y0+1; + double ncol00[yn]; + double ncol01[yn]; + double ncol10[yn]; + double ncol11[yn]; + sampleNoiseColumnEnd(ncol00, &sn, &en, cellx, cellz, y0, y1); + sampleNoiseColumnEnd(ncol01, &sn, &en, cellx, cellz+1, y0, y1); + sampleNoiseColumnEnd(ncol10, &sn, &en, cellx+1, cellz, y0, y1); + sampleNoiseColumnEnd(ncol11, &sn, &en, cellx+1, cellz+1, y0, y1); - return getSurfaceHeight(ncol00, ncol01, ncol10, ncol11, 32, 4, dx, dz); + return getSurfaceHeight(ncol00, ncol01, ncol10, ncol11, y0, y1, 4, dx, dz); }