Somewhat major changes to structure and layer functions.

1) Redone structure validation for 1.16 and for bug fixes.
2) Layer generation was reworked for performace.
This commit is contained in:
Cubitect 2020-07-25 18:16:39 +02:00
parent b26f4eb1f7
commit cf85da7159
9 changed files with 460 additions and 674 deletions

View File

@ -23,7 +23,8 @@ static DWORD WINAPI searchCompactBiomesThread(LPVOID data)
int w = 2*info.range, h = 2*info.range;
int64_t s;
LayerStack g = setupGenerator(MC_1_14);
int mcversion = MC_1_14;
LayerStack g = setupGenerator(mcversion);
int *cache = allocCache(&g.layers[L_VORONOI_ZOOM_1], w, h);
for (s = info.seedStart; s != info.seedEnd; s++)
@ -40,7 +41,7 @@ static DWORD WINAPI searchCompactBiomesThread(LPVOID data)
{
Pos p;
p = getStructurePos(SWAMP_HUT_CONFIG, s, x, z);
if (isViableFeaturePos(Swamp_Hut, g, cache, p.x, p.z))
if (isViableStructurePos(SWAMP_HUT_CONFIG, mcversion, &g, s, p.x, p.z))
goto L_hut_found;
}
}
@ -56,7 +57,7 @@ static DWORD WINAPI searchCompactBiomesThread(LPVOID data)
{
Pos p;
p = getLargeStructurePos(MONUMENT_CONFIG, s, x, z);
if (isViableOceanMonumentPos(g, cache, p.x, p.z))
if (isViableStructurePos(MONUMENT_CONFIG, mcversion, &g, s, p.x, p.z))
goto L_monument_found;
}
}

View File

@ -24,7 +24,7 @@ int main(int argc, char *argv[])
int regPosX = 0;
int regPosZ = 0;
int mcversion = 0;
int mcversion = MC_1_16;
const char *seedFileName;
StructureConfig featureConfig;
@ -35,14 +35,25 @@ int main(int argc, char *argv[])
if (argc > 3)
{
if (sscanf(argv[3], "%d", &mcversion) != 1) mcversion = 0;
int mcarg1 = 0, mcarg2 = 0;
int ac = sscanf(argv[3], "%d.%d", &mcarg1, &mcarg2);
if (ac < 1)
{
printf("Bad version format\n");
exit(1);
}
if (ac > 1)
mcarg1 = 100 * mcarg1 + mcarg2;
if (mcarg1 < 113)
mcversion = MC_1_7;
else if (mcarg1 < 116)
mcversion = MC_1_13;
else
mcversion = MC_1_16;
}
else
{
printf("MC version not specified. Set using 'mcversion' argument:\n"
"17 for MC1.7 - MC1.12\n113 for MC1.13+\n"
"Defaulting to MC 1.7.\n\n");
mcversion = 17;
printf("MC version not specified. Defaulting to 1.16\n");
}
}
else
@ -55,7 +66,7 @@ int main(int argc, char *argv[])
regPosX -= 1;
regPosZ -= 1;
if (mcversion >= 113)
if (mcversion >= MC_1_13)
{
featureConfig = SWAMP_HUT_CONFIG;
seedFileName = "./seeds/quadhutbases_1_13_Q1.txt";
@ -186,11 +197,10 @@ int main(int argc, char *argv[])
if (biomeCache[0] != swamp)
continue;
applySeed(&g, seed);
if (getBiomeAtPos(g, qhpos[0]) != swamp) continue;
if (getBiomeAtPos(g, qhpos[1]) != swamp) continue;
if (getBiomeAtPos(g, qhpos[2]) != swamp) continue;
if (getBiomeAtPos(g, qhpos[3]) != swamp) continue;
if (!isViableStructurePos(SWAMP_HUT_CONFIG, mcversion, &g, seed, qhpos[0].x, qhpos[0].z)) continue;
if (!isViableStructurePos(SWAMP_HUT_CONFIG, mcversion, &g, seed, qhpos[1].x, qhpos[1].z)) continue;
if (!isViableStructurePos(SWAMP_HUT_CONFIG, mcversion, &g, seed, qhpos[2].x, qhpos[2].z)) continue;
if (!isViableStructurePos(SWAMP_HUT_CONFIG, mcversion, &g, seed, qhpos[3].x, qhpos[3].z)) continue;
printf("%" PRId64 "\n", seed);
hits++;

616
finders.c
View File

@ -100,10 +100,10 @@ int64_t *loadSavedSeeds(const char *fnam, int64_t *scnt)
int isQuadFeatureBase(const StructureConfig sconf, const int64_t seed, const int qual)
{
// seed offsets for the regions (0,0) to (1,1)
const int64_t reg00base = sconf.seed;
const int64_t reg01base = 341873128712 + sconf.seed;
const int64_t reg10base = 132897987541 + sconf.seed;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.seed;
const int64_t reg00base = sconf.salt;
const int64_t reg01base = 341873128712 + sconf.salt;
const int64_t reg10base = 132897987541 + sconf.salt;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.salt;
const int range = sconf.chunkRange;
const int upper = range - qual - 1;
@ -141,10 +141,10 @@ int isQuadFeatureBase(const StructureConfig sconf, const int64_t seed, const int
void checkVec4QuadBases(const StructureConfig sconf, int64_t seeds[256])
{
const int64_t reg00base = sconf.seed;
const int64_t reg01base = 341873128712 + sconf.seed;
const int64_t reg10base = 132897987541 + sconf.seed;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.seed;
const int64_t reg00base = sconf.salt;
const int64_t reg01base = 341873128712 + sconf.salt;
const int64_t reg10base = 132897987541 + sconf.salt;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.salt;
int i;
for (i = 0; i < 256; i++)
@ -204,10 +204,10 @@ void checkVec4QuadBases(const StructureConfig sconf, int64_t seeds[256])
int isTriFeatureBase(const StructureConfig sconf, const int64_t seed, const int qual)
{
// seed offsets for the regions (0,0) to (1,1)
const int64_t reg00base = sconf.seed;
const int64_t reg01base = 341873128712 + sconf.seed;
const int64_t reg10base = 132897987541 + sconf.seed;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.seed;
const int64_t reg00base = sconf.salt;
const int64_t reg01base = 341873128712 + sconf.salt;
const int64_t reg10base = 132897987541 + sconf.salt;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.salt;
const int range = sconf.chunkRange;
const int upper = range - qual - 1;
@ -257,10 +257,10 @@ int isTriFeatureBase(const StructureConfig sconf, const int64_t seed, const int
int isLargeQuadBase(const StructureConfig sconf, const int64_t seed, const int qual)
{
// seed offsets for the regions (0,0) to (1,1)
const int64_t reg00base = sconf.seed;
const int64_t reg01base = 341873128712 + sconf.seed;
const int64_t reg10base = 132897987541 + sconf.seed;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.seed;
const int64_t reg00base = sconf.salt;
const int64_t reg01base = 341873128712 + sconf.salt;
const int64_t reg10base = 132897987541 + sconf.salt;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.salt;
// p1 = nextInt(range); p2 = nextInt(range); pos = (p1+p2)>>1
const int range = sconf.chunkRange;
@ -334,10 +334,10 @@ int isLargeQuadBase(const StructureConfig sconf, const int64_t seed, const int q
int isLargeTriBase(const StructureConfig sconf, const int64_t seed, const int qual)
{
// seed offsets for the regions (0,0) to (1,1)
const int64_t reg00base = sconf.seed;
const int64_t reg01base = 341873128712 + sconf.seed;
const int64_t reg10base = 132897987541 + sconf.seed;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.seed;
const int64_t reg00base = sconf.salt;
const int64_t reg01base = 341873128712 + sconf.salt;
const int64_t reg10base = 132897987541 + sconf.salt;
const int64_t reg11base = 341873128712 + 132897987541 + sconf.salt;
// p1 = nextInt(range); p2 = nextInt(range); pos = (p1+p2)>>1
const int range = sconf.chunkRange;
@ -577,7 +577,7 @@ static DWORD WINAPI search4QuadBasesThread(LPVOID data)
lowerBitsCnt = sizeof(lowerBaseBitsQ1) / sizeof(lowerBaseBitsQ1[0]);
for (i = 0; i < lowerBitsCnt; i++)
{
lowerBits[i] = (lowerBaseBitsQ1[i] - stc.seed) & 0xffff;
lowerBits[i] = (lowerBaseBitsQ1[i] - stc.salt) & 0xffff;
}
}
else if (stc.properties == 0 && stc.chunkRange == 24 && info.quality == 2)
@ -585,7 +585,7 @@ static DWORD WINAPI search4QuadBasesThread(LPVOID data)
lowerBitsCnt = sizeof(lowerBaseBitsQ2) / sizeof(lowerBaseBitsQ2[0]);
for (i = 0; i < lowerBitsCnt; i++)
{
lowerBits[i] = (lowerBaseBitsQ2[i] - stc.seed) & 0xffff;
lowerBits[i] = (lowerBaseBitsQ2[i] - stc.salt) & 0xffff;
}
}
else if (stc.properties == 0 && stc.chunkRange == 24 && info.quality == -1)
@ -794,7 +794,7 @@ Pos getStructurePos(const StructureConfig config, int64_t seed,
Pos pos;
// set seed
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.seed;
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.salt;
seed = (seed ^ 0x5deece66dLL);// & ((1LL << 48) - 1);
seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
@ -836,7 +836,7 @@ Pos getStructureChunkInRegion(const StructureConfig config, int64_t seed,
*/
Pos pos;
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.seed;
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.salt;
seed = (seed ^ 0x5deece66dLL);// & ((1LL << 48) - 1);
seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
@ -869,7 +869,7 @@ Pos getLargeStructurePos(StructureConfig config, int64_t seed,
//TODO: power of two chunk ranges...
// set seed
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.seed;
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.salt;
seed = (seed ^ 0x5deece66dLL) & ((1LL << 48) - 1);
seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
@ -898,7 +898,7 @@ Pos getLargeStructureChunkInRegion(StructureConfig config, int64_t seed,
//TODO: power of two chunk ranges...
// set seed
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.seed;
seed = regionX*341873128712 + regionZ*132897987541 + seed + config.salt;
seed = (seed ^ 0x5deece66dLL) & ((1LL << 48) - 1);
seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
@ -931,7 +931,7 @@ int isMineshaftChunk(int64_t seed, const int chunkX, const int chunkZ)
int isTreasureChunk(int64_t seed, const int chunkX, const int chunkZ)
{
seed = chunkX*341873128712 + chunkZ*132897987541 + seed + TREASURE_CONFIG.seed;
seed = chunkX*341873128712 + chunkZ*132897987541 + seed + TREASURE_CONFIG.salt;
setSeed(&seed);
return nextFloat(&seed) < 0.01;
}
@ -953,12 +953,12 @@ int getBiomeAtPos(const LayerStack g, const Pos pos)
Pos findBiomePosition(
const int mcversion,
const LayerStack g,
const Layer *l,
int *cache,
const int centerX,
const int centerZ,
const int range,
const int *isValid,
const char *isValid,
int64_t *seed,
int *passes
)
@ -972,18 +972,17 @@ Pos findBiomePosition(
int *map;
int i, j, found;
Layer *layer = &g.layers[L_RIVER_MIX_4];
Pos out;
if (layer->scale != 4)
if (l->scale != 4)
{
printf("WARN findBiomePosition: The generator has unexpected scale %d at layer %d.\n",
layer->scale, L_RIVER_MIX_4);
printf("WARN findBiomePosition: require scale = 4, but have %d.\n",
l->scale);
}
map = cache ? cache : allocCache(layer, width, height);
map = cache ? cache : allocCache(l, width, height);
genArea(layer, map, x1, z1, width, height);
genArea(l, map, x1, z1, width, height);
out.x = centerX;
out.z = centerZ;
@ -1033,12 +1032,12 @@ Pos findBiomePosition(
int areBiomesViable(
const LayerStack g,
const Layer * l,
int * cache,
const int posX,
const int posZ,
const int radius,
const int * isValid
const char * isValid
)
{
int x1 = (posX - radius) >> 2;
@ -1050,16 +1049,14 @@ int areBiomesViable(
int i;
int *map;
Layer *layer = &g.layers[L_RIVER_MIX_4];
if (layer->scale != 4)
if (l->scale != 4)
{
printf("WARN areBiomesViable: The generator has unexpected scale %d at layer %d.\n",
layer->scale, L_RIVER_MIX_4);
printf("WARN areBiomesViable: require scale = 4, but have %d.\n",
l->scale);
}
map = cache ? cache : allocCache(layer, width, height);
genArea(layer, map, x1, z1, width, height);
map = cache ? cache : allocCache(l, width, height);
genArea(l, map, x1, z1, width, height);
for (i = 0; i < width*height; i++)
{
@ -1121,9 +1118,9 @@ int getBiomeRadius(
//==============================================================================
int* getValidStrongholdBiomes()
const char* getValidStrongholdBiomes()
{
static int validStrongholdBiomes[256];
static char validStrongholdBiomes[256];
if (!validStrongholdBiomes[plains])
{
@ -1139,10 +1136,10 @@ int* getValidStrongholdBiomes()
}
int findStrongholds(const int mcversion, LayerStack *g, int *cache,
int findStrongholds(const int mcversion, const LayerStack *g, int *cache,
Pos *locations, int64_t worldSeed, int maxSH, const int maxRadius)
{
const int *validStrongholdBiomes = getValidStrongholdBiomes();
const char *validStrongholdBiomes = getValidStrongholdBiomes();
int i, x, z;
double distance;
@ -1153,6 +1150,8 @@ int findStrongholds(const int mcversion, LayerStack *g, int *cache,
setSeed(&worldSeed);
double angle = nextDouble(&worldSeed) * PI * 2.0;
const Layer *l = &g->layers[L_RIVER_MIX_4];
if (mcversion >= MC_1_9)
{
if (maxSH <= 0) maxSH = 128;
@ -1168,7 +1167,7 @@ int findStrongholds(const int mcversion, LayerStack *g, int *cache,
x = (int)round(cos(angle) * distance);
z = (int)round(sin(angle) * distance);
locations[i] = findBiomePosition(mcversion, *g, cache,
locations[i] = findBiomePosition(mcversion, l, cache,
(x << 4) + 8, (z << 4) + 8, 112, validStrongholdBiomes,
&worldSeed, NULL);
@ -1201,7 +1200,7 @@ int findStrongholds(const int mcversion, LayerStack *g, int *cache,
x = (int)round(cos(angle) * distance);
z = (int)round(sin(angle) * distance);
locations[i] = findBiomePosition(mcversion, *g, cache,
locations[i] = findBiomePosition(mcversion, l, cache,
(x << 4) + 8, (z << 4) + 8, 112, validStrongholdBiomes,
&worldSeed, NULL);
@ -1269,38 +1268,38 @@ static double getGrassProbability(int64_t seed, int biome, int x, int z)
}
}
static int canCoordinateBeSpawn(const int64_t seed, LayerStack *g, int *cache, Pos pos)
static int canCoordinateBeSpawn(const int64_t seed, const LayerStack *g, int *cache, Pos pos)
{
int biome = getBiomeAtPos(*g, pos);
return getGrassProbability(seed, biome, pos.x, pos.z) >= 0.5;
}
static int* getValidSpawnBiomes()
static const char* getValidSpawnBiomes()
{
static int isSpawnBiome[256];
static const int biomesToSpawnIn[] = {forest, plains, taiga, taiga_hills, wooded_hills, jungle, jungle_hills};
static char isValid[256];
unsigned int i;
if (!isSpawnBiome[biomesToSpawnIn[0]])
{
if (!isValid[biomesToSpawnIn[0]])
for (i = 0; i < sizeof(biomesToSpawnIn) / sizeof(int); i++)
{
isSpawnBiome[ biomesToSpawnIn[i] ] = 1;
}
}
isValid[ biomesToSpawnIn[i] ] = 1;
return isSpawnBiome;
return isValid;
}
Pos getSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed)
Pos getSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed)
{
const int *isSpawnBiome = getValidSpawnBiomes();
const char *isSpawnBiome = getValidSpawnBiomes();
Pos spawn;
int found;
int i;
const Layer *l = &g->layers[L_RIVER_MIX_4];
setSeed(&worldSeed);
spawn = findBiomePosition(mcversion, *g, cache, 0, 0, 256, isSpawnBiome,
spawn = findBiomePosition(mcversion, l, cache, 0, 0, 256, isSpawnBiome,
&worldSeed, &found);
if (!found)
@ -1361,14 +1360,16 @@ Pos getSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed)
}
Pos estimateSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed)
Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed)
{
const int *isSpawnBiome = getValidSpawnBiomes();
const char *isSpawnBiome = getValidSpawnBiomes();
Pos spawn;
int found;
Layer *l = &g->layers[L_RIVER_MIX_4];
setSeed(&worldSeed);
spawn = findBiomePosition(mcversion, *g, cache, 0, 0, 256, isSpawnBiome,
spawn = findBiomePosition(mcversion, l, cache, 0, 0, 256, isSpawnBiome,
&worldSeed, &found);
if (!found)
@ -1386,15 +1387,9 @@ Pos estimateSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldS
//==============================================================================
int isViableFeaturePos(const int structureType, const LayerStack g, int *cache,
const int blockX, const int blockZ)
int isViableFeatureBiome(int structureType, int biomeID)
{
int *map = cache ? cache : allocCache(&g.layers[L_VORONOI_ZOOM_1], 1, 1);
genArea(&g.layers[L_VORONOI_ZOOM_1], map, blockX, blockZ, 1, 1);
int biomeID = map[0];
if (!cache) free(map);
switch(structureType)
switch (structureType)
{
case Desert_Pyramid:
return biomeID == desert || biomeID == desert_hills;
@ -1410,73 +1405,193 @@ int isViableFeaturePos(const int structureType, const LayerStack g, int *cache,
return isOceanic(biomeID) || biomeID == beach || biomeID == snowy_beach;
case Ruined_Portal:
return 1;
case Outpost:
return biomeID == plains || biomeID == desert || biomeID == taiga || biomeID == snowy_tundra || biomeID == savanna;
case Treasure:
return biomeID == beach || biomeID == snowy_beach || biomeID == stone_shore || biomeID == mushroom_field_shore;
default:
fprintf(stderr, "Structure type is not valid for the scattered feature biome check.\n");
fprintf(stderr, "ERR isViableFeatureBiome: not implemented for structure type.\n");
exit(1);
}
return 0;
}
int isViableVillagePos(const LayerStack g, int *cache,
const int blockX, const int blockZ)
static const char *getValidMonumentBiomes1()
{
static int isVillageBiome[0x100];
if (!isVillageBiome[villageBiomeList[0]])
static const int oceanMonumentBiomeList1[] =
{
unsigned int i;
for (i = 0; i < sizeof(villageBiomeList) / sizeof(int); i++)
{
isVillageBiome[ villageBiomeList[i] ] = 1;
}
}
ocean, deep_ocean, river, frozen_river,
frozen_ocean, deep_frozen_ocean, cold_ocean, deep_cold_ocean,
lukewarm_ocean, deep_lukewarm_ocean, warm_ocean, deep_warm_ocean
};
static char isValid[256];
unsigned int i;
return areBiomesViable(g, cache, blockX, blockZ, 0, isVillageBiome);
}
int isViableOceanMonumentPos(const LayerStack g, int *cache,
const int blockX, const int blockZ)
{
static int isWaterBiome[0x100];
static int isDeepOcean[0x100];
if (!isWaterBiome[oceanMonumentBiomeList1[1]])
{
unsigned int i;
if (!isValid[oceanMonumentBiomeList1[0]])
for (i = 0; i < sizeof(oceanMonumentBiomeList1) / sizeof(int); i++)
{
isWaterBiome[ oceanMonumentBiomeList1[i] ] = 1;
}
isValid[ oceanMonumentBiomeList1[i] ] = 1;
for (i = 0; i < sizeof(oceanMonumentBiomeList2) / sizeof(int); i++)
{
isDeepOcean[ oceanMonumentBiomeList2[i] ] = 1;
}
}
return areBiomesViable(g, cache, blockX, blockZ, 16, isDeepOcean) &&
areBiomesViable(g, cache, blockX, blockZ, 29, isWaterBiome);
return isValid;
}
int isViableMansionPos(const LayerStack g, int *cache,
const int blockX, const int blockZ)
static const char *getValidMonumentBiomes2()
{
static int isMansionBiome[0x100];
if (!isMansionBiome[mansionBiomeList[0]])
static const int oceanMonumentBiomeList2[] =
{
unsigned int i;
for (i = 0; i < sizeof(mansionBiomeList) / sizeof(int); i++)
{
isMansionBiome[ mansionBiomeList[i] ] = 1;
}
}
deep_frozen_ocean, deep_cold_ocean, deep_ocean,
deep_lukewarm_ocean, deep_warm_ocean
};
static char isValid[256];
unsigned int i;
return areBiomesViable(g, cache, blockX, blockZ, 32, isMansionBiome);
if (!isValid[oceanMonumentBiomeList2[0]])
for (i = 0; i < sizeof(oceanMonumentBiomeList2) / sizeof(int); i++)
isValid[ oceanMonumentBiomeList2[i] ] = 1;
return isValid;
}
static const char *getValidMansionBiomes()
{
static const int mansionBiomeList[] = {dark_forest, dark_forest+128};
static char isValid[256];
unsigned int i;
if (!isValid[mansionBiomeList[0]])
for (i = 0; i < sizeof(mansionBiomeList) / sizeof(int); i++)
isValid[ mansionBiomeList[i] ] = 1;
return isValid;
}
int isViableStructurePos(const StructureConfig sconf, int mcversion,
LayerStack *g, int64_t seed, int blockX, int blockZ)
{
int biomeID;
int *map = NULL;
Layer *l;
int64_t chunkX = blockX >> 4;
int64_t chunkZ = blockZ >> 4;
// TODO: where possible perform cheaper biome checks before full validation
switch (sconf.structType)
{
case Desert_Pyramid:
case Igloo:
case Jungle_Pyramid:
case Swamp_Hut:
case Ocean_Ruin:
case Shipwreck:
case Ruined_Portal:
case Treasure:
if (mcversion < MC_1_16)
{
l = &g->layers[L_VORONOI_ZOOM_1];
setWorldSeed(l, seed);
map = allocCache(l, 1, 1);
genArea(l, map, blockX, blockZ, 1, 1);
}
else // position and layer check changed position in 1.16
{
l = &g->layers[L_RIVER_MIX_4]; // oceanic checks should be fine here
setWorldSeed(l, seed);
map = allocCache(l, 1, 1);
genArea(l, map, (chunkX << 2) + 2, (chunkZ << 2) + 2, 1, 1);
}
biomeID = map[0];
free(map);
return isViableFeatureBiome(sconf.structType, biomeID);
case Village:
l = &g->layers[L_RIVER_MIX_4];
setWorldSeed(l, seed);
map = allocCache(l, 1, 1);
if (mcversion < MC_1_16) // TODO: check this (and if it makes a difference)
genArea(l, map, blockX >> 2, blockZ >> 2, 1, 1);
else
genArea(l, map, (chunkX << 2) + 2, (chunkZ << 2) + 2, 1, 1);
biomeID = map[0];
free(map);
if (biomeID == plains || biomeID == desert || biomeID == savanna || biomeID == taiga)
return 1;
if (mcversion >= MC_1_14 && biomeID == snowy_tundra)
return 1;
if (mcversion == MC_BE && biomeID == snowy_taiga)
return 1;
return 0;
case Outpost:
{
int64_t rnds = seed;
rnds ^= ((chunkX >> 4) ^ (chunkZ >> 4)) << 4;
setSeed(&rnds);
next(&rnds, 32);
if (nextInt(&rnds, 5) != 0)
return 0;
if (mcversion < MC_1_16)
{
l = &g->layers[L_VORONOI_ZOOM_1];
setWorldSeed(l, seed);
map = allocCache(l, 1, 1);
genArea(l, map, blockX, blockZ, 1, 1);
}
else
{
l = &g->layers[L_RIVER_MIX_4]; // oceanic checks should be fine here
setWorldSeed(l, seed);
map = allocCache(l, 1, 1);
genArea(l, map, (chunkX << 2) + 2, (chunkZ << 2) + 2, 1, 1);
}
biomeID = map[0];
free(map);
// TODO: support for MC_BE
if (biomeID != plains && biomeID != desert && biomeID != taiga && biomeID != snowy_tundra && biomeID != savanna)
return 0;
// look for villages within 10 chunks
int cx0 = (chunkX-10), cx1 = (chunkX+10);
int cz0 = (chunkZ-10), cz1 = (chunkZ+10);
int rx, rz;
for (rz = cz0 >> 5; rz <= cz1 >> 5; rz++)
{
for (rx = cx0 >> 5; rx <= cx1 >> 5; rx++)
{
Pos p = getStructurePos(VILLAGE_CONFIG, seed, rx, rz);
int cx = p.x >> 4, cz = p.z >> 4;
if (cx >= cx0 && cx <= cx1 && cz >= cz0 && cz <= cz1)
{
if (mcversion >= MC_1_16)
return 0;
if (isViableStructurePos(VILLAGE_CONFIG, mcversion, g, seed, p.x, p.z))
return 0;
return 1;
}
}
}
return 1;
}
case Monument:
if (mcversion >= MC_1_13)
l = &g->layers[L13_OCEAN_MIX_4];
else
l = &g->layers[L_RIVER_MIX_4];
setWorldSeed(l, seed);
if (areBiomesViable(l, NULL, blockX, blockZ, 16, getValidMonumentBiomes1()))
if (areBiomesViable(l, NULL, blockX, blockZ, 29, getValidMonumentBiomes2()))
return 1;
return 0;
case Mansion:
l = &g->layers[L_RIVER_MIX_4];
setWorldSeed(l, seed);
return areBiomesViable(l, NULL, blockX, blockZ, 32, getValidMansionBiomes());
default:
fprintf(stderr, "ERR isViableStructurePos: validation for structure type not implemented");
return 0;
}
}
//==============================================================================
@ -1496,7 +1611,7 @@ int isZombieVillage(const int mcversion, const int64_t worldSeed,
}
// get the chunk position of the village
seed = regionX*341873128712 + regionZ*132897987541 + seed + VILLAGE_CONFIG.seed;
seed = regionX*341873128712 + regionZ*132897987541 + seed + VILLAGE_CONFIG.salt;
seed = (seed ^ 0x5deece66dLL);// & ((1LL << 48) - 1);
seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
@ -1517,28 +1632,6 @@ int isZombieVillage(const int mcversion, const int64_t worldSeed,
}
int isBabyZombieVillage(const int mcversion, const int64_t worldSeed,
const int regionX, const int regionZ)
{
if (!isZombieVillage(mcversion, worldSeed, regionX, regionZ))
return 0;
// Whether the zombie is a child or not is dependent on the world random
// object which is not reset for villages. The last reset is instead
// performed during the positioning of Mansions.
int64_t rnd = worldSeed;
rnd = regionX*341873128712 + regionZ*132897987541 + rnd + MANSION_CONFIG.seed;
setSeed(&rnd);
skipNextN(&rnd, 5);
int isChild = nextFloat(&rnd) < 0.05;
//int mountNearbyChicken = nextFloat(&rnd) < 0.05;
//int spawnNewChicken = nextFloat(&rnd) < 0.05;
return isChild;
}
int64_t getHouseList(const int64_t worldSeed, const int chunkX, const int chunkZ,
int *out)
{
@ -1563,233 +1656,6 @@ int64_t getHouseList(const int64_t worldSeed, const int chunkX, const int chunkZ
//==============================================================================
int64_t filterAllTempCats(
LayerStack * g,
int * cache,
const int64_t * seedsIn,
int64_t * seedsOut,
const int64_t seedCnt,
const int centX,
const int centZ)
{
/* We require all temperature categories, including the special variations
* in order to get all main biomes. This gives 8 required values:
* Oceanic, Warm, Lush, Cold, Freezing,
* Special Warm, Special Lush, Special Cold
* These categories generate at Layer 13: Edge, Special.
*
* Note: The scale at this layer is 1:1024 and each element can "leak" its
* biome values up to 1024 blocks outwards into the negative coordinates
* (due to the Zoom layers).
*
* The plan is to check if the 3x3 area contains all 8 temperature types.
* For this, we can check even earlier at Layer 10: Add Island, that each of
* the Warm, Cold and Freezing categories are present.
*/
/* Edit:
* All the biomes that are generated by a simple Cold climate can actually
* be generated later on. So I have commented out the Cold requirements.
*/
const int pX = centX-1, pZ = centZ-1;
const int sX = 3, sZ = 3;
int *map;
Layer *lFilterSnow = &g->layers[L_ADD_SNOW_1024];
Layer *lFilterSpecial = &g->layers[L_SPECIAL_1024];
map = cache ? cache : allocCache(lFilterSpecial, sX, sZ);
int64_t sidx, hits, seed;
int types[9];
int specialCnt;
int i, j;
hits = 0;
for (sidx = 0; sidx < seedCnt; sidx++)
{
seed = seedsIn[sidx];
/*** Pre-Generation Checks ***/
// We require at least 3 special temperature categories which can be
// tested for without going through the previous layers. (We'll get
// false positives due to Oceans, but this works fine to rule out some
// seeds early on.)
int64_t ss = getStartSeed(seed, lFilterSpecial->layerSeed);
specialCnt = 0;
for (i = 0; i < sX; i++)
{
for (j = 0; j < sZ; j++)
{
int64_t cs = getChunkSeed(ss, i+pX, j+pZ);
if (mcFirstInt(cs, 13) == 0)
specialCnt++;
}
}
if (specialCnt < 3)
{
continue;
}
/*** Cold/Warm Check ***/
// Continue by checking if enough cold and warm categories are present.
setWorldSeed(lFilterSnow, seed);
genArea(lFilterSnow, map, pX,pZ, sX,sZ);
memset(types, 0, sizeof(types));
for (i = 0; i < sX*sZ; i++)
types[map[i]]++;
// 1xOcean needs to be present
// 4xWarm need to turn into Warm, Lush, Special Warm and Special Lush
// 1xFreezing that needs to stay Freezing
// 3x(Cold + Freezing) for Cold, Special Cold and Freezing
if ( types[Ocean] < 1 || types[Warm] < 4 || types[Freezing] < 1 ||
types[Cold]+types[Freezing] < 2)
{
continue;
}
/*** Complete Temperature Category Check ***/
// Check that all temperature variants are present.
setWorldSeed(lFilterSpecial, seed);
genArea(lFilterSpecial, map, pX,pZ, sX,sZ);
memset(types, 0, sizeof(types));
for (i = 0; i < sX*sZ; i++)
types[ map[i] > 4 ? (map[i]&0xf) + 4 : map[i] ]++;
if ( types[Ocean] < 1 || types[Warm] < 1 || types[Lush] < 1 ||
/*types[Cold] < 1 ||*/ types[Freezing] < 1 ||
types[Warm+4] < 1 || types[Lush+4] < 1 || types[Cold+4] < 1)
{
continue;
}
/*
for (i = 0; i < sX*sZ; i++)
{
printf("%c%d ", " s"[cache[i] > 4], cache[i]&0xf);
if (i % sX == sX-1) printf("\n");
}
printf("\n");*/
// Save the candidate.
seedsOut[hits] = seed;
hits++;
}
if (cache == NULL) free(map);
return hits;
}
const int majorBiomes[] = {
ocean, plains, desert, mountains, forest, taiga, swamp,
snowy_tundra, mushroom_fields, jungle, deep_ocean, birch_forest, dark_forest,
snowy_taiga, giant_tree_taiga, savanna, wooded_badlands_plateau, badlands_plateau
};
int64_t filterAllMajorBiomes(
LayerStack * g,
int * cache,
const int64_t * seedsIn,
int64_t * seedsOut,
const int64_t seedCnt,
const int pX,
const int pZ,
const unsigned int sX,
const unsigned int sZ)
{
Layer *lFilterMushroom = &g->layers[L_ADD_MUSHROOM_256];
Layer *lFilterBiomes = &g->layers[L_BIOME_256];
int *map;
int64_t sidx, seed, hits;
unsigned int i, id, hasAll;
int types[BIOME_NUM];
map = cache ? cache : allocCache(lFilterBiomes, sX, sZ);
hits = 0;
for (sidx = 0; sidx < seedCnt; sidx++)
{
/* We can use the Mushroom layer both to check for mushroom_fields biomes
* and to make sure all temperature categories are present in the area.
*/
seed = seedsIn[sidx];
setWorldSeed(lFilterMushroom, seed);
genArea(lFilterMushroom, map, pX,pZ, sX,sZ);
memset(types, 0, sizeof(types));
for (i = 0; i < sX*sZ; i++)
{
id = map[i];
if (id >= BIOME_NUM) id = (id & 0xf) + 4;
types[id]++;
}
if ( types[Ocean] < 1 || types[Warm] < 1 || types[Lush] < 1 ||
/* types[Cold] < 1 || */ types[Freezing] < 1 ||
types[Warm+4] < 1 || types[Lush+4] < 1 || types[Cold+4] < 1 ||
types[mushroom_fields] < 1)
{
continue;
}
/*** Find all major biomes ***/
setWorldSeed(lFilterBiomes, seed);
genArea(lFilterBiomes, map, pX,pZ, sX,sZ);
memset(types, 0, sizeof(types));
for (i = 0; i < sX*sZ; i++)
{
types[map[i]]++;
}
hasAll = 1;
for (i = 0; i < sizeof(majorBiomes) / sizeof(*majorBiomes); i++)
{
// plains, taiga and deep_ocean can be generated in later layers.
// Also small islands of Forests can be generated in deep_ocean
// biomes, but we are going to ignore those.
if (majorBiomes[i] == plains ||
majorBiomes[i] == taiga ||
majorBiomes[i] == deep_ocean)
{
continue;
}
if (types[majorBiomes[i]] < 1)
{
hasAll = 0;
break;
}
}
if (!hasAll)
{
continue;
}
seedsOut[hits] = seed;
hits++;
}
if (cache == NULL) free(map);
return hits;
}
BiomeFilter setupBiomeFilter(const int *biomeList, int listLen)
{
BiomeFilter bf;
@ -1978,7 +1844,7 @@ int64_t checkForBiomes(
{
for (x = 0; x < areaWidth256; x++)
{
cs = getChunkSeed(ss, (int64_t)(x + areaX256), (int64_t)(z + areaZ256));
cs = getChunkSeed(ss, x + areaX256, z + areaZ256);
if (mcFirstInt(cs, 100) == 0)
{
goto after_protomushroom;
@ -2004,7 +1870,7 @@ int64_t checkForBiomes(
{
for (x = 0; x < areaWidth256; x++)
{
cs = getChunkSeed(ss, (int64_t)(x + areaX256), (int64_t)(z + areaZ256));
cs = getChunkSeed(ss, x + areaX256, z + areaZ256);
cs >>= 24;
int cs6 = cs % 6;

175
finders.h
View File

@ -26,11 +26,14 @@ typedef pthread_t thread_id_t;
#define LARGE_STRUCT 1
#define CHUNK_STRUCT 2
enum
enum StructureType
{
// scattered features
Desert_Pyramid, Igloo, Jungle_Pyramid, Swamp_Hut,
//
Village, Ocean_Ruin, Shipwreck, Monument, Mansion, Outpost,
Ruined_Portal
Ruined_Portal,
Treasure
};
enum // village house types prior to 1.14
@ -41,55 +44,41 @@ enum // village house types prior to 1.14
STRUCT(StructureConfig)
{
int64_t seed;
int regionSize, chunkRange;
int properties;
int salt;
char regionSize;
char chunkRange;
unsigned char structType;
unsigned char properties;
};
/* for desert temples, igloos, jungle temples and witch huts prior to 1.13 */
static const StructureConfig FEATURE_CONFIG = { 14357617, 32, 24, 0};
static const StructureConfig FEATURE_CONFIG = { 14357617, 32, 24, Desert_Pyramid, 0};
/* ocean features before 1.16 */
static const StructureConfig OCEAN_RUIN_CONFIG_113 = { 14357621, 16, 8, 0};
static const StructureConfig SHIPWRECK_CONFIG_113 = {165745295, 15, 7, 0};
static const StructureConfig OCEAN_RUIN_CONFIG_113 = { 14357621, 16, 8, Ocean_Ruin, 0};
static const StructureConfig SHIPWRECK_CONFIG_113 = {165745295, 15, 7, Shipwreck, 0};
/* 1.13 separated feature seeds by type */
static const StructureConfig DESERT_PYRAMID_CONFIG = { 14357617, 32, 24, 0};
static const StructureConfig IGLOO_CONFIG = { 14357618, 32, 24, 0};
static const StructureConfig JUNGLE_PYRAMID_CONFIG = { 14357619, 32, 24, 0};
static const StructureConfig SWAMP_HUT_CONFIG = { 14357620, 32, 24, 0};
static const StructureConfig DESERT_PYRAMID_CONFIG = { 14357617, 32, 24, Desert_Pyramid, 0};
static const StructureConfig IGLOO_CONFIG = { 14357618, 32, 24, Igloo, 0};
static const StructureConfig JUNGLE_PYRAMID_CONFIG = { 14357619, 32, 24, Jungle_Pyramid, 0};
static const StructureConfig SWAMP_HUT_CONFIG = { 14357620, 32, 24, Swamp_Hut, 0};
static const StructureConfig OUTPOST_CONFIG = {165745296, 32, 24, 0};
static const StructureConfig VILLAGE_CONFIG = { 10387312, 32, 24, 0};
static const StructureConfig OCEAN_RUIN_CONFIG = { 14357621, 20, 12, 0};
static const StructureConfig SHIPWRECK_CONFIG = {165745295, 24, 20, 0};
static const StructureConfig MONUMENT_CONFIG = { 10387313, 32, 27, LARGE_STRUCT};
static const StructureConfig MANSION_CONFIG = { 10387319, 80, 60, LARGE_STRUCT};
static const StructureConfig RUINED_PORTAL_CONFIG = { 34222645, 40, 25, 0}; // overworld variant
static const StructureConfig OUTPOST_CONFIG = {165745296, 32, 24, Outpost, 0};
static const StructureConfig VILLAGE_CONFIG = { 10387312, 32, 24, Village, 0};
static const StructureConfig OCEAN_RUIN_CONFIG = { 14357621, 20, 12, Ocean_Ruin, 0};
static const StructureConfig SHIPWRECK_CONFIG = {165745295, 24, 20, Shipwreck, 0};
static const StructureConfig MONUMENT_CONFIG = { 10387313, 32, 27, Monument, LARGE_STRUCT};
static const StructureConfig MANSION_CONFIG = { 10387319, 80, 60, Mansion, LARGE_STRUCT};
static const StructureConfig RUINED_PORTAL_CONFIG = { 34222645, 40, 25, Ruined_Portal, 0}; // overworld variant
// structures that check each chunk individually
static const StructureConfig TREASURE_CONFIG = { 10387320, 1, 0, CHUNK_STRUCT};
static const StructureConfig TREASURE_CONFIG = { 10387320, 1, 0, Treasure, CHUNK_STRUCT};
//==============================================================================
// Biome Tables
//==============================================================================
static const int templeBiomeList[] = {desert, desert_hills, jungle, jungle_hills, swamp, snowy_tundra, snowy_taiga};
static const int biomesToSpawnIn[] = {forest, plains, taiga, taiga_hills, wooded_hills, jungle, jungle_hills};
static const int villageBiomeList[] = {plains, desert, savanna, taiga};
static const int villageBiomeListBE[] = {plains, desert, savanna, taiga, snowy_tundra, snowy_taiga};
static const int mansionBiomeList[] = {dark_forest, dark_forest+128};
static const int oceanMonumentBiomeList1[] =
{
ocean, deep_ocean, river, frozen_river,
frozen_ocean, deep_frozen_ocean, cold_ocean, deep_cold_ocean,
lukewarm_ocean, deep_lukewarm_ocean, warm_ocean, deep_warm_ocean
};
static const int oceanMonumentBiomeList2[] =
{
deep_frozen_ocean, deep_cold_ocean, deep_ocean, deep_lukewarm_ocean, deep_warm_ocean
};
static const int achievementBiomes_1_7[] =
{
ocean, plains, desert, extremeHills, forest, taiga, swampland, river, /*hell, sky,*/ // 0-9
@ -295,7 +284,7 @@ int getBiomeAtPos(const LayerStack g, const Pos pos);
* Warning: accurate, but slow!
*
* @mcversion : Minecraft version (changed in: 1.7, 1.13)
* @g : generator layer stack
* @l : entry layer with scale = 4
* @cache : biome buffer, set to NULL for temporary allocation
* @centreX, centreZ : origin for the search
* @range : square 'radius' of the search
@ -306,12 +295,12 @@ int getBiomeAtPos(const LayerStack g, const Pos pos);
*/
Pos findBiomePosition(
const int mcversion,
const LayerStack g,
const Layer * l,
int * cache,
const int centerX,
const int centerZ,
const int range,
const int * isValid,
const char * isValid,
int64_t * seed,
int * passes
);
@ -321,19 +310,19 @@ Pos findBiomePosition(
* and mansions.
* Warning: accurate, but slow!
*
* @g : generator layer stack
* @l : entry layer with scale = 4: (L_RIVER_MIX_4, L13_OCEAN_MIX_4)
* @cache : biome buffer, set to NULL for temporary allocation
* @posX, posZ : centre for the check
* @radius : 'radius' of the check area
* @isValid : boolean array of valid biome ids (size = 256)
*/
int areBiomesViable(
const LayerStack g,
const Layer * l,
int * cache,
const int posX,
const int posZ,
const int radius,
const int * isValid
const char * isValid
);
/* Finds the smallest radius (by square around the origin) at which all the
@ -380,7 +369,7 @@ int getBiomeRadius(
*/
int findStrongholds(
const int mcversion,
LayerStack * g,
const LayerStack * g,
int * cache,
Pos * locations,
int64_t worldSeed,
@ -397,7 +386,7 @@ int findStrongholds(
* @cache : biome buffer, set to NULL for temporary allocation
* @worldSeed : world seed used for the generator
*/
Pos getSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed);
Pos getSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed);
/* Finds the approximate spawn point in the world.
*
@ -406,54 +395,32 @@ Pos getSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed);
* @cache : biome buffer, set to NULL for temporary allocation
* @worldSeed : world seed used for the generator
*/
Pos estimateSpawn(const int mcversion, LayerStack *g, int *cache, int64_t worldSeed);
Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed);
//==============================================================================
// Validating Structure Positions
//==============================================================================
/************************ Biome Checks for Structures **************************
*
* Scattered features only do a simple check of the biome at the block position
* of the structure origin (i.e. the north-west corner). Before 1.13 the type of
* structure was determined by the biome, while in 1.13 the scattered feature
* positions are calculated separately for each type. However, the biome
* requirements remain the same:
*
* Desert Pyramid: desert or desertHills
* Igloo : icePlains or coldTaiga
* Jungle Pyramid: jungle or jungleHills
* Swamp Hut : swampland
*
* Similarly, Ocean Ruins and Shipwrecks require any oceanic biome at their
* block position.
*
* Villages, Monuments and Mansions on the other hand require a certain area to
* be of a valid biome and the check is performed at a 1:4 scale instead of 1:1.
* (Actually the area for villages has a radius zero, which means it is a simple
* biome check at a 1:4 scale.)
*/
/* These functions perform 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
* the block positions using the appropriate getXXXPos() function.
*
* @g : generator layer stack [set seed using applySeed()]
* @cache : biome buffer, set to NULL for temporary allocation
* @sconf : structure config for the type to be checked
* @mcversion : minecraft version
* @g : generator layer stack, seed will be applied to layers
* @seed : world seed, will be applied to generator
* @blockX, blockZ : block coordinates
*
* In the case of isViableFeaturePos() the 'type' argument specifies the type of
* scattered feature (as an enum) for which the check is performed.
*
* The return value is non-zero if the position is valid.
*/
int isViableFeaturePos(const int type, const LayerStack g, int *cache, const int blockX, const int blockZ);
int isViableVillagePos(const LayerStack g, int *cache, const int blockX, const int blockZ);
int isViableOceanMonumentPos(const LayerStack g, int *cache, const int blockX, const int blockZ);
int isViableMansionPos(const LayerStack g, int *cache, const int blockX, const int blockZ);
int isViableStructurePos(const StructureConfig sconf, int mcversion,
LayerStack *g, int64_t seed, int blockX, int blockZ);
/* Checks if the specified structure type could generate in the given biome.
*/
int isViableFeatureBiome(int structureType, int biomeID);
//==============================================================================
@ -479,12 +446,6 @@ inline static int64_t chunkGenerateRnd(const int64_t worldSeed, const int chunkX
int isZombieVillage(const int mcversion, const int64_t worldSeed,
const int regionX, const int regionZ);
/* Checks if the village in the given region would generate as a baby zombie
* village. (The fact that these exist could be regarded as a bug.)
* (Minecraft 1.12)
*/
int isBabyZombieVillage(const int mcversion, const int64_t worldSeed,
const int regionX, const int regionZ);
/* Finds the number of each type of house that generate in a village.
* @worldSeed : world seed
@ -502,54 +463,6 @@ int64_t getHouseList(const int64_t worldSeed, const int chunkX, const int chunkZ
// Seed Filters
//==============================================================================
/* Looks through the seeds in 'seedsIn' and copies those for which all
* temperature categories are present in the 3x3 area centred on the specified
* coordinates into 'seedsOut'. The map scale at this layer is 1:1024.
*
* @g : generator layer stack, (NOTE: seed will be modified)
* @cache : biome buffer, set to NULL for temporary allocation
* @seedsIn : list of seeds to check
* @seedsOut : output buffer for the candidate seeds
* @seedCnt : number of seeds in 'seedsIn'
* @centX, centZ : search origin centre (in 1024 block units)
*
* Returns the number of found candidates.
*/
int64_t filterAllTempCats(
LayerStack * g,
int * cache,
const int64_t * seedsIn,
int64_t * seedsOut,
const int64_t seedCnt,
const int centX,
const int centZ
);
/* Looks through the list of seeds in 'seedsIn' and copies those that have all
* major overworld biomes in the specified area into 'seedsOut'. These checks
* are done at a scale of 1:256.
*
* @g : generator layer stack, (NOTE: seed will be modified)
* @cache : biome buffer, set to NULL for temporary allocation
* @seedsIn : list of seeds to check
* @seedsOut : output buffer for the candidate seeds
* @seedCnt : number of seeds in 'seedsIn'
* @pX, pZ : search starting coordinates (in 256 block units)
* @sX, sZ : size of the searching area (in 256 block units)
*
* Returns the number of seeds found.
*/
int64_t filterAllMajorBiomes(
LayerStack * g,
int * cache,
const int64_t * seedsIn,
int64_t * seedsOut,
const int64_t seedCnt,
const int pX,
const int pZ,
const unsigned int sX,
const unsigned int sZ
);
/* Creates a biome filter configuration from a given list of biomes.
*/

View File

@ -8,7 +8,7 @@
void setupLayer(Layer *l, Layer *p, int s,
void (*getMap)(const Layer * RESTRICT, int *, int, int, int, int))
void (*getMap)(const Layer *, int *, int, int, int, int))
{
l->layerSeed = getLayerSeed(s);
l->startSalt = 0;
@ -21,7 +21,7 @@ void setupLayer(Layer *l, Layer *p, int s,
}
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s,
void (*getMap)(const Layer * RESTRICT, int *, int, int, int, int))
void (*getMap)(const Layer *, int *, int, int, int, int))
{
setupLayer(l, p1, s, getMap);
l->p2 = p2;
@ -79,7 +79,7 @@ static LayerStack setupGeneratorImpl(const int mcversion, const int largeBiomes)
setupLayer(&l[L_DEEP_OCEAN_256], &l[L_ADD_MUSHROOM_256], 4, mapDeepOcean);
// biome layer chain
setupLayer(&l[L_BIOME_256], &l[L_DEEP_OCEAN_256], 200,
mcversion != MCBE ? mapBiome : mapBiomeBE);
mcversion != MC_BE ? mapBiome : mapBiomeBE);
if (mcversion <= MC_1_13)
setupLayer(&l[L_ZOOM_128], &l[L_BIOME_256], 1000, mapZoom);
@ -180,7 +180,7 @@ void freeGenerator(LayerStack g)
/* Recursively calculates the minimum buffer size required to generate an area
* of the specified size from the current layer onwards.
*/
static void getMaxArea(Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ)
static void getMaxArea(const Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ)
{
if (layer == NULL)
return;
@ -224,7 +224,7 @@ static void getMaxArea(Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ)
getMaxArea(layer->p2, areaX, areaZ, maxX, maxZ);
}
int calcRequiredBuf(Layer *layer, int areaX, int areaZ)
int calcRequiredBuf(const Layer *layer, int areaX, int areaZ)
{
int maxX = areaX, maxZ = areaZ;
getMaxArea(layer, areaX, areaZ, &maxX, &maxZ);
@ -232,7 +232,7 @@ int calcRequiredBuf(Layer *layer, int areaX, int areaZ)
return maxX * maxZ;
}
int *allocCache(Layer *layer, int sizeX, int sizeZ)
int *allocCache(const Layer *layer, int sizeX, int sizeZ)
{
int size = calcRequiredBuf(layer, sizeX, sizeZ);

View File

@ -8,7 +8,7 @@ enum MCversion
{
MC_1_7, MC_1_8, MC_1_9, MC_1_10, MC_1_11, MC_1_12, MC_1_13, MC_1_14,
MC_1_15, MC_1_16,
MCBE = 256
MC_BE = 128
};
/* Enumeration of the layer indices in the generator. */
@ -211,18 +211,17 @@ void freeGenerator(LayerStack g);
/* Calculates the minimum size of the buffers required to generate an area of
* dimensions 'sizeX' by 'sizeZ' at the specified layer.
*/
int calcRequiredBuf(Layer *layer, int areaX, int areaZ);
int calcRequiredBuf(const Layer *layer, int areaX, int areaZ);
/* Allocates an amount of memory required to generate an area of dimensions
* 'sizeX' by 'sizeZ' for the magnification of the current top layer.
*/
int *allocCache(Layer *layer, int sizeX, int sizeZ);
int *allocCache(const Layer *layer, int sizeX, int sizeZ);
/* Set up custom layers. */
void setupLayer(Layer *l, Layer *p, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h));
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h));
void setupLayer(Layer *l, Layer *p, int s, void (*getMap)(const Layer *, int *, int, int, int, int));
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(const Layer *, int *, int, int, int, int));
/* Sets the world seed for the generator */
void applySeed(LayerStack *g, int64_t seed);
@ -233,7 +232,7 @@ void applySeed(LayerStack *g, int64_t seed);
* It is recommended that 'out' is allocated using allocCache() for the correct
* buffer size.
*/
void genArea(Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight);
void genArea(const Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight);
#ifdef __cplusplus

205
layers.c
View File

@ -148,35 +148,32 @@ void initBiomes()
}
void setWorldSeed(Layer *layer, int64_t seed)
void setWorldSeed(Layer *layer, int64_t worldSeed)
{
if (layer->p2 != NULL && layer->getMap != mapHills)
setWorldSeed(layer->p2, seed);
setWorldSeed(layer->p2, worldSeed);
if (layer->p != NULL)
setWorldSeed(layer->p, seed);
setWorldSeed(layer->p, worldSeed);
if (layer->oceanRnd != NULL)
oceanRndInit(layer->oceanRnd, seed);
oceanRndInit(layer->oceanRnd, worldSeed);
layer->startSalt = seed;
layer->startSalt *= layer->startSalt * 6364136223846793005LL + 1442695040888963407LL;
layer->startSalt += layer->layerSeed;
layer->startSalt *= layer->startSalt * 6364136223846793005LL + 1442695040888963407LL;
layer->startSalt += layer->layerSeed;
layer->startSalt *= layer->startSalt * 6364136223846793005LL + 1442695040888963407LL;
layer->startSalt += layer->layerSeed;
int64_t st = worldSeed;
st = mcStepSeed(st, layer->layerSeed);
st = mcStepSeed(st, layer->layerSeed);
st = mcStepSeed(st, layer->layerSeed);
layer->startSeed = layer->startSalt;
layer->startSeed *= layer->startSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->startSalt = st;
layer->startSeed = mcStepSeed(st, 0);
}
void mapNull(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapNull(const Layer * l, int * out, int x, int z, int w, int h)
{
}
void mapSkip(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapSkip(const Layer * l, int * out, int x, int z, int w, int h)
{
if (l->p == NULL)
{
@ -187,7 +184,7 @@ void mapSkip(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
}
void mapIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapIsland(const Layer * l, int * out, int x, int z, int w, int h)
{
register int i, j;
@ -199,7 +196,7 @@ void mapIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w
for (i = 0; i < w; i++)
{
cs = getChunkSeed(ss, i + x, j + z);
out[i + j*w] = mcFirstInt(cs, 10) == 0;
out[i + j*w] = mcFirstIsZero(cs, 10);
}
}
@ -372,7 +369,7 @@ static inline __m128i select4ModeOrRandom(__m128i* cs, int ws, __m128i a1, __m12
#if defined USE_SIMD && __AVX2__
void mapZoom(Layer *l, int* __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight)
void mapZoom(Layer *l, int* out, int areaX, int areaZ, int areaWidth, int areaHeight)
{
int pWidth = (areaWidth>>1)+2, pHeight = (areaHeight>>1)+1;
@ -435,7 +432,7 @@ void mapZoom(Layer *l, int* __restrict out, int areaX, int areaZ, int areaWidth,
#elif defined USE_SIMD && defined __SSE4_2__
void mapZoom(Layer *l, int* __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight)
void mapZoom(Layer *l, int* out, int areaX, int areaZ, int areaWidth, int areaHeight)
{
int pWidth = (areaWidth>>1)+2, pHeight = (areaHeight>>1)+1;
@ -497,7 +494,7 @@ void mapZoom(Layer *l, int* __restrict out, int areaX, int areaZ, int areaWidth,
#else
void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapZoom(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x >> 1;
int pZ = z >> 1;
@ -509,7 +506,7 @@ void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
int newW = (pW) << 1;
int newH = (pH) << 1;
int idx, a, b;
int idx, v00, v01;
int *buf = (int*) malloc((newW+1)*(newH+1)*sizeof(*buf));
const int st = (int)l->startSalt;
@ -520,18 +517,18 @@ void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
for (j = 0; j < pH; j++)
{
idx = (j << 1) * newW;
a = out[(j+0)*pW];
b = out[(j+1)*pW];
v00 = out[(j+0)*pW];
v01 = out[(j+1)*pW];
for (i = 0; i < pW; i++)
{
int a1 = out[i+1 + (j+0)*pW];
int b1 = out[i+1 + (j+1)*pW];
int v10 = out[i+1 + (j+0)*pW];
int v11 = out[i+1 + (j+1)*pW];
const int chunkX = (i + pX) << 1;
const int chunkZ = (j + pZ) << 1;
int chunkX = (i + pX) << 1;
int chunkZ = (j + pZ) << 1;
register int cs = ss;
int cs = ss;
cs += chunkX;
cs *= cs * 1284865837 + 4150755663;
cs += chunkZ;
@ -540,13 +537,13 @@ void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
cs *= cs * 1284865837 + 4150755663;
cs += chunkZ;
buf[idx] = a;
buf[idx + newW] = (cs >> 24) & 1 ? b : a;
buf[idx] = v00;
buf[idx + newW] = (cs >> 24) & 1 ? v01 : v00;
idx++;
cs *= cs * 1284865837 + 4150755663;
cs += st;
buf[idx] = (cs >> 24) & 1 ? a1 : a;
buf[idx] = (cs >> 24) & 1 ? v10 : v00;
if (isHighestZoom)
@ -554,34 +551,36 @@ void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
//selectRandom4
cs *= cs * 1284865837 + 4150755663;
cs += st;
const int i = (cs >> 24) & 3;
buf[idx + newW] = i==0 ? a : i==1 ? a1 : i==2 ? b : b1;
int r = (cs >> 24) & 3;
buf[idx + newW] = r==0 ? v00 : r==1 ? v10 : r==2 ? v01 : v11;
}
else
{
//selectModeOrRandom
if (a1 == b && b == b1) buf[idx + newW] = a1;
else if (a == a1 && a == b ) buf[idx + newW] = a;
else if (a == a1 && a == b1) buf[idx + newW] = a;
else if (a == b && a == b1) buf[idx + newW] = a;
else if (a == a1 && b != b1) buf[idx + newW] = a;
else if (a == b && a1 != b1) buf[idx + newW] = a;
else if (a == b1 && a1 != b ) buf[idx + newW] = a;
else if (a1 == b && a != b1) buf[idx + newW] = a1;
else if (a1 == b1 && a != b ) buf[idx + newW] = a1;
else if (b == b1 && a != a1) buf[idx + newW] = b;
int v;
if (v10 == v01 && v01 == v11) v = v10;
else if (v00 == v10 && v00 == v01) v = v00;
else if (v00 == v10 && v00 == v11) v = v00;
else if (v00 == v01 && v00 == v11) v = v00;
else if (v00 == v10 && v01 != v11) v = v00;
else if (v00 == v01 && v10 != v11) v = v00;
else if (v00 == v11 && v10 != v01) v = v00;
else if (v10 == v01 && v00 != v11) v = v10;
else if (v10 == v11 && v00 != v01) v = v10;
else if (v01 == v11 && v00 != v10) v = v01;
else
{
cs *= cs * 1284865837 + 4150755663;
cs += st;
const int i = (cs >> 24) & 3;
buf[idx + newW] = i==0 ? a : i==1 ? a1 : i==2 ? b : b1;
int r = (cs >> 24) & 3;
v = r==0 ? v00 : r==1 ? v10 : r==2 ? v01 : v11;
}
buf[idx + newW] = v;
}
idx++;
a = a1;
b = b1;
v00 = v10;
v01 = v11;
}
}
@ -595,7 +594,7 @@ void mapZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
#endif
void mapAddIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapAddIsland(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -683,7 +682,7 @@ void mapAddIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
}
void mapRemoveTooMuchOcean(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapRemoveTooMuchOcean(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -711,7 +710,7 @@ void mapRemoveTooMuchOcean(const Layer * RESTRICT l, int * RESTRICT out, int x,
if (v11 == 0)
{
cs = getChunkSeed(ss, i+x, j+z);
if (mcFirstInt(cs, 2) == 0)
if (mcFirstIsZero(cs, 2))
{
out[i + j*w] = 1;
}
@ -721,7 +720,7 @@ void mapRemoveTooMuchOcean(const Layer * RESTRICT l, int * RESTRICT out, int x,
}
void mapAddSnow(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapAddSnow(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -761,7 +760,7 @@ void mapAddSnow(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapCoolWarm(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapCoolWarm(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -796,7 +795,7 @@ void mapCoolWarm(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapHeatIce(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapHeatIce(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -831,7 +830,7 @@ void mapHeatIce(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapSpecial(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapSpecial(const Layer * l, int * out, int x, int z, int w, int h)
{
l->p->getMap(l->p, out, x, z, w, h);
@ -849,7 +848,7 @@ void mapSpecial(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
cs = getChunkSeed(ss, i+x, j+z);
if (mcFirstInt(cs, 13) == 0)
if (mcFirstIsZero(cs, 13))
{
cs = mcStepSeed(cs, st);
v |= (1 + mcFirstInt(cs, 15)) << 8 & 0xf00;
@ -861,7 +860,7 @@ void mapSpecial(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapAddMushroomIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapAddMushroomIsland(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -884,7 +883,7 @@ void mapAddMushroomIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, i
if (v11 == 0 && !out[i+0 + (j+0)*pW] && !out[i+2 + (j+0)*pW] && !out[i+0 + (j+2)*pW] && !out[i+2 + (j+2)*pW])
{
cs = getChunkSeed(ss, i+x, j+z);
if (mcFirstInt(cs, 100) == 0)
if (mcFirstIsZero(cs, 100))
{
out[i + j*w] = mushroom_fields;
continue;
@ -897,7 +896,7 @@ void mapAddMushroomIsland(const Layer * RESTRICT l, int * RESTRICT out, int x, i
}
void mapDeepOcean(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapDeepOcean(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -958,7 +957,7 @@ const int lushBiomes[] = {forest, dark_forest, mountains, plains, birch_forest,
const int coldBiomes[] = {forest, mountains, taiga, plains};
const int snowBiomes[] = {snowy_tundra, snowy_tundra, snowy_tundra, snowy_taiga};
void mapBiome(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapBiome(const Layer * l, int * out, int x, int z, int w, int h)
{
l->p->getMap(l->p, out, x, z, w, h);
@ -985,7 +984,7 @@ void mapBiome(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
switch(id){
case Warm:
if (hasHighBit) out[idx] = (mcFirstInt(cs, 3) == 0) ? badlands_plateau : wooded_badlands_plateau;
if (hasHighBit) out[idx] = mcFirstIsZero(cs, 3) ? badlands_plateau : wooded_badlands_plateau;
else out[idx] = warmBiomes[mcFirstInt(cs, 6)];
break;
case Lush:
@ -1009,7 +1008,7 @@ void mapBiome(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
const int lushBiomesBE[] = {forest, dark_forest, mountains, plains, plains, plains, birch_forest, swamp};
void mapBiomeBE(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapBiomeBE(const Layer * l, int * out, int x, int z, int w, int h)
{
l->p->getMap(l->p, out, x, z, w, h);
@ -1036,7 +1035,7 @@ void mapBiomeBE(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
switch(id){
case Warm:
if (hasHighBit) out[idx] = (mcFirstInt(cs, 3) == 0) ? badlands_plateau : wooded_badlands_plateau;
if (hasHighBit) out[idx] = mcFirstIsZero(cs, 3) ? badlands_plateau : wooded_badlands_plateau;
else out[idx] = warmBiomes[mcFirstInt(cs, 6)];
break;
case Lush:
@ -1058,7 +1057,7 @@ void mapBiomeBE(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapRiverInit(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapRiverInit(const Layer * l, int * out, int x, int z, int w, int h)
{
l->p->getMap(l->p, out, x, z, w, h);
@ -1084,7 +1083,7 @@ void mapRiverInit(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
}
void mapAddBamboo(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapAddBamboo(const Layer * l, int * out, int x, int z, int w, int h)
{
l->p->getMap(l->p, out, x, z, w, h);
@ -1100,7 +1099,7 @@ void mapAddBamboo(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
if (out[idx] != jungle) continue;
cs = getChunkSeed(ss, i + x, j + z);
if (mcFirstInt(cs, 10) == 0)
if (mcFirstIsZero(cs, 10))
{
out[idx] = bamboo_jungle;
}
@ -1123,7 +1122,7 @@ static inline int replaceEdge(int *out, int idx, int v10, int v21, int v01, int
return 1;
}
void mapBiomeEdge(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapBiomeEdge(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1190,7 +1189,7 @@ void mapBiomeEdge(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
}
void mapHills(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapHills(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1233,7 +1232,7 @@ void mapHills(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
else
{
cs = getChunkSeed(ss, i + x, j + z);
if (mcFirstInt(cs, 3) != 0 && !var12)
if (mcFirstIsZero(cs, 3) && !var12)
{
out[idx] = a11;
}
@ -1259,7 +1258,7 @@ void mapHills(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
hillID = snowy_taiga_hills; break;
case plains:
cs = mcStepSeed(cs, st);
hillID = (mcFirstInt(cs, 3) == 0) ? wooded_hills : forest; break;
hillID = mcFirstIsZero(cs, 3) ? wooded_hills : forest; break;
case snowy_tundra:
hillID = snowy_mountains; break;
case jungle:
@ -1273,8 +1272,8 @@ void mapHills(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
default:
if (areSimilar(a11, wooded_badlands_plateau))
hillID = badlands;
else if (a11 == deep_ocean && mcFirstInt(cs = mcStepSeed(cs, st), 3) == 0)
hillID = (mcFirstInt(mcStepSeed(cs, st), 2) == 0) ? plains : forest;
else if (a11 == deep_ocean && mcFirstIsZero(cs = mcStepSeed(cs, st), 3))
hillID = mcFirstIsZero(mcStepSeed(cs, st), 2) ? plains : forest;
break;
}
@ -1317,7 +1316,7 @@ void mapHills(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
}
void mapHills113(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapHills113(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1364,7 +1363,7 @@ void mapHills113(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
else
{
cs = getChunkSeed(ss, i + x, j + z);
if (mcFirstInt(cs, 3) == 0 || bn == 0)
if (bn == 0 || mcFirstIsZero(cs, 3))
{
int hillID = a11;
@ -1386,7 +1385,7 @@ void mapHills113(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
hillID = snowy_taiga_hills; break;
case plains:
cs = mcStepSeed(cs, st);
hillID = (mcFirstInt(cs, 3) == 0) ? wooded_hills : forest; break;
hillID = mcFirstIsZero(cs, 3) ? wooded_hills : forest; break;
case snowy_tundra:
hillID = snowy_mountains; break;
case jungle:
@ -1405,10 +1404,10 @@ void mapHills113(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
else if (isDeepOcean(a11))
{
cs = mcStepSeed(cs, st);
if (mcFirstInt(cs, 3) == 0)
if (mcFirstIsZero(cs, 3))
{
cs = mcStepSeed(cs, st);
hillID = (mcFirstInt(cs, 2) == 0) ? plains : forest;
hillID = mcFirstIsZero(cs, 2) ? plains : forest;
}
}
break;
@ -1462,7 +1461,7 @@ static inline int reduceID(int id)
return id >= 2 ? 2 + (id & 1) : id;
}
void mapRiver(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapRiver(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1481,12 +1480,9 @@ void mapRiver(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
for (i = 0; i < w; i++)
{
int v11 = reduceID(vz1[i+1]);
int v10 = reduceID(vz0[i+1]);
int v21 = reduceID(vz1[i+2]);
int v01 = reduceID(vz1[i+0]);
int v12 = reduceID(vz2[i+1]);
if (v11 == v01 && v11 == v10 && v11 == v21 && v11 == v12)
if (v11 == reduceID(vz1[i+0]) && v11 == reduceID(vz1[i+2]) &&
v11 == reduceID(vz0[i+1]) && v11 == reduceID(vz2[i+1]))
{
out[i + j * w] = -1;
}
@ -1499,7 +1495,7 @@ void mapRiver(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
}
void mapSmooth(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapSmooth(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1521,23 +1517,26 @@ void mapSmooth(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w
for (i = 0; i < w; i++)
{
int v11 = vz1[i+1];
int v10 = vz0[i+1];
int v21 = vz1[i+2];
int v01 = vz1[i+0];
int v12 = vz2[i+1];
int v10 = vz0[i+1];
if (v01 == v21 && v10 == v12)
if (v11 != v01 || v11 != v10)
{
cs = getChunkSeed(ss, i+x, j+z);
if (cs & ((int64_t)1 << 24))
v11 = v10;
int v21 = vz1[i+2];
int v12 = vz2[i+1];
if (v01 == v21 && v10 == v12)
{
cs = getChunkSeed(ss, i+x, j+z);
if (cs & ((int64_t)1 << 24))
v11 = v10;
else
v11 = v01;
}
else
v11 = v01;
}
else
{
if (v01 == v21) v11 = v01;
if (v10 == v12) v11 = v10;
{
if (v01 == v21) v11 = v01;
if (v10 == v12) v11 = v10;
}
}
out[i + j * w] = v11;
@ -1546,7 +1545,7 @@ void mapSmooth(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w
}
void mapRareBiome(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapRareBiome(const Layer * l, int * out, int x, int z, int w, int h)
{
int i, j;
@ -1564,7 +1563,7 @@ void mapRareBiome(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
if (v == plains)
{
cs = getChunkSeed(ss, i + x, j + z);
if (mcFirstInt(cs, 57) == 0)
if (mcFirstIsZero(cs, 57))
{
// Sunflower Plains
out[i + j*w] = plains + 128;
@ -1592,7 +1591,7 @@ inline static int isBiomeJFTO(int id)
return biomeExists(id) && (getBiomeType(id) == Jungle || id == forest || id == taiga || isOceanic(id));
}
void mapShore(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapShore(const Layer * l, int * out, int x, int z, int w, int h)
{
int pX = x - 1;
int pZ = z - 1;
@ -1683,7 +1682,7 @@ void mapShore(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w,
}
void mapRiverMix(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapRiverMix(const Layer * l, int * out, int x, int z, int w, int h)
{
int idx;
int len;
@ -1821,7 +1820,7 @@ static double getOceanTemp(const OceanRnd *rnd, double d1, double d2, double d3)
return lerp(t3, l1, l5);
}
void mapOceanTemp(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapOceanTemp(const Layer * l, int * out, int x, int z, int w, int h)
{
int i, j;
OceanRnd *rnd = l->oceanRnd;
@ -1847,7 +1846,7 @@ void mapOceanTemp(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, in
}
/* Warning: this function is horribly slow compared to other layers! */
void mapOceanMix(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapOceanMix(const Layer * l, int * out, int x, int z, int w, int h)
{
int landX = x - 8, landZ = z - 8;
int landW = w + 17, landH = h + 17;
@ -1936,7 +1935,7 @@ void mapOceanMix(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int
}
void mapVoronoiZoom(const Layer * RESTRICT l, int * RESTRICT out, int x, int z, int w, int h)
void mapVoronoiZoom(const Layer * l, int * out, int x, int z, int w, int h)
{
x -= 2;
z -= 2;

View File

@ -13,8 +13,6 @@
#define NULL ((void*)0)
#endif
#define RESTRICT __restrict
#define REGISTER register
#define STRUCT(S) typedef struct S S; struct S
@ -147,14 +145,14 @@ STRUCT(OceanRnd)
STRUCT(Layer)
{
int64_t layerSeed; // (depends only on layer salt)
int64_t startSalt; // (world seed dependent) for RND ints beyond the first
int64_t startSalt; // (world seed dependent) = worldGenSeed, used for RND beyond the first
int64_t startSeed; // (world seed dependent) starting point for chunk seeds
OceanRnd *oceanRnd; // world seed dependent data for ocean temperatures
int scale; // map scale of this layer (map entry = scale x scale blocks)
void (*getMap)(const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void (*getMap)(const Layer *, int *, int, int, int, int);
Layer *p, *p2; // parent layers
};
@ -175,7 +173,7 @@ extern Biome biomes[256];
void initBiomes();
/* Applies the given world seed to the layer and all dependent layers. */
void setWorldSeed(Layer *layer, int64_t seed);
void setWorldSeed(Layer *layer, int64_t worldSeed);
//==============================================================================
@ -270,8 +268,8 @@ static inline int isBiomeSnowy(int id)
* The seed pipeline:
*
* Salt of Layer -> layerSeed (ls)
* layerSeed (ls) + worldSeed (ws) -> startSalt (st) + startSeed (ss)
* startSeed (ls) + coords (x,z) -> chunkSeed (cs)
* layerSeed (ls) & worldSeed (ws) -> startSalt (st) & startSeed (ss)
* startSeed (ls) & coords (x,z) -> chunkSeed (cs)
*
* The chunkSeed alone is enough to generate the first RND integer with:
* mcFirstInt(cs, mod)
@ -293,7 +291,7 @@ static inline int mcFirstInt(int64_t s, int mod)
return ret;
}
static inline int mcIsFirstZero(int64_t s, int mod)
static inline int mcFirstIsZero(int64_t s, int mod)
{
return (int)((s >> 24) % mod) == 0;
}
@ -332,40 +330,40 @@ static inline int64_t getStartSeed(int64_t ws, int64_t ls)
//==============================================================================
// A null layer does nothing, and can be used to apply a layer to existing data.
void mapNull (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapNull (const Layer *, int *, int, int, int, int);
// A skip layer simply calls its first parent without modification.
// This can be used as an easy way to skip a layer in a generator.
void mapSkip (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapSkip (const Layer *, int *, int, int, int, int);
void mapIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapZoom (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRemoveTooMuchOcean (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddSnow (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapCoolWarm (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapHeatIce (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapSpecial (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddMushroomIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapDeepOcean (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiome (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiomeBE (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddBamboo (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiverInit (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiomeEdge (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapHills (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiver (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapSmooth (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRareBiome (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapShore (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiverMix (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapIsland (const Layer *, int *, int, int, int, int);
void mapZoom (const Layer *, int *, int, int, int, int);
void mapAddIsland (const Layer *, int *, int, int, int, int);
void mapRemoveTooMuchOcean (const Layer *, int *, int, int, int, int);
void mapAddSnow (const Layer *, int *, int, int, int, int);
void mapCoolWarm (const Layer *, int *, int, int, int, int);
void mapHeatIce (const Layer *, int *, int, int, int, int);
void mapSpecial (const Layer *, int *, int, int, int, int);
void mapAddMushroomIsland (const Layer *, int *, int, int, int, int);
void mapDeepOcean (const Layer *, int *, int, int, int, int);
void mapBiome (const Layer *, int *, int, int, int, int);
void mapBiomeBE (const Layer *, int *, int, int, int, int);
void mapAddBamboo (const Layer *, int *, int, int, int, int);
void mapRiverInit (const Layer *, int *, int, int, int, int);
void mapBiomeEdge (const Layer *, int *, int, int, int, int);
void mapHills (const Layer *, int *, int, int, int, int);
void mapRiver (const Layer *, int *, int, int, int, int);
void mapSmooth (const Layer *, int *, int, int, int, int);
void mapRareBiome (const Layer *, int *, int, int, int, int);
void mapShore (const Layer *, int *, int, int, int, int);
void mapRiverMix (const Layer *, int *, int, int, int, int);
// 1.13 layers
void mapHills113 (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapOceanTemp (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapOceanMix (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapHills113 (const Layer *, int *, int, int, int, int);
void mapOceanTemp (const Layer *, int *, int, int, int, int);
void mapOceanMix (const Layer *, int *, int, int, int, int);
// final layer 1:1
void mapVoronoiZoom (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapVoronoiZoom (const Layer *, int *, int, int, int, int);
#ifdef __cplusplus

View File

@ -16,7 +16,7 @@ endif
.PHONY : all debug libcubiomes clean
all: CFLAGS += -O3 -march=native
all: find_quadhuts find_compactbiomes clean
all: libcubiomes find_quadhuts find_compactbiomes clean
debug: CFLAGS += -DDEBUG -O0 -ggdb3
debug: find_quadhuts find_compactbiomes clean
@ -54,5 +54,5 @@ util.o: util.c util.h
$(CC) -c $(CFLAGS) $<
clean:
$(RM) *.o
$(RM) *.o libcubiomes.a find_quadhuts find_compactbiomes