mirror of
https://github.com/Cubitect/cubiomes.git
synced 2025-09-22 11:04:57 -04:00
API change for getStructurePos to support new structs for Nether and End
This commit is contained in:
parent
19aa9b4944
commit
0224865935
193
finders.c
193
finders.c
@ -74,57 +74,109 @@ int64_t *loadSavedSeeds(const char *fnam, int64_t *scnt)
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
|
||||||
static int testOutpostPos(int64_t s, int cx, int cz)
|
void setAttemptSeed(int64_t *s, int cx, int cz)
|
||||||
{
|
{
|
||||||
s ^= (cx >> 4) ^ ( (cz >> 4) << 4 );
|
*s ^= (cx >> 4) ^ ( (cz >> 4) << 4 );
|
||||||
setSeed(&s, s);
|
setSeed(s, *s);
|
||||||
next(&s, 32);
|
next(s, 31);
|
||||||
return nextInt(&s, 5) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pos getStructurePos(StructureConfig config, int64_t seed, int regX, int regZ, int *valid)
|
int getStructurePos(int structureType, int mc, int64_t seed, int regX, int regZ, Pos *pos)
|
||||||
{
|
{
|
||||||
Pos pos = {0,0};
|
StructureConfig sconf;
|
||||||
if (valid) *valid = 0;
|
switch (structureType)
|
||||||
|
{
|
||||||
|
case Feature:
|
||||||
|
if (mc > MC_1_12) return 0;
|
||||||
|
sconf = FEATURE_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Desert_Pyramid:
|
||||||
|
sconf = mc <= MC_1_12 ? DESERT_PYRAMID_CONFIG_112 : DESERT_PYRAMID_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Jungle_Pyramid:
|
||||||
|
sconf = mc <= MC_1_12 ? JUNGLE_PYRAMID_CONFIG_112 : JUNGLE_PYRAMID_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Swamp_Hut:
|
||||||
|
sconf = mc <= MC_1_12 ? SWAMP_HUT_CONFIG_112 : SWAMP_HUT_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Igloo:
|
||||||
|
if (mc < MC_1_9) return 0;
|
||||||
|
sconf = mc <= MC_1_12 ? IGLOO_CONFIG_112 : IGLOO_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Village:
|
||||||
|
sconf = VILLAGE_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Ocean_Ruin:
|
||||||
|
if (mc < MC_1_13) return 0;
|
||||||
|
sconf = mc <= MC_1_15 ? OCEAN_RUIN_CONFIG_115 : OCEAN_RUIN_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Shipwreck:
|
||||||
|
if (mc < MC_1_13) return 0;
|
||||||
|
sconf = mc <= MC_1_15 ? SHIPWRECK_CONFIG_115 : SHIPWRECK_CONFIG;
|
||||||
|
goto L_feature;
|
||||||
|
case Ruined_Portal:
|
||||||
|
if (mc < MC_1_16) return 0;
|
||||||
|
sconf = RUINED_PORTAL_CONFIG;
|
||||||
|
L_feature:
|
||||||
|
*pos = getFeaturePos(sconf, seed, regX, regZ);
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (config.properties == 0)
|
case Monument:
|
||||||
{
|
if (mc < MC_1_8) return 0;
|
||||||
pos = getFeaturePos(config, seed, regX, regZ);
|
sconf = MONUMENT_CONFIG;
|
||||||
if (valid)
|
goto L_large_struct;
|
||||||
{
|
case End_City:
|
||||||
if (config.structType == Outpost)
|
if (mc < MC_1_9) return 0;
|
||||||
{
|
sconf = END_CITY_CONFIG;
|
||||||
*valid = testOutpostPos(seed, pos.x >> 4, pos.z >> 4);
|
goto L_large_struct;
|
||||||
// Outposts also require that there are no villages nearby.
|
case Mansion:
|
||||||
// However, before 1.16 this would include a biome check, so it
|
if (mc < MC_1_11) return 0;
|
||||||
// should be tested for in the position viability check.
|
sconf = MANSION_CONFIG;
|
||||||
}
|
L_large_struct:
|
||||||
else
|
*pos = getLargeStructurePos(sconf, seed, regX, regZ);
|
||||||
{
|
return 1;
|
||||||
*valid = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (config.properties == LARGE_STRUCT)
|
|
||||||
{
|
|
||||||
if ((config.chunkRange & (config.chunkRange-1)))
|
|
||||||
{
|
|
||||||
pos = getLargeStructurePos(config, seed, regX, regZ);
|
|
||||||
if (valid) *valid = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (config.properties == CHUNK_STRUCT)
|
|
||||||
{
|
|
||||||
pos.x = (regX << 4) + 9;
|
|
||||||
pos.z = (regZ << 4) + 9;
|
|
||||||
if (valid)
|
|
||||||
{
|
|
||||||
if (config.structType == Treasure)
|
|
||||||
*valid = isTreasureChunk(seed, regX, regZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos;
|
case Outpost:
|
||||||
|
if (mc < MC_1_14) return 0;
|
||||||
|
*pos = getFeaturePos(OUTPOST_CONFIG, seed, regX, regZ);
|
||||||
|
setAttemptSeed(&seed, (pos->x) >> 4, (pos->z) >> 4);
|
||||||
|
return nextInt(&seed, 5) == 0;
|
||||||
|
|
||||||
|
case Treasure:
|
||||||
|
if (mc < MC_1_13) return 0;
|
||||||
|
pos->x = (regX << 4) + 9;
|
||||||
|
pos->z = (regZ << 4) + 9;
|
||||||
|
return isTreasureChunk(seed, regX, regZ);
|
||||||
|
|
||||||
|
case Fortress:
|
||||||
|
sconf = FORTRESS_CONFIG;
|
||||||
|
if (mc < MC_1_16) {
|
||||||
|
setAttemptSeed(&seed, regX << 4, regZ << 4);
|
||||||
|
int valid = nextInt(&seed, 3) == 0;
|
||||||
|
pos->x = ((regX << 4) + nextInt(&seed, 8) + 4) << 4;
|
||||||
|
pos->z = ((regZ << 4) + nextInt(&seed, 8) + 4) << 4;
|
||||||
|
return valid;
|
||||||
|
} else {
|
||||||
|
setSeed(&seed, regX*341873128712 + regZ*132897987541 + seed + sconf.salt);
|
||||||
|
pos->x = (regX * sconf.regionSize + nextInt(&seed, 24)) << 4;
|
||||||
|
pos->z = (regZ * sconf.regionSize + nextInt(&seed, 24)) << 4;
|
||||||
|
return nextInt(&seed, 5) < 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Bastion:
|
||||||
|
if (mc < MC_1_16) return 0;
|
||||||
|
sconf = BASTION_CONFIG;
|
||||||
|
setSeed(&seed, regX*341873128712 + regZ*132897987541 + seed + sconf.salt);
|
||||||
|
pos->x = (regX * sconf.regionSize + nextInt(&seed, 24)) << 4;
|
||||||
|
pos->z = (regZ * sconf.regionSize + nextInt(&seed, 24)) << 4;
|
||||||
|
return nextInt(&seed, 5) >= 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERR getStructurePos: unsupported structure type %d\n", structureType);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isMineshaftChunk(int64_t seed, int chunkX, int chunkZ)
|
int isMineshaftChunk(int64_t seed, int chunkX, int chunkZ)
|
||||||
@ -503,7 +555,7 @@ int searchAll48(
|
|||||||
|
|
||||||
// split path into directory and file and create missing directories
|
// split path into directory and file and create missing directories
|
||||||
if (pathlen + 8 >= sizeof(dpath))
|
if (pathlen + 8 >= sizeof(dpath))
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
strcpy(dpath, path);
|
strcpy(dpath, path);
|
||||||
|
|
||||||
for (i = pathlen-1; i >= 0; i--)
|
for (i = pathlen-1; i >= 0; i--)
|
||||||
@ -512,7 +564,7 @@ int searchAll48(
|
|||||||
{
|
{
|
||||||
dpath[i] = 0;
|
dpath[i] = 0;
|
||||||
if (mkdirp(dpath))
|
if (mkdirp(dpath))
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,7 +572,7 @@ int searchAll48(
|
|||||||
else if (seedbuf == NULL || buflen == NULL)
|
else if (seedbuf == NULL || buflen == NULL)
|
||||||
{
|
{
|
||||||
// no file and no buffer return: no output possible
|
// no file and no buffer return: no output possible
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the thread info and load progress if present
|
// prepare the thread info and load progress if present
|
||||||
@ -540,7 +592,7 @@ int searchAll48(
|
|||||||
snprintf(info[t].path, sizeof(info[t].path), "%s.part%d", path, t);
|
snprintf(info[t].path, sizeof(info[t].path), "%s.part%d", path, t);
|
||||||
FILE *fp = fopen(info[t].path, "a+");
|
FILE *fp = fopen(info[t].path, "a+");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
|
|
||||||
int c, nnl = 0;
|
int c, nnl = 0;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -607,7 +659,7 @@ int searchAll48(
|
|||||||
// merge partial files
|
// merge partial files
|
||||||
FILE *fp = fopen(path, "w");
|
FILE *fp = fopen(path, "w");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
|
|
||||||
for (t = 0; t < threads; t++)
|
for (t = 0; t < threads; t++)
|
||||||
{
|
{
|
||||||
@ -620,7 +672,7 @@ int searchAll48(
|
|||||||
if (!fwrite(buffer, sizeof(char), n, fp))
|
if (!fwrite(buffer, sizeof(char), n, fp))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
goto L_ERR;
|
goto L_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,7 +725,7 @@ int searchAll48(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (0)
|
if (0)
|
||||||
L_ERR:
|
L_err:
|
||||||
err = 1;
|
err = 1;
|
||||||
|
|
||||||
free(tids);
|
free(tids);
|
||||||
@ -1303,8 +1355,8 @@ Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t
|
|||||||
|
|
||||||
if (mcversion >= MC_1_13)
|
if (mcversion >= MC_1_13)
|
||||||
{
|
{
|
||||||
spawn.x = (spawn.x >> 4) << 4;
|
spawn.x &= ~0xf;
|
||||||
spawn.z = (spawn.z >> 4) << 4;
|
spawn.z &= ~0xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return spawn;
|
return spawn;
|
||||||
@ -1370,6 +1422,20 @@ int isViableFeatureBiome(int mc, int structureType, int biomeID)
|
|||||||
if (mc < MC_1_11) return 0;
|
if (mc < MC_1_11) return 0;
|
||||||
return biomeID == dark_forest || biomeID == dark_forest_hills;
|
return biomeID == dark_forest || biomeID == dark_forest_hills;
|
||||||
|
|
||||||
|
case Fortress:
|
||||||
|
return (biomeID == nether_wastes || biomeID == soul_sand_valley ||
|
||||||
|
biomeID == warped_forest || biomeID == crimson_forest);
|
||||||
|
|
||||||
|
case Bastion:
|
||||||
|
if (mc < MC_1_16) return 0;
|
||||||
|
return (biomeID == nether_wastes || biomeID == soul_sand_valley ||
|
||||||
|
biomeID == warped_forest || biomeID == crimson_forest ||
|
||||||
|
biomeID == basalt_deltas);
|
||||||
|
|
||||||
|
case End_City:
|
||||||
|
if (mc < MC_1_9) return 0;
|
||||||
|
return biomeID == end_midlands || biomeID == end_highlands;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"isViableFeatureBiome: not implemented for structure type %d.\n",
|
"isViableFeatureBiome: not implemented for structure type %d.\n",
|
||||||
@ -1599,7 +1665,11 @@ L_feature:
|
|||||||
|
|
||||||
case Outpost:
|
case Outpost:
|
||||||
{
|
{
|
||||||
if (mc < MC_1_14 || !testOutpostPos(seed, chunkX, chunkZ))
|
if (mc < MC_1_14)
|
||||||
|
goto L_not_viable;
|
||||||
|
int64_t rnd = seed;
|
||||||
|
setAttemptSeed(&rnd, chunkX, chunkZ);
|
||||||
|
if (nextInt(&rnd, 5) != 0)
|
||||||
goto L_not_viable;
|
goto L_not_viable;
|
||||||
if (mc < MC_1_16)
|
if (mc < MC_1_16)
|
||||||
{
|
{
|
||||||
@ -1712,6 +1782,19 @@ L_not_viable:
|
|||||||
return viable;
|
return viable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn,
|
||||||
|
int64_t seed, int blockX, int blockZ)
|
||||||
|
{
|
||||||
|
if (mc < MC_1_16)
|
||||||
|
return structureType == Fortress;
|
||||||
|
|
||||||
|
blockX = ((blockX >> 4) << 2) + 2;
|
||||||
|
blockZ = ((blockZ >> 4) << 2) + 2;
|
||||||
|
setNetherSeed(nn, seed);
|
||||||
|
int biomeID = getNetherBiome(nn, blockX, 0, blockZ);
|
||||||
|
return isViableFeatureBiome(mc, structureType, biomeID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Finding Properties of Structures
|
// Finding Properties of Structures
|
||||||
|
52
finders.h
52
finders.h
@ -46,6 +46,9 @@ enum StructureType
|
|||||||
Outpost,
|
Outpost,
|
||||||
Ruined_Portal,
|
Ruined_Portal,
|
||||||
Treasure,
|
Treasure,
|
||||||
|
Fortress,
|
||||||
|
Bastion,
|
||||||
|
End_City,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum // village house types prior to 1.14
|
enum // village house types prior to 1.14
|
||||||
@ -92,6 +95,12 @@ static const StructureConfig RUINED_PORTAL_CONFIG = { 34222645, 40, 25, Ruined_
|
|||||||
// structures that check each chunk individually
|
// structures that check each chunk individually
|
||||||
static const StructureConfig TREASURE_CONFIG = { 10387320, 1, 1, Treasure, CHUNK_STRUCT};
|
static const StructureConfig TREASURE_CONFIG = { 10387320, 1, 1, Treasure, CHUNK_STRUCT};
|
||||||
|
|
||||||
|
// nether and end structures
|
||||||
|
static const StructureConfig FORTRESS_CONFIG = { 30084232, 27, 4, Fortress, 0};
|
||||||
|
static const StructureConfig BASTION_CONFIG = { 30084232, 27, 4, Bastion, 0};
|
||||||
|
static const StructureConfig END_CITY_CONFIG = { 10387313, 20, 9, End_City, LARGE_STRUCT};
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Biome Tables
|
// Biome Tables
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
@ -270,21 +279,28 @@ int64_t *loadSavedSeeds(const char *fnam, int64_t *scnt);
|
|||||||
// Finding Structure Positions
|
// Finding Structure Positions
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
/* Finds the block position at which the structure generation attempt will
|
|
||||||
* occur within the specified region. This function is a wrapper for the more
|
|
||||||
* specific inlinable functions, which can be found below. You can use
|
|
||||||
* isViableStructurePos() to test if the necessary biome requirements are met
|
|
||||||
* for the structure to actually generate at the returned position (much much
|
|
||||||
* slower than checking attempts).
|
|
||||||
*
|
|
||||||
* @config : the structure configuration
|
|
||||||
* @seed : world seed (only the lower 48-bits are relevant)
|
|
||||||
* @regX,regZ : region coordinates
|
|
||||||
* @valid : some structures, like outposts, can have invalid positions,
|
|
||||||
* use NULL to ignore this options
|
|
||||||
*/
|
|
||||||
Pos getStructurePos(StructureConfig config, int64_t seed, int regX, int regZ, int *valid);
|
|
||||||
|
|
||||||
|
/* Finds the block position of the structure generation attempt in a given
|
||||||
|
* region. You can use isViableStructurePos() to test if the necessary biome
|
||||||
|
* requirements are met for the structure to actually generate at that position.
|
||||||
|
* Some structure types may fail to produce a valid position in the given
|
||||||
|
* region regardless of biomes, in which case the function returns zero.
|
||||||
|
*
|
||||||
|
* @structureType : structure type
|
||||||
|
* @mc : minecraft version
|
||||||
|
* @seed : world seed (only the lower 48-bits are relevant)
|
||||||
|
* @regX,regZ : region coordinates (the region size depends on type)
|
||||||
|
* @pos : output block position
|
||||||
|
*
|
||||||
|
* Returns zero if the position is invalid, or non-zero otherwise.
|
||||||
|
*/
|
||||||
|
int getStructurePos(int structureType, int mc, int64_t seed, int regX, int regZ, Pos *pos);
|
||||||
|
|
||||||
|
/* The inline functions below get the generation attempt position given a
|
||||||
|
* structure configuration. Most small structures use the getFeature..
|
||||||
|
* variants, which have a uniform distribution, while large structures
|
||||||
|
* (monuments and mansions) have a triangular distribution.
|
||||||
|
*/
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
Pos getFeaturePos(StructureConfig config, int64_t seed, int regX, int regZ);
|
Pos getFeaturePos(StructureConfig config, int64_t seed, int regX, int regZ);
|
||||||
|
|
||||||
@ -611,7 +627,7 @@ Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t
|
|||||||
|
|
||||||
/* This function performs a biome check at the specified block coordinates to
|
/* This function performs a biome check at the specified block coordinates to
|
||||||
* determine whether the corresponding structure would spawn there. You can get
|
* determine whether the corresponding structure would spawn there. You can get
|
||||||
* the block positions using the appropriate getXXXPos() function.
|
* the block positions using getStructurePos().
|
||||||
*
|
*
|
||||||
* @structureType : structure type to be checked
|
* @structureType : structure type to be checked
|
||||||
* @mc : minecraft version
|
* @mc : minecraft version
|
||||||
@ -623,6 +639,9 @@ Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t
|
|||||||
*/
|
*/
|
||||||
int isViableStructurePos(int structureType, int mc, LayerStack *g,
|
int isViableStructurePos(int structureType, int mc, LayerStack *g,
|
||||||
int64_t seed, int blockX, int blockZ);
|
int64_t seed, int blockX, int blockZ);
|
||||||
|
int isViableNetherStructurePos(int structureType, int mc, NetherNoise *nn,
|
||||||
|
int64_t seed, int blockX, int blockZ);
|
||||||
|
// TODO: viability checks for end cities
|
||||||
|
|
||||||
/* Checks if the specified structure type could generate in the given biome.
|
/* Checks if the specified structure type could generate in the given biome.
|
||||||
*/
|
*/
|
||||||
@ -727,8 +746,7 @@ Pos getFeatureChunkInRegion(StructureConfig config, int64_t seed, int regX, int
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
// Vanilla like implementation.
|
// Vanilla like implementation.
|
||||||
seed = regionX*341873128712 + regionZ*132897987541 + seed + structureSeed;
|
setSeed(&seed, regX*341873128712 + regZ*132897987541 + seed + config.salt);
|
||||||
setSeed(&(seed));
|
|
||||||
|
|
||||||
Pos pos;
|
Pos pos;
|
||||||
pos.x = nextInt(&seed, 24);
|
pos.x = nextInt(&seed, 24);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user