From 9733dd5b5e5516e18775665db132b2446492716c Mon Sep 17 00:00:00 2001
From: proller <proller@github.com>
Date: Sat, 13 Jul 2013 21:48:14 +0400
Subject: [PATCH] Leveled nodebox

---
 src/mapnode.cpp                 | 25 ++++++++++++++++++++++++-
 src/mapnode.h                   |  7 +++++++
 src/nodedef.cpp                 |  7 +++++--
 src/nodedef.h                   |  7 ++++++-
 src/script/common/c_content.cpp |  2 ++
 src/script/cpp_api/s_node.cpp   |  2 ++
 6 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/src/mapnode.cpp b/src/mapnode.cpp
index f93231187..33644cf5c 100644
--- a/src/mapnode.cpp
+++ b/src/mapnode.cpp
@@ -163,7 +163,7 @@ static std::vector<aabb3f> transformNodeBox(const MapNode &n,
 		const NodeBox &nodebox, INodeDefManager *nodemgr)
 {
 	std::vector<aabb3f> boxes;
-	if(nodebox.type == NODEBOX_FIXED)
+	if(nodebox.type == NODEBOX_FIXED || nodebox.type == NODEBOX_LEVELED)
 	{
 		const std::vector<aabb3f> &fixed = nodebox.fixed;
 		int facedir = n.getFaceDir(nodemgr);
@@ -174,6 +174,11 @@ static std::vector<aabb3f> transformNodeBox(const MapNode &n,
 				i != fixed.end(); i++)
 		{
 			aabb3f box = *i;
+
+			if (nodebox.type == NODEBOX_LEVELED) {
+				box.MaxEdge.Y = -BS/2 + BS*((float)1/LEVELED_MAX) * n.getLevel(nodemgr);
+			}
+
 			switch (axisdir)
 			{
 			case 0:
@@ -354,6 +359,24 @@ std::vector<aabb3f> MapNode::getSelectionBoxes(INodeDefManager *nodemgr) const
 	return transformNodeBox(*this, f.selection_box, nodemgr);
 }
 
+u8 MapNode::getLevel(INodeDefManager *nodemgr) const
+{
+	const ContentFeatures &f = nodemgr->get(*this);
+	if(f.liquid_type == LIQUID_SOURCE)
+		return LIQUID_LEVEL_SOURCE;
+	if (f.param_type_2 == CPT2_FLOWINGLIQUID)
+		return getParam2() & LIQUID_LEVEL_MASK;
+	if(f.liquid_type == LIQUID_FLOWING) // can remove if all param_type_2 setted
+		return getParam2() & LIQUID_LEVEL_MASK;
+	if(f.leveled || f.param_type_2 == CPT2_LEVELED) {
+		 u8 level = getParam2() & LEVELED_MASK;
+		 if(level) return level;
+		 if(f.leveled > LEVELED_MAX) return LEVELED_MAX;
+		 return f.leveled; //default
+	}
+	return 0;
+}
+
 u32 MapNode::serializedLength(u8 version)
 {
 	if(!ser_ver_supported(version))
diff --git a/src/mapnode.h b/src/mapnode.h
index 60211b87c..53e36b670 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -87,6 +87,10 @@ enum Rotation {
 
 #define LIQUID_INFINITY_MASK 0x80 //0b10000000
 
+// mask for param2, now as for liquid
+#define LEVELED_MASK 0x07
+#define LEVELED_MAX LEVELED_MASK
+
 /*
 	This is the stuff what the whole world consists of.
 */
@@ -206,6 +210,9 @@ struct MapNode
 	*/
 	std::vector<aabb3f> getSelectionBoxes(INodeDefManager *nodemgr) const;
 
+	/* Liquid helpers */
+	u8 getLevel(INodeDefManager *nodemgr) const;
+
 	/*
 		Serialization functions
 	*/
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 13e7e9958..4b2fe1643 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -50,7 +50,7 @@ void NodeBox::serialize(std::ostream &os) const
 	writeU8(os, 1); // version
 	writeU8(os, type);
 
-	if(type == NODEBOX_FIXED)
+	if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
 	{
 		writeU16(os, fixed.size());
 		for(std::vector<aabb3f>::const_iterator
@@ -82,7 +82,7 @@ void NodeBox::deSerialize(std::istream &is)
 
 	type = (enum NodeBoxType)readU8(is);
 
-	if(type == NODEBOX_FIXED)
+	if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
 	{
 		u16 fixed_count = readU16(is);
 		while(fixed_count--)
@@ -206,6 +206,7 @@ void ContentFeatures::reset()
 	climbable = false;
 	buildable_to = false;
 	rightclickable = true;
+	leveled = 0;
 	liquid_type = LIQUID_NONE;
 	liquid_alternative_flowing = "";
 	liquid_alternative_source = "";
@@ -281,6 +282,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
 	// Stuff below should be moved to correct place in a version that otherwise changes
 	// the protocol version
 	writeU8(os, drowning);
+	writeU8(os, leveled);
 }
 
 void ContentFeatures::deSerialize(std::istream &is)
@@ -346,6 +348,7 @@ void ContentFeatures::deSerialize(std::istream &is)
 		// Stuff below should be moved to correct place in a version that
 		// otherwise changes the protocol version
 		drowning = readU8(is);
+		leveled = readU8(is);
 	}catch(SerializationError &e) {};
 }
 
diff --git a/src/nodedef.h b/src/nodedef.h
index 665a5ddc2..7505cc12d 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -56,13 +56,15 @@ enum ContentParamType2
 	CPT2_FACEDIR,
 	// Direction for signs, torches and such
 	CPT2_WALLMOUNTED,
+	// Block level like FLOWINGLIQUID
+	CPT2_LEVELED,
 };
 
 enum LiquidType
 {
 	LIQUID_NONE,
 	LIQUID_FLOWING,
-	LIQUID_SOURCE
+	LIQUID_SOURCE,
 };
 
 enum NodeBoxType
@@ -70,6 +72,7 @@ enum NodeBoxType
 	NODEBOX_REGULAR, // Regular block; allows buildable_to
 	NODEBOX_FIXED, // Static separately defined box(es)
 	NODEBOX_WALLMOUNTED, // Box for wall mounted nodes; (top, bottom, side)
+	NODEBOX_LEVELED, // Same as fixed, but with dynamic height from param2. for snow, ...
 };
 
 struct NodeBox
@@ -207,6 +210,8 @@ struct ContentFeatures
 	bool buildable_to;
 	// Player cannot build to these (placement prediction disabled)
 	bool rightclickable;
+	// Flowing liquid or snow, value = default level
+	u8 leveled;
 	// Whether the node is non-liquid, source liquid or flowing liquid
 	enum LiquidType liquid_type;
 	// If the content is liquid, this is the flowing version of the liquid.
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index 4ea296523..11f749160 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -389,6 +389,8 @@ ContentFeatures read_content_features(lua_State *L, int index)
 	// the slowest possible
 	f.liquid_viscosity = getintfield_default(L, index,
 			"liquid_viscosity", f.liquid_viscosity);
+	f.leveled = getintfield_default(L, index, "leveled", f.leveled);
+
 	getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
 	getboolfield(L, index, "drowning", f.drowning);
 	// Amount of light the node emits
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index 969e2f4d9..49a825cac 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -50,6 +50,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
 		{CPT2_FLOWINGLIQUID, "flowingliquid"},
 		{CPT2_FACEDIR, "facedir"},
 		{CPT2_WALLMOUNTED, "wallmounted"},
+		{CPT2_LEVELED, "leveled"},
 		{0, NULL},
 	};
 
@@ -73,6 +74,7 @@ struct EnumString ScriptApiNode::es_NodeBoxType[] =
 		{NODEBOX_REGULAR, "regular"},
 		{NODEBOX_FIXED, "fixed"},
 		{NODEBOX_WALLMOUNTED, "wallmounted"},
+		{NODEBOX_LEVELED, "leveled"},
 		{0, NULL},
 	};
 
-- 
GitLab