From e3badd7062d4bee62335cf100f3f91ef4c370aae Mon Sep 17 00:00:00 2001
From: kwolekr <kwolekr@minetest.net>
Date: Sat, 16 Mar 2013 19:37:27 -0400
Subject: [PATCH] Make saplings only grow on dirt or grass, make jungle tree
 trunks only replace air

---
 src/content_abm.cpp | 19 +++++++++++++++++--
 src/treegen.cpp     | 28 ++++++++++++++++++----------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/src/content_abm.cpp b/src/content_abm.cpp
index e50edddd7..ccd9ca19c 100644
--- a/src/content_abm.cpp
+++ b/src/content_abm.cpp
@@ -94,7 +94,17 @@ class RemoveGrassABM : public ActiveBlockModifier
 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
 {
 private:
+	content_t c_junglesapling;
+	content_t c_dirt;
+	content_t c_dirt_with_grass;
+	
 public:
+	MakeTreesFromSaplingsABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
+		c_junglesapling   = nodemgr->getId("junglesapling");
+		c_dirt            = nodemgr->getId("mapgen_dirt");
+		c_dirt_with_grass = nodemgr->getId("mapgen_dirt_with_grass");
+	}
+
 	virtual std::set<std::string> getTriggerContents()
 	{
 		std::set<std::string> s;
@@ -112,7 +122,12 @@ class MakeTreesFromSaplingsABM : public ActiveBlockModifier
 		INodeDefManager *ndef = env->getGameDef()->ndef();
 		ServerMap *map = &env->getServerMap();
 		
-		bool is_jungle_tree = n.getContent() == ndef->getId("junglesapling");
+		MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0));
+		if (n_below.getContent() != c_dirt &&
+			n_below.getContent() != c_dirt_with_grass)
+			return;
+			
+		bool is_jungle_tree = n.getContent() == c_junglesapling;
 		
 		actionstream <<"A " << (is_jungle_tree ? "jungle " : "")
 				<< "sapling grows into a tree at "
@@ -187,7 +202,7 @@ void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
 {
 	env->addActiveBlockModifier(new GrowGrassABM());
 	env->addActiveBlockModifier(new RemoveGrassABM());
-	env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
+	env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
 	if (g_settings->getBool("liquid_finite"))
 		env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
 }
diff --git a/src/treegen.cpp b/src/treegen.cpp
index 9df528a21..808cf916a 100644
--- a/src/treegen.cpp
+++ b/src/treegen.cpp
@@ -528,19 +528,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++;
 	}
 
@@ -593,8 +601,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)
-- 
GitLab