diff --git a/finders.c b/finders.c index d545570..9c016ea 100644 --- a/finders.c +++ b/finders.c @@ -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 diff --git a/layers.c b/layers.c index 43210e2..4494683 100644 --- a/layers.c +++ b/layers.c @@ -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 diff --git a/layers.h b/layers.h index aea12e7..5b2fb07 100644 --- a/layers.h +++ b/layers.h @@ -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. */ diff --git a/tests.c b/tests.c index 501d18b..0f9c26e 100644 --- a/tests.c +++ b/tests.c @@ -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();