Fixed nether portal variants for 1.17- + support arbitrary end biome scales

This commit is contained in:
Cubitect 2022-09-12 21:12:49 +02:00
parent 8b87d9379a
commit d4afdbf19e
4 changed files with 76 additions and 134 deletions

108
finders.c
View File

@ -1505,8 +1505,8 @@ L_feature:
default:
fprintf(stderr,
"isViableStructurePos: validation for structure type %d not implemented\n",
structureType);
"isViableStructurePos: bad structure type %d or dimension %d\n",
structureType, dim);
goto L_not_viable;
}
@ -1816,67 +1816,51 @@ int getVariant(StructureVariant *r, int structType, int mc, uint64_t seed,
// move into unsupported biomes. Testing for this case requires the
// surface height and is therefore not supported.
{
uint64_t rng0 = rng;
const int b_ruined_portal[] = { plains,
beach, snowy_beach, river, frozen_river, taiga, snowy_taiga,
old_growth_pine_taiga, old_growth_spruce_taiga, forest,
flower_forest, birch_forest, old_growth_birch_forest,
dark_forest, grove, mushroom_fields, ice_spikes,
dripstone_caves, lush_caves, savanna, snowy_plains, plains,
sunflower_plains, -1
}, b_ruined_portal_desert[] = { desert,
desert, -1
}, b_ruined_portal_jungle[] = { jungle,
jungle, bamboo_jungle, sparse_jungle, -1
}, b_ruined_portal_swamp[] = { swamp,
swamp, mangrove_swamp, -1
}, d_ruined_portal_mountain[] = { mountains,
badlands, eroded_badlands, wooded_badlands, windswept_hills,
windswept_forest, windswept_gravelly_hills, savanna_plateau,
windswept_savanna, stony_shore, meadow, frozen_peaks,
jagged_peaks, stony_peaks, snowy_slopes, -1
}, d_ruined_portal_ocean[] = { ocean,
deep_frozen_ocean, deep_cold_ocean, deep_ocean,
deep_lukewarm_ocean, frozen_ocean, ocean, cold_ocean,
lukewarm_ocean, warm_ocean, -1
}, d_ruined_portal_nether[] = { nether_wastes,
nether_wastes, soul_sand_valley, crimson_forest,
warped_forest, basalt_deltas, -1
};
const int *b_vars[] = {
b_ruined_portal,
b_ruined_portal_desert,
b_ruined_portal_jungle,
b_ruined_portal_swamp,
d_ruined_portal_mountain,
d_ruined_portal_ocean,
d_ruined_portal_nether,
};
for (t = 7; t >= 1; t--)
int cat = getCategory(mc, biomeID);
switch (cat)
{
int v = nextInt(&rng, t);
int i, j = 0;
for (i = 0; i < 7; i++)
{
if (b_vars[i])
{
if (j == v)
break;
j++;
}
}
for (j = 1; b_vars[i][j] != -1; j++)
{
if (b_vars[i][j] == biomeID)
{
r->biome = b_vars[i][0];
t = 0; break;
}
}
b_vars[i] = NULL;
case desert:
case jungle:
case swamp:
case ocean:
case nether_wastes:
r->biome = cat;
break;
}
rng = rng0;
if (r->biome == -1)
{
switch (biomeID)
{
case mangrove_swamp:
r->biome = swamp;
break;
case mountains: // windswept_hills
case mountain_edge:
case wooded_mountains: // windswept_forest
case gravelly_mountains: // windswept_gravelly_hills
case modified_gravelly_mountains:
case savanna_plateau:
case shattered_savanna: // windswept_savanna
case shattered_savanna_plateau:
case badlands:
case eroded_badlands:
case wooded_badlands_plateau: // wooded_badlands
case modified_badlands_plateau:
case modified_wooded_badlands_plateau:
case snowy_taiga_mountains:
case taiga_mountains:
case stony_shore:
case meadow:
case frozen_peaks:
case jagged_peaks:
case stony_peaks:
case snowy_slopes:
r->biome = mountains;
break;
}
}
if (r->biome == -1)
r->biome = plains;
if (r->biome == plains || r->biome == mountains)
{
r->underground = nextFloat(&rng) < 0.5f;
@ -3036,7 +3020,7 @@ int checkForBiomes(
int trials = n;
struct touple { int i, x, y, z; } *buf = NULL;
if (r.scale == 4 && r.sx * r.sz > 64)
if (r.scale == 4 && r.sx * r.sz > 64 && dim == DIM_OVERWORLD)
{
// Do a gradient descent to find the min/max of some climate parameters
// and check the biomes along the way. This has a much better chance

View File

@ -318,6 +318,13 @@ int getCategory(int mc, int id)
case giant_spruce_taiga_hills:
return taiga;
case nether_wastes:
case soul_sand_valley:
case crimson_forest:
case warped_forest:
case basalt_deltas:
return nether_wastes;
default:
return none;
}
@ -871,7 +878,11 @@ int mapEnd(const EndNoise *en, int *out, int x, int z, int w, int h)
return 0;
}
float getEndHeightNoise(const EndNoise *en, int x, int z)
/* Samples the End height. The coordinates used here represent eight blocks per
* cell. By default a range of 12 cells is sampled, which can be overriden for
* optimization purposes.
*/
float getEndHeightNoise(const EndNoise *en, int x, int z, int range)
{
int hx = x / 2;
int hz = z / 2;
@ -880,10 +891,12 @@ float getEndHeightNoise(const EndNoise *en, int x, int z)
int i, j;
int64_t h = 64 * (x*(int64_t)x + z*(int64_t)z);
if (range == 0)
range = 12;
for (j = -12; j <= 12; j++)
for (j = -range; j <= range; j++)
{
for (i = -12; i <= 12; i++)
for (i = -range; i <= range; i++)
{
int64_t rx = hx + i;
int64_t rz = hz + j;
@ -911,7 +924,7 @@ float getEndHeightNoise(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;
double depth = getEndHeightNoise(en, x, z, 0) - 8.0f;
int y;
for (y = colymin; y <= colymax; y++)
{
@ -990,9 +1003,6 @@ int getSurfaceHeightEnd(int mc, uint64_t seed, int x, int z)
int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha)
{
if (r.scale != 1 && r.scale != 4 && r.scale != 16 && r.scale != 64)
return 1; // unsupported scale
if (r.sy == 0)
r.sy = 1;
@ -1044,81 +1054,38 @@ int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha)
err = mapEndBiome(en, out, r.x, r.z, r.sx, r.sz);
if (err) return err;
}
else if (r.scale == 64)
else
{
int i, j, di, dj;
int d = 4;
int hw = (2+r.sx) * d + 1;
int hh = (2+r.sz) * d + 1;
int16_t *hmap = (int16_t*) calloc(hw*hh, sizeof(*hmap));
float d = r.scale / 8.0;
int i, j;
for (j = 0; j < r.sz; j++)
{
for (i = 0; i < r.sx; i++)
{
int64_t hx = (i+r.x) * d;
int64_t hz = (j+r.z) * d;
int64_t hx = (int64_t)((i+r.x) * d);
int64_t hz = (int64_t)((j+r.z) * d);
uint64_t rsq = hx*hx + hz*hz;
if (rsq <= 4096L)
if (rsq <= 16384L)
{
out[j*r.sx+i] = the_end;
continue;
}
else if (mc >= MC_1_14 && (int)(4*rsq) < 0)
else if (mc >= MC_1_14 && (int)(rsq) < 0)
{
out[j*r.sx+i] = small_end_islands;
continue;
}
int64_t h = 64*16*16;
for (dj = -d; dj < d; dj++)
{
for (di = -d; di < d; di++)
{
int64_t rx = hx + di;
int64_t rz = hz + dj;
int hi = i*d + di+d;
int hj = j*d + dj+d;
int16_t *p = &hmap[hj*hw + hi];
if (*p == 0)
{
if (sampleSimplex2D(&en->perlin, rx, rz) < -0.9f)
{
*p = (llabs(rx) * 3439 + llabs(rz) * 147) % 13 + 9;
*p *= *p;
}
else
{
*p = -1;
}
}
if (*p > 0)
{
int64_t noise = 4*(di*di + dj*dj) * (*p);
if (noise < h)
h = noise;
}
}
}
if (h < 3600)
float h = getEndHeightNoise(en, hx, hz, 4);
if (h > 40)
out[j*r.sx+i] = end_highlands;
else if (h <= 10000)
else if (h >= 0)
out[j*r.sx+i] = end_midlands;
else if (h <= 14400)
else if (h >= -20)
out[j*r.sx+i] = end_barrens;
else
out[j*r.sx+i] = small_end_islands;
}
}
free(hmap);
}
else
{ // A scale higher than 1:64 is discouraged and not well defined.
// TODO...
return 1;
}
// expanding 2D into 3D

View File

@ -358,7 +358,7 @@ enum
NP_WEIRDNESS = 5,
NP_MAX
};
/// Overworld and Nether biome generator for 1.18
// Overworld biome generator for 1.18+
STRUCT(BiomeNoise)
{
DoublePerlinNoise climate[NP_MAX];
@ -488,7 +488,7 @@ void genBiomeNoiseChunkSection(const BiomeNoise *bn, int out[4][4][4],
int cx, int cy, int cz, uint64_t *dat);
/**
* The scaled biome noise generation applies for the Overworld version 1.18.
* The scaled biome noise generation applies for the Overworld version 1.18+.
* The 'sha' hash of the seed is only required for voronoi at scale 1:1.
* A scale of zero is interpreted as the default 1:4 scale.
*/

View File

@ -407,17 +407,8 @@ void testCanBiomesGenerate()
canGenerateTest(MC_1_17, L_OCEAN_TEMP_256);
}
int main()
{
uint64_t seed = 4;
int cx = -208 >> 4;
int cz = -400 >> 4;
Piece list[1000];
int n = getFortressPieces(list, 1000, MC_1_17, seed, cx, cz);
printf("n=%d\n", n);
//testCanBiomesGenerate();
//testGeneration();
//findBiomeParaBounds();