aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2014-10-29 01:54:11 -0400
committerkwolekr <kwolekr@minetest.net>2014-10-29 01:56:37 -0400
commit1cb6ea6346f568cd068380c5af52f7be269e3490 (patch)
tree1eab8e93b1621b5065c16c0973efecd4d5770939
parent7c6da2f38468b1eaf3b6c9b5cd0ee985e6675e31 (diff)
downloadminetest-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.cpp10
-rw-r--r--src/mapgen.cpp105
-rw-r--r--src/mapgen.h3
-rw-r--r--src/nodedef.h2
-rw-r--r--src/script/lua_api/l_mapgen.cpp155
-rw-r--r--src/script/lua_api/l_mapgen.h9
-rw-r--r--src/util/numeric.h4
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; \