Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes (Beta 1.8-1.8.9 spawnpoint bug, preprocesser #define guards, etc.) #133

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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).
```

Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions biomenoise.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 16 additions & 7 deletions finders.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <math.h>


#ifdef PI
#undef PI
#endif
#define PI 3.14159265358979323846


Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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] = {
Expand Down
3 changes: 3 additions & 0 deletions finders.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ extern "C"
{
#endif

#ifdef MASK48
#undef MASK48
#endif
#define MASK48 (((int64_t)1 << 48) - 1)

enum StructureType
Expand Down
3 changes: 3 additions & 0 deletions layers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "biomes.h"


#ifdef LAYER_INIT_SHA
#undef LAYER_INIT_SHA
#endif
#define LAYER_INIT_SHA (~0ULL)


Expand Down
16 changes: 16 additions & 0 deletions quadbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,24 @@
#include <sys/stat.h>


#ifdef IS_DIR_SEP
#undef IS_DIR_SEP
#endif

#if defined(_WIN32)

#include <windows.h>
typedef HANDLE thread_id_t;
#include <direct.h>
#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)
Expand Down Expand Up @@ -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)
Expand Down
30 changes: 30 additions & 0 deletions rng.h
Original file line number Diff line number Diff line change
@@ -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 <stdlib.h>
Expand All @@ -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)
Expand Down Expand Up @@ -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; \
Expand Down