summaryrefslogtreecommitdiffstats
path: root/source/BlockArea.h
blob: b1a2d90530df42dc67c5a3ab0eaaa5bd697c4722 (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

// BlockArea.h

// Interfaces to the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries
// The object also supports writing the blockdata back into cWorld, even into other coords

// NOTE: All Nibble values (meta, blocklight, skylight) are stored one-nibble-per-byte for faster access / editting!





#pragma once





// fwd: World.h
class cWorld;

// fwd: FastNBT.h
class cParsedNBT;





// tolua_begin
class cBlockArea
{
	// tolua_end
	DISALLOW_COPY_AND_ASSIGN(cBlockArea);
	// tolua_begin
	
public:

	/// What data is to be queried (bit-mask)
	enum
	{
		baTypes    = 1,
		baMetas    = 2,
		baLight    = 4,
		baSkyLight = 8,
	} ;
	
	cBlockArea(void);
	~cBlockArea();
	
	/// Clears the data stored to reclaim memory
	void Clear(void);
	
	/// Reads an area of blocks specified. Returns true if successful. All coords are inclusive.
	bool Read(cWorld * a_World, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes = baTypes | baMetas);
	
	/// Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all
	bool Write(cWorld * a_World, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes = baTypes | baMetas);
	
	/// Copies this object's contents into the specified BlockArea.
	void CopyTo(cBlockArea & a_Into) const;
	
	/// Copies the contents from the specified BlockArea into this object.
	void CopyFrom(const cBlockArea & a_From);
	
	/// For testing purposes only, dumps the area into a file.
	void DumpToRawFile(const AString & a_FileName);
	
	// TODO: Write() is not too good an interface: if it fails, there's no way to repeat only for the parts that didn't write
	// A better way may be to return a list of cBlockAreas for each part that didn't succeed writing, so that the caller may try again
	
	/// Loads an area from a .schematic file. Returns true if successful
	bool LoadFromSchematicFile(const AString & a_FileName);
	
	/// Saves the area into a .schematic file. Returns true if successful
	bool SaveToSchematicFile(const AString & a_FileName);
	
	/// Crops the internal contents by the specified amount of blocks from each border.
	void Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
	
	/// Expands the internal contents by the specified amount of blocks from each border
	void Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
	
	// Setters:
	void SetRelBlockType    (int a_RelX,   int a_RelY,   int a_RelZ,   BLOCKTYPE  a_BlockType);
	void SetBlockType       (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE  a_BlockType);
	void SetRelBlockMeta    (int a_RelX,   int a_RelY,   int a_RelZ,   NIBBLETYPE a_BlockMeta);
	void SetBlockMeta       (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta);
	void SetRelBlockLight   (int a_RelX,   int a_RelY,   int a_RelZ,   NIBBLETYPE a_BlockLight);
	void SetBlockLight      (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockLight);
	void SetRelBlockSkyLight(int a_RelX,   int a_RelY,   int a_RelZ,   NIBBLETYPE a_BlockSkyLight);
	void SetBlockSkyLight   (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockSkyLight);

	// Getters:
	BLOCKTYPE  GetRelBlockType    (int a_RelX,   int a_RelY,   int a_RelZ)   const;
	BLOCKTYPE  GetBlockType       (int a_BlockX, int a_BlockY, int a_BlockZ) const;
	NIBBLETYPE GetRelBlockMeta    (int a_RelX,   int a_RelY,   int a_RelZ)   const;
	NIBBLETYPE GetBlockMeta       (int a_BlockX, int a_BlockY, int a_BlockZ) const;
	NIBBLETYPE GetRelBlockLight   (int a_RelX,   int a_RelY,   int a_RelZ)   const;
	NIBBLETYPE GetBlockLight      (int a_BlockX, int a_BlockY, int a_BlockZ) const;
	NIBBLETYPE GetRelBlockSkyLight(int a_RelX,   int a_RelY,   int a_RelZ)   const;
	NIBBLETYPE GetBlockSkyLight   (int a_BlockX, int a_BlockY, int a_BlockZ) const;

	void SetBlockTypeMeta   (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType,   NIBBLETYPE a_BlockMeta);
	void SetRelBlockTypeMeta(int a_RelX,   int a_RelY,   int a_RelZ,   BLOCKTYPE a_BlockType,   NIBBLETYPE a_BlockMeta);
	void GetBlockTypeMeta   (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
	void GetRelBlockTypeMeta(int a_RelX,   int a_RelY,   int a_RelZ,   BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
	
	int GetSizeX(void) const { return m_SizeX; }
	int GetSizeY(void) const { return m_SizeY; }
	int GetSizeZ(void) const { return m_SizeZ; }
	
	int GetOriginX(void) const { return m_OriginX; }
	int GetOriginY(void) const { return m_OriginY; }
	int GetOriginZ(void) const { return m_OriginZ; }
	
	/// Returns the datatypes that are stored in the object (bitmask of baXXX values)
	int GetDataTypes(void) const;
	
	bool HasBlockTypes    (void) const { return (m_BlockTypes    != NULL); }
	bool HasBlockMetas    (void) const { return (m_BlockMetas    != NULL); }
	bool HasBlockLights   (void) const { return (m_BlockLight    != NULL); }
	bool HasBlockSkyLights(void) const { return (m_BlockSkyLight != NULL); }
	
	// tolua_end
	
	// Clients can use these for faster access to all blocktypes. Be careful though!
	/// Returns the internal pointer to the block types
	BLOCKTYPE *  GetBlockTypes   (void) { return m_BlockTypes; }
	NIBBLETYPE * GetBlockMetas   (void) { return m_BlockMetas; }     // NOTE: one byte per block!
	NIBBLETYPE * GetBlockLight   (void) { return m_BlockLight; }     // NOTE: one byte per block!
	NIBBLETYPE * GetBlockSkyLight(void) { return m_BlockSkyLight; }  // NOTE: one byte per block!
	int          GetBlockCount(void) const { return m_SizeX * m_SizeY * m_SizeZ; }
	int MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const;

protected:
	friend class cChunkDesc;
	
	class cChunkReader :
		public cChunkDataCallback
	{
	public:
		cChunkReader(cBlockArea & a_Area);
		
	protected:
		cBlockArea & m_Area;
		int m_OriginX;
		int m_OriginY;
		int m_OriginZ;
		int m_CurrentChunkX;
		int m_CurrentChunkZ;
		
		void CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc);
		
		// cChunkDataCallback overrides:
		virtual bool Coords       (int a_ChunkX, int a_ChunkZ) override;
		virtual void BlockTypes   (const BLOCKTYPE *  a_BlockTypes)    override;
		virtual void BlockMeta    (const NIBBLETYPE * a_BlockMetas)    override;
		virtual void BlockLight   (const NIBBLETYPE * a_BlockLight)    override;
		virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override;
	} ;
	
	typedef NIBBLETYPE * NIBBLEARRAY;
	
	
	int m_OriginX;
	int m_OriginY;
	int m_OriginZ;
	int m_SizeX;
	int m_SizeY;
	int m_SizeZ;
	
	BLOCKTYPE *  m_BlockTypes;
	NIBBLETYPE * m_BlockMetas;     // Each meta is stored as a separate byte for faster access
	NIBBLETYPE * m_BlockLight;     // Each light value is stored as a separate byte for faster access
	NIBBLETYPE * m_BlockSkyLight;  // Each light value is stored as a separate byte for faster access
	
	/// Clears the data stored and prepares a fresh new block area with the specified dimensions
	bool SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes);
	
	// Basic Setters:
	void SetRelNibble(int a_RelX,   int a_RelY,   int a_RelZ,   NIBBLETYPE a_Value, NIBBLETYPE * a_Array);
	void SetNibble   (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array);

	// Basic Getters:
	NIBBLETYPE GetRelNibble(int a_RelX,   int a_RelY,   int a_RelZ,   NIBBLETYPE * a_Array) const;
	NIBBLETYPE GetNibble   (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE * a_Array) const;
	
	// Crop helpers:
	void CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
	void CropNibbles   (NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
	
	// Expand helpers:
	void ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
	void ExpandNibbles   (NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
	
	/// Loads the area from a schematic file uncompressed and parsed into a NBT tree. Returns true if successful.
	bool LoadFromSchematicNBT(cParsedNBT & a_NBT);

	// tolua_begin
} ;
// tolua_end