From c7b2675f5e5bbd331409356483a636afe620416b Mon Sep 17 00:00:00 2001 From: NelS <75831544+Nel-S@users.noreply.github.com> Date: Wed, 11 Dec 2024 00:12:54 -0800 Subject: [PATCH] b1.8-1.8.9 spawnpoint bug + preprocessr define guards, and other fixes - Beta 1.8 - 1.8.9 spawn first-stage fallback is (0,0), not (8,8) - Added #ifdef/#undef guards in case any #define'd keywords were already previously defined (an error occurs otherwise) - change stronghold chunk offset to (0,0) to match /locate coordinate - change 1.18+ second-stage spawn estimate chunk offset to (0,0) to match most likely coordinate pick - update Readme spawn description for 1.18+, plus add basic Windows instructions and makefile debugging information --- README.md | 24 +++++++++++++----------- biomenoise.c | 6 ++++++ finders.c | 23 ++++++++++++++++------- finders.h | 3 +++ layers.h | 3 +++ quadbase.c | 16 ++++++++++++++++ rng.h | 30 ++++++++++++++++++++++++++++++ 7 files changed, 87 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index adcb1af..587c490 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # cubiomes -Cubiomes is a standalone library, written in C, that mimics the biome and feature generation of Minecraft Java Edition. +Cubiomes is a standalone library, written in C, that mimics the biome and feature generation of Minecraft: Java Edition. It is intended as a powerful tool to devise very fast, custom seed-finding applications and large-scale map viewers with minimal memory usage. #### Cubiomes-Viewer -If you want to get started without coding, there is now also a [graphical application](https://github.com/Cubitect/cubiomes-viewer) based on this library. +If you want to get started without coding, there is also a [graphical application](https://github.com/Cubitect/cubiomes-viewer) based on this library. #### Audience @@ -58,21 +58,23 @@ int main() } ``` -You can compile this code either by directly adding a target to the makefile via +You can compile this code by creating an archive of the library (libcubiomes.a) using the provided makefile: ``` $ cd cubiomes -$ make +$ make # on Linux, or mingw32-make.exe if using MSYS2 on Windows ``` -...or you can compile and link to a cubiomes archive using either of the following commands. +Then you can compile your program, while linking the archive, using either of the following commands. ``` -$ gcc find_biome_at.c libcubiomes.a -fwrapv -lm # static -$ gcc find_biome_at.c -L. -lcubiomes -fwrapv -lm # dynamic +$ gcc find_biome_at.c libcubiomes.a -fwrapv -lm # static; or gcc.exe [...] on Windows +$ gcc find_biome_at.c -L. -lcubiomes -fwrapv -lm # dynamic; or gcc.exe [...] on Windows ``` -Both commands assume that your source code is saved as `find_biome_at.c` in the cubiomes working directory. If your makefile is configured to use pthreads, you may also need to add the `-lpthread` option for the compiler. +Both commands assume that your source code is saved as `find_biome_at.c` in the Cubiomes working directory. If your makefile is configured to use pthreads, you may also need to add the `-lpthread` option for the compiler. The option `-fwrapv` enforces two's complement for signed integer overflow, which is otherwise undefined behavior. It is not really necessary for this example, but it is a common pitfall when dealing with code that emulates the behavior of Java. -Running the program should output: +If the archive fails to generate, or the compilation claims the library's functions are undefined or missing, run `make clean`/`mingw32-make.exe clean` to delete the failed archive, then retry the process. + +Running the final program should output: ``` -$ ./a.out +$ ./a.out # or ./a.exe on Windows Seed 262 has a Mushroom Fields biome at block position (0, 0). ``` @@ -264,7 +266,7 @@ int main() #### Strongholds and Spawn -Strongholds, as well as the world spawn point, actually search until they find a suitable location, rather than checking a single spot like most other structures. This causes them to be particularly performance expensive to find. Furthermore, the positions of strongholds have to be generated in a certain order, which can be done in iteratively with `initFirstStronghold()` and `nextStronghold()`. For the world spawn, the generation starts with a search for a suitable biome near the origin and will continue until a grass or podzol block is found. There is no reliable way to check actual blocks, so the search relies on a statistic, matching grass presence to biomes. Alternatively, we can simply use `estimateSpawn()` and terminate the search after the first biome check under the assumption that grass is nearby. +Strongholds, as well as worlds' spawnpoints, actually search until they find a suitable location, rather than checking a single spot like most other structures. This causes them to be particularly slow to find. Furthermore, the positions of strongholds have to be generated in a certain order, which can be done in iteratively with `initFirstStronghold()` and `nextStronghold()`. For the world spawn, the exact coordinate is found after a search for a grass or podzol block prior to 1.18, or for any topsolid nonwaterlogged block in 1.18+; this library cannot model individual blocks, so the search relies on heuristics such as biomes and climate-dependent world heights. Alternatively, we can simply use `estimateSpawn()` and terminate the search after the first biome/climate check under the assumption that grass/a topsolid nonwaterlogged block is nearby. ```C diff --git a/biomenoise.c b/biomenoise.c index 9002732..d6673c5 100644 --- a/biomenoise.c +++ b/biomenoise.c @@ -403,6 +403,12 @@ static int getEndBiome(int hx, int hz, const uint16_t *hmap, int hw) uint32_t u; // force unroll for(i=0;i<25;i++) in a cross compatible way + #ifdef x5 + #undef x5 + #endif + #ifdef for25 + #undef for25 + #endif #define x5(i,x) { x; i++; x; i++; x; i++; x; i++; x; i++; } #define for25(i,x) { i = 0; x5(i,x) x5(i,x) x5(i,x) x5(i,x) x5(i,x) } for25(i, diff --git a/finders.c b/finders.c index 783d5ec..74f3e87 100644 --- a/finders.c +++ b/finders.c @@ -9,6 +9,9 @@ #include +#ifdef PI + #undef PI +#endif #define PI 3.14159265358979323846 @@ -901,9 +904,9 @@ int nextStronghold(StrongholdIter *sh, const Generator *g) { return 0; } - // staircase is located at (4, 4) in chunk - sh->pos.x = (sh->pos.x & ~15) + 4; - sh->pos.z = (sh->pos.z & ~15) + 4; + // staircase is located at corner of chunk + sh->pos.x = (sh->pos.x & ~15); + sh->pos.z = (sh->pos.z & ~15); sh->ringidx++; sh->angle += 2 * PI / sh->ringmax; @@ -1009,9 +1012,9 @@ Pos findFittestPos(const Generator *g) uint64_t fitness = calcFitness(g, 0, 0); findFittest(g, &spawn, &fitness, 2048.0, 512.0); findFittest(g, &spawn, &fitness, 512.0, 32.0); - // center of chunk - spawn.x = (spawn.x & ~15) + 8; - spawn.z = (spawn.z & ~15) + 8; + // corner of chunk + spawn.x = (spawn.x & ~15); + spawn.z = (spawn.z & ~15); return spawn; } @@ -1045,7 +1048,7 @@ Pos estimateSpawn(const Generator *g, uint64_t *rng) setSeed(&s, g->seed); spawn = locateBiome(g, 0, 63, 0, 256, spawn_biomes, 0, &s, &found); if (!found) - spawn.x = spawn.z = 8; + spawn.x = spawn.z = 8*(g->mc >= MC_1_9); if (rng) *rng = s; } @@ -5391,6 +5394,12 @@ int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax, return err; } +#ifdef IMIN + #undef IMIN +#endif +#ifdef IMAX + #undef IMAX +#endif #define IMIN INT_MIN #define IMAX INT_MAX static const int g_biome_para_range_18[][13] = { diff --git a/finders.h b/finders.h index 74eee98..fe16d8a 100644 --- a/finders.h +++ b/finders.h @@ -10,6 +10,9 @@ extern "C" { #endif +#ifdef MASK48 + #undef MASK48 +#endif #define MASK48 (((int64_t)1 << 48) - 1) enum StructureType diff --git a/layers.h b/layers.h index a20cafe..f3682fc 100644 --- a/layers.h +++ b/layers.h @@ -5,6 +5,9 @@ #include "biomes.h" +#ifdef LAYER_INIT_SHA + #undef LAYER_INIT_SHA +#endif #define LAYER_INIT_SHA (~0ULL) diff --git a/quadbase.c b/quadbase.c index bd4696b..f1ba10f 100644 --- a/quadbase.c +++ b/quadbase.c @@ -8,11 +8,24 @@ #include +#ifdef IS_DIR_SEP + #undef IS_DIR_SEP +#endif + #if defined(_WIN32) #include typedef HANDLE thread_id_t; #include +#ifdef stat + #undef stat +#endif +#ifdef mkdir + #undef mkdir +#endif +#ifdef S_IFDIR + #undef S_IFDIR +#endif #define IS_DIR_SEP(C) ((C) == '/' || (C) == '\\') #define stat _stat #define mkdir(P,X) _mkdir(P) @@ -223,6 +236,9 @@ Pos getOptimalAfk(Pos p[4], int ax, int ay, int az, int *spcnt) } +#ifdef MAX_PATHLEN + #undef MAX_PATHLEN +#endif #define MAX_PATHLEN 4096 STRUCT(linked_seeds_t) diff --git a/rng.h b/rng.h index 62881f2..03d673c 100644 --- a/rng.h +++ b/rng.h @@ -1,6 +1,9 @@ #ifndef RNG_H_ #define RNG_H_ +#ifdef __STDC_FORMAT_MACROS + #undef __STDC_FORMAT_MACROS +#endif #define __STDC_FORMAT_MACROS 1 #include @@ -24,8 +27,32 @@ typedef float f32; typedef double f64; +#ifdef STRUCT + #undef STRUCT +#endif #define STRUCT(S) typedef struct S S; struct S +#ifdef IABS + #undef IABS +#endif +#ifdef PREFETCH + #undef PREFETCH +#endif +#ifdef likely + #undef likely +#endif +#ifdef unlikely + #undef unlikely +#endif +#ifdef ATTR + #undef ATTR +#endif +#ifdef BSWAP32 + #undef BSWAP32 +#endif +#ifdef UNREACHABLE + #undef UNREACHABLE +#endif #if __GNUC__ #define IABS(X) __builtin_abs(X) @@ -134,6 +161,9 @@ static inline double nextDouble(uint64_t *seed) * This is a macro and not an inline function, as many compilers can make use * of the additional optimisation passes for the surrounding code. */ +#ifdef JAVA_NEXT_INT24 + #undef JAVA_NEXT_INT24 +#endif #define JAVA_NEXT_INT24(S,X) \ do { \ uint64_t a = (1ULL << 48) - 1; \