diff options
author | kwolekr <kwolekr@minetest.net> | 2014-10-29 01:54:11 -0400 |
---|---|---|
committer | kwolekr <kwolekr@minetest.net> | 2014-10-29 01:56:37 -0400 |
commit | 1cb6ea6346f568cd068380c5af52f7be269e3490 (patch) | |
tree | 1eab8e93b1621b5065c16c0973efecd4d5770939 | |
parent | 7c6da2f38468b1eaf3b6c9b5cd0ee985e6675e31 (diff) | |
download | minetest-1cb6ea6346f568cd068380c5af52f7be269e3490.tar.gz minetest-1cb6ea6346f568cd068380c5af52f7be269e3490.tar.bz2 minetest-1cb6ea6346f568cd068380c5af52f7be269e3490.zip |
Refactor decoration-related code
Split up ModApiMapgen::l_register_decoration()
Define and make use of CONTAINS() and ARRLEN() macros
-rw-r--r-- | src/clouds.cpp | 10 | ||||
-rw-r--r-- | src/mapgen.cpp | 105 | ||||
-rw-r--r-- | src/mapgen.h | 3 | ||||
-rw-r--r-- | src/nodedef.h | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_mapgen.cpp | 155 | ||||
-rw-r--r-- | src/script/lua_api/l_mapgen.h | 9 | ||||
-rw-r--r-- | src/util/numeric.h | 4 |
7 files changed, 152 insertions, 136 deletions
diff --git a/src/clouds.cpp b/src/clouds.cpp index 1bf6dc9c1..10ac8f5b3 100644 --- a/src/clouds.cpp +++ b/src/clouds.cpp @@ -189,7 +189,7 @@ void Clouds::render() } #define GETINDEX(x, z, radius) (((z)+(radius))*(radius)*2 + (x)+(radius)) -#define CONTAINS(x, z, radius) \ +#define INAREA(x, z, radius) \ ((x) >= -(radius) && (x) < (radius) && (z) >= -(radius) && (z) < (radius)) for(s16 zi0=-cloud_radius_i; zi0<cloud_radius_i; zi0++) @@ -247,7 +247,7 @@ void Clouds::render() v[3].Pos.set( rx, ry,-rz); break; case 1: // back - if(CONTAINS(xi, zi-1, cloud_radius_i)){ + if(INAREA(xi, zi-1, cloud_radius_i)){ u32 j = GETINDEX(xi, zi-1, cloud_radius_i); if(grid[j]) continue; @@ -262,7 +262,7 @@ void Clouds::render() v[3].Pos.set(-rx,-ry,-rz); break; case 2: //right - if(CONTAINS(xi+1, zi, cloud_radius_i)){ + if(INAREA(xi+1, zi, cloud_radius_i)){ u32 j = GETINDEX(xi+1, zi, cloud_radius_i); if(grid[j]) continue; @@ -277,7 +277,7 @@ void Clouds::render() v[3].Pos.set( rx,-ry,-rz); break; case 3: // front - if(CONTAINS(xi, zi+1, cloud_radius_i)){ + if(INAREA(xi, zi+1, cloud_radius_i)){ u32 j = GETINDEX(xi, zi+1, cloud_radius_i); if(grid[j]) continue; @@ -292,7 +292,7 @@ void Clouds::render() v[3].Pos.set( rx,-ry, rz); break; case 4: // left - if(CONTAINS(xi-1, zi, cloud_radius_i)){ + if(INAREA(xi-1, zi, cloud_radius_i)){ u32 j = GETINDEX(xi-1, zi, cloud_radius_i); if(grid[j]) continue; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index b7c929be7..11f76984d 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -149,9 +149,10 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed, continue; u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); - for (size_t ii = 0; ii < c_wherein.size(); ii++) - if (vm->m_data[i].getContent() == c_wherein[ii]) - vm->m_data[i] = n_ore; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; + + vm->m_data[i] = n_ore; } } } @@ -187,13 +188,10 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed, u32 i = vm->m_area.index(x, y, z); if (!vm->m_area.contains(i)) continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; - for (size_t ii = 0; ii < c_wherein.size(); ii++) { - if (vm->m_data[i].getContent() == c_wherein[ii]) { - vm->m_data[i] = n_ore; - break; - } - } + vm->m_data[i] = n_ore; } } } @@ -360,53 +358,56 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) /////////////////////////////////////////////////////////////////////////////// - -void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { - ManualMapVoxelManipulator *vm = mg->vm; +bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p) { + // Don't bother if there aren't any decorations to place + if (c_decos.size() == 0) + return false; u32 vi = vm->m_area.index(p); - content_t c = vm->m_data[vi].getContent(); - size_t idx; - for (idx = 0; idx != c_place_on.size(); idx++) { - if (c == c_place_on[idx]) - break; - } - if ((idx != 0) && (idx == c_place_on.size())) - return; - if (nspawnby != -1) { - int nneighs = 0; - v3s16 dirs[8] = { // a Moore neighborhood - v3s16( 0, 0, 1), - v3s16( 0, 0, -1), - v3s16( 1, 0, 0), - v3s16(-1, 0, 0), - v3s16( 1, 0, 1), - v3s16(-1, 0, 1), - v3s16(-1, 0, -1), - v3s16( 1, 0, -1) - }; - - for (int i = 0; i != 8; i++) { - u32 index = vm->m_area.index(p + dirs[i]); - if (!vm->m_area.contains(index)) - continue; + // Check if the decoration can be placed on this node + if (!CONTAINS(c_place_on, vm->m_data[vi].getContent())) + return false; - content_t c = vm->m_data[index].getContent(); - for (size_t j = 0; j != c_spawnby.size(); j++) { - if (c == c_spawnby[j]) { - nneighs++; - break; - } - } - } + // Don't continue if there are no spawnby constraints + if (nspawnby == -1) + return true; + + int nneighs = 0; + v3s16 dirs[8] = { + v3s16( 0, 0, 1), + v3s16( 0, 0, -1), + v3s16( 1, 0, 0), + v3s16(-1, 0, 0), + v3s16( 1, 0, 1), + v3s16(-1, 0, 1), + v3s16(-1, 0, -1), + v3s16( 1, 0, -1) + }; + + // Check a Moore neighborhood if there are enough spawnby nodes + for (size_t i = 0; i != ARRLEN(dirs); i++) { + u32 index = vm->m_area.index(p + dirs[i]); + if (!vm->m_area.contains(index)) + continue; - if (nneighs < nspawnby) - return; + if (CONTAINS(c_spawnby, vm->m_data[index].getContent())) + nneighs++; } - if (c_decos.size() == 0) + if (nneighs < nspawnby) + return false; + + return true; +} + + +void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { + ManualMapVoxelManipulator *vm = mg->vm; + + if (!canPlaceDecoration(vm, p)) return; + content_t c_place = c_decos[pr->range(0, c_decos.size() - 1)]; s16 height = (deco_height_max > 0) ? @@ -415,6 +416,7 @@ void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { height = MYMIN(height, max_y - p.Y); v3s16 em = vm->m_area.getExtent(); + u32 vi = vm->m_area.index(p); for (int i = 0; i < height; i++) { vm->m_area.add_y(em, vi, 1); @@ -477,12 +479,7 @@ void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { u32 vi = vm->m_area.index(p); content_t c = vm->m_data[vi].getContent(); - size_t idx; - for (idx = 0; idx != c_place_on.size(); idx++) { - if (c == c_place_on[idx]) - break; - } - if ((idx != 0) && (idx == c_place_on.size())) + if (!CONTAINS(c_place_on, c)) return; Rotation rot = (rotation == ROTATE_RAND) ? diff --git a/src/mapgen.h b/src/mapgen.h index 01ab22730..b6efe8200 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -207,7 +207,7 @@ Ore *createOre(OreType type); enum DecorationType { - DECO_SIMPLE = 1, + DECO_SIMPLE, DECO_SCHEMATIC, DECO_LSYSTEM }; @@ -262,6 +262,7 @@ public: ~DecoSimple() {} + bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p); virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); virtual int getHeight(); virtual std::string getName(); diff --git a/src/nodedef.h b/src/nodedef.h index 489aefffd..f41017f63 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -350,7 +350,7 @@ public: before the pending request had been satisfied, cancelNodeList() must be called. - @param nodename Name of node (or node group) to be resolved. + @param nodename Name of node (or node group) to be resolved. @param content_vec Pointer to content_t vector onto which the results are added. diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index d0337cad6..75f5afa88 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -354,12 +354,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); enum DecorationType decotype = (DecorationType)getenumfield(L, index, - "deco_type", es_DecorationType, 0); - if (decotype == 0) { - errorstream << "register_decoration: unrecognized " - "decoration placement type"; - return 0; - } + "deco_type", es_DecorationType, -1); Decoration *deco = createDecoration(decotype); if (!deco) { @@ -398,90 +393,100 @@ int ModApiMapgen::l_register_decoration(lua_State *L) } //// Handle decoration type-specific parameters + bool success = false; switch (decotype) { - case DECO_SIMPLE: { - DecoSimple *dsimple = (DecoSimple *)deco; + case DECO_SIMPLE: + success = regDecoSimple(L, resolver, (DecoSimple *)deco); + break; + case DECO_SCHEMATIC: + success = regDecoSchematic(L, resolver, (DecoSchematic *)deco); + break; + case DECO_LSYSTEM: + break; + } - dsimple->deco_height = getintfield_default(L, index, "height", 1); - dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0); - dsimple->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); + if (!success) { + delete deco; + return 0; + } - if (dsimple->deco_height <= 0) { - errorstream << "register_decoration: simple decoration height" - " must be greater than 0" << std::endl; - delete dsimple; - return 0; - } + emerge->decorations.push_back(deco); - std::vector<const char *> deco_names; - getstringlistfield(L, index, "decoration", deco_names); - if (deco_names.size() == 0) { - errorstream << "register_decoration: no decoration nodes " - "defined" << std::endl; - delete dsimple; - return 0; - } + verbosestream << "register_decoration: decoration '" << deco->getName() + << "' registered" << std::endl; - std::vector<const char *> spawnby_names; - getstringlistfield(L, index, "spawn_by", spawnby_names); - if (dsimple->nspawnby != -1 && spawnby_names.size() == 0) { - errorstream << "register_decoration: no spawn_by nodes defined," - " but num_spawn_by specified" << std::endl; - delete dsimple; - return 0; - } + return 0; +} - for (size_t i = 0; i != deco_names.size(); i++) - resolver->addNodeList(deco_names[i], &dsimple->c_decos); - for (size_t i = 0; i != spawnby_names.size(); i++) - resolver->addNodeList(spawnby_names[i], &dsimple->c_spawnby); +bool ModApiMapgen::regDecoSimple(lua_State *L, + NodeResolver *resolver, DecoSimple *deco) +{ + int index = 1; - break; - } - case DECO_SCHEMATIC: { - DecoSchematic *dschem = (DecoSchematic *)deco; + deco->deco_height = getintfield_default(L, index, "height", 1); + deco->deco_height_max = getintfield_default(L, index, "height_max", 0); + deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); - dschem->flags = 0; - getflagsfield(L, index, "flags", flagdesc_deco_schematic, - &dschem->flags, NULL); + if (deco->deco_height <= 0) { + errorstream << "register_decoration: simple decoration height" + " must be greater than 0" << std::endl; + return false; + } - dschem->rotation = (Rotation)getenumfield(L, index, - "rotation", es_Rotation, ROTATE_0); + std::vector<const char *> deco_names; + getstringlistfield(L, index, "decoration", deco_names); + if (deco_names.size() == 0) { + errorstream << "register_decoration: no decoration nodes " + "defined" << std::endl; + return false; + } - std::map<std::string, std::string> replace_names; - lua_getfield(L, index, "replacements"); - if (lua_istable(L, -1)) - read_schematic_replacements(L, replace_names, lua_gettop(L)); - lua_pop(L, 1); + std::vector<const char *> spawnby_names; + getstringlistfield(L, index, "spawn_by", spawnby_names); + if (deco->nspawnby != -1 && spawnby_names.size() == 0) { + errorstream << "register_decoration: no spawn_by nodes defined," + " but num_spawn_by specified" << std::endl; + return false; + } - lua_getfield(L, index, "schematic"); - if (!read_schematic(L, -1, dschem, getServer(L))) { - delete dschem; - return 0; - } - lua_pop(L, -1); + for (size_t i = 0; i != deco_names.size(); i++) + resolver->addNodeList(deco_names[i], &deco->c_decos); + for (size_t i = 0; i != spawnby_names.size(); i++) + resolver->addNodeList(spawnby_names[i], &deco->c_spawnby); - if (!dschem->filename.empty() && - !dschem->loadSchematicFile(resolver, replace_names)) { - errorstream << "register_decoration: failed to load schematic" - " file '" << dschem->filename << "'" << std::endl; - delete dschem; - return 0; - } + return true; +} - break; - } - case DECO_LSYSTEM: { - //DecoLSystem *decolsystem = (DecoLSystem *)deco; - break; - } - } +bool ModApiMapgen::regDecoSchematic(lua_State *L, + NodeResolver *resolver, DecoSchematic *deco) +{ + int index = 1; - emerge->decorations.push_back(deco); + deco->flags = 0; + getflagsfield(L, index, "flags", flagdesc_deco_schematic, &deco->flags, NULL); - verbosestream << "register_decoration: decoration '" << deco->getName() - << "' registered" << std::endl; - return 0; + deco->rotation = (Rotation)getenumfield(L, index, "rotation", + es_Rotation, ROTATE_0); + + std::map<std::string, std::string> replace_names; + lua_getfield(L, index, "replacements"); + if (lua_istable(L, -1)) + read_schematic_replacements(L, replace_names, lua_gettop(L)); + lua_pop(L, 1); + + lua_getfield(L, index, "schematic"); + if (!read_schematic(L, -1, deco, getServer(L))) + return false; + lua_pop(L, -1); + + if (!deco->filename.empty() && + !deco->loadSchematicFile(resolver, replace_names)) { + errorstream << "register_decoration: failed to load schematic" + " file '" << deco->filename << "'" << std::endl; + return false; + } + + return true; } // register_ore({lots of stuff}) diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 8ffe32893..d14471a08 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -22,6 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" +class NodeResolver; +class DecoSimple; +class DecoSchematic; + class ModApiMapgen : public ModApiBase { private: // get_mapgen_object(objectname) @@ -53,6 +57,11 @@ private: // place_schematic(p, schematic, rotation, replacement) static int l_place_schematic(lua_State *L); + static bool regDecoSimple(lua_State *L, + NodeResolver *resolver, DecoSimple *deco); + static bool regDecoSchematic(lua_State *L, + NodeResolver *resolver, DecoSchematic *deco); + static struct EnumString es_BiomeTerrainType[]; static struct EnumString es_DecorationType[]; static struct EnumString es_MapgenObject[]; diff --git a/src/util/numeric.h b/src/util/numeric.h index 8e3a617ff..ee8fea8cf 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../irr_v3d.h" #include "../irr_aabb3d.h" #include <list> +#include <algorithm> // Calculate the borders of a "d-radius" cube void getFacePositions(std::list<v3s16> &list, u16 d); @@ -139,6 +140,9 @@ inline v3s16 arealim(v3s16 p, s16 d) return p; } +#define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) +#define CONTAINS(c, v) (std::find((c).begin(), (c).end(), (v)) != (c).end()) + // The naive swap performs better than the xor version #define SWAP(t, x, y) do { \ t temp = x; \ |