Split end city validity and terrain checks

This commit is contained in:
Cubitect 2021-06-04 00:10:43 +02:00
parent 4195eab986
commit 3a6a923553
3 changed files with 85 additions and 75 deletions

100
finders.c
View File

@ -1795,23 +1795,10 @@ int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn,
return isViableFeatureBiome(mc, structureType, biomeID); return isViableFeatureBiome(mc, structureType, biomeID);
} }
int isViableEndStructurePos(int structureType, int mc, EndNoise *en,
/* 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,
int64_t seed, int blockX, int blockZ) int64_t seed, int blockX, int blockZ)
{ {
if (mc < MC_1_9) if (structureType != End_City || mc < MC_1_9)
return 0; return 0;
setEndSeed(en, seed); 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) // end biomes vary only on a per-chunk scale (1:16)
// voronoi shouldn't matter as the check will be near the chunk center // voronoi shouldn't matter as the check will be near the chunk center
int id; int id;
int chunkX = blockX >> 4, chunkZ = blockZ >> 4; int chunkX = blockX >> 4;
int chunkZ = blockZ >> 4;
mapEndBiome(en, &id, chunkX, chunkZ, 1, 1); mapEndBiome(en, &id, chunkX, chunkZ, 1, 1);
if (!isViableFeatureBiome(mc, End_City, id)) return isViableFeatureBiome(mc, End_City, id) ? id : 0;
return 0; }
if (!sn) /* Given bordering noise columns and a fractional position between those,
return 1; * 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; blockX = (chunkX << 4) + 7;
blockZ = (chunkZ << 4) + 7; blockZ = (chunkZ << 4) + 7;
int cellx = (blockX >> 3); int cellx = (blockX >> 3);
int cellz = (blockZ >> 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][0], sn, en, cellx, cellz, y0, y1);
sampleNoiseColumnEnd(ncol[0][1], sn, en, cellx, cellz+1); sampleNoiseColumnEnd(ncol[0][1], sn, en, cellx, cellz+1, y0, y1);
sampleNoiseColumnEnd(ncol[1][0], sn, en, cellx+1, cellz); sampleNoiseColumnEnd(ncol[1][0], sn, en, cellx+1, cellz, y0, y1);
sampleNoiseColumnEnd(ncol[1][1], sn, en, cellx+1, cellz+1); sampleNoiseColumnEnd(ncol[1][1], sn, en, cellx+1, cellz+1, y0, y1);
int h00, h01, h10, h11; int h00, h01, h10, h11;
h00 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], 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; int64_t cs;
setSeed(&cs, chunkX + chunkZ * 10387313LL); setSeed(&cs, chunkX + chunkZ * 10387313LL);
switch (nextInt(&cs, 4)) switch (nextInt(&cs, 4))
{ {
case 0: // (++) 0 case 0: // (++) 0
sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2); sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2, y0, y1);
sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2); sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2, y0, y1);
sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0); sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0, y0, y1);
sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1); sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1, y0, y1);
sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+2); 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], 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], 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], 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; break;
case 1: // (-+) 90 case 1: // (-+) 90
sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2); sampleNoiseColumnEnd(ncol[0][2], sn, en, cellx+0, cellz+2, y0, y1);
sampleNoiseColumnEnd(ncol[1][2], sn, en, cellx+1, cellz+2); 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], 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], 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], 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; break;
case 2: // (--) 180 case 2: // (--) 180
h01 = getSurfaceHeight(ncol[0][0], ncol[0][1], ncol[1][0], ncol[1][1], 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], 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], 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; break;
case 3: // (+-) 270 case 3: // (+-) 270
sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0); sampleNoiseColumnEnd(ncol[2][0], sn, en, cellx+2, cellz+0, y0, y1);
sampleNoiseColumnEnd(ncol[2][1], sn, en, cellx+2, cellz+1); 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], 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], 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], 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; break;
default: default:
return 0; // error return 0; // error
} }
//printf("%d %d %d %d\n", h00, h01, h10, h11);
if (h01 < h00) h00 = h01; if (h01 < h00) h00 = h01;
if (h10 < h00) h00 = h10; if (h10 < h00) h00 = h10;
if (h11 < h00) h00 = h11; if (h11 < h00) h00 = h11;

View File

@ -627,13 +627,19 @@ int isViableStructurePos(int structureType, int mc, LayerStack *g,
int64_t seed, int blockX, int blockZ); int64_t seed, int blockX, int blockZ);
int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn, int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn,
int64_t seed, int blockX, int blockZ); 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); int64_t seed, int blockX, int blockZ);
/* Checks if the specified structure type could generate in the given biome. /* Checks if the specified structure type could generate in the given biome.
*/ */
int isViableFeatureBiome(int mc, int structureType, int biomeID); 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 // Finding Properties of Structures

View File

@ -946,42 +946,43 @@ float getEndHeightNoise(const EndNoise *en, int x, int z)
return ret; return ret;
} }
void sampleNoiseColumnEnd(double column[33], const SurfaceNoise *sn, void sampleNoiseColumnEnd(double column[], const SurfaceNoise *sn,
const EndNoise *en, int x, int z) const EndNoise *en, int x, int z, int colymin, int colymax)
{ {
double depth = getEndHeightNoise(en, x, z) - 8.0f; double depth = getEndHeightNoise(en, x, z) - 8.0f;
int y; int y;
for (y = 0; y <= 32; y++) for (y = colymin; y <= colymax; y++)
{ {
double noise = sampleSurfaceNoise(sn, x, y, z); double noise = sampleSurfaceNoise(sn, x, y, z);
noise += depth; // falloff for the End is just the depth noise += depth; // falloff for the End is just the depth
// clamp top and bottom slides from End settings // clamp top and bottom slides from End settings
noise = clampedLerp((32 + 46 - y) / 64.0, -3000, noise); noise = clampedLerp((32 + 46 - y) / 64.0, -3000, noise);
noise = clampedLerp((y - 1) / 7.0, -30, 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, /* Given bordering noise columns and a fractional position between those,
* determine the surface block height (i.e. where the interpolated noise > 0). * 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( int getSurfaceHeight(
const double ncol00[], const double ncol01[], const double ncol00[], const double ncol01[],
const double ncol10[], const double ncol11[], int colheight, const double ncol10[], const double ncol11[],
int blockspercell, double dx, double dz) int colymin, int colymax, int blockspercell, double dx, double dz)
{ {
int y, celly; int y, celly;
for (celly = colheight-1; celly >= 0; celly--) for (celly = colymax-1; celly >= colymin; celly--)
{ {
double v000 = ncol00[celly]; int idx = celly - colymin;
double v001 = ncol01[celly]; double v000 = ncol00[idx];
double v100 = ncol10[celly]; double v001 = ncol01[idx];
double v101 = ncol11[celly]; double v100 = ncol10[idx];
double v010 = ncol00[celly+1]; double v101 = ncol11[idx];
double v011 = ncol01[celly+1]; double v010 = ncol00[idx+1];
double v110 = ncol10[celly+1]; double v011 = ncol01[idx+1];
double v111 = ncol11[celly+1]; double v110 = ncol10[idx+1];
double v111 = ncol11[idx+1];
for (y = blockspercell - 1; y >= 0; y--) 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 dx = (x & 7) / 8.0;
double dz = (z & 7) / 8.0; double dz = (z & 7) / 8.0;
double ncol00[33]; const int y0 = 0, y1 = 32, yn = y1-y0+1;
double ncol01[33]; double ncol00[yn];
double ncol10[33]; double ncol01[yn];
double ncol11[33]; double ncol10[yn];
sampleNoiseColumnEnd(ncol00, &sn, &en, cellx, cellz); double ncol11[yn];
sampleNoiseColumnEnd(ncol01, &sn, &en, cellx, cellz+1); sampleNoiseColumnEnd(ncol00, &sn, &en, cellx, cellz, y0, y1);
sampleNoiseColumnEnd(ncol10, &sn, &en, cellx+1, cellz); sampleNoiseColumnEnd(ncol01, &sn, &en, cellx, cellz+1, y0, y1);
sampleNoiseColumnEnd(ncol11, &sn, &en, cellx+1, cellz+1); 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);
} }