diff --git a/src/ChunkData.cpp b/src/ChunkData.cpp index c2b09bafb..310945f17 100644 --- a/src/ChunkData.cpp +++ b/src/ChunkData.cpp @@ -422,6 +422,129 @@ void cChunkData::CopySkyLight(NIBBLETYPE * a_Dest) const +void cChunkData::FillBlockTypes(BLOCKTYPE a_Value) +{ + // If needed, allocate any missing sections + if (a_Value != 0x00) + { + for (auto & Section : m_Sections) + { + if (Section == nullptr) + { + Section = Allocate(); + std::fill(std::begin(Section->m_BlockMetas), std::end(Section->m_BlockMetas), 0x00); + std::fill(std::begin(Section->m_BlockLight), std::end(Section->m_BlockLight), 0x00); + std::fill(std::begin(Section->m_BlockSkyLight), std::end(Section->m_BlockSkyLight), 0xff); + } + } + } + + for (auto Section : m_Sections) + { + if (Section != nullptr) + { + std::fill(std::begin(Section->m_BlockTypes), std::end(Section->m_BlockTypes), a_Value); + } + } +} + + + + + +void cChunkData::FillMetas(NIBBLETYPE a_Value) +{ + // If needed, allocate any missing sections + if (a_Value != 0x00) + { + for (auto & Section : m_Sections) + { + if (Section == nullptr) + { + Section = Allocate(); + std::fill(std::begin(Section->m_BlockTypes), std::end(Section->m_BlockTypes), 0x00); + std::fill(std::begin(Section->m_BlockLight), std::end(Section->m_BlockLight), 0x00); + std::fill(std::begin(Section->m_BlockSkyLight), std::end(Section->m_BlockSkyLight), 0xff); + } + } + } + + NIBBLETYPE NewMeta = static_cast((a_Value << 4) | a_Value); + for (auto Section : m_Sections) + { + if (Section != nullptr) + { + std::fill(std::begin(Section->m_BlockMetas), std::end(Section->m_BlockMetas), NewMeta); + } + } +} + + + + + +void cChunkData::FillBlockLight(NIBBLETYPE a_Value) +{ + // If needed, allocate any missing sections + if (a_Value != 0x00) + { + for (auto & Section : m_Sections) + { + if (Section == nullptr) + { + Section = Allocate(); + std::fill(std::begin(Section->m_BlockTypes), std::end(Section->m_BlockTypes), 0x00); + std::fill(std::begin(Section->m_BlockMetas), std::end(Section->m_BlockMetas), 0x00); + std::fill(std::begin(Section->m_BlockSkyLight), std::end(Section->m_BlockSkyLight), 0xff); + } + } + } + + NIBBLETYPE NewLight = static_cast((a_Value << 4) | a_Value); + for (auto Section : m_Sections) + { + if (Section != nullptr) + { + std::fill(std::begin(Section->m_BlockLight), std::end(Section->m_BlockLight), NewLight); + } + } +} + + + + + +void cChunkData::FillSkyLight(NIBBLETYPE a_Value) +{ + // If needed, allocate any missing sections + if (a_Value != 0x0f) + { + for (auto & Section : m_Sections) + { + if (Section == nullptr) + { + Section = Allocate(); + std::fill(std::begin(Section->m_BlockTypes), std::end(Section->m_BlockTypes), 0x00); + std::fill(std::begin(Section->m_BlockMetas), std::end(Section->m_BlockMetas), 0x00); + std::fill(std::begin(Section->m_BlockLight), std::end(Section->m_BlockLight), 0x00); + } + } + } + + NIBBLETYPE NewSkyLight = static_cast((a_Value << 4) | a_Value); + for (auto Section : m_Sections) + { + if (Section != nullptr) + { + std::fill(std::begin(Section->m_BlockSkyLight), std::end(Section->m_BlockSkyLight), NewSkyLight); + } + } +} + + + + + void cChunkData::SetBlockTypes(const BLOCKTYPE * a_Src) { ASSERT(a_Src != nullptr); diff --git a/src/ChunkData.h b/src/ChunkData.h index 49a03fb4a..6bc2b5366 100644 --- a/src/ChunkData.h +++ b/src/ChunkData.h @@ -80,6 +80,18 @@ public: /** Copies the skylight data into the specified flat array. */ void CopySkyLight (NIBBLETYPE * a_Dest) const; + /** Fills the chunk with the specified block. */ + void FillBlockTypes(BLOCKTYPE a_Value); + + /** Fills the chunk with the specified meta value. */ + void FillMetas (NIBBLETYPE a_Value); + + /** Fills the chunk with the specified block light. */ + void FillBlockLight(NIBBLETYPE a_Value); + + /** Fills the chunk with the specified sky light. */ + void FillSkyLight (NIBBLETYPE a_Value); + /** Copies the blocktype data from the specified flat array into the internal representation. Allocates sections that are needed for the operation. Requires that a_Src is a valid pointer. */ diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 73c633e1a..1e8543648 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -68,11 +68,11 @@ void cNBTChunkSerializer::Finish(void) m_Writer.EndList(); } - // If light not valid, reset it to all zeroes: + // If light not valid, reset it to defaults: if (!m_IsLightValid) { - memset(m_BlockLight, 0, sizeof(m_BlockLight)); - memset(m_BlockSkyLight, 0, sizeof(m_BlockSkyLight)); + m_Data.FillBlockLight(0x00); + m_Data.FillSkyLight(0x0f); } // Check if "Entity" and "TileEntities" lists exists. MCEdit requires this. diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 3637ea655..50d98a518 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -1,4 +1,4 @@ - + // NBTChunkSerializer.h // Declares the cNBTChunkSerializer class that is used for saving individual chunks into NBT format used by Anvil @@ -55,7 +55,7 @@ class cPainting; class cNBTChunkSerializer : - public cChunkDataSeparateCollector + public cChunkDataCopyCollector { public: cChunkDef::BiomeMap m_Biomes; @@ -69,15 +69,12 @@ public: /** Close NBT tags that we've opened */ void Finish(void); - bool IsLightValid(void) const {return m_IsLightValid; } + bool IsLightValid(void) const { return m_IsLightValid; } protected: - /* From cChunkDataSeparateCollector we inherit: - - m_BlockTypes[] - - m_BlockMetas[] - - m_BlockLight[] - - m_BlockSkyLight[] */ + /* From cChunkDataCopyCollector we inherit: + - cChunkData m_Data */ cFastNBTWriter & m_Writer; diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index bbbffb07f..a3251481f 100755 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -515,23 +515,25 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_ // Save blockdata: a_Writer.BeginList("Sections", TAG_Compound); - size_t SliceSizeBlock = cChunkDef::Width * cChunkDef::Width * 16; - size_t SliceSizeNibble = SliceSizeBlock / 2; - const char * BlockTypes = reinterpret_cast(Serializer.m_BlockTypes); - const char * BlockMetas = reinterpret_cast(Serializer.m_BlockMetas); - #ifdef DEBUG_SKYLIGHT - const char * BlockLight = reinterpret_cast(Serializer.m_BlockSkyLight); - #else - const char * BlockLight = reinterpret_cast(Serializer.m_BlockLight); - #endif - const char * BlockSkyLight = reinterpret_cast(Serializer.m_BlockSkyLight); - for (int Y = 0; Y < 16; Y++) + for (size_t Y = 0; Y != cChunkData::NumSections; ++Y) { + auto Section = Serializer.m_Data.GetSection(Y); + if (Section == nullptr) + { + continue; + } + a_Writer.BeginCompound(""); - a_Writer.AddByteArray("Blocks", BlockTypes + static_cast(Y) * SliceSizeBlock, SliceSizeBlock); - a_Writer.AddByteArray("Data", BlockMetas + static_cast(Y) * SliceSizeNibble, SliceSizeNibble); - a_Writer.AddByteArray("SkyLight", BlockSkyLight + static_cast(Y) * SliceSizeNibble, SliceSizeNibble); - a_Writer.AddByteArray("BlockLight", BlockLight + static_cast(Y) * SliceSizeNibble, SliceSizeNibble); + a_Writer.AddByteArray("Blocks", reinterpret_cast(Section->m_BlockTypes), ARRAYCOUNT(Section->m_BlockTypes)); + a_Writer.AddByteArray("Data", reinterpret_cast(Section->m_BlockMetas), ARRAYCOUNT(Section->m_BlockMetas)); + + #ifdef DEBUG_SKYLIGHT + a_Writer.AddByteArray("BlockLight", reinterpret_cast(Section->m_BlockSkyLight), ARRAYCOUNT(Section->m_BlockSkyLight)); + #else + a_Writer.AddByteArray("BlockLight", reinterpret_cast(Section->m_BlockLight), ARRAYCOUNT(Section->m_BlockLight)); + #endif + + a_Writer.AddByteArray("SkyLight", reinterpret_cast(Section->m_BlockSkyLight), ARRAYCOUNT(Section->m_BlockSkyLight)); a_Writer.AddByte("Y", static_cast(Y)); a_Writer.EndCompound(); }