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
|
// WSSCompact.h
// Interfaces to the cWSSCompact class representing the "Compact" storage schema (PAK-files)
#pragma once
#ifndef WSSCOMPACT_H_INCLUDED
#define WSSCOMPACT_H_INCLUDED
#include "WorldStorage.h"
#include "../Vector3.h"
#include "json/json.h"
#include "ChunkBuffer.h"
/// Helper class for serializing a chunk into Json
class cJsonChunkSerializer :
public cChunkDataCollector
{
public:
cJsonChunkSerializer(void);
Json::Value & GetRoot (void) {return m_Root; }
BLOCKTYPE * GetBlockData(void) {return (BLOCKTYPE *)m_BlockData; }
bool HasJsonData (void) const {return m_HasJsonData; }
protected:
// NOTE: block data is serialized into inherited cChunkDataCollector's m_BlockData[] array
// Entities and BlockEntities are serialized to Json
Json::Value m_Root;
bool m_HasJsonData;
// cChunkDataCollector overrides:
virtual void Entity (cEntity * a_Entity) override;
virtual void BlockEntity (cBlockEntity * a_Entity) override;
virtual void LightIsValid (bool a_IsLightValid) override;
} ;
class cWSSCompact :
public cWSSchema
{
public:
cWSSCompact(cWorld * a_World, int a_CompressionFactor) : cWSSchema(a_World), m_CompressionFactor(a_CompressionFactor) {}
virtual ~cWSSCompact();
protected:
enum
{
// Offsets to individual components in the joined blockdata array
MetaOffset = cChunkDef::NumBlocks,
LightOffset = MetaOffset + cChunkDef::NumBlocks / 2,
SkyLightOffset = LightOffset + cChunkDef::NumBlocks / 2,
} ;
struct sChunkHeader;
typedef std::vector<sChunkHeader *> sChunkHeaders;
/// Implements a cache for a single PAK file; implements lazy-write in order to be able to write multiple chunks fast
class cPAKFile
{
public:
cPAKFile(const AString & a_FileName, int a_LayerX, int a_LayerZ, int a_CompressionFactor);
~cPAKFile();
bool GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data);
bool SetChunkData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data);
bool EraseChunkData(const cChunkCoords & a_Chunk);
bool SaveChunk(const cChunkCoords & a_Chunk, cWorld * a_World);
int GetLayerX(void) const {return m_LayerX; }
int GetLayerZ(void) const {return m_LayerZ; }
static const int PAK_VERSION = 1;
#if AXIS_ORDER == AXIS_ORDER_XZY
static const int CHUNK_VERSION = 3;
#elif AXIS_ORDER == AXIS_ORDER_YZX
static const int CHUNK_VERSION = 2;
#endif
protected:
AString m_FileName;
int m_CompressionFactor;
int m_LayerX;
int m_LayerZ;
sChunkHeaders m_ChunkHeaders;
AString m_DataContents; // Data contents of the file, cached
int m_NumDirty; // Number of chunks that were written into m_DataContents but not into the file
Vector3i m_ChunkSize; // Is related to m_ChunkVersion
char m_ChunkVersion;
char m_PakVersion;
bool SaveChunkToData(const cChunkCoords & a_Chunk, cWorld * a_World); // Saves the chunk to m_DataContents, updates headers and m_NumDirty
void SynchronizeFile(void); // Writes m_DataContents along with the headers to file, resets m_NumDirty
void UpdateChunk1To2(void); // Height from 128 to 256
void UpdateChunk2To3(void); // Axis order from YZX to XZY
} ;
typedef std::list<cPAKFile *> cPAKFiles;
cCriticalSection m_CS;
cPAKFiles m_PAKFiles; // A MRU cache of PAK files
int m_CompressionFactor;
/// Loads the correct PAK file either from cache or from disk, manages the m_PAKFiles cache
cPAKFile * LoadPAKFile(const cChunkCoords & a_Chunk);
/// Gets chunk data from the correct file; locks CS as needed
bool GetChunkData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, AString & a_Data);
/// Sets chunk data to the correct file; locks CS as needed
bool SetChunkData(const cChunkCoords & a_Chunk, int a_UncompressedSize, const AString & a_Data);
/// Erases chunk data from the correct file; locks CS as needed
bool EraseChunkData(const cChunkCoords & a_Chunk);
/// Loads the chunk from the data (no locking needed)
bool LoadChunkFromData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, const AString & a_Data, cWorld * a_World);
void LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities, cWorld * a_World);
// 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 "compact"; }
} ;
#endif // WSSCOMPACT_H_INCLUDED
|