From 29d905f98a8ce7db9ae78a572b51d479f04fb48d Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Sun, 24 Jul 2011 12:09:33 +0300
Subject: [PATCH] Added a mapblock analyzing function for debugging use and
 fixed remaining mapgen bugs

---
 src/main.cpp     |   6 +++
 src/map.cpp      |  21 +++++++-
 src/mapblock.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++
 src/mapblock.h   |   5 ++
 src/server.cpp   |  43 ++++++++++-------
 5 files changed, 179 insertions(+), 19 deletions(-)

diff --git a/src/main.cpp b/src/main.cpp
index 3bc7ca5f6..09c299004 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -72,6 +72,12 @@ Other things to note:
   variable and fix them (result of getContent() must be stored in
   content_t, which is 16-bit)
 
+NOTE: Seeds in 1260:6c77e7dbfd29:
+5721858502589302589:
+	Spawns you on a small sand island with a surface dungeon
+2983455799928051958:
+	Enormous jungle + a surface dungeon at ~(250,0,0)
+
 Old, wild and random suggestions that probably won't be done:
 -------------------------------------------------------------
 
diff --git a/src/map.cpp b/src/map.cpp
index f0ea2f6f1..b205d9918 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -2264,7 +2264,26 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
 
 	/*dstream<<"finishBlockMake() done for ("<<blockpos.X<<","<<blockpos.Y<<","
 			<<blockpos.Z<<")"<<std::endl;*/
-	
+#if 0
+	if(enable_mapgen_debug_info)
+	{
+		/*
+			Analyze resulting blocks
+		*/
+		for(s16 x=-1; x<=1; x++)
+		for(s16 y=-1; y<=1; y++)
+		for(s16 z=-1; z<=1; z++)
+		{
+			v3s16 p = block->getPos()+v3s16(x,y,z);
+			MapBlock *block = getBlockNoCreateNoEx(p);
+			char spos[20];
+			snprintf(spos, 20, "(%2d,%2d,%2d)", x, y, z);
+			dstream<<"Generated "<<spos<<": "
+					<<analyze_block(block)<<std::endl;
+		}
+	}
+#endif
+
 	return block;
 }
 
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index 49d215bf6..b7981348c 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -867,5 +867,128 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
 	}
 }
 
+/*
+	Get a quick string to describe what a block actually contains
+*/
+std::string analyze_block(MapBlock *block)
+{
+	if(block == NULL)
+	{
+		return "NULL";
+	}
+
+	std::ostringstream desc;
+	
+	v3s16 p = block->getPos();
+	char spos[20];
+	snprintf(spos, 20, "(%2d,%2d,%2d), ", p.X, p.Y, p.Z);
+	desc<<spos;
+	
+	switch(block->getModified())
+	{
+	case MOD_STATE_CLEAN:
+		desc<<"CLEAN,           ";
+		break;
+	case MOD_STATE_WRITE_AT_UNLOAD:
+		desc<<"WRITE_AT_UNLOAD, ";
+		break;
+	case MOD_STATE_WRITE_NEEDED:
+		desc<<"WRITE_NEEDED,    ";
+		break;
+	default:
+		desc<<"unknown getModified()="+itos(block->getModified())+", ";
+	}
+
+	if(block->isGenerated())
+		desc<<"is_gen [X], ";
+	else
+		desc<<"is_gen [ ], ";
+
+	if(block->getIsUnderground())
+		desc<<"is_ug [X], ";
+	else
+		desc<<"is_ug [ ], ";
+
+	if(block->getMeshExpired())
+		desc<<"mesh_exp [X], ";
+	else
+		desc<<"mesh_exp [ ], ";
+
+	if(block->getLightingExpired())
+		desc<<"lighting_exp [X], ";
+	else
+		desc<<"lighting_exp [ ], ";
+
+	if(block->isDummy())
+	{
+		desc<<"Dummy, ";
+	}
+	else
+	{
+		// We'll just define the numbers here, don't want to include
+		// content_mapnode.h
+		const content_t content_water = 2;
+		const content_t content_watersource = 9;
+		const content_t content_tree = 0x801;
+		const content_t content_leaves = 0x802;
+		const content_t content_jungletree = 0x815;
+
+		bool full_ignore = true;
+		bool some_ignore = false;
+		bool full_air = true;
+		bool some_air = false;
+		bool trees = false;
+		bool water = false;
+		for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+		for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+		for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+		{
+			v3s16 p(x0,y0,z0);
+			MapNode n = block->getNode(p);
+			content_t c = n.getContent();
+			if(c == CONTENT_IGNORE)
+				some_ignore = true;
+			else
+				full_ignore = false;
+			if(c == CONTENT_AIR)
+				some_air = true;
+			else
+				full_air = false;
+			if(c == content_tree || c == content_jungletree
+					|| c == content_leaves)
+				trees = true;
+			if(c == content_water
+					|| c == content_watersource)
+				water = true;
+		}
+		
+		desc<<"content {";
+		
+		std::ostringstream ss;
+		
+		if(full_ignore)
+			ss<<"IGNORE (full), ";
+		else if(some_ignore)
+			ss<<"IGNORE, ";
+		
+		if(full_air)
+			ss<<"AIR (full), ";
+		else if(some_air)
+			ss<<"AIR, ";
+
+		if(trees)
+			ss<<"trees, ";
+		if(water)
+			ss<<"water, ";
+		
+		if(ss.str().size()>=2)
+			desc<<ss.str().substr(0, ss.str().size()-2);
+
+		desc<<"}, ";
+	}
+
+	return desc.str().substr(0, desc.str().size()-2);
+}
+
 
 //END
diff --git a/src/mapblock.h b/src/mapblock.h
index 8f3b8464a..741c306eb 100644
--- a/src/mapblock.h
+++ b/src/mapblock.h
@@ -743,5 +743,10 @@ inline s16 getNodeBlockY(s16 y)
 	return getContainerPos(y, MAP_BLOCKSIZE);
 }
 
+/*
+	Get a quick string to describe what a block actually contains
+*/
+std::string analyze_block(MapBlock *block);
+
 #endif
 
diff --git a/src/server.cpp b/src/server.cpp
index e3c6ce4d9..e2e6ce46b 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -105,10 +105,10 @@ void * EmergeThread::Thread()
 
 	DSTACK(__FUNCTION_NAME);
 
-	//bool debug=false;
-	
 	BEGIN_DEBUG_EXCEPTION_HANDLER
 
+	bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
+	
 	/*
 		Get block info from queue, emerge them and send them
 		to clients.
@@ -155,7 +155,7 @@ void * EmergeThread::Thread()
 			Also decrement the emerge queue count in clients.
 		*/
 
-		bool optional = true;
+		bool only_from_disk = true;
 
 		{
 			core::map<u16, u8>::Iterator i;
@@ -166,14 +166,15 @@ void * EmergeThread::Thread()
 				// Check flags
 				u8 flags = i.getNode()->getValue();
 				if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false)
-					optional = false;
+					only_from_disk = false;
 				
 			}
 		}
-
-		/*dstream<<"EmergeThread: p="
-				<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
-				<<"optional="<<optional<<std::endl;*/
+		
+		if(enable_mapgen_debug_info)
+			dstream<<"EmergeThread: p="
+					<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
+					<<"only_from_disk="<<only_from_disk<<std::endl;
 		
 		ServerMap &map = ((ServerMap&)m_server->m_env.getMap());
 			
@@ -184,11 +185,6 @@ void * EmergeThread::Thread()
 		bool got_block = true;
 		core::map<v3s16, MapBlock*> modified_blocks;
 		
-		bool only_from_disk = false;
-		
-		if(optional)
-			only_from_disk = true;
-
 		/*
 			Fetch block from map or generate a single block
 		*/
@@ -203,6 +199,9 @@ void * EmergeThread::Thread()
 			block = map.getBlockNoCreateNoEx(p);
 			if(!block || block->isDummy() || !block->isGenerated())
 			{
+				if(enable_mapgen_debug_info)
+					dstream<<"EmergeThread: not in memory, loading"<<std::endl;
+
 				// Get, load or create sector
 				/*ServerMapSector *sector =
 						(ServerMapSector*)map.createSector(p2d);*/
@@ -213,12 +212,20 @@ void * EmergeThread::Thread()
 						lighting_invalidated_blocks);*/
 
 				block = map.loadBlock(p);
+				
+				if(only_from_disk == false)
+				{
+					if(block == NULL || block->isGenerated() == false)
+					{
+						if(enable_mapgen_debug_info)
+							dstream<<"EmergeThread: generating"<<std::endl;
+						block = map.generateBlock(p, modified_blocks);
+					}
+				}
 
-				if(block == NULL && only_from_disk == false)
-					block = map.generateBlock(p, modified_blocks);
-					//block = map.generateBlock(p, changed_blocks);
-					/*block = map.generateBlock(p, block, sector, changed_blocks,
-							lighting_invalidated_blocks);*/
+				if(enable_mapgen_debug_info)
+					dstream<<"EmergeThread: ended up with: "
+							<<analyze_block(block)<<std::endl;
 
 				if(block == NULL)
 				{
-- 
GitLab