#include "testHarness.h" #include "vf/NetherGen.h" #include #include using namespace vf; namespace { std::map censusColumn(const World& world, int columnX, int columnZ, int ceilingY) { std::map tally; int ox = columnX * chunkSize; int oz = columnZ * chunkSize; for (int gx = ox; gx < ox + chunkSize; ++gx) for (int gz = oz; gz < oz + chunkSize; ++gz) for (int gy = 0; gy < ceilingY; ++gy) ++tally[world.blockAt(gx, gy, gz)]; return tally; } int countOf(const std::map& tally, Block block) { auto it = tally.find(block); return it == tally.end() ? 0 : it->second; } int findColumnWithBiome(const NetherGenerator& generator, NetherBiome biome, int& outColumnX, int& outColumnZ) { for (int columnX = -40; columnX <= 40; ++columnX) { for (int columnZ = -40; columnZ <= 40; ++columnZ) { int probeX = columnX * chunkSize + 8; int probeZ = columnZ * chunkSize + 8; if (generator.biomeAt(probeX, probeZ) != biome) continue; outColumnX = columnX; outColumnZ = columnZ; return 1; } } return 0; } } // namespace VF_TEST(netherChunkGenerationRepeatsExactlyOnTheSameSeed) { NetherGenerator generator; Chunk first, second; generator.generateChunk(first, {2, 3, -4}); generator.generateChunk(second, {2, 3, -4}); CHECK(first.raw() == second.raw()); Chunk elsewhere; generator.generateChunk(elsewhere, {2, 3, 5}); CHECK(first.raw() != elsewhere.raw()); NetherGenerator::Params other; other.seed = 9001u; NetherGenerator reseeded(other); World original, alternative; generator.generateColumn(original, 2, -4); reseeded.generateColumn(alternative, 2, -4); int differingChunks = 0; for (const auto& entry : original.allChunks()) { const Chunk* twin = alternative.chunkAt(entry.first); if (!twin || twin->raw() != entry.second->raw()) ++differingChunks; } CHECK(differingChunks > 0); } VF_TEST(netherColumnIsByteIdenticalAcrossTwoRuns) { NetherGenerator generator; World first, second; generator.generateColumn(first, -3, 6); generator.generateColumn(second, -3, 6); CHECK_EQ(first.chunkCount(), second.chunkCount()); CHECK_EQ(first.chunkCount(), static_cast(generator.stackChunkCount())); int mismatches = 0; for (const auto& entry : first.allChunks()) { const Chunk* twin = second.chunkAt(entry.first); if (!twin || twin->raw() != entry.second->raw()) ++mismatches; } CHECK_EQ(mismatches, 0); } VF_TEST(netherGenerationStaysInsideTheColumnItWasAskedFor) { NetherGenerator generator; World world; generator.generateColumn(world, 5, 7); int strays = 0; for (const auto& entry : world.allChunks()) if (entry.first.x != 5 || entry.first.z != 7) ++strays; CHECK_EQ(strays, 0); } VF_TEST(netherIsSealedByBedrockAtTheFloorAndTheRoof) { NetherGenerator generator; const NetherGenerator::Params& params = generator.settings(); World world; generator.generateColumn(world, 0, 0); int floorGaps = 0; int roofGaps = 0; for (int gx = 0; gx < chunkSize; ++gx) { for (int gz = 0; gz < chunkSize; ++gz) { if (world.blockAt(gx, params.floorY, gz) != Block::Bedrock) ++floorGaps; if (world.blockAt(gx, params.ceilingY - 1, gz) != Block::Bedrock) ++roofGaps; } } CHECK_EQ(floorGaps, 0); CHECK_EQ(roofGaps, 0); // The bands just inside those layers are ragged, not uniformly bedrock. int raggedFloor = 0; for (int gx = 0; gx < chunkSize; ++gx) for (int gz = 0; gz < chunkSize; ++gz) if (generator.isBedrock(gx, params.floorY + 2, gz)) ++raggedFloor; CHECK(raggedFloor > 0); CHECK(raggedFloor < chunkSize * chunkSize); CHECK(!generator.isBedrock(0, 60, 0)); } VF_TEST(netherCavernSitsBetweenTheFloorAndTheRoofMass) { NetherGenerator generator; const NetherGenerator::Params& params = generator.settings(); int drownedColumns = 0; int dryColumns = 0; for (int gx = -400; gx <= 400; gx += 37) { for (int gz = -400; gz <= 400; gz += 37) { NetherColumn column = generator.columnAt(gx, gz); CHECK(column.floorHeight > params.floorY); CHECK(column.ceilingHeight < params.ceilingY - 1); CHECK(column.cavernHeight() >= 9); CHECK_EQ(column.lavaLevel, params.lavaLevel); if (column.drowned) ++drownedColumns; else ++dryColumns; } } CHECK(drownedColumns > 0); CHECK(dryColumns > 0); } VF_TEST(netherLavaSeaLeavesNoAirBelowItsSurface) { NetherGenerator generator; const NetherGenerator::Params& params = generator.settings(); int airBelowLava = 0; int lavaSamples = 0; for (int gx = -120; gx <= 120; gx += 11) { for (int gz = -120; gz <= 120; gz += 11) { NetherColumn column = generator.columnAt(gx, gz); for (int gy = params.floorY + 1; gy <= params.lavaLevel; ++gy) { Block block = generator.blockAt(column, gx, gy, gz); if (block == Block::Air) ++airBelowLava; if (block == Block::Lava) ++lavaSamples; } } } CHECK_EQ(airBelowLava, 0); CHECK(lavaSamples > 0); }