cubiomes/generator.c

258 lines
9.3 KiB
C
Raw Normal View History

2018-03-06 05:20:54 +08:00
#include "generator.h"
#include "layers.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void setupLayer(Layer *l, Layer *p, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h))
2018-03-06 05:20:54 +08:00
{
setBaseSeed(l, s);
l->p = p;
l->p2 = NULL;
l->getMap = getMap;
l->oceanRnd = NULL;
2018-03-06 05:20:54 +08:00
}
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h))
2018-03-06 05:20:54 +08:00
{
setBaseSeed(l, s);
l->p = p1;
l->p2 = p2;
l->getMap = getMap;
l->oceanRnd = NULL;
2018-03-06 05:20:54 +08:00
}
static void setupScale(Layer *l, int scale)
{
l->scale = scale;
int m = 1;
if (l->getMap == mapZoom) {
m = 2;
} else if (l->getMap == mapVoronoiZoom) {
m = 4;
}
if (l->p) {
setupScale(l->p, scale * m);
}
if (l->p2) {
setupScale(l->p2, scale * m);
}
}
2018-03-18 00:53:16 +08:00
2020-05-05 18:49:06 +08:00
static LayerStack setupGeneratorImpl(const int mcversion, const int largeBiomes)
2018-03-06 05:20:54 +08:00
{
2018-07-28 22:36:41 +08:00
if (biomes[plains].id == 0)
2018-03-06 05:20:54 +08:00
{
fprintf(stderr, "Warning: The biomes have to be initialised first using initBiomes() before any generator can be used.\n");
}
2018-03-18 00:53:16 +08:00
LayerStack g;
g.layerCnt = L_NUM;
g.layers = (Layer *) calloc(g.layerCnt, sizeof(Layer));
Layer *l = g.layers;
// LAYER PARENT SEED LAYER_FUNCTION
setupLayer(&l[L_ISLAND_4096], NULL, 1, mapIsland);
setupLayer(&l[L_ZOOM_2048], &l[L_ISLAND_4096], 2000, mapZoom);
setupLayer(&l[L_ADD_ISLAND_2048], &l[L_ZOOM_2048], 1, mapAddIsland);
setupLayer(&l[L_ZOOM_1024], &l[L_ADD_ISLAND_2048], 2001, mapZoom);
setupLayer(&l[L_ADD_ISLAND_1024A], &l[L_ZOOM_1024], 2, mapAddIsland);
setupLayer(&l[L_ADD_ISLAND_1024B], &l[L_ADD_ISLAND_1024A], 50, mapAddIsland);
setupLayer(&l[L_ADD_ISLAND_1024C], &l[L_ADD_ISLAND_1024B], 70, mapAddIsland);
setupLayer(&l[L_REMOVE_OCEAN_1024], &l[L_ADD_ISLAND_1024C], 2, mapRemoveTooMuchOcean);
setupLayer(&l[L_ADD_SNOW_1024], &l[L_REMOVE_OCEAN_1024], 2, mapAddSnow);
setupLayer(&l[L_ADD_ISLAND_1024D], &l[L_ADD_SNOW_1024], 3, mapAddIsland);
setupLayer(&l[L_COOL_WARM_1024], &l[L_ADD_ISLAND_1024D], 2, mapCoolWarm);
setupLayer(&l[L_HEAT_ICE_1024], &l[L_COOL_WARM_1024], 2, mapHeatIce);
setupLayer(&l[L_SPECIAL_1024], &l[L_HEAT_ICE_1024], 3, mapSpecial);
setupLayer(&l[L_ZOOM_512], &l[L_SPECIAL_1024], 2002, mapZoom);
setupLayer(&l[L_ZOOM_256], &l[L_ZOOM_512], 2003, mapZoom);
setupLayer(&l[L_ADD_ISLAND_256], &l[L_ZOOM_256], 4, mapAddIsland);
setupLayer(&l[L_ADD_MUSHROOM_256], &l[L_ADD_ISLAND_256], 5, mapAddMushroomIsland);
setupLayer(&l[L_DEEP_OCEAN_256], &l[L_ADD_MUSHROOM_256], 4, mapDeepOcean);
2018-03-06 05:20:54 +08:00
// biome layer chain
setupLayer(&l[L_BIOME_256], &l[L_DEEP_OCEAN_256], 200,
mcversion != MCBE ? mapBiome : mapBiomeBE);
2018-03-06 05:20:54 +08:00
if (mcversion <= MC_1_13)
setupLayer(&l[L_ZOOM_128], &l[L_BIOME_256], 1000, mapZoom);
else
2018-03-11 05:45:57 +08:00
{
setupLayer(&l[L14_BAMBOO_256], &l[L_BIOME_256], 1001, mapAddBamboo);
setupLayer(&l[L_ZOOM_128], &l[L14_BAMBOO_256], 1000, mapZoom);
2018-03-11 05:45:57 +08:00
}
setupLayer(&l[L_ZOOM_64], &l[L_ZOOM_128], 1001, mapZoom);
setupLayer(&l[L_BIOME_EDGE_64], &l[L_ZOOM_64], 1000, mapBiomeEdge);
2018-03-11 05:45:57 +08:00
// basic river layer chain, used to determine where hills generate
setupLayer(&l[L_RIVER_INIT_256], &l[L_DEEP_OCEAN_256], 100, mapRiverInit);
setupLayer(&l[L_ZOOM_128_HILLS], &l[L_RIVER_INIT_256], 1000, mapZoom);
setupLayer(&l[L_ZOOM_64_HILLS], &l[L_ZOOM_128_HILLS], 1001, mapZoom);
setupMultiLayer(&l[L_HILLS_64], &l[L_BIOME_EDGE_64], &l[L_ZOOM_64_HILLS], 1000,
(mcversion & 0xff) <= MC_1_12 ? mapHills : mapHills113);
setupLayer(&l[L_RARE_BIOME_64], &l[L_HILLS_64], 1001, mapRareBiome);
setupLayer(&l[L_ZOOM_32], &l[L_RARE_BIOME_64], 1000, mapZoom);
setupLayer(&l[L_ADD_ISLAND_32], &l[L_ZOOM_32], 3, mapAddIsland);
setupLayer(&l[L_ZOOM_16], &l[L_ADD_ISLAND_32], 1001, mapZoom);
setupLayer(&l[L_SHORE_16], &l[L_ZOOM_16], 1000, mapShore);
setupLayer(&l[L_ZOOM_8], &l[L_SHORE_16], 1002, mapZoom);
setupLayer(&l[L_ZOOM_4], &l[L_ZOOM_8], 1003, mapZoom);
2020-05-05 17:32:35 +08:00
2020-05-05 18:49:06 +08:00
if (largeBiomes != 0) {
setupLayer(&l[L_ZOOM_LARGE_BIOME_A], &l[L_ZOOM_4], 1004, mapZoom);
setupLayer(&l[L_ZOOM_LARGE_BIOME_B], &l[L_ZOOM_LARGE_BIOME_A], 1005, mapZoom);
setupLayer(&l[L_SMOOTH_4], &l[L_ZOOM_LARGE_BIOME_B], 1000, mapSmooth);
2020-05-05 17:32:35 +08:00
} else {
setupLayer(&l[L_SMOOTH_4], &l[L_ZOOM_4], 1000, mapSmooth);
2020-05-05 17:32:35 +08:00
}
2018-03-11 05:45:57 +08:00
// river layer chain
setupLayer(&l[L_ZOOM_128_RIVER], &l[L_RIVER_INIT_256], 1000, mapZoom);
setupLayer(&l[L_ZOOM_64_RIVER], &l[L_ZOOM_128_RIVER], 1001, mapZoom);
setupLayer(&l[L_ZOOM_32_RIVER], &l[L_ZOOM_64_RIVER], 1000, mapZoom);
setupLayer(&l[L_ZOOM_16_RIVER], &l[L_ZOOM_32_RIVER], 1001, mapZoom);
setupLayer(&l[L_ZOOM_8_RIVER], &l[L_ZOOM_16_RIVER], 1002, mapZoom);
setupLayer(&l[L_ZOOM_4_RIVER], &l[L_ZOOM_8_RIVER], 1003, mapZoom);
setupLayer(&l[L_RIVER_4], &l[L_ZOOM_4_RIVER], 1, mapRiver);
setupLayer(&l[L_SMOOTH_4_RIVER], &l[L_RIVER_4], 1000, mapSmooth);
setupMultiLayer(&l[L_RIVER_MIX_4], &l[L_SMOOTH_4], &l[L_SMOOTH_4_RIVER], 100, mapRiverMix);
if (mcversion <= MC_1_12)
2018-11-29 12:32:12 +08:00
{
setupLayer(&l[L_VORONOI_ZOOM_1], &l[L_RIVER_MIX_4], 10, mapVoronoiZoom);
}
else
{
// ocean variants
setupLayer(&l[L13_OCEAN_TEMP_256], NULL, 2, mapOceanTemp);
l[L13_OCEAN_TEMP_256].oceanRnd = (OceanRnd *) malloc(sizeof(OceanRnd));
setupLayer(&l[L13_ZOOM_128], &l[L13_OCEAN_TEMP_256], 2001, mapZoom);
setupLayer(&l[L13_ZOOM_64], &l[L13_ZOOM_128], 2002, mapZoom);
setupLayer(&l[L13_ZOOM_32], &l[L13_ZOOM_64], 2003, mapZoom);
setupLayer(&l[L13_ZOOM_16], &l[L13_ZOOM_32], 2004, mapZoom);
setupLayer(&l[L13_ZOOM_8], &l[L13_ZOOM_16], 2005, mapZoom);
setupLayer(&l[L13_ZOOM_4], &l[L13_ZOOM_8], 2006, mapZoom);
setupMultiLayer(&l[L13_OCEAN_MIX_4], &l[L_RIVER_MIX_4], &l[L13_ZOOM_4], 100, mapOceanMix);
setupLayer(&l[L_VORONOI_ZOOM_1], &l[L13_OCEAN_MIX_4], 10, mapVoronoiZoom);
2018-11-29 12:32:12 +08:00
}
setupScale(&l[L_VORONOI_ZOOM_1], 1);
2018-11-29 12:32:12 +08:00
return g;
}
2020-05-05 18:49:06 +08:00
LayerStack setupGenerator(const int mcversion)
{
return setupGeneratorImpl(mcversion, 0);
}
LayerStack setupLargeBiomesGenerator(const int mcversion)
{
return setupGeneratorImpl(mcversion, 1);
}
2018-07-28 22:36:41 +08:00
void freeGenerator(LayerStack g)
{
int i;
for(i = 0; i < g.layerCnt; i++)
2018-07-28 22:36:41 +08:00
{
if (g.layers[i].oceanRnd != NULL)
free(g.layers[i].oceanRnd);
}
2018-03-11 05:45:57 +08:00
2018-07-28 22:36:41 +08:00
free(g.layers);
}
/* Recursively calculates the minimum buffer size required to generate an area
* of the specified size from the current layer onwards.
*/
2018-03-11 05:45:57 +08:00
static void getMaxArea(Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ)
2018-03-06 05:20:54 +08:00
{
2018-07-28 22:36:41 +08:00
if (layer == NULL)
2018-03-11 05:45:57 +08:00
return;
2018-03-06 05:20:54 +08:00
2018-07-28 22:36:41 +08:00
if (layer->getMap == mapZoom)
2018-03-06 05:20:54 +08:00
{
2018-03-11 05:45:57 +08:00
areaX = (areaX >> 1) + 2;
areaZ = (areaZ >> 1) + 2;
}
2018-07-28 22:36:41 +08:00
else if (layer->getMap == mapVoronoiZoom)
2018-03-11 05:45:57 +08:00
{
areaX = (areaX >> 2) + 2;
areaZ = (areaZ >> 2) + 2;
}
2018-07-28 22:36:41 +08:00
else if (layer->getMap == mapOceanMix)
{
areaX += 17;
areaZ += 17;
}
2018-03-11 05:45:57 +08:00
else
{
2018-07-28 22:36:41 +08:00
if (layer->getMap != mapNull &&
layer->getMap != mapSkip &&
layer->getMap != mapIsland &&
2018-03-11 05:45:57 +08:00
layer->getMap != mapSpecial &&
layer->getMap != mapBiome &&
layer->getMap != mapRiverInit &&
layer->getMap != mapRiverMix &&
layer->getMap != mapOceanTemp)
2018-03-06 05:20:54 +08:00
{
areaX += 2;
areaZ += 2;
}
}
2018-07-28 22:36:41 +08:00
if (areaX > *maxX) *maxX = areaX;
if (areaZ > *maxZ) *maxZ = areaZ;
2018-03-11 05:45:57 +08:00
getMaxArea(layer->p, areaX, areaZ, maxX, maxZ);
getMaxArea(layer->p2, areaX, areaZ, maxX, maxZ);
}
int calcRequiredBuf(Layer *layer, int areaX, int areaZ)
{
int maxX = areaX, maxZ = areaZ;
getMaxArea(layer, areaX, areaZ, &maxX, &maxZ);
return maxX * maxZ;
2018-03-06 05:20:54 +08:00
}
2018-07-28 22:36:41 +08:00
int *allocCache(Layer *layer, int sizeX, int sizeZ)
2018-03-06 05:20:54 +08:00
{
2018-07-28 22:36:41 +08:00
int size = calcRequiredBuf(layer, sizeX, sizeZ);
2018-07-28 22:36:41 +08:00
int *ret = (int *) malloc(sizeof(*ret)*size);
memset(ret, 0, sizeof(*ret)*size);
return ret;
2018-03-06 05:20:54 +08:00
}
2018-07-28 22:36:41 +08:00
2018-07-04 23:48:05 +08:00
void applySeed(LayerStack *g, int64_t seed)
2018-03-06 05:20:54 +08:00
{
2018-03-11 05:45:57 +08:00
// the seed has to be applied recursively
setWorldSeed(&g->layers[L_VORONOI_ZOOM_1], seed);
2018-03-06 05:20:54 +08:00
}
2018-03-18 00:53:16 +08:00
void genArea(Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight)
2018-03-06 05:20:54 +08:00
{
memset(out, 0, areaWidth*areaHeight*sizeof(*out));
2018-03-18 00:53:16 +08:00
layer->getMap(layer, out, areaX, areaZ, areaWidth, areaHeight);
2018-03-06 05:20:54 +08:00
}