From 01ce57ade534f83d80bbb1f0c48630891b338237 Mon Sep 17 00:00:00 2001
From: kwolekr <kwolekr@minetest.net>
Date: Fri, 3 Oct 2014 03:16:43 -0400
Subject: [PATCH] Clean up nodedef.cpp

---
 src/nodedef.cpp | 1102 ++++++++++++++++++++++++-----------------------
 1 file changed, 562 insertions(+), 540 deletions(-)

diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 8a5cff3bf..92e4b59b3 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -370,592 +370,612 @@ void ContentFeatures::deSerialize(std::istream &is)
 	CNodeDefManager
 */
 
-class CNodeDefManager: public IWritableNodeDefManager
-{
+class CNodeDefManager: public IWritableNodeDefManager {
 public:
-	void clear()
-	{
-		m_content_features.clear();
-		m_name_id_mapping.clear();
-		m_name_id_mapping_with_aliases.clear();
-		m_group_to_items.clear();
-		m_next_id = 0;
-
-		u32 initial_length = 0;
-		initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
-		initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
-		initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1);
-		m_content_features.resize(initial_length);
-
-		// Set CONTENT_UNKNOWN
-		{
-			ContentFeatures f;
-			f.name = "unknown";
-			// Insert directly into containers
-			content_t c = CONTENT_UNKNOWN;
-			m_content_features[c] = f;
-			addNameIdMapping(c, f.name);
-		}
+	CNodeDefManager();
+	virtual ~CNodeDefManager();
+	void clear();
+	virtual IWritableNodeDefManager *clone();
+	virtual const ContentFeatures& get(content_t c) const;
+	virtual const ContentFeatures& get(const MapNode &n) const;
+	virtual bool getId(const std::string &name, content_t &result) const;
+	virtual content_t getId(const std::string &name) const;
+	virtual void getIds(const std::string &name, std::set<content_t> &result) const;
+	virtual const ContentFeatures& get(const std::string &name) const;
+	content_t allocateId();
+	virtual content_t set(const std::string &name, const ContentFeatures &def);
+	virtual content_t allocateDummy(const std::string &name);
+	virtual void updateAliases(IItemDefManager *idef);
+	virtual void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc);
+	void serialize(std::ostream &os, u16 protocol_version);
+	void deSerialize(std::istream &is);
 
-		// Set CONTENT_AIR
-		{
-			ContentFeatures f;
-			f.name                = "air";
-			f.drawtype            = NDT_AIRLIKE;
-			f.param_type          = CPT_LIGHT;
-			f.light_propagates    = true;
-			f.sunlight_propagates = true;
-			f.walkable            = false;
-			f.pointable           = false;
-			f.diggable            = false;
-			f.buildable_to        = true;
-			f.is_ground_content   = true;
-			// Insert directly into containers
-			content_t c = CONTENT_AIR;
-			m_content_features[c] = f;
-			addNameIdMapping(c, f.name);
-		}
+private:
+	void addNameIdMapping(content_t i, std::string name);
+#ifndef SERVER
+	void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef,
+		u32 shader_id, bool use_normal_texture, u8 alpha, u8 material_type);
+#endif
 
-		// Set CONTENT_IGNORE
-		{
-			ContentFeatures f;
-			f.name                = "ignore";
-			f.drawtype            = NDT_AIRLIKE;
-			f.param_type          = CPT_NONE;
-			f.light_propagates    = false;
-			f.sunlight_propagates = false;
-			f.walkable            = false;
-			f.pointable           = false;
-			f.diggable            = false;
-			f.buildable_to        = true; // A way to remove accidental CONTENT_IGNOREs
-			f.is_ground_content   = true;
-			// Insert directly into containers
-			content_t c = CONTENT_IGNORE;
-			m_content_features[c] = f;
-			addNameIdMapping(c, f.name);
-		}
-	}
-	CNodeDefManager()
-	{
-		clear();
-	}
-	virtual ~CNodeDefManager()
-	{
-	}
-	virtual IWritableNodeDefManager* clone()
-	{
-		CNodeDefManager *mgr = new CNodeDefManager();
-		*mgr = *this;
-		return mgr;
-	}
-	virtual const ContentFeatures& get(content_t c) const
+	// Features indexed by id
+	std::vector<ContentFeatures> m_content_features;
+
+	// A mapping for fast converting back and forth between names and ids
+	NameIdMapping m_name_id_mapping;
+
+	// Like m_name_id_mapping, but only from names to ids, and includes
+	// item aliases too. Updated by updateAliases()
+	// Note: Not serialized.
+
+	std::map<std::string, content_t> m_name_id_mapping_with_aliases;
+
+	// A mapping from groups to a list of content_ts (and their levels)
+	// that belong to it.  Necessary for a direct lookup in getIds().
+	// Note: Not serialized.
+	std::map<std::string, GroupItems> m_group_to_items;
+
+	// Next possibly free id
+	content_t m_next_id;
+};
+
+
+CNodeDefManager::CNodeDefManager()
+{
+	clear();
+}
+
+
+CNodeDefManager::~CNodeDefManager()
+{
+}
+
+
+void CNodeDefManager::clear()
+{
+	m_content_features.clear();
+	m_name_id_mapping.clear();
+	m_name_id_mapping_with_aliases.clear();
+	m_group_to_items.clear();
+	m_next_id = 0;
+
+	u32 initial_length = 0;
+	initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
+	initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
+	initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1);
+	m_content_features.resize(initial_length);
+
+	// Set CONTENT_UNKNOWN
 	{
-		if(c < m_content_features.size())
-			return m_content_features[c];
-		else
-			return m_content_features[CONTENT_UNKNOWN];
+		ContentFeatures f;
+		f.name = "unknown";
+		// Insert directly into containers
+		content_t c = CONTENT_UNKNOWN;
+		m_content_features[c] = f;
+		addNameIdMapping(c, f.name);
 	}
-	virtual const ContentFeatures& get(const MapNode &n) const
+
+	// Set CONTENT_AIR
 	{
-		return get(n.getContent());
+		ContentFeatures f;
+		f.name                = "air";
+		f.drawtype            = NDT_AIRLIKE;
+		f.param_type          = CPT_LIGHT;
+		f.light_propagates    = true;
+		f.sunlight_propagates = true;
+		f.walkable            = false;
+		f.pointable           = false;
+		f.diggable            = false;
+		f.buildable_to        = true;
+		f.is_ground_content   = true;
+		// Insert directly into containers
+		content_t c = CONTENT_AIR;
+		m_content_features[c] = f;
+		addNameIdMapping(c, f.name);
 	}
-	virtual bool getId(const std::string &name, content_t &result) const
+
+	// Set CONTENT_IGNORE
 	{
-		std::map<std::string, content_t>::const_iterator
-			i = m_name_id_mapping_with_aliases.find(name);
-		if(i == m_name_id_mapping_with_aliases.end())
-			return false;
-		result = i->second;
-		return true;
+		ContentFeatures f;
+		f.name                = "ignore";
+		f.drawtype            = NDT_AIRLIKE;
+		f.param_type          = CPT_NONE;
+		f.light_propagates    = false;
+		f.sunlight_propagates = false;
+		f.walkable            = false;
+		f.pointable           = false;
+		f.diggable            = false;
+		f.buildable_to        = true; // A way to remove accidental CONTENT_IGNOREs
+		f.is_ground_content   = true;
+		// Insert directly into containers
+		content_t c = CONTENT_IGNORE;
+		m_content_features[c] = f;
+		addNameIdMapping(c, f.name);
 	}
-	virtual content_t getId(const std::string &name) const
-	{
+}
+
+
+IWritableNodeDefManager *CNodeDefManager::clone()
+{
+	CNodeDefManager *mgr = new CNodeDefManager();
+	*mgr = *this;
+	return mgr;
+}
+
+
+const ContentFeatures& CNodeDefManager::get(content_t c) const
+{
+	if (c < m_content_features.size())
+		return m_content_features[c];
+	else
+		return m_content_features[CONTENT_UNKNOWN];
+}
+
+
+const ContentFeatures& CNodeDefManager::get(const MapNode &n) const
+{
+	return get(n.getContent());
+}
+
+
+bool CNodeDefManager::getId(const std::string &name, content_t &result) const
+{
+	std::map<std::string, content_t>::const_iterator
+		i = m_name_id_mapping_with_aliases.find(name);
+	if(i == m_name_id_mapping_with_aliases.end())
+		return false;
+	result = i->second;
+	return true;
+}
+
+
+content_t CNodeDefManager::getId(const std::string &name) const
+{
+	content_t id = CONTENT_IGNORE;
+	getId(name, id);
+	return id;
+}
+
+
+void CNodeDefManager::getIds(const std::string &name, std::set<content_t> &result)
+		const
+{
+	//TimeTaker t("getIds", NULL, PRECISION_MICRO);
+	if (name.substr(0,6) != "group:") {
 		content_t id = CONTENT_IGNORE;
-		getId(name, id);
-		return id;
+		if(getId(name, id))
+			result.insert(id);
+		return;
 	}
-	virtual void getIds(const std::string &name, std::set<content_t> &result)
-			const
-	{
-		//TimeTaker t("getIds", NULL, PRECISION_MICRO);
-		if(name.substr(0,6) != "group:"){
-			content_t id = CONTENT_IGNORE;
-			if(getId(name, id))
-				result.insert(id);
-			return;
+	std::string group = name.substr(6);
+
+	std::map<std::string, GroupItems>::const_iterator
+		i = m_group_to_items.find(group);
+	if (i == m_group_to_items.end())
+		return;
+
+	const GroupItems &items = i->second;
+	for (GroupItems::const_iterator j = items.begin();
+		j != items.end(); ++j) {
+		if ((*j).second != 0)
+			result.insert((*j).first);
+	}
+	//printf("getIds: %dus\n", t.stop());
+}
+
+
+const ContentFeatures& CNodeDefManager::get(const std::string &name) const
+{
+	content_t id = CONTENT_UNKNOWN;
+	getId(name, id);
+	return get(id);
+}
+
+
+// returns CONTENT_IGNORE if no free ID found
+content_t CNodeDefManager::allocateId()
+{
+	for (content_t id = m_next_id;
+			id >= m_next_id; // overflow?
+			++id) {
+		while (id >= m_content_features.size()) {
+			m_content_features.push_back(ContentFeatures());
 		}
-		std::string group = name.substr(6);
-
-		std::map<std::string, GroupItems>::const_iterator
-			i = m_group_to_items.find(group);
-		if (i == m_group_to_items.end())
-			return;
-
-		const GroupItems &items = i->second;
-		for (GroupItems::const_iterator j = items.begin();
-			j != items.end(); ++j) {
-			if ((*j).second != 0)
-				result.insert((*j).first);
+		const ContentFeatures &f = m_content_features[id];
+		if (f.name == "") {
+			m_next_id = id + 1;
+			return id;
 		}
-		//printf("getIds: %dus\n", t.stop());
-	}
-	virtual const ContentFeatures& get(const std::string &name) const
-	{
-		content_t id = CONTENT_UNKNOWN;
-		getId(name, id);
-		return get(id);
 	}
-	// returns CONTENT_IGNORE if no free ID found
-	content_t allocateId()
-	{
-		for(content_t id = m_next_id;
-				id >= m_next_id; // overflow?
-				++id){
-			while(id >= m_content_features.size()){
-				m_content_features.push_back(ContentFeatures());
-			}
-			const ContentFeatures &f = m_content_features[id];
-			if(f.name == ""){
-				m_next_id = id + 1;
-				return id;
-			}
-		}
-		// If we arrive here, an overflow occurred in id.
-		// That means no ID was found
+	// If we arrive here, an overflow occurred in id.
+	// That means no ID was found
+	return CONTENT_IGNORE;
+}
+
+
+// IWritableNodeDefManager
+content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &def)
+{
+	assert(name != "");
+	assert(name == def.name);
+
+	// Don't allow redefining ignore (but allow air and unknown)
+	if (name == "ignore") {
+		infostream << "NodeDefManager: WARNING: Ignoring "
+			"CONTENT_IGNORE redefinition"<<std::endl;
 		return CONTENT_IGNORE;
 	}
-	// IWritableNodeDefManager
-	virtual content_t set(const std::string &name,
-			const ContentFeatures &def)
-	{
-		assert(name != "");
-		assert(name == def.name);
 
-		// Don't allow redefining ignore (but allow air and unknown)
-		if(name == "ignore"){
-			infostream<<"NodeDefManager: WARNING: Ignoring "
-					<<"CONTENT_IGNORE redefinition"<<std::endl;
+	content_t id = CONTENT_IGNORE;
+	if (!m_name_id_mapping.getId(name, id)) { // ignore aliases
+		// Get new id
+		id = allocateId();
+		if (id == CONTENT_IGNORE) {
+			infostream << "NodeDefManager: WARNING: Absolute "
+				"limit reached" << std::endl;
 			return CONTENT_IGNORE;
 		}
+		assert(id != CONTENT_IGNORE);
+		addNameIdMapping(id, name);
+	}
+	m_content_features[id] = def;
+	verbosestream << "NodeDefManager: registering content id \"" << id
+		<< "\": name=\"" << def.name << "\""<<std::endl;
 
-		content_t id = CONTENT_IGNORE;
-		bool found = m_name_id_mapping.getId(name, id);  // ignore aliases
-		if(!found){
-			// Get new id
-			id = allocateId();
-			if(id == CONTENT_IGNORE){
-				infostream<<"NodeDefManager: WARNING: Absolute "
-						<<"limit reached"<<std::endl;
-				return CONTENT_IGNORE;
-			}
-			assert(id != CONTENT_IGNORE);
-			addNameIdMapping(id, name);
-		}
-		m_content_features[id] = def;
-		verbosestream<<"NodeDefManager: registering content id \""<<id
-				<<"\": name=\""<<def.name<<"\""<<std::endl;
-
-		// Add this content to the list of all groups it belongs to
-		// FIXME: This should remove a node from groups it no longer
-		// belongs to when a node is re-registered
-		for (ItemGroupList::const_iterator i = def.groups.begin();
-			i != def.groups.end(); ++i) {
-			std::string group_name = i->first;
-
-			std::map<std::string, GroupItems>::iterator
-				j = m_group_to_items.find(group_name);
-			if (j == m_group_to_items.end()) {
-				m_group_to_items[group_name].push_back(
-						std::make_pair(id, i->second));
-			} else {
-				GroupItems &items = j->second;
-				items.push_back(std::make_pair(id, i->second));
-			}
+	// Add this content to the list of all groups it belongs to
+	// FIXME: This should remove a node from groups it no longer
+	// belongs to when a node is re-registered
+	for (ItemGroupList::const_iterator i = def.groups.begin();
+		i != def.groups.end(); ++i) {
+		std::string group_name = i->first;
+
+		std::map<std::string, GroupItems>::iterator
+			j = m_group_to_items.find(group_name);
+		if (j == m_group_to_items.end()) {
+			m_group_to_items[group_name].push_back(
+					std::make_pair(id, i->second));
+		} else {
+			GroupItems &items = j->second;
+			items.push_back(std::make_pair(id, i->second));
 		}
-		return id;
 	}
-	virtual content_t allocateDummy(const std::string &name)
-	{
-		assert(name != "");
-		ContentFeatures f;
-		f.name = name;
-		return set(name, f);
-	}
-	virtual void updateAliases(IItemDefManager *idef)
-	{
-		std::set<std::string> all = idef->getAll();
-		m_name_id_mapping_with_aliases.clear();
-		for(std::set<std::string>::iterator
-				i = all.begin(); i != all.end(); i++)
-		{
-			std::string name = *i;
-			std::string convert_to = idef->getAlias(name);
-			content_t id;
-			if(m_name_id_mapping.getId(convert_to, id))
-			{
-				m_name_id_mapping_with_aliases.insert(
-						std::make_pair(name, id));
-			}
+	return id;
+}
+
+
+content_t CNodeDefManager::allocateDummy(const std::string &name)
+{
+	assert(name != "");
+	ContentFeatures f;
+	f.name = name;
+	return set(name, f);
+}
+
+
+void CNodeDefManager::updateAliases(IItemDefManager *idef)
+{
+	std::set<std::string> all = idef->getAll();
+	m_name_id_mapping_with_aliases.clear();
+	for (std::set<std::string>::iterator
+			i = all.begin(); i != all.end(); i++) {
+		std::string name = *i;
+		std::string convert_to = idef->getAlias(name);
+		content_t id;
+		if (m_name_id_mapping.getId(convert_to, id)) {
+			m_name_id_mapping_with_aliases.insert(
+					std::make_pair(name, id));
 		}
 	}
-	virtual void updateTextures(ITextureSource *tsrc,
-		IShaderSource *shdsrc)
-	{
+}
+
+
+void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc)
+{
 #ifndef SERVER
-		infostream<<"CNodeDefManager::updateTextures(): Updating "
-				<<"textures in node definitions"<<std::endl;
-
-		bool new_style_water = g_settings->getBool("new_style_water");
-		bool new_style_leaves = g_settings->getBool("new_style_leaves");
-		bool connected_glass = g_settings->getBool("connected_glass");
-		bool opaque_water = g_settings->getBool("opaque_water");
-		bool enable_shaders = g_settings->getBool("enable_shaders");
-		bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping");
-		bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion");
-
-		for(u32 i=0; i<m_content_features.size(); i++)
-		{
-			ContentFeatures *f = &m_content_features[i];
-
-			// Figure out the actual tiles to use
-			TileDef tiledef[6];
-			for(u32 j = 0; j < 6; j++)
-			{
-				tiledef[j] = f->tiledef[j];
-				if(tiledef[j].name == "")
-					tiledef[j].name = "unknown_node.png";
-			}
+	infostream << "CNodeDefManager::updateTextures(): Updating "
+		"textures in node definitions" << std::endl;
 
-			bool is_liquid = false;
-			bool is_water_surface = false;
+	bool new_style_water           = g_settings->getBool("new_style_water");
+	bool new_style_leaves          = g_settings->getBool("new_style_leaves");
+	bool connected_glass           = g_settings->getBool("connected_glass");
+	bool opaque_water              = g_settings->getBool("opaque_water");
+	bool enable_shaders            = g_settings->getBool("enable_shaders");
+	bool enable_bumpmapping        = g_settings->getBool("enable_bumpmapping");
+	bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion");
 
-			u8 material_type;
-			material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
+	bool use_normal_texture = enable_shaders &&
+		(enable_bumpmapping || enable_parallax_occlusion);
 
-			switch(f->drawtype){
-			default:
-			case NDT_NORMAL:
-				f->solidness = 2;
-				break;
-			case NDT_AIRLIKE:
-				f->solidness = 0;
-				break;
-			case NDT_LIQUID:
-				assert(f->liquid_type == LIQUID_SOURCE);
-				if(opaque_water)
-					f->alpha = 255;
-				if(new_style_water){
-					f->solidness = 0;
-				} else {
-					f->solidness = 1;
-					f->backface_culling = false;
-				}
-				is_liquid = true;
-				break;
-			case NDT_FLOWINGLIQUID:
-				assert(f->liquid_type == LIQUID_FLOWING);
-				f->solidness = 0;
-				if(opaque_water)
-					f->alpha = 255;
-				is_liquid = true;
-				break;
-			case NDT_GLASSLIKE:
-				f->solidness = 0;
-				f->visual_solidness = 1;
-				break;
-			case NDT_GLASSLIKE_FRAMED:
-				f->solidness = 0;
-				f->visual_solidness = 1;
-				break;
-			case NDT_GLASSLIKE_FRAMED_OPTIONAL:
-				f->solidness = 0;
-				f->visual_solidness = 1;
-				if (connected_glass) {
-					f->drawtype = NDT_GLASSLIKE_FRAMED;
-				} else {
-					f->drawtype = NDT_GLASSLIKE;
-				}
-				break;
-			case NDT_ALLFACES:
-				f->solidness = 0;
-				f->visual_solidness = 1;
-				break;
-			case NDT_ALLFACES_OPTIONAL:
-				if(new_style_leaves){
-					f->drawtype = NDT_ALLFACES;
-					f->solidness = 0;
-					f->visual_solidness = 1;
-				} else {
-					f->drawtype = NDT_NORMAL;
-					f->solidness = 2;
-					for(u32 i=0; i<6; i++){
-						tiledef[i].name += std::string("^[noalpha");
-					}
-				}
-				if (f->waving == 1)
-					material_type = TILE_MATERIAL_WAVING_LEAVES;
-				break;
-			case NDT_PLANTLIKE:
+	for (u32 i = 0; i < m_content_features.size(); i++) {
+		ContentFeatures *f = &m_content_features[i];
+
+		// Figure out the actual tiles to use
+		TileDef tiledef[6];
+		for (u32 j = 0; j < 6; j++) {
+			tiledef[j] = f->tiledef[j];
+			if (tiledef[j].name == "")
+				tiledef[j].name = "unknown_node.png";
+		}
+
+		bool is_liquid = false;
+		bool is_water_surface = false;
+
+		u8 material_type = (f->alpha == 255) ?
+			TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
+
+		switch (f->drawtype) {
+		default:
+		case NDT_NORMAL:
+			f->solidness = 2;
+			break;
+		case NDT_AIRLIKE:
+			f->solidness = 0;
+			break;
+		case NDT_LIQUID:
+			assert(f->liquid_type == LIQUID_SOURCE);
+			if (opaque_water)
+				f->alpha = 255;
+			if (new_style_water){
 				f->solidness = 0;
+			} else {
+				f->solidness = 1;
 				f->backface_culling = false;
-				if (f->waving == 1)
-					material_type = TILE_MATERIAL_WAVING_PLANTS;
-				break;
-			case NDT_FIRELIKE:
-				f->backface_culling = false;
-			case NDT_TORCHLIKE:
-			case NDT_SIGNLIKE:
-			case NDT_FENCELIKE:
-			case NDT_RAILLIKE:
-			case NDT_NODEBOX:
+			}
+			is_liquid = true;
+			break;
+		case NDT_FLOWINGLIQUID:
+			assert(f->liquid_type == LIQUID_FLOWING);
+			f->solidness = 0;
+			if (opaque_water)
+				f->alpha = 255;
+			is_liquid = true;
+			break;
+		case NDT_GLASSLIKE:
+			f->solidness = 0;
+			f->visual_solidness = 1;
+			break;
+		case NDT_GLASSLIKE_FRAMED:
+			f->solidness = 0;
+			f->visual_solidness = 1;
+			break;
+		case NDT_GLASSLIKE_FRAMED_OPTIONAL:
+			f->solidness = 0;
+			f->visual_solidness = 1;
+			f->drawtype = connected_glass ? NDT_GLASSLIKE_FRAMED : NDT_GLASSLIKE;
+			break;
+		case NDT_ALLFACES:
+			f->solidness = 0;
+			f->visual_solidness = 1;
+			break;
+		case NDT_ALLFACES_OPTIONAL:
+			if (new_style_leaves) {
+				f->drawtype = NDT_ALLFACES;
 				f->solidness = 0;
-				break;
+				f->visual_solidness = 1;
+			} else {
+				f->drawtype = NDT_NORMAL;
+				f->solidness = 2;
+				for (u32 i = 0; i < 6; i++)
+					tiledef[i].name += std::string("^[noalpha");
 			}
+			if (f->waving == 1)
+				material_type = TILE_MATERIAL_WAVING_LEAVES;
+			break;
+		case NDT_PLANTLIKE:
+			f->solidness = 0;
+			f->backface_culling = false;
+			if (f->waving == 1)
+				material_type = TILE_MATERIAL_WAVING_PLANTS;
+			break;
+		case NDT_FIRELIKE:
+			f->backface_culling = false;
+		case NDT_TORCHLIKE:
+		case NDT_SIGNLIKE:
+		case NDT_FENCELIKE:
+		case NDT_RAILLIKE:
+		case NDT_NODEBOX:
+			f->solidness = 0;
+			break;
+		}
 
-			if (is_liquid){
-				material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
-				if (f->name == "default:water_source")
-					is_water_surface = true;
-			}
-			u32 tile_shader[6];
-			for(u16 j=0; j<6; j++)
-				tile_shader[j] = shdsrc->getShader("nodes_shader",material_type, f->drawtype);
-
-			if (is_water_surface)
-				tile_shader[0] = shdsrc->getShader("water_surface_shader",material_type, f->drawtype);
-
-			// Tiles (fill in f->tiles[])
-			for(u16 j = 0; j < 6; j++){
-				// Shader
-				f->tiles[j].shader_id = tile_shader[j];
-				// Texture
-				f->tiles[j].texture = tsrc->getTexture(
-						tiledef[j].name,
-						&f->tiles[j].texture_id);
-				// Normal texture
-				if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
-					f->tiles[j].normal_texture = tsrc->getNormalTexture(tiledef[j].name);
-				// Alpha
-				f->tiles[j].alpha = f->alpha;
-				// Material type
-				f->tiles[j].material_type = material_type;
-				// Material flags
-				f->tiles[j].material_flags = 0;
-				if(f->backface_culling)
-					f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
-				if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES)
-					f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
-				// Animation parameters
-				int frame_count = 1;
-				if(f->tiles[j].material_flags &	MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
-					// Get texture size to determine frame count by
-					// aspect ratio
-					v2u32 size = f->tiles[j].texture->getOriginalSize();
-					int frame_height = (float)size.X /
-							(float)tiledef[j].animation.aspect_w *
-							(float)tiledef[j].animation.aspect_h;
-					frame_count = size.Y / frame_height;
-					int frame_length_ms = 1000.0 *
-							tiledef[j].animation.length / frame_count;
-					f->tiles[j].animation_frame_count = frame_count;
-					f->tiles[j].animation_frame_length_ms = frame_length_ms;
-				}
-				if(frame_count == 1) {
-					f->tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
-				} else {
-					std::ostringstream os(std::ios::binary);
-					for (int i = 0; i < frame_count; i++) {
-						FrameSpec frame;
-						os.str("");
-						os<<tiledef[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
-						frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
-						if (f->tiles[j].normal_texture)
-							frame.normal_texture = tsrc->getNormalTexture(os.str());
-						f->tiles[j].frames[i]=frame;
-					}
-				}
-			}
-			// Special tiles (fill in f->special_tiles[])
-			for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
-				// Shader
-				f->special_tiles[j].shader_id = tile_shader[j];
-				// Texture
-				f->special_tiles[j].texture = tsrc->getTexture(
-						f->tiledef_special[j].name,
-						&f->special_tiles[j].texture_id);
-				// Normal texture
-				if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
-					f->special_tiles[j].normal_texture = tsrc->getNormalTexture(f->tiledef_special[j].name);
-				// Alpha
-				f->special_tiles[j].alpha = f->alpha;
-				// Material type
-				f->special_tiles[j].material_type = material_type;
-				// Material flags
-				f->special_tiles[j].material_flags = 0;
-				if(f->tiledef_special[j].backface_culling)
-					f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
-				if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES)
-					f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
-				// Animation parameters
-				int frame_count = 1;
-				if(f->special_tiles[j].material_flags &	MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
-					// Get texture size to determine frame count by
-					// aspect ratio
-					v2u32 size = f->special_tiles[j].texture->getOriginalSize();
-					int frame_height = (float)size.X /
-							(float)f->tiledef_special[j].animation.aspect_w *
-							(float)f->tiledef_special[j].animation.aspect_h;
-					frame_count = size.Y / frame_height;
-					int frame_length_ms = 1000.0 *
-							f->tiledef_special[j].animation.length / frame_count;
-					f->special_tiles[j].animation_frame_count = frame_count;
-					f->special_tiles[j].animation_frame_length_ms = frame_length_ms;
-				}
-				if(frame_count == 1) {
-					f->special_tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
-				} else {
-					std::ostringstream os(std::ios::binary);
-					for (int i = 0; i < frame_count; i++) {
-						FrameSpec frame;
-						os.str("");
-						os<<f->tiledef_special[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
-						frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
-						if (f->special_tiles[j].normal_texture)
-							frame.normal_texture = tsrc->getNormalTexture(os.str());
-						f->special_tiles[j].frames[i]=frame;
-					}
-				}
-			}
+		if (is_liquid) {
+			material_type = (f->alpha == 255) ?
+				TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
+			if (f->name == "default:water_source")
+				is_water_surface = true;
+		}
+
+		u32 tile_shader[6];
+		for (u16 j = 0; j < 6; j++) {
+			tile_shader[j] = shdsrc->getShader("nodes_shader",
+				material_type, f->drawtype);
+		}
+
+		if (is_water_surface) {
+			tile_shader[0] = shdsrc->getShader("water_surface_shader",
+				material_type, f->drawtype);
+		}
+
+		// Tiles (fill in f->tiles[])
+		for (u16 j = 0; j < 6; j++) {
+			fillTileAttribs(tsrc, &f->tiles[j], &tiledef[j], tile_shader[j],
+				use_normal_texture, f->alpha, material_type);
+		}
+
+		// Special tiles (fill in f->special_tiles[])
+		for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
+			fillTileAttribs(tsrc, &f->special_tiles[j], &f->tiledef_special[j],
+				tile_shader[j], use_normal_texture, f->alpha, material_type);
 		}
+	}
 #endif
+}
+
+
+#ifndef SERVER
+void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
+		TileDef *tiledef, u32 shader_id, bool use_normal_texture,
+		u8 alpha, u8 material_type)
+{
+	tile->shader_id     = shader_id;
+	tile->texture       = tsrc->getTexture(tiledef->name, &tile->texture_id);
+	tile->alpha         = alpha;
+	tile->material_type = material_type;
+
+	// Normal texture
+	if (use_normal_texture)
+		tile->normal_texture = tsrc->getNormalTexture(tiledef->name);
+
+	// Material flags
+	tile->material_flags = 0;
+	if (tiledef->backface_culling)
+		tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
+	if (tiledef->animation.type == TAT_VERTICAL_FRAMES)
+		tile->material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
+
+	// Animation parameters
+	int frame_count = 1;
+	if (tile->material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
+		// Get texture size to determine frame count by aspect ratio
+		v2u32 size = tile->texture->getOriginalSize();
+		int frame_height = (float)size.X /
+				(float)tiledef->animation.aspect_w *
+				(float)tiledef->animation.aspect_h;
+		frame_count = size.Y / frame_height;
+		int frame_length_ms = 1000.0 * tiledef->animation.length / frame_count;
+		tile->animation_frame_count = frame_count;
+		tile->animation_frame_length_ms = frame_length_ms;
 	}
-	void serialize(std::ostream &os, u16 protocol_version)
-	{
-		writeU8(os, 1); // version
-		u16 count = 0;
-		std::ostringstream os2(std::ios::binary);
-		for(u32 i = 0; i < m_content_features.size(); i++)
-		{
-			if(i == CONTENT_IGNORE || i == CONTENT_AIR
-					|| i == CONTENT_UNKNOWN)
-				continue;
-			ContentFeatures *f = &m_content_features[i];
-			if(f->name == "")
-				continue;
-			writeU16(os2, i);
-			// Wrap it in a string to allow different lengths without
-			// strict version incompatibilities
-			std::ostringstream wrapper_os(std::ios::binary);
-			f->serialize(wrapper_os, protocol_version);
-			os2<<serializeString(wrapper_os.str());
-
-			assert(count + 1 > count); // must not overflow
-			count++;
+
+	if (frame_count == 1) {
+		tile->material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
+	} else {
+		std::ostringstream os(std::ios::binary);
+		for (int i = 0; i < frame_count; i++) {
+			FrameSpec frame;
+
+			os.str("");
+			os << tiledef->name << "^[verticalframe:"
+				<< frame_count << ":" << i;
+
+			frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
+			if (tile->normal_texture)
+				frame.normal_texture = tsrc->getNormalTexture(os.str());
+			tile->frames[i] = frame;
 		}
-		writeU16(os, count);
-		os<<serializeLongString(os2.str());
 	}
-	void deSerialize(std::istream &is)
-	{
-		clear();
-		int version = readU8(is);
-		if(version != 1)
-			throw SerializationError("unsupported NodeDefinitionManager version");
-		u16 count = readU16(is);
-		std::istringstream is2(deSerializeLongString(is), std::ios::binary);
-		ContentFeatures f;
-		for(u16 n = 0; n < count; n++){
-			u16 i = readU16(is2);
-
-			// Read it from the string wrapper
-			std::string wrapper = deSerializeString(is2);
-			std::istringstream wrapper_is(wrapper, std::ios::binary);
-			f.deSerialize(wrapper_is);
-
-			// Check error conditions
-			if(i == CONTENT_IGNORE || i == CONTENT_AIR
-					|| i == CONTENT_UNKNOWN){
-				infostream<<"NodeDefManager::deSerialize(): WARNING: "
-					<<"not changing builtin node "<<i
-					<<std::endl;
-				continue;
-			}
-			if(f.name == ""){
-				infostream<<"NodeDefManager::deSerialize(): WARNING: "
-					<<"received empty name"<<std::endl;
-				continue;
-			}
-			u16 existing_id;
-			bool found = m_name_id_mapping.getId(f.name, existing_id);  // ignore aliases
-			if(found && i != existing_id){
-				infostream<<"NodeDefManager::deSerialize(): WARNING: "
-					<<"already defined with different ID: "
-					<<f.name<<std::endl;
-				continue;
-			}
+}
+#endif
 
-			// All is ok, add node definition with the requested ID
-			if(i >= m_content_features.size())
-				m_content_features.resize((u32)(i) + 1);
-			m_content_features[i] = f;
-			addNameIdMapping(i, f.name);
-			verbosestream<<"deserialized "<<f.name<<std::endl;
-		}
+
+void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version)
+{
+	writeU8(os, 1); // version
+	u16 count = 0;
+	std::ostringstream os2(std::ios::binary);
+	for (u32 i = 0; i < m_content_features.size(); i++) {
+		if (i == CONTENT_IGNORE || i == CONTENT_AIR
+				|| i == CONTENT_UNKNOWN)
+			continue;
+		ContentFeatures *f = &m_content_features[i];
+		if (f->name == "")
+			continue;
+		writeU16(os2, i);
+		// Wrap it in a string to allow different lengths without
+		// strict version incompatibilities
+		std::ostringstream wrapper_os(std::ios::binary);
+		f->serialize(wrapper_os, protocol_version);
+		os2<<serializeString(wrapper_os.str());
+
+		assert(count + 1 > count); // must not overflow
+		count++;
 	}
-private:
-	void addNameIdMapping(content_t i, std::string name)
-	{
-		m_name_id_mapping.set(i, name);
-		m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
+	writeU16(os, count);
+	os << serializeLongString(os2.str());
+}
+
+
+void CNodeDefManager::deSerialize(std::istream &is)
+{
+	clear();
+	int version = readU8(is);
+	if (version != 1)
+		throw SerializationError("unsupported NodeDefinitionManager version");
+	u16 count = readU16(is);
+	std::istringstream is2(deSerializeLongString(is), std::ios::binary);
+	ContentFeatures f;
+	for (u16 n = 0; n < count; n++) {
+		u16 i = readU16(is2);
+
+		// Read it from the string wrapper
+		std::string wrapper = deSerializeString(is2);
+		std::istringstream wrapper_is(wrapper, std::ios::binary);
+		f.deSerialize(wrapper_is);
+
+		// Check error conditions
+		if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) {
+			infostream << "NodeDefManager::deSerialize(): WARNING: "
+				"not changing builtin node " << i << std::endl;
+			continue;
+		}
+		if (f.name == "") {
+			infostream << "NodeDefManager::deSerialize(): WARNING: "
+				"received empty name" << std::endl;
+			continue;
+		}
+
+		// Ignore aliases
+		u16 existing_id;
+		if (m_name_id_mapping.getId(f.name, existing_id) && i != existing_id) {
+			infostream << "NodeDefManager::deSerialize(): WARNING: "
+				"already defined with different ID: " << f.name << std::endl;
+			continue;
+		}
+
+		// All is ok, add node definition with the requested ID
+		if (i >= m_content_features.size())
+			m_content_features.resize((u32)(i) + 1);
+		m_content_features[i] = f;
+		addNameIdMapping(i, f.name);
+		verbosestream << "deserialized " << f.name << std::endl;
 	}
-private:
-	// Features indexed by id
-	std::vector<ContentFeatures> m_content_features;
-	// A mapping for fast converting back and forth between names and ids
-	NameIdMapping m_name_id_mapping;
-	// Like m_name_id_mapping, but only from names to ids, and includes
-	// item aliases too. Updated by updateAliases()
-	// Note: Not serialized.
-	std::map<std::string, content_t> m_name_id_mapping_with_aliases;
-	// A mapping from groups to a list of content_ts (and their levels)
-	// that belong to it.  Necessary for a direct lookup in getIds().
-	// Note: Not serialized.
-	std::map<std::string, GroupItems> m_group_to_items;
-	// Next possibly free id
-	content_t m_next_id;
-};
+}
+
 
-IWritableNodeDefManager* createNodeDefManager()
+void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
+{
+	m_name_id_mapping.set(i, name);
+	m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
+}
+
+
+IWritableNodeDefManager *createNodeDefManager()
 {
 	return new CNodeDefManager();
 }
 
-/*
-	Serialization of old ContentFeatures formats
-*/
 
+//// Serialization of old ContentFeatures formats
 void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
 {
-	if(protocol_version == 13)
+	if (protocol_version == 13)
 	{
 		writeU8(os, 5); // version
 		os<<serializeString(name);
 		writeU16(os, groups.size());
-		for(ItemGroupList::const_iterator
-				i = groups.begin(); i != groups.end(); i++){
+		for (ItemGroupList::const_iterator
+				i = groups.begin(); i != groups.end(); i++) {
 			os<<serializeString(i->first);
 			writeS16(os, i->second);
 		}
 		writeU8(os, drawtype);
 		writeF1000(os, visual_scale);
 		writeU8(os, 6);
-		for(u32 i = 0; i < 6; i++)
+		for (u32 i = 0; i < 6; i++)
 			tiledef[i].serialize(os, protocol_version);
 		//CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
 		writeU8(os, 2);
-		for(u32 i = 0; i < 2; i++){
+		for (u32 i = 0; i < 2; i++)
 			tiledef_special[i].serialize(os, protocol_version);
-		}
 		writeU8(os, alpha);
 		writeU8(os, post_effect_color.getAlpha());
 		writeU8(os, post_effect_color.getRed());
@@ -990,21 +1010,20 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
 		writeU8(os, 6); // version
 		os<<serializeString(name);
 		writeU16(os, groups.size());
-		for(ItemGroupList::const_iterator
-			i = groups.begin(); i != groups.end(); i++){
+		for (ItemGroupList::const_iterator
+			i = groups.begin(); i != groups.end(); i++) {
 				os<<serializeString(i->first);
 				writeS16(os, i->second);
 		}
 		writeU8(os, drawtype);
 		writeF1000(os, visual_scale);
 		writeU8(os, 6);
-		for(u32 i = 0; i < 6; i++)
+		for (u32 i = 0; i < 6; i++)
 			tiledef[i].serialize(os, protocol_version);
 		//CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
 		writeU8(os, 2);
-		for(u32 i = 0; i < 2; i++){
+		for (u32 i = 0; i < 2; i++)
 			tiledef_special[i].serialize(os, protocol_version);
-		}
 		writeU8(os, alpha);
 		writeU8(os, post_effect_color.getAlpha());
 		writeU8(os, post_effect_color.getRed());
@@ -1040,12 +1059,14 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
 		writeU8(os, leveled);
 		writeU8(os, liquid_range);
 	} else 
-		throw SerializationError("ContentFeatures::serialize(): Unsupported version requested");
+		throw SerializationError("ContentFeatures::serialize(): "
+			"Unsupported version requested");
 }
 
+
 void ContentFeatures::deSerializeOld(std::istream &is, int version)
 {
-	if(version == 5) // In PROTOCOL_VERSION 13
+	if (version == 5) // In PROTOCOL_VERSION 13
 	{
 		name = deSerializeString(is);
 		groups.clear();
@@ -1057,13 +1078,13 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
 		}
 		drawtype = (enum NodeDrawType)readU8(is);
 		visual_scale = readF1000(is);
-		if(readU8(is) != 6)
+		if (readU8(is) != 6)
 			throw SerializationError("unsupported tile count");
-		for(u32 i=0; i<6; i++)
+		for (u32 i = 0; i < 6; i++)
 			tiledef[i].deSerialize(is);
-		if(readU8(is) != CF_SPECIAL_COUNT)
+		if (readU8(is) != CF_SPECIAL_COUNT)
 			throw SerializationError("unsupported CF_SPECIAL_COUNT");
-		for(u32 i=0; i<CF_SPECIAL_COUNT; i++)
+		for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
 			tiledef_special[i].deSerialize(is);
 		alpha = readU8(is);
 		post_effect_color.setAlpha(readU8(is));
@@ -1098,21 +1119,21 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
 		name = deSerializeString(is);
 		groups.clear();
 		u32 groups_size = readU16(is);
-		for(u32 i=0; i<groups_size; i++){
+		for (u32 i = 0; i < groups_size; i++) {
 			std::string name = deSerializeString(is);
 			int	value = readS16(is);
 			groups[name] = value;
 		}
 		drawtype = (enum NodeDrawType)readU8(is);
 		visual_scale = readF1000(is);
-		if(readU8(is) != 6)
+		if (readU8(is) != 6)
 			throw SerializationError("unsupported tile count");
-		for(u32 i=0; i<6; i++)
+		for (u32 i = 0; i < 6; i++)
 			tiledef[i].deSerialize(is);
 		// CF_SPECIAL_COUNT in version 6 = 2
-		if(readU8(is) != 2)
+		if (readU8(is) != 2)
 			throw SerializationError("unsupported CF_SPECIAL_COUNT");
-		for(u32 i=0; i<2; i++)
+		for (u32 i = 0; i < 2; i++)
 			tiledef_special[i].deSerialize(is);
 		alpha = readU8(is);
 		post_effect_color.setAlpha(readU8(is));
@@ -1148,6 +1169,7 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
 		drowning = readU8(is);
 		leveled = readU8(is);
 		liquid_range = readU8(is);
-	} else
+	} else {
 		throw SerializationError("unsupported ContentFeatures version");
+	}
 }
-- 
GitLab