summaryrefslogtreecommitdiffstats
path: root/src/WorldStorage
diff options
context:
space:
mode:
Diffstat (limited to 'src/WorldStorage')
-rw-r--r--src/WorldStorage/FastNBT.cpp12
-rw-r--r--src/WorldStorage/FastNBT.h1
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp94
-rw-r--r--src/WorldStorage/WSSAnvil.cpp188
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.h17
5 files changed, 171 insertions, 141 deletions
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index d5b9fd0f7..df93e21e4 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -637,6 +637,18 @@ void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value,
+void cFastNBTWriter::AddByteArray(const AString & a_Name, size_t a_NumElements, unsigned char a_Value)
+{
+ TagCommon(a_Name, TAG_ByteArray);
+ UInt32 len = htonl(static_cast<UInt32>(a_NumElements));
+ m_Result.append(reinterpret_cast<const std::byte *>(&len), 4);
+ m_Result.append(a_NumElements, std::byte(a_Value));
+}
+
+
+
+
+
void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value, size_t a_NumElements)
{
TagCommon(a_Name, TAG_IntArray);
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index 0df520e21..d9c388179 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -340,6 +340,7 @@ public:
void AddDouble (const AString & a_Name, double a_Value);
void AddString (const AString & a_Name, std::string_view a_Value);
void AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements);
+ void AddByteArray(const AString & a_Name, size_t a_NumElements, unsigned char a_Value);
void AddIntArray (const AString & a_Name, const Int32 * a_Value, size_t a_NumElements);
void AddByteArray(const AString & a_Name, const AString & a_Value)
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 2542cd2da..714c65a91 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -53,16 +53,14 @@
/** Collects and stores the chunk data via the cChunkDataCallback interface */
-class SerializerCollector:
+class SerializerCollector final :
public cChunkDataCopyCollector
{
public:
// The data collected from the chunk:
- cChunkDef::BiomeMap mBiomes;
- UInt8 mVanillaBiomes[cChunkDef::Width * cChunkDef::Width];
- int mVanillaHeightMap[cChunkDef::Width * cChunkDef::Width];
- bool mBiomesAreValid;
+ UInt8 Biomes[cChunkDef::Width * cChunkDef::Width];
+ int Heights[cChunkDef::Width * cChunkDef::Width];
/** True if a tag has been opened in the callbacks and not yet closed. */
bool mIsTagOpen;
@@ -84,7 +82,6 @@ public:
SerializerCollector(cFastNBTWriter & aWriter):
- mBiomesAreValid(false),
mIsTagOpen(false),
mHasHadEntity(false),
mHasHadBlockEntity(false),
@@ -106,14 +103,13 @@ public:
- virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) override
+ virtual void HeightMap(const cChunkDef::HeightMap & a_HeightMap) override
{
- for (int RelX = 0; RelX < cChunkDef::Width; RelX++)
+ for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++)
{
- for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++)
+ for (int RelX = 0; RelX < cChunkDef::Width; RelX++)
{
- int Height = cChunkDef::GetHeight(*a_HeightMap, RelX, RelZ);
- mVanillaHeightMap[(RelZ << 4) | RelX] = Height;
+ Heights[RelX + RelZ * cChunkDef::Width] = cChunkDef::GetHeight(a_HeightMap, RelX, RelZ);
}
}
}
@@ -122,15 +118,14 @@ public:
- virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override
+ virtual void BiomeMap(const cChunkDef::BiomeMap & a_BiomeMap) override
{
- memcpy(mBiomes, a_BiomeMap, sizeof(mBiomes));
- for (size_t i = 0; i < ARRAYCOUNT(mBiomes); i++)
+ for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
{
- if ((*a_BiomeMap)[i] < 255)
+ if (a_BiomeMap[i] < 255)
{
// Normal MC biome, copy as-is:
- mVanillaBiomes[i] = static_cast<Byte>((*a_BiomeMap)[i]);
+ Biomes[i] = static_cast<Byte>(a_BiomeMap[i]);
}
else
{
@@ -139,7 +134,6 @@ public:
return;
}
} // for i - mBiomeMap[]
- mBiomesAreValid = true;
}
@@ -252,13 +246,6 @@ public:
mWriter.EndList();
}
- // If light not valid, reset it to defaults:
- if (!mIsLightValid)
- {
- m_Data.FillBlockLight(0x00);
- m_Data.FillSkyLight(0x0f);
- }
-
// Check if "Entity" and "TileEntities" lists exists. MCEdit requires this.
if (!mHasHadEntity)
{
@@ -1187,40 +1174,57 @@ void NBTChunkSerializer::Serialize(const cWorld & aWorld, cChunkCoords aCoords,
ASSERT(Result);
serializer.Finish(); // Close NBT tags
- // Save biomes, both MCS (IntArray) and MC-vanilla (ByteArray):
- if (serializer.mBiomesAreValid)
- {
- aWriter.AddByteArray("Biomes", reinterpret_cast<const char *>(serializer.mVanillaBiomes), ARRAYCOUNT(serializer.mVanillaBiomes));
- aWriter.AddIntArray ("MCSBiomes", reinterpret_cast<const int *>(serializer.mBiomes), ARRAYCOUNT(serializer.mBiomes));
- }
+ // Save biomes:
+ aWriter.AddByteArray("Biomes", reinterpret_cast<const char *>(serializer.Biomes), ARRAYCOUNT(serializer.Biomes));
// Save heightmap (Vanilla require this):
- aWriter.AddIntArray("HeightMap", reinterpret_cast<const int *>(serializer.mVanillaHeightMap), ARRAYCOUNT(serializer.mVanillaHeightMap));
+ aWriter.AddIntArray("HeightMap", reinterpret_cast<const int *>(serializer.Heights), ARRAYCOUNT(serializer.Heights));
// Save blockdata:
aWriter.BeginList("Sections", TAG_Compound);
- for (size_t Y = 0; Y != cChunkData::NumSections; ++Y)
+ ChunkDef::ForEachSection(serializer.m_BlockData, serializer.m_LightData, [&aWriter](const auto Y, const auto Blocks, const auto Metas, const auto BlockLights, const auto SkyLights)
{
- auto section = serializer.m_Data.GetSection(Y);
- if (section == nullptr)
+ aWriter.BeginCompound("");
+
+ if (Blocks != nullptr)
{
- continue;
+ aWriter.AddByteArray("Blocks", reinterpret_cast<const char *>(Blocks->data()), Blocks->size());
+ }
+ else
+ {
+ aWriter.AddByteArray("Blocks", ChunkBlockData::SectionBlockCount, ChunkBlockData::DefaultValue);
}
- aWriter.BeginCompound("");
- aWriter.AddByteArray("Blocks", reinterpret_cast<const char *>(section->m_BlockTypes), ARRAYCOUNT(section->m_BlockTypes));
- aWriter.AddByteArray("Data", reinterpret_cast<const char *>(section->m_BlockMetas), ARRAYCOUNT(section->m_BlockMetas));
+ if (Metas != nullptr)
+ {
+ aWriter.AddByteArray("Data", reinterpret_cast<const char *>(Metas->data()), Metas->size());
+ }
+ else
+ {
+ aWriter.AddByteArray("Data", ChunkBlockData::SectionMetaCount, ChunkBlockData::DefaultMetaValue);
+ }
+
+ if (BlockLights != nullptr)
+ {
+ aWriter.AddByteArray("BlockLight", reinterpret_cast<const char *>(BlockLights->data()), BlockLights->size());
+ }
+ else
+ {
+ aWriter.AddByteArray("BlockLight", ChunkLightData::SectionLightCount, ChunkLightData::DefaultBlockLightValue);
+ }
- #ifdef DEBUG_SKYLIGHT
- aWriter.AddByteArray("BlockLight", reinterpret_cast<const char *>(section->m_BlockSkyLight), ARRAYCOUNT(section->m_BlockSkyLight));
- #else
- aWriter.AddByteArray("BlockLight", reinterpret_cast<const char *>(section->m_BlockLight), ARRAYCOUNT(section->m_BlockLight));
- #endif
+ if (SkyLights != nullptr)
+ {
+ aWriter.AddByteArray("SkyLight", reinterpret_cast<const char *>(SkyLights->data()), SkyLights->size());
+ }
+ else
+ {
+ aWriter.AddByteArray("SkyLight", ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue);
+ }
- aWriter.AddByteArray("SkyLight", reinterpret_cast<const char *>(section->m_BlockSkyLight), ARRAYCOUNT(section->m_BlockSkyLight));
aWriter.AddByte("Y", static_cast<unsigned char>(Y));
aWriter.EndCompound();
- }
+ });
aWriter.EndList(); // "Sections"
// Store the information that the lighting is valid.
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 78320d636..e2a9b1539 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -353,16 +353,7 @@ Compression::Result cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk)
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;
- cChunkDef::BlockNibbles MetaData;
- cChunkDef::BlockNibbles BlockLight;
- cChunkDef::BlockNibbles SkyLight;
-
- memset(BlockTypes, 0, sizeof(BlockTypes));
- memset(MetaData, 0, sizeof(MetaData));
- memset(SkyLight, 0xff, sizeof(SkyLight)); // By default, data not present in the NBT means air, which means full skylight
- memset(BlockLight, 0x00, sizeof(BlockLight));
+ struct SetChunkData Data(a_Chunk);
// Load the blockdata, blocklight and skylight:
int Level = a_NBT.FindChildByName(0, "Level");
@@ -371,12 +362,14 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing NBT tag: Level", a_RawChunkData);
return false;
}
+
int Sections = a_NBT.FindChildByName(Level, "Sections");
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing NBT tag: Sections", a_RawChunkData);
return false;
}
+
eTagType SectionsType = a_NBT.GetChildrenType(Sections);
if ((SectionsType != TAG_Compound) && (SectionsType != TAG_End))
{
@@ -385,39 +378,56 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
}
for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
{
- int y = 0;
- int SectionY = a_NBT.FindChildByName(Child, "Y");
- if ((SectionY < 0) || (a_NBT.GetType(SectionY) != TAG_Byte))
+ const int SectionYTag = a_NBT.FindChildByName(Child, "Y");
+ if ((SectionYTag < 0) || (a_NBT.GetType(SectionYTag) != TAG_Byte))
{
- continue;
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT tag missing or has wrong: Y", a_RawChunkData);
+ return false;
}
- y = a_NBT.GetByte(SectionY);
- if ((y < 0) || (y > 15))
+
+ const int Y = a_NBT.GetByte(SectionYTag);
+ if ((Y < 0) || (Y > static_cast<int>(cChunkDef::NumSections - 1)))
{
- continue;
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT tag exceeds chunk bounds: Y", a_RawChunkData);
+ return false;
+ }
+
+ const auto
+ BlockData = GetSectionData(a_NBT, Child, "Blocks", ChunkBlockData::SectionBlockCount),
+ MetaData = GetSectionData(a_NBT, Child, "Data", ChunkBlockData::SectionMetaCount),
+ BlockLightData = GetSectionData(a_NBT, Child, "BlockLight", ChunkLightData::SectionLightCount),
+ SkyLightData = GetSectionData(a_NBT, Child, "SkyLight", ChunkLightData::SectionLightCount);
+ if ((BlockData != nullptr) && (MetaData != nullptr) && (SkyLightData != nullptr) && (BlockLightData != nullptr))
+ {
+ Data.BlockData.SetSection(*reinterpret_cast<const ChunkBlockData::SectionType *>(BlockData), *reinterpret_cast<const ChunkBlockData::SectionMetaType *>(MetaData), static_cast<size_t>(Y));
+ Data.LightData.SetSection(*reinterpret_cast<const ChunkLightData::SectionType *>(BlockLightData), *reinterpret_cast<const ChunkLightData::SectionType *>(SkyLightData), static_cast<size_t>(Y));
+ }
+ else
+ {
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk block/light data", a_RawChunkData);
+ return false;
}
- CopyNBTData(a_NBT, Child, "Blocks", reinterpret_cast<char *>(&(BlockTypes[y * 4096])), 4096);
- CopyNBTData(a_NBT, Child, "Data", reinterpret_cast<char *>(&(MetaData[y * 2048])), 2048);
- CopyNBTData(a_NBT, Child, "SkyLight", reinterpret_cast<char *>(&(SkyLight[y * 2048])), 2048);
- CopyNBTData(a_NBT, Child, "BlockLight", reinterpret_cast<char *>(&(BlockLight[y * 2048])), 2048);
} // for itr - LevelSections[]
- // Load the biomes from NBT, if present and valid. First try MCS-style, then Vanilla-style:
- cChunkDef::BiomeMap BiomeMap;
- cChunkDef::BiomeMap * Biomes = LoadBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "MCSBiomes"));
- if (Biomes == nullptr)
+ // Load the biomes from NBT, if present and valid:
+ if (!LoadBiomeMapFromNBT(Data.BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes")))
+ {
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk biome data", a_RawChunkData);
+ return false;
+ }
+
+ // Height map too:
+ if (!LoadHeightMapFromNBT(Data.HeightMap, a_NBT, a_NBT.FindChildByName(Level, "HeightMap")))
{
- // MCS-style biomes not available, load vanilla-style:
- Biomes = LoadVanillaBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes"));
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk height data", a_RawChunkData);
+ return false;
}
// Load the entities from NBT:
- cEntityList Entities;
- cBlockEntities BlockEntities;
- LoadEntitiesFromNBT (Entities, a_NBT, a_NBT.FindChildByName(Level, "Entities"));
- LoadBlockEntitiesFromNBT(BlockEntities, a_NBT, a_NBT.FindChildByName(Level, "TileEntities"), BlockTypes, MetaData);
+ LoadEntitiesFromNBT (Data.Entities, a_NBT, a_NBT.FindChildByName(Level, "Entities"));
+ LoadBlockEntitiesFromNBT(Data.BlockEntities, a_NBT, a_NBT.FindChildByName(Level, "TileEntities"), Data.BlockData);
- bool IsLightValid = (a_NBT.FindChildByName(Level, "MCSIsLightValid") > 0);
+ Data.IsLightValid = (a_NBT.FindChildByName(Level, "MCSIsLightValid") > 0);
/*
// Uncomment this block for really cool stuff :)
@@ -455,16 +465,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
} // for y
//*/
- auto SetChunkData = std::make_unique<cSetChunkData>(
- a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
- BlockTypes, MetaData,
- IsLightValid ? BlockLight : nullptr,
- IsLightValid ? SkyLight : nullptr,
- nullptr, Biomes,
- std::move(Entities), std::move(BlockEntities),
- false
- );
- m_World->QueueSetChunkData(std::move(SetChunkData));
+ m_World->QueueSetChunkData(std::move(Data));
return true;
}
@@ -472,69 +473,66 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
-void cWSSAnvil::CopyNBTData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, char * a_Destination, size_t a_Length)
+bool cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap & a_BiomeMap, const cParsedNBT & a_NBT, const int a_TagIdx)
{
- int Child = a_NBT.FindChildByName(a_Tag, a_ChildName);
- if ((Child >= 0) && (a_NBT.GetType(Child) == TAG_ByteArray) && (a_NBT.GetDataLength(Child) == a_Length))
+ if (
+ (a_TagIdx < 0) ||
+ (a_NBT.GetType(a_TagIdx) != TAG_ByteArray) ||
+ (a_NBT.GetDataLength(a_TagIdx) != std::size(a_BiomeMap))
+ )
{
- memcpy(a_Destination, a_NBT.GetData(Child), a_Length);
+ return false;
}
-}
-
-
-
-
-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))
- {
- return nullptr;
- }
- if (a_NBT.GetDataLength(a_TagIdx) != 16 * 16)
+ const auto * const BiomeData = a_NBT.GetData(a_TagIdx);
+ for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++)
{
- // The biomes stored don't match in size
- return nullptr;
- }
- const unsigned char * VanillaBiomeData = reinterpret_cast<const unsigned char *>(a_NBT.GetData(a_TagIdx));
- for (size_t i = 0; i < ARRAYCOUNT(*a_BiomeMap); i++)
- {
- if ((VanillaBiomeData)[i] == 0xff)
+ if (BiomeData[i] > std::byte(EMCSBiome::biMaxVariantBiome))
{
- // Unassigned biomes
- return nullptr;
+ // Unassigned biomes:
+ return false;
}
- (*a_BiomeMap)[i] = static_cast<EMCSBiome>(VanillaBiomeData[i]);
+
+ a_BiomeMap[i] = static_cast<EMCSBiome>(BiomeData[i]);
}
- return a_BiomeMap;
+
+ return true;
}
-cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx)
+bool cWSSAnvil::LoadHeightMapFromNBT(cChunkDef::HeightMap & a_HeightMap, const cParsedNBT & a_NBT, const int a_TagIdx)
{
- if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_IntArray))
+ if (
+ (a_TagIdx < 0) ||
+ (a_NBT.GetType(a_TagIdx) != TAG_IntArray) ||
+ (a_NBT.GetDataLength(a_TagIdx) != (4 * std::size(a_HeightMap)))
+ )
{
- return nullptr;
- }
- if (a_NBT.GetDataLength(a_TagIdx) != sizeof(*a_BiomeMap))
- {
- // The biomes stored don't match in size
- return nullptr;
+ return false;
}
- const auto * BiomeData = a_NBT.GetData(a_TagIdx);
- for (size_t i = 0; i < ARRAYCOUNT(*a_BiomeMap); i++)
+
+ const auto * const HeightData = a_NBT.GetData(a_TagIdx);
+ for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++)
{
- (*a_BiomeMap)[i] = static_cast<EMCSBiome>(GetBEInt(&BiomeData[i * 4]));
- if ((*a_BiomeMap)[i] == 0xff)
+ for (int RelX = 0; RelX < cChunkDef::Width; RelX++)
{
- // Unassigned biomes
- return nullptr;
+ const int Index = 4 * (RelX + RelZ * cChunkDef::Width);
+ const int Height = GetBEInt(HeightData + Index);
+
+ if (Height > std::numeric_limits<HEIGHTTYPE>::max())
+ {
+ // Invalid data:
+ return false;
+ }
+
+ cChunkDef::SetHeight(a_HeightMap, RelX, RelZ, static_cast<HEIGHTTYPE>(Height));
}
}
- return a_BiomeMap;
+
+ return true;
}
@@ -575,7 +573,7 @@ void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entities, const cParsedNBT &
-void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas)
+void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, const ChunkBlockData & a_BlockData)
{
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List))
{
@@ -596,11 +594,11 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntities, const
LOGWARNING("Bad block entity, missing the coords. Will be ignored.");
continue;
}
- auto relPos = cChunkDef::AbsoluteToRelative(absPos);
+ const auto relPos = cChunkDef::AbsoluteToRelative(absPos);
// Load the proper BlockEntity type based on the block type:
- BLOCKTYPE BlockType = cChunkDef::GetBlock(a_BlockTypes, relPos);
- NIBBLETYPE BlockMeta = cChunkDef::GetNibble(a_BlockMetas, relPos);
+ const auto BlockType = a_BlockData.GetBlock(relPos);
+ const auto BlockMeta = a_BlockData.GetMeta(relPos);
OwnedBlockEntity Entity;
try
@@ -3990,6 +3988,20 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, ContiguousB
+const std::byte * cWSSAnvil::GetSectionData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, size_t a_Length)
+{
+ int Child = a_NBT.FindChildByName(a_Tag, a_ChildName);
+ if ((Child >= 0) && (a_NBT.GetType(Child) == TAG_ByteArray) && (a_NBT.GetDataLength(Child) == a_Length))
+ {
+ return a_NBT.GetData(Child);
+ }
+ return nullptr;
+}
+
+
+
+
+
bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data)
{
if (!OpenFile(false))
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index 1751c6761..d37bf2d25 100755
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -24,6 +24,7 @@ class cMonster;
class cProjectileEntity;
class cHangingEntity;
class cUUID;
+class ChunkBlockData;
@@ -106,6 +107,9 @@ protected:
/** Gets chunk data from the correct file; locks file CS as needed */
bool GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data);
+ /** Copies a_Length bytes of data from the specified NBT Tag's Child into the a_Destination buffer */
+ const std::byte * GetSectionData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, size_t a_Length);
+
/** Sets chunk data into the correct file; locks file CS as needed */
bool SetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data);
@@ -119,17 +123,17 @@ protected:
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, 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);
+ /** Loads the chunk's biome map into a_BiomeMap if biomes present and valid; returns false otherwise. */
+ bool LoadBiomeMapFromNBT(cChunkDef::BiomeMap & a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx);
- /** Loads the chunk's biome map from MCS format; returns a_BiomeMap if biomes present and valid, nullptr otherwise */
- cChunkDef::BiomeMap * LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx);
+ /** Loads the chunk's height map into a_HeightMap if heights present and valid; returns false otherwise. */
+ bool LoadHeightMapFromNBT(cChunkDef::HeightMap & a_HeightMap, const cParsedNBT & a_NBT, int a_TagIdx);
/** 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(cBlockEntities & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas);
+ void LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag, const ChunkBlockData & a_BlockData);
/** Loads the data for a block entity from the specified NBT tag.
Returns the loaded block entity, or nullptr upon failure. */
@@ -298,9 +302,6 @@ protected:
/** 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, size_t a_Length);
-
// cWSSchema overrides:
virtual bool LoadChunk(const cChunkCoords & a_Chunk) override;
virtual bool SaveChunk(const cChunkCoords & a_Chunk) override;