#include "irr_v3d.h"
#include <stack>
+#include "util/pointer.h"
#include "util/numeric.h"
#include "util/mathconstants.h"
#include "map.h"
namespace treegen
{
-void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
+void make_tree(MMVManip &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"));
}
// 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);
+ MMVManip 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
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(MMVManip &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;
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);
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);
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);
stack_position.push(position);
break;
case ']':
+ if (stack_orientation.empty())
+ return UNBALANCED_BRACKETS;
rotation=stack_orientation.top();
stack_orientation.pop();
position=stack_position.top();
break;
}
}
+
+ return SUCCESS;
}
-void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_node_placement(MMVManip &vmanip, v3f p0,
MapNode node)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
vmanip.m_data[vmanip.m_area.index(p1)] = node;
}
-void tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_trunk_placement(MMVManip &vmanip, v3f p0,
TreeDef &tree_definition)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.trunknode;
}
-void tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_leaves_placement(MMVManip &vmanip, v3f p0,
PseudoRandom ps ,TreeDef &tree_definition)
{
MapNode leavesnode=tree_definition.leavesnode;
u32 vi = vmanip.m_area.index(p1);
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
- return;
+ return;
if (tree_definition.fruit_chance>0)
{
if (ps.range(1,100) > 100-tree_definition.fruit_chance)
vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
}
-void tree_single_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_single_leaves_placement(MMVManip &vmanip, v3f p0,
PseudoRandom ps, TreeDef &tree_definition)
{
MapNode leavesnode=tree_definition.leavesnode;
vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
}
-void tree_fruit_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_fruit_placement(MMVManip &vmanip, v3f p0,
TreeDef &tree_definition)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
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
+ */
content_t c_tree = ndef->getId("mapgen_jungletree");
content_t c_leaves = ndef->getId("mapgen_jungleleaves");
if (c_tree == CONTENT_IGNORE)
v3s16 p2 = p0 + v3s16(x,-1,z);
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;