summaryrefslogtreecommitdiffstats
path: root/src/WorldStorage
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2021-01-11 17:39:43 +0100
committerGitHub <noreply@github.com>2021-01-11 17:39:43 +0100
commiteeb63b8901a9c049f1bb594abb9ce9b4a9c47620 (patch)
treeb07daae788f918b83eeb0bdbd51e49292f1c8d88 /src/WorldStorage
parentFixed switch-ups regarding some slab and stair recipes (#5099) (diff)
downloadcuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar.gz
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar.bz2
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar.lz
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar.xz
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.tar.zst
cuberite-eeb63b8901a9c049f1bb594abb9ce9b4a9c47620.zip
Diffstat (limited to 'src/WorldStorage')
-rw-r--r--src/WorldStorage/FastNBT.cpp78
-rw-r--r--src/WorldStorage/FastNBT.h48
-rw-r--r--src/WorldStorage/FireworksSerializer.cpp4
-rw-r--r--src/WorldStorage/MapSerializer.cpp53
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp10
-rw-r--r--src/WorldStorage/NBTChunkSerializer.h5
-rw-r--r--src/WorldStorage/SchematicFileSerializer.cpp115
-rw-r--r--src/WorldStorage/SchematicFileSerializer.h33
-rw-r--r--src/WorldStorage/ScoreboardSerializer.cpp55
-rw-r--r--src/WorldStorage/WSSAnvil.cpp147
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.h35
11 files changed, 201 insertions, 382 deletions
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index ec43d2f12..d5b9fd0f7 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -137,7 +137,7 @@ std::error_code make_error_code(eNBTParseError a_Err) noexcept
#define NEEDBYTES(N, ERR) \
do { \
- if (m_Length - m_Pos < static_cast<size_t>(N)) \
+ if (m_Data.size() - m_Pos < static_cast<size_t>(N)) \
{ \
return ERR; \
} \
@@ -147,9 +147,8 @@ std::error_code make_error_code(eNBTParseError a_Err) noexcept
-cParsedNBT::cParsedNBT(const char * a_Data, size_t a_Length) :
+cParsedNBT::cParsedNBT(const ContiguousByteBufferView a_Data) :
m_Data(a_Data),
- m_Length(a_Length),
m_Pos(0)
{
m_Error = Parse();
@@ -161,12 +160,12 @@ cParsedNBT::cParsedNBT(const char * a_Data, size_t a_Length) :
eNBTParseError cParsedNBT::Parse(void)
{
- if (m_Length < 3)
+ if (m_Data.size() < 3)
{
// Data too short
return eNBTParseError::npNeedBytes;
}
- if (m_Data[0] != TAG_Compound)
+ if (m_Data[0] != std::byte(TAG_Compound))
{
// The top-level tag must be a Compound
return eNBTParseError::npNoTopLevelCompound;
@@ -190,7 +189,7 @@ eNBTParseError cParsedNBT::ReadString(size_t & a_StringStart, size_t & a_StringL
{
NEEDBYTES(2, eNBTParseError::npStringMissingLength);
a_StringStart = m_Pos + 2;
- a_StringLen = static_cast<size_t>(GetBEShort(m_Data + m_Pos));
+ a_StringLen = static_cast<size_t>(GetBEShort(m_Data.data() + m_Pos));
NEEDBYTES(2 + a_StringLen, eNBTParseError::npStringInvalidLength);
m_Pos += 2 + a_StringLen;
return eNBTParseError::npSuccess;
@@ -210,8 +209,8 @@ eNBTParseError cParsedNBT::ReadCompound(void)
for (;;)
{
NEEDBYTES(1, eNBTParseError::npCompoundImbalancedTag);
- const char TagTypeNum = m_Data[m_Pos];
- if ((TagTypeNum < TAG_Min) || (TagTypeNum > TAG_Max))
+ const auto TagTypeNum = m_Data[m_Pos];
+ if ((TagTypeNum < std::byte(TAG_Min)) || (TagTypeNum > std::byte(TAG_Max)))
{
return eNBTParseError::npUnknownTag;
}
@@ -248,10 +247,10 @@ eNBTParseError cParsedNBT::ReadList(eTagType a_ChildrenType)
// Read the count:
NEEDBYTES(4, eNBTParseError::npListMissingLength);
- int Count = GetBEInt(m_Data + m_Pos);
+ int Count = GetBEInt(m_Data.data() + m_Pos);
m_Pos += 4;
auto MinChildSize = GetMinTagSize(a_ChildrenType);
- if ((Count < 0) || (Count > static_cast<int>((m_Length - m_Pos) / MinChildSize)))
+ if ((Count < 0) || (Count > static_cast<int>((m_Data.size() - m_Pos) / MinChildSize)))
{
return eNBTParseError::npListInvalidLength;
}
@@ -312,7 +311,7 @@ eNBTParseError cParsedNBT::ReadTag(void)
case TAG_ByteArray:
{
NEEDBYTES(4, eNBTParseError::npArrayMissingLength);
- int len = GetBEInt(m_Data + m_Pos);
+ int len = GetBEInt(m_Data.data() + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -344,7 +343,7 @@ eNBTParseError cParsedNBT::ReadTag(void)
case TAG_IntArray:
{
NEEDBYTES(4, eNBTParseError::npArrayMissingLength);
- int len = GetBEInt(m_Data + m_Pos);
+ int len = GetBEInt(m_Data.data() + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -392,7 +391,7 @@ int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLen
{
if (
(m_Tags[static_cast<size_t>(Child)].m_NameLength == a_NameLength) &&
- (memcmp(m_Data + m_Tags[static_cast<size_t>(Child)].m_NameStart, a_Name, a_NameLength) == 0)
+ (memcmp(m_Data.data() + m_Tags[static_cast<size_t>(Child)].m_NameStart, a_Name, a_NameLength) == 0)
)
{
return Child;
@@ -470,9 +469,9 @@ cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
m_CurrentStack(0)
{
m_Stack[0].m_Type = TAG_Compound;
- m_Result.reserve(100 * 1024);
- m_Result.push_back(TAG_Compound);
- WriteString(a_RootTagName.data(), static_cast<UInt16>(a_RootTagName.size()));
+ m_Result.reserve(100 KiB);
+ m_Result.push_back(std::byte(TAG_Compound));
+ WriteString(a_RootTagName);
}
@@ -502,7 +501,7 @@ void cFastNBTWriter::EndCompound(void)
ASSERT(m_CurrentStack > 0);
ASSERT(IsStackTopCompound());
- m_Result.push_back(TAG_End);
+ m_Result.push_back(std::byte(TAG_End));
--m_CurrentStack;
}
@@ -520,8 +519,8 @@ void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
TagCommon(a_Name, TAG_List);
- m_Result.push_back(static_cast<char>(a_ChildrenType));
- m_Result.append(4, static_cast<char>(0));
+ m_Result.push_back(std::byte(a_ChildrenType));
+ m_Result.append(4, std::byte(0));
++m_CurrentStack;
m_Stack[m_CurrentStack].m_Type = TAG_List;
@@ -540,7 +539,7 @@ void cFastNBTWriter::EndList(void)
ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);
// Update the list count:
- SetBEInt(const_cast<char *>(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);
+ SetBEInt(m_Result.data() + m_Stack[m_CurrentStack].m_Pos, m_Stack[m_CurrentStack].m_Count);
--m_CurrentStack;
}
@@ -552,7 +551,7 @@ void cFastNBTWriter::EndList(void)
void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
{
TagCommon(a_Name, TAG_Byte);
- m_Result.push_back(static_cast<char>(a_Value));
+ m_Result.push_back(std::byte(a_Value));
}
@@ -563,7 +562,7 @@ void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
TagCommon(a_Name, TAG_Short);
UInt16 Value = htons(static_cast<UInt16>(a_Value));
- m_Result.append(reinterpret_cast<const char *>(&Value), 2);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Value), 2);
}
@@ -574,7 +573,7 @@ void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
TagCommon(a_Name, TAG_Int);
UInt32 Value = htonl(static_cast<UInt32>(a_Value));
- m_Result.append(reinterpret_cast<const char *>(&Value), 4);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Value), 4);
}
@@ -585,7 +584,7 @@ void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
TagCommon(a_Name, TAG_Long);
UInt64 Value = HostToNetwork8(&a_Value);
- m_Result.append(reinterpret_cast<const char *>(&Value), 8);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Value), 8);
}
@@ -596,7 +595,7 @@ void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
TagCommon(a_Name, TAG_Float);
UInt32 Value = HostToNetwork4(&a_Value);
- m_Result.append(reinterpret_cast<const char *>(&Value), 4);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Value), 4);
}
@@ -607,7 +606,7 @@ void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
TagCommon(a_Name, TAG_Double);
UInt64 Value = HostToNetwork8(&a_Value);
- m_Result.append(reinterpret_cast<const char *>(&Value), 8);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Value), 8);
}
@@ -618,8 +617,8 @@ void cFastNBTWriter::AddString(const AString & a_Name, const std::string_view a_
{
TagCommon(a_Name, TAG_String);
const UInt16 Length = htons(static_cast<UInt16>(a_Value.size()));
- m_Result.append(reinterpret_cast<const char *>(&Length), sizeof(Length));
- m_Result.append(a_Value);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Length), sizeof(Length));
+ m_Result.append({ reinterpret_cast<const std::byte *>(a_Value.data()), a_Value.size() });
}
@@ -630,8 +629,8 @@ void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value,
{
TagCommon(a_Name, TAG_ByteArray);
UInt32 len = htonl(static_cast<UInt32>(a_NumElements));
- m_Result.append(reinterpret_cast<const char *>(&len), 4);
- m_Result.append(a_Value, a_NumElements);
+ m_Result.append(reinterpret_cast<const std::byte *>(&len), 4);
+ m_Result.append(reinterpret_cast<const std::byte *>(a_Value), a_NumElements);
}
@@ -648,11 +647,11 @@ void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value,
{
m_Result.reserve(size + 4 + (a_NumElements * 4));
}
- m_Result.append(reinterpret_cast<const char *>(&len), 4);
+ m_Result.append(reinterpret_cast<const std::byte *>(&len), sizeof(len));
for (size_t i = 0; i < a_NumElements; i++)
{
UInt32 Element = htonl(static_cast<UInt32>(a_Value[i]));
- m_Result.append(reinterpret_cast<const char *>(&Element), 4);
+ m_Result.append(reinterpret_cast<const std::byte *>(&Element), sizeof(Element));
}
}
@@ -663,20 +662,17 @@ void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value,
void cFastNBTWriter::Finish(void)
{
ASSERT(m_CurrentStack == 0);
- m_Result.push_back(TAG_End);
+ m_Result.push_back(std::byte(TAG_End));
}
-void cFastNBTWriter::WriteString(const char * a_Data, UInt16 a_Length)
+void cFastNBTWriter::WriteString(const std::string_view a_Data)
{
- UInt16 Len = htons(a_Length);
- m_Result.append(reinterpret_cast<const char *>(&Len), 2);
- m_Result.append(a_Data, a_Length);
+ // TODO check size <= short max
+ UInt16 Len = htons(static_cast<unsigned short>(a_Data.size()));
+ m_Result.append(reinterpret_cast<const std::byte *>(&Len), sizeof(Len));
+ m_Result.append(reinterpret_cast<const std::byte *>(a_Data.data()), a_Data.size());
}
-
-
-
-
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index 257115fe1..0df520e21 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -152,7 +152,7 @@ Each primitive tag also stores the length of the contained data, in bytes.
class cParsedNBT
{
public:
- cParsedNBT(const char * a_Data, size_t a_Length);
+ cParsedNBT(ContiguousByteBufferView a_Data);
bool IsValid(void) const { return (m_Error == eNBTParseError::npSuccess); }
@@ -179,7 +179,7 @@ public:
/** Returns the length of the tag's data, in bytes.
Not valid for Compound or List tags! */
- size_t GetDataLength (int a_Tag) const
+ size_t GetDataLength(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type != TAG_List);
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type != TAG_Compound);
@@ -188,11 +188,11 @@ public:
/** Returns the data stored in this tag.
Not valid for Compound or List tags! */
- const char * GetData(int a_Tag) const
+ const std::byte * GetData(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type != TAG_List);
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type != TAG_Compound);
- return m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart;
+ return m_Data.data() + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart;
}
/** Returns the direct child tag of the specified name, or -1 if no such tag. */
@@ -227,21 +227,21 @@ public:
inline Int16 GetShort(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Short);
- return GetBEShort(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart);
+ return GetBEShort(GetData(a_Tag));
}
/** Returns the value stored in an Int tag. Not valid for any other tag type. */
inline Int32 GetInt(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Int);
- return GetBEInt(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart);
+ return GetBEInt(GetData(a_Tag));
}
/** Returns the value stored in a Long tag. Not valid for any other tag type. */
inline Int64 GetLong(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Long);
- return NetworkToHostLong8(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart);
+ return NetworkToHostLong8(GetData(a_Tag));
}
/** Returns the value stored in a Float tag. Not valid for any other tag type. */
@@ -256,7 +256,7 @@ public:
UNUSED_VAR(Check1);
UNUSED_VAR(Check2);
- Int32 i = GetBEInt(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart);
+ Int32 i = GetBEInt(GetData(a_Tag));
float f;
memcpy(&f, &i, sizeof(f));
return f;
@@ -273,29 +273,33 @@ public:
UNUSED_VAR(Check2);
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Double);
- return NetworkToHostDouble8(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart);
+ return NetworkToHostDouble8(GetData(a_Tag));
}
/** Returns the value stored in a String tag. Not valid for any other tag type. */
inline AString GetString(int a_Tag) const
{
+ return AString(GetStringView(a_Tag));
+ }
+
+ /** Returns the value stored in a String tag. Not valid for any other tag type. */
+ inline std::string_view GetStringView(int a_Tag) const
+ {
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_String);
- AString res;
- res.assign(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_DataStart, static_cast<size_t>(m_Tags[static_cast<size_t>(a_Tag)].m_DataLength));
- return res;
+ return { reinterpret_cast<const char *>(GetData(a_Tag)), GetDataLength(a_Tag) };
}
/** Returns the tag's name. For tags that are not named, returns an empty string. */
inline AString GetName(int a_Tag) const
{
AString res;
- res.assign(m_Data + m_Tags[static_cast<size_t>(a_Tag)].m_NameStart, static_cast<size_t>(m_Tags[static_cast<size_t>(a_Tag)].m_NameLength));
+ res.assign(reinterpret_cast<const char *>(m_Data.data()) + m_Tags[static_cast<size_t>(a_Tag)].m_NameStart, static_cast<size_t>(m_Tags[static_cast<size_t>(a_Tag)].m_NameLength));
return res;
}
protected:
- const char * m_Data;
- size_t m_Length;
+
+ ContiguousByteBufferView m_Data;
std::vector<cFastNBTTag> m_Tags;
eNBTParseError m_Error; // npSuccess if parsing succeeded
@@ -343,7 +347,7 @@ public:
AddByteArray(a_Name, a_Value.data(), a_Value.size());
}
- const AString & GetResult(void) const {return m_Result; }
+ ContiguousByteBufferView GetResult(void) const { return m_Result; }
void Finish(void);
@@ -363,11 +367,11 @@ protected:
sParent m_Stack[MAX_STACK];
int m_CurrentStack;
- AString m_Result;
+ ContiguousByteBuffer m_Result;
bool IsStackTopCompound(void) const { return (m_Stack[m_CurrentStack].m_Type == TAG_Compound); }
- void WriteString(const char * a_Data, UInt16 a_Length);
+ void WriteString(std::string_view a_Data);
inline void TagCommon(const AString & a_Name, eTagType a_Type)
{
@@ -377,8 +381,8 @@ protected:
if (IsStackTopCompound())
{
// Compound: add the type and name:
- m_Result.push_back(static_cast<char>(a_Type));
- WriteString(a_Name.c_str(), static_cast<UInt16>(a_Name.length()));
+ m_Result.push_back(std::byte(a_Type));
+ WriteString(a_Name);
}
else
{
@@ -387,7 +391,3 @@ protected:
}
}
} ;
-
-
-
-
diff --git a/src/WorldStorage/FireworksSerializer.cpp b/src/WorldStorage/FireworksSerializer.cpp
index 7cf3c3eea..fa411b4e9 100644
--- a/src/WorldStorage/FireworksSerializer.cpp
+++ b/src/WorldStorage/FireworksSerializer.cpp
@@ -105,7 +105,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
continue;
}
- const char * ColourData = (a_NBT.GetData(explosiontag));
+ const auto * ColourData = (a_NBT.GetData(explosiontag));
for (size_t i = 0; i < DataLength; i += 4)
{
a_FireworkItem.m_Colours.push_back(GetBEInt(ColourData + i));
@@ -121,7 +121,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
continue;
}
- const char * FadeColourData = (a_NBT.GetData(explosiontag));
+ const auto * FadeColourData = (a_NBT.GetData(explosiontag));
for (size_t i = 0; i < DataLength; i += 4)
{
a_FireworkItem.m_FadeColours.push_back(GetBEInt(FadeColourData + i));
diff --git a/src/WorldStorage/MapSerializer.cpp b/src/WorldStorage/MapSerializer.cpp
index d030b5a32..40d428dab 100644
--- a/src/WorldStorage/MapSerializer.cpp
+++ b/src/WorldStorage/MapSerializer.cpp
@@ -4,8 +4,7 @@
#include "Globals.h"
#include "MapSerializer.h"
-#include "../StringCompression.h"
-#include "zlib/zlib.h"
+#include "OSSupport/GZipFile.h"
#include "FastNBT.h"
#include "../Map.h"
@@ -32,22 +31,9 @@ cMapSerializer::cMapSerializer(const AString & a_WorldName, cMap * a_Map):
bool cMapSerializer::Load(void)
{
- AString Data = cFile::ReadWholeFile(m_Path);
- if (Data.empty())
- {
- return false;
- }
+ const auto Data = GZipFile::ReadRestOfFile(m_Path);
+ const cParsedNBT NBT(Data.GetView());
- AString Uncompressed;
- int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed);
-
- if (res != Z_OK)
- {
- return false;
- }
-
- // Parse the NBT data:
- cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
if (!NBT.IsValid())
{
// NBT Parsing failed
@@ -64,32 +50,15 @@ bool cMapSerializer::Load(void)
bool cMapSerializer::Save(void)
{
cFastNBTWriter Writer;
-
SaveMapToNBT(Writer);
-
Writer.Finish();
#ifdef _DEBUG
- cParsedNBT TestParse(Writer.GetResult().data(), Writer.GetResult().size());
+ cParsedNBT TestParse(Writer.GetResult());
ASSERT(TestParse.IsValid());
#endif // _DEBUG
- cFile File;
- if (!File.Open(m_Path, cFile::fmWrite))
- {
- return false;
- }
-
- AString Compressed;
- int res = CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
-
- if (res != Z_OK)
- {
- return false;
- }
-
- File.Write(Compressed.data(), Compressed.size());
- File.Close();
+ GZipFile::Write(m_Path, Writer.GetResult());
return true;
}
@@ -225,7 +194,7 @@ bool cIDCountSerializer::Load(void)
// NOTE: idcounts.dat is not compressed (raw format)
// Parse the NBT data:
- cParsedNBT NBT(Data.data(), Data.size());
+ cParsedNBT NBT({ reinterpret_cast<const std::byte *>(Data.data()), Data.size() });
if (!NBT.IsValid())
{
// NBT Parsing failed
@@ -261,7 +230,7 @@ bool cIDCountSerializer::Save(void)
Writer.Finish();
#ifdef _DEBUG
- cParsedNBT TestParse(Writer.GetResult().data(), Writer.GetResult().size());
+ cParsedNBT TestParse(Writer.GetResult());
ASSERT(TestParse.IsValid());
#endif // _DEBUG
@@ -278,11 +247,3 @@ bool cIDCountSerializer::Save(void)
return true;
}
-
-
-
-
-
-
-
-
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 0e3cdde76..2542cd2da 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -1177,17 +1177,14 @@ public:
////////////////////////////////////////////////////////////////////////////////
// NBTChunkSerializer:
-bool NBTChunkSerializer::serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter)
+void NBTChunkSerializer::Serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter)
{
SerializerCollector serializer(aWriter);
aWriter.BeginCompound("Level");
aWriter.AddInt("xPos", aCoords.m_ChunkX);
aWriter.AddInt("zPos", aCoords.m_ChunkZ);
- if (!aWorld.GetChunkData(aCoords, serializer))
- {
- aWriter.EndCompound(); // "Level"
- return false;
- }
+ [[maybe_unused]] const bool Result = aWorld.GetChunkData(aCoords, serializer); // Chunk must be present in order to save
+ ASSERT(Result);
serializer.Finish(); // Close NBT tags
// Save biomes, both MCS (IntArray) and MC-vanilla (ByteArray):
@@ -1240,5 +1237,4 @@ bool NBTChunkSerializer::serialize(const cWorld & aWorld, cChunkCoords aCoords,
aWriter.AddByte("TerrainPopulated", 1);
aWriter.EndCompound(); // "Level"
- return true;
}
diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h
index aeac9fc46..c2de79269 100644
--- a/src/WorldStorage/NBTChunkSerializer.h
+++ b/src/WorldStorage/NBTChunkSerializer.h
@@ -21,7 +21,6 @@ class NBTChunkSerializer
{
public:
- /** Serializes the chunk into the specified writer.
- Returns true on success, false on failure (chunk not present etc.) */
- static bool serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter);
+ /** Serializes the chunk into the specified writer. The chunk must be present. */
+ static void Serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter);
};
diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp
index 44ce7ca9b..656a98709 100644
--- a/src/WorldStorage/SchematicFileSerializer.cpp
+++ b/src/WorldStorage/SchematicFileSerializer.cpp
@@ -7,7 +7,6 @@
#include "FastNBT.h"
#include "SchematicFileSerializer.h"
-#include "../StringCompression.h"
#include "../OSSupport/GZipFile.h"
@@ -17,118 +16,59 @@
////////////////////////////////////////////////////////////////////////////////
// cSchematicFileSerializer:
-bool cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName)
+void cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const std::string & a_FileName)
{
- // Un-GZip the contents:
- AString Contents;
- cGZipFile File;
- if (!File.Open(a_FileName, cGZipFile::fmRead))
- {
- LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str());
- return false;
- }
- int NumBytesRead = File.ReadRestOfFile(Contents);
- if (NumBytesRead < 0)
- {
- LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead);
- return false;
- }
- File.Close();
+ const auto Data = GZipFile::ReadRestOfFile(a_FileName);
+ const cParsedNBT NBT(Data.GetView());
- // Parse the NBT:
- cParsedNBT NBT(Contents.data(), Contents.size());
if (!NBT.IsValid())
{
- LOG("Cannot parse the NBT in the schematic file \"%s\".", a_FileName.c_str());
- return false;
+ throw std::runtime_error(fmt::format("Cannot parse the NBT in the schematic file \"{}\".", a_FileName));
}
- return LoadFromSchematicNBT(a_BlockArea, NBT);
+ LoadFromSchematicNBT(a_BlockArea, NBT);
}
-bool cSchematicFileSerializer::LoadFromSchematicString(cBlockArea & a_BlockArea, const AString & a_SchematicData)
+void cSchematicFileSerializer::LoadFromSchematicString(cBlockArea & a_BlockArea, const ContiguousByteBufferView a_SchematicData)
{
- // Uncompress the data:
- AString UngzippedData;
- if (UncompressStringGZIP(a_SchematicData.data(), a_SchematicData.size(), UngzippedData) != Z_OK)
- {
- LOG("%s: Cannot unGZip the schematic data.", __FUNCTION__);
- return false;
- }
+ const auto Extracted = Compression::Extractor().ExtractGZip(a_SchematicData);
+ const cParsedNBT NBT(Extracted.GetView());
- // Parse the NBT:
- cParsedNBT NBT(UngzippedData.data(), UngzippedData.size());
if (!NBT.IsValid())
{
- LOG("%s: Cannot parse the NBT in the schematic data.", __FUNCTION__);
- return false;
+ throw std::runtime_error("Cannot parse the NBT in the schematic data.");
}
- return LoadFromSchematicNBT(a_BlockArea, NBT);
+ LoadFromSchematicNBT(a_BlockArea, NBT);
}
-bool cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName)
+void cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockArea, const std::string & a_FileName)
{
- // Serialize into NBT data:
- AString NBT = SaveToSchematicNBT(a_BlockArea);
- if (NBT.empty())
- {
- LOG("%s: Cannot serialize the area into an NBT representation for file \"%s\".", __FUNCTION__, a_FileName.c_str());
- return false;
- }
-
- // Save to file
- cGZipFile File;
- if (!File.Open(a_FileName, cGZipFile::fmWrite))
- {
- LOG("%s: Cannot open file \"%s\" for writing.", __FUNCTION__, a_FileName.c_str());
- return false;
- }
- if (!File.Write(NBT))
- {
- LOG("%s: Cannot write data to file \"%s\".", __FUNCTION__, a_FileName.c_str());
- return false;
- }
- return true;
+ GZipFile::Write(a_FileName, SaveToSchematicNBT(a_BlockArea));
}
-bool cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea, AString & a_Out)
+Compression::Result cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea)
{
- // Serialize into NBT data:
- AString NBT = SaveToSchematicNBT(a_BlockArea);
- if (NBT.empty())
- {
- LOG("%s: Cannot serialize the area into an NBT representation.", __FUNCTION__);
- return false;
- }
-
- // Gzip the data:
- int res = CompressStringGZIP(NBT.data(), NBT.size(), a_Out);
- if (res != Z_OK)
- {
- LOG("%s: Cannot Gzip the area data NBT representation: %d", __FUNCTION__, res);
- return false;
- }
- return true;
+ return Compression::Compressor().CompressGZip(SaveToSchematicNBT(a_BlockArea));
}
-bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cParsedNBT & a_NBT)
+void cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, const cParsedNBT & a_NBT)
{
int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials");
if ((TMaterials > 0) && (a_NBT.GetType(TMaterials) == TAG_String))
@@ -136,8 +76,7 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP
AString Materials = a_NBT.GetString(TMaterials);
if (Materials.compare("Alpha") != 0)
{
- LOG("Materials tag is present and \"%s\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials.c_str());
- return false;
+ throw std::runtime_error(fmt::format("Materials tag is present and \"{}\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials));
}
}
int TSizeX = a_NBT.FindChildByName(a_NBT.GetRoot(), "Width");
@@ -150,13 +89,13 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP
(a_NBT.GetType(TSizeZ) != TAG_Short)
)
{
- LOG("Dimensions are missing from the schematic file (%d, %d, %d), (%d, %d, %d)",
+ throw std::runtime_error(fmt::format(
+ "Dimensions are missing from the schematic file ({}, {}, {}), ({}, {}, {})",
TSizeX, TSizeY, TSizeZ,
(TSizeX >= 0) ? a_NBT.GetType(TSizeX) : -1,
(TSizeY >= 0) ? a_NBT.GetType(TSizeY) : -1,
(TSizeZ >= 0) ? a_NBT.GetType(TSizeZ) : -1
- );
- return false;
+ ));
}
int SizeX = a_NBT.GetShort(TSizeX);
@@ -164,16 +103,14 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP
int SizeZ = a_NBT.GetShort(TSizeZ);
if ((SizeX < 1) || (SizeX > 65535) || (SizeY < 1) || (SizeY > 65535) || (SizeZ < 1) || (SizeZ > 65535))
{
- LOG("Dimensions are invalid in the schematic file: %d, %d, %d", SizeX, SizeY, SizeZ);
- return false;
+ throw std::runtime_error(fmt::format("Dimensions are invalid in the schematic file: {}, {}, {}", SizeX, SizeY, SizeZ));
}
int TBlockTypes = a_NBT.FindChildByName(a_NBT.GetRoot(), "Blocks");
int TBlockMetas = a_NBT.FindChildByName(a_NBT.GetRoot(), "Data");
if ((TBlockTypes < 0) || (a_NBT.GetType(TBlockTypes) != TAG_ByteArray))
{
- LOG("BlockTypes are invalid in the schematic file: %d", TBlockTypes);
- return false;
+ throw std::runtime_error(fmt::format("BlockTypes are invalid in the schematic file: {}", TBlockTypes));
}
bool AreMetasPresent = (TBlockMetas > 0) && (a_NBT.GetType(TBlockMetas) == TAG_ByteArray);
@@ -222,15 +159,13 @@ bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, cP
}
memcpy(a_BlockArea.GetBlockMetas(), a_NBT.GetData(TBlockMetas), NumMetaBytes);
}
-
- return true;
}
-AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea)
+ContiguousByteBuffer cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea)
{
cFastNBTWriter Writer("Schematic");
Writer.AddShort("Width", static_cast<Int16>(a_BlockArea.m_Size.x));
@@ -267,9 +202,5 @@ AString cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockA
Writer.EndList();
Writer.Finish();
- return Writer.GetResult();
+ return ContiguousByteBuffer(Writer.GetResult());
}
-
-
-
-
diff --git a/src/WorldStorage/SchematicFileSerializer.h b/src/WorldStorage/SchematicFileSerializer.h
index 6aaa0662f..d52f80da1 100644
--- a/src/WorldStorage/SchematicFileSerializer.h
+++ b/src/WorldStorage/SchematicFileSerializer.h
@@ -10,6 +10,7 @@
#pragma once
#include "../BlockArea.h"
+#include "../StringCompression.h"
@@ -26,29 +27,23 @@ class cSchematicFileSerializer
{
public:
- /** Loads an area from a .schematic file. Returns true if successful. */
- static bool LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName);
+ /** Loads an area from a .schematic file. */
+ static void LoadFromSchematicFile(cBlockArea & a_BlockArea, const std::string & a_FileName);
- /** Loads an area from a string containing the .schematic file data. Returns true if successful. */
- static bool LoadFromSchematicString(cBlockArea & a_BlockArea, const AString & a_SchematicData);
+ /** Loads an area from a string containing the .schematic file data. */
+ static void LoadFromSchematicString(cBlockArea & a_BlockArea, ContiguousByteBufferView a_SchematicData);
- /** Saves the area into a .schematic file. Returns true if successful. */
- static bool SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName);
+ /** Saves the area into a .schematic file. */
+ static void SaveToSchematicFile(const cBlockArea & a_BlockArea, const std::string & a_FileName);
- /** Saves the area into a string containing the .schematic file data.
- Returns true if successful, false on failure. The data is stored into a_Out. */
- static bool SaveToSchematicString(const cBlockArea & a_BlockArea, AString & a_Out);
+ /** Saves the area into a string containing the .schematic file data. */
+ static Compression::Result SaveToSchematicString(const cBlockArea & a_BlockArea);
private:
- /** Loads the area from a schematic file uncompressed and parsed into a NBT tree.
- Returns true if successful. */
- static bool LoadFromSchematicNBT(cBlockArea & a_BlockArea, cParsedNBT & a_NBT);
-
- /** Saves the area into a NBT representation and returns the NBT data as a string.
- Returns an empty string if failed. */
- static AString SaveToSchematicNBT(const cBlockArea & a_BlockArea);
-};
-
-
+ /** Loads the area from a schematic file uncompressed and parsed into a NBT tree. */
+ static void LoadFromSchematicNBT(cBlockArea & a_BlockArea, const cParsedNBT & a_NBT);
+ /** Saves the area into a NBT representation and returns the NBT data as a string. */
+ static ContiguousByteBuffer SaveToSchematicNBT(const cBlockArea & a_BlockArea);
+};
diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp
index 7b41f92b1..3ad4d42ee 100644
--- a/src/WorldStorage/ScoreboardSerializer.cpp
+++ b/src/WorldStorage/ScoreboardSerializer.cpp
@@ -4,8 +4,7 @@
#include "Globals.h"
#include "ScoreboardSerializer.h"
-#include "../StringCompression.h"
-#include "zlib/zlib.h"
+#include "OSSupport/GZipFile.h"
#include "FastNBT.h"
#include "../Scoreboard.h"
@@ -31,29 +30,24 @@ cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScore
bool cScoreboardSerializer::Load(void)
{
- AString Data = cFile::ReadWholeFile(m_Path);
- if (Data.empty())
+ try
{
- return false;
- }
+ const auto Data = GZipFile::ReadRestOfFile(m_Path);
+ const cParsedNBT NBT(Data.GetView());
- AString Uncompressed;
- int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed);
+ if (!NBT.IsValid())
+ {
+ // NBT Parsing failed
+ return false;
+ }
- if (res != Z_OK)
- {
- return false;
+ return LoadScoreboardFromNBT(NBT);
}
-
- // Parse the NBT data:
- cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
- if (!NBT.IsValid())
+ catch (const std::exception & Oops)
{
- // NBT Parsing failed
+ LOGWARNING("Failed to load scoreboard from \"%s\": %s", m_Path.c_str(), Oops.what());
return false;
}
-
- return LoadScoreboardFromNBT(NBT);
}
@@ -63,32 +57,15 @@ bool cScoreboardSerializer::Load(void)
bool cScoreboardSerializer::Save(void)
{
cFastNBTWriter Writer;
-
SaveScoreboardToNBT(Writer);
-
Writer.Finish();
- #ifdef _DEBUG
- cParsedNBT TestParse(Writer.GetResult().data(), Writer.GetResult().size());
+#ifdef _DEBUG
+ cParsedNBT TestParse(Writer.GetResult());
ASSERT(TestParse.IsValid());
- #endif // _DEBUG
-
- cFile File;
- if (!File.Open(m_Path, cFile::fmWrite))
- {
- return false;
- }
-
- AString Compressed;
- int res = CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
-
- if (res != Z_OK)
- {
- return false;
- }
+#endif // _DEBUG
- File.Write(Compressed.data(), Compressed.size());
- File.Close();
+ GZipFile::Write(m_Path, Writer.GetResult());
return true;
}
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 0e874df7c..78320d636 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -8,8 +8,8 @@
#include "NBTChunkSerializer.h"
#include "EnchantmentSerializer.h"
#include "NamespaceSerializer.h"
-#include "zlib/zlib.h"
#include "json/json.h"
+#include "OSSupport/GZipFile.h"
#include "../World.h"
#include "../Item.h"
#include "../ItemGrid.h"
@@ -86,7 +86,7 @@ Since only the header is actually in the memory, this number can be high, but st
cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
Super(a_World),
- m_CompressionFactor(a_CompressionFactor)
+ m_Compressor(a_CompressionFactor)
{
// Create a level.dat file for mapping tools, if it doesn't already exist:
AString fnam;
@@ -117,12 +117,7 @@ cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
Writer.EndCompound();
Writer.Finish();
- gzFile gz = gzopen((fnam).c_str(), "wb");
- if (gz != nullptr)
- {
- gzwrite(gz, Writer.GetResult().data(), static_cast<unsigned>(Writer.GetResult().size()));
- }
- gzclose(gz);
+ GZipFile::Write(fnam, Writer.GetResult());
}
}
@@ -145,7 +140,7 @@ cWSSAnvil::~cWSSAnvil()
bool cWSSAnvil::LoadChunk(const cChunkCoords & a_Chunk)
{
- AString ChunkData;
+ ContiguousByteBuffer ChunkData;
if (!GetChunkData(a_Chunk, ChunkData))
{
// The reason for failure is already printed in GetChunkData()
@@ -161,15 +156,17 @@ bool cWSSAnvil::LoadChunk(const cChunkCoords & a_Chunk)
bool cWSSAnvil::SaveChunk(const cChunkCoords & a_Chunk)
{
- AString ChunkData;
- if (!SaveChunkToData(a_Chunk, ChunkData))
+ try
{
- LOGWARNING("Cannot serialize chunk [%d, %d] into data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
+ if (!SetChunkData(a_Chunk, SaveChunkToData(a_Chunk).GetView()))
+ {
+ LOGWARNING("Cannot store chunk [%d, %d] data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ return false;
+ }
}
- if (!SetChunkData(a_Chunk, ChunkData))
+ catch (const std::exception & Oops)
{
- LOGWARNING("Cannot store chunk [%d, %d] data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ LOGWARNING("Cannot serialize chunk [%d, %d] into data: %s", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Oops.what());
return false;
}
@@ -181,7 +178,7 @@ bool cWSSAnvil::SaveChunk(const cChunkCoords & a_Chunk)
-void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, const AString & a_ChunkDataToSave)
+void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, const ContiguousByteBufferView a_ChunkDataToSave)
{
// Construct the filename for offloading:
AString OffloadFileName;
@@ -202,7 +199,7 @@ void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Re
// Log the warning to console:
const int RegionX = FAST_FLOOR_DIV(a_ChunkX, 32);
const int RegionZ = FAST_FLOOR_DIV(a_ChunkZ, 32);
- AString Info = Printf("Loading chunk [%d, %d] for world %s from file r.%d.%d.mca failed: %s. Offloading old chunk data to file %s and regenerating chunk.",
+ AString Info = Printf("Loading chunk [%d, %d] for world %s from file r.%d.%d.mca failed: %s Offloading old chunk data to file %s and regenerating chunk.",
a_ChunkX, a_ChunkZ, m_World->GetName().c_str(), RegionX, RegionZ, a_Reason.c_str(), OffloadFileName.c_str()
);
LOGWARNING("%s", Info.c_str());
@@ -231,7 +228,7 @@ void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Re
-bool cWSSAnvil::GetChunkData(const cChunkCoords & a_Chunk, AString & a_Data)
+bool cWSSAnvil::GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data)
{
cCSLock Lock(m_CS);
cMCAFile * File = LoadMCAFile(a_Chunk);
@@ -246,7 +243,7 @@ bool cWSSAnvil::GetChunkData(const cChunkCoords & a_Chunk, AString & a_Data)
-bool cWSSAnvil::SetChunkData(const cChunkCoords & a_Chunk, const AString & a_Data)
+bool cWSSAnvil::SetChunkData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data)
{
cCSLock Lock(m_CS);
cMCAFile * File = LoadMCAFile(a_Chunk);
@@ -314,55 +311,47 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
-bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data)
+bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data)
{
- // Uncompress the data:
- AString Uncompressed;
- int res = InflateString(a_Data.data(), a_Data.size(), Uncompressed);
- if (res != Z_OK)
+ try
{
- LOGWARNING("Uncompressing chunk [%d, %d] failed: %d", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, res);
- ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "InflateString() failed", a_Data);
- return false;
- }
+ const auto Extracted = m_Extractor.ExtractZLib(a_Data);
+ cParsedNBT NBT(Extracted.GetView());
- // Parse the NBT data:
- cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
- if (!NBT.IsValid())
+ if (!NBT.IsValid())
+ {
+ // NBT Parsing failed:
+ throw std::runtime_error(fmt::format("NBT parsing failed. {} at position {}.", NBT.GetErrorCode().message(), NBT.GetErrorPos()));
+ }
+
+ // Load the data from NBT:
+ return LoadChunkFromNBT(a_Chunk, NBT, a_Data);
+ }
+ catch (const std::exception & Oops)
{
- // NBT Parsing failed
- auto msg = fmt::format("NBT parsing failed: {}, pos {}", NBT.GetErrorCode().message(), NBT.GetErrorPos());
- ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, msg, a_Data);
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Oops.what(), a_Data);
return false;
}
-
- // Load the data from NBT:
- return LoadChunkFromNBT(a_Chunk, NBT, a_Data);
}
-bool cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk, AString & a_Data)
+Compression::Result cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk)
{
cFastNBTWriter Writer;
- if (!SaveChunkToNBT(a_Chunk, Writer))
- {
- LOGWARNING("Cannot save chunk [%d, %d] to NBT", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
- return false;
- }
+ NBTChunkSerializer::Serialize(*m_World, a_Chunk, Writer);
Writer.Finish();
- CompressString(Writer.GetResult().data(), Writer.GetResult().size(), a_Data, m_CompressionFactor);
- return true;
+ return m_Compressor.CompressZLib(Writer.GetResult());
}
-bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, const AString & a_RawChunkData)
+bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, const ContiguousByteBufferView a_RawChunkData)
{
// The data arrays, in MCA-native y / z / x ordering (will be reordered for the final chunk data)
cChunkDef::BlockTypes BlockTypes;
@@ -496,20 +485,6 @@ void cWSSAnvil::CopyNBTData(const cParsedNBT & a_NBT, int a_Tag, const AString &
-bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_Writer)
-{
- if (!NBTChunkSerializer::serialize(*m_World, a_Chunk, a_Writer))
- {
- LOGWARNING("Failed to save chunk %s.", a_Chunk.ToString());
- return false;
- }
- return true;
-}
-
-
-
-
-
cChunkDef::BiomeMap * cWSSAnvil::LoadVanillaBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx)
{
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_ByteArray))
@@ -549,7 +524,7 @@ cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_Bio
// The biomes stored don't match in size
return nullptr;
}
- const char * BiomeData = (a_NBT.GetData(a_TagIdx));
+ const auto * BiomeData = a_NBT.GetData(a_TagIdx);
for (size_t i = 0; i < ARRAYCOUNT(*a_BiomeMap); i++)
{
(*a_BiomeMap)[i] = static_cast<EMCSBiome>(GetBEInt(&BiomeData[i * 4]));
@@ -587,7 +562,7 @@ void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entities, const cParsedNBT &
try
{
- LoadEntityFromNBT(a_Entities, a_NBT, Child, a_NBT.GetData(sID), a_NBT.GetDataLength(sID));
+ LoadEntityFromNBT(a_Entities, a_NBT, Child, a_NBT.GetStringView(sID));
}
catch (...)
{
@@ -690,14 +665,9 @@ OwnedBlockEntity cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int
// All the other blocktypes should have no entities assigned to them. Report an error:
// Get the "id" tag:
int TagID = a_NBT.FindChildByName(a_Tag, "id");
- AString TypeName("<unknown>");
- if (TagID >= 0)
- {
- TypeName.assign(a_NBT.GetData(TagID), static_cast<size_t>(a_NBT.GetDataLength(TagID)));
- }
FLOGINFO("WorldLoader({0}): Block entity mismatch: block type {1} ({2}), type \"{3}\", at {4}; the entity will be lost.",
m_World->GetName(),
- ItemTypeToString(a_BlockType), a_BlockType, TypeName,
+ ItemTypeToString(a_BlockType), a_BlockType, (TagID >= 0) ? a_NBT.GetStringView(TagID) : "unknown",
a_Pos
);
return nullptr;
@@ -887,10 +857,16 @@ bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, con
return false;
}
+ // Check if the "id" tag is a string:
+ if (a_NBT.GetType(TagID) != eTagType::TAG_String)
+ {
+ return false;
+ }
+
// Compare the value:
for (const auto & et: a_ExpectedTypes)
{
- if (strncmp(a_NBT.GetData(TagID), et.c_str(), static_cast<size_t>(a_NBT.GetDataLength(TagID))) == 0)
+ if (a_NBT.GetStringView(TagID) == et)
{
return true;
}
@@ -906,8 +882,7 @@ bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, con
}
FLOGWARNING("Block entity type mismatch: exp {0}, got \"{1}\". The block entity at {2} will lose all its properties.",
expectedTypes.c_str() + 2, // Skip the first ", " that is extra in the string
- AString(a_NBT.GetData(TagID), static_cast<size_t>(a_NBT.GetDataLength(TagID))),
- a_Pos
+ a_NBT.GetStringView(TagID), a_Pos
);
return false;
}
@@ -1364,7 +1339,7 @@ OwnedBlockEntity cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int
int Type = a_NBT.FindChildByName(a_TagIdx, "EntityId");
if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_String))
{
- const auto StatInfo = NamespaceSerializer::SplitNamespacedID(a_NBT.GetString(Type));
+ const auto StatInfo = NamespaceSerializer::SplitNamespacedID(a_NBT.GetStringView(Type));
if (StatInfo.first == NamespaceSerializer::Namespace::Unknown)
{
return nullptr;
@@ -1571,10 +1546,10 @@ OwnedBlockEntity cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagI
-void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, size_t a_IDTagLength)
+void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const std::string_view a_EntityName)
{
typedef void (cWSSAnvil::*EntityLoaderFunc)(cEntityList &, const cParsedNBT &, int a_EntityTagIdx);
- typedef std::map<AString, EntityLoaderFunc> EntityLoaderMap;
+ typedef std::map<std::string_view, EntityLoaderFunc> EntityLoaderMap;
static const EntityLoaderMap EntityTypeToFunction
{
{ "Boat", &cWSSAnvil::LoadBoatFromNBT },
@@ -1624,14 +1599,14 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
// TODO: flatten monster\projectile into one entity type enum
- auto it = EntityTypeToFunction.find(AString(a_IDTag, a_IDTagLength));
+ const auto it = EntityTypeToFunction.find(a_EntityName);
if (it != EntityTypeToFunction.end())
{
(this->*it->second)(a_Entities, a_NBT, a_EntityTagIdx);
return;
}
- const auto StatInfo = NamespaceSerializer::SplitNamespacedID({ a_IDTag, a_IDTagLength });
+ const auto StatInfo = NamespaceSerializer::SplitNamespacedID(a_EntityName);
if (StatInfo.first == NamespaceSerializer::Namespace::Unknown)
{
return;
@@ -3947,7 +3922,7 @@ bool cWSSAnvil::cMCAFile::OpenFile(bool a_IsForReading)
-bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a_Data)
+bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data)
{
if (!OpenFile(true))
{
@@ -3976,21 +3951,21 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
UInt32 ChunkSize = 0;
if (m_File.Read(&ChunkSize, 4) != 4)
{
- m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk size", "");
+ m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk size", {});
return false;
}
ChunkSize = ntohl(ChunkSize);
if (ChunkSize < 1)
{
// Chunk size too small
- m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Chunk size too small", "");
+ m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Chunk size too small", {});
return false;
}
char CompressionType = 0;
if (m_File.Read(&CompressionType, 1) != 1)
{
- m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk compression", "");
+ m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk compression", {});
return false;
}
ChunkSize--;
@@ -4015,7 +3990,7 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
-bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AString & a_Data)
+bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data)
{
if (!OpenFile(false))
{
@@ -4034,7 +4009,7 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
LocalZ = 32 + LocalZ;
}
- unsigned ChunkSector = FindFreeLocation(LocalX, LocalZ, a_Data);
+ unsigned ChunkSector = FindFreeLocation(LocalX, LocalZ, a_Data.size());
// Store the chunk data:
m_File.Seek(static_cast<int>(ChunkSector * 4096));
@@ -4103,12 +4078,12 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
-unsigned cWSSAnvil::cMCAFile::FindFreeLocation(int a_LocalX, int a_LocalZ, const AString & a_Data)
+unsigned cWSSAnvil::cMCAFile::FindFreeLocation(int a_LocalX, int a_LocalZ, const size_t a_DataSize)
{
// See if it fits the current location:
unsigned ChunkLocation = ntohl(m_Header[a_LocalX + 32 * a_LocalZ]);
unsigned ChunkLen = ChunkLocation & 0xff;
- if (a_Data.size() + MCA_CHUNK_HEADER_LENGTH <= (ChunkLen * 4096))
+ if (a_DataSize + MCA_CHUNK_HEADER_LENGTH <= (ChunkLen * 4096))
{
return ChunkLocation >> 8;
}
@@ -4126,7 +4101,3 @@ unsigned cWSSAnvil::cMCAFile::FindFreeLocation(int a_LocalX, int a_LocalZ, const
} // for i - m_Header[]
return MaxLocation >> 8;
}
-
-
-
-
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index 6d9b49788..1751c6761 100755
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -11,6 +11,7 @@
#include "../BlockEntities/BlockEntity.h"
#include "WorldStorage.h"
#include "FastNBT.h"
+#include "StringCompression.h"
@@ -62,9 +63,8 @@ protected:
cMCAFile(cWSSAnvil & a_ParentSchema, 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);
+ bool GetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data);
+ bool SetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data);
int GetRegionX (void) const {return m_RegionX; }
int GetRegionZ (void) const {return m_RegionZ; }
@@ -86,8 +86,8 @@ protected:
// Chunk timestamps, following the chunk headers
unsigned m_TimeStamps[MCA_MAX_CHUNKS];
- /** 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);
+ /** Finds a free location large enough to hold a_Data. Returns the sector number. */
+ unsigned FindFreeLocation(int a_LocalX, int a_LocalZ, size_t a_DataSize);
/** Opens a MCA file either for a Read operation (fails if doesn't exist) or for a Write operation (creates new if not found) */
bool OpenFile(bool a_IsForReading);
@@ -97,30 +97,27 @@ protected:
cCriticalSection m_CS;
cMCAFiles m_Files; // a MRU cache of MCA files
- int m_CompressionFactor;
-
+ Compression::Extractor m_Extractor;
+ Compression::Compressor m_Compressor;
/** Reports that the specified chunk failed to load and saves the chunk data to an external file. */
- void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, const AString & a_ChunkDataToSave);
+ void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, ContiguousByteBufferView a_ChunkDataToSave);
/** Gets chunk data from the correct file; locks file CS as needed */
- bool GetChunkData(const cChunkCoords & a_Chunk, AString & a_Data);
+ bool GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data);
/** Sets chunk data into the correct file; locks file CS as needed */
- bool SetChunkData(const cChunkCoords & a_Chunk, const AString & a_Data);
+ bool SetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data);
/** Loads the chunk from the data (no locking needed) */
- bool LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data);
+ bool LoadChunkFromData(const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data);
/** Saves the chunk into datastream (no locking needed) */
- bool SaveChunkToData(const cChunkCoords & a_Chunk, AString & a_Data);
+ Compression::Result SaveChunkToData(const cChunkCoords & a_Chunk);
/** Loads the chunk from NBT data (no locking needed).
a_RawChunkData is the raw (compressed) chunk data, used for offloading when chunk loading fails. */
- bool LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, const AString & a_RawChunkData);
-
- /** Saves the chunk into NBT data using a_Writer; returns true on success */
- bool SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_Writer);
+ bool LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, ContiguousByteBufferView a_RawChunkData);
/** Loads the chunk's biome map from vanilla-format; returns a_BiomeMap if biomes present and valid, nullptr otherwise */
cChunkDef::BiomeMap * LoadVanillaBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -175,7 +172,7 @@ protected:
OwnedBlockEntity LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
- void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, size_t a_IDTagLength);
+ void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, std::string_view a_EntityName);
void LoadBoatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadEnderCrystalFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -309,7 +306,3 @@ protected:
virtual bool SaveChunk(const cChunkCoords & a_Chunk) override;
virtual const AString GetName(void) const override {return "anvil"; }
} ;
-
-
-
-