mirror of
https://github.com/Cubitect/cubiomes.git
synced 2025-09-25 13:00:27 -04:00
Fix 1.18 spawn and stronghold finders (please fix MC-241546, Mojang)
This commit is contained in:
parent
65414ac3be
commit
8fea920b49
@ -277,7 +277,7 @@ Strongholds as well as the world spawn point actually search until they find a s
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int mc = MC_1_17;
|
int mc = MC_1_18;
|
||||||
uint64_t seed = 3055141959546LL;
|
uint64_t seed = 3055141959546LL;
|
||||||
|
|
||||||
// Only the first stronghold has a position which can be estimated
|
// Only the first stronghold has a position which can be estimated
|
||||||
|
165
finders.c
165
finders.c
@ -944,12 +944,17 @@ Pos locateBiome(
|
|||||||
x >>= 2;
|
x >>= 2;
|
||||||
z >>= 2;
|
z >>= 2;
|
||||||
radius >>= 2;
|
radius >>= 2;
|
||||||
|
uint64_t dat = 0;
|
||||||
|
|
||||||
for (i = -radius; i <= radius; i++)
|
for (j = -radius; j <= radius; j++)
|
||||||
{
|
{
|
||||||
for (j = -radius; j <= radius; j++)
|
for (i = -radius; i <= radius; i++)
|
||||||
{
|
{
|
||||||
int id = getBiomeAt(g, 4, x+i, y, z+j);
|
int id, xi = x+i, zj = z+j;
|
||||||
|
// emulate dependent biome generation MC-241546
|
||||||
|
//id = getBiomeAt(g, 4, xi, y, zj);
|
||||||
|
id = sampleBiomeNoise(&g->bn, NULL, xi, y, zj, &dat, 0);
|
||||||
|
|
||||||
if (!validBiomes[id]) continue;
|
if (!validBiomes[id]) continue;
|
||||||
if (found == 0 || nextInt(rng, found+1) == 0)
|
if (found == 0 || nextInt(rng, found+1) == 0)
|
||||||
{
|
{
|
||||||
@ -1114,28 +1119,29 @@ const char* getValidStrongholdBiomes(int mc)
|
|||||||
modified_gravelly_mountains, shattered_savanna,
|
modified_gravelly_mountains, shattered_savanna,
|
||||||
shattered_savanna_plateau, eroded_badlands,
|
shattered_savanna_plateau, eroded_badlands,
|
||||||
modified_wooded_badlands_plateau, modified_badlands_plateau,
|
modified_wooded_badlands_plateau, modified_badlands_plateau,
|
||||||
bamboo_jungle, bamboo_jungle_hills,
|
bamboo_jungle, bamboo_jungle_hills, dripstone_caves, lush_caves, meadow,
|
||||||
|
grove, snowy_slopes, stony_peaks, jagged_peaks, frozen_peaks,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char isValid115[256], isValid[256];
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
static char v15[256], v17[256], v18[256];
|
||||||
|
char *valid = (mc <= MC_1_15 ? v15 : mc <= MC_1_17 ? v17 : v18);
|
||||||
|
|
||||||
if (mc <= MC_1_15)
|
if (!valid[strongholdBiomes[0]])
|
||||||
{
|
{
|
||||||
if (!isValid115[strongholdBiomes[0]])
|
for (i = 0; i < sizeof(strongholdBiomes)/sizeof(int); i++)
|
||||||
for (i = 0; i < sizeof(strongholdBiomes) / sizeof(int); i++)
|
valid[ strongholdBiomes[i] ] = 1;
|
||||||
isValid115[ strongholdBiomes[i] ] = 1;
|
|
||||||
return isValid115;
|
if (mc >= MC_1_18)
|
||||||
}
|
{
|
||||||
else
|
valid[stone_shore] = 0;
|
||||||
{ // simulate MC-199298
|
}
|
||||||
if (!isValid[strongholdBiomes[0]])
|
else if (mc >= MC_1_16)
|
||||||
for (i = 0; i < sizeof(strongholdBiomes) / sizeof(int); i++)
|
{ // simulate MC-199298
|
||||||
isValid[ strongholdBiomes[i] ] = 1;
|
valid[bamboo_jungle] = 0;
|
||||||
isValid[bamboo_jungle] = 0;
|
valid[bamboo_jungle_hills] = 0;
|
||||||
isValid[bamboo_jungle_hills] = 0;
|
}
|
||||||
return isValid;
|
|
||||||
}
|
}
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pos initFirstStronghold(StrongholdIter *sh, int mc, uint64_t s48)
|
Pos initFirstStronghold(StrongholdIter *sh, int mc, uint64_t s48)
|
||||||
@ -1343,6 +1349,79 @@ static int findServerSpawn(const Generator *g, int chunkX, int chunkZ,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
uint64_t getSpawnDist(const Generator *g, int x, int z)
|
||||||
|
{
|
||||||
|
int64_t np[6];
|
||||||
|
uint32_t flags = SAMPLE_NO_DEPTH | SAMPLE_NO_BIOME;
|
||||||
|
sampleBiomeNoise(&g->bn, np, x>>2, 0, z>>2, NULL, flags);
|
||||||
|
const int64_t spawn_np[][2] = {
|
||||||
|
{-10000,10000},{-10000,10000},{-1100,10000},{-10000,10000},{0,0},
|
||||||
|
{-10000,-1600},{1600,10000} // [6]: weirdness for the second noise point
|
||||||
|
};
|
||||||
|
uint64_t ds = 0, ds1 = 0, ds2 = 0;
|
||||||
|
uint64_t a, b, q, i;
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
a = +np[i] - (uint64_t)spawn_np[i][1];
|
||||||
|
b = -np[i] + (uint64_t)spawn_np[i][0];
|
||||||
|
q = (int64_t)a > 0 ? a : (int64_t)b > 0 ? b : 0;
|
||||||
|
ds += q * q;
|
||||||
|
}
|
||||||
|
a = +np[5] - (uint64_t)spawn_np[5][1];
|
||||||
|
b = -np[5] + (uint64_t)spawn_np[5][0];
|
||||||
|
q = (int64_t)a > 0 ? a : (int64_t)b > 0 ? b : 0;
|
||||||
|
ds1 = ds + q*q;
|
||||||
|
a = +np[5] - (uint64_t)spawn_np[6][1];
|
||||||
|
b = -np[5] + (uint64_t)spawn_np[6][0];
|
||||||
|
q = (int64_t)a > 0 ? a : (int64_t)b > 0 ? b : 0;
|
||||||
|
ds2 = ds + q*q;
|
||||||
|
return ds1 <= ds2 ? ds1 : ds2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void findFittest(const Generator *g, Pos *pos, uint64_t *fitness, double maxrad, double step)
|
||||||
|
{
|
||||||
|
double rad = step, ang = 0;
|
||||||
|
Pos p = *pos;
|
||||||
|
while (rad <= maxrad)
|
||||||
|
{
|
||||||
|
int x = p.x + (int)(sin(ang) * rad);
|
||||||
|
int z = p.z + (int)(cos(ang) * rad);
|
||||||
|
// calc fitness
|
||||||
|
double d = ((double)x*x + (double)z*z) / (2500*2500);
|
||||||
|
uint64_t fit = (uint64_t)(d*d * 1e8);
|
||||||
|
// calculate the distance to the noise points for spawn
|
||||||
|
fit += getSpawnDist(g, x, z);
|
||||||
|
if (fit < *fitness)
|
||||||
|
{
|
||||||
|
pos->x = x;
|
||||||
|
pos->z = z;
|
||||||
|
*fitness = fit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ang += step / rad;
|
||||||
|
if (ang <= M_PI*2)
|
||||||
|
continue;
|
||||||
|
ang = 0;
|
||||||
|
rad += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
Pos findFittestPos(const Generator *g)
|
||||||
|
{
|
||||||
|
Pos spawn = {0, 0};
|
||||||
|
uint64_t fitness = getSpawnDist(g, 0, 0);
|
||||||
|
findFittest(g, &spawn, &fitness, 2048.0, 512.0);
|
||||||
|
findFittest(g, &spawn, &fitness, 512.0, 32.0);
|
||||||
|
// center of chunk
|
||||||
|
spawn.x = ((spawn.x >> 4) << 4) + 8;
|
||||||
|
spawn.z = ((spawn.z >> 4) << 4) + 8;
|
||||||
|
return spawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Pos getSpawn(const Generator *g)
|
Pos getSpawn(const Generator *g)
|
||||||
{
|
{
|
||||||
const char *isSpawnBiome = getValidSpawnBiomes();
|
const char *isSpawnBiome = getValidSpawnBiomes();
|
||||||
@ -1351,13 +1430,18 @@ Pos getSpawn(const Generator *g)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
uint64_t rnd;
|
uint64_t rnd;
|
||||||
setSeed(&rnd, g->seed);
|
if (g->mc <= MC_1_17)
|
||||||
spawn = locateBiome(g, 0, 63, 0, 256, isSpawnBiome, &rnd, &found);
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
{
|
||||||
//printf("Unable to find spawn biome.\n");
|
setSeed(&rnd, g->seed);
|
||||||
spawn.x = spawn.z = 8;
|
spawn = locateBiome(g, 0, 63, 0, 256, isSpawnBiome, &rnd, &found);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
spawn.x = spawn.z = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spawn = findFittestPos(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
double accum = 1;
|
double accum = 1;
|
||||||
@ -1374,7 +1458,7 @@ Pos getSpawn(const Generator *g)
|
|||||||
{
|
{
|
||||||
if (j > -16 && j <= 16 && k > -16 && k <= 16)
|
if (j > -16 && j <= 16 && k > -16 && k <= 16)
|
||||||
{
|
{
|
||||||
if (findServerSpawn(g, (spawn.x>>4)+j, (spawn.x>>4)+k,
|
if (findServerSpawn(g, (spawn.x>>4)+j, (spawn.z>>4)+k,
|
||||||
&bx, &bz, &bn, &accum))
|
&bx, &bz, &bn, &accum))
|
||||||
{
|
{
|
||||||
spawn.x = (int) round(bx / bn);
|
spawn.x = (int) round(bx / bn);
|
||||||
@ -1420,25 +1504,30 @@ Pos getSpawn(const Generator *g)
|
|||||||
return spawn;
|
return spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pos estimateSpawn(const Generator *g)
|
Pos estimateSpawn(const Generator *g)
|
||||||
{
|
{
|
||||||
const char *isSpawnBiome = getValidSpawnBiomes();
|
const char *isSpawnBiome = getValidSpawnBiomes();
|
||||||
Pos spawn;
|
Pos spawn;
|
||||||
int found;
|
|
||||||
uint64_t rnd;
|
|
||||||
setSeed(&rnd, g->seed);
|
|
||||||
spawn = locateBiome(g, 0, 63, 0, 256, isSpawnBiome, &rnd, &found);
|
|
||||||
|
|
||||||
if (!found)
|
if (g->mc <= MC_1_17)
|
||||||
{
|
{
|
||||||
spawn.x = spawn.z = 8;
|
int found;
|
||||||
|
uint64_t rnd;
|
||||||
|
setSeed(&rnd, g->seed);
|
||||||
|
spawn = locateBiome(g, 0, 63, 0, 256, isSpawnBiome, &rnd, &found);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
spawn.x = spawn.z = 8;
|
||||||
|
}
|
||||||
|
if (g->mc >= MC_1_13)
|
||||||
|
{
|
||||||
|
spawn.x &= ~0xf;
|
||||||
|
spawn.z &= ~0xf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (g->mc >= MC_1_13)
|
|
||||||
{
|
{
|
||||||
spawn.x &= ~0xf;
|
spawn = findFittestPos(g);
|
||||||
spawn.z &= ~0xf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return spawn;
|
return spawn;
|
||||||
|
46
layers.c
46
layers.c
@ -1354,11 +1354,12 @@ int p2overworld(const uint64_t np[6], uint64_t *dat);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Biome sampler for MC 1.18
|
/// Biome sampler for MC 1.18
|
||||||
int sampleBiomeNoise(const BiomeNoise *bn, int x, int y, int z, uint64_t *dat, int approx)
|
int sampleBiomeNoise(const BiomeNoise *bn, int64_t *np, int x, int y, int z,
|
||||||
|
uint64_t *dat, uint32_t flags)
|
||||||
{
|
{
|
||||||
float t = 0, h = 0, c = 0, e = 0, d = 0, w = 0;
|
float t = 0, h = 0, c = 0, e = 0, d = 0, w = 0;
|
||||||
double px = x, pz = z;
|
double px = x, pz = z;
|
||||||
if (approx == 0)
|
if (!(flags & SAMPLE_NO_SHIFT))
|
||||||
{
|
{
|
||||||
px += sampleDoublePerlin(&bn->shift, x, 0, z) * 4.0;
|
px += sampleDoublePerlin(&bn->shift, x, 0, z) * 4.0;
|
||||||
pz += sampleDoublePerlin(&bn->shift, z, x, 0) * 4.0;
|
pz += sampleDoublePerlin(&bn->shift, z, x, 0) * 4.0;
|
||||||
@ -1368,27 +1369,32 @@ int sampleBiomeNoise(const BiomeNoise *bn, int x, int y, int z, uint64_t *dat, i
|
|||||||
e = sampleDoublePerlin(&bn->erosion, px, 0, pz);
|
e = sampleDoublePerlin(&bn->erosion, px, 0, pz);
|
||||||
w = sampleDoublePerlin(&bn->weirdness, px, 0, pz);
|
w = sampleDoublePerlin(&bn->weirdness, px, 0, pz);
|
||||||
|
|
||||||
float np_param[] = {
|
if (!(flags & SAMPLE_NO_DEPTH))
|
||||||
c, e, -3.0F * ( fabsf( fabsf(w) - 0.6666667F ) - 0.33333334F ), w,
|
{
|
||||||
};
|
float np_param[] = {
|
||||||
double off = getSpline(bn->sp, np_param) + 0.015F;
|
c, e, -3.0F * ( fabsf( fabsf(w) - 0.6666667F ) - 0.33333334F ), w,
|
||||||
|
};
|
||||||
|
double off = getSpline(bn->sp, np_param) + 0.015F;
|
||||||
|
|
||||||
//double py = y + sampleDoublePerlin(&bn->shift, y, z, x) * 4.0;
|
//double py = y + sampleDoublePerlin(&bn->shift, y, z, x) * 4.0;
|
||||||
d = 1.0 - (y << 2) / 128.0 - 83.0/160.0 + off;
|
d = 1.0 - (y << 2) / 128.0 - 83.0/160.0 + off;
|
||||||
|
}
|
||||||
|
|
||||||
t = sampleDoublePerlin(&bn->temperature, px, 0, pz);
|
t = sampleDoublePerlin(&bn->temperature, px, 0, pz);
|
||||||
h = sampleDoublePerlin(&bn->humidity, px, 0, pz);
|
h = sampleDoublePerlin(&bn->humidity, px, 0, pz);
|
||||||
|
|
||||||
int64_t np[] = {
|
int64_t l_np[6];
|
||||||
(int64_t)(10000.0F*t),
|
int64_t *p_np = np ? np : l_np;
|
||||||
(int64_t)(10000.0F*h),
|
p_np[0] = (int64_t)(10000.0F*t);
|
||||||
(int64_t)(10000.0F*c),
|
p_np[1] = (int64_t)(10000.0F*h);
|
||||||
(int64_t)(10000.0F*e),
|
p_np[2] = (int64_t)(10000.0F*c);
|
||||||
(int64_t)(10000.0F*d),
|
p_np[3] = (int64_t)(10000.0F*e);
|
||||||
(int64_t)(10000.0F*w),
|
p_np[4] = (int64_t)(10000.0F*d);
|
||||||
};
|
p_np[5] = (int64_t)(10000.0F*w);
|
||||||
|
|
||||||
int id = p2overworld((const uint64_t*)np, dat);
|
int id = none;
|
||||||
|
if (!(flags & SAMPLE_NO_BIOME))
|
||||||
|
id = p2overworld((const uint64_t*)p_np, dat);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1396,6 +1402,8 @@ int sampleBiomeNoise(const BiomeNoise *bn, int x, int y, int z, uint64_t *dat, i
|
|||||||
static void genBiomeNoise3D(const BiomeNoise *bn, int *out, Range r, int opt)
|
static void genBiomeNoise3D(const BiomeNoise *bn, int *out, Range r, int opt)
|
||||||
{
|
{
|
||||||
uint64_t dat = 0;
|
uint64_t dat = 0;
|
||||||
|
uint64_t *p_dat = opt ? &dat : NULL;
|
||||||
|
uint32_t flags = opt ? SAMPLE_NO_SHIFT : 0;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
int *p = out;
|
int *p = out;
|
||||||
int scale = r.scale > 4 ? r.scale / 4 : 1;
|
int scale = r.scale > 4 ? r.scale / 4 : 1;
|
||||||
@ -1409,7 +1417,7 @@ static void genBiomeNoise3D(const BiomeNoise *bn, int *out, Range r, int opt)
|
|||||||
for (i = 0; i < r.sx; i++)
|
for (i = 0; i < r.sx; i++)
|
||||||
{
|
{
|
||||||
int xi = (r.x+i)*scale + mid;
|
int xi = (r.x+i)*scale + mid;
|
||||||
*p = sampleBiomeNoise(bn, xi, yk, zj, opt ? &dat : NULL, opt);
|
*p = sampleBiomeNoise(bn, NULL, xi, yk, zj, p_dat, flags);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1457,7 +1465,7 @@ int genBiomeNoiseScaled(const BiomeNoise *bn, int *out, Range r, int mc, uint64_
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*p = sampleBiomeNoise(bn, x4, y4, z4, 0, 0);
|
*p = sampleBiomeNoise(bn, 0, x4, y4, z4, 0, 0);
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
8
layers.h
8
layers.h
@ -436,9 +436,15 @@ int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha);
|
|||||||
* The 1.18 End generation remains similar to 1.17 and does NOT use the
|
* The 1.18 End generation remains similar to 1.17 and does NOT use the
|
||||||
* biome noise.
|
* biome noise.
|
||||||
*/
|
*/
|
||||||
|
enum {
|
||||||
|
SAMPLE_NO_SHIFT = 0x1,
|
||||||
|
SAMPLE_NO_DEPTH = 0x2,
|
||||||
|
SAMPLE_NO_BIOME = 0x4,
|
||||||
|
};
|
||||||
void initBiomeNoise(BiomeNoise *bn, int mc);
|
void initBiomeNoise(BiomeNoise *bn, int mc);
|
||||||
void setBiomeSeed(BiomeNoise *bn, uint64_t seed, int large);
|
void setBiomeSeed(BiomeNoise *bn, uint64_t seed, int large);
|
||||||
int sampleBiomeNoise(const BiomeNoise *bn, int x, int y, int z, uint64_t *dat, int approx);
|
int sampleBiomeNoise(const BiomeNoise *bn, int64_t *np, int x, int y, int z,
|
||||||
|
uint64_t *dat, uint32_t flags);
|
||||||
/**
|
/**
|
||||||
* The scaled biome noise generation applies for the Overworld version 1.18.
|
* The scaled biome noise generation applies for the Overworld version 1.18.
|
||||||
* The 'sha' hash of the seed is only required for voronoi at scale 1:1.
|
* The 'sha' hash of the seed is only required for voronoi at scale 1:1.
|
||||||
|
21
tests.c
21
tests.c
@ -112,7 +112,7 @@ int testBiomeGen1x1(const int *mc, const uint32_t *expect, int dim, int bits, in
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
double t = -now();
|
double t = -now();
|
||||||
h = getRef(mc[test], dim, bits, spread, "t16");
|
h = getRef(mc[test], dim, bits, spread, NULL);
|
||||||
t += now();
|
t += now();
|
||||||
printf("got %08x %s\e[0m (%ld msec)\n",
|
printf("got %08x %s\e[0m (%ld msec)\n",
|
||||||
h, h == expect[test] ? "\e[1;92mOK" : "\e[1;91mFAILED",
|
h, h == expect[test] ? "\e[1;92mOK" : "\e[1;91mFAILED",
|
||||||
@ -158,6 +158,8 @@ uint32_t testAreas(int mc, int dim, int scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int testGeneration()
|
int testGeneration()
|
||||||
{
|
{
|
||||||
const int mc_vers[] = {
|
const int mc_vers[] = {
|
||||||
@ -172,9 +174,20 @@ int testGeneration()
|
|||||||
};
|
};
|
||||||
const int testcnt = sizeof(mc_vers) / sizeof(int);
|
const int testcnt = sizeof(mc_vers) / sizeof(int);
|
||||||
|
|
||||||
printf("Testing 1x1 biome generation (quick):\n");
|
//printf("Testing 1x1 biome generation (quick):\n");
|
||||||
if (!testBiomeGen1x1(mc_vers, b6_hashes, 0, 6, 1, 1))// testcnt))
|
//if (!testBiomeGen1x1(mc_vers, b6_hashes, 0, 6, 1, testcnt))
|
||||||
;//return -1;
|
// return -1;
|
||||||
|
|
||||||
|
Generator g;
|
||||||
|
setupGenerator(&g, MC_1_18, 0);
|
||||||
|
applySeed(&g, 0, 1234);
|
||||||
|
Pos p = getSpawn(&g);
|
||||||
|
printf("%d %d\n", p.x, p.z);
|
||||||
|
|
||||||
|
StrongholdIter sh;
|
||||||
|
initFirstStronghold(&sh, g.mc, g.seed);
|
||||||
|
while (nextStronghold(&sh, &g) > 0)
|
||||||
|
printf("Stronghold #: (%6d, %6d)\n", sh.pos.x, sh.pos.z);
|
||||||
|
|
||||||
printf("Area generation tests:\n");
|
printf("Area generation tests:\n");
|
||||||
testAreas(MC_1_18, 0, 1);
|
testAreas(MC_1_18, 0, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user