mirror of
https://github.com/Cubitect/cubiomes.git
synced 2025-08-03 09:46:41 -04:00
Added Pale Garden biome and Small End Islands
* added pale_garden biome with 1.21.3 (version TBA) * added small end islands and better end surface generation (#117) * added linked end gateway finder (#117) * fixed inaccurate End generation at large distances from 0,0 * fixed incorrect biome in outer end rings * fixed incorrect biome area size (#122)
This commit is contained in:
parent
0af31b4e7e
commit
e49c8c561b
109
biomenoise.c
109
biomenoise.c
@ -74,9 +74,11 @@ double sampleSurfaceNoiseBetween(const SurfaceNoise *sn, int x, int y, int z,
|
||||
dy = y * sy;
|
||||
|
||||
vmin += samplePerlin(&sn->octmin.octaves[i], dx, dy, dz, sy, dy) * amp;
|
||||
if (vmin - amp > noiseMax) return noiseMax;
|
||||
vmax += samplePerlin(&sn->octmax.octaves[i], dx, dy, dz, sy, dy) * amp;
|
||||
if (vmax + amp < noiseMin) return noiseMin;
|
||||
if (vmin - amp > noiseMax && vmax - amp > noiseMax)
|
||||
return noiseMax;
|
||||
if (vmin + amp < noiseMin && vmax + amp < noiseMin)
|
||||
return noiseMin;
|
||||
|
||||
amp *= 0.5;
|
||||
persist *= 2.0;
|
||||
@ -436,7 +438,10 @@ int mapEndBiome(const EndNoise *en, int *out, int x, int z, int w, int h)
|
||||
uint16_t v = 0;
|
||||
if (rsq > 4096 && sampleSimplex2D(&en->perlin, rx, rz) < -0.9f)
|
||||
{
|
||||
v = (llabs(rx) * 3439 + llabs(rz) * 147) % 13 + 9;
|
||||
//v = (llabs(rx) * 3439 + llabs(rz) * 147) % 13 + 9;
|
||||
v = (unsigned int)(
|
||||
fabsf((float)rx) * 3439.0f + fabsf((float)rz) * 147.0f
|
||||
) % 13 + 9;
|
||||
v *= v;
|
||||
}
|
||||
hmap[(int64_t)j*hw+i] = v;
|
||||
@ -457,12 +462,12 @@ int mapEndBiome(const EndNoise *en, int *out, int x, int z, int w, int h)
|
||||
{
|
||||
hx = 2*hx + 1;
|
||||
hz = 2*hz + 1;
|
||||
if (en->mc >= MC_1_14)
|
||||
{
|
||||
if (en->mc > MC_1_13)
|
||||
{ // add outer end rings
|
||||
rsq = hx * hx + hz * hz;
|
||||
if ((int)rsq < 0)
|
||||
{
|
||||
out[j*w+i] = small_end_islands;
|
||||
out[j*w+i] = end_barrens;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -529,7 +534,10 @@ float getEndHeightNoise(const EndNoise *en, int x, int z, int range)
|
||||
uint16_t v = 0;
|
||||
if (rsq > 4096 && sampleSimplex2D(&en->perlin, rx, rz) < -0.9f)
|
||||
{
|
||||
v = (llabs(rx) * 3439 + llabs(rz) * 147) % 13 + 9;
|
||||
//v = (llabs(rx) * 3439 + llabs(rz) * 147) % 13 + 9;
|
||||
v = (unsigned int)(
|
||||
fabsf((float)rx) * 3439.0f + fabsf((float)rz) * 147.0f
|
||||
) % 13 + 9;
|
||||
rx = (oddx - i * 2);
|
||||
rz = (oddz - j * 2);
|
||||
rsq = rx*rx + rz*rz;
|
||||
@ -546,28 +554,9 @@ float getEndHeightNoise(const EndNoise *en, int x, int z, int range)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define END_NOISE_COL_YMIN 2
|
||||
#define END_NOISE_COL_YMAX 18
|
||||
#define END_NOISE_COL_SIZE (END_NOISE_COL_YMAX - END_NOISE_COL_YMIN + 1)
|
||||
|
||||
void sampleNoiseColumnEnd(double column[], const SurfaceNoise *sn,
|
||||
const EndNoise *en, int x, int z, int colymin, int colymax)
|
||||
{
|
||||
double depth = getEndHeightNoise(en, x, z, 0) - 8.0f;
|
||||
int y;
|
||||
for (y = colymin; y <= colymax; y++)
|
||||
{
|
||||
double noise = sampleSurfaceNoise(sn, x, y, z);
|
||||
noise += depth; // falloff for the End is just the depth
|
||||
// clamp top and bottom slides from End settings
|
||||
noise = clampedLerp((32 + 46 - y) / 64.0, -3000, noise);
|
||||
noise = clampedLerp((y - 1) / 7.0, -30, noise);
|
||||
column[y - colymin] = noise;
|
||||
}
|
||||
}
|
||||
|
||||
void sampleNoiseColumnEndFull(double column[END_NOISE_COL_SIZE],
|
||||
const SurfaceNoise *sn, const EndNoise *en, int x, int z)
|
||||
void sampleNoiseColumnEnd(double column[],
|
||||
const SurfaceNoise *sn, const EndNoise *en, int x, int z,
|
||||
int colymin, int colymax)
|
||||
{
|
||||
// clamped (32 + 46 - y) / 64.0
|
||||
static const double upper_drop[] = {
|
||||
@ -583,9 +572,21 @@ void sampleNoiseColumnEndFull(double column[END_NOISE_COL_SIZE],
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 8-15
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 16-23
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 24-31
|
||||
1.0 // 32
|
||||
1.0, // 32
|
||||
};
|
||||
|
||||
int y;
|
||||
if (en->mc > MC_1_13)
|
||||
{ // add outer end rings
|
||||
uint64_t rsq = (uint64_t) x * x + (uint64_t) z * z;
|
||||
if ((int)rsq < 0)
|
||||
{
|
||||
for (y = colymin; y <= colymax; y++)
|
||||
column[y - colymin] = nan("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// depth is between [-108, +72]
|
||||
// noise is between [-128, +128]
|
||||
// for a sold block we need the upper drop as:
|
||||
@ -595,23 +596,18 @@ void sampleNoiseColumnEndFull(double column[END_NOISE_COL_SIZE],
|
||||
// (72 + 128) * l - 30 * (1-l) > 0 => lower_drop = l > 3/23
|
||||
// which occurs at y = 3 for the lowest relevant noise cell
|
||||
|
||||
// in terms of the depth this becomes:
|
||||
// l > 30 / (103 + depth)
|
||||
|
||||
double depth = getEndHeightNoise(en, x, z, 0) - 8.0f;
|
||||
int y;
|
||||
for (y = END_NOISE_COL_YMIN; y <= END_NOISE_COL_YMAX; y++)
|
||||
for (y = colymin; y <= colymax; y++)
|
||||
{
|
||||
if (lower_drop[y] * (103.0 + depth) < 30)
|
||||
{
|
||||
column[y - END_NOISE_COL_YMIN] = -30;
|
||||
if (lower_drop[y] == 0.0) {
|
||||
column[y - colymin] = -30;
|
||||
continue;
|
||||
}
|
||||
double noise = sampleSurfaceNoiseBetween(sn, x, y, z, -128, 128);
|
||||
double noise = sampleSurfaceNoiseBetween(sn, x, y, z, -128, +128);
|
||||
double clamped = noise + depth;
|
||||
clamped = lerp(upper_drop[y], -3000, clamped);
|
||||
clamped = lerp(lower_drop[y], -30, clamped);
|
||||
column[y - END_NOISE_COL_YMIN] = clamped;
|
||||
column[y - colymin] = clamped;
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,7 +646,7 @@ int getSurfaceHeight(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getSurfaceHeightEnd(int mc, uint64_t seed, int x, int z)
|
||||
int getEndSurfaceHeight(int mc, uint64_t seed, int x, int z)
|
||||
{
|
||||
EndNoise en;
|
||||
setEndSeed(&en, mc, seed);
|
||||
@ -678,14 +674,17 @@ int getSurfaceHeightEnd(int mc, uint64_t seed, int x, int z)
|
||||
return getSurfaceHeight(ncol00, ncol01, ncol10, ncol11, y0, y1, 4, dx, dz);
|
||||
}
|
||||
|
||||
int mapSurfaceHeightEnd(const EndNoise *en, const SurfaceNoise *sn, float *y,
|
||||
int x, int z, int w, int h, int scale)
|
||||
int mapEndSurfaceHeight(float *y, const EndNoise *en, const SurfaceNoise *sn,
|
||||
int x, int z, int w, int h, int scale, int ymin)
|
||||
{
|
||||
if (scale != 1 && scale != 2 && scale != 4 && scale != 8)
|
||||
return 1;
|
||||
|
||||
enum { YSIZ = END_NOISE_COL_SIZE };
|
||||
|
||||
int y0 = ymin >> 2;
|
||||
if (y0 < 2) y0 = 2;
|
||||
if (y0 > 17) y0 = 17;
|
||||
int y1 = 18;
|
||||
int yn = y1 - y0 + 1;
|
||||
double cellmid = scale > 1 ? scale / 16.0 : 0;
|
||||
int cellsiz = 8 / scale;
|
||||
int cx = floordiv(x, cellsiz);
|
||||
@ -693,13 +692,13 @@ int mapSurfaceHeightEnd(const EndNoise *en, const SurfaceNoise *sn, float *y,
|
||||
int cw = floordiv(x + w - 1, cellsiz) - cx + 2;
|
||||
int i, j;
|
||||
|
||||
double *buf = malloc(sizeof(double) * YSIZ * cw * 2);
|
||||
double *buf = malloc(sizeof(double) * yn * cw * 2);
|
||||
double *ncol[2];
|
||||
ncol[0] = buf;
|
||||
ncol[1] = buf + YSIZ * cw;
|
||||
ncol[1] = buf + yn * cw;
|
||||
|
||||
for (i = 0; i < cw; i++)
|
||||
sampleNoiseColumnEndFull(ncol[1]+i*YSIZ, sn, en, cx+i, cz+0);
|
||||
sampleNoiseColumnEnd(ncol[1]+i*yn, sn, en, cx+i, cz+0, y0, y1);
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
@ -711,7 +710,7 @@ int mapSurfaceHeightEnd(const EndNoise *en, const SurfaceNoise *sn, float *y,
|
||||
ncol[0] = ncol[1];
|
||||
ncol[1] = tmp;
|
||||
for (i = 0; i < cw; i++)
|
||||
sampleNoiseColumnEndFull(ncol[1]+i*YSIZ, sn, en, cx+i, cj+1);
|
||||
sampleNoiseColumnEnd(ncol[1]+i*yn, sn, en, cx+i, cj+1, y0, y1);
|
||||
}
|
||||
|
||||
for (i = 0; i < w; i++)
|
||||
@ -720,10 +719,10 @@ int mapSurfaceHeightEnd(const EndNoise *en, const SurfaceNoise *sn, float *y,
|
||||
int di = x + i - ci * cellsiz;
|
||||
double dx = di / (double) cellsiz + cellmid;
|
||||
double dz = dj / (double) cellsiz + cellmid;
|
||||
double *ncol0 = ncol[0] + (ci - cx) * YSIZ;
|
||||
double *ncol1 = ncol[1] + (ci - cx) * YSIZ;
|
||||
y[j*w+i] = getSurfaceHeight(ncol0, ncol1, ncol0+YSIZ, ncol1+YSIZ,
|
||||
END_NOISE_COL_YMIN, END_NOISE_COL_YMAX, 4, dx, dz);
|
||||
double *ncol0 = ncol[0] + (ci - cx) * yn;
|
||||
double *ncol1 = ncol[1] + (ci - cx) * yn;
|
||||
y[j*w+i] = getSurfaceHeight(ncol0, ncol1, ncol0+yn, ncol1+yn,
|
||||
y0, y1, 4, dx, dz);
|
||||
}
|
||||
}
|
||||
|
||||
@ -802,9 +801,9 @@ int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha)
|
||||
out[j*r.sx+i] = the_end;
|
||||
continue;
|
||||
}
|
||||
else if (mc >= MC_1_14 && (int)(rsq) < 0)
|
||||
else if (mc > MC_1_13 && (int)(rsq) < 0)
|
||||
{
|
||||
out[j*r.sx+i] = small_end_islands;
|
||||
out[j*r.sx+i] = end_barrens;
|
||||
continue;
|
||||
}
|
||||
float h = getEndHeightNoise(en, hx, hz, 4);
|
||||
|
10
biomenoise.h
10
biomenoise.h
@ -175,6 +175,8 @@ extern BiomeTree g_btree[MC_NEWEST - MC_1_18 + 1];
|
||||
void initSurfaceNoise(SurfaceNoise *sn, int dim, uint64_t seed);
|
||||
void initSurfaceNoiseBeta(SurfaceNoiseBeta *snb, uint64_t seed);
|
||||
double sampleSurfaceNoise(const SurfaceNoise *sn, int x, int y, int z);
|
||||
double sampleSurfaceNoiseBetween(const SurfaceNoise *sn, int x, int y, int z,
|
||||
double noiseMin, double noiseMax);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
@ -222,9 +224,9 @@ int genNetherScaled(const NetherNoise *nn, int *out, Range r, int mc, uint64_t s
|
||||
void setEndSeed(EndNoise *en, int mc, uint64_t seed);
|
||||
int mapEndBiome(const EndNoise *en, int *out, int x, int z, int w, int h);
|
||||
int mapEnd(const EndNoise *en, int *out, int x, int z, int w, int h);
|
||||
int getSurfaceHeightEnd(int mc, uint64_t seed, int x, int z);
|
||||
int mapSurfaceHeightEnd(const EndNoise *en, const SurfaceNoise *sn, float *y,
|
||||
int x, int z, int w, int h, int scale);
|
||||
int getEndSurfaceHeight(int mc, uint64_t seed, int x, int z);
|
||||
int mapEndSurfaceHeight(float *y, const EndNoise *en, const SurfaceNoise *sn,
|
||||
int x, int z, int w, int h, int scale, int ymin);
|
||||
|
||||
/**
|
||||
* The scaled End generation supports scales 1, 4, 16, and 64.
|
||||
@ -307,6 +309,8 @@ int genBiomeNoiseBetaScaled(const BiomeNoiseBeta *bnb, const SurfaceNoiseBeta *s
|
||||
int *out, Range r);
|
||||
|
||||
|
||||
int getBiomeDepthAndScale(int id, double *depth, double *scale, int *grass);
|
||||
|
||||
// Gets the range in the parent/source layer which may be accessed by voronoi.
|
||||
Range getVoronoiSrcRange(Range r);
|
||||
|
||||
|
455
biomes.c
Normal file
455
biomes.c
Normal file
@ -0,0 +1,455 @@
|
||||
#include "biomes.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
int biomeExists(int mc, int id)
|
||||
{
|
||||
if (mc >= MC_1_18)
|
||||
{
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas)
|
||||
return 1;
|
||||
if (id >= small_end_islands && id <= end_barrens)
|
||||
return 1;
|
||||
|
||||
if (id == pale_garden)
|
||||
return mc >= MC_1_21_3;
|
||||
|
||||
if (id == cherry_grove)
|
||||
return mc >= MC_1_20;
|
||||
|
||||
if (id == deep_dark || id == mangrove_swamp)
|
||||
return mc >= MC_1_19_2;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case ocean:
|
||||
case plains:
|
||||
case desert:
|
||||
case mountains: // windswept_hills
|
||||
case forest:
|
||||
case taiga:
|
||||
case swamp:
|
||||
case river:
|
||||
case nether_wastes:
|
||||
case the_end:
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra: // snowy_plains
|
||||
case mushroom_fields:
|
||||
case beach:
|
||||
case jungle:
|
||||
case jungle_edge: // sparse_jungle
|
||||
case deep_ocean:
|
||||
case stone_shore: // stony_shore
|
||||
case snowy_beach:
|
||||
case birch_forest:
|
||||
case dark_forest:
|
||||
case snowy_taiga:
|
||||
case giant_tree_taiga: // old_growth_pine_taiga
|
||||
case wooded_mountains: // windswept_forest
|
||||
case savanna:
|
||||
case savanna_plateau:
|
||||
case badlands:
|
||||
case wooded_badlands_plateau: // wooded_badlands
|
||||
case warm_ocean:
|
||||
case lukewarm_ocean:
|
||||
case cold_ocean:
|
||||
case deep_warm_ocean:
|
||||
case deep_lukewarm_ocean:
|
||||
case deep_cold_ocean:
|
||||
case deep_frozen_ocean:
|
||||
case sunflower_plains:
|
||||
case gravelly_mountains: // windswept_gravelly_hills
|
||||
case flower_forest:
|
||||
case ice_spikes:
|
||||
case tall_birch_forest: // old_growth_birch_forest
|
||||
case giant_spruce_taiga: // old_growth_spruce_taiga
|
||||
case shattered_savanna: // windswept_savanna
|
||||
case eroded_badlands:
|
||||
case bamboo_jungle:
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
case meadow:
|
||||
case grove:
|
||||
case snowy_slopes:
|
||||
case stony_peaks:
|
||||
case jagged_peaks:
|
||||
case frozen_peaks:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mc <= MC_B1_7)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case plains:
|
||||
case desert:
|
||||
case forest:
|
||||
case taiga:
|
||||
case swamp:
|
||||
case snowy_tundra:
|
||||
case savanna:
|
||||
case seasonal_forest:
|
||||
case rainforest:
|
||||
case shrubland:
|
||||
// we treat areas below the sea level as oceans
|
||||
case ocean:
|
||||
case frozen_ocean:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mc <= MC_B1_8)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra:
|
||||
case mushroom_fields:
|
||||
case mushroom_field_shore:
|
||||
case the_end:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (mc <= MC_1_0)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case snowy_mountains:
|
||||
case beach:
|
||||
case desert_hills:
|
||||
case wooded_hills:
|
||||
case taiga_hills:
|
||||
case mountain_edge:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (id >= ocean && id <= mountain_edge) return 1;
|
||||
if (id >= jungle && id <= jungle_hills) return mc >= MC_1_2;
|
||||
if (id >= jungle_edge && id <= badlands_plateau) return mc >= MC_1_7;
|
||||
if (id >= small_end_islands && id <= end_barrens) return mc >= MC_1_9;
|
||||
if (id >= warm_ocean && id <= deep_frozen_ocean) return mc >= MC_1_13;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
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:
|
||||
case crimson_forest:
|
||||
case warped_forest:
|
||||
case basalt_deltas:
|
||||
return mc >= MC_1_16_1;
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
return mc >= MC_1_17;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int isOverworld(int mc, int id)
|
||||
{
|
||||
if (!biomeExists(mc, id))
|
||||
return 0;
|
||||
|
||||
if (id >= small_end_islands && id <= end_barrens) return 0;
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas) return 0;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case nether_wastes:
|
||||
case the_end:
|
||||
return 0;
|
||||
case frozen_ocean:
|
||||
return mc <= MC_1_6 || mc >= MC_1_13;
|
||||
case mountain_edge:
|
||||
return mc <= MC_1_6;
|
||||
case deep_warm_ocean:
|
||||
case the_void:
|
||||
return 0;
|
||||
case tall_birch_forest:
|
||||
return mc <= MC_1_8 || mc >= MC_1_11;
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
return mc >= MC_1_18;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int getDimension(int id)
|
||||
{
|
||||
if (id >= small_end_islands && id <= end_barrens) return DIM_END;
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas) return DIM_NETHER;
|
||||
if (id == the_end) return DIM_END;
|
||||
if (id == nether_wastes) return DIM_NETHER;
|
||||
return DIM_OVERWORLD;
|
||||
}
|
||||
|
||||
int getMutated(int mc, int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case plains: return sunflower_plains;
|
||||
case desert: return desert_lakes;
|
||||
case mountains: return gravelly_mountains;
|
||||
case forest: return flower_forest;
|
||||
case taiga: return taiga_mountains;
|
||||
case swamp: return swamp_hills;
|
||||
case snowy_tundra: return ice_spikes;
|
||||
case jungle: return modified_jungle;
|
||||
case jungle_edge: return modified_jungle_edge;
|
||||
// emulate MC-98995
|
||||
case birch_forest:
|
||||
return (mc >= MC_1_9 && mc <= MC_1_10) ? tall_birch_hills : tall_birch_forest;
|
||||
case birch_forest_hills:
|
||||
return (mc >= MC_1_9 && mc <= MC_1_10) ? none : tall_birch_hills;
|
||||
case dark_forest: return dark_forest_hills;
|
||||
case snowy_taiga: return snowy_taiga_mountains;
|
||||
case giant_tree_taiga: return giant_spruce_taiga;
|
||||
case giant_tree_taiga_hills: return giant_spruce_taiga_hills;
|
||||
case wooded_mountains: return modified_gravelly_mountains;
|
||||
case savanna: return shattered_savanna;
|
||||
case savanna_plateau: return shattered_savanna_plateau;
|
||||
case badlands: return eroded_badlands;
|
||||
case wooded_badlands_plateau: return modified_wooded_badlands_plateau;
|
||||
case badlands_plateau: return modified_badlands_plateau;
|
||||
default:
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
int getCategory(int mc, int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case beach:
|
||||
case snowy_beach:
|
||||
return beach;
|
||||
|
||||
case desert:
|
||||
case desert_hills:
|
||||
case desert_lakes:
|
||||
return desert;
|
||||
|
||||
case mountains:
|
||||
case mountain_edge:
|
||||
case wooded_mountains:
|
||||
case gravelly_mountains:
|
||||
case modified_gravelly_mountains:
|
||||
return mountains;
|
||||
|
||||
case forest:
|
||||
case wooded_hills:
|
||||
case birch_forest:
|
||||
case birch_forest_hills:
|
||||
case dark_forest:
|
||||
case flower_forest:
|
||||
case tall_birch_forest:
|
||||
case tall_birch_hills:
|
||||
case dark_forest_hills:
|
||||
return forest;
|
||||
|
||||
case snowy_tundra:
|
||||
case snowy_mountains:
|
||||
case ice_spikes:
|
||||
return snowy_tundra;
|
||||
|
||||
case jungle:
|
||||
case jungle_hills:
|
||||
case jungle_edge:
|
||||
case modified_jungle:
|
||||
case modified_jungle_edge:
|
||||
case bamboo_jungle:
|
||||
case bamboo_jungle_hills:
|
||||
return jungle;
|
||||
|
||||
case badlands:
|
||||
case eroded_badlands:
|
||||
case modified_wooded_badlands_plateau:
|
||||
case modified_badlands_plateau:
|
||||
return mesa;
|
||||
|
||||
case wooded_badlands_plateau:
|
||||
case badlands_plateau:
|
||||
return mc <= MC_1_15 ? mesa : badlands_plateau;
|
||||
|
||||
case mushroom_fields:
|
||||
case mushroom_field_shore:
|
||||
return mushroom_fields;
|
||||
|
||||
case stone_shore:
|
||||
return stone_shore;
|
||||
|
||||
case ocean:
|
||||
case frozen_ocean:
|
||||
case deep_ocean:
|
||||
case warm_ocean:
|
||||
case lukewarm_ocean:
|
||||
case cold_ocean:
|
||||
case deep_warm_ocean:
|
||||
case deep_lukewarm_ocean:
|
||||
case deep_cold_ocean:
|
||||
case deep_frozen_ocean:
|
||||
return ocean;
|
||||
|
||||
case plains:
|
||||
case sunflower_plains:
|
||||
return plains;
|
||||
|
||||
case river:
|
||||
case frozen_river:
|
||||
return river;
|
||||
|
||||
case savanna:
|
||||
case savanna_plateau:
|
||||
case shattered_savanna:
|
||||
case shattered_savanna_plateau:
|
||||
return savanna;
|
||||
|
||||
case swamp:
|
||||
case swamp_hills:
|
||||
return swamp;
|
||||
|
||||
case taiga:
|
||||
case taiga_hills:
|
||||
case snowy_taiga:
|
||||
case snowy_taiga_hills:
|
||||
case giant_tree_taiga:
|
||||
case giant_tree_taiga_hills:
|
||||
case taiga_mountains:
|
||||
case snowy_taiga_mountains:
|
||||
case giant_spruce_taiga:
|
||||
case giant_spruce_taiga_hills:
|
||||
return taiga;
|
||||
|
||||
case nether_wastes:
|
||||
case soul_sand_valley:
|
||||
case crimson_forest:
|
||||
case warped_forest:
|
||||
case basalt_deltas:
|
||||
return nether_wastes;
|
||||
|
||||
default:
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
int areSimilar(int mc, int id1, int id2)
|
||||
{
|
||||
if (id1 == id2) return 1;
|
||||
|
||||
if (mc <= MC_1_15)
|
||||
{
|
||||
if (id1 == wooded_badlands_plateau || id1 == badlands_plateau)
|
||||
return id2 == wooded_badlands_plateau || id2 == badlands_plateau;
|
||||
}
|
||||
|
||||
return getCategory(mc, id1) == getCategory(mc, id2);
|
||||
}
|
||||
|
||||
int isMesa(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case badlands:
|
||||
case eroded_badlands:
|
||||
case modified_wooded_badlands_plateau:
|
||||
case modified_badlands_plateau:
|
||||
case wooded_badlands_plateau:
|
||||
case badlands_plateau:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int isShallowOcean(int id)
|
||||
{
|
||||
const uint64_t shallow_bits =
|
||||
(1ULL << ocean) |
|
||||
(1ULL << frozen_ocean) |
|
||||
(1ULL << warm_ocean) |
|
||||
(1ULL << lukewarm_ocean) |
|
||||
(1ULL << cold_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & shallow_bits);
|
||||
}
|
||||
|
||||
int isDeepOcean(int id)
|
||||
{
|
||||
const uint64_t deep_bits =
|
||||
(1ULL << deep_ocean) |
|
||||
(1ULL << deep_warm_ocean) |
|
||||
(1ULL << deep_lukewarm_ocean) |
|
||||
(1ULL << deep_cold_ocean) |
|
||||
(1ULL << deep_frozen_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & deep_bits);
|
||||
}
|
||||
|
||||
int isOceanic(int id)
|
||||
{
|
||||
const uint64_t ocean_bits =
|
||||
(1ULL << ocean) |
|
||||
(1ULL << frozen_ocean) |
|
||||
(1ULL << warm_ocean) |
|
||||
(1ULL << lukewarm_ocean) |
|
||||
(1ULL << cold_ocean) |
|
||||
(1ULL << deep_ocean) |
|
||||
(1ULL << deep_warm_ocean) |
|
||||
(1ULL << deep_lukewarm_ocean) |
|
||||
(1ULL << deep_cold_ocean) |
|
||||
(1ULL << deep_frozen_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & ocean_bits);
|
||||
}
|
||||
|
||||
int isSnowy(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra:
|
||||
case snowy_mountains:
|
||||
case snowy_beach:
|
||||
case snowy_taiga:
|
||||
case snowy_taiga_hills:
|
||||
case ice_spikes:
|
||||
case snowy_taiga_mountains:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
37
biomes.h
37
biomes.h
@ -30,10 +30,12 @@ enum MCVersion
|
||||
MC_1_17_1, MC_1_17 = MC_1_17_1,
|
||||
MC_1_18_2, MC_1_18 = MC_1_18_2,
|
||||
MC_1_19_2,
|
||||
MC_1_19, // 1.19.3 - 1.19.4
|
||||
MC_1_20,
|
||||
MC_1_21,
|
||||
MC_NEWEST = MC_1_21,
|
||||
MC_1_19_4, MC_1_19 = MC_1_19_4,
|
||||
MC_1_20_6, MC_1_20 = MC_1_20_6,
|
||||
MC_1_21_2,
|
||||
MC_1_21_3, // (Winter Drop version TBA)
|
||||
MC_1_21 = MC_1_21_2,
|
||||
MC_NEWEST = MC_1_21_3,
|
||||
};
|
||||
|
||||
enum Dimension
|
||||
@ -168,8 +170,35 @@ enum BiomeID
|
||||
mangrove_swamp = 184,
|
||||
// 1.20
|
||||
cherry_grove = 185,
|
||||
// 1.21.3
|
||||
pale_garden = 186,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// BiomeID Helper Functions
|
||||
//==============================================================================
|
||||
|
||||
int biomeExists(int mc, int id);
|
||||
int isOverworld(int mc, int id); // false for biomes that don't generate
|
||||
int getDimension(int id);
|
||||
int getMutated(int mc, int id);
|
||||
int getCategory(int mc, int id);
|
||||
int areSimilar(int mc, int id1, int id2);
|
||||
int isMesa(int id);
|
||||
int isShallowOcean(int id);
|
||||
int isDeepOcean(int id);
|
||||
int isOceanic(int id);
|
||||
int isSnowy(int id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BIOMES_H_ */
|
||||
|
||||
|
14
biometree.c
14
biometree.c
@ -4,23 +4,27 @@
|
||||
#include "tables/btree192.h"
|
||||
#include "tables/btree19.h"
|
||||
#include "tables/btree20.h"
|
||||
#include "tables/btree213.h"
|
||||
|
||||
BiomeTree g_btree[MC_NEWEST - MC_1_18 + 1] =
|
||||
BiomeTree g_btree[MC_NEWEST - MC_1_18 + 1] =
|
||||
{
|
||||
// MC_1_18 (== MC_1_18_2)
|
||||
// MC_1_18_2
|
||||
{ btree18_steps, &btree18_param[0][0], btree18_nodes, btree18_order,
|
||||
sizeof(btree18_nodes) / sizeof(uint64_t) },
|
||||
// MC_1_19_2
|
||||
{ btree192_steps, &btree192_param[0][0], btree192_nodes, btree192_order,
|
||||
sizeof(btree192_nodes) / sizeof(uint64_t) },
|
||||
// MC_1_19
|
||||
// MC_1_19_4
|
||||
{ btree19_steps, &btree19_param[0][0], btree19_nodes, btree19_order,
|
||||
sizeof(btree19_nodes) / sizeof(uint64_t) },
|
||||
// MC_1_20
|
||||
// MC_1_20_6
|
||||
{ btree20_steps, &btree20_param[0][0], btree20_nodes, btree20_order,
|
||||
sizeof(btree20_nodes) / sizeof(uint64_t) },
|
||||
// MC_1_21
|
||||
// MC_1_21_2
|
||||
{ btree20_steps, &btree20_param[0][0], btree20_nodes, btree20_order,
|
||||
sizeof(btree20_nodes) / sizeof(uint64_t) },
|
||||
// MC_1_21_3
|
||||
{ btree213_steps, &btree213_param[0][0], btree213_nodes, btree213_order,
|
||||
sizeof(btree213_nodes) / sizeof(uint64_t) },
|
||||
};
|
||||
|
||||
|
421
finders.c
421
finders.c
@ -1,4 +1,5 @@
|
||||
#include "finders.h"
|
||||
#include "biomes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -102,7 +103,7 @@ int getStructureConfig(int structureType, int mc, StructureConfig *sconf)
|
||||
s_end_gateway_116 = { 40013, 1, 1, End_Gateway, STRUCT_END|STRUCT_CHUNK, 700},
|
||||
s_end_gateway_117 = { 40013, 1, 1, End_Gateway, STRUCT_END|STRUCT_CHUNK, 1.f/700},
|
||||
s_end_gateway = { 40000, 1, 1, End_Gateway, STRUCT_END|STRUCT_CHUNK, 1.f/700},
|
||||
s_end_island_115 = { 0, 1, 1, End_Island, STRUCT_END|STRUCT_CHUNK, 14},
|
||||
s_end_island_116 = { 0, 1, 1, End_Island, STRUCT_END|STRUCT_CHUNK, 14},
|
||||
s_end_island = { 0, 1, 1, End_Island, STRUCT_END|STRUCT_CHUNK, 1.f/14}
|
||||
;
|
||||
|
||||
@ -174,7 +175,7 @@ int getStructureConfig(int structureType, int mc, StructureConfig *sconf)
|
||||
// the block filling, making them much more difficult to predict
|
||||
return mc >= MC_1_13;
|
||||
case End_Island:
|
||||
if (mc <= MC_1_15) *sconf = s_end_island_115;
|
||||
if (mc <= MC_1_16) *sconf = s_end_island_116;
|
||||
else *sconf = s_end_island;
|
||||
return mc >= MC_1_13; // we only support decorator features for 1.13+
|
||||
case Desert_Well:
|
||||
@ -385,7 +386,249 @@ int getMineshafts(int mc, uint64_t seed, int cx0, int cz0, int cx1, int cz1,
|
||||
return n;
|
||||
}
|
||||
|
||||
int getEndIslands(EndIsland islands[2], int mc, uint64_t seed, int chunkX, int chunkZ)
|
||||
{
|
||||
StructureConfig sconf;
|
||||
if (!getStructureConfig(End_Island, mc, &sconf))
|
||||
return 0;
|
||||
|
||||
int x = chunkX * 16;
|
||||
int z = chunkZ * 16;
|
||||
uint64_t rng = getPopulationSeed(mc, seed, x, z);
|
||||
Xoroshiro xr;
|
||||
float r;
|
||||
|
||||
if (mc <= MC_1_16)
|
||||
{
|
||||
setSeed(&rng, rng + sconf.salt);
|
||||
if (nextInt(&rng, (int)sconf.rarity) != 0)
|
||||
return 0;
|
||||
islands[0].x = nextInt(&rng, 16) + x;
|
||||
islands[0].y = nextInt(&rng, 16) + 55;
|
||||
islands[0].z = nextInt(&rng, 16) + z;
|
||||
if (nextInt(&rng, 4) != 0)
|
||||
{
|
||||
islands[0].r = nextInt(&rng, 3) + 4;
|
||||
return 1;
|
||||
}
|
||||
islands[1].x = nextInt(&rng, 16) + x;
|
||||
islands[1].y = nextInt(&rng, 16) + 55;
|
||||
islands[1].z = nextInt(&rng, 16) + z;
|
||||
islands[0].r = nextInt(&rng, 3) + 4;
|
||||
for (r = islands[0].r; r > 0.5; r -= nextInt(&rng, 2) + 0.5);
|
||||
islands[1].r = nextInt(&rng, 3) + 4;
|
||||
return 2;
|
||||
}
|
||||
else if (mc <= MC_1_17)
|
||||
{
|
||||
setSeed(&rng, rng + sconf.salt);
|
||||
if (nextFloat(&rng) >= sconf.rarity)
|
||||
return 0;
|
||||
int second = nextInt(&rng, 4) == 0;
|
||||
islands[0].x = nextInt(&rng, 16) + x;
|
||||
islands[0].z = nextInt(&rng, 16) + z;
|
||||
islands[0].y = nextInt(&rng, 16) + 55;
|
||||
islands[0].r = nextInt(&rng, 3) + 4;
|
||||
for (r = islands[0].r; r > 0.5; r -= nextInt(&rng, 2) + 0.5);
|
||||
if (!second)
|
||||
return 1;
|
||||
islands[1].x = nextInt(&rng, 16) + x;
|
||||
islands[1].z = nextInt(&rng, 16) + z;
|
||||
islands[1].y = nextInt(&rng, 16) + 55;
|
||||
islands[1].r = nextInt(&rng, 3) + 4;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSetSeed(&xr, rng + sconf.salt);
|
||||
if (xNextFloat(&xr) >= sconf.rarity)
|
||||
return 0;
|
||||
int second = (xNextIntJ(&xr, 4) == 3);
|
||||
islands[0].x = xNextIntJ(&xr, 16) + x;
|
||||
islands[0].z = xNextIntJ(&xr, 16) + z;
|
||||
islands[0].y = xNextIntJ(&xr, 16) + 55;
|
||||
islands[0].r = xNextIntJ(&xr, 3) + 4;
|
||||
if (!second)
|
||||
return 1;
|
||||
for (r = islands[0].r; r > 0.5; r -= xNextIntJ(&xr, 2) + 0.5);
|
||||
islands[1].x = xNextIntJ(&xr, 16) + x;
|
||||
islands[1].z = xNextIntJ(&xr, 16) + z;
|
||||
islands[1].y = xNextIntJ(&xr, 16) + 55;
|
||||
islands[1].r = xNextIntJ(&xr, 3) + 4;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void applyEndIslandHeight(float *y, const EndIsland *island,
|
||||
int x, int z, int w, int h, int scale)
|
||||
{
|
||||
int r = island->r;
|
||||
int r2 = (r + 1) * (r + 1);
|
||||
int x0 = floordiv(island->x - r, scale);
|
||||
int z0 = floordiv(island->z - r, scale);
|
||||
int x1 = floordiv(island->x + r, scale);
|
||||
int z1 = floordiv(island->z + r, scale);
|
||||
int ds = 0;
|
||||
int i, j;
|
||||
for (j = z0; j <= z1; j++)
|
||||
{
|
||||
if (j < z || j >= z+h)
|
||||
continue;
|
||||
int dz = j * scale - island->z + ds;
|
||||
for (i = x0; i <= x1; i++)
|
||||
{
|
||||
if (i < x || i >= x+w)
|
||||
continue;
|
||||
int dx = i * scale - island->x + ds;
|
||||
if (dx*dx + dz*dz > r2)
|
||||
continue;
|
||||
int idx = (j - z) * w + (i - x);
|
||||
if (y[idx] < island->y)
|
||||
y[idx] = island->y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mapEndIslandHeight(float *y, const EndNoise *en, uint64_t seed,
|
||||
int x, int z, int w, int h, int scale)
|
||||
{
|
||||
int rmax = (6 + scale - 1) / scale;
|
||||
int cx = floordiv(x - rmax, 16 / scale);
|
||||
int cz = floordiv(z - rmax, 16 / scale);
|
||||
int cw = floordiv(x + w + rmax, 16 / scale) - cx + 1;
|
||||
int ch = floordiv(z + h + rmax, 16 / scale) - cz + 1;
|
||||
int ci, cj;
|
||||
|
||||
int *ids = (int*) malloc(sizeof(int) * cw * ch);
|
||||
mapEndBiome(en, ids, cx, cz, cw, ch);
|
||||
|
||||
for (cj = 0; cj < ch; cj++)
|
||||
{
|
||||
for (ci = 0; ci < cw; ci++)
|
||||
{
|
||||
if (ids[cj*cw + ci] != small_end_islands)
|
||||
continue;
|
||||
EndIsland islands[2];
|
||||
int n = getEndIslands(islands, en->mc, seed, cx+ci, cz+cj);
|
||||
while (n --> 0)
|
||||
applyEndIslandHeight(y, islands+n, x, z, w, h, scale);
|
||||
}
|
||||
}
|
||||
|
||||
free(ids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float getEndHeightNoise(const EndNoise *en, int x, int z, int range);
|
||||
|
||||
int isEndChunkEmpty(const EndNoise *en, const SurfaceNoise *sn, uint64_t seed,
|
||||
int chunkX, int chunkZ)
|
||||
{
|
||||
int i, j, k;
|
||||
int x = chunkX * 2;
|
||||
int z = chunkZ * 2;
|
||||
double depth[3][3];
|
||||
float y[256];
|
||||
|
||||
// check if small end islands intersect this chunk
|
||||
for (j = -1; j <= +1; j++)
|
||||
{
|
||||
for (i = -1; i <= +1; i++)
|
||||
{
|
||||
EndIsland is[2];
|
||||
int n = getEndIslands(is, en->mc, seed, chunkX+i, chunkZ+j);
|
||||
while (n --> 0)
|
||||
{
|
||||
if (is[n].x + is[n].r <= chunkX*16) continue;
|
||||
if (is[n].z + is[n].r <= chunkZ*16) continue;
|
||||
if (is[n].x - is[n].r > chunkX*16 + 15) continue;
|
||||
if (is[n].z - is[n].r > chunkZ*16 + 15) continue;
|
||||
int id;
|
||||
mapEndBiome(en, &id, is[n].x >> 4, is[n].z >> 4, 1, 1);
|
||||
if (id == small_end_islands)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clamped (32 + 46 - y) / 64.0
|
||||
static const double upper_drop[] = {
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 0-7
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 63./64, // 8-15
|
||||
62./64, 61./64, 60./64, 59./64, 58./64, 57./64, 56./64, 55./64, // 16-23
|
||||
54./64, 53./64, 52./64, 51./64, 50./64, 49./64, 48./64, 47./64, // 24-31
|
||||
46./64 // 32
|
||||
};
|
||||
// clamped (y - 1) / 7.0
|
||||
static const double lower_drop[] = {
|
||||
0.0, 0.0, 1./7, 2./7, 3./7, 4./7, 5./7, 6./7, // 0-7
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 8-15
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 16-23
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 24-31
|
||||
1.0, // 32
|
||||
};
|
||||
// inverse of clamping func: ( 30 * (1-l) / l + 3000 * (1-u) ) / u
|
||||
static const double inverse_drop[] = {
|
||||
1e9, 1e9, 180.0, 75.0, 40.0, 22.5, 12.0, 5.0, // 0-7
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // 8-14
|
||||
1000./21, 3000./31, 9000./61, 200.0, // 15-18
|
||||
};
|
||||
const double eps = 0.001;
|
||||
|
||||
// get the inner depth values and see if they imply blocks in the chunk
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
depth[i][j] = getEndHeightNoise(en, x+i, z+j, 0) - 8.0f;
|
||||
for (k = 8; k <= 14; k++)
|
||||
{
|
||||
double u = upper_drop[k];
|
||||
double l = lower_drop[k];
|
||||
double noise = depth[i][j];
|
||||
double pivot = inverse_drop[k] - noise;
|
||||
noise += sampleSurfaceNoiseBetween(sn, x+i, k, z+j, pivot-eps, pivot+eps);
|
||||
noise = lerp(u, -3000, noise);
|
||||
noise = lerp(l, -30, noise);
|
||||
if (noise > 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill in the depth values at the boundaries to neighbouring chunks
|
||||
for (i = 0; i < 3; i++)
|
||||
depth[i][2] = getEndHeightNoise(en, x+i, z+2, 0) - 8.0f;
|
||||
for (j = 0; j < 2; j++)
|
||||
depth[2][j] = getEndHeightNoise(en, x+2, z+j, 0) - 8.0f;
|
||||
|
||||
// see if none of the noise values can generate blocks
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
for (k = 2; k < 18; k++)
|
||||
{
|
||||
double u = upper_drop[k];
|
||||
double l = lower_drop[k];
|
||||
double noise = depth[i][j];
|
||||
double pivot = inverse_drop[k] - noise;
|
||||
noise += sampleSurfaceNoiseBetween(sn, x+i, k, z+j, pivot-eps, pivot+eps);
|
||||
noise = lerp(u, -3000, noise);
|
||||
noise = lerp(l, -30, noise);
|
||||
if (noise > 0)
|
||||
goto L_check_full;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
L_check_full:
|
||||
mapEndSurfaceHeight(y, en, sn, chunkX*16, chunkZ*16, 16, 16, 1, 0);
|
||||
for (k = 0; k < 256; k++)
|
||||
if (y[k] != 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Checking Biomes & Biome Helper Functions
|
||||
@ -1633,7 +1876,7 @@ int isViableEndCityTerrain(const Generator *g, const SurfaceNoise *sn,
|
||||
blockZ = chunkZ * 16 + 7;
|
||||
int cellx = (blockX >> 3);
|
||||
int cellz = (blockZ >> 3);
|
||||
// TODO: make sure upper bound is ok
|
||||
|
||||
enum { y0 = 15, y1 = 18, yn = y1-y0+1 };
|
||||
double ncol[3][3][yn];
|
||||
|
||||
@ -2618,27 +2861,160 @@ uint64_t getHouseList(int *out, uint64_t seed, int chunkX, int chunkZ)
|
||||
}
|
||||
|
||||
|
||||
void getFixedEndGateways(Pos pos[20][2], uint64_t seed)
|
||||
void getFixedEndGateways(int mc, uint64_t seed, Pos src[20])
|
||||
{
|
||||
(void) seed;
|
||||
(void) mc;
|
||||
static const Pos fixed[20] = {
|
||||
{ 96, 0}, { 91, 29}, { 77, 56}, { 56, 77}, { 29, 91},
|
||||
{ -1, 96}, {-30, 91}, {-57, 77}, {-78, 56}, {-92, 29},
|
||||
{-96, -1}, {-92,-30}, {-78,-57}, {-57,-78}, {-30,-92},
|
||||
{ 0,-96}, { 29,-92}, { 56,-78}, { 77,-57}, { 91,-30},
|
||||
};
|
||||
int i;
|
||||
for (i = 0; i < 20; i++)
|
||||
|
||||
uint8_t order[] = {
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
};
|
||||
|
||||
uint64_t rng = 0;
|
||||
setSeed(&rng, seed);
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
Pos p = pos[i][0] = fixed[i];
|
||||
// TODO: estimated positions on outer island
|
||||
float r = sqrtf(p.x * p.x + p.z * p.z);
|
||||
r = 1024.0f / r;
|
||||
pos[i][1].x = (int) (p.x * r);
|
||||
pos[i][1].z = (int) (p.z * r);
|
||||
uint8_t j = 19 - nextInt(&rng, 20-i);
|
||||
uint8_t tmp = order[i];
|
||||
order[i] = order[j];
|
||||
order[j] = tmp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
src[i] = fixed[ order[i] ];
|
||||
}
|
||||
|
||||
Pos getLinkedGatewayChunk(const EndNoise *en, const SurfaceNoise *sn, uint64_t seed,
|
||||
Pos src, Pos *dst)
|
||||
{
|
||||
double invr = 1.0 / sqrt(src.x * src.x + src.z * src.z);
|
||||
double dx = src.x * invr;
|
||||
double dz = src.z * invr;
|
||||
double px = dx * 1024;
|
||||
double pz = dz * 1024;
|
||||
dx *= 16;
|
||||
dz *= 16;
|
||||
|
||||
int i;
|
||||
Pos c;
|
||||
c.x = (int) floor(px) >> 4;
|
||||
c.z = (int) floor(pz) >> 4;
|
||||
|
||||
if (isEndChunkEmpty(en, sn, seed, c.x, c.z))
|
||||
{ // look forward for the first non-empty chunk
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
int qx = (int) floor(px += dx) >> 4;
|
||||
int qz = (int) floor(pz += dz) >> 4;
|
||||
if (qx == c.x && qz == c.z)
|
||||
continue;
|
||||
c.x = qx;
|
||||
c.z = qz;
|
||||
if (!isEndChunkEmpty(en, sn, seed, c.x, c.z))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // look backward for the last non-empty chunk
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
int qx = (int) floor(px -= dx) >> 4;
|
||||
int qz = (int) floor(pz -= dz) >> 4;
|
||||
if (isEndChunkEmpty(en, sn, seed, qx, qz))
|
||||
break;
|
||||
c.x = qx;
|
||||
c.z = qz;
|
||||
}
|
||||
}
|
||||
if (dst)
|
||||
{
|
||||
dst->x = (int) floor(px);
|
||||
dst->z = (int) floor(pz);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
Pos getLinkedGatewayPos(const EndNoise *en, const SurfaceNoise *sn, uint64_t seed, Pos src)
|
||||
{
|
||||
float y[33*33]; // buffer for [16][16] and [33][33]
|
||||
int ymin = 0;
|
||||
int i, j;
|
||||
|
||||
Pos dst;
|
||||
Pos c = getLinkedGatewayChunk(en, sn, seed, src, &dst);
|
||||
|
||||
if (en->mc > MC_1_16)
|
||||
{
|
||||
// The original java implementation has a bug where the result
|
||||
// variable for the in-chunk block search is assigned a reference
|
||||
// to the mutable iterator, which ends up as the last iteration
|
||||
// position and discards the found location.
|
||||
dst.x = c.x * 16 + 15;
|
||||
dst.z = c.z * 16 + 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapEndSurfaceHeight(y, en, sn, c.x*16, c.z*16, 16, 16, 1, 30);
|
||||
mapEndIslandHeight(y, en, seed, c.x*16, c.z*16, 16, 16, 1);
|
||||
|
||||
uint64_t d = 0;
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int v = (int) y[j*16 + i];
|
||||
if (v < 30) continue;
|
||||
uint64_t dx = 16*c.x + i;
|
||||
uint64_t dz = 16*c.z + j;
|
||||
uint64_t dr = dx*dx + dz*dz + v*v;
|
||||
if (dr > d)
|
||||
{
|
||||
d = dr;
|
||||
dst.x = dx;
|
||||
dst.z = dz;
|
||||
}
|
||||
}
|
||||
}
|
||||
// use the previous result to retrieve the minimum y-level we know,
|
||||
// we can skip generation of surfaces that are lower than this
|
||||
for (i = 0; i < 16*16; i++)
|
||||
if (y[i] > ymin)
|
||||
ymin = (int) floor(y[i]);
|
||||
}
|
||||
|
||||
Pos sp = { dst.x-16, dst.z-16 };
|
||||
// checking end islands is much cheaper than surface height generation, so
|
||||
// we can also skip surface generation lower than the highest island around
|
||||
memset(y, 0, sizeof(float)*33*33);
|
||||
mapEndIslandHeight(y, en, seed, sp.x, sp.z, 33, 33, 1);
|
||||
for (i = 0; i < 33*33; i++)
|
||||
if (y[i] > ymin)
|
||||
ymin = (int) floor(y[i]);
|
||||
|
||||
mapEndSurfaceHeight(y, en, sn, sp.x, sp.z, 33, 33, 1, ymin);
|
||||
mapEndIslandHeight(y, en, seed, sp.x, sp.z, 33, 33, 1);
|
||||
|
||||
float v = -1;
|
||||
for (i = 0; i < 33; i++)
|
||||
{
|
||||
for (j = 0; j < 33; j++)
|
||||
{
|
||||
if (y[j*33 + i] <= v)
|
||||
continue;
|
||||
v = y[j*33 + i];
|
||||
dst.x = sp.x + i;
|
||||
dst.z = sp.z + j;
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
@ -4040,10 +4416,12 @@ int floodFillGen(struct locate_info_t *info, int i, int j, Pos *p)
|
||||
i = queue[qn].i;
|
||||
j = queue[qn].j;
|
||||
int k = j * info->r.sx + i;
|
||||
int id = info->ids[k];
|
||||
if (id == INT_MAX)
|
||||
continue;
|
||||
info->ids[k] = INT_MAX;
|
||||
int x = info->r.x + i;
|
||||
int z = info->r.z + j;
|
||||
int id = info->ids[k];
|
||||
info->ids[k] = INT_MAX;
|
||||
if (info->g->mc >= MC_1_18)
|
||||
id = getBiomeAt(info->g, info->r.scale, x, info->r.y, z);
|
||||
if (id == info->match)
|
||||
@ -5079,6 +5457,10 @@ static const int g_biome_para_range_20_diff[][13] = {
|
||||
{cherry_grove , -4500, 2000, IMIN,-1000, 300, IMAX, -7799, 500, IMIN, IMAX, 2666, IMAX},
|
||||
};
|
||||
|
||||
static const int g_biome_para_range_213_diff[][13] = {
|
||||
{pale_garden , -1500, 2000, 3000, IMAX, 300, IMAX, -7799, 500, IMIN, IMAX, 2666, IMAX},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the min/max parameter values within which a biome change can occur.
|
||||
@ -5117,6 +5499,15 @@ const int *getBiomeParaLimits(int mc, int id)
|
||||
if (mc <= MC_1_17)
|
||||
return NULL;
|
||||
int i, n;
|
||||
if (mc > MC_1_21_2)
|
||||
{
|
||||
n = sizeof(g_biome_para_range_213_diff) / sizeof(g_biome_para_range_213_diff[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (g_biome_para_range_213_diff[i][0] == id)
|
||||
return &g_biome_para_range_213_diff[i][1];
|
||||
}
|
||||
}
|
||||
if (mc > MC_1_19)
|
||||
{
|
||||
n = sizeof(g_biome_para_range_20_diff) / sizeof(g_biome_para_range_20_diff[0]);
|
||||
|
36
finders.h
36
finders.h
@ -108,6 +108,11 @@ STRUCT(Piece)
|
||||
Piece *next;
|
||||
};
|
||||
|
||||
STRUCT(EndIsland)
|
||||
{
|
||||
int x, y, z;
|
||||
int r;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
@ -257,6 +262,23 @@ int isSlimeChunk(uint64_t seed, int chunkX, int chunkZ)
|
||||
return nextInt(&rnd, 10) == 0;
|
||||
}
|
||||
|
||||
/* Finds the position and size of the small end islands in a given chunk.
|
||||
* Returns the number of end islands found.
|
||||
*/
|
||||
int getEndIslands(EndIsland islands[2], int mc, uint64_t seed, int chunkX, int chunkZ);
|
||||
|
||||
/* Finds the small end islands in the given area and updates the existing
|
||||
* height map, y, accordingly. Note that values in the y-map can only increase
|
||||
* using this.
|
||||
*/
|
||||
int mapEndIslandHeight(float *y, const EndNoise *en, uint64_t seed,
|
||||
int x, int z, int w, int h, int scale);
|
||||
|
||||
/* Checks if the given chunk contains no blocks. This included a check for
|
||||
* small end islands.
|
||||
*/
|
||||
int isEndChunkEmpty(const EndNoise *en, const SurfaceNoise *sn, uint64_t seed,
|
||||
int chunkX, int chunkZ);
|
||||
|
||||
//==============================================================================
|
||||
// Finding Strongholds and Spawn
|
||||
@ -447,10 +469,18 @@ enum
|
||||
PIECE_COUNT,
|
||||
};
|
||||
|
||||
/* Find the inner ring positions where End Gateways generate upon defeating the
|
||||
* Dragon, as well as an estimate of where they link up to (WIP).
|
||||
/* Find the 20 fixed inner positions where End Gateways generate upon defeating
|
||||
* the Dragon. The positions are written to 'src' in generation order.
|
||||
*/
|
||||
void getFixedEndGateways(Pos pos[20][2], uint64_t seed);
|
||||
void getFixedEndGateways(int mc, uint64_t seed, Pos src[20]);
|
||||
|
||||
/* Get the outer linked Gateway destination for an inner source Gateway.
|
||||
* (mc > MC_1_12)
|
||||
*/
|
||||
Pos getLinkedGatewayChunk(const EndNoise *en, const SurfaceNoise *sn,
|
||||
uint64_t seed, Pos src, Pos *dst);
|
||||
Pos getLinkedGatewayPos(const EndNoise *en, const SurfaceNoise *sn,
|
||||
uint64_t seed, Pos src);
|
||||
|
||||
|
||||
/* Find the number of each type of house that generate in a village
|
||||
|
@ -154,7 +154,7 @@ size_t getMinCacheSize(const Generator *g, int scale, int sx, int sy, int sz)
|
||||
const Layer *entry = getLayerForScale(g, scale);
|
||||
if (!entry) {
|
||||
printf("getMinCacheSize(): failed to determine scaled entry\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
size_t len2d = getMinLayerCacheSize(entry, sx, sz);
|
||||
len += len2d - sx*sz;
|
||||
@ -173,6 +173,8 @@ size_t getMinCacheSize(const Generator *g, int scale, int sx, int sy, int sz)
|
||||
int *allocCache(const Generator *g, Range r)
|
||||
{
|
||||
size_t len = getMinCacheSize(g, r.scale, r.sx, r.sy, r.sz);
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
return (int*) calloc(len, sizeof(int));
|
||||
}
|
||||
|
||||
@ -615,7 +617,7 @@ int mapApproxHeight(float *y, int *ids, const Generator *g, const SurfaceNoise *
|
||||
{
|
||||
if (g->mc <= MC_1_8)
|
||||
return 1;
|
||||
return mapSurfaceHeightEnd(&g->en, sn, y, x, z, w, h, 4);
|
||||
return mapEndSurfaceHeight(y, &g->en, sn, x, z, w, h, 4, 0);
|
||||
}
|
||||
|
||||
if (g->mc >= MC_1_18)
|
||||
|
452
layers.c
452
layers.c
@ -6,458 +6,6 @@
|
||||
#include <float.h>
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Essentials
|
||||
//==============================================================================
|
||||
|
||||
int biomeExists(int mc, int id)
|
||||
{
|
||||
if (mc >= MC_1_18)
|
||||
{
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas)
|
||||
return 1;
|
||||
if (id >= small_end_islands && id <= end_barrens)
|
||||
return 1;
|
||||
|
||||
if (id == cherry_grove)
|
||||
return mc >= MC_1_20;
|
||||
|
||||
if (id == deep_dark || id == mangrove_swamp)
|
||||
return mc >= MC_1_19_2;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case ocean:
|
||||
case plains:
|
||||
case desert:
|
||||
case mountains: // windswept_hills
|
||||
case forest:
|
||||
case taiga:
|
||||
case swamp:
|
||||
case river:
|
||||
case nether_wastes:
|
||||
case the_end:
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra: // snowy_plains
|
||||
case mushroom_fields:
|
||||
case beach:
|
||||
case jungle:
|
||||
case jungle_edge: // sparse_jungle
|
||||
case deep_ocean:
|
||||
case stone_shore: // stony_shore
|
||||
case snowy_beach:
|
||||
case birch_forest:
|
||||
case dark_forest:
|
||||
case snowy_taiga:
|
||||
case giant_tree_taiga: // old_growth_pine_taiga
|
||||
case wooded_mountains: // windswept_forest
|
||||
case savanna:
|
||||
case savanna_plateau:
|
||||
case badlands:
|
||||
case wooded_badlands_plateau: // wooded_badlands
|
||||
case warm_ocean:
|
||||
case lukewarm_ocean:
|
||||
case cold_ocean:
|
||||
case deep_warm_ocean:
|
||||
case deep_lukewarm_ocean:
|
||||
case deep_cold_ocean:
|
||||
case deep_frozen_ocean:
|
||||
case sunflower_plains:
|
||||
case gravelly_mountains: // windswept_gravelly_hills
|
||||
case flower_forest:
|
||||
case ice_spikes:
|
||||
case tall_birch_forest: // old_growth_birch_forest
|
||||
case giant_spruce_taiga: // old_growth_spruce_taiga
|
||||
case shattered_savanna: // windswept_savanna
|
||||
case eroded_badlands:
|
||||
case bamboo_jungle:
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
case meadow:
|
||||
case grove:
|
||||
case snowy_slopes:
|
||||
case stony_peaks:
|
||||
case jagged_peaks:
|
||||
case frozen_peaks:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mc <= MC_B1_7)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case plains:
|
||||
case desert:
|
||||
case forest:
|
||||
case taiga:
|
||||
case swamp:
|
||||
case snowy_tundra:
|
||||
case savanna:
|
||||
case seasonal_forest:
|
||||
case rainforest:
|
||||
case shrubland:
|
||||
// we treat areas below the sea level as oceans
|
||||
case ocean:
|
||||
case frozen_ocean:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mc <= MC_B1_8)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra:
|
||||
case mushroom_fields:
|
||||
case mushroom_field_shore:
|
||||
case the_end:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (mc <= MC_1_0)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case snowy_mountains:
|
||||
case beach:
|
||||
case desert_hills:
|
||||
case wooded_hills:
|
||||
case taiga_hills:
|
||||
case mountain_edge:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (id >= ocean && id <= mountain_edge) return 1;
|
||||
if (id >= jungle && id <= jungle_hills) return mc >= MC_1_2;
|
||||
if (id >= jungle_edge && id <= badlands_plateau) return mc >= MC_1_7;
|
||||
if (id >= small_end_islands && id <= end_barrens) return mc >= MC_1_9;
|
||||
if (id >= warm_ocean && id <= deep_frozen_ocean) return mc >= MC_1_13;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
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:
|
||||
case crimson_forest:
|
||||
case warped_forest:
|
||||
case basalt_deltas:
|
||||
return mc >= MC_1_16_1;
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
return mc >= MC_1_17;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int isOverworld(int mc, int id)
|
||||
{
|
||||
if (!biomeExists(mc, id))
|
||||
return 0;
|
||||
|
||||
if (id >= small_end_islands && id <= end_barrens) return 0;
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas) return 0;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case nether_wastes:
|
||||
case the_end:
|
||||
return 0;
|
||||
case frozen_ocean:
|
||||
return mc <= MC_1_6 || mc >= MC_1_13;
|
||||
case mountain_edge:
|
||||
return mc <= MC_1_6;
|
||||
case deep_warm_ocean:
|
||||
case the_void:
|
||||
return 0;
|
||||
case tall_birch_forest:
|
||||
return mc <= MC_1_8 || mc >= MC_1_11;
|
||||
case dripstone_caves:
|
||||
case lush_caves:
|
||||
return mc >= MC_1_18;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int getDimension(int id)
|
||||
{
|
||||
if (id >= small_end_islands && id <= end_barrens) return DIM_END;
|
||||
if (id >= soul_sand_valley && id <= basalt_deltas) return DIM_NETHER;
|
||||
if (id == the_end) return DIM_END;
|
||||
if (id == nether_wastes) return DIM_NETHER;
|
||||
return DIM_OVERWORLD;
|
||||
}
|
||||
|
||||
int getMutated(int mc, int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case plains: return sunflower_plains;
|
||||
case desert: return desert_lakes;
|
||||
case mountains: return gravelly_mountains;
|
||||
case forest: return flower_forest;
|
||||
case taiga: return taiga_mountains;
|
||||
case swamp: return swamp_hills;
|
||||
case snowy_tundra: return ice_spikes;
|
||||
case jungle: return modified_jungle;
|
||||
case jungle_edge: return modified_jungle_edge;
|
||||
// emulate MC-98995
|
||||
case birch_forest:
|
||||
return (mc >= MC_1_9 && mc <= MC_1_10) ? tall_birch_hills : tall_birch_forest;
|
||||
case birch_forest_hills:
|
||||
return (mc >= MC_1_9 && mc <= MC_1_10) ? none : tall_birch_hills;
|
||||
case dark_forest: return dark_forest_hills;
|
||||
case snowy_taiga: return snowy_taiga_mountains;
|
||||
case giant_tree_taiga: return giant_spruce_taiga;
|
||||
case giant_tree_taiga_hills: return giant_spruce_taiga_hills;
|
||||
case wooded_mountains: return modified_gravelly_mountains;
|
||||
case savanna: return shattered_savanna;
|
||||
case savanna_plateau: return shattered_savanna_plateau;
|
||||
case badlands: return eroded_badlands;
|
||||
case wooded_badlands_plateau: return modified_wooded_badlands_plateau;
|
||||
case badlands_plateau: return modified_badlands_plateau;
|
||||
default:
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
int getCategory(int mc, int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case beach:
|
||||
case snowy_beach:
|
||||
return beach;
|
||||
|
||||
case desert:
|
||||
case desert_hills:
|
||||
case desert_lakes:
|
||||
return desert;
|
||||
|
||||
case mountains:
|
||||
case mountain_edge:
|
||||
case wooded_mountains:
|
||||
case gravelly_mountains:
|
||||
case modified_gravelly_mountains:
|
||||
return mountains;
|
||||
|
||||
case forest:
|
||||
case wooded_hills:
|
||||
case birch_forest:
|
||||
case birch_forest_hills:
|
||||
case dark_forest:
|
||||
case flower_forest:
|
||||
case tall_birch_forest:
|
||||
case tall_birch_hills:
|
||||
case dark_forest_hills:
|
||||
return forest;
|
||||
|
||||
case snowy_tundra:
|
||||
case snowy_mountains:
|
||||
case ice_spikes:
|
||||
return snowy_tundra;
|
||||
|
||||
case jungle:
|
||||
case jungle_hills:
|
||||
case jungle_edge:
|
||||
case modified_jungle:
|
||||
case modified_jungle_edge:
|
||||
case bamboo_jungle:
|
||||
case bamboo_jungle_hills:
|
||||
return jungle;
|
||||
|
||||
case badlands:
|
||||
case eroded_badlands:
|
||||
case modified_wooded_badlands_plateau:
|
||||
case modified_badlands_plateau:
|
||||
return mesa;
|
||||
|
||||
case wooded_badlands_plateau:
|
||||
case badlands_plateau:
|
||||
return mc <= MC_1_15 ? mesa : badlands_plateau;
|
||||
|
||||
case mushroom_fields:
|
||||
case mushroom_field_shore:
|
||||
return mushroom_fields;
|
||||
|
||||
case stone_shore:
|
||||
return stone_shore;
|
||||
|
||||
case ocean:
|
||||
case frozen_ocean:
|
||||
case deep_ocean:
|
||||
case warm_ocean:
|
||||
case lukewarm_ocean:
|
||||
case cold_ocean:
|
||||
case deep_warm_ocean:
|
||||
case deep_lukewarm_ocean:
|
||||
case deep_cold_ocean:
|
||||
case deep_frozen_ocean:
|
||||
return ocean;
|
||||
|
||||
case plains:
|
||||
case sunflower_plains:
|
||||
return plains;
|
||||
|
||||
case river:
|
||||
case frozen_river:
|
||||
return river;
|
||||
|
||||
case savanna:
|
||||
case savanna_plateau:
|
||||
case shattered_savanna:
|
||||
case shattered_savanna_plateau:
|
||||
return savanna;
|
||||
|
||||
case swamp:
|
||||
case swamp_hills:
|
||||
return swamp;
|
||||
|
||||
case taiga:
|
||||
case taiga_hills:
|
||||
case snowy_taiga:
|
||||
case snowy_taiga_hills:
|
||||
case giant_tree_taiga:
|
||||
case giant_tree_taiga_hills:
|
||||
case taiga_mountains:
|
||||
case snowy_taiga_mountains:
|
||||
case giant_spruce_taiga:
|
||||
case giant_spruce_taiga_hills:
|
||||
return taiga;
|
||||
|
||||
case nether_wastes:
|
||||
case soul_sand_valley:
|
||||
case crimson_forest:
|
||||
case warped_forest:
|
||||
case basalt_deltas:
|
||||
return nether_wastes;
|
||||
|
||||
default:
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
int areSimilar(int mc, int id1, int id2)
|
||||
{
|
||||
if (id1 == id2) return 1;
|
||||
|
||||
if (mc <= MC_1_15)
|
||||
{
|
||||
if (id1 == wooded_badlands_plateau || id1 == badlands_plateau)
|
||||
return id2 == wooded_badlands_plateau || id2 == badlands_plateau;
|
||||
}
|
||||
|
||||
return getCategory(mc, id1) == getCategory(mc, id2);
|
||||
}
|
||||
|
||||
int isMesa(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case badlands:
|
||||
case eroded_badlands:
|
||||
case modified_wooded_badlands_plateau:
|
||||
case modified_badlands_plateau:
|
||||
case wooded_badlands_plateau:
|
||||
case badlands_plateau:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int isShallowOcean(int id)
|
||||
{
|
||||
const uint64_t shallow_bits =
|
||||
(1ULL << ocean) |
|
||||
(1ULL << frozen_ocean) |
|
||||
(1ULL << warm_ocean) |
|
||||
(1ULL << lukewarm_ocean) |
|
||||
(1ULL << cold_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & shallow_bits);
|
||||
}
|
||||
|
||||
int isDeepOcean(int id)
|
||||
{
|
||||
const uint64_t deep_bits =
|
||||
(1ULL << deep_ocean) |
|
||||
(1ULL << deep_warm_ocean) |
|
||||
(1ULL << deep_lukewarm_ocean) |
|
||||
(1ULL << deep_cold_ocean) |
|
||||
(1ULL << deep_frozen_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & deep_bits);
|
||||
}
|
||||
|
||||
int isOceanic(int id)
|
||||
{
|
||||
const uint64_t ocean_bits =
|
||||
(1ULL << ocean) |
|
||||
(1ULL << frozen_ocean) |
|
||||
(1ULL << warm_ocean) |
|
||||
(1ULL << lukewarm_ocean) |
|
||||
(1ULL << cold_ocean) |
|
||||
(1ULL << deep_ocean) |
|
||||
(1ULL << deep_warm_ocean) |
|
||||
(1ULL << deep_lukewarm_ocean) |
|
||||
(1ULL << deep_cold_ocean) |
|
||||
(1ULL << deep_frozen_ocean);
|
||||
return (uint32_t) id < 64 && ((1ULL << id) & ocean_bits);
|
||||
}
|
||||
|
||||
int isSnowy(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case frozen_ocean:
|
||||
case frozen_river:
|
||||
case snowy_tundra:
|
||||
case snowy_mountains:
|
||||
case snowy_beach:
|
||||
case snowy_taiga:
|
||||
case snowy_taiga_hills:
|
||||
case ice_spikes:
|
||||
case snowy_taiga_mountains:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Essentials
|
||||
//==============================================================================
|
||||
|
17
layers.h
17
layers.h
@ -127,23 +127,6 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// BiomeID Helpers
|
||||
//==============================================================================
|
||||
|
||||
int biomeExists(int mc, int id);
|
||||
int isOverworld(int mc, int id);
|
||||
int getDimension(int id);
|
||||
int getMutated(int mc, int id);
|
||||
int getCategory(int mc, int id);
|
||||
int areSimilar(int mc, int id1, int id2);
|
||||
int isMesa(int id);
|
||||
int isShallowOcean(int id);
|
||||
int isDeepOcean(int id);
|
||||
int isOceanic(int id);
|
||||
int isSnowy(int id);
|
||||
int getBiomeDepthAndScale(int id, double *depth, double *scale, int *grass);
|
||||
|
||||
//==============================================================================
|
||||
// Essentials
|
||||
//==============================================================================
|
||||
|
5
makefile
5
makefile
@ -30,7 +30,7 @@ release: CFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
|
||||
libcubiomes: noise.o layers.o biometree.o biomenoise.o generator.o finders.o util.o quadbase.o
|
||||
libcubiomes: noise.o biomes.o layers.o biometree.o biomenoise.o generator.o finders.o util.o quadbase.o
|
||||
$(AR) $(ARFLAGS) libcubiomes.a $^
|
||||
|
||||
finders.o: finders.c finders.h
|
||||
@ -48,6 +48,9 @@ biometree.o: biometree.c
|
||||
layers.o: layers.c layers.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
biomes.o: biomes.c biomes.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
noise.o: noise.c noise.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
|
@ -45,7 +45,7 @@ static const int32_t btree20_param[][2] =
|
||||
|
||||
static const uint64_t btree20_nodes[] =
|
||||
{
|
||||
// Binary encoded biome parameter search tree for 1.20 (20w07a).
|
||||
// Binary encoded biome parameter search tree for 1.20 (23w07a).
|
||||
//
|
||||
// +-------------- If the top byte equals 0xFF, the node is a leaf and the
|
||||
// | second byte is the biome id, otherwise the two bytes
|
||||
|
2342
tables/btree213.h
Normal file
2342
tables/btree213.h
Normal file
File diff suppressed because it is too large
Load Diff
76
tests.c
76
tests.c
@ -133,6 +133,8 @@ uint32_t testAreas(int mc, int dim, int scale)
|
||||
Generator g;
|
||||
setupGenerator(&g, mc, 0);
|
||||
|
||||
SurfaceNoise sn;
|
||||
|
||||
double t = -now();
|
||||
uint32_t hash = 0;
|
||||
uint64_t s;
|
||||
@ -149,6 +151,14 @@ uint32_t testAreas(int mc, int dim, int scale)
|
||||
Range r = {scale, x, z, w, h, y, 1};
|
||||
int *ids = allocCache(&g, r);
|
||||
genBiomes(&g, ids, r);
|
||||
|
||||
float *surf = malloc(4 * w * h);
|
||||
initSurfaceNoise(&sn, dim, s);
|
||||
mapApproxHeight(surf, 0, &g, &sn, x, z, w, h);
|
||||
for (int i = 0; i < w*h; i++)
|
||||
ids[i] = (int) surf[i];
|
||||
free(surf);
|
||||
|
||||
int i = 0;
|
||||
hash = 0;
|
||||
for (i = 0; i < w*h; i++)
|
||||
@ -322,7 +332,7 @@ void findBiomeParaBounds()
|
||||
}
|
||||
|
||||
Generator g;
|
||||
setupGenerator(&g, MC_1_20, 0);
|
||||
setupGenerator(&g, MC_1_21_3, 0);
|
||||
int64_t s;
|
||||
int r = 1000;
|
||||
for (s = 0; s < 20000; s++)
|
||||
@ -337,14 +347,16 @@ void findBiomeParaBounds()
|
||||
getParaRange(&g.bn.climate[NP_EROSION], &tmin, &tmax, x-r, z-r, r, r, &g, _f2);
|
||||
getParaRange(&g.bn.climate[NP_CONTINENTALNESS], &tmin, &tmax, x-r, z-r, r, r, &g, _f2);
|
||||
getParaRange(&g.bn.climate[NP_WEIRDNESS], &tmin, &tmax, x-r, z-r, r, r, &g, _f2);
|
||||
if (s % 1000 == 999)
|
||||
printf(".\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if (!isOverworld(MC_1_20, i))
|
||||
if (!isOverworld(MC_1_21_3, i))
|
||||
continue;
|
||||
|
||||
printf("{%-24s", biome2str(MC_1_20, i));
|
||||
printf("{%-24s", biome2str(MC_1_21_3, i));
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
printf(", %6ld,%6ld", bbounds[i][j][0], bbounds[i][j][1]);
|
||||
@ -458,20 +470,70 @@ void findStructures(int structureType, int mc, int dim, uint64_t seed,
|
||||
if (!isViableStructureTerrain(structureType, &g, pos.x, pos.z))
|
||||
continue;
|
||||
}
|
||||
printf("%d, %d\n", pos.x, pos.z);
|
||||
|
||||
int id = getBiomeAt(&g, 4, pos.x>>2, 320>>2, pos.z>>2);
|
||||
StructureVariant sv;
|
||||
getVariant(&sv, structureType, mc, seed, pos.x, pos.z, id);
|
||||
int x = pos.x + sv.x;
|
||||
int z = pos.z + sv.z;
|
||||
printf("%d, %d : [%d %d %d] - [%d %d %d]\n", pos.x, pos.z,
|
||||
x, sv.y, z, x+sv.sx, sv.y+sv.sy, z+sv.sz
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getStructureConfig_override(int stype, int mc, StructureConfig *sconf)
|
||||
{
|
||||
return getStructureConfig(stype, mc, sconf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
//testAreas(mc, 0, 1);
|
||||
/*
|
||||
int mc = MC_1_21;
|
||||
uint64_t seed = 2;
|
||||
|
||||
double t0 = 0, t1 = 0;
|
||||
t0 -= now();
|
||||
|
||||
EndNoise en;
|
||||
setEndSeed(&en, mc, seed);
|
||||
|
||||
SurfaceNoise sn;
|
||||
initSurfaceNoise(&sn, DIM_END, seed);
|
||||
|
||||
Pos src[20];
|
||||
getFixedEndGateways(mc, seed, src);
|
||||
|
||||
t0 += now();
|
||||
t1 -= now();
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
Pos dst = getLinkedGatewayPos(&en, &sn, seed, src[i]);
|
||||
printf("%d %d -> %d %d\n", src[i].x, src[i].z, dst.x, dst.z);
|
||||
}
|
||||
t1 += now();
|
||||
|
||||
printf("Time: %g -> %g sec\n", t0, t1);
|
||||
*/
|
||||
|
||||
//findStructures(Trial_Chambers, MC_1_21, 0, 1, 3056, 3440, 3056, 3440);
|
||||
|
||||
//endHeight(MC_1_21, 1, 80>>1, 1216>>1, 32, 32, 2);
|
||||
|
||||
//endHeight(MC_1_15, 1, 370704, 96, 32, 32, 1);
|
||||
|
||||
//testAreas(MC_1_21, 1, 1);
|
||||
//testAreas(mc, 0, 4);
|
||||
//testAreas(mc, 0, 16);
|
||||
//testAreas(mc, 0, 256);
|
||||
//testCanBiomesGenerate();
|
||||
testGeneration();
|
||||
//findBiomeParaBounds();
|
||||
//testGeneration();
|
||||
findBiomeParaBounds();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
32
util.c
32
util.c
@ -73,7 +73,9 @@ const char* mc2str(int mc)
|
||||
case MC_1_19_2: return "1.19.2"; break;
|
||||
case MC_1_19: return "1.19"; break;
|
||||
case MC_1_20: return "1.20"; break;
|
||||
case MC_1_21: return "1.21"; break;
|
||||
case MC_1_21_2: return "1.21.2"; break;
|
||||
case MC_1_21_3: return "1.21.3"; break;
|
||||
//case MC_1_21: return "1.21"; break;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -81,29 +83,52 @@ const char* mc2str(int mc)
|
||||
int str2mc(const char *s)
|
||||
{
|
||||
if (!strcmp(s, "1.21")) return MC_1_21;
|
||||
if (!strcmp(s, "1.21.3")) return MC_1_21_3;
|
||||
if (!strcmp(s, "1.21.2")) return MC_1_21_2;
|
||||
if (!strcmp(s, "1.20")) return MC_1_20;
|
||||
if (!strcmp(s, "1.20.6")) return MC_1_20_6;
|
||||
if (!strcmp(s, "1.19")) return MC_1_19;
|
||||
if (!strcmp(s, "1.19.4")) return MC_1_19_4;
|
||||
if (!strcmp(s, "1.19.2")) return MC_1_19_2;
|
||||
if (!strcmp(s, "1.18")) return MC_1_18;
|
||||
if (!strcmp(s, "1.18.2")) return MC_1_18_2;
|
||||
if (!strcmp(s, "1.17")) return MC_1_17;
|
||||
if (!strcmp(s, "1.16.1")) return MC_1_16_1;
|
||||
if (!strcmp(s, "1.17.1")) return MC_1_17_1;
|
||||
if (!strcmp(s, "1.16")) return MC_1_16;
|
||||
if (!strcmp(s, "1.16.5")) return MC_1_16_5;
|
||||
if (!strcmp(s, "1.16.1")) return MC_1_16_1;
|
||||
if (!strcmp(s, "1.15")) return MC_1_15;
|
||||
if (!strcmp(s, "1.15.2")) return MC_1_15_2;
|
||||
if (!strcmp(s, "1.14")) return MC_1_14;
|
||||
if (!strcmp(s, "1.14.4")) return MC_1_14_4;
|
||||
if (!strcmp(s, "1.13")) return MC_1_13;
|
||||
if (!strcmp(s, "1.13.2")) return MC_1_13_2;
|
||||
if (!strcmp(s, "1.12")) return MC_1_12;
|
||||
if (!strcmp(s, "1.12.2")) return MC_1_12_2;
|
||||
if (!strcmp(s, "1.11")) return MC_1_11;
|
||||
if (!strcmp(s, "1.11.2")) return MC_1_11_2;
|
||||
if (!strcmp(s, "1.10")) return MC_1_10;
|
||||
if (!strcmp(s, "1.10.2")) return MC_1_10_2;
|
||||
if (!strcmp(s, "1.9")) return MC_1_9;
|
||||
if (!strcmp(s, "1.9.4")) return MC_1_9_4;
|
||||
if (!strcmp(s, "1.8")) return MC_1_8;
|
||||
if (!strcmp(s, "1.8.9")) return MC_1_8_9;
|
||||
if (!strcmp(s, "1.7")) return MC_1_7;
|
||||
if (!strcmp(s, "1.7.10")) return MC_1_7_10;
|
||||
if (!strcmp(s, "1.6")) return MC_1_6;
|
||||
if (!strcmp(s, "1.6.4")) return MC_1_6_4;
|
||||
if (!strcmp(s, "1.5")) return MC_1_5;
|
||||
if (!strcmp(s, "1.5.2")) return MC_1_5_2;
|
||||
if (!strcmp(s, "1.4")) return MC_1_4;
|
||||
if (!strcmp(s, "1.4.7")) return MC_1_4_7;
|
||||
if (!strcmp(s, "1.3")) return MC_1_3;
|
||||
if (!strcmp(s, "1.3.2")) return MC_1_3_2;
|
||||
if (!strcmp(s, "1.2")) return MC_1_2;
|
||||
if (!strcmp(s, "1.2.5")) return MC_1_2_5;
|
||||
if (!strcmp(s, "1.1")) return MC_1_1;
|
||||
if (!strcmp(s, "1.1.0")) return MC_1_1_0;
|
||||
if (!strcmp(s, "1.0")) return MC_1_0;
|
||||
if (!strcmp(s, "1.0.0")) return MC_1_0_0;
|
||||
if (!strcmp(s, "Beta 1.8")) return MC_B1_8;
|
||||
if (!strcmp(s, "Beta 1.7")) return MC_B1_7;
|
||||
return -1;
|
||||
@ -242,6 +267,8 @@ const char *biome2str(int mc, int id)
|
||||
case mangrove_swamp: return "mangrove_swamp";
|
||||
// 1.20
|
||||
case cherry_grove: return "cherry_grove";
|
||||
// 1.21.3 (Winter Drop)
|
||||
case pale_garden: return "pale_garden";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -387,6 +414,7 @@ void initBiomeColors(unsigned char colors[256][3])
|
||||
setColor(colors, deep_dark, 0x031f29); // -
|
||||
setColor(colors, mangrove_swamp, 0x2ccc8e); // -
|
||||
setColor(colors, cherry_grove, 0xff91c8); // -
|
||||
setColor(colors, pale_garden, 0x726c68); // -
|
||||
}
|
||||
|
||||
void initBiomeTypeColors(unsigned char colors[256][3])
|
||||
|
Loading…
x
Reference in New Issue
Block a user