From 61a341e1f695ec10d1ec836618275e871c69df4e Mon Sep 17 00:00:00 2001 From: Cubitect Date: Sun, 18 Jul 2021 11:48:54 +0200 Subject: [PATCH] fixes for large biomes + more efficient mineshaft finder --- finders.c | 69 +++++++++++++++++++++++++++++++++++++++-------------- finders.h | 15 +++++++----- generator.c | 36 ++++++++++++++++++---------- generator.h | 8 ++++--- layers.c | 2 +- 5 files changed, 89 insertions(+), 41 deletions(-) diff --git a/finders.c b/finders.c index 643e2ec..dcf32b5 100644 --- a/finders.c +++ b/finders.c @@ -223,9 +223,7 @@ int getStructurePos(int structureType, int mc, uint64_t seed, int regX, int regZ return nextFloat(&seed) < 0.01; case Mineshaft: - pos->x = (int)( ((uint32_t)regX << 4) ); - pos->z = (int)( ((uint32_t)regZ << 4) ); - return isMineshaftChunk(mc, seed, regX, regZ); + return getMineshafts(mc, seed, regX, regZ, regX, regZ, pos, 1); case Fortress: if (mc < MC_1_16) { @@ -262,29 +260,64 @@ int getStructurePos(int structureType, int mc, uint64_t seed, int regX, int regZ } -int isMineshaftChunk(int mc, uint64_t seed, int chunkX, int chunkZ) +int getMineshafts(int mc, uint64_t seed, int cx0, int cz0, int cx1, int cz1, + Pos *out, int nout) { uint64_t s; setSeed(&s, seed); - uint64_t i = nextLong(&s); - uint64_t j = nextLong(&s); - setSeed(&s, chunkX * i ^ chunkZ * j ^ seed); - if (mc >= MC_1_13) + uint64_t a = nextLong(&s); + uint64_t b = nextLong(&s); + int i, j; + int n = 0; + + for (i = cx0; i <= cx1; i++) { - return nextDouble(&s) < 0.004; - } - else - { - int d = chunkX; - if (-chunkX > d) d = -chunkX; - if (+chunkZ > d) d = +chunkZ; - if (-chunkZ > d) d = -chunkZ; - skipNextN(&s, 1); - return nextDouble(&s) < 0.004 && nextInt(&s, 80) < d; + uint64_t aix = i * a ^ seed; + + for (j = cz0; j <= cz1; j++) + { + setSeed(&s, aix ^ j * b); + + if (mc >= MC_1_13) + { + if U(nextDouble(&s) < 0.004) + { + if (out && n < nout) + { + out[n].x = (int)((uint32_t)i << 4); + out[n].z = (int)((uint32_t)j << 4); + } + n++; + } + } + else + { + skipNextN(&s, 1); + if U(nextDouble(&s) < 0.004) + { + int d = i; + if (-i > d) d = -i; + if (+j > d) d = +j; + if (-j > d) d = -j; + if (d >= 80 || nextInt(&s, 80) < d) + { + if (out && n < nout) + { + out[n].x = (int)((uint32_t)i << 4); + out[n].z = (int)((uint32_t)j << 4); + } + n++; + } + } + } + } } + + return n; } + //============================================================================== // Multi-Structure Checks //============================================================================== diff --git a/finders.h b/finders.h index 71aaff9..cbd5887 100644 --- a/finders.h +++ b/finders.h @@ -52,6 +52,7 @@ enum StructureType Bastion, End_City, End_Gateway, + FEATURE_NUM }; enum // village house types prior to 1.14 @@ -323,11 +324,13 @@ Pos getLargeStructurePos(StructureConfig config, uint64_t seed, int regX, int re static inline __attribute__((const)) Pos getLargeStructureChunkInRegion(StructureConfig config, uint64_t seed, int regX, int regZ); -/* Some structures check each chunk individually for viability. - * The placement and biome check within a valid chunk is at block position (9,9) - * or at (2,2) with layer scale=4 from 1.16 onwards. +/* Checks a chunk area, starting at (chunkX, chunkZ) with size (chunkW, chunkH) + * for Mineshaft positions. If not NULL, positions are written to the buffer + * 'out' up to a maximum number of 'nout'. The return value is the number of + * chunks with Mineshafts in the area. */ -int isMineshaftChunk(int mc, uint64_t seed, int chunkX, int chunkZ); +int getMineshafts(int mc, uint64_t seed, int chunkX, int chunkZ, + int chunkW, int chunkH, Pos *out, int nout); // not exacly a structure static inline __attribute__((const)) @@ -668,8 +671,8 @@ int isViableEndCityTerrain(const EndNoise *en, const SurfaceNoise *sn, * This random object is used for recursiveGenerate() which is responsible for * generating caves, ravines, mineshafts, and virtually all other structures. */ -inline static int64_t chunkGenerateRnd(const uint64_t worldSeed, - const int chunkX, const int chunkZ) +inline static +uint64_t chunkGenerateRnd(uint64_t worldSeed, int chunkX, int chunkZ) { uint64_t rnd; setSeed(&rnd, worldSeed); diff --git a/generator.c b/generator.c index c56b32e..1a1d2d4 100644 --- a/generator.c +++ b/generator.c @@ -37,7 +37,7 @@ static void setupScale(Layer *l, int scale) setupScale(l->p2, scale * l->zoom); } -static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) +void setupGeneratorLargeBiomes(LayerStack *g, int mc, int largeBiomes) { memset(g, 0, sizeof(LayerStack)); Layer *p; @@ -144,8 +144,8 @@ static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) if (largeBiomes) { - p = setupLayer(g, L_ZOOM_LARGE_BIOME_A, mapZoom, mc, 2, 3, 1004, p, 0); - p = setupLayer(g, L_ZOOM_LARGE_BIOME_B, mapZoom, mc, 2, 3, 1005, p, 0); + p = setupLayer(g, L_ZOOM_LARGE_A, mapZoom, mc, 2, 3, 1004, p, 0); + p = setupLayer(g, L_ZOOM_LARGE_B, mapZoom, mc, 2, 3, 1005, p, 0); } p = setupLayer(g, L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0); @@ -158,6 +158,13 @@ static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) p = setupLayer(g, L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1001, p, 0); p = setupLayer(g, L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1002, p, 0); p = setupLayer(g, L_ZOOM_4_RIVER, mapZoom, mc, 2, 3, 1003, p, 0); + + if (largeBiomes) + { + p = setupLayer(g, L_ZOOM_L_RIVER_A, mapZoom, mc, 2, 3, 1004, p, 0); + p = setupLayer(g, L_ZOOM_L_RIVER_B, mapZoom, mc, 2, 3, 1005, p, 0); + } + p = setupLayer(g, L_RIVER_4, mapRiver, mc, 1, 2, 1, p, 0); p = setupLayer(g, L_SMOOTH_4_RIVER, mapSmooth, mc, 1, 2, 1000, p, 0); } @@ -192,23 +199,26 @@ static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) g->entry_1 = p; g->entry_4 = g->layers + (mc <= MC_1_12 ? L_RIVER_MIX_4 : L_OCEAN_MIX_4); - g->entry_16 = g->layers + (mc <= MC_1_6 ? L_SWAMP_RIVER_16 : L_SHORE_16); - g->entry_64 = g->layers + (mc <= MC_1_7 ? L_HILLS_64 : L_SUNFLOWER_64); - g->entry_256 = g->layers + (mc <= MC_1_14 ? L_BIOME_256 : L_BAMBOO_256); + if (largeBiomes) + { + g->entry_16 = g->layers + L_ZOOM_4; + g->entry_64 = g->layers + (mc <= MC_1_6 ? L_SWAMP_RIVER_16 : L_SHORE_16); + g->entry_256 = g->layers + (mc <= MC_1_7 ? L_HILLS_64 : L_SUNFLOWER_64); + } + else + { + g->entry_16 = g->layers + (mc <= MC_1_6 ? L_SWAMP_RIVER_16 : L_SHORE_16); + g->entry_64 = g->layers + (mc <= MC_1_7 ? L_HILLS_64 : L_SUNFLOWER_64); + g->entry_256 = g->layers + (mc <= MC_1_14 ? L_BIOME_256 : L_BAMBOO_256); + } setupScale(g->entry_1, 1); } void setupGenerator(LayerStack *g, int mc) { - setupGeneratorImpl(g, mc, 0); + setupGeneratorLargeBiomes(g, mc, 0); } -void setupLargeBiomesGenerator(LayerStack *g, int mc) -{ - setupGeneratorImpl(g, mc, 1); -} - - /* Recursively calculates the minimum buffer size required to generate an area * of the specified size from the current layer onwards. */ diff --git a/generator.h b/generator.h index 22538dc..e4a96be 100644 --- a/generator.h +++ b/generator.h @@ -66,8 +66,10 @@ enum L_VORONOI_1, L_VORONOI_ZOOM_1 = L_VORONOI_1, // largeBiomes layers - L_ZOOM_LARGE_BIOME_A, - L_ZOOM_LARGE_BIOME_B, + L_ZOOM_LARGE_A, + L_ZOOM_LARGE_B, + L_ZOOM_L_RIVER_A, + L_ZOOM_L_RIVER_B, L_NUM }; @@ -95,7 +97,7 @@ extern "C" void setupGenerator(LayerStack *g, int mc); /* Initialise an instance of a generator with largeBiomes configuration. */ -void setupLargeBiomesGenerator(LayerStack *g, int mc); +void setupGeneratorLargeBiomes(LayerStack *g, int mc, int largeBiomes); /* Calculates the minimum size of the buffers required to generate an area of diff --git a/layers.c b/layers.c index 134c5ec..2e9aede 100644 --- a/layers.c +++ b/layers.c @@ -2712,7 +2712,7 @@ int mapOceanMix(const Layer * l, int * out, int x, int z, int w, int h) return 0; } -static inline void getVoronoiCell(int64_t sha, int a, int b, int c, +static inline void getVoronoiCell(uint64_t sha, int a, int b, int c, int *x, int *y, int *z) { uint64_t s = sha;