Added biome center finder

This commit is contained in:
Cubitect 2022-10-01 15:14:37 +02:00
parent 6f2ef55b73
commit 2dbece7363
2 changed files with 203 additions and 1 deletions

185
finders.c
View File

@ -379,7 +379,7 @@ Pos locateBiome(
for (i = -radius; i <= radius; i++)
{
// emulate order-dependent biome generation MC-241546
//id = getBiomeAt(g, 4, x+i, y, z+j);
//int id = getBiomeAt(g, 4, x+i, y, z+j);
int id = sampleBiomeNoise(&g->bn, NULL, x+i, y, z+j, &dat, 0);
if (!id_matches(id, validB, validM))
continue;
@ -3692,6 +3692,189 @@ int checkForTemps(LayerStack *g, uint64_t seed, int x, int z, int w, int h, cons
}
struct locate_info_t
{
Generator *g;
int *ids;
Range r;
int match;
int64_t sumx, sumz;
int n, dmax;
volatile char *stop;
};
static
void floodFillGen(struct locate_info_t *info, int i, int j, int d)
{
if (i < 0 || j < 0 || i >= info->r.sx || j >= info->r.sz)
return;
if (info->stop && *info->stop)
return;
int idx = j * info->r.sx + i;
int id = info->ids[idx];
if (id == INT_MAX)
return;
info->ids[idx] = INT_MAX;
int x = info->r.x + i;
int z = info->r.z + j;
if (info->g->mc >= MC_1_18)
id = getBiomeAt(info->g, 4, x, info->r.y, z);
if (id == info->match)
{
info->sumx += x;
info->sumz += z;
info->n += 1;
d = 0;
}
else
{
if (++d >= info->dmax)
return;
}
floodFillGen(info, i, j-1, d);
floodFillGen(info, i, j+1, d);
floodFillGen(info, i-1, j, d);
floodFillGen(info, i+1, j, d);
}
int getBiomeCenters(Pos *pos, int *siz, int nmax, Generator *g, Range r,
int match, int minsiz, int tol, volatile char *stop)
{
if (r.scale != 4)
{
printf("getBiomeCenters() unsupported scale\n");
return 0;
}
if (minsiz <= 0)
minsiz = 1;
int i, j, k, n = 0;
int *ids = (int*) malloc(r.sx*r.sz * sizeof(int));
memset(ids, -1, r.sx*r.sz * sizeof(int));
if (tol <= 0)
tol = 1;
int step = tol;
struct locate_info_t info;
info.g = g;
info.ids = ids;
info.r = r;
info.stop = stop;
info.match = match;
info.dmax = tol;
if (g->mc >= MC_1_18)
{
const int *lim = getBiomeParaLimits(g->mc, match);
int para[] = {
NP_TEMPERATURE,
NP_HUMIDITY,
NP_EROSION,
NP_CONTINENTALNESS,
NP_WEIRDNESS,
};
int npara = sizeof(para) / sizeof(para[0]);
if (tol == 1)
step = 1 + floor(sqrt(minsiz) * 0.5);
for (j = 0; j < r.sz; j += step)
{
for (i = 0; i < r.sx; i += step)
{
if (stop && *stop)
break;
for (k = 0; k < npara; k++)
{
const int *plim = lim + 2*para[k];
if (plim[0] == INT_MIN && plim[1] == INT_MAX)
continue;
DoublePerlinNoise *dpn = &g->bn.climate[para[k]];
int p = 10000 * sampleDoublePerlin(dpn, r.x+i, 0, r.z+j);
if (p < plim[0] || p > plim[1])
{
ids[j*r.sx + i] = -2;
break;
}
}
}
}
match = -1; // id entries that are still -1 are our candidates
}
else // 1.17-
{
int ts = 64;
int tx = (int) floor(r.x / (double)ts);
int tz = (int) floor(r.z / (double)ts);
int tw = (int) ceil((r.x+r.sx) / (double)ts) - tx;
int th = (int) ceil((r.z+r.sz) / (double)ts) - tz;
int ti, tj;
BiomeFilter bf;
setupBiomeFilter(&bf, g->mc, 0, &match, 1, 0, 0, 0, 0);
//applySeed(g, 0, g->seed);
Range tr = { 4, 0, 0, ts, ts, 0, 1 };
int *cache = allocCache(g, r);
for (tj = 0; tj < th; tj++)
{
for (ti = 0; ti < tw; ti++)
{
if (stop && *stop)
break;
tr.x = (tx+ti) * ts;
tr.z = (tz+tj) * ts;
if (checkForBiomes(g, cache, tr, DIM_OVERWORLD, g->seed,
&bf, stop) != 1)
{
continue;
}
for (j = 0; j < ts; j++)
{
int jj = tr.z + j - r.z;
if (jj < 0 || jj >= r.sz)
continue;
for (i = 0; i < ts; i++)
{
int ii = tr.x + i - r.x;
if (ii < 0 || ii >= r.sx)
continue;
ids[jj*r.sx + ii] = cache[j*tr.sx + i];
}
}
}
}
free(cache);
}
for (j = 0; j < r.sz; j += step)
{
for (i = 0; i < r.sx; i += step)
{
if (stop && *stop)
break;
if (ids[j*r.sx + i] != match)
continue;
info.sumx = info.sumz = info.n = 0;
floodFillGen(&info, i, j, 0);
if (info.n >= minsiz)
{
pos[n].x = (int) round(2.0 + 4.0*info.sumx / info.n);
pos[n].z = (int) round(2.0 + 4.0*info.sumz / info.n);
if (siz) siz[n] = info.n;
if (++n >= nmax)
goto L_end;
}
}
}
L_end:
free(ids);
return n;
}
int canBiomeGenerate(int layerId, int mc, uint32_t flags, int id)
{
int dofilter = 0;

19
tests.c
View File

@ -8,6 +8,7 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <limits.h>
uint32_t hash32(uint32_t x)
{
@ -462,6 +463,24 @@ void findStructures(int structureType, int mc, int dim, uint64_t seed,
int main()
{
int mc = MC_1_19;
uint64_t seed = 18;
Generator g;
setupGenerator(&g, mc, 0);
applySeed(&g, 0, seed);
Range r = {4, -1000, -1000, 2001, 2001, 256>>2};
Pos p[100];
int b[100];
int n = getBiomeCenters(p, b, 100, &g, r, forest, 1, 8, NULL);
int i;
for (i = 0; i < n; i++)
{
printf("(%d, %d) size:%d\n", p[i].x, p[i].z, b[i]);
}
//testCanBiomesGenerate();
//testGeneration();
//findBiomeParaBounds();