From 8cd0f24cf14a59c9d306d394ad4b8f534444d9f9 Mon Sep 17 00:00:00 2001 From: Cubitect Date: Tue, 20 Apr 2021 23:13:53 +0200 Subject: [PATCH] Layer ranaming and further integration of 1.6 version support 1) renamed layer enums and functions to somewhat resemble the current mappings 2) replaced biome tables with a canBiomeGenerate() function 3) fixed stronghold biome list --- README.md | 22 +-- finders.c | 424 ++++++++++++++++++++++++++++++---------------------- finders.h | 60 +++----- generator.c | 198 ++++++++++++------------ generator.h | 185 +++++------------------ layers.c | 162 ++++++++++++-------- layers.h | 63 ++++---- tests.c | 9 +- 8 files changed, 542 insertions(+), 581 deletions(-) diff --git a/README.md b/README.md index 72fa751..d2d8178 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,6 @@ Let's create a simple program called `find_jedge.c` which tests seeds for a Jung int main() { - // First initialize the global biome table. This sets up properties such as - // the category and temperature of each biome. - initBiomes(); - // Initialize a stack of biome layers that reflects the biome generation of // Minecraft 1.16 LayerStack g; @@ -67,10 +63,12 @@ $ make libcubiomes ``` To compile, and link the cubiomes library you can use one of ``` -$ gcc find_jedge.c libcubiomes.a -lm # static -$ gcc find_jedge.c -L. -lcubiomes -lm # dynamic +$ gcc find_jedge.c libcubiomes.a -fwrapv -lm # static +$ gcc find_jedge.c -L. -lcubiomes -fwrapv -lm # dynamic ``` -Both options assume that your source code is saved as `find_jedge.c` in the cubiomes working directory. If your makefile is configured to use pthreads you also may need to add the `-lpthread` option to the compiler. Running the program should output: +Both commands assume that your source code is saved as `find_jedge.c` in the cubiomes working directory. If your makefile is configured to use pthreads you also may need to add the `-lpthread` option to the compiler. +The option `-fwrapv` enforces two's complement for signed integer overflow, which this library relies on. It is not strictly necessary for this example as the library should already be compiled with this flag, but it is good practice to prevent undefined behaviour. +Running the program should output: ``` $ ./a.out Seed 615 has a Junge Edge biome at block position (0, 0). @@ -87,8 +85,6 @@ int main() { unsigned char biomeColours[256][3]; - // Initialize global biome table. - initBiomes(); // Initialize a colour map for biomes. initBiomeColours(biomeColours); @@ -141,8 +137,6 @@ Biome filters provide a way of generating an area, but only if that area contain int main() { - initBiomes(); - int mc = MC_1_16; LayerStack g; BiomeFilter filter; @@ -187,8 +181,6 @@ The generation of structures can usually be regarded as a two stage process: gen int main() { - initBiomes(); - int structType = Outpost; int mc = MC_1_16; @@ -244,8 +236,6 @@ int check(int64_t s48, void *data) int main() { - initBiomes(); - int styp = Swamp_Hut; int mc = MC_1_16; int64_t basecnt = 0; @@ -321,8 +311,6 @@ Strongholds as well as the world spawn point actually search until they find a s int main() { - initBiomes(); - int mc = MC_1_16; int64_t seed = 3055141959546LL; diff --git a/finders.c b/finders.c index d94f64d..014aed9 100644 --- a/finders.c +++ b/finders.c @@ -803,10 +803,10 @@ int scanForQuads( int getBiomeAtPos(const LayerStack *g, const Pos pos) { - int *map = allocCache(g->entry_1, 1, 1); - genArea(g->entry_1, map, pos.x, pos.z, 1, 1); - int biomeID = map[0]; - free(map); + int *ids = allocCache(g->entry_1, 1, 1); + genArea(g->entry_1, ids, pos.x, pos.z, 1, 1); + int biomeID = ids[0]; + free(ids); return biomeID; } @@ -828,7 +828,7 @@ Pos findBiomePosition( int z2 = (centerZ+range) >> 2; int width = x2 - x1 + 1; int height = z2 - z1 + 1; - int *map; + int *ids; int i, j, found; Pos out; @@ -839,9 +839,9 @@ Pos findBiomePosition( l->scale); } - map = cache ? cache : allocCache(l, width, height); + ids = cache ? cache : allocCache(l, width, height); - genArea(l, map, x1, z1, width, height); + genArea(l, ids, x1, z1, width, height); out.x = centerX; out.z = centerZ; @@ -851,7 +851,7 @@ Pos findBiomePosition( { for (i = 0, j = 2; i < width*height; i++) { - if (!isValid[map[i]]) continue; + if (!isValid[ids[i]]) continue; if ((found == 0 || nextInt(seed, j++) == 0)) { out.x = (x1 + i%width) << 2; @@ -865,7 +865,7 @@ Pos findBiomePosition( { for (i = 0; i < width*height; i++) { - if (isValid[map[i]] && (found == 0 || nextInt(seed, found + 1) == 0)) + if (isValid[ids[i]] && (found == 0 || nextInt(seed, found + 1) == 0)) { out.x = (x1 + i%width) << 2; out.z = (z1 + i/width) << 2; @@ -877,7 +877,7 @@ Pos findBiomePosition( if (cache == NULL) { - free(map); + free(ids); } if (passes != NULL) @@ -905,7 +905,7 @@ int areBiomesViable( int width = x2 - x1 + 1; int height = z2 - z1 + 1; int i; - int *map; + int *ids; int viable; if (l->scale != 4) @@ -914,14 +914,14 @@ int areBiomesViable( l->scale); } - map = cache ? cache : allocCache(l, width, height); - viable = !genArea(l, map, x1, z1, width, height); + ids = cache ? cache : allocCache(l, width, height); + viable = !genArea(l, ids, x1, z1, width, height); if (viable) { for (i = 0; i < width*height; i++) { - if (!isValid[ map[i] ]) + if (!isValid[ ids[i] ]) { viable = 0; break; @@ -930,52 +930,11 @@ int areBiomesViable( } if (cache == NULL) - free(map); + free(ids); return viable; } -int getBiomeRadius( - const int * map, - const int mapSide, - const int * biomes, - const int bnum, - const int ignoreMutations) -{ - int r, i, b; - int blist[0x100]; - int mask = ignoreMutations ? 0x7f : 0xff; - int radiusMax = mapSide / 2; - - if ((mapSide & 1) == 0) - { - printf("WARN getBiomeRadius: Side length of the square map should be an odd integer.\n"); - } - - memset(blist, 0, sizeof(blist)); - - for (r = 1; r < radiusMax; r++) - { - for (i = radiusMax-r; i <= radiusMax+r; i++) - { - blist[ map[(radiusMax-r) * mapSide+ i] & mask ] = 1; - blist[ map[(radiusMax+r-1) * mapSide + i] & mask ] = 1; - blist[ map[mapSide*i + (radiusMax-r)] & mask ] = 1; - blist[ map[mapSide*i + (radiusMax+r-1)] & mask ] = 1; - } - - for (b = 0; b < bnum && blist[biomes[b] & mask]; b++); - if (b >= bnum) - { - break; - } - } - - return r != radiusMax ? r : -1; -} - - - //============================================================================== // Finding Strongholds and Spawn //============================================================================== @@ -985,19 +944,19 @@ const char* getValidStrongholdBiomes(int mc) { static const int strongholdBiomes[] = { plains, desert, mountains, forest, taiga, snowy_tundra, snowy_mountains, - mushroom_fields, desert_hills, wooded_hills, taiga_hills, mountain_edge, - jungle, jungle_hills, jungle_edge, stone_shore, birch_forest, - birch_forest_hills, dark_forest, snowy_taiga, snowy_taiga_hills, - giant_tree_taiga, giant_tree_taiga_hills, wooded_mountains, savanna, - savanna_plateau, badlands, wooded_badlands_plateau, badlands_plateau, - - plains+128, desert+128, mountains+128, forest+128, taiga+128, - snowy_tundra+128, jungle+128, jungle_edge+128, birch_forest+128, - birch_forest_hills+128, dark_forest+128, snowy_taiga+128, - giant_tree_taiga+128, giant_tree_taiga_hills+128, wooded_mountains+128, - savanna+128, savanna_plateau+128, badlands+128, - wooded_badlands_plateau+128, badlands_plateau+128, - + mushroom_fields, mushroom_field_shore, desert_hills, wooded_hills, + taiga_hills, mountain_edge, jungle,jungle_hills, jungle_edge, + stone_shore, birch_forest, birch_forest_hills, dark_forest, snowy_taiga, + snowy_taiga_hills, giant_tree_taiga, giant_tree_taiga_hills, + wooded_mountains, savanna, savanna_plateau, badlands, + wooded_badlands_plateau, badlands_plateau, sunflower_plains, + desert_lakes, gravelly_mountains, flower_forest, taiga_mountains, + ice_spikes, modified_jungle, modified_jungle_edge, tall_birch_forest, + tall_birch_hills, dark_forest_hills, snowy_taiga_mountains, + giant_spruce_taiga, giant_spruce_taiga_hills, + modified_gravelly_mountains, shattered_savanna, + shattered_savanna_plateau, eroded_badlands, + modified_wooded_badlands_plateau, modified_badlands_plateau, bamboo_jungle, bamboo_jungle_hills, }; @@ -1610,7 +1569,7 @@ static int mapViableShore(const Layer * l, int * out, int x, int z, int w, int h int isViableStructurePos(int structureType, int mc, LayerStack *g, int64_t seed, int blockX, int blockZ) { - int *map = NULL; + int *ids = NULL; Layer *l; int viable = 0; @@ -1660,10 +1619,10 @@ L_feature: biomeZ = (chunkZ << 2) + 2; } setLayerSeed(l, seed); - map = allocCache(l, 1, 1); - if (genArea(l, map, biomeX, biomeZ, 1, 1)) + ids = allocCache(l, 1, 1); + if (genArea(l, ids, biomeX, biomeZ, 1, 1)) goto L_not_viable; - if (!isViableFeatureBiome(mc, structureType, map[0])) + if (!isViableFeatureBiome(mc, structureType, ids[0])) goto L_not_viable; goto L_viable; @@ -1672,12 +1631,12 @@ L_feature: biomeX = (chunkX << 2) + 2; biomeZ = (chunkZ << 2) + 2; setLayerSeed(l, seed); - map = allocCache(l, 1, 1); - if (genArea(l, map, biomeX, biomeZ, 1, 1)) + ids = allocCache(l, 1, 1); + if (genArea(l, ids, biomeX, biomeZ, 1, 1)) goto L_not_viable; - if (!isViableFeatureBiome(mc, structureType, map[0])) + if (!isViableFeatureBiome(mc, structureType, ids[0])) goto L_not_viable; - viable = map[0]; // biome for viablility value as it may be useful for further analysis + viable = ids[0]; // biome for viablility value as it may be useful for further analysis goto L_viable; case Outpost: @@ -1701,10 +1660,10 @@ L_feature: biomeZ = (chunkZ << 2) + 2; } setLayerSeed(l, seed); - map = allocCache(l, 1, 1); - if (genArea(l, map, biomeX, biomeZ, 1, 1)) + ids = allocCache(l, 1, 1); + if (genArea(l, ids, biomeX, biomeZ, 1, 1)) goto L_not_viable; - if (!isViableFeatureBiome(mc, structureType, map[0])) + if (!isViableFeatureBiome(mc, structureType, ids[0])) goto L_not_viable; // look for villages within 10 chunks int cx0 = (chunkX-10), cx1 = (chunkX+10); @@ -1736,8 +1695,8 @@ L_feature: { // In 1.8 monuments require only a single deep ocean block. l = g->entry_1; setLayerSeed(l, seed); - map = allocCache(l, 1, 1); - if (genArea(l, map, (chunkX << 4) + 8, (chunkZ << 4) + 8, 1, 1)) + ids = allocCache(l, 1, 1); + if (genArea(l, ids, (chunkX << 4) + 8, (chunkZ << 4) + 8, 1, 1)) goto L_not_viable; } else @@ -1745,11 +1704,11 @@ L_feature: // branch => worth checking for potential deep ocean beforehand. l = &g->layers[L_SHORE_16]; setLayerSeed(l, seed); - map = allocCache(l, 1, 1); - if (genArea(l, map, chunkX, chunkZ, 1, 1)) + ids = allocCache(l, 1, 1); + if (genArea(l, ids, chunkX, chunkZ, 1, 1)) goto L_not_viable; } - if (!isDeepOcean(map[0])) + if (!isDeepOcean(ids[0])) goto L_not_viable; if (mc >= MC_1_13) l = &g->layers[L13_OCEAN_MIX_4]; @@ -1793,8 +1752,8 @@ L_not_viable: g->layers[L_BIOME_256] = lbiome; g->layers[L_SHORE_16] = lshore; - if (map) - free(map); + if (ids) + free(ids); return viable; } @@ -2491,7 +2450,7 @@ int checkForBiomes( { Layer *l; - if (protoCheck) + if (protoCheck) // TODO: protoCheck for 1.6- { l = &g->layers[layerID]; @@ -2535,7 +2494,7 @@ int checkForBiomes( if (filter.majorToFind & (1ULL << mushroom_fields)) { - ss = getStartSeed(seed, g->layers[L_ADD_MUSHROOM_256].layerSalt); + ss = getStartSeed(seed, g->layers[L_MUSHROOM_256].layerSalt); for (j = z0; j <= z1; j++) { @@ -2591,28 +2550,28 @@ L_HAS_PROTO_MUSHROOM: } l = g->layers; - int *map = cache ? cache : allocCache(&l[layerID], w, h); + int *ids = cache ? cache : allocCache(&l[layerID], w, h); filter_data_t fd[9]; - swapMap(fd+0, &filter, l+L13_OCEAN_MIX_4, mapFilterOceanMix); - swapMap(fd+1, &filter, l+L_RIVER_MIX_4, mapFilterRiverMix); - swapMap(fd+2, &filter, l+L_SHORE_16, mapFilterShore); - swapMap(fd+3, &filter, l+L_RARE_BIOME_64, mapFilterRareBiome); - swapMap(fd+4, &filter, l+L_BIOME_EDGE_64, mapFilterBiomeEdge); - swapMap(fd+5, &filter, l+L13_OCEAN_TEMP_256, mapFilterOceanTemp); - swapMap(fd+6, &filter, l+L_BIOME_256, mapFilterBiome); - swapMap(fd+7, &filter, l+L_ADD_MUSHROOM_256, mapFilterMushroom); - swapMap(fd+8, &filter, l+L_SPECIAL_1024, mapFilterSpecial); + swapMap(fd+0, &filter, l+L_OCEAN_MIX_4, mapFilterOceanMix); + swapMap(fd+1, &filter, l+L_RIVER_MIX_4, mapFilterRiverMix); + swapMap(fd+2, &filter, l+L_SHORE_16, mapFilterShore); + swapMap(fd+3, &filter, l+L_SUNFLOWER_64, mapFilterRareBiome); + swapMap(fd+4, &filter, l+L_BIOME_EDGE_64, mapFilterBiomeEdge); + swapMap(fd+5, &filter, l+L_OCEAN_TEMP_256, mapFilterOceanTemp); + swapMap(fd+6, &filter, l+L_BIOME_256, mapFilterBiome); + swapMap(fd+7, &filter, l+L_MUSHROOM_256, mapFilterMushroom); + swapMap(fd+8, &filter, l+L_SPECIAL_1024, mapFilterSpecial); setLayerSeed(&l[layerID], seed); - int ret = !l[layerID].getMap(&l[layerID], map, x, z, w, h); + int ret = !l[layerID].getMap(&l[layerID], ids, x, z, w, h); if (ret) { uint64_t required, b = 0, bm = 0; unsigned int i; for (i = 0; i < w*h; i++) { - int id = map[i]; + int id = ids[i]; if (id < 128) b |= (1ULL << id); else bm |= (1ULL << (id-128)); } @@ -2627,17 +2586,17 @@ L_HAS_PROTO_MUSHROOM: } restoreMap(fd+8, l+L_SPECIAL_1024); - restoreMap(fd+7, l+L_ADD_MUSHROOM_256); + restoreMap(fd+7, l+L_MUSHROOM_256); restoreMap(fd+6, l+L_BIOME_256); - restoreMap(fd+5, l+L13_OCEAN_TEMP_256); + restoreMap(fd+5, l+L_OCEAN_TEMP_256); restoreMap(fd+4, l+L_BIOME_EDGE_64); - restoreMap(fd+3, l+L_RARE_BIOME_64); + restoreMap(fd+3, l+L_SUNFLOWER_64); restoreMap(fd+2, l+L_SHORE_16); restoreMap(fd+1, l+L_RIVER_MIX_4); - restoreMap(fd+0, l+L13_OCEAN_MIX_4); + restoreMap(fd+0, l+L_OCEAN_MIX_4); if (cache == NULL) - free(map); + free(ids); return ret; } @@ -2699,30 +2658,140 @@ int checkForTemps(LayerStack *g, int64_t seed, int x, int z, int w, int h, const } +int canBiomeGenerate(int layerId, int mc, int id) +{ + int dofilter = 0; + + if (dofilter || layerId == L_BIOME_256) + { + dofilter = 1; + if (id >= 64) + return 0; + } + if (dofilter || (layerId == L_BAMBOO_256 && mc >= MC_1_14)) + { + dofilter = 1; + switch (id) + { + case jungle_edge: + case wooded_mountains: + case badlands: + return 0; + } + } + if (dofilter || (layerId == L_BIOME_EDGE_64 && mc >= MC_1_7)) + { + dofilter = 1; + if (id >= 64 && id != bamboo_jungle) + return 0; + switch (id) + { + case snowy_mountains: + case desert_hills: + case wooded_hills: + case taiga_hills: + case jungle_hills: + case birch_forest_hills: + case snowy_taiga_hills: + case giant_tree_taiga_hills: + case savanna_plateau: + return 0; + } + } + if (dofilter || layerId == L_HILLS_64) + { + dofilter = 1; + // sunflower_plains actually generate at Hills layer as well + } + if (dofilter || (layerId == L_SUNFLOWER_64 && mc >= MC_1_7)) + { + dofilter = 1; + switch (id) + { + case frozen_ocean: + case mushroom_field_shore: + case beach: + case stone_shore: + case snowy_beach: + return 0; + } + } + if (dofilter || layerId == L_SHORE_16) + { + dofilter = 1; + if (id == river || id == frozen_river) + return 0; + } + if (dofilter || layerId == L_RIVER_MIX_4) + { + dofilter = 1; + switch (id) + { + case frozen_ocean: + if (mc >= MC_1_7) + return 0; + break; + case warm_ocean...deep_frozen_ocean: + return 0; + } + } + if (dofilter || (layerId == L_OCEAN_MIX_4 && mc >= MC_1_13)) + { + dofilter = 1; + } + + if (!dofilter && layerId != L_VORONOI_1) + { + printf("canBiomeGenerate(): unsupported layer or version\n"); + return 0; + } + return isOverworld(mc, id); +} + + +// TODO: This function requires testing across versions void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) { - if (layer >= L_BIOME_256 && !isOverworld(mc, id)) + // filter out bad biomes + if (layer >= L_BIOME_256 && !canBiomeGenerate(mc, layer, id)) return; - int i; - switch (layer) { - case L_SPECIAL_1024: // biomes added in (L_SPECIAL_1024, L_ADD_MUSHROOM_256] + case L_SPECIAL_1024: // biomes added in (L_SPECIAL_1024, L_MUSHROOM_256] + if (mc <= MC_1_6) goto L_bad_layer; if (id == Oceanic) - genPotential(mL, mM, L_ADD_MUSHROOM_256, mc, mushroom_fields); + genPotential(mL, mM, L_MUSHROOM_256, mc, mushroom_fields); if ((id & ~0xf00) >= Oceanic && (id & ~0xf00) <= Freezing) - genPotential(mL, mM, L_ADD_MUSHROOM_256, mc, id); + genPotential(mL, mM, L_MUSHROOM_256, mc, id); break; - case L_ADD_MUSHROOM_256: // biomes added in (L_ADD_MUSHROOM_256, L_DEEP_OCEAN_256] - if (id == Oceanic) - genPotential(mL, mM, L_DEEP_OCEAN_256, mc, deep_ocean); - if ((id & ~0xf00) >= Oceanic && (id & ~0xf00) <= Freezing) - genPotential(mL, mM, L_DEEP_OCEAN_256, mc, id); + case L_MUSHROOM_256: // biomes added in (L_MUSHROOM_256, L_DEEP_OCEAN_256] + if (mc >= MC_1_7) { + if (id == Oceanic) + genPotential(mL, mM, L_DEEP_OCEAN_256, mc, deep_ocean); + if ((id & ~0xf00) >= Oceanic && (id & ~0xf00) <= Freezing) + genPotential(mL, mM, L_DEEP_OCEAN_256, mc, id); + } else { // (L_MUSHROOM_256, L_BIOME_256] for 1.6 + if (id == ocean || id == mushroom_fields) { + genPotential(mL, mM, L_BIOME_256, mc, id); + } else { + genPotential(mL, mM, L_BIOME_256, mc, desert); + genPotential(mL, mM, L_BIOME_256, mc, forest); + genPotential(mL, mM, L_BIOME_256, mc, mountains); + genPotential(mL, mM, L_BIOME_256, mc, swamp); + genPotential(mL, mM, L_BIOME_256, mc, plains); + genPotential(mL, mM, L_BIOME_256, mc, taiga); + if (mc >= MC_1_2) + genPotential(mL, mM, L_BIOME_256, mc, jungle); + if (id != plains) + genPotential(mL, mM, L_BIOME_256, mc, snowy_tundra); + } + } break; case L_DEEP_OCEAN_256: // biomes added in (L_DEEP_OCEAN_256, L_BIOME_256] + if (mc <= MC_1_6) goto L_bad_layer; switch (id & ~0xf00) { case Warm: @@ -2768,30 +2837,27 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) break; case L_BIOME_256: // biomes added in (L_BIOME_256, L_BIOME_EDGE_64] - for (i = sizeof(BIOMES_L_BIOME_256) / sizeof(int); i >= 0; i--) - if (BIOMES_L_BIOME_256[i] == id) - break; - if (i < 0) break; - if (mc >= MC_1_14 && id == jungle) - genPotential(mL, mM, L_BIOME_EDGE_64, mc, bamboo_jungle); - if (id == wooded_badlands_plateau || id == badlands_plateau) - genPotential(mL, mM, L_BIOME_EDGE_64, mc, badlands); - else if(id == giant_tree_taiga) - genPotential(mL, mM, L_BIOME_EDGE_64, mc, taiga); - else if (id == desert) - genPotential(mL, mM, L_BIOME_EDGE_64, mc, wooded_mountains); - else if (id == swamp) { - genPotential(mL, mM, L_BIOME_EDGE_64, mc, jungle_edge); - genPotential(mL, mM, L_BIOME_EDGE_64, mc, plains); + if (mc >= MC_1_7) { + if (mc >= MC_1_14 && id == jungle) + genPotential(mL, mM, L_BIOME_EDGE_64, mc, bamboo_jungle); + if (id == wooded_badlands_plateau || id == badlands_plateau) + genPotential(mL, mM, L_BIOME_EDGE_64, mc, badlands); + else if(id == giant_tree_taiga) + genPotential(mL, mM, L_BIOME_EDGE_64, mc, taiga); + else if (id == desert) + genPotential(mL, mM, L_BIOME_EDGE_64, mc, wooded_mountains); + else if (id == swamp) { + genPotential(mL, mM, L_BIOME_EDGE_64, mc, jungle_edge); + genPotential(mL, mM, L_BIOME_EDGE_64, mc, plains); + } + genPotential(mL, mM, L_BIOME_EDGE_64, mc, id); + break; } - genPotential(mL, mM, L_BIOME_EDGE_64, mc, id); - break; + // (L_BIOME_256, L_HILLS_64] for 1.6 + // fallthrough case L_BIOME_EDGE_64: // biomes added in (L_BIOME_EDGE_64, L_HILLS_64] - for (i = sizeof(BIOMES_L_BIOME_EDGE_64) / sizeof(int); i >= 0; i--) - if (BIOMES_L_BIOME_EDGE_64[i] == id) - break; - if (i < 0) break; + if (mc <= MC_1_6 && layer == L_BIOME_EDGE_64) goto L_bad_layer; if (!isShallowOcean(id) && getMutated(mc, id) > 0) genPotential(mL, mM, L_HILLS_64, mc, getMutated(mc, id)); switch (id) @@ -2818,7 +2884,8 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) genPotential(mL, mM, L_HILLS_64, mc, getMutated(mc, giant_tree_taiga_hills)); break; case plains: - genPotential(mL, mM, L_HILLS_64, mc, wooded_hills); + if (mc >= MC_1_7) + genPotential(mL, mM, L_HILLS_64, mc, wooded_hills); genPotential(mL, mM, L_HILLS_64, mc, forest); genPotential(mL, mM, L_HILLS_64, mc, getMutated(mc, forest)); break; @@ -2829,11 +2896,14 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) genPotential(mL, mM, L_HILLS_64, mc, bamboo_jungle_hills); break; case ocean: - genPotential(mL, mM, L_HILLS_64, mc, deep_ocean); + if (mc >= MC_1_7) + genPotential(mL, mM, L_HILLS_64, mc, deep_ocean); break; case mountains: - genPotential(mL, mM, L_HILLS_64, mc, wooded_mountains); - genPotential(mL, mM, L_HILLS_64, mc, getMutated(mc, wooded_mountains)); + if (mc >= MC_1_7) { + genPotential(mL, mM, L_HILLS_64, mc, wooded_mountains); + genPotential(mL, mM, L_HILLS_64, mc, getMutated(mc, wooded_mountains)); + } break; case savanna: genPotential(mL, mM, L_HILLS_64, mc, savanna_plateau); @@ -2857,20 +2927,23 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) break; case L_HILLS_64: // biomes added in (L_HILLS_64, L_RARE_BIOME_64] - for (i = sizeof(BIOMES_L_HILLS_64) / sizeof(int); i >= 0; i--) - if (BIOMES_L_HILLS_64[i] == id) - break; - if (i < 0) break; - if (id == plains) - genPotential(mL, mM, L_RARE_BIOME_64, mc, sunflower_plains); - genPotential(mL, mM, L_RARE_BIOME_64, mc, id); + if (mc <= MC_1_6) { // (L_HILLS_64, L_SHORE_16] for 1.6 + if (id == mushroom_fields) + genPotential(mL, mM, L_SHORE_16, mc, mushroom_field_shore); + else if (id == mountains) + genPotential(mL, mM, L_SHORE_16, mc, mountain_edge); + else if (id != ocean && id != river && id != swamp) + genPotential(mL, mM, L_SHORE_16, mc, beach); + genPotential(mL, mM, L_SHORE_16, mc, id); + } else { + if (id == plains) + genPotential(mL, mM, L_SUNFLOWER_64, mc, sunflower_plains); + genPotential(mL, mM, L_SUNFLOWER_64, mc, id); + } break; - case L_RARE_BIOME_64: // biomes added in (L_RARE_BIOME_64, L_SHORE_16] - for (i = sizeof(BIOMES_L_HILLS_64) / sizeof(int); i >= 0; i--) - if (BIOMES_L_HILLS_64[i] == id) - break; - if (i < 0 && id != sunflower_plains) break; + case L_SUNFLOWER_64: // biomes added in (L_SUNFLOWER_64, L_SHORE_16] 1.7+ + if (mc <= MC_1_6) goto L_bad_layer; if (id == mushroom_fields) genPotential(mL, mM, L_SHORE_16, mc, mushroom_field_shore); else if (getCategory(mc, id) == jungle) { @@ -2889,10 +2962,6 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) break; case L_SHORE_16: // biomes added in (L_SHORE_16, L_RIVER_MIX_4] - for (i = sizeof(BIOMES_L_SHORE_16) / sizeof(int); i >= 0; i--) - if (BIOMES_L_SHORE_16[i] == id) - break; - if (i < 0) break; if (id == snowy_tundra) genPotential(mL, mM, L_RIVER_MIX_4, mc, frozen_river); if (id == mushroom_fields || id == mushroom_field_shore) @@ -2900,30 +2969,26 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) genPotential(mL, mM, L_RIVER_MIX_4, mc, id); break; - case L_RIVER_MIX_4: // biomes added in (L_RIVER_MIX_4, L_VORONOI_ZOOM_1] - if (mc >= MC_1_13 && isOceanic(id)) - { - if (id == ocean) - { - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, warm_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, lukewarm_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, cold_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, frozen_ocean); - } - else if (id == deep_ocean) - { - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, deep_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, deep_lukewarm_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, deep_cold_ocean); - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, deep_frozen_ocean); + case L_RIVER_MIX_4: // biomes added in (L_RIVER_MIX_4, L_VORONOI_1] + if (mc >= MC_1_13 && isOceanic(id)) { + if (id == ocean) { + genPotential(mL, mM, L_VORONOI_1, mc, ocean); + genPotential(mL, mM, L_VORONOI_1, mc, warm_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, lukewarm_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, cold_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, frozen_ocean); + } else if (id == deep_ocean) { + genPotential(mL, mM, L_VORONOI_1, mc, deep_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, deep_lukewarm_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, deep_cold_ocean); + genPotential(mL, mM, L_VORONOI_1, mc, deep_frozen_ocean); } else break; } - genPotential(mL, mM, L_VORONOI_ZOOM_1, mc, id); + genPotential(mL, mM, L_VORONOI_1, mc, id); break; - case L_VORONOI_ZOOM_1: + case L_VORONOI_1: if (id < 128) *mL |= 1ULL << id; else *mM |= 1ULL << (id-128); break; @@ -2931,6 +2996,11 @@ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id) default: printf("genPotential() not implemented for layer %d\n", layer); } + if (0) + { + L_bad_layer: + printf("genPotential() bad layer %d for version\n", layer); + } } diff --git a/finders.h b/finders.h index df6f3ec..c4e8200 100644 --- a/finders.h +++ b/finders.h @@ -101,20 +101,6 @@ static const StructureConfig BASTION_CONFIG = { 30084232, 27, 4, Bastion static const StructureConfig END_CITY_CONFIG = { 10387313, 20, 9, End_City, LARGE_STRUCT}; -//============================================================================== -// Biome Tables -//============================================================================== - -static const int achievementBiomes_1_7[] = -{ - ocean, plains, desert, extremeHills, forest, taiga, swampland, river, /*hell, sky,*/ // 0-9 - /*frozenOcean,*/ frozenRiver, icePlains, iceMountains, mushroomIsland, mushroomIslandShore, beach, desertHills, forestHills, taigaHills, // 10-19 - /*extremeHillsEdge,*/ jungle, jungleHills, jungleEdge, deepOcean, stoneBeach, coldBeach, birchForest, birchForestHills, roofedForest, // 20-29 - coldTaiga, coldTaigaHills, megaTaiga, megaTaigaHills, extremeHillsPlus, savanna, savannaPlateau, mesa, mesaPlateau_F, mesaPlateau // 30-39 -}; - - - STRUCT(Pos) { int x, z; @@ -522,7 +508,7 @@ Pos findBiomePosition( * and mansions. * Warning: accurate, but slow! * - * @l : entry layer with scale = 4: (L_RIVER_MIX_4, L13_OCEAN_MIX_4) + * @l : entry layer with scale = 4: [L_RIVER_MIX_4|L13_OCEAN_MIX_4] * @cache : biome buffer, set to NULL for temporary allocation * @posX, posZ : centre for the check * @radius : 'radius' of the check area @@ -537,26 +523,6 @@ int areBiomesViable( const char * isValid ); -/* Finds the smallest radius (by square around the origin) at which all the - * specified biomes are present. The input map is assumed to be a square of - * side length 'sideLen'. - * - * @map : square biome map to be tested - * @sideLen : side length of the square map (should be 2*radius+1) - * @biomes : list of biomes to check for - * @bnum : length of 'biomes' - * @ignoreMutations : flag to count mutated biomes as their original form - * - * Return the radius on the square map that covers all biomes in the list. - * If the map does not contain all the specified biomes, -1 is returned. - */ -int getBiomeRadius( - const int * map, - const int mapSide, - const int * biomes, - const int bnum, - const int ignoreMutations); - //============================================================================== // Finding Strongholds and Spawn @@ -587,7 +553,8 @@ Pos initFirstStronghold(StrongholdIter *sh, int mc, int64_t s48); */ int nextStronghold(StrongholdIter *sh, const LayerStack *g, int *cache); -/* Finds the block positions of the strongholds in the world. Note that the +/* deprecated - use initFirstStronghold() and nextStronghold() instead + * Finds the block positions of the strongholds in the world. Note that the * number of strongholds was increased from 3 to 128 in MC 1.9. * Warning: Slow! * @@ -602,6 +569,7 @@ int nextStronghold(StrongholdIter *sh, const LayerStack *g, int *cache); * * Returned is the number of strongholds found. */ +__attribute__((deprecated)) int findStrongholds( const int mcversion, const LayerStack * g, @@ -616,21 +584,21 @@ int findStrongholds( * Warning: Slow, and may be inaccurate because the world spawn depends on * grass blocks! * - * @mcversion : Minecraft version (changed in 1.7, 1.13) + * @mc : Minecraft version (changed in 1.7, 1.13) * @g : generator layer stack [worldSeed should be applied before call!] * @cache : biome buffer, set to NULL for temporary allocation * @worldSeed : world seed used for the generator */ -Pos getSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed); +Pos getSpawn(const int mc, const LayerStack *g, int *cache, int64_t worldSeed); /* Finds the approximate spawn point in the world. * - * @mcversion : Minecraft version (changed in 1.7, 1.13) + * @mc : Minecraft version (changed in 1.7, 1.13) * @g : generator layer stack [worldSeed should be applied before call!] * @cache : biome buffer, set to NULL for temporary allocation * @worldSeed : world seed used for the generator */ -Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed); +Pos estimateSpawn(const int mc, const LayerStack *g, int *cache, int64_t worldSeed); //============================================================================== @@ -717,7 +685,7 @@ BiomeFilter setupBiomeFilter(const int *biomeList, int listLen); * @seed : world seed * @x,z,w,h : requested area * @filter : biomes to be checked for - * @protoCheck : enables more aggressive filtering when non-zero + * @protoCheck : enables more aggressive filtering when non-zero (MC >= 1.7) */ int checkForBiomes( LayerStack * g, @@ -738,9 +706,18 @@ int checkForBiomes( * if (tc[TEMP_CAT] < 0) avoid, there shall be no entries of this category * TEMP_CAT is any of: * Oceanic, Warm, Lush, Cold, Freeing, Special+Warm, Special+Lush, Special+Cold + * For 1.7+ only. */ int checkForTemps(LayerStack *g, int64_t seed, int x, int z, int w, int h, const int tc[9]); +/* Checks if a biome may generate given a version and layer ID as entry point. + * The supported layers are: + * L_BIOME_256, L_BAMBOO_256, L_BIOME_EDGE_64, L_HILLS_64, L_SUNFLOWER_64, + * L_SHORE_16, L_RIVER_MIX_4, L_OCEAN_MIX_4, L_VORONOI_1 + * (provided the version matches) + */ +int canBiomeGenerate(int layerId, int mc, int biomeID); + /* Given a biome 'id' at a generation 'layer', this functions finds which * biomes may generate from it. The result is stored in the bitfields: * mL : for ids 0-63 @@ -748,7 +725,6 @@ int checkForTemps(LayerStack *g, int64_t seed, int x, int z, int w, int h, const */ void genPotential(uint64_t *mL, uint64_t *mM, int layer, int mc, int id); - //============================================================================== // Implementaions for Functions that Ideally Should be Inlined //============================================================================== diff --git a/generator.c b/generator.c index c896f90..4616107 100644 --- a/generator.c +++ b/generator.c @@ -6,8 +6,7 @@ #include - -Layer *setupLayer(LayerStack *g, int layerId, mapfunc_t map, int mc, +Layer *setupLayer(LayerStack *g, int layerId, mapfunc_t *map, int mc, int8_t zoom, int8_t edge, int saltbase, Layer *p, Layer *p2) { Layer *l = g->layers + layerId; @@ -28,6 +27,7 @@ Layer *setupLayer(LayerStack *g, int layerId, mapfunc_t map, int mc, static void setupScale(Layer *l, int scale) { + l->scale = scale; if (l->p) setupScale(l->p, scale * l->zoom); if (l->p2) @@ -49,110 +49,114 @@ static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) // P1: parent 1 // P2: parent 2 - // G, L, M V Z E S P1 P2 - p = setupLayer(g, L_ISLAND_4096, mapIsland, mc, 1, 0, 1, 0, 0); - p = setupLayer(g, L_ZOOM_2048, mapZoomIsland, mc, 2, 3, 2000, p, 0); - p = setupLayer(g, L_ADD_ISLAND_2048, mapAddIsland, mc, 1, 2, 1, p, 0); - p = setupLayer(g, L_ZOOM_1024, mapZoom, mc, 2, 3, 2001, p, 0); - p = setupLayer(g, L_ADD_ISLAND_1024A, mapAddIsland, mc, 1, 2, 2, p, 0); + // G, L, M V Z E S P1 P2 + p = setupLayer(g, L_CONTINENT_4096, mapContinent, mc, 1, 0, 1, 0, 0); + p = setupLayer(g, L_ZOOM_2048, mapZoomFuzzy, mc, 2, 3, 2000, p, 0); + p = setupLayer(g, L_LAND_2048, mapLand, mc, 1, 2, 1, p, 0); + p = setupLayer(g, L_ZOOM_1024, mapZoom, mc, 2, 3, 2001, p, 0); + p = setupLayer(g, L_LAND_1024_A, mapLand, mc, 1, 2, 2, p, 0); if (mc <= MC_1_6) { - // G L M V Z E S P1 P2 - p = setupLayer(g, L_ADD_SNOW_1024, mapAddSnow16, mc, 1, 2, 2, p, 0); - p = setupLayer(g, L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0); - p = setupLayer(g, L_ADD_ISLAND_1024D, mapAddIsland16, mc, 1, 2, 3, p, 0); - p = setupLayer(g, L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0); - p = setupLayer(g, L_ADD_ISLAND_256, mapAddIsland16, mc, 1, 2, 4, p, 0); - p = setupLayer(g, L_ADD_MUSHROOM_256, mapAddMushroomIsland, mc, 1, 2, 5, p, 0); - p = setupLayer(g, L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0); - p = setupLayer(g, L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0); - p = setupLayer(g, L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0); + // G L M V Z E S P1 P2 + p = setupLayer(g, L_SNOW_1024, mapSnow16, mc, 1, 2, 2, p, 0); + p = setupLayer(g, L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0); + p = setupLayer(g, L_LAND_512, mapLand16, mc, 1, 2, 3, p, 0); + p = setupLayer(g, L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0); + p = setupLayer(g, L_LAND_256, mapLand16, mc, 1, 2, 4, p, 0); + p = setupLayer(g, L_MUSHROOM_256, mapMushroom, mc, 1, 2, 5, p, 0); + p = setupLayer(g, L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0); + p = setupLayer(g, L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0); + p = setupLayer(g, L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0); - // river RNG layer chain, also used to determine where hills generate - p = setupLayer(g, L_RIVER_INIT_256, mapRiverInit, mc, 1, 0, 100, g->layers+L_ADD_MUSHROOM_256, 0); - p = setupLayer(g, L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, 0, p, 0); - p = setupLayer(g, L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, 0, p, 0); + // river noise layer chain, also used to determine where hills generate + p = setupLayer(g, L_NOISE_256, mapNoise, mc, 1, 0, 100, + g->layers+L_MUSHROOM_256, 0); + p = setupLayer(g, L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, 0, p, 0); + p = setupLayer(g, L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, 0, p, 0); - p = setupLayer(g, L_HILLS_64, mapHills, mc, 1, 2, 1000, + p = setupLayer(g, L_HILLS_64, mapHills, mc, 1, 2, 1000, g->layers+L_ZOOM_64, g->layers+L_ZOOM_64_HILLS); - p = setupLayer(g, L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0); - p = setupLayer(g, L_ADD_ISLAND_32, mapAddIsland16, mc, 1, 2, 3, p, 0); - p = setupLayer(g, L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0); - p = setupLayer(g, L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0); - p = setupLayer(g, L_RIVER_BIOME_16, mapRiverInBiome, mc, 1, 0, 1000, p, 0); - p = setupLayer(g, L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0); - p = setupLayer(g, L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0); + p = setupLayer(g, L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0); + p = setupLayer(g, L_LAND_32, mapLand16, mc, 1, 2, 3, p, 0); + p = setupLayer(g, L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0); + p = setupLayer(g, L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0); + p = setupLayer(g, L_SWAMP_RIVER_16, mapSwampRiver, mc, 1, 0, 1000, p, 0); + p = setupLayer(g, L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0); + p = setupLayer(g, L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0); - p = setupLayer(g, L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0); + p = setupLayer(g, L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0); // river layer chain - p = setupLayer(g, L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000, g->layers+L_RIVER_INIT_256, 0); - p = setupLayer(g, L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0); - p = setupLayer(g, L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1002, p, 0); - p = setupLayer(g, L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1003, p, 0); - p = setupLayer(g, L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1004, p, 0); - p = setupLayer(g, L_ZOOM_4_RIVER, 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); + p = setupLayer(g, L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000, + g->layers+L_NOISE_256, 0); + p = setupLayer(g, L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0); + p = setupLayer(g, L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1002, p, 0); + p = setupLayer(g, L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1003, p, 0); + p = setupLayer(g, L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1004, p, 0); + p = setupLayer(g, L_ZOOM_4_RIVER, 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); } else { - // G L M V Z E S P1 P2 - p = setupLayer(g, L_ADD_ISLAND_1024B, mapAddIsland, mc, 1, 2, 50, p, 0); - p = setupLayer(g, L_ADD_ISLAND_1024C, mapAddIsland, mc, 1, 2, 70, p, 0); - p = setupLayer(g, L_REMOVE_OCEAN_1024, mapRemoveTooMuchOcean, mc, 1, 2, 2, p, 0); - p = setupLayer(g, L_ADD_SNOW_1024, mapAddSnow, mc, 1, 2, 2, p, 0); - p = setupLayer(g, L_ADD_ISLAND_1024D, mapAddIsland, mc, 1, 2, 3, p, 0); - p = setupLayer(g, L_COOL_WARM_1024, mapCoolWarm, mc, 1, 2, 2, p, 0); - p = setupLayer(g, L_HEAT_ICE_1024, mapHeatIce, mc, 1, 2, 2, p, 0); - p = setupLayer(g, L_SPECIAL_1024, mapSpecial, mc, 1, 2, 3, p, 0); - p = setupLayer(g, L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0); - p = setupLayer(g, L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0); - p = setupLayer(g, L_ADD_ISLAND_256, mapAddIsland, mc, 1, 2, 4, p, 0); - p = setupLayer(g, L_ADD_MUSHROOM_256, mapAddMushroomIsland, mc, 1, 2, 5, p, 0); - p = setupLayer(g, L_DEEP_OCEAN_256, mapDeepOcean, mc, 1, 2, 4, p, 0); - p = setupLayer(g, L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0); + // G L M V Z E S P1 P2 + p = setupLayer(g, L_LAND_1024_B, mapLand, mc, 1, 2, 50, p, 0); + p = setupLayer(g, L_LAND_1024_C, mapLand, mc, 1, 2, 70, p, 0); + p = setupLayer(g, L_ISLAND_1024, mapIsland, mc, 1, 2, 2, p, 0); + p = setupLayer(g, L_SNOW_1024, mapSnow, mc, 1, 2, 2, p, 0); + p = setupLayer(g, L_LAND_1024_D, mapLand, mc, 1, 2, 3, p, 0); + p = setupLayer(g, L_COOL_1024, mapCool, mc, 1, 2, 2, p, 0); + p = setupLayer(g, L_HEAT_1024, mapHeat, mc, 1, 2, 2, p, 0); + p = setupLayer(g, L_SPECIAL_1024, mapSpecial, mc, 1, 2, 3, p, 0); + p = setupLayer(g, L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0); + p = setupLayer(g, L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0); + p = setupLayer(g, L_LAND_256, mapLand, mc, 1, 2, 4, p, 0); + p = setupLayer(g, L_MUSHROOM_256, mapMushroom, mc, 1, 2, 5, p, 0); + p = setupLayer(g, L_DEEP_OCEAN_256, mapDeepOcean, mc, 1, 2, 4, p, 0); + p = setupLayer(g, L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0); if (mc > MC_1_13) - p = setupLayer(g, L14_BAMBOO_256, mapAddBamboo, mc, 1, 0, 1001, p, 0); - p = setupLayer(g, L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0); - p = setupLayer(g, L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0); - p = setupLayer(g, L_BIOME_EDGE_64, mapBiomeEdge, mc, 1, 2, 1000, p, 0); + p = setupLayer(g, L_BAMBOO_256, mapBamboo, mc, 1, 0, 1001, p, 0); + p = setupLayer(g, L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0); + p = setupLayer(g, L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0); + p = setupLayer(g, L_BIOME_EDGE_64, mapBiomeEdge, mc, 1, 2, 1000, p, 0); - // river RNG layer chain, also used to determine where hills generate - p = setupLayer(g, L_RIVER_INIT_256, mapRiverInit, mc, 1, 0, 100, g->layers+L_DEEP_OCEAN_256, 0); - p = setupLayer(g, L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, mc < MC_1_13 ? 0 : 1000, p, 0); - p = setupLayer(g, L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, mc < MC_1_13 ? 0 : 1001, p, 0); + // river noise layer chain, also used to determine where hills generate + p = setupLayer(g, L_RIVER_INIT_256, mapNoise, mc, 1, 0, 100, + g->layers+L_DEEP_OCEAN_256, 0); + p = setupLayer(g, L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, mc < MC_1_13 ? 0 : 1000, p, 0); + p = setupLayer(g, L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, mc < MC_1_13 ? 0 : 1001, p, 0); - p = setupLayer(g, L_HILLS_64, mapHills, mc, 1, 2, 1000, + p = setupLayer(g, L_HILLS_64, mapHills, mc, 1, 2, 1000, g->layers+L_BIOME_EDGE_64, g->layers+L_ZOOM_64_HILLS); - p = setupLayer(g, L_RARE_BIOME_64, mapRareBiome, mc, 1, 0, 1001, p, 0); - p = setupLayer(g, L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0); - p = setupLayer(g, L_ADD_ISLAND_32, mapAddIsland, mc, 1, 2, 3, p, 0); - p = setupLayer(g, L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0); - p = setupLayer(g, L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0); - p = setupLayer(g, L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0); - p = setupLayer(g, L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0); + p = setupLayer(g, L_SUNFLOWER_64, mapSunflower, mc, 1, 0, 1001, p, 0); + p = setupLayer(g, L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0); + p = setupLayer(g, L_LAND_32, mapLand, mc, 1, 2, 3, p, 0); + p = setupLayer(g, L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0); + p = setupLayer(g, L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0); + p = setupLayer(g, L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0); + p = setupLayer(g, L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0); 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_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_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0); + p = setupLayer(g, L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0); // river layer chain - p = setupLayer(g, L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000, g->layers+L_RIVER_INIT_256, 0); - p = setupLayer(g, L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0); - p = setupLayer(g, L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1000, p, 0); - 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); - 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); + p = setupLayer(g, L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000, + g->layers+L_RIVER_INIT_256, 0); + p = setupLayer(g, L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0); + p = setupLayer(g, L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1000, p, 0); + 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); + 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); } p = setupLayer(g, L_RIVER_MIX_4, mapRiverMix, mc, 1, 0, 100, @@ -161,31 +165,33 @@ static void setupGeneratorImpl(LayerStack *g, int mc, int largeBiomes) if (mc <= MC_1_12) { - g->entry_4 = p; - p = setupLayer(g, L_VORONOI_ZOOM_1, mapVoronoiZoom114, mc, 4, 7, 10, p, 0); + p = setupLayer(g, L_VORONOI_1, mapVoronoi114, mc, 4, 7, 10, p, 0); } else { // ocean variants - p = setupLayer(g, L13_OCEAN_TEMP_256, mapOceanTemp, mc, 1, 0, 2, 0, 0); + p = setupLayer(g, L_OCEAN_TEMP_256, mapOceanTemp, mc, 1, 0, 2, 0, 0); p->noise = &g->oceanRnd; - p = setupLayer(g, L13_ZOOM_128, mapZoom, mc, 2, 3, 2001, p, 0); - p = setupLayer(g, L13_ZOOM_64, mapZoom, mc, 2, 3, 2002, p, 0); - p = setupLayer(g, L13_ZOOM_32, mapZoom, mc, 2, 3, 2003, p, 0); - p = setupLayer(g, L13_ZOOM_16, mapZoom, mc, 2, 3, 2004, p, 0); - p = setupLayer(g, L13_ZOOM_8, mapZoom, mc, 2, 3, 2005, p, 0); - p = setupLayer(g, L13_ZOOM_4, mapZoom, mc, 2, 3, 2006, p, 0); - p = setupLayer(g, L13_OCEAN_MIX_4, mapOceanMix, mc, 1, 17, 100, - g->layers+L_RIVER_MIX_4, g->layers+L13_ZOOM_4); - g->entry_4 = p; + p = setupLayer(g, L_ZOOM_128_OCEAN, mapZoom, mc, 2, 3, 2001, p, 0); + p = setupLayer(g, L_ZOOM_64_OCEAN, mapZoom, mc, 2, 3, 2002, p, 0); + p = setupLayer(g, L_ZOOM_32_OCEAN, mapZoom, mc, 2, 3, 2003, p, 0); + p = setupLayer(g, L_ZOOM_16_OCEAN, mapZoom, mc, 2, 3, 2004, p, 0); + p = setupLayer(g, L_ZOOM_8_OCEAN, mapZoom, mc, 2, 3, 2005, p, 0); + p = setupLayer(g, L_ZOOM_4_OCEAN, mapZoom, mc, 2, 3, 2006, p, 0); + p = setupLayer(g, L_OCEAN_MIX_4, mapOceanMix, mc, 1, 17, 100, + g->layers+L_RIVER_MIX_4, g->layers+L_ZOOM_4_OCEAN); if (mc <= MC_1_14) - p = setupLayer(g, L_VORONOI_ZOOM_1, mapVoronoiZoom114, mc, 4, 7, 10, p, 0); + p = setupLayer(g, L_VORONOI_1, mapVoronoi114, mc, 4, 7, 10, p, 0); else - p = setupLayer(g, L_VORONOI_ZOOM_1, mapVoronoiZoom, mc, 4, 7, -1, p, 0); + p = setupLayer(g, L_VORONOI_1, mapVoronoi, mc, 4, 7, -1, p, 0); } g->entry_1 = p; + g->entry_4 = g->layers + (mc <= MC_1_12 ? L_RIVER_MIX_4 : L_OCEAN_MIX_4); + g->shore_16 = g->layers + L_SHORE_16; + g->hills_64 = g->layers + (mc <= MC_1_7 ? L_HILLS_64 : L_SUNFLOWER_64); + g->biome_256 = g->layers + (mc <= MC_1_14 ? L_BIOME_256 : L_BAMBOO_256); setupScale(g->entry_1, 1); } @@ -262,5 +268,3 @@ int genArea(const Layer *layer, int *out, int areaX, int areaZ, int areaWidth, i - - diff --git a/generator.h b/generator.h index ce62152..587602f 100644 --- a/generator.h +++ b/generator.h @@ -6,38 +6,41 @@ /* Enumeration of the layer indices in the generator. */ enum { - L_ISLAND_4096 = 0, + // new [[deprecated]] + L_CONTINENT_4096 = 0, L_ISLAND_4096 = L_CONTINENT_4096, L_ZOOM_2048, - L_ADD_ISLAND_2048, + L_LAND_2048, L_ADD_ISLAND_2048 = L_LAND_2048, L_ZOOM_1024, - L_ADD_ISLAND_1024A, - L_ADD_ISLAND_1024B, - L_ADD_ISLAND_1024C, - L_REMOVE_OCEAN_1024, - L_ADD_SNOW_1024, - L_ADD_ISLAND_1024D, - L_COOL_WARM_1024, - L_HEAT_ICE_1024, - L_SPECIAL_1024, + L_LAND_1024_A, L_ADD_ISLAND_1024A = L_LAND_1024_A, + L_LAND_1024_B, L_ADD_ISLAND_1024B = L_LAND_1024_B, // 1.7+ + L_LAND_1024_C, L_ADD_ISLAND_1024C = L_LAND_1024_C, // 1.7+ + L_ISLAND_1024, L_REMOVE_OCEAN_1024 = L_ISLAND_1024, // 1.7+ + L_SNOW_1024, L_ADD_SNOW_1024 = L_SNOW_1024, + L_LAND_1024_D, L_ADD_ISLAND_1024D = L_LAND_1024_D, // 1.7+ + L_COOL_1024, L_COOL_WARM_1024 = L_COOL_1024, // 1.7+ + L_HEAT_1024, L_HEAT_ICE_1024 = L_HEAT_1024, // 1.7+ + L_SPECIAL_1024, // 1.7+ L_ZOOM_512, + L_LAND_512, // 1.6- L_ZOOM_256, - L_ADD_ISLAND_256, - L_ADD_MUSHROOM_256, - L_DEEP_OCEAN_256, + L_LAND_256, L_ADD_ISLAND_256 = L_LAND_256, + L_MUSHROOM_256, L_ADD_MUSHROOM_256 = L_MUSHROOM_256, + L_DEEP_OCEAN_256, // 1.7+ L_BIOME_256, + L_BAMBOO_256, L14_BAMBOO_256 = L_BAMBOO_256, // 1.14+ L_ZOOM_128, L_ZOOM_64, L_BIOME_EDGE_64, - L_RIVER_INIT_256, + L_NOISE_256, L_RIVER_INIT_256 = L_NOISE_256, L_ZOOM_128_HILLS, L_ZOOM_64_HILLS, L_HILLS_64, - L_RARE_BIOME_64, + L_SUNFLOWER_64, L_RARE_BIOME_64 = L_SUNFLOWER_64, // 1.7+ L_ZOOM_32, - L_ADD_ISLAND_32, + L_LAND_32, L_ADD_ISLAND_32 = L_LAND_32, L_ZOOM_16, L_SHORE_16, - L_RIVER_BIOME_16, // MC 1.6 + L_SWAMP_RIVER_16, // 1.6- L_ZOOM_8, L_ZOOM_4, L_SMOOTH_4, @@ -50,20 +53,16 @@ enum L_RIVER_4, L_SMOOTH_4_RIVER, L_RIVER_MIX_4, - L_VORONOI_ZOOM_1, + L_OCEAN_TEMP_256, L13_OCEAN_TEMP_256 = L_OCEAN_TEMP_256, // 1.13+ + L_ZOOM_128_OCEAN, L13_ZOOM_128 = L_ZOOM_128_OCEAN, // 1.13+ + L_ZOOM_64_OCEAN, L13_ZOOM_64 = L_ZOOM_64_OCEAN, // 1.13+ + L_ZOOM_32_OCEAN, L13_ZOOM_32 = L_ZOOM_32_OCEAN, // 1.13+ + L_ZOOM_16_OCEAN, L13_ZOOM_16 = L_ZOOM_16_OCEAN, // 1.13+ + L_ZOOM_8_OCEAN, L13_ZOOM_8 = L_ZOOM_8_OCEAN, // 1.13+ + L_ZOOM_4_OCEAN, L13_ZOOM_4 = L_ZOOM_4_OCEAN, // 1.13+ + L_OCEAN_MIX_4, L13_OCEAN_MIX_4 = L_OCEAN_MIX_4, // 1.13+ - // 1.13 layers - L13_OCEAN_TEMP_256, - L13_ZOOM_128, - L13_ZOOM_64, - L13_ZOOM_32, - L13_ZOOM_16, - L13_ZOOM_8, - L13_ZOOM_4, - L13_OCEAN_MIX_4, - - // 1.14 layers - L14_BAMBOO_256, + L_VORONOI_1, L_VORONOI_ZOOM_1 = L_VORONOI_1, // largeBiomes layers L_ZOOM_LARGE_BIOME_A, @@ -76,13 +75,14 @@ enum STRUCT(LayerStack) { Layer layers[L_NUM]; - Layer *entry_1; // entry layer, scale (1:1) [L_VORONOI_ZOOM_1] - Layer *entry_4; // entry layer, scale (1:4) [L_RIVER_MIX_4|L13_OCEAN_MIX_4] + Layer *entry_1; // entry scale (1:1) [L_VORONOI_1] + Layer *entry_4; // entry scale (1:4) [L_RIVER_MIX_4|L_OCEAN_MIX_4] + Layer *shore_16; // useful entry for (1:16) [L_SHORE_16] + Layer *hills_64; // useful entry for (1:64) [L_HILLS_64|L_SUNFLOWER_64] + Layer *biome_256; // useful entry for (1:256) [L_BIOME_256|L_BAMBOO_256] PerlinNoise oceanRnd; }; -typedef int (*mapfunc_t)(const Layer *, int *, int, int, int, int); - #ifdef __cplusplus extern "C" @@ -108,7 +108,7 @@ int *allocCache(const Layer *layer, int sizeX, int sizeZ); /* Set up custom layers. */ -Layer *setupLayer(LayerStack *g, int layerId, mapfunc_t map, int mc, +Layer *setupLayer(LayerStack *g, int layerId, mapfunc_t *map, int mc, int8_t zoom, int8_t edge, int saltbase, Layer *p, Layer *p2); /* Sets the world seed for the generator */ @@ -123,119 +123,6 @@ void applySeed(LayerStack *g, int64_t seed); int genArea(const Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight); - -/******************************** BIOME TABLES ********************************* - * The biome tables below are lists of the biomes that can be present at some - * notable layers. Of cause, layers that are applied later in the hierarchy will - * also contain these biomes. - */ - - -//============================================================================== -// MC Biome Tables -//============================================================================== - -/* L_ADD_MUSHROOM_ISLAND_256 and L_DEEP_OCEAN_256 - * add the mushroom_fields and deep_ocean biomes respectively, however the rest of - * the biomes are incomplete and are better described by temperature categories - * with special modifications bits. - */ - -// BIOMES_L_BIOME_256: Changes temperature to weighted biomes: -// Warm -> [desert, desert, desert, savanna, savanna, plains] -// Warm,special -> [badlands_plateau, wooded_badlands_plateau, wooded_badlands_plateau] -// Lush -> [forest, dark_forest, mountains, plains, birch_forest, swamp] -// Lush,special -> [jungle] -// Cold -> [forest, mountains, taiga, plains] -// Cold,special -> [giant_tree_taiga] -// Freezing -> [snowy_tundra, snowy_tundra, snowy_tundra, snowy_taiga] -static const int BIOMES_L_BIOME_256[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, /*river, hell, sky,*/ // 0-9 - /*frozen_ocean, frozen_river,*/ snowy_tundra, /*snowy_mountains,*/ mushroom_fields, /*mushroom_field_shore, beach, desert_hills, wooded_hills, taiga_hills,*/ // 10-19 - /*mountain_edge,*/ jungle, /*jungle_hills, jungleEdge,*/ deep_ocean, /*stone_shore, snowy_beach,*/ birch_forest, /*birch_forest_hills,*/ dark_forest, // 20-29 - snowy_taiga, /*snowy_taiga_hills,*/ giant_tree_taiga, /*giant_tree_taiga_hills, wooded_mountains,*/ savanna, /*savanna_plateau, badlands,*/ wooded_badlands_plateau, badlands_plateau, // 30-39 -}; - -// Introduces biomes: jungle_edge, wooded_mountains, badlands -// Inherits new biomes: bamboo_jungle -static const int BIOMES_L_BIOME_EDGE_64[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, /*river, hell, sky,*/ // 0-9 - /*frozen_ocean, frozen_river,*/ snowy_tundra, /*snowy_mountains,*/ mushroom_fields, /*mushroom_field_shore, beach, desert_hills, wooded_hills, taiga_hills,*/ // 10-19 - /*mountain_edge,*/ jungle, /*jungle_hills,*/ jungle_edge, deep_ocean, /*stone_shore, snowy_beach,*/ birch_forest, /*birch_forest_hills,*/ dark_forest, // 20-29 - snowy_taiga, /*snowy_taiga_hills,*/ giant_tree_taiga, /*giant_tree_taiga_hills,*/ wooded_mountains, savanna, /*savanna_plateau,*/ badlands, wooded_badlands_plateau, badlands_plateau, // 30-39 - bamboo_jungle, // 168 -}; - -// Introduces biomes: snowy_mountains, desert_hills, wooded_hills, taiga_hills, -// jungle_hills, birch_forest_hills, snowy_taiga_hills, giant_tree_taiga_hills, savanna_plateau, -// bamboo_jungle_hills -// and all 21 mutated biomes -static const int BIOMES_L_HILLS_64[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, /*river, hell, sky,*/ // 0-9 - /*frozen_ocean, frozen_river,*/ snowy_tundra, snowy_mountains, mushroom_fields, /*mushroom_field_shore, beach,*/ desert_hills, wooded_hills, taiga_hills, // 10-19 - /*mountain_edge,*/ jungle, jungle_hills, jungle_edge, deep_ocean, /*stone_shore, snowy_beach,*/ birch_forest, birch_forest_hills, dark_forest, // 20-29 - snowy_taiga, snowy_taiga_hills, giant_tree_taiga, giant_tree_taiga_hills, wooded_mountains, savanna, savanna_plateau, badlands, wooded_badlands_plateau, badlands_plateau, // 30-39 - - // Modified variants... - plains+128, desert+128, mountains+128, forest+128, taiga+128, swamp+128, - snowy_tundra+128, jungle+128, jungleEdge+128, birch_forest+128, birch_forest_hills+128, dark_forest+128, - snowy_taiga+128, giant_tree_taiga+128, giant_tree_taiga_hills+128, wooded_mountains+128, savanna+128, savanna_plateau+128, badlands+128, wooded_badlands_plateau+128, badlands_plateau+128, - - bamboo_jungle, bamboo_jungle_hills, // 168, 169 -}; - -// Introduces biomes: mushroom_field_shore, beach, stone_shore, snowy_beach -// Inherits new biiomes: sunflower_plains -static const int BIOMES_L_SHORE_16[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, /*river, hell, sky,*/ // 0-9 - /*frozen_ocean, frozen_river,*/ snowy_tundra, snowy_mountains, mushroom_fields, mushroom_field_shore, beach, desert_hills, wooded_hills, taiga_hills, // 10-19 - /*mountain_edge,*/ jungle, jungle_hills, jungle_edge, deep_ocean, stone_shore, snowy_beach, birch_forest, birch_forest_hills, dark_forest, // 20-29 - snowy_taiga, snowy_taiga_hills, giant_tree_taiga, giant_tree_taiga_hills, wooded_mountains, savanna, savanna_plateau, badlands, wooded_badlands_plateau, badlands_plateau, // 30-39 - // Modified variants... - plains+128, desert+128, mountains+128, forest+128, taiga+128, swamp+128, - snowy_tundra+128, jungle+128, jungleEdge+128, birch_forest+128, birch_forest_hills+128, dark_forest+128, - snowy_taiga+128, giant_tree_taiga+128, giant_tree_taiga_hills+128, wooded_mountains+128, savanna+128, savanna_plateau+128, badlands+128, wooded_badlands_plateau+128, badlands_plateau+128, - - bamboo_jungle, bamboo_jungle_hills, // 168, 169 -}; - -// Merges the river branch and adds frozen_river biome -static const int BIOMES_L_RIVER_MIX_4[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, river, /*hell, sky,*/ // 0-9 - /*frozen_ocean,*/ frozen_river, snowy_tundra, snowy_mountains, mushroom_fields, mushroom_field_shore, beach, desert_hills, wooded_hills, taiga_hills, // 10-19 - /*mountain_edge,*/ jungle, jungle_hills, jungle_edge, deep_ocean, stone_shore, snowy_beach, birch_forest, birch_forest_hills, dark_forest, // 20-29 - snowy_taiga, snowy_taiga_hills, giant_tree_taiga, giant_tree_taiga_hills, wooded_mountains, savanna, savanna_plateau, badlands, wooded_badlands_plateau, badlands_plateau, // 30-39 - // Modified variants... - plains+128, desert+128, mountains+128, forest+128, taiga+128, swamp+128, - snowy_tundra+128, jungle+128, jungleEdge+128, birch_forest+128, birch_forest_hills+128, dark_forest+128, - snowy_taiga+128, giant_tree_taiga+128, giant_tree_taiga_hills+128, wooded_mountains+128, savanna+128, savanna_plateau+128, badlands+128, wooded_badlands_plateau+128, badlands_plateau+128, - - bamboo_jungle, bamboo_jungle_hills, // 168, 169 -}; - -// Merges ocean variants -static const int BIOMES_L13_OCEAN_MIX_4[] = -{ - ocean, plains, desert, mountains, forest, taiga, swamp, river, /*hell, sky,*/ // 0-9 - frozen_ocean, frozen_river, snowy_tundra, snowy_mountains, mushroom_fields, mushroom_field_shore, beach, desert_hills, wooded_hills, taiga_hills, // 10-19 - /*mountain_edge,*/ jungle, jungle_hills, jungle_edge, deep_ocean, stone_shore, snowy_beach, birch_forest, birch_forest_hills, dark_forest, // 20-29 - snowy_taiga, snowy_taiga_hills, giant_tree_taiga, giant_tree_taiga_hills, wooded_mountains, savanna, savanna_plateau, badlands, wooded_badlands_plateau, badlands_plateau, // 30-39 - /*skyIslandLow, skyIslandMedium, skyIslandHigh, skyIslandBarren,*/ warm_ocean, lukewarm_ocean, cold_ocean, /*deep_warm_ocean,*/ deep_lukewarm_ocean, deep_cold_ocean, // 40-49 - deep_frozen_ocean, - // Modified variants... - plains+128, desert+128, mountains+128, forest+128, taiga+128, swamp+128, - snowy_tundra+128, jungle+128, jungleEdge+128, birch_forest+128, birch_forest_hills+128, dark_forest+128, - snowy_taiga+128, giant_tree_taiga+128, giant_tree_taiga_hills+128, wooded_mountains+128, savanna+128, savanna_plateau+128, badlands+128, wooded_badlands_plateau+128, badlands_plateau+128, - - bamboo_jungle, bamboo_jungle_hills, // 168, 169 -}; - - #ifdef __cplusplus } #endif diff --git a/layers.c b/layers.c index c74c7c8..d97ca02 100644 --- a/layers.c +++ b/layers.c @@ -11,16 +11,47 @@ int biomeExists(int mc, int id) { - // TODO: version dependence - (void) mc; switch (id) { - case ocean...deep_frozen_ocean: - case the_void: - case sunflower_plains...modified_badlands_plateau: - case bamboo_jungle...bamboo_jungle_hills: - case soul_sand_valley...basalt_deltas: + case ocean...mountain_edge: return 1; + case jungle...jungle_hills: + return mc >= MC_1_2; + case jungle_edge...badlands_plateau: + return mc >= MC_1_7; + case small_end_islands...end_barrens: + return mc >= MC_1_9; + case warm_ocean...deep_frozen_ocean: + return mc >= MC_1_13; + case the_void: + return mc >= MC_1_9; + case sunflower_plains: + case desert_lakes: + case gravelly_mountains: + case flower_forest: + case taiga_mountains: + case swamp_hills: + case ice_spikes: + case modified_jungle: + case modified_jungle_edge: + case tall_birch_forest: + case tall_birch_hills: + case dark_forest_hills: + case snowy_taiga_mountains: + case giant_spruce_taiga: + case giant_spruce_taiga_hills: + case modified_gravelly_mountains: + case shattered_savanna: + case shattered_savanna_plateau: + case eroded_badlands: + case modified_wooded_badlands_plateau: + case modified_badlands_plateau: + return mc >= MC_1_7; + case bamboo_jungle: + case bamboo_jungle_hills: + return mc >= MC_1_14; + case soul_sand_valley...basalt_deltas: + return mc >= MC_1_16; default: return 0; } @@ -28,24 +59,28 @@ int biomeExists(int mc, int id) int isOverworld(int mc, int id) { - // TODO: <= MC 1.6 + if (!biomeExists(mc, id)) + return 0; + switch (id) { - case ocean...river: - return 1; + case nether_wastes: + case the_end: + return 0; case frozen_ocean: - return mc >= MC_1_13; - case frozen_river...badlands_plateau: - return id != mountain_edge; - case warm_ocean...deep_frozen_ocean: - return mc >= MC_1_13 && id != deep_warm_ocean; - case sunflower_plains...modified_badlands_plateau: - return id != tall_birch_hills || mc < MC_1_9 || mc > MC_1_10; - case bamboo_jungle...bamboo_jungle_hills: - return mc >= MC_1_14; - default: + return mc <= MC_1_6 || mc >= MC_1_13; + case mountain_edge: + return mc <= MC_1_6; + case small_end_islands...end_barrens: + case deep_warm_ocean: + case the_void: + return 0; + case tall_birch_hills: + return mc <= MC_1_8 || mc >= MC_1_11; + case soul_sand_valley...basalt_deltas: return 0; } + return 1; } int getMutated(int mc, int id) @@ -186,7 +221,7 @@ int getCategory(int mc, int id) return taiga; default: - return the_void; + return none; } } @@ -196,8 +231,6 @@ int areSimilar(int mc, int id1, int id2) if (mc <= MC_1_15) { - // before 1.16 if one id1 was badland_plateau and id2 a mesa variant - // they would compare as false if (id1 == wooded_badlands_plateau || id1 == badlands_plateau) return id2 == wooded_badlands_plateau || id2 == badlands_plateau; } @@ -789,8 +822,13 @@ int mapEnd(const EndNoise *en, int *out, int x, int z, int w, int h) // Layers //============================================================================== +// convenience function used in several layers +static inline int isAny4(int id, int a, int b, int c, int d) +{ + return id == a || id == b || id == c || id == d; +} -int mapIsland(const Layer * l, int * out, int x, int z, int w, int h) +int mapContinent(const Layer * l, int * out, int x, int z, int w, int h) { int64_t ss = l->startSeed; int64_t cs; @@ -813,7 +851,7 @@ int mapIsland(const Layer * l, int * out, int x, int z, int w, int h) return 0; } -int mapZoomIsland(const Layer * l, int * out, int x, int z, int w, int h) +int mapZoomFuzzy(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x >> 1; int pZ = z >> 1; @@ -996,7 +1034,7 @@ int mapZoom(const Layer * l, int * out, int x, int z, int w, int h) } /// This is the most performance crittical layer, especially for getBiomeAtPos. -int mapAddIsland(const Layer * l, int * out, int x, int z, int w, int h) +int mapLand(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1112,7 +1150,7 @@ int mapAddIsland(const Layer * l, int * out, int x, int z, int w, int h) return 0; } -int mapAddIsland16(const Layer * l, int * out, int x, int z, int w, int h) +int mapLand16(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1208,7 +1246,7 @@ int mapAddIsland16(const Layer * l, int * out, int x, int z, int w, int h) } -int mapRemoveTooMuchOcean(const Layer * l, int * out, int x, int z, int w, int h) +int mapIsland(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1230,13 +1268,13 @@ int mapRemoveTooMuchOcean(const Layer * l, int * out, int x, int z, int w, int h int v11 = out[i+1 + (j+1)*pW]; out[i + j*w] = v11; - if (out[i+1 + (j+0)*pW] != 0) continue; - if (out[i+2 + (j+1)*pW] != 0) continue; - if (out[i+0 + (j+1)*pW] != 0) continue; - if (out[i+1 + (j+2)*pW] != 0) continue; - - if (v11 == 0) + if (v11 == Oceanic) { + if (out[i+1 + (j+0)*pW] != Oceanic) continue; + if (out[i+2 + (j+1)*pW] != Oceanic) continue; + if (out[i+0 + (j+1)*pW] != Oceanic) continue; + if (out[i+1 + (j+2)*pW] != Oceanic) continue; + cs = getChunkSeed(ss, i+x, j+z); if (mcFirstIsZero(cs, 2)) { @@ -1249,7 +1287,7 @@ int mapRemoveTooMuchOcean(const Layer * l, int * out, int x, int z, int w, int h return 0; } -int mapAddSnow16(const Layer * l, int * out, int x, int z, int w, int h) +int mapSnow16(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1282,7 +1320,7 @@ int mapAddSnow16(const Layer * l, int * out, int x, int z, int w, int h) return 0; } -int mapAddSnow(const Layer * l, int * out, int x, int z, int w, int h) +int mapSnow(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1326,7 +1364,7 @@ int mapAddSnow(const Layer * l, int * out, int x, int z, int w, int h) } -int mapCoolWarm(const Layer * l, int * out, int x, int z, int w, int h) +int mapCool(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1344,16 +1382,16 @@ int mapCoolWarm(const Layer * l, int * out, int x, int z, int w, int h) { int v11 = out[i+1 + (j+1)*pW]; - if (v11 == 1) + if (v11 == Warm) { int v10 = out[i+1 + (j+0)*pW]; int v21 = out[i+2 + (j+1)*pW]; int v01 = out[i+0 + (j+1)*pW]; int v12 = out[i+1 + (j+2)*pW]; - if (v10 == 3 || v10 == 4 || v21 == 3 || v21 == 4 || v01 == 3 || v01 == 4 || v12 == 3 || v12 == 4) + if (isAny4(Cold, v10, v21, v01, v12) || isAny4(Freezing, v10, v21, v01, v12)) { - v11 = 2; + v11 = Lush; } } @@ -1365,7 +1403,7 @@ int mapCoolWarm(const Layer * l, int * out, int x, int z, int w, int h) } -int mapHeatIce(const Layer * l, int * out, int x, int z, int w, int h) +int mapHeat(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1383,16 +1421,16 @@ int mapHeatIce(const Layer * l, int * out, int x, int z, int w, int h) { int v11 = out[i+1 + (j+1)*pW]; - if (v11 == 4) + if (v11 == Freezing) { int v10 = out[i+1 + (j+0)*pW]; int v21 = out[i+2 + (j+1)*pW]; int v01 = out[i+0 + (j+1)*pW]; int v12 = out[i+1 + (j+2)*pW]; - if (v10 == 1 || v10 == 2 || v21 == 1 || v21 == 2 || v01 == 1 || v01 == 2 || v12 == 1 || v12 == 2) + if (isAny4(Warm, v10, v21, v01, v12) || isAny4(Lush, v10, v21, v01, v12)) { - v11 = 3; + v11 = Cold; } } @@ -1438,7 +1476,7 @@ int mapSpecial(const Layer * l, int * out, int x, int z, int w, int h) } -int mapAddMushroomIsland(const Layer * l, int * out, int x, int z, int w, int h) +int mapMushroom(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; int pZ = z - 1; @@ -1625,7 +1663,7 @@ int mapBiome(const Layer * l, int * out, int x, int z, int w, int h) } -int mapRiverInit(const Layer * l, int * out, int x, int z, int w, int h) +int mapNoise(const Layer * l, int * out, int x, int z, int w, int h) { int err = l->p->getMap(l->p, out, x, z, w, h); if U(err != 0) @@ -1657,7 +1695,7 @@ int mapRiverInit(const Layer * l, int * out, int x, int z, int w, int h) } -int mapAddBamboo(const Layer * l, int * out, int x, int z, int w, int h) +int mapBamboo(const Layer * l, int * out, int x, int z, int w, int h) { int err = l->p->getMap(l->p, out, x, z, w, h); if U(err != 0) @@ -1690,7 +1728,6 @@ static inline int replaceEdge(int *out, int idx, int mc, int v10, int v21, int v { if (id != baseID) return 0; - // areSimilar() has not changed behaviour for ids < 128, so use the faster variant if (areSimilar(mc, v10, baseID) && areSimilar(mc, v21, baseID) && areSimilar(mc, v01, baseID) && areSimilar(mc, v12, baseID)) out[idx] = id; @@ -1700,10 +1737,6 @@ static inline int replaceEdge(int *out, int idx, int mc, int v10, int v21, int v return 1; } -static int isAny4(int id, int a, int b, int c, int d) -{ - return id == a || id == b || id == c || id == d; -} int mapBiomeEdge(const Layer * l, int * out, int x, int z, int w, int h) { @@ -2062,7 +2095,7 @@ int mapSmooth(const Layer * l, int * out, int x, int z, int w, int h) } -int mapRareBiome(const Layer * l, int * out, int x, int z, int w, int h) +int mapSunflower(const Layer * l, int * out, int x, int z, int w, int h) { int i, j; @@ -2106,7 +2139,6 @@ inline static int replaceOcean(int *out, int idx, int v10, int v21, int v01, int return 1; } - inline static int isAll4JFTO(int mc, int a, int b, int c, int d) { return @@ -2121,7 +2153,6 @@ inline static int isAny4Oceanic(int a, int b, int c, int d) return isOceanic(a) || isOceanic(b) || isOceanic(c) || isOceanic(d); } - int mapShore(const Layer * l, int * out, int x, int z, int w, int h) { int pX = x - 1; @@ -2161,16 +2192,16 @@ int mapShore(const Layer * l, int * out, int x, int z, int w, int h) if (mc <= MC_1_6) { - if (v11 != ocean && v11 != river && v11 != swamp && v11 != mountains) - { - if (isAny4(ocean, v10, v21, v01, v12)) - v11 = beach; - } - else if (v11 == mountains) + if (v11 == mountains) { if (v10 != mountains || v21 != mountains || v01 != mountains || v12 != mountains) v11 = mountain_edge; } + else if (v11 != ocean && v11 != river && v11 != swamp) + { + if (isAny4(ocean, v10, v21, v01, v12)) + v11 = beach; + } out[i + j*w] = v11; } else if (getCategory(mc, v11) == jungle) @@ -2187,7 +2218,7 @@ int mapShore(const Layer * l, int * out, int x, int z, int w, int h) out[i + j*w] = jungle_edge; } } - else if (v11 == mountains || v11 == wooded_mountains || v11 == mountain_edge) + else if (v11 == mountains || v11 == wooded_mountains /* || v11 == mountain_edge*/) { replaceOcean(out, i + j*w, v10, v21, v01, v12, v11, stone_shore); } @@ -2229,8 +2260,7 @@ int mapShore(const Layer * l, int * out, int x, int z, int w, int h) return 0; } -// only for 1.1 - 1.6 -int mapRiverInBiome(const Layer * l, int * out, int x, int z, int w, int h) +int mapSwampRiver(const Layer * l, int * out, int x, int z, int w, int h) { int i, j; @@ -2479,7 +2509,7 @@ static inline void getVoronoiCell(int64_t sha, int a, int b, int c, *z = (((s >> 24) & 1023) - 512) * 36; } -int mapVoronoiZoom(const Layer * l, int * out, int x, int z, int w, int h) +int mapVoronoi(const Layer * l, int * out, int x, int z, int w, int h) { x -= 2; z -= 2; @@ -2645,7 +2675,7 @@ int mapVoronoiZoom(const Layer * l, int * out, int x, int z, int w, int h) } -int mapVoronoiZoom114(const Layer * l, int * out, int x, int z, int w, int h) +int mapVoronoi114(const Layer * l, int * out, int x, int z, int w, int h) { x -= 2; z -= 2; diff --git a/layers.h b/layers.h index b039246..25064eb 100644 --- a/layers.h +++ b/layers.h @@ -151,9 +151,12 @@ STRUCT(DoublePerlinNoise) int octcnt; }; +struct Layer; +typedef int (mapfunc_t)(const struct Layer *, int *, int, int, int, int); + STRUCT(Layer) { - int (*getMap)(const Layer *, int *, int, int, int, int); + mapfunc_t *getMap; int8_t mc; // minecraft version int8_t zoom; // zoom factor of layer @@ -340,37 +343,37 @@ int isSnowy(int id); // Layers //============================================================================== -int mapIsland (const Layer *, int *, int, int, int, int); -int mapZoomIsland (const Layer *, int *, int, int, int, int); -int mapZoom (const Layer *, int *, int, int, int, int); -int mapAddIsland (const Layer *, int *, int, int, int, int); -int mapAddIsland16 (const Layer *, int *, int, int, int, int); -int mapRemoveTooMuchOcean (const Layer *, int *, int, int, int, int); -int mapAddSnow (const Layer *, int *, int, int, int, int); -int mapAddSnow16 (const Layer *, int *, int, int, int, int); -int mapCoolWarm (const Layer *, int *, int, int, int, int); -int mapHeatIce (const Layer *, int *, int, int, int, int); -int mapSpecial (const Layer *, int *, int, int, int, int); -int mapAddMushroomIsland (const Layer *, int *, int, int, int, int); -int mapDeepOcean (const Layer *, int *, int, int, int, int); -int mapBiome (const Layer *, int *, int, int, int, int); -int mapBiomeBE (const Layer *, int *, int, int, int, int); -int mapAddBamboo (const Layer *, int *, int, int, int, int); -int mapRiverInit (const Layer *, int *, int, int, int, int); -int mapBiomeEdge (const Layer *, int *, int, int, int, int); -int mapHills (const Layer *, int *, int, int, int, int); -int mapRiver (const Layer *, int *, int, int, int, int); -int mapSmooth (const Layer *, int *, int, int, int, int); -int mapRareBiome (const Layer *, int *, int, int, int, int); -int mapRiverInBiome (const Layer *, int *, int, int, int, int); -int mapShore (const Layer *, int *, int, int, int, int); -int mapRiverMix (const Layer *, int *, int, int, int, int); -int mapOceanTemp (const Layer *, int *, int, int, int, int); -int mapOceanMix (const Layer *, int *, int, int, int, int); +// old names +mapfunc_t mapContinent; // mapIsland +mapfunc_t mapZoomFuzzy; +mapfunc_t mapZoom; +mapfunc_t mapLand; // mapAddIsland +mapfunc_t mapLand16; +mapfunc_t mapIsland; // mapRemoveTooMuchOcean +mapfunc_t mapSnow; // mapAddSnow +mapfunc_t mapSnow16; +mapfunc_t mapCool; // mapCoolWarm +mapfunc_t mapHeat; // mapHeatIce +mapfunc_t mapSpecial; +mapfunc_t mapMushroom; // mapAddMushroomIsland +mapfunc_t mapDeepOcean; +mapfunc_t mapBiome; +mapfunc_t mapBamboo; // mapAddBamboo +mapfunc_t mapNoise; // mapRiverInit +mapfunc_t mapBiomeEdge; +mapfunc_t mapHills; +mapfunc_t mapRiver; +mapfunc_t mapSmooth; +mapfunc_t mapSunflower; // mapRareBiome +mapfunc_t mapShore; +mapfunc_t mapSwampRiver; +mapfunc_t mapRiverMix; +mapfunc_t mapOceanTemp; +mapfunc_t mapOceanMix; // final layer 1:1 -int mapVoronoiZoom (const Layer *, int *, int, int, int, int); -int mapVoronoiZoom114 (const Layer *, int *, int, int, int, int); +mapfunc_t mapVoronoi; // mapVoronoiZoom +mapfunc_t mapVoronoi114; // With 1.15 voronoi changed in preparation for 3D biome generation. // Biome generation now stops at scale 1:4 OceanMix and voronoi is just an diff --git a/tests.c b/tests.c index 342a33d..61c1fc8 100644 --- a/tests.c +++ b/tests.c @@ -70,13 +70,16 @@ int testBiomeGen1x1(const int *mc, const uint32_t *expect, int bits, int cnt) int main() { const int mc_vers[] = { - MC_1_16, MC_1_15, MC_1_12, MC_1_9, MC_1_7, MC_1_6, + MC_1_16, MC_1_15, MC_1_13, MC_1_12, MC_1_9, MC_1_7, + MC_1_6, }; const uint32_t b6_hashes[] = { - 0xde9a6574, 0x3a568a6d, 0xbc75e996, 0xe27a45a2, 0xbc75e996, 0x15b47206, + 0xde9a6574, 0x3a568a6d, 0x96c97323, 0xbc75e996, 0xe27a45a2, 0xbc75e996, + 0x15b47206, }; const uint32_t b10_hashes[] = { - 0xfdede71d, 0xca8005d7, 0xb3363967, 0x17e5592f, 0xb3363967, 0xa52e377c, + 0xfdede71d, 0xca8005d7, 0x399f7cc8, 0xb3363967, 0x17e5592f, 0xb3363967, + 0xa52e377c, }; const int testcnt = sizeof(mc_vers) / sizeof(int);