From 71f5d4b3443c6ea770463838a2c84b85d9fa3b21 Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Fri, 1 Jul 2011 21:04:40 +0300
Subject: [PATCH] Fixed objects being sometimes not able to be stored
 statically in a block when block has been unloaded

---
 src/environment.cpp | 29 ++++++++++++++-----------
 src/main.cpp        | 24 +++++++++++----------
 src/map.cpp         | 52 ++++++++++++++++++++++++++++++++++-----------
 src/map.h           | 21 +++++-------------
 src/server.cpp      |  2 ++
 5 files changed, 77 insertions(+), 51 deletions(-)

diff --git a/src/environment.cpp b/src/environment.cpp
index ac69c8ae2..ac78107a3 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -1177,7 +1177,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
 			block->setChangedFlag();
 	}
 	else{
-		dstream<<"WARNING: Server: Could not find a block for "
+		dstream<<"WARNING: ServerEnv: Could not find a block for "
 				<<"storing newly added static active object"<<std::endl;
 	}
 
@@ -1349,7 +1349,20 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
 		StaticObject s_obj(obj->getType(), objectpos, staticdata);
 		// Add to the block where the object is located in
 		v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
-		MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
+		// Get or generate the block
+		MapBlock *block = m_map->emergeBlock(blockpos);
+
+		/*MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
+		if(block == NULL)
+		{
+			// Block not found. Is the old block still ok?
+			if(oldblock)
+				block = oldblock;
+			// Load from disk or generate
+			else
+				block = m_map->emergeBlock(blockpos);
+		}*/
+
 		if(block)
 		{
 			block->m_static_objects.insert(0, s_obj);
@@ -1357,17 +1370,9 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
 			obj->m_static_exists = true;
 			obj->m_static_block = block->getPos();
 		}
-		// If not possible, add back to previous block
-		else if(oldblock)
-		{
-			oldblock->m_static_objects.insert(0, s_obj);
-			oldblock->setChangedFlag();
-			obj->m_static_exists = true;
-			obj->m_static_block = oldblock->getPos();
-		}
 		else{
-			dstream<<"WARNING: Server: Could not find a block for "
-					<<"storing static object"<<std::endl;
+			dstream<<"WARNING: ServerEnv: Could not find or generate "
+					<<"a block for storing static object"<<std::endl;
 			obj->m_static_exists = false;
 			continue;
 		}
diff --git a/src/main.cpp b/src/main.cpp
index cd5df666d..698c5fc71 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -126,6 +126,16 @@ SUGG: Erosion simulation at map generation time
 	- Simulate rock falling from cliffs when water has removed
 	  enough solid rock from the bottom
 
+SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface
+      stuff as simple flags/values
+      - Light?
+	  - A building?
+	  And at some point make the server send this data to the client too,
+	  instead of referring to the noise functions
+	  - Ground height
+	  - Surface ground type
+	  - Trees?
+
 Gaming ideas:
 -------------
 
@@ -199,12 +209,13 @@ SUGG: Make fetching sector's blocks more efficient when rendering
       sectors that have very large amounts of blocks (on client)
 	  - Is this necessary at all?
 
-TODO: Flowing water animation
-
 SUGG: Draw cubes in inventory directly with 3D drawing commands, so that
       animating them is easier.
 
 SUGG: Option for enabling proper alpha channel for textures
+
+TODO: Flowing water animation
+
 TODO: A setting for enabling bilinear filtering for textures
 
 TODO: Better control of draw_control.wanted_max_blocks
@@ -321,15 +332,6 @@ TODO: Think about using same bits for material for fences and doors, for
 TODO: Move mineral to param2, increment map serialization version, add
       conversion
 
-TODO: Add a per-sector database to store surface stuff as simple flags/values
-      - Light?
-	  - A building?
-	  And at some point make the server send this data to the client too,
-	  instead of referring to the noise functions
-	  - Ground height
-	  - Surface ground type
-	  - Trees?
-
 TODO: Restart irrlicht completely when coming back to main menu from game.
 	- This gets rid of everything that is stored in irrlicht's caches.
 
diff --git a/src/map.cpp b/src/map.cpp
index 79f2a40af..dc66b4d55 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -2442,23 +2442,51 @@ MapBlock * ServerMap::createBlock(v3s16 p)
 	return block;
 }
 
-#if 0
-MapBlock * ServerMap::emergeBlock(
-		v3s16 p,
-		bool only_from_disk,
-		core::map<v3s16, MapBlock*> &changed_blocks,
-		core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
-)
+MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
 {
-	DSTACKF("%s: p=(%d,%d,%d), only_from_disk=%d",
+	DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
 			__FUNCTION_NAME,
-			p.X, p.Y, p.Z, only_from_disk);
+			p.X, p.Y, p.Z, allow_generate);
 	
-	// This has to be redone or removed
-	assert(0);
+	{
+		MapBlock *block = getBlockNoCreateNoEx(p);
+		if(block)
+			return block;
+	}
+
+	{
+		MapBlock *block = loadBlock(p);
+		if(block)
+			return block;
+	}
+
+	if(allow_generate)
+	{
+		core::map<v3s16, MapBlock*> modified_blocks;
+		MapBlock *block = generateBlock(p, modified_blocks);
+		if(block)
+		{
+			MapEditEvent event;
+			event.type = MEET_OTHER;
+			event.p = p;
+
+			// Copy modified_blocks to event
+			for(core::map<v3s16, MapBlock*>::Iterator
+					i = modified_blocks.getIterator();
+					i.atEnd()==false; i++)
+			{
+				event.modified_blocks.insert(i.getNode()->getKey(), false);
+			}
+
+			// Queue event
+			dispatchEvent(&event);
+								
+			return block;
+		}
+	}
+
 	return NULL;
 }
-#endif
 
 #if 0
 	/*
diff --git a/src/map.h b/src/map.h
index 71101b8e4..a8aa8e679 100644
--- a/src/map.h
+++ b/src/map.h
@@ -57,7 +57,7 @@ enum MapEditEventType{
 	// Node metadata of block changed (not knowing which node exactly)
 	// p stores block coordinate
 	MEET_BLOCK_NODE_METADATA_CHANGED,
-	// Anything else
+	// Anything else (modified_blocks are set unsent)
 	MEET_OTHER
 };
 
@@ -338,24 +338,13 @@ class ServerMap : public Map
 	*/
 	MapBlock * createBlock(v3s16 p);
 
-#if 0
 	/*
-		NOTE: This comment might be outdated
-		
 		Forcefully get a block from somewhere.
-
-		InvalidPositionException possible if only_from_disk==true
-		
-		Parameters:
-		changed_blocks: Blocks that have been modified
+		- Memory
+		- Load from disk
+		- Generate
 	*/
-	MapBlock * emergeBlock(
-			v3s16 p,
-			bool only_from_disk,
-			core::map<v3s16, MapBlock*> &changed_blocks,
-			core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
-	);
-#endif
+	MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
 	
 	// Helper for placing objects on ground level
 	s16 findGroundLevel(v2s16 p2d);
diff --git a/src/server.cpp b/src/server.cpp
index 798f36ac1..c2433e1af 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1739,6 +1739,7 @@ void Server::AsyncRunStep()
 			*/
 			if(far_players.size() > 0)
 			{
+				// Convert list format to that wanted by SetBlocksNotSent
 				core::map<v3s16, MapBlock*> modified_blocks2;
 				for(core::map<v3s16, bool>::Iterator
 						i = event->modified_blocks.getIterator();
@@ -1748,6 +1749,7 @@ void Server::AsyncRunStep()
 					modified_blocks2.insert(p,
 							m_env.getMap().getBlockNoCreateNoEx(p));
 				}
+				// Set blocks not sent
 				for(core::list<u16>::Iterator
 						i = far_players.begin();
 						i != far_players.end(); i++)
-- 
GitLab