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);
}
/* 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;

View File

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

View File

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