DIFF

ConstructionManagerStatic.c


//! Static part of the construction system, for global handling mostly
class ConstructionManagerStatic
{
	protected static const int UPDATE_QUEUE_BATCH_SIZE_DEFAULT = 15; //parts processed in a single simulation step
	
	protected static bool m_Initialized;
	protected static bool m_IsServerBatchProcessing; //is server?
	protected static ScriptInvoker m_UpdateQueue;
	protected static ref map<ConstructionBase, ref array<ConstructionPart>> m_QueueConstructionMap;
	protected static ref array<ConstructionBase> m_CleanupQueue;
	
	static void Init()
	{
		if (!m_Initialized)
		{
			m_UpdateQueue = g_Game.GetUpdateQueue(CALL_CATEGORY_SYSTEM);
			m_IsServerBatchProcessing = g_Game.IsServer() || !g_Game.IsMultiplayer();
			m_QueueConstructionMap = new map<ConstructionBase, ref array<ConstructionPart>>();
			m_CleanupQueue = new array<ConstructionBase>();
			m_Initialized = true;
		}
	}
	
	//============================================
	// Batching and processing
	//============================================
	
	///////////////////////
	//API
	
	static void AddPartToProcess(ConstructionBase con, ConstructionPart part)
	{
		if (!m_Initialized)
			Init();
		
		array<ConstructionPart> tmp;
		if (!m_QueueConstructionMap.Find(con, tmp))
			tmp = new array<ConstructionPart>();
		
		if (tmp.Find(part) == -1)
			tmp.Insert(part);
		
		m_QueueConstructionMap.Set(con, tmp);
		
		if (m_UpdateQueue.Count(ProcessUpdateQueues) == 0)
			m_UpdateQueue.Insert(ProcessUpdateQueues);
	}
	
	//! Unremoved objects can become NULL
	static void RemoveFromProcessing(ConstructionBase con)
	{
		if (m_QueueConstructionMap.Contains(con))
			m_QueueConstructionMap.Remove(con);
	}
	
	///////////////////////
	//Internals
	
	protected static void ProcessUpdateQueues()
	{
		int batchCounter = UPDATE_QUEUE_BATCH_SIZE_DEFAULT;
		int count;
		
		foreach (ConstructionBase con, array<ConstructionPart> updatePartsArray : m_QueueConstructionMap)
		{
			if (batchCounter == 0)
				break;
			
			count = updatePartsArray.Count();
			for (int i = count - 1; i > -1; --i)
			{
				if (batchCounter == 0)
					break;
				
				ConstructionPart part = updatePartsArray[i];
				con.UpdateSpecificPartPhysics(part);
				if (m_IsServerBatchProcessing)
					con.UpdateSpecificPartVisuals(part);
				
				updatePartsArray.Remove(i);
				--batchCounter;
				
				if (updatePartsArray.Count() == 0)
				{
					m_CleanupQueue.Insert(con);
					break;
				}
			}
		}
		
		foreach (ConstructionBase cleanupCon : m_CleanupQueue)
		{
			if (m_IsServerBatchProcessing)
				cleanupCon.UpdateNavmesh();
			m_QueueConstructionMap.Remove(cleanupCon);
		}
		
		m_CleanupQueue.Clear();
		
		if (m_QueueConstructionMap.Count() == 0 && m_UpdateQueue.Count(ProcessUpdateQueues) > 0)
		{
			m_UpdateQueue.Remove(ProcessUpdateQueues);
			m_QueueConstructionMap.Clear();
		}
	}
}