summaryrefslogblamecommitdiffstats
path: root/src/Generating/GridStructGen.cpp
blob: 975fd3fdcc0f63bba6b0041627a8a7dbf6f19d84 (plain) (tree)









































































































































                                                                                                                                            

// GridStructGen.cpp

// Implements the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid

#include "Globals.h"
#include "GridStructGen.h"




cGridStructGen::cGridStructGen(
	int a_Seed,
	int a_GridSizeX, int a_GridSizeZ,
	int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
	size_t a_MaxCacheSize
) :
	m_Seed(a_Seed),
	m_GridSizeX(a_GridSizeX),
	m_GridSizeZ(a_GridSizeZ),
	m_MaxStructureSizeX(a_MaxStructureSizeX),
	m_MaxStructureSizeZ(a_MaxStructureSizeZ),
	m_MaxCacheSize(a_MaxCacheSize)
{
}





void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures)
{
	// Calculate the min and max grid coords of the structures to be returned:
	int MinBlockX = a_ChunkX * cChunkDef::Width - m_MaxStructureSizeX;
	int MinBlockZ = a_ChunkZ * cChunkDef::Width - m_MaxStructureSizeZ;
	int MaxBlockX = a_ChunkX * cChunkDef::Width + m_MaxStructureSizeX + cChunkDef::Width - 1;
	int MaxBlockZ = a_ChunkZ * cChunkDef::Width + m_MaxStructureSizeZ + cChunkDef::Width - 1;
	int MinGridX = MinBlockX / m_GridSizeX;
	int MinGridZ = MinBlockZ / m_GridSizeZ;
	int MaxGridX = MaxBlockX / m_GridSizeX;
	int MaxGridZ = MaxBlockX / m_GridSizeZ;
	if (MinGridX < 0)
	{
		--MinGridX;
	}
	if (MinGridZ < 0)
	{
		--MinGridZ;
	}
	if (MaxGridX < 0)
	{
		--MaxGridX;
	}
	if (MaxGridZ < 0)
	{
		--MaxGridZ;
	}

	// Walk the cache, move each structure that we want into a_Structures:
	for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
	{
		if (
			((*itr)->m_OriginX >= MinBlockX) && ((*itr)->m_OriginX < MaxBlockX) &&
			((*itr)->m_OriginZ >= MinBlockZ) && ((*itr)->m_OriginZ < MaxBlockZ)
		)
		{
			// want
			a_Structures.push_back(*itr);
			itr = m_Cache.erase(itr);
		}
		else
		{
			// don't want
			++itr;
		}
	}  // for itr - m_Cache[]

	// Create those structures that haven't been in the cache:
	for (int x = MinGridX; x < MaxGridX; x++)
	{
		int OriginX = x * m_GridSizeX;
		for (int z = MinGridZ; z < MaxGridZ; z++)
		{
			int OriginZ = z * m_GridSizeZ;
			bool Found = false;
			for (cStructurePtrs::const_iterator itr = a_Structures.begin(), end = a_Structures.end(); itr != end; ++itr)
			{
				if (((*itr)->m_OriginX == OriginX) && ((*itr)->m_OriginZ == OriginZ))
				{
					Found = true;
					break;
				}
			}  // for itr - a_Structures[]
			if (!Found)
			{
				a_Structures.push_back(CreateStructure(OriginX, OriginZ));
			}
		}  // for z
	}  // for x

	// Copy a_Forts into m_Cache to the beginning:
	cStructurePtrs StructuresCopy (a_Structures);
	m_Cache.splice(m_Cache.begin(), StructuresCopy, StructuresCopy.begin(), StructuresCopy.end());

	// Trim the cache if it's too long:
	size_t CacheSize = 0;
	for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
	{
		CacheSize += (*itr)->GetCacheCost();
		if (CacheSize > m_MaxCacheSize)
		{
			// Erase all items from this one till the cache end
			m_Cache.erase(itr, m_Cache.end());
			break;
		}
	}
}





void cGridStructGen::GenFinish(cChunkDesc & a_ChunkDesc)
{
	int ChunkX = a_ChunkDesc.GetChunkX();
	int ChunkZ = a_ChunkDesc.GetChunkZ();
	cStructurePtrs Structures;
	GetStructuresForChunk(ChunkX, ChunkZ, Structures);
	for (cStructurePtrs::const_iterator itr = Structures.begin(); itr != Structures.end(); ++itr)
	{
		(*itr)->DrawIntoChunk(a_ChunkDesc);
	}  // for itr - Structures[]
}