mirror of
https://github.com/Cubitect/cubiomes.git
synced 2025-09-24 04:03:39 -04:00
Check MC in structure validation + scanning for quad-huts.
This commit is contained in:
parent
13c9e34f89
commit
496c6a2f6a
107
finders.c
107
finders.c
@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -150,8 +151,8 @@ int isTreasureChunk(int64_t seed, int chunkX, int chunkZ)
|
||||
*/
|
||||
int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
|
||||
{
|
||||
int minX = 3e7, minZ = 3e7, maxX = -3e7, maxZ = -3e7;
|
||||
int bestr, bestn, i, x, z, px, pz;
|
||||
int64_t minX = INT_MAX, minZ = INT_MAX, maxX = INT_MIN, maxZ = INT_MIN;
|
||||
int64_t bestr, bestn, i, x, z, px, pz;
|
||||
|
||||
|
||||
// Find corners
|
||||
@ -169,6 +170,7 @@ int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
|
||||
maxZ += az;
|
||||
bestr = 0;
|
||||
bestn = 0;
|
||||
double afkx = 0, afkz = 0;
|
||||
|
||||
double thsq = 128.0*128.0 - ay*ay/4.0;
|
||||
|
||||
@ -198,8 +200,8 @@ int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
|
||||
{
|
||||
if (afk)
|
||||
{
|
||||
afk->x = x;
|
||||
afk->z = z;
|
||||
afkx = x;
|
||||
afkz = z;
|
||||
bestn = 1;
|
||||
}
|
||||
bestr = inrange;
|
||||
@ -208,8 +210,8 @@ int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
|
||||
{
|
||||
if (afk)
|
||||
{
|
||||
afk->x += x;
|
||||
afk->z += z;
|
||||
afkx += x;
|
||||
afkz += z;
|
||||
bestn++;
|
||||
}
|
||||
}
|
||||
@ -218,8 +220,8 @@ int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
|
||||
|
||||
if (afk && bestn)
|
||||
{
|
||||
afk->x /= bestn;
|
||||
afk->z /= bestn;
|
||||
afk->x = (int)round(afkx / bestn);
|
||||
afk->z = (int)round(afkz / bestn);
|
||||
}
|
||||
|
||||
return bestr;
|
||||
@ -593,6 +595,40 @@ L_ERR:
|
||||
}
|
||||
|
||||
|
||||
int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
|
||||
int x, int z, int w, int h, Pos *qplist, int n)
|
||||
{
|
||||
const int m = (1LL << 20);
|
||||
const int64_t A = 341873128712LL;
|
||||
const int64_t invB = 132477LL; // = mulInv(132897987541LL, m);
|
||||
|
||||
if (n < 1)
|
||||
return 0;
|
||||
|
||||
int i, j, cnt = 0;
|
||||
for (i = x; i <= x+w; i++)
|
||||
{
|
||||
int64_t sx = s48 + A * i;
|
||||
j = (z & ~(m-1)) | ((low20 - sx) * invB & (m-1));
|
||||
if (j < z)
|
||||
j += m;
|
||||
for (; j <= z+h; j += m)
|
||||
{
|
||||
int64_t sp = moveStructure(s48, -i, -j);
|
||||
if (isQuadBase(sconf, sp - sconf.salt, 128))
|
||||
{
|
||||
qplist[cnt].x = i;
|
||||
qplist[cnt].z = j;
|
||||
cnt++;
|
||||
if (cnt >= n)
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Checking Biomes & Biome Helper Functions
|
||||
@ -1193,7 +1229,9 @@ int isViableFeatureBiome(int structureType, int biomeID)
|
||||
case Mansion:
|
||||
return biomeID == dark_forest || biomeID == dark_forest_hills;
|
||||
default:
|
||||
fprintf(stderr, "ERR isViableFeatureBiome: not implemented for structure type.\n");
|
||||
fprintf(stderr,
|
||||
"isViableFeatureBiome: not implemented for structure type %d.\n",
|
||||
structureType);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
@ -1359,13 +1397,18 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
|
||||
switch (structureType)
|
||||
{
|
||||
case Desert_Pyramid:
|
||||
case Jungle_Pyramid:
|
||||
case Swamp_Hut:
|
||||
case Igloo:
|
||||
case Ocean_Ruin:
|
||||
case Shipwreck:
|
||||
case Treasure:
|
||||
if (mcversion < MC_1_13) goto L_NOT_VIABLE;
|
||||
goto L_FEATURE;
|
||||
case Igloo:
|
||||
if (mcversion < MC_1_9) goto L_NOT_VIABLE;
|
||||
goto L_FEATURE;
|
||||
case Desert_Pyramid:
|
||||
case Jungle_Pyramid:
|
||||
case Swamp_Hut:
|
||||
L_FEATURE:
|
||||
if (mcversion < MC_1_16)
|
||||
{
|
||||
l = &g->layers[L_VORONOI_ZOOM_1];
|
||||
@ -1414,7 +1457,7 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
|
||||
case Outpost:
|
||||
{
|
||||
if (!testOutpostPos(seed, chunkX, chunkZ))
|
||||
if (mcversion < MC_1_14 || !testOutpostPos(seed, chunkX, chunkZ))
|
||||
goto L_NOT_VIABLE;
|
||||
if (mcversion < MC_1_16)
|
||||
{
|
||||
@ -1458,7 +1501,18 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
}
|
||||
|
||||
case Monument:
|
||||
if (mcversion >= MC_1_9)
|
||||
if (mcversion < MC_1_8)
|
||||
goto L_NOT_VIABLE;
|
||||
else if (mcversion == MC_1_8)
|
||||
{
|
||||
// In 1.8 monuments require only a single deep ocean block.
|
||||
l = g->entry_1;
|
||||
setWorldSeed(l, seed);
|
||||
map = allocCache(l, 1, 1);
|
||||
if (genArea(l, map, blockX, blockZ, 1, 1))
|
||||
goto L_NOT_VIABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Monuments require two viability checks with the ocean layer
|
||||
// branch => worth checking for potential deep ocean beforehand.
|
||||
@ -1468,15 +1522,6 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
if (genArea(l, map, chunkX, chunkZ, 1, 1))
|
||||
goto L_NOT_VIABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In 1.8 monuments require only a single deep ocean block.
|
||||
l = g->entry_1;
|
||||
setWorldSeed(l, seed);
|
||||
map = allocCache(l, 1, 1);
|
||||
if (genArea(l, map, blockX, blockZ, 1, 1))
|
||||
goto L_NOT_VIABLE;
|
||||
}
|
||||
if (!isDeepOcean(map[0]))
|
||||
goto L_NOT_VIABLE;
|
||||
if (mcversion >= MC_1_13)
|
||||
@ -1490,6 +1535,8 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
goto L_NOT_VIABLE;
|
||||
|
||||
case Mansion:
|
||||
if (mcversion < MC_1_11)
|
||||
goto L_NOT_VIABLE;
|
||||
l = &g->layers[L_RIVER_MIX_4];
|
||||
setWorldSeed(l, seed);
|
||||
if (areBiomesViable(l, NULL, blockX, blockZ, 32, getValidMansionBiomes()))
|
||||
@ -1497,10 +1544,14 @@ int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
|
||||
goto L_NOT_VIABLE;
|
||||
|
||||
case Ruined_Portal:
|
||||
goto L_VIABLE;
|
||||
if (mcversion >= MC_1_16)
|
||||
goto L_VIABLE;
|
||||
goto L_NOT_VIABLE;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "ERR isViableStructurePos: validation for structure type not implemented");
|
||||
fprintf(stderr,
|
||||
"isViableStructurePos: validation for structure type %d not implemented",
|
||||
structureType);
|
||||
goto L_NOT_VIABLE;
|
||||
}
|
||||
|
||||
@ -1594,7 +1645,7 @@ BiomeFilter setupBiomeFilter(const int *biomeList, int listLen)
|
||||
id = biomeList[i];
|
||||
if (id & ~0xbf) // i.e. not in ranges [0,64),[128,192)
|
||||
{
|
||||
fprintf(stderr, "ERR: biomeID=%d not supported by filter.\n", id);
|
||||
fprintf(stderr, "setupBiomeFilter: biomeID=%d not supported.\n", id);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -1642,6 +1693,8 @@ BiomeFilter setupBiomeFilter(const int *biomeList, int listLen)
|
||||
if (id == bamboo_jungle || id == bamboo_jungle_hills) {
|
||||
// bamboo%64 are End biomes, so we can reuse the edgesToFind
|
||||
bf.edgesToFind |= (1ULL << (bamboo_jungle & 0x3f));
|
||||
bf.raresToFindM |= (1ULL << (id-128));
|
||||
bf.riverToFindM |= (1ULL << (id-128));
|
||||
} else if (id == jungle_edge) {
|
||||
// un-modified jungle_edge can be created at shore layer
|
||||
bf.riverToFind |= (1ULL << jungle_edge);
|
||||
|
35
finders.h
35
finders.h
@ -25,7 +25,7 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define MASK48 ((1LL << 48) - 1)
|
||||
#define MASK48 (((int64_t)1 << 48) - 1)
|
||||
#define PI 3.141592653589793
|
||||
|
||||
#define LARGE_STRUCT 1
|
||||
@ -66,14 +66,14 @@ STRUCT(StructureConfig)
|
||||
|
||||
/* for desert pyramids, jungle temples, witch huts and igloos prior to 1.13 */
|
||||
static const StructureConfig FEATURE_CONFIG = { 14357617, 32, 24, Feature, 0};
|
||||
static const StructureConfig DESERT_CONFIG_17 = { 14357617, 32, 24, Desert_Pyramid, 0};
|
||||
static const StructureConfig IGLOO_CONFIG_17 = { 14357617, 32, 24, Igloo, 0};
|
||||
static const StructureConfig JUNGLE_CONFIG_17 = { 14357617, 32, 24, Jungle_Pyramid, 0};
|
||||
static const StructureConfig SWAMP_HUT_CONFIG_17 = { 14357617, 32, 24, Swamp_Hut, 0};
|
||||
static const StructureConfig IGLOO_CONFIG_112 = { 14357617, 32, 24, Igloo, 0};
|
||||
static const StructureConfig SWAMP_HUT_CONFIG_112 = { 14357617, 32, 24, Swamp_Hut, 0};
|
||||
static const StructureConfig DESERT_PYRAMID_CONFIG_112 = { 14357617, 32, 24, Desert_Pyramid, 0};
|
||||
static const StructureConfig JUNGLE_PYRAMID_CONFIG_112 = { 14357617, 32, 24, Jungle_Pyramid, 0};
|
||||
|
||||
/* ocean features before 1.16 */
|
||||
static const StructureConfig OCEAN_RUIN_CONFIG_113 = { 14357621, 16, 8, Ocean_Ruin, 0};
|
||||
static const StructureConfig SHIPWRECK_CONFIG_113 = {165745295, 15, 7, Shipwreck, 0};
|
||||
static const StructureConfig OCEAN_RUIN_CONFIG_115 = { 14357621, 16, 8, Ocean_Ruin, 0};
|
||||
static const StructureConfig SHIPWRECK_CONFIG_115 = {165745295, 15, 7, Shipwreck, 0};
|
||||
|
||||
/* 1.13 separated feature seeds by type */
|
||||
static const StructureConfig DESERT_PYRAMID_CONFIG = { 14357617, 32, 24, Desert_Pyramid, 0};
|
||||
@ -399,6 +399,23 @@ int searchAll48(
|
||||
|
||||
int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk);
|
||||
|
||||
/* Scans the seed 's48' for quad-structures in the given area of region
|
||||
* coordiantes. The search is performed for only a specific lower 20-bits of
|
||||
* the transformed bases (i.e. each call looks for only one constellation of
|
||||
* quad-structure).
|
||||
*
|
||||
* @sconf : structure config (SWAMP_HUT_CONFIG or FEATURE_CONFIG)
|
||||
* @s48 : 48-bit seed to scan
|
||||
* @low20 : only consider transformations that yield these lower bits
|
||||
* @x,z,w,h : area to scan in region coordinates (inclusive)
|
||||
* @qplist : output region coordinates for the descovered quad-structures
|
||||
* @n : maximum number of quad-structures to look for
|
||||
*
|
||||
* Returns the number of quad-structures found (up to 'n').
|
||||
*/
|
||||
int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
|
||||
int x, int z, int w, int h, Pos *qplist, int n);
|
||||
|
||||
//==============================================================================
|
||||
// Checking Biomes & Biome Helper Functions
|
||||
//==============================================================================
|
||||
@ -835,8 +852,8 @@ static inline float isQuadBase(const StructureConfig sconf, int64_t seed, int ra
|
||||
//case Ruined_Portal:
|
||||
|
||||
default:
|
||||
fprintf(stderr, "ERR isQuadBase: not implemented for structure type"
|
||||
" %d\n", sconf.structType);
|
||||
fprintf(stderr, "isQuadBase: not implemented for structure type %d\n",
|
||||
sconf.structType);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
27
javarnd.h
27
javarnd.h
@ -81,7 +81,8 @@ static inline void skipNextN(int64_t *seed, const int n)
|
||||
* Returns the previous 48-bit seed which will generate 'nseed'.
|
||||
* The upper 16 bits are ignored, both here and in the generator.
|
||||
*/
|
||||
static inline int64_t invSeed48(int64_t nseed)
|
||||
static inline __attribute__((const))
|
||||
int64_t invSeed48(int64_t nseed)
|
||||
{
|
||||
const int64_t x = 0x5deece66d;
|
||||
const int64_t xinv = 0xdfe05bcb1365LL;
|
||||
@ -111,4 +112,28 @@ static inline int64_t invSeed48(int64_t nseed)
|
||||
}
|
||||
|
||||
|
||||
/* Find the modular inverse: (1/x) | mod m.
|
||||
* Assumes x and m are positive and co-prime.
|
||||
*/
|
||||
static inline __attribute__((const))
|
||||
int64_t mulInv(int64_t x, int64_t m)
|
||||
{
|
||||
int64_t t, q, a, b;
|
||||
if (m == 1)
|
||||
return 0; // no solution
|
||||
|
||||
a = 0; b = 1;
|
||||
|
||||
while (x > 1)
|
||||
{
|
||||
if (m == 0)
|
||||
return 0; // x and m are co-prime
|
||||
q = x / m;
|
||||
t = m; m = x % m; x = t;
|
||||
t = a; a = b - q * a; b = t;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
#endif /* JAVARND_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user