From 1cb6ea6346f568cd068380c5af52f7be269e3490 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Wed, 29 Oct 2014 01:54:11 -0400 Subject: [PATCH] Refactor decoration-related code Split up ModApiMapgen::l_register_decoration() Define and make use of CONTAINS() and ARRLEN() macros --- src/clouds.cpp | 10 +- src/mapgen.cpp | 109 +++++++++++---------- src/mapgen.h | 3 +- src/nodedef.h | 2 +- src/script/lua_api/l_mapgen.cpp | 163 ++++++++++++++++---------------- src/script/lua_api/l_mapgen.h | 9 ++ src/util/numeric.h | 4 + 7 files changed, 158 insertions(+), 142 deletions(-) diff --git a/src/clouds.cpp b/src/clouds.cpp index 1bf6dc9c..10ac8f5b 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; zi0m_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) /////////////////////////////////////////////////////////////////////////////// +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); + + // Check if the decoration can be placed on this node + if (!CONTAINS(c_place_on, vm->m_data[vi].getContent())) + return false; + + // 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 (CONTAINS(c_spawnby, vm->m_data[index].getContent())) + nneighs++; + } + + if (nneighs < nspawnby) + return false; + + return true; +} + void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) { ManualMapVoxelManipulator *vm = mg->vm; - 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 (!canPlaceDecoration(vm, p)) 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; - - 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; - } - } - } - - if (nneighs < nspawnby) - return; - } - - if (c_decos.size() == 0) - 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 01ab2273..b6efe820 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 489aefff..f41017f6 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 d0337cad..75f5afa8 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,92 +393,102 @@ 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; - - 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 (dsimple->deco_height <= 0) { - errorstream << "register_decoration: simple decoration height" - " must be greater than 0" << std::endl; - delete dsimple; - return 0; - } - - std::vector 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; - } - - std::vector 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; - } - - 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); - + case DECO_SIMPLE: + success = regDecoSimple(L, resolver, (DecoSimple *)deco); break; - } - case DECO_SCHEMATIC: { - DecoSchematic *dschem = (DecoSchematic *)deco; - - dschem->flags = 0; - getflagsfield(L, index, "flags", flagdesc_deco_schematic, - &dschem->flags, NULL); - - dschem->rotation = (Rotation)getenumfield(L, index, - "rotation", es_Rotation, ROTATE_0); - - std::map 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, dschem, getServer(L))) { - delete dschem; - return 0; - } - lua_pop(L, -1); - - 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; - } - + case DECO_SCHEMATIC: + success = regDecoSchematic(L, resolver, (DecoSchematic *)deco); break; - } - case DECO_LSYSTEM: { - //DecoLSystem *decolsystem = (DecoLSystem *)deco; + case DECO_LSYSTEM: break; - } + } + + if (!success) { + delete deco; + return 0; } emerge->decorations.push_back(deco); verbosestream << "register_decoration: decoration '" << deco->getName() << "' registered" << std::endl; + return 0; } +bool ModApiMapgen::regDecoSimple(lua_State *L, + NodeResolver *resolver, DecoSimple *deco) +{ + int index = 1; + + 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); + + if (deco->deco_height <= 0) { + errorstream << "register_decoration: simple decoration height" + " must be greater than 0" << std::endl; + return false; + } + + std::vector 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::vector 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; + } + + 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); + + return true; +} + +bool ModApiMapgen::regDecoSchematic(lua_State *L, + NodeResolver *resolver, DecoSchematic *deco) +{ + int index = 1; + + deco->flags = 0; + getflagsfield(L, index, "flags", flagdesc_deco_schematic, &deco->flags, NULL); + + deco->rotation = (Rotation)getenumfield(L, index, "rotation", + es_Rotation, ROTATE_0); + + std::map 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}) int ModApiMapgen::l_register_ore(lua_State *L) { diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 8ffe3289..d14471a0 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 8e3a617f..ee8fea8c 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 +#include // Calculate the borders of a "d-radius" cube void getFacePositions(std::list &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; \