1
0

Implement anvil chunk sparsing

This commit is contained in:
peterbell10 2017-08-20 23:23:23 +01:00 committed by Lukas Pioch
parent 3ebcf0fd5c
commit 447d929da1
5 changed files with 160 additions and 26 deletions

View File

@ -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<NIBBLETYPE>((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<NIBBLETYPE>((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<NIBBLETYPE>((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) void cChunkData::SetBlockTypes(const BLOCKTYPE * a_Src)
{ {
ASSERT(a_Src != nullptr); ASSERT(a_Src != nullptr);

View File

@ -80,6 +80,18 @@ public:
/** Copies the skylight data into the specified flat array. */ /** Copies the skylight data into the specified flat array. */
void CopySkyLight (NIBBLETYPE * a_Dest) const; 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. /** Copies the blocktype data from the specified flat array into the internal representation.
Allocates sections that are needed for the operation. Allocates sections that are needed for the operation.
Requires that a_Src is a valid pointer. */ Requires that a_Src is a valid pointer. */

View File

@ -68,11 +68,11 @@ void cNBTChunkSerializer::Finish(void)
m_Writer.EndList(); m_Writer.EndList();
} }
// If light not valid, reset it to all zeroes: // If light not valid, reset it to defaults:
if (!m_IsLightValid) if (!m_IsLightValid)
{ {
memset(m_BlockLight, 0, sizeof(m_BlockLight)); m_Data.FillBlockLight(0x00);
memset(m_BlockSkyLight, 0, sizeof(m_BlockSkyLight)); m_Data.FillSkyLight(0x0f);
} }
// Check if "Entity" and "TileEntities" lists exists. MCEdit requires this. // Check if "Entity" and "TileEntities" lists exists. MCEdit requires this.

View File

@ -1,4 +1,4 @@

// NBTChunkSerializer.h // NBTChunkSerializer.h
// Declares the cNBTChunkSerializer class that is used for saving individual chunks into NBT format used by Anvil // 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 : class cNBTChunkSerializer :
public cChunkDataSeparateCollector public cChunkDataCopyCollector
{ {
public: public:
cChunkDef::BiomeMap m_Biomes; cChunkDef::BiomeMap m_Biomes;
@ -69,15 +69,12 @@ public:
/** Close NBT tags that we've opened */ /** Close NBT tags that we've opened */
void Finish(void); void Finish(void);
bool IsLightValid(void) const {return m_IsLightValid; } bool IsLightValid(void) const { return m_IsLightValid; }
protected: protected:
/* From cChunkDataSeparateCollector we inherit: /* From cChunkDataCopyCollector we inherit:
- m_BlockTypes[] - cChunkData m_Data */
- m_BlockMetas[]
- m_BlockLight[]
- m_BlockSkyLight[] */
cFastNBTWriter & m_Writer; cFastNBTWriter & m_Writer;

View File

@ -515,23 +515,25 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
// Save blockdata: // Save blockdata:
a_Writer.BeginList("Sections", TAG_Compound); a_Writer.BeginList("Sections", TAG_Compound);
size_t SliceSizeBlock = cChunkDef::Width * cChunkDef::Width * 16; for (size_t Y = 0; Y != cChunkData::NumSections; ++Y)
size_t SliceSizeNibble = SliceSizeBlock / 2;
const char * BlockTypes = reinterpret_cast<const char *>(Serializer.m_BlockTypes);
const char * BlockMetas = reinterpret_cast<const char *>(Serializer.m_BlockMetas);
#ifdef DEBUG_SKYLIGHT
const char * BlockLight = reinterpret_cast<const char *>(Serializer.m_BlockSkyLight);
#else
const char * BlockLight = reinterpret_cast<const char *>(Serializer.m_BlockLight);
#endif
const char * BlockSkyLight = reinterpret_cast<const char *>(Serializer.m_BlockSkyLight);
for (int Y = 0; Y < 16; Y++)
{ {
auto Section = Serializer.m_Data.GetSection(Y);
if (Section == nullptr)
{
continue;
}
a_Writer.BeginCompound(""); a_Writer.BeginCompound("");
a_Writer.AddByteArray("Blocks", BlockTypes + static_cast<unsigned int>(Y) * SliceSizeBlock, SliceSizeBlock); a_Writer.AddByteArray("Blocks", reinterpret_cast<const char *>(Section->m_BlockTypes), ARRAYCOUNT(Section->m_BlockTypes));
a_Writer.AddByteArray("Data", BlockMetas + static_cast<unsigned int>(Y) * SliceSizeNibble, SliceSizeNibble); a_Writer.AddByteArray("Data", reinterpret_cast<const char *>(Section->m_BlockMetas), ARRAYCOUNT(Section->m_BlockMetas));
a_Writer.AddByteArray("SkyLight", BlockSkyLight + static_cast<unsigned int>(Y) * SliceSizeNibble, SliceSizeNibble);
a_Writer.AddByteArray("BlockLight", BlockLight + static_cast<unsigned int>(Y) * SliceSizeNibble, SliceSizeNibble); #ifdef DEBUG_SKYLIGHT
a_Writer.AddByteArray("BlockLight", reinterpret_cast<const char *>(Section->m_BlockSkyLight), ARRAYCOUNT(Section->m_BlockSkyLight));
#else
a_Writer.AddByteArray("BlockLight", reinterpret_cast<const char *>(Section->m_BlockLight), ARRAYCOUNT(Section->m_BlockLight));
#endif
a_Writer.AddByteArray("SkyLight", reinterpret_cast<const char *>(Section->m_BlockSkyLight), ARRAYCOUNT(Section->m_BlockSkyLight));
a_Writer.AddByte("Y", static_cast<unsigned char>(Y)); a_Writer.AddByte("Y", static_cast<unsigned char>(Y));
a_Writer.EndCompound(); a_Writer.EndCompound();
} }