From 85f119e1e6cc958a54eaf8468f2a302aa8c60dbe Mon Sep 17 00:00:00 2001
From: Mark Holmquist <marktraceur@gmail.com>
Date: Tue, 16 Aug 2011 02:14:49 -0700
Subject: [PATCH] Adding (most) of the sapling functionality. It has yet to
 work, since MEET_OTHER was not implemented at the time of this commit.
 Hopefully it will work when merged with celeron's latest.

---
 src/content_mapblock.cpp | 61 ++++++++++++++++++++++++++++++++++++++++
 src/content_mapnode.cpp  | 14 +++++++++
 src/content_mapnode.h    |  2 +-
 src/environment.cpp      | 30 +++++++++++++++++++-
 src/map.cpp              |  1 +
 src/mapgen.h             |  3 ++
 src/mapnode.h            |  4 +++
 src/server.cpp           | 28 ++++++++++++++++++
 8 files changed, 141 insertions(+), 2 deletions(-)

diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 1cc37b969..9a156cb55 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -199,6 +199,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 			g_texturesource->getTextureId("apple.png"));
 	material_apple.setTexture(0, pa_apple.atlas);
 
+
+	// Sapling material
+	video::SMaterial material_sapling;
+	material_sapling.setFlag(video::EMF_LIGHTING, false);
+	material_sapling.setFlag(video::EMF_BILINEAR_FILTER, false);
+	material_sapling.setFlag(video::EMF_FOG_ENABLE, true);
+	material_sapling.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+	AtlasPointer pa_sapling = g_texturesource->getTexture(
+			g_texturesource->getTextureId("sapling.png"));
+	material_sapling.setTexture(0, pa_sapling.atlas);
+
+
 	// junglegrass material
 	video::SMaterial material_junglegrass;
 	material_junglegrass.setFlag(video::EMF_LIGHTING, false);
@@ -1263,6 +1275,55 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 				collector.append(material_apple, vertices, 4, indices, 6);
 			}
 		}
+		else if(n.getContent() == CONTENT_SAPLING) {
+		        u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+			video::SColor c = MapBlock_LightColor(255, l);
+
+			for(u32 j=0; j<4; j++)
+			{
+				video::S3DVertex vertices[4] =
+				{
+					video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
+						pa_sapling.x0(), pa_sapling.y1()),
+					video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
+						pa_sapling.x1(), pa_sapling.y1()),
+					video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
+						pa_sapling.x1(), pa_sapling.y0()),
+					video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
+						pa_sapling.x0(), pa_sapling.y0()),
+				};
+
+				if(j == 0)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(45);
+				}
+				else if(j == 1)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(-45);
+				}
+				else if(j == 2)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(135);
+				}
+				else if(j == 3)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(-135);
+				}
+
+				for(u16 i=0; i<4; i++)
+				{
+					vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+				}
+
+				u16 indices[] = {0,1,2,2,3,0};
+				// Add to mesh collector
+				collector.append(material_sapling, vertices, 4, indices, 6);
+			}
+		}
 	}
 }
 #endif
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index 09a84156a..308397735 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -242,6 +242,8 @@ void content_mapnode_init()
 	{
 		f->setAllTextures("[noalpha:leaves.png");
 	}
+	f->extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
+	f->extra_dug_item_rarity = 10;
 	f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
 	setWoodLikeDiggingProperties(f->digging_properties, 0.15);
 
@@ -629,6 +631,18 @@ void content_mapnode_init()
 	f->setInventoryTexture("nc_rb.png");
 	f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
 	setStoneLikeDiggingProperties(f->digging_properties, 3.0);
+
+	i = CONTENT_SAPLING;
+	f = &content_features(i);
+	f->param_type = CPT_LIGHT;
+	f->setAllTextures("sapling.png");
+	f->setInventoryTexture("sapling.png");
+	f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+	f->light_propagates = true;
+	f->air_equivalent = false;
+	f->solidness = 0; // drawn separately, makes no faces
+	f->walkable = false;
+	f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
 	
 	i = CONTENT_APPLE;
 	f = &content_features(i);
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index 35dcc20ec..c1e12ab42 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -84,7 +84,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
 #define CONTENT_NC 0x817
 #define CONTENT_NC_RB 0x818
 #define CONTENT_APPLE 0x819
-
+#define CONTENT_SAPLING 0x820
 
 #endif
 
diff --git a/src/environment.cpp b/src/environment.cpp
index 8103b7110..93f1627c5 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock.h"
 #include "serverobject.h"
 #include "content_sao.h"
+#include "mapgen.h"
 
 Environment::Environment():
 	m_time_of_day(9000)
@@ -922,7 +923,34 @@ void ServerEnvironment::step(float dtime)
 							addActiveObject(obj);
 						}
 					}
-			 }
+				}
+				/*
+				        Make trees from saplings!
+				*/
+				if(n.getContent() == CONTENT_SAPLING)
+				{
+				        if(myrand()%2 == 0)
+					{
+					        core::map<v3s16, MapBlock*> modified_blocks;
+					        v3s16 tree_p = p;
+						MapEditEvent event;
+						event.type = MEET_OTHER;
+						ManualMapVoxelManipulator vmanip(m_map);
+						v3s16 tree_blockp = getNodeBlockPos(tree_p);
+						vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
+						bool is_apple_tree = myrand()%4 == 0;
+						mapgen::make_tree(vmanip, tree_p, is_apple_tree);
+						for(core::map<v3s16, MapBlock*>::Iterator
+						      i = modified_blocks.getIterator();
+						      i.atEnd() == false; i++)
+					        {
+						        v3s16 p = i.getNode()->getKey();
+							event.modified_blocks.insert(p, true);
+						}
+						m_map->dispatchEvent(&event);
+					}
+				}
+						
 			}
 		}
 	}
diff --git a/src/map.cpp b/src/map.cpp
index 7de79c75d..d870b5e71 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "porting.h"
 #include "mapgen.h"
 #include "nodemetadata.h"
+#include "content_mapnode.h"
 
 /*
 	SQLite format specification:
diff --git a/src/mapgen.h b/src/mapgen.h
index 57d0ee8a0..f848389a8 100644
--- a/src/mapgen.h
+++ b/src/mapgen.h
@@ -40,6 +40,9 @@ namespace mapgen
 	
 	// Add objects according to block content
 	void add_random_objects(MapBlock *block);
+
+	// Add a tree
+	void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, bool is_apple_tree);
 	
 	/*
 		These are used by FarMesh
diff --git a/src/mapnode.h b/src/mapnode.h
index 3ad67aaf6..88e7a0d0a 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -145,6 +145,10 @@ struct ContentFeatures
 	// Inventory item string as which the node appears in inventory when dug.
 	// Mineral overrides this.
 	std::string dug_item;
+
+        // Extra dug item and its rarity
+        std::string extra_dug_item;
+        s32 extra_dug_item_rarity;
 	
 	// Initial metadata is cloned from this
 	NodeMetadata *initial_metadata;
diff --git a/src/server.cpp b/src/server.cpp
index a04417074..04a23b777 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2735,6 +2735,34 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 					UpdateCrafting(player->peer_id);
 					SendInventory(player->peer_id);
 				}
+
+				item = NULL;
+
+				if(mineral != MINERAL_NONE)
+				  item = getDiggedMineralItem(mineral);
+			
+				// If not mineral
+				if(item == NULL)
+				{
+				        std::string &extra_dug_s = content_features(material).extra_dug_item;
+					s32 extra_rarity = content_features(material).extra_dug_item_rarity;
+					if(extra_dug_s != "" && extra_rarity != 0
+					   && myrand() % extra_rarity == 0)
+					{
+				                std::istringstream is(extra_dug_s, std::ios::binary);
+						item = InventoryItem::deSerialize(is);
+					}
+				}
+			
+				if(item != NULL)
+				{
+				        // Add a item to inventory
+				        player->inventory.addItem("main", item);
+
+					// Send inventory
+					UpdateCrafting(player->peer_id);
+					SendInventory(player->peer_id);
+				}
 			}
 
 			/*
-- 
GitLab