diff options
author | Tiger Wang <ziwei.tiger@outlook.com> | 2021-03-05 14:03:55 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-05 14:03:55 +0100 |
commit | 868cd94ee9a5a0638c014a4cc42224f01ff234c8 (patch) | |
tree | cd23dc866f77de5b0b3e89a5eafeeb2ef24ffbdd /src/WorldStorage | |
parent | fixed the crash on generating in the SinglePiceStructuresGen (#5136) (diff) | |
download | cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar.gz cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar.bz2 cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar.lz cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar.xz cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.tar.zst cuberite-868cd94ee9a5a0638c014a4cc42224f01ff234c8.zip |
Diffstat (limited to 'src/WorldStorage')
-rw-r--r-- | src/WorldStorage/FastNBT.cpp | 12 | ||||
-rw-r--r-- | src/WorldStorage/FastNBT.h | 1 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.cpp | 94 | ||||
-rw-r--r-- | src/WorldStorage/WSSAnvil.cpp | 188 | ||||
-rwxr-xr-x | src/WorldStorage/WSSAnvil.h | 17 |
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; |