Refactor decoration-related code
authorkwolekr <kwolekr@minetest.net>
Wed, 29 Oct 2014 05:54:11 +0000 (01:54 -0400)
committerkwolekr <kwolekr@minetest.net>
Wed, 29 Oct 2014 05:56:37 +0000 (01:56 -0400)
Split up ModApiMapgen::l_register_decoration()
Define and make use of CONTAINS() and ARRLEN() macros

src/clouds.cpp
src/mapgen.cpp
src/mapgen.h
src/nodedef.h
src/script/lua_api/l_mapgen.cpp
src/script/lua_api/l_mapgen.h
src/util/numeric.h

index 1bf6dc9c1170d46318ee97431c3e6558da505e1f..10ac8f5b36b1ee679ee4b54e4ef21c5e22952d89 100644 (file)
@@ -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;
index b7c929be7d6cb4185c416f739a54f1849e6c9eec..11f76984d8d52fec2ca17bc2664181a0d7ead6c6 100644 (file)
@@ -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) ?
index 01ab22730613b2993a4a4dfb7e5f8eadf5eebce4..b6efe8200a0eff324d8434d25ee8eadd4886f208 100644 (file)
@@ -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();
index 489aefffddb0af0b53ac58af06932d5797e26187..f41017f63ec22f054aae382eb8bef69219be588a 100644 (file)
@@ -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.
 
index d0337cad6aaec8dde4872dd640886f1ff4d8a359..75f5afa88a64b6f17a45318992898ba0fa1b672f 100644 (file)
@@ -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})
index 8ffe32893f793226835cf73fba8da49b34732799..d14471a08f62e266e3e5a643aa0063e12201ed2f 100644 (file)
@@ -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[];
index 8e3a617ffdc0a0a0622c7844e208e38c9f574dbf..ee8fea8cfb0e68ad7c231c1ddae360a0c6375e14 100644 (file)
@@ -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;            \