summaryrefslogtreecommitdiffstats
path: root/src/Generating/GridStructGen.cpp
blob: 3bbc89054000da7abaf96163e1f2e3806caecbdf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

// 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 - 1) / m_GridSizeX;
	int MaxGridZ = (MaxBlockZ + m_GridSizeZ - 1) / m_GridSizeZ;
	int MinX = MinGridX * m_GridSizeX;
	int MaxX = MaxGridX * m_GridSizeX;
	int MinZ = MinGridZ * m_GridSizeZ;
	int MaxZ = MaxGridZ * m_GridSizeZ;

	// 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 >= MinX) && ((*itr)->m_OriginX < MaxX) &&
			((*itr)->m_OriginZ >= MinZ) && ((*itr)->m_OriginZ < MaxZ)
		)
		{
			// 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[]
}