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
|
// WSSAnvil.h
// Interfaces to the cWSSAnvil class representing the Anvil world storage scheme
#pragma once
#include "WorldStorage.h"
#include "FastNBT.h"
enum
{
/// Maximum number of chunks in an MCA file - also the count of the header items
MCA_MAX_CHUNKS = 32 * 32,
/// The MCA header is 8 KiB
MCA_HEADER_SIZE = MCA_MAX_CHUNKS * 8,
/// There are 5 bytes of header in front of each chunk
MCA_CHUNK_HEADER_LENGTH = 5,
} ;
// fwd: "NBT.h"
class cNBTTag;
class cNBTList;
class cNBTCompound;
class cWSSAnvil :
public cWSSchema
{
typedef cWSSchema super;
public:
cWSSAnvil(cWorld * a_World);
virtual ~cWSSAnvil();
protected:
class cMCAFile
{
public:
cMCAFile(const AString & a_FileName, int a_RegionX, int a_RegionZ);
bool GetChunkData (const cChunkCoords & a_Chunk, AString & a_Data);
bool SetChunkData (const cChunkCoords & a_Chunk, const AString & a_Data);
bool EraseChunkData(const cChunkCoords & a_Chunk);
int GetRegionX (void) const {return m_RegionX; }
int GetRegionZ (void) const {return m_RegionZ; }
const AString & GetFileName(void) const {return m_FileName; }
protected:
int m_RegionX;
int m_RegionZ;
cFile m_File;
AString m_FileName;
// The header, copied from the file so we don't have to seek to it all the time
// First 1024 entries are chunk locations - the 3 + 1 byte sector-offset and sector-count
unsigned m_Header[MCA_MAX_CHUNKS];
// Chunk timestamps, following the chunk headers, are unused by MCS
/// Finds a free location large enough to hold a_Data. Gets a hint of the chunk coords, places the data there if it fits. Returns the sector number.
unsigned FindFreeLocation(int a_LocalX, int a_LocalZ, const AString & a_Data);
} ;
typedef std::list<cMCAFile *> cMCAFiles;
cCriticalSection m_CS;
cMCAFiles m_Files; // a MRU cache of MCA files
/// Gets chunk data from the correct file; locks file CS as needed
bool GetChunkData(const cChunkCoords & a_Chunk, AString & a_Data);
/// Sets chunk data into the correct file; locks file CS as needed
bool SetChunkData(const cChunkCoords & a_Chunk, const AString & a_Data);
/// Loads the chunk from the data (no locking needed)
bool LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data);
/// Saves the chunk into datastream (no locking needed)
bool SaveChunkToData(const cChunkCoords & a_Chunk, AString & a_Data);
/// Loads the chunk from NBT data (no locking needed)
bool LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT);
/// Saves the chunk into NBT data using a_Writer; returns true on success
bool SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_Writer);
/// Loads the chunk's entities from NBT data (a_Tag is the Level\\Entities list tag; may be -1)
void LoadEntitiesFromNBT(cEntityList & a_Entitites, const cParsedNBT & a_NBT, int a_Tag);
/// Loads the chunk's BlockEntities from NBT data (a_Tag is the Level\\TileEntities list tag; may be -1)
void LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag);
void LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
/// Helper function for extracting the X, Y, and Z int subtags of a NBT compound; returns true if successful
bool GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, int & a_X, int & a_Y, int & a_Z);
/// Gets the correct MCA file either from cache or from disk, manages the m_MCAFiles cache; assumes m_CS is locked
cMCAFile * LoadMCAFile(const cChunkCoords & a_Chunk);
/// Copies a_Length bytes of data from the specified NBT Tag's Child into the a_Destination buffer
void CopyNBTData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, char * a_Destination, int a_Length);
// cWSSchema overrides:
virtual bool LoadChunk(const cChunkCoords & a_Chunk) override;
virtual bool SaveChunk(const cChunkCoords & a_Chunk) override;
virtual const AString GetName(void) const override {return "anvil"; }
} ;
|