mirror of
https://github.com/minetest/minetest.git
synced 2025-01-03 20:07:30 +01:00
Mapgen: Add rudimentary unittests
This commit is contained in:
parent
c7fe2ee5c9
commit
50928b9759
@ -25,21 +25,7 @@ BiomeManager::BiomeManager(Server *server) :
|
||||
|
||||
// Create default biome to be used in case none exist
|
||||
Biome *b = new Biome;
|
||||
|
||||
b->name = "default";
|
||||
b->flags = 0;
|
||||
b->depth_top = 0;
|
||||
b->depth_filler = -MAX_MAP_GENERATION_LIMIT;
|
||||
b->depth_water_top = 0;
|
||||
b->depth_riverbed = 0;
|
||||
b->min_pos = v3s16(-MAX_MAP_GENERATION_LIMIT,
|
||||
-MAX_MAP_GENERATION_LIMIT, -MAX_MAP_GENERATION_LIMIT);
|
||||
b->max_pos = v3s16(MAX_MAP_GENERATION_LIMIT,
|
||||
MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT);
|
||||
b->heat_point = 0.0;
|
||||
b->humidity_point = 0.0;
|
||||
b->vertical_blend = 0;
|
||||
b->weight = 1.0f;
|
||||
|
||||
b->m_nodenames.emplace_back("mapgen_stone");
|
||||
b->m_nodenames.emplace_back("mapgen_stone");
|
||||
@ -64,12 +50,14 @@ void BiomeManager::clear()
|
||||
{
|
||||
EmergeManager *emerge = m_server->getEmergeManager();
|
||||
|
||||
if (emerge) {
|
||||
// Remove all dangling references in Decorations
|
||||
DecorationManager *decomgr = emerge->getWritableDecorationManager();
|
||||
for (size_t i = 0; i != decomgr->getNumObjects(); i++) {
|
||||
Decoration *deco = (Decoration *)decomgr->getRaw(i);
|
||||
deco->biomes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Don't delete the first biome
|
||||
for (size_t i = 1; i < m_objects.size(); i++)
|
||||
@ -299,8 +287,6 @@ ObjDef *Biome::clone() const
|
||||
ObjDef::cloneTo(obj);
|
||||
NodeResolver::cloneTo(obj);
|
||||
|
||||
obj->flags = flags;
|
||||
|
||||
obj->c_top = c_top;
|
||||
obj->c_filler = c_filler;
|
||||
obj->c_stone = c_stone;
|
||||
|
@ -19,6 +19,12 @@ class BiomeManager;
|
||||
|
||||
typedef u16 biome_t;
|
||||
|
||||
constexpr v3s16 MAX_MAP_GENERATION_LIMIT_V3(
|
||||
MAX_MAP_GENERATION_LIMIT,
|
||||
MAX_MAP_GENERATION_LIMIT,
|
||||
MAX_MAP_GENERATION_LIMIT
|
||||
);
|
||||
|
||||
#define BIOME_NONE ((biome_t)0)
|
||||
|
||||
enum BiomeType {
|
||||
@ -29,32 +35,32 @@ class Biome : public ObjDef, public NodeResolver {
|
||||
public:
|
||||
ObjDef *clone() const;
|
||||
|
||||
u32 flags;
|
||||
|
||||
content_t c_top;
|
||||
content_t c_filler;
|
||||
content_t c_stone;
|
||||
content_t c_water_top;
|
||||
content_t c_water;
|
||||
content_t c_river_water;
|
||||
content_t c_riverbed;
|
||||
content_t c_dust;
|
||||
content_t
|
||||
c_top = CONTENT_IGNORE,
|
||||
c_filler = CONTENT_IGNORE,
|
||||
c_stone = CONTENT_IGNORE,
|
||||
c_water_top = CONTENT_IGNORE,
|
||||
c_water = CONTENT_IGNORE,
|
||||
c_river_water = CONTENT_IGNORE,
|
||||
c_riverbed = CONTENT_IGNORE,
|
||||
c_dust = CONTENT_IGNORE;
|
||||
std::vector<content_t> c_cave_liquid;
|
||||
content_t c_dungeon;
|
||||
content_t c_dungeon_alt;
|
||||
content_t c_dungeon_stair;
|
||||
content_t
|
||||
c_dungeon = CONTENT_IGNORE,
|
||||
c_dungeon_alt = CONTENT_IGNORE,
|
||||
c_dungeon_stair = CONTENT_IGNORE;
|
||||
|
||||
s16 depth_top;
|
||||
s16 depth_filler;
|
||||
s16 depth_water_top;
|
||||
s16 depth_riverbed;
|
||||
s16 depth_top = 0;
|
||||
s16 depth_filler = -MAX_MAP_GENERATION_LIMIT;
|
||||
s16 depth_water_top = 0;
|
||||
s16 depth_riverbed = 0;
|
||||
|
||||
v3s16 min_pos;
|
||||
v3s16 max_pos;
|
||||
float heat_point;
|
||||
float humidity_point;
|
||||
s16 vertical_blend;
|
||||
float weight;
|
||||
v3s16 min_pos = -MAX_MAP_GENERATION_LIMIT_V3;
|
||||
v3s16 max_pos = MAX_MAP_GENERATION_LIMIT_V3;
|
||||
float heat_point = 0.0f;
|
||||
float humidity_point = 0.0f;
|
||||
s16 vertical_blend = 0;
|
||||
float weight = 1.0f;
|
||||
|
||||
virtual void resolveNodeNames();
|
||||
};
|
||||
|
@ -366,22 +366,19 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
|
||||
ModApiMapgen::es_BiomeTerrainType, BIOMETYPE_NORMAL);
|
||||
Biome *b = BiomeManager::create(biometype);
|
||||
|
||||
b->name = getstringfield_default(L, index, "name", "");
|
||||
b->depth_top = getintfield_default(L, index, "depth_top", 0);
|
||||
b->depth_filler = getintfield_default(L, index, "depth_filler", -31000);
|
||||
b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
|
||||
b->depth_riverbed = getintfield_default(L, index, "depth_riverbed", 0);
|
||||
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
|
||||
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
|
||||
b->vertical_blend = getintfield_default(L, index, "vertical_blend", 0);
|
||||
b->weight = getfloatfield_default(L, index, "weight", 1.f);
|
||||
b->flags = 0; // reserved
|
||||
getstringfield(L, index, "name", b->name);
|
||||
getintfield(L, index, "depth_top", b->depth_top);
|
||||
getintfield(L, index, "depth_filler", b->depth_filler);
|
||||
getintfield(L, index, "depth_water_top", b->depth_water_top);
|
||||
getintfield(L, index, "depth_riverbed", b->depth_riverbed);
|
||||
getfloatfield(L, index, "heat_point", b->heat_point);
|
||||
getfloatfield(L, index, "humidity_point", b->humidity_point);
|
||||
getintfield(L, index, "vertical_blend", b->vertical_blend);
|
||||
getfloatfield(L, index, "weight", b->weight);
|
||||
|
||||
b->min_pos = getv3s16field_default(
|
||||
L, index, "min_pos", v3s16(-31000, -31000, -31000));
|
||||
b->min_pos = getv3s16field_default(L, index, "min_pos", b->min_pos);
|
||||
getintfield(L, index, "y_min", b->min_pos.Y);
|
||||
b->max_pos = getv3s16field_default(
|
||||
L, index, "max_pos", v3s16(31000, 31000, 31000));
|
||||
b->max_pos = getv3s16field_default(L, index, "max_pos", b->max_pos);
|
||||
getintfield(L, index, "y_max", b->max_pos.Y);
|
||||
|
||||
std::vector<std::string> &nn = b->m_nodenames;
|
||||
|
@ -17,6 +17,7 @@ set (UNITTEST_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_lua.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_map.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapblock.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapgen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_map_settings_manager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mapnode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_modchannels.cpp
|
||||
|
114
src/unittest/test_mapgen.cpp
Normal file
114
src/unittest/test_mapgen.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
// Luanti
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2024 Minetest core developers & community
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "emerge.h"
|
||||
#include "mapgen/mapgen.h"
|
||||
#include "mapgen/mg_biome.h"
|
||||
#include "mock_server.h"
|
||||
|
||||
class TestMapgen : public TestBase
|
||||
{
|
||||
public:
|
||||
TestMapgen() { TestManager::registerTestModule(this); }
|
||||
const char *getName() { return "TestMapgen"; }
|
||||
|
||||
void runTests(IGameDef *gamedef);
|
||||
|
||||
void testBiomeGen(IGameDef *gamedef);
|
||||
};
|
||||
|
||||
static TestMapgen g_test_instance;
|
||||
|
||||
namespace {
|
||||
class MockBiomeManager : public BiomeManager {
|
||||
public:
|
||||
MockBiomeManager(Server *server) : BiomeManager(server) {}
|
||||
|
||||
void setNodeDefManager(const NodeDefManager *ndef)
|
||||
{
|
||||
m_ndef = ndef;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void TestMapgen::runTests(IGameDef *gamedef)
|
||||
{
|
||||
TEST(testBiomeGen, gamedef);
|
||||
}
|
||||
|
||||
void TestMapgen::testBiomeGen(IGameDef *gamedef)
|
||||
{
|
||||
MockServer server(getTestTempDirectory());
|
||||
MockBiomeManager bmgr(&server);
|
||||
bmgr.setNodeDefManager(gamedef->getNodeDefManager());
|
||||
|
||||
{
|
||||
// Add some biomes (equivalent to l_register_biome)
|
||||
// Taken from minetest_game/mods/default/mapgen.lua
|
||||
size_t bmgr_count = bmgr.getNumObjects(); // this is 1 ?
|
||||
|
||||
Biome *b = BiomeManager::create(BIOMETYPE_NORMAL);
|
||||
b->name = "deciduous_forest";
|
||||
b->c_top = t_CONTENT_GRASS;
|
||||
b->depth_top = 1;
|
||||
b->c_filler = t_CONTENT_BRICK; // dirt
|
||||
b->depth_filler = 3;
|
||||
b->c_stone = t_CONTENT_STONE;
|
||||
b->min_pos.Y = 1;
|
||||
b->heat_point = 60.0f;
|
||||
b->humidity_point = 68.0f;
|
||||
UASSERT(bmgr.add(b) != OBJDEF_INVALID_HANDLE);
|
||||
|
||||
b = BiomeManager::create(BIOMETYPE_NORMAL);
|
||||
b->name = "deciduous_forest_shore";
|
||||
b->c_top = t_CONTENT_BRICK; // dirt
|
||||
b->depth_top = 1;
|
||||
b->c_filler = t_CONTENT_BRICK; // dirt
|
||||
b->depth_filler = 3;
|
||||
b->c_stone = t_CONTENT_STONE;
|
||||
b->max_pos.Y = 0;
|
||||
b->heat_point = 60.0f;
|
||||
b->humidity_point = 68.0f;
|
||||
UASSERT(bmgr.add(b) != OBJDEF_INVALID_HANDLE);
|
||||
UASSERT(bmgr.getNumObjects() - bmgr_count == 2);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<BiomeParams> params(BiomeManager::createBiomeParams(BIOMEGEN_ORIGINAL));
|
||||
|
||||
constexpr v3s16 CSIZE(16, 16, 16); // misleading name. measured in nodes.
|
||||
std::unique_ptr<BiomeGen> biomegen(
|
||||
bmgr.createBiomeGen(BIOMEGEN_ORIGINAL, params.get(), CSIZE)
|
||||
);
|
||||
|
||||
{
|
||||
// Test biome transitions
|
||||
// getBiomeAtIndex (Y only)
|
||||
// getNextTransitionY
|
||||
const struct {
|
||||
s16 check_y;
|
||||
const char *name;
|
||||
s16 next_y;
|
||||
} expected_biomes[] = {
|
||||
{ MAX_MAP_GENERATION_LIMIT, "deciduous_forest", 1 },
|
||||
// ^ FIXME: next_y should be 0 (min_pos.Y - 1)
|
||||
{ 1, "deciduous_forest", 0 },
|
||||
{ 0, "deciduous_forest_shore", -MAX_MAP_GENERATION_LIMIT },
|
||||
{ -100, "deciduous_forest_shore", -MAX_MAP_GENERATION_LIMIT },
|
||||
};
|
||||
for (const auto expected : expected_biomes) {
|
||||
Biome *biome = biomegen->getBiomeAtIndex(
|
||||
(1 * CSIZE.X) + 1, // index in CSIZE 2D noise map
|
||||
v3s16(2000, expected.check_y, -1000) // absolute coordinates
|
||||
);
|
||||
s16 next_y = biomegen->getNextTransitionY(expected.check_y);
|
||||
|
||||
UASSERTEQ(auto, biome->name, expected.name);
|
||||
UASSERTEQ(auto, next_y, expected.next_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user