summaryrefslogtreecommitdiffstats
path: root/src/Generating/ChunkDesc.h
blob: d066660f1083f4417b97d98f0f2402cf52e39213 (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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

// ChunkDesc.h

// Declares the cChunkDesc class representing the chunk description used while generating a chunk. This class is also exported to Lua for HOOK_CHUNK_GENERATING.





#pragma once

#include "../BlockArea.h"
#include "../Cuboid.h"





// fwd: ../BlockArea.h
class cBlockArea;





// tolua_begin
class cChunkDesc
{
public:
	// tolua_end

	/** The datatype used to represent the entire chunk worth of shape.
	0 = air
	1 = solid
	Indexed as [y + 256 * x + 256 * 16 * z]. */
	typedef Byte Shape[256 * 16 * 16];

	/** Uncompressed block metas, 1 meta per byte */
	typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks];


	cChunkDesc(cChunkCoords a_Coords);
	~cChunkDesc();

	void SetChunkCoords(cChunkCoords a_Coords);

	// tolua_begin

	int GetChunkX() const { return m_Coords.m_ChunkX; }  // Prefer GetChunkCoords() instead
	int GetChunkZ() const { return m_Coords.m_ChunkZ; }  // Prefer GetChunkCoords() instead

	// tolua_end

	cChunkCoords GetChunkCoords() const { return m_Coords; }

	// tolua_begin

	void       FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
	void       SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);

	// tolua_end
	/** Returns the BlockType and BlockMeta at the specified coords.
	Exported to Lua manually to avoid extra parameters generated by ToLua++. */
	void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
	// tolua_begin

	void       SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType);
	BLOCKTYPE  GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const;

	void       SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta);
	NIBBLETYPE GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ) const;

	void       SetBiome(int a_RelX, int a_RelZ, EMCSBiome a_BiomeID);
	EMCSBiome  GetBiome(int a_RelX, int a_RelZ) const;

	// These operate on the heightmap, so they could get out of sync with the data
	// Use UpdateHeightmap() to re-calculate heightmap from the block data
	void       SetHeight(int a_RelX, int a_RelZ, HEIGHTTYPE a_Height);
	HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const;

	// tolua_end

	/** Sets the heightmap to match the given shape data.
	Note that this ignores overhangs; the method is mostly used by old composition generators. */
	void SetHeightFromShape(const Shape & a_Shape);

	/** Sets the shape in a_Shape to match the heightmap stored currently in m_HeightMap. */
	void GetShapeFromHeight(Shape & a_Shape) const;

	/** Returns the index into the internal shape array for the specified coords */
	inline static size_t MakeShapeIndex(int a_X, int a_Y, int a_Z)
	{
		return static_cast<size_t>(a_Y + a_X * cChunkDef::Height + a_Z * cChunkDef::Height * cChunkDef::Width);
	}

	inline static void SetShapeIsSolidAt(Shape & a_Shape, int a_X, int a_Y, int a_Z, bool a_IsSolid)
	{
		auto index = MakeShapeIndex(a_X, a_Y, a_Z);
		a_Shape[index] = a_IsSolid ? 1 : 0;
	}

	inline static bool GetShapeIsSolidAt(const Shape & a_Shape, int a_X, int a_Y, int a_Z)
	{
		auto index = MakeShapeIndex(a_X, a_Y, a_Z);
		return a_Shape[index];
	}

	// tolua_begin

	// Default generation:
	void SetUseDefaultBiomes(bool a_bUseDefaultBiomes);
	bool IsUsingDefaultBiomes(void) const;
	void SetUseDefaultHeight(bool a_bUseDefaultHeight);
	bool IsUsingDefaultHeight(void) const;
	void SetUseDefaultComposition(bool a_bUseDefaultComposition);
	bool IsUsingDefaultComposition(void) const;
	void SetUseDefaultFinish(bool a_bUseDefaultFinish);
	bool IsUsingDefaultFinish(void) const;

	/** Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. */
	void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite);

	/** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */
	void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ);

	/** Returns the maximum height value in the heightmap. */
	HEIGHTTYPE GetMaxHeight(void) const;

	/** Returns the minimum height value in the heightmap. */
	HEIGHTTYPE GetMinHeight(void) const;

	/** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */
	void FillRelCuboid(
		int a_MinX, int a_MaxX,
		int a_MinY, int a_MaxY,
		int a_MinZ, int a_MaxZ,
		BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
	);

	/** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */
	void FillRelCuboid(const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
	{
		FillRelCuboid(
			a_RelCuboid.p1.x, a_RelCuboid.p2.x,
			a_RelCuboid.p1.y, a_RelCuboid.p2.y,
			a_RelCuboid.p1.z, a_RelCuboid.p2.z,
			a_BlockType, a_BlockMeta
		);
	}

	/** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */
	void ReplaceRelCuboid(
		int a_MinX, int a_MaxX,
		int a_MinY, int a_MaxY,
		int a_MinZ, int a_MaxZ,
		BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta,
		BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
	);

	/** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */
	void ReplaceRelCuboid(
		const cCuboid & a_RelCuboid,
		BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta,
		BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
	)
	{
		ReplaceRelCuboid(
			a_RelCuboid.p1.x, a_RelCuboid.p2.x,
			a_RelCuboid.p1.y, a_RelCuboid.p2.y,
			a_RelCuboid.p1.z, a_RelCuboid.p2.z,
			a_SrcType, a_SrcMeta,
			a_DstType, a_DstMeta
		);
	}

	/** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */
	void FloorRelCuboid(
		int a_MinX, int a_MaxX,
		int a_MinY, int a_MaxY,
		int a_MinZ, int a_MaxZ,
		BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
	);

	/** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */
	void FloorRelCuboid(
		const cCuboid & a_RelCuboid,
		BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
	)
	{
		FloorRelCuboid(
			a_RelCuboid.p1.x, a_RelCuboid.p2.x,
			a_RelCuboid.p1.y, a_RelCuboid.p2.y,
			a_RelCuboid.p1.z, a_RelCuboid.p2.z,
			a_DstType, a_DstMeta
		);
	}

	/** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */
	void RandomFillRelCuboid(
		int a_MinX, int a_MaxX,
		int a_MinY, int a_MaxY,
		int a_MinZ, int a_MaxZ,
		BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
		int a_RandomSeed, int a_ChanceOutOf10k
	);

	/** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */
	void RandomFillRelCuboid(
		const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
		int a_RandomSeed, int a_ChanceOutOf10k
	)
	{
		RandomFillRelCuboid(
			a_RelCuboid.p1.x, a_RelCuboid.p2.x,
			a_RelCuboid.p1.y, a_RelCuboid.p2.y,
			a_RelCuboid.p1.z, a_RelCuboid.p2.z,
			a_BlockType, a_BlockMeta,
			a_RandomSeed, a_ChanceOutOf10k
		);
	}

	/** Returns the block entity at the specified coords.
	If there is no block entity at those coords, tries to create one, based on the block type
	If the blocktype doesn't support a block entity, returns nullptr. */
	cBlockEntity * GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ);

	/** Updates the heightmap to match the current contents.
	Useful for plugins when writing custom block areas into the chunk */
	void UpdateHeightmap(void);

	// tolua_end

	// Accessors used by cChunkGenerator::Generator descendants:
	inline cChunkDef::BiomeMap &     GetBiomeMap              (void) { return m_BiomeMap; }
	inline cChunkDef::BlockTypes &   GetBlockTypes            (void) { return *(reinterpret_cast<cChunkDef::BlockTypes *>(m_BlockArea.GetBlockTypes())); }
	// CANNOT, different compression!
	// inline cChunkDef::BlockNibbles & GetBlockMetas            (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); }
	inline BlockNibbleBytes &        GetBlockMetasUncompressed(void) { return *(reinterpret_cast<BlockNibbleBytes *>(m_BlockArea.GetBlockMetas())); }
	inline cChunkDef::HeightMap &    GetHeightMap             (void) { return m_HeightMap; }
	inline cEntityList &             GetEntities              (void) { return m_Entities; }
	inline cBlockEntities &          GetBlockEntities         (void) { return m_BlockEntities; }

	inline const cChunkDef::BiomeMap &     GetBiomeMap()   const { return m_BiomeMap; }
	inline const cChunkDef::BlockTypes &   GetBlockTypes() const { return *(reinterpret_cast<cChunkDef::BlockTypes *>(m_BlockArea.GetBlockTypes())); }
	inline const cChunkDef::HeightMap &    GetHeightMap()  const { return m_HeightMap; }

	/** Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) */
	void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas);

	#ifndef NDEBUG
	/** Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column */
	void VerifyHeightmap(void);
	#endif  // !NDEBUG

private:
	cChunkCoords m_Coords;

	cChunkDef::BiomeMap     m_BiomeMap;
	cBlockArea              m_BlockArea;
	cChunkDef::HeightMap    m_HeightMap;
	cEntityList             m_Entities;
	cBlockEntities          m_BlockEntities;  // Individual block entities are NOT owned by this object!

	bool m_bUseDefaultBiomes;
	bool m_bUseDefaultHeight;
	bool m_bUseDefaultComposition;
	bool m_bUseDefaultFinish;
} ;  // tolua_export