Node highlighting.
[oweals/minetest.git] / src / treegen.cpp
index 5ddf1132d46810dccd3a7837fde3163a9e9fcc6d..bd4a2f2c9b9760d0a439f8b9f63922e32907b864 100644 (file)
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irr_v3d.h"
 #include <stack>
+#include "util/pointer.h"
 #include "util/numeric.h"
 #include "util/mathconstants.h"
 #include "map.h"
@@ -32,6 +33,11 @@ namespace treegen
 void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
                bool is_apple_tree, INodeDefManager *ndef, int seed)
 {
+       /*
+               NOTE: Tree-placing code is currently duplicated in the engine
+               and in games that have saplings; both are deprecated but not
+               replaced yet
+       */
        MapNode treenode(ndef->getId("mapgen_tree"));
        MapNode leavesnode(ndef->getId("mapgen_leaves"));
        MapNode applenode(ndef->getId("mapgen_apple"));
@@ -112,14 +118,19 @@ void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
 }
 
 // L-System tree LUA spawner
-void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
+treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
 {
        ServerMap *map = &env->getServerMap();
        std::map<v3s16, MapBlock*> modified_blocks;
        ManualMapVoxelManipulator vmanip(map);
        v3s16 tree_blockp = getNodeBlockPos(p0);
+       treegen::error e;
+
        vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
-       make_ltree (vmanip, p0, ndef, tree_definition);
+       e = make_ltree (vmanip, p0, ndef, tree_definition);
+       if (e != SUCCESS)
+               return e;
+
        vmanip.blitBackAll(&modified_blocks);
 
        // update lighting
@@ -136,15 +147,25 @@ void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDe
                event.modified_blocks.insert(i->first);
        }
        map->dispatchEvent(&event);
+       return SUCCESS;
 }
 
 //L-System tree generator
-void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
+treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
                TreeDef tree_definition)
 {
        MapNode dirtnode(ndef->getId("mapgen_dirt"));
+       int seed;
+       if (tree_definition.explicit_seed)
+       {
+               seed = tree_definition.seed+14002;
+       }
+       else
+       {
+               seed = p0.X*2 + p0.Y*4 + p0.Z;      // use the tree position to seed PRNG
+       }
+       PseudoRandom ps(seed);
 
-       PseudoRandom ps(tree_definition.seed+14002);
        // chance of inserting abcd rules
        double prop_a = 9;
        double prop_b = 8;
@@ -225,7 +246,7 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z+1),dirtnode);
                tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z+1),dirtnode);
        }
-       if (tree_definition.trunk_type == "crossed")
+       else if (tree_definition.trunk_type == "crossed")
        {
                tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z),dirtnode);
                tree_node_placement(vmanip,v3f(position.X-1,position.Y-1,position.Z),dirtnode);
@@ -283,7 +304,7 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                                tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
                                tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition);
                        }
-                       if (tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches)
+                       else if (tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches)
                        {
                                tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
                                tree_trunk_placement(vmanip,v3f(position.X-1,position.Y,position.Z),tree_definition);
@@ -303,7 +324,7 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                                tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
                                tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition);
                        }
-                       if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") ||
+                       else if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") ||
                                (!stack_orientation.empty() && tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches))
                        {
                                tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
@@ -348,6 +369,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                        stack_position.push(position);
                        break;
                case ']':
+                       if (stack_orientation.empty())
+                               return UNBALANCED_BRACKETS;
                        rotation=stack_orientation.top();
                        stack_orientation.pop();
                        position=stack_position.top();
@@ -387,6 +410,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                        break;
                }
        }
+
+       return SUCCESS;
 }
 
 void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
@@ -510,8 +535,20 @@ v3f transposeMatrix(irr::core::matrix4 M, v3f v)
 void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
                INodeDefManager *ndef, int seed)
 {
-       MapNode treenode(ndef->getId("mapgen_jungletree"));
-       MapNode leavesnode(ndef->getId("mapgen_leaves"));
+       /*
+               NOTE: Tree-placing code is currently duplicated in the engine
+               and in games that have saplings; both are deprecated but not
+               replaced yet
+       */
+       content_t c_tree   = ndef->getId("mapgen_jungletree");
+       content_t c_leaves = ndef->getId("mapgen_jungleleaves");
+       if (c_tree == CONTENT_IGNORE)
+               c_tree = ndef->getId("mapgen_tree");
+       if (c_leaves == CONTENT_IGNORE)
+               c_leaves = ndef->getId("mapgen_leaves");
+
+       MapNode treenode(c_tree);
+       MapNode leavesnode(c_leaves);
 
        PseudoRandom pr(seed);
        for(s16 x=-1; x<=1; x++)
@@ -521,19 +558,27 @@ void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
                        continue;
                v3s16 p1 = p0 + v3s16(x,0,z);
                v3s16 p2 = p0 + v3s16(x,-1,z);
-               if(vmanip.m_area.contains(p2)
-                               && vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR)
-                       vmanip.m_data[vmanip.m_area.index(p2)] = treenode;
-               else if(vmanip.m_area.contains(p1))
-                       vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
+               u32 vi1 = vmanip.m_area.index(p1);
+               u32 vi2 = vmanip.m_area.index(p2);
+               
+               if (vmanip.m_area.contains(p2) &&
+                       vmanip.m_data[vi2].getContent() == CONTENT_AIR)
+                       vmanip.m_data[vi2] = treenode;
+               else if (vmanip.m_area.contains(p1) &&
+                               vmanip.m_data[vi1].getContent() == CONTENT_AIR)
+                       vmanip.m_data[vi1] = treenode;
        }
+       vmanip.m_data[vmanip.m_area.index(p0)] = treenode;
 
        s16 trunk_h = pr.range(8, 12);
        v3s16 p1 = p0;
-       for(s16 ii=0; ii<trunk_h; ii++)
+       for (s16 ii=0; ii<trunk_h; ii++)
        {
-               if(vmanip.m_area.contains(p1))
-                       vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
+               if (vmanip.m_area.contains(p1)) {
+                       u32 vi = vmanip.m_area.index(p1);
+                       if (vmanip.m_data[vi].getContent() == CONTENT_AIR)
+                               vmanip.m_data[vi] = treenode;
+               }
                p1.Y++;
        }
 
@@ -586,8 +631,8 @@ void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
                if(vmanip.m_area.contains(p) == false)
                        continue;
                u32 vi = vmanip.m_area.index(p);
-               if(vmanip.m_data[vi].getContent() != CONTENT_AIR
-                               && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
+               if (vmanip.m_data[vi].getContent() != CONTENT_AIR &&
+                       vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
                        continue;
                u32 i = leaves_a.index(x,y,z);
                if(leaves_d[i] == 1)