From 0643cef09a741d1e8a7b971f3ae70b45ac8d44bf Mon Sep 17 00:00:00 2001
From: Ciaran Gultnieks <ciaran@ciarang.com>
Date: Thu, 6 Mar 2014 19:20:06 +0000
Subject: [PATCH] Update ABM object counts when triggers add objects

Also fixes long-standing accuracy issue due to unknown wider
object count not being incremented.
---
 src/environment.cpp | 49 ++++++++++++++++++++++++++++++---------------
 src/environment.h   |  4 ++++
 2 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/src/environment.cpp b/src/environment.cpp
index 9f7207b8d..3593c94f0 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -712,17 +712,13 @@ public:
 			}
 		}
 	}
-	void apply(MapBlock *block)
+	// Find out how many objects the given block and its neighbours contain.
+	// Returns the number of objects in the block, and also in 'wider' the
+	// number of objects in the block and all its neighbours. The latter
+	// may an estimate if any neighbours are unloaded.
+	u32 countObjects(MapBlock *block, ServerMap * map, u32 &wider)
 	{
-		if(m_aabms.empty())
-			return;
-
-		ServerMap *map = &m_env->getServerMap();
-
-		// Find out how many objects the block contains
-		u32 active_object_count = block->m_static_objects.m_active.size();
-		// Find out how many objects this and all the neighbors contain
-		u32 active_object_count_wider = 0;
+		wider = 0;
 		u32 wider_unknown_count = 0;
 		for(s16 x=-1; x<=1; x++)
 		for(s16 y=-1; y<=1; y++)
@@ -731,17 +727,30 @@ public:
 			MapBlock *block2 = map->getBlockNoCreateNoEx(
 					block->getPos() + v3s16(x,y,z));
 			if(block2==NULL){
-				wider_unknown_count = 0;
+				wider_unknown_count++;
 				continue;
 			}
-			active_object_count_wider +=
-					block2->m_static_objects.m_active.size()
+			wider += block2->m_static_objects.m_active.size()
 					+ block2->m_static_objects.m_stored.size();
 		}
 		// Extrapolate
+		u32 active_object_count = block->m_static_objects.m_active.size();
 		u32 wider_known_count = 3*3*3 - wider_unknown_count;
-		active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count;
-				
+		wider += wider_unknown_count * wider / wider_known_count;
+		return active_object_count;
+
+	}
+	void apply(MapBlock *block)
+	{
+		if(m_aabms.empty())
+			return;
+
+		ServerMap *map = &m_env->getServerMap();
+
+		u32 active_object_count_wider;
+		u32 active_object_count = this->countObjects(block, map, active_object_count_wider);
+		m_env->m_added_objects = 0;
+
 		v3s16 p0;
 		for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
 		for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
@@ -788,7 +797,14 @@ neighbor_found:
 				// Call all the trigger variations
 				i->abm->trigger(m_env, p, n);
 				i->abm->trigger(m_env, p, n,
-						active_object_count, active_object_count_wider);
+						active_object_count,
+						active_object_count_wider + active_object_count);
+
+				// Count surrounding objects again if the abms added any
+				if(m_env->m_added_objects > 0) {
+					active_object_count = countObjects(block, map, active_object_count_wider);
+					m_env->m_added_objects = 0;
+				}
 			}
 		}
 	}
@@ -1358,6 +1374,7 @@ u16 getFreeServerActiveObjectId(
 u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
 {
 	assert(object);
+	m_added_objects++;
 	u16 id = addActiveObjectRaw(object, true, 0);
 	return id;
 }
diff --git a/src/environment.h b/src/environment.h
index 8cc0bcd7e..d99e27ba4 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -105,6 +105,9 @@ public:
 		m_day_night_ratio_override = value;
 	}
 
+	// counter used internally when triggering ABMs
+	u32 m_added_objects;
+
 protected:
 	// peer_ids in here should be unique, except that there may be many 0s
 	std::list<Player*> m_players;
@@ -118,6 +121,7 @@ protected:
 	// Overriding the day-night ratio is useful for custom sky visuals
 	bool m_enable_day_night_ratio_override;
 	u32 m_day_night_ratio_override;
+
 };
 
 /*
-- 
2.25.1