summaryrefslogtreecommitdiffstats
path: root/src/Generating/ComposableGenerator.h
blob: 0a7d99b7da763e5a105d7ce8ad61b626d80458dc (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

// ComposableGenerator.h

// Declares the cComposableGenerator class representing the chunk generator that takes the composition approach to
// generating chunks

/*
Generating works by composing several algorithms:
Biome, TerrainHeight, TerrainComposition, Ores, Structures and SmallFoliage
Each algorithm may be chosen from a pool of available algorithms in the same class and combined with others,
based on user's preferences in the world.ini.
See https://forum.cuberite.org/thread-409.html for details.
*/





#pragma once

#include "ChunkGenerator.h"
#include "ChunkDesc.h"





// Forward-declare the shared pointers to subgenerator classes:
class cBiomeGen;
class cTerrainShapeGen;
class cTerrainHeightGen;
class cTerrainCompositionGen;
class cFinishGen;





/** The interface that a biome generator must implement
A biome generator takes chunk coords on input and outputs an array of biome indices for that chunk on output.
The output array is sequenced in the same way as the MapChunk packet's biome data.
*/
class cBiomeGen
{
  public:
	virtual ~cBiomeGen() {}  // Force a virtual destructor in descendants

	/** Generates biomes for the given chunk */
	virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) = 0;

	/** Reads parameters from the ini file, prepares generator for use. */
	virtual void InitializeBiomeGen(cIniFile & a_IniFile) {}

	/** Creates the correct BiomeGen descendant based on the ini file settings.
	a_Seed is the seed read from the INI file.
	a_CacheOffByDefault gets set to whether the cache should be disabled by default.
	Used in BiomeVisualiser, too.
	Implemented in BioGen.cpp! */
	static std::unique_ptr<cBiomeGen> CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault);
};





/** The interface that a terrain shape generator must implement
A terrain shape generator takes chunk coords on input and outputs a 3D array of "shape" for that chunk. The shape here
represents the distinction between air and solid; there's no representation of Water since that is added by the
composition geenrator.
The output array is indexed [y + 256 * z + 16 * 256 * x], so that it's fast to later compose a single column of the
terrain, which is the dominant operation following the shape generation. The generator may request biome information
from the underlying BiomeGen, it may even request information for other chunks than the one it's currently generating
(neighbors - for averaging)
*/
class cTerrainShapeGen
{
  public:
	virtual ~cTerrainShapeGen() {}  // Force a virtual destructor in descendants

	/** Generates the shape for the given chunk */
	virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) = 0;

	/** Reads parameters from the ini file, prepares generator for use. */
	virtual void InitializeShapeGen(cIniFile & a_IniFile) {}

	/** Creates the correct TerrainShapeGen descendant based on the ini file settings and the seed provided.
	a_BiomeGen is the underlying biome generator, some shape generators may depend on it providing additional biomes
	data around the chunk a_CacheOffByDefault gets set to whether the cache should be disabled by default Implemented in
	ShapeGen.cpp!
	*/
	static std::unique_ptr<cTerrainShapeGen> CreateShapeGen(
		cIniFile & a_IniFile,
		cBiomeGen & a_BiomeGen,
		int a_Seed,
		bool & a_CacheOffByDefault
	);
};





/** The interface that is used to query terrain height from the shape generator.
Usually the structure generators require only the final heightmap, and generating the whole shape only to
consume the heightmap is wasteful, so this interface is used instead; it has a cache implemented over it so
that data is retained. */
class cTerrainHeightGen
{
  public:
	virtual ~cTerrainHeightGen() {}  // Force a virtual destructor in descendants

	/** Retrieves the heightmap for the specified chunk. */
	virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) = 0;

	/** Initializes the generator, reading its parameters from the INI file. */
	virtual void InitializeHeightGen(cIniFile & a_IniFile) {}

	/** Returns the height at the specified column.
	The default implementation calls GenHeightMap(), and then queries the heightmap.
	Descendants may provide a better-performing method. */
	virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ)
	{
		auto chunkCoords = cChunkDef::BlockToChunk({a_BlockX, 0, a_BlockZ});
		cChunkDef::HeightMap heightMap;
		GenHeightMap(chunkCoords, heightMap);
		return cChunkDef::GetHeight(
			heightMap,
			a_BlockX - chunkCoords.m_ChunkX * cChunkDef::Width,
			a_BlockZ - chunkCoords.m_ChunkZ * cChunkDef::Width
		);
	}

	/** Creates a cTerrainHeightGen descendant based on the INI file settings. */
	static std::unique_ptr<cTerrainHeightGen> CreateHeightGen(
		cIniFile & a_IniFile,
		cBiomeGen & a_BiomeGen,
		int a_Seed,
		bool & a_CacheOffByDefault
	);
};





/** The interface that a terrain composition generator must implement
Terrain composition takes chunk coords on input and outputs the blockdata for that entire chunk, along with
the list of entities. It is supposed to make use of the underlying TerrainHeightGen and BiomeGen for that purpose,
but it may request information for other chunks than the one it's currently generating from them.
*/
class cTerrainCompositionGen
{
  public:
	virtual ~cTerrainCompositionGen() {}  // Force a virtual destructor in descendants

	/** Generates the chunk's composition into a_ChunkDesc, using the terrain shape provided in a_Shape.
	Is expected to fill a_ChunkDesc's heightmap with the data from a_Shape. */
	virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) = 0;

	/** Reads parameters from the ini file, prepares generator for use. */
	virtual void InitializeCompoGen(cIniFile & a_IniFile) {}

	/** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided.
	a_BiomeGen is the underlying biome generator, some composition generators may depend on it providing additional
	biomes around the chunk a_ShapeGen is the underlying shape generator, some composition generators may depend on it
	providing additional shape around the chunk. */
	static std::unique_ptr<cTerrainCompositionGen> CreateCompositionGen(
		cIniFile & a_IniFile,
		cBiomeGen & a_BiomeGen,
		cTerrainShapeGen & a_ShapeGen,
		int a_Seed
	);
};





/** The interface that a finisher must implement
Finisher implements changes to the chunk after the rough terrain has been generated.
Examples of finishers are trees, snow, ore, lilypads and others.
Note that a worldgenerator may contain multiple finishers, chained one after another.
Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is
no longer relevant, all structure generators are considered finishers now (#398)
*/
class cFinishGen
{
  public:
	virtual ~cFinishGen() {}  // Force a virtual destructor in descendants

	virtual void GenFinish(cChunkDesc & a_ChunkDesc) = 0;
};





class cComposableGenerator : public cChunkGenerator
{
	using Super = cChunkGenerator;

  public:
	cComposableGenerator();

	// cChunkGenerator::cGenerator overrides:
	virtual void Initialize(cIniFile & a_IniFile) override;
	virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override;
	virtual void Generate(cChunkDesc & a_ChunkDesc) override;

	/** If there's no particular sub-generator set in the INI file,
	adds the default one, based on the dimension. */
	static void InitializeGeneratorDefaults(cIniFile & a_IniFile, eDimension a_Dimension);


  protected:
	// The generator's composition:
	/** The biome generator. */
	std::unique_ptr<cBiomeGen> m_BiomeGen;

	/** The terrain shape generator. */
	std::unique_ptr<cTerrainShapeGen> m_ShapeGen;

	/** The terrain composition generator. */
	std::unique_ptr<cTerrainCompositionGen> m_CompositionGen;

	/** The cache for the heights of the composited terrain. */
	std::unique_ptr<cTerrainHeightGen> m_CompositedHeightCache;

	/** The finisher generators, in the order in which they are applied. */
	std::vector<std::unique_ptr<cFinishGen>> m_FinishGens;


	/** Reads the BiomeGen settings from the ini and initializes m_BiomeGen accordingly */
	void InitBiomeGen(cIniFile & a_IniFile);

	/** Reads the ShapeGen settings from the ini and initializes m_ShapeGen accordingly */
	void InitShapeGen(cIniFile & a_IniFile);

	/** Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly */
	void InitCompositionGen(cIniFile & a_IniFile);

	/** Reads the finishers from the ini and initializes m_FinishGens accordingly */
	void InitFinishGens(cIniFile & a_IniFile);
};