diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp index 11bd76e6c..40fdd68c0 100644 --- a/src/BlockArea.cpp +++ b/src/BlockArea.cpp @@ -1903,7 +1903,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) if (m_Area.m_BlockMetas != NULL) { - a_BlockBuffer.CopyMeta(m_Area.m_BlockMetas); + a_BlockBuffer.CopyMetas(m_Area.m_BlockMetas); } if (m_Area.m_BlockLight != NULL) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index e5f8f1e29..23412a4c3 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -282,8 +282,8 @@ void cChunk::SetAllData( CalculateHeightmap(a_BlockTypes); } - m_ChunkData.SetBlocks(a_BlockTypes); - m_ChunkData.SetMeta(a_BlockMeta); + m_ChunkData.SetBlockTypes(a_BlockTypes); + m_ChunkData.SetMetas(a_BlockMeta); m_ChunkData.SetBlockLight(a_BlockLight); m_ChunkData.SetSkyLight(a_BlockSkyLight); @@ -339,7 +339,7 @@ void cChunk::SetLight( void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes) { - m_ChunkData.CopyBlocks(a_BlockTypes); + m_ChunkData.CopyBlockTypes(a_BlockTypes); } diff --git a/src/ChunkData.cpp b/src/ChunkData.cpp index 172858e4e..cc4793ec3 100644 --- a/src/ChunkData.cpp +++ b/src/ChunkData.cpp @@ -1,14 +1,39 @@ +// ChunkData.cpp + +// Implements the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk + #include "Globals.h" #include "ChunkData.h" -cChunkData::cChunkData() + + + + +/** Returns true if all a_Array's elements between [0] and [a_NumElements - 1] are equal to a_Value. */ +template inline bool IsAllValue(const T * a_Array, size_t a_NumElements, T a_Value) +{ + for (size_t i = 0; i < a_NumElements; i++) + { + if (a_Array[i] != a_Value) + { + return false; + } + } + return true; +} + + + + + +cChunkData::cChunkData(void) #if __cplusplus < 201103L // auto_ptr style interface for memory management : m_IsOwner(true) #endif { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { m_Sections[i] = NULL; } @@ -27,7 +52,7 @@ cChunkData::~cChunkData() return; } #endif - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { Free(m_Sections[i]); } @@ -43,7 +68,7 @@ cChunkData::~cChunkData() m_IsOwner(true) { // Move contents and ownership from a_Other to this, pointer-wise: - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { m_Sections[i] = a_Other.m_Sections[i]; } @@ -65,7 +90,7 @@ cChunkData::~cChunkData() // Free any currently held contents: if (m_IsOwner) { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { Free(m_Sections[i]); } @@ -73,7 +98,7 @@ cChunkData::~cChunkData() // Move contents and ownership from a_Other to this, pointer-wise: m_IsOwner = true; - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { m_Sections[i] = a_Other.m_Sections[i]; } @@ -86,7 +111,7 @@ cChunkData::~cChunkData() // unique_ptr style interface for memory management cChunkData::cChunkData(cChunkData && other) { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { m_Sections[i] = other.m_Sections[i]; other.m_Sections[i] = NULL; @@ -101,7 +126,7 @@ cChunkData::~cChunkData() { if (&other != this) { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { Free(m_Sections[i]); m_Sections[i] = other.m_Sections[i]; @@ -121,10 +146,10 @@ BLOCKTYPE cChunkData::GetBlock(int a_X, int a_Y, int a_Z) const ASSERT((a_X >= 0) && (a_X < cChunkDef::Width)); ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height)); ASSERT((a_Z >= 0) && (a_Z < cChunkDef::Width)); - int Section = a_Y / CHUNK_SECTION_HEIGHT; + int Section = a_Y / SectionHeight; if (m_Sections[Section] != NULL) { - int Index = cChunkDef::MakeIndexNoCheck(a_X, a_Y - (Section * CHUNK_SECTION_HEIGHT), a_Z); + int Index = cChunkDef::MakeIndexNoCheck(a_X, a_Y - (Section * SectionHeight), a_Z); return m_Sections[Section]->m_BlockTypes[Index]; } else @@ -149,7 +174,7 @@ void cChunkData::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block) return; } - int Section = a_RelY / CHUNK_SECTION_HEIGHT; + int Section = a_RelY / SectionHeight; if (m_Sections[Section] == NULL) { if (a_Block == 0x00) @@ -164,7 +189,7 @@ void cChunkData::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block) } ZeroSection(m_Sections[Section]); } - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * CHUNK_SECTION_HEIGHT), a_RelZ); + int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ); m_Sections[Section]->m_BlockTypes[Index] = a_Block; } @@ -179,10 +204,10 @@ NIBBLETYPE cChunkData::GetMeta(int a_RelX, int a_RelY, int a_RelZ) const (a_RelY < cChunkDef::Height) && (a_RelY > -1) && (a_RelZ < cChunkDef::Width) && (a_RelZ > -1)) { - int Section = a_RelY / CHUNK_SECTION_HEIGHT; + int Section = a_RelY / SectionHeight; if (m_Sections[Section] != NULL) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * CHUNK_SECTION_HEIGHT), a_RelZ); + int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ); return (m_Sections[Section]->m_BlockMeta[Index / 2] >> ((Index & 1) * 4)) & 0x0f; } else @@ -210,7 +235,7 @@ bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble return false; } - int Section = a_RelY / CHUNK_SECTION_HEIGHT; + int Section = a_RelY / SectionHeight; if (m_Sections[Section] == NULL) { if ((a_Nibble & 0xf) == 0x00) @@ -225,7 +250,7 @@ bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble } ZeroSection(m_Sections[Section]); } - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * CHUNK_SECTION_HEIGHT), a_RelZ); + int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ); NIBBLETYPE oldval = m_Sections[Section]->m_BlockMeta[Index / 2] >> ((Index & 1) * 4) & 0xf; m_Sections[Section]->m_BlockMeta[Index / 2] = static_cast( (m_Sections[Section]->m_BlockMeta[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble @@ -246,10 +271,10 @@ NIBBLETYPE cChunkData::GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const (a_RelZ < cChunkDef::Width) && (a_RelZ > -1) ) { - int Section = a_RelY / CHUNK_SECTION_HEIGHT; + int Section = a_RelY / SectionHeight; if (m_Sections[Section] != NULL) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * CHUNK_SECTION_HEIGHT), a_RelZ); + int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ); return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f; } else @@ -269,10 +294,10 @@ NIBBLETYPE cChunkData::GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const { if ((a_RelX < cChunkDef::Width) && (a_RelX > -1) && (a_RelY < cChunkDef::Height) && (a_RelY > -1) && (a_RelZ < cChunkDef::Width) && (a_RelZ > -1)) { - int Section = a_RelY / CHUNK_SECTION_HEIGHT; + int Section = a_RelY / SectionHeight; if (m_Sections[Section] != NULL) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * CHUNK_SECTION_HEIGHT), a_RelZ); + int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ); return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f; } else @@ -291,7 +316,7 @@ NIBBLETYPE cChunkData::GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const cChunkData cChunkData::Copy(void) const { cChunkData copy; - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { if (m_Sections[i] != NULL) { @@ -306,11 +331,12 @@ cChunkData cChunkData::Copy(void) const -void cChunkData::CopyBlocks(BLOCKTYPE * a_Dest, size_t a_Idx, size_t a_Length) const +void cChunkData::CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx, size_t a_Length) const { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + // TODO: This code seems wrong. It always copies into a_Dest[i * SegmentLength], even when a_Idx > 0 + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16; + const size_t SegmentLength = SectionHeight * 16 * 16; if (a_Idx > 0) { a_Idx = std::max(a_Idx - a_Length, (size_t) 0); @@ -321,19 +347,11 @@ void cChunkData::CopyBlocks(BLOCKTYPE * a_Dest, size_t a_Idx, size_t a_Length) a_Length -= ToCopy; if (m_Sections[i] != NULL) { - memcpy( - &a_Dest[i * SegmentLength], - &m_Sections[i]->m_BlockTypes, - sizeof(BLOCKTYPE) * ToCopy - ); + memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockTypes, sizeof(BLOCKTYPE) * ToCopy); } else { - memset( - &a_Dest[i * SegmentLength], - 0, - sizeof(BLOCKTYPE) * ToCopy - ); + memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * ToCopy); } } } @@ -343,26 +361,18 @@ void cChunkData::CopyBlocks(BLOCKTYPE * a_Dest, size_t a_Idx, size_t a_Length) -void cChunkData::CopyMeta(NIBBLETYPE * a_Dest) const +void cChunkData::CopyMetas(NIBBLETYPE * a_Dest) const { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + const size_t SegmentLength = SectionHeight * 16 * 16 / 2; if (m_Sections[i] != NULL) { - memcpy( - &a_Dest[i * SegmentLength], - &m_Sections[i]->m_BlockMeta, - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockMeta, sizeof(NIBBLETYPE) * SegmentLength); } else { - memset( - &a_Dest[i * SegmentLength], - 0, - sizeof(BLOCKTYPE) * SegmentLength - ); + memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * SegmentLength); } } } @@ -373,24 +383,16 @@ void cChunkData::CopyMeta(NIBBLETYPE * a_Dest) const void cChunkData::CopyBlockLight(NIBBLETYPE * a_Dest) const { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + const size_t SegmentLength = SectionHeight * 16 * 16 / 2; if (m_Sections[i] != NULL) { - memcpy( - &a_Dest[i * SegmentLength], - &m_Sections[i]->m_BlockLight, - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockLight, sizeof(NIBBLETYPE) * SegmentLength); } else { - memset( - &a_Dest[i * SegmentLength], - 0, - sizeof(BLOCKTYPE) * SegmentLength - ); + memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * SegmentLength); } } } @@ -401,24 +403,16 @@ void cChunkData::CopyBlockLight(NIBBLETYPE * a_Dest) const void cChunkData::CopySkyLight(NIBBLETYPE * a_Dest) const { - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + const size_t SegmentLength = SectionHeight * 16 * 16 / 2; if (m_Sections[i] != NULL) { - memcpy( - &a_Dest[i * SegmentLength], - &m_Sections[i]->m_BlockSkyLight, - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockSkyLight, sizeof(NIBBLETYPE) * SegmentLength); } else { - memset( - &a_Dest[i * SegmentLength], - 0xFF, - sizeof(BLOCKTYPE) * SegmentLength - ); + memset(&a_Dest[i * SegmentLength], 0xff, sizeof(BLOCKTYPE) * SegmentLength); } } } @@ -427,165 +421,102 @@ void cChunkData::CopySkyLight(NIBBLETYPE * a_Dest) const -void cChunkData::SetBlocks(const BLOCKTYPE * a_Src) +void cChunkData::SetBlockTypes(const BLOCKTYPE * a_Src) { ASSERT(a_Src != NULL); - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + static const size_t SegmentLength = SectionHeight * 16 * 16; + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16; + // If the section is already allocated, copy the data into it: if (m_Sections[i] != NULL) { - memcpy( - &m_Sections[i]->m_BlockTypes, - &a_Src[i * SegmentLength], - sizeof(BLOCKTYPE) * SegmentLength - ); + memcpy(&m_Sections[i]->m_BlockTypes, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength); + continue; } - else + + // The section doesn't exist, find out if it is needed: + if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (const BLOCKTYPE)0)) { - // j counts how many of leading zeros the buffer has - // if j == SegmentLength then the buffer is all zeros so there is no point - // creating the buffer. - size_t j = 0; - // do nothing whilst 0 - for (; (j < SegmentLength) && (a_Src[i * SegmentLength + j] == 0); j++); - if (j != SegmentLength) - { - m_Sections[i] = Allocate(); - memcpy( - &m_Sections[i]->m_BlockTypes, - &a_Src[i * SegmentLength], - sizeof(BLOCKTYPE) * SegmentLength - ); - memset( - m_Sections[i]->m_BlockMeta, - 0x00, - sizeof(m_Sections[i]->m_BlockMeta) - ); - memset( - m_Sections[i]->m_BlockLight, - 0x00, - sizeof(m_Sections[i]->m_BlockLight) - ); - memset( - m_Sections[i]->m_BlockSkyLight, - 0xFF, - sizeof(m_Sections[i]->m_BlockSkyLight) - ); - } + // No need for the section, the data is all-air + continue; } - } + + // Allocate the section and copy the data into it: + m_Sections[i] = Allocate(); + memcpy(&m_Sections[i]->m_BlockTypes, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength); + memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta)); + memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight)); + memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight)); + } // for i - m_Sections[] } -void cChunkData::SetMeta(const NIBBLETYPE * a_Src) +void cChunkData::SetMetas(const NIBBLETYPE * a_Src) { ASSERT(a_Src != NULL); - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + // If the section is already allocated, copy the data into it: if (m_Sections[i] != NULL) { - memcpy( - &m_Sections[i]->m_BlockMeta, - &a_Src[i * SegmentLength], - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&m_Sections[i]->m_BlockMeta, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength); + continue; } - else + + // The section doesn't exist, find out if it is needed: + if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0)) { - // j counts how many of leading zeros the buffer has - // if j == SegmentLength then the buffer is all zeros so there is no point - // creating the buffer. - size_t j = 0; - // do nothing whilst 0 - for (; (j < SegmentLength) && (a_Src[i * SegmentLength + j] == 0); j++); - if (j != SegmentLength) - { - m_Sections[i] = Allocate(); - memcpy( - &m_Sections[i]->m_BlockMeta, - &a_Src[i * SegmentLength], - sizeof(BLOCKTYPE) * SegmentLength - ); - memset( - m_Sections[i]->m_BlockTypes, - 0x00, - sizeof(m_Sections[i]->m_BlockTypes) - ); - memset( - m_Sections[i]->m_BlockLight, - 0x00, - sizeof(m_Sections[i]->m_BlockLight) - ); - memset( - m_Sections[i]->m_BlockSkyLight, - 0xFF, - sizeof(m_Sections[i]->m_BlockSkyLight) - ); - } + // No need for the section, the data is all zeroes + continue; } - } + + // Allocate the section and copy the data into it: + m_Sections[i] = Allocate(); + memcpy(&m_Sections[i]->m_BlockMeta, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength); + memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes)); + memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight)); + memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight)); + } // for i - m_Sections[] } + void cChunkData::SetBlockLight(const NIBBLETYPE * a_Src) { if (a_Src == NULL) { return; } - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + // If the section is already allocated, copy the data into it: if (m_Sections[i] != NULL) { - memcpy( - &m_Sections[i]->m_BlockLight, - &a_Src[i * SegmentLength], - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&m_Sections[i]->m_BlockLight, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength); + continue; } - else + + // The section doesn't exist, find out if it is needed: + if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0)) { - // j counts how many of leading zeros the buffer has - // if j == SegmentLength then the buffer is all zeros so there is no point - // creating the buffer. - size_t j = 0; - // do nothing whilst 0 - for (; (j < SegmentLength) && (a_Src[i * SegmentLength + j] == 0); j++); - if (j != SegmentLength) - { - m_Sections[i] = Allocate(); - memcpy( - &m_Sections[i]->m_BlockLight, - &a_Src[i * SegmentLength], - sizeof(BLOCKTYPE) * SegmentLength - ); - memset( - m_Sections[i]->m_BlockTypes, - 0x00, - sizeof(m_Sections[i]->m_BlockTypes) - ); - memset( - m_Sections[i]->m_BlockMeta, - 0x00, - sizeof(m_Sections[i]->m_BlockMeta) - ); - memset( - m_Sections[i]->m_BlockSkyLight, - 0xFF, - sizeof(m_Sections[i]->m_BlockSkyLight) - ); - } + // No need for the section, the data is all zeroes + continue; } - } + + // Allocate the section and copy the data into it: + m_Sections[i] = Allocate(); + memcpy(&m_Sections[i]->m_BlockLight, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength); + memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes)); + memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta)); + memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight)); + } // for i - m_Sections[] } @@ -598,51 +529,29 @@ void cChunkData::SetSkyLight(const NIBBLETYPE * a_Src) return; } - for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) + for (size_t i = 0; i < NumSections; i++) { - const size_t SegmentLength = CHUNK_SECTION_HEIGHT * 16 * 16 / 2; + // If the section is already allocated, copy the data into it: if (m_Sections[i] != NULL) { - memcpy( - &m_Sections[i]->m_BlockSkyLight, - &a_Src[i * SegmentLength], - sizeof(NIBBLETYPE) * SegmentLength - ); + memcpy(&m_Sections[i]->m_BlockSkyLight, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength); + continue; } - else + + // The section doesn't exist, find out if it is needed: + if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0xff)) { - // j counts how many of leading zeros the buffer has - // if j == SegmentLength then the buffer is all zeros so there is no point - // creating the buffer. - size_t j = 0; - // do nothing whilst 0 - for (; (j < SegmentLength) && (a_Src[i * SegmentLength + j]) == 0xFF; j++); - if (j != SegmentLength) - { - m_Sections[i] = Allocate(); - memcpy( - &m_Sections[i]->m_BlockSkyLight, - &a_Src[i * SegmentLength], - sizeof(BLOCKTYPE) * SegmentLength - ); - memset( - m_Sections[i]->m_BlockTypes, - 0x00, - sizeof(m_Sections[i]->m_BlockTypes) - ); - memset( - m_Sections[i]->m_BlockMeta, - 0x00, - sizeof(m_Sections[i]->m_BlockMeta) - ); - memset( - m_Sections[i]->m_BlockLight, - 0x00, - sizeof(m_Sections[i]->m_BlockLight) - ); - } + // No need for the section, the data is all zeroes + continue; } - } + + // Allocate the section and copy the data into it: + m_Sections[i] = Allocate(); + memcpy(&m_Sections[i]->m_BlockSkyLight, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength); + memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes)); + memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta)); + memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight)); + } // for i - m_Sections[] } @@ -671,26 +580,10 @@ void cChunkData::Free(cChunkData::sChunkSection * a_Section) void cChunkData::ZeroSection(cChunkData::sChunkSection * a_Section) const { - memset( - a_Section->m_BlockTypes, - 0x00, - sizeof(a_Section->m_BlockTypes) - ); - memset( - a_Section->m_BlockMeta, - 0x00, - sizeof(a_Section->m_BlockMeta) - ); - memset( - a_Section->m_BlockLight, - 0x00, - sizeof(a_Section->m_BlockLight) - ); - memset( - a_Section->m_BlockSkyLight, - 0xFF, - sizeof(a_Section->m_BlockSkyLight) - ); + memset(a_Section->m_BlockTypes, 0x00, sizeof(a_Section->m_BlockTypes)); + memset(a_Section->m_BlockMeta, 0x00, sizeof(a_Section->m_BlockMeta)); + memset(a_Section->m_BlockLight, 0x00, sizeof(a_Section->m_BlockLight)); + memset(a_Section->m_BlockSkyLight, 0xff, sizeof(a_Section->m_BlockSkyLight)); } diff --git a/src/ChunkData.h b/src/ChunkData.h index e6aaa99b8..341c15301 100644 --- a/src/ChunkData.h +++ b/src/ChunkData.h @@ -1,4 +1,12 @@ +// ChunkData.h + +// Declares the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk + + + + + #pragma once @@ -20,7 +28,7 @@ class cChunkData { public: - cChunkData(); + cChunkData(void); ~cChunkData(); #if __cplusplus < 201103L @@ -43,25 +51,48 @@ public: NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const; + /** Creates a (deep) copy of self. */ cChunkData Copy(void) const; - // Copys data from this object into the buffer in the a_Dest param - // CopyBlocks also povides the optional parameters a_Idx and a_Length which specify an offset and length for - // copying part of the BlockTypes array. - void CopyBlocks (BLOCKTYPE * a_Dest, size_t a_Idx = 0, size_t a_Length = cChunkDef::NumBlocks) const; - void CopyMeta (NIBBLETYPE * a_Dest) const; + /** Copies the blocktype data into the specified flat array. + Optionally, only a part of the data is copied, as specified by the a_Idx and a_Length parameters. */ + void CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx = 0, size_t a_Length = cChunkDef::NumBlocks) const; + + /** Copies the metadata into the specified flat array. */ + void CopyMetas(NIBBLETYPE * a_Dest) const; + + /** Copies the block light data into the specified flat array. */ void CopyBlockLight(NIBBLETYPE * a_Dest) const; + + /** Copies the skylight data into the specified flat array. */ void CopySkyLight (NIBBLETYPE * a_Dest) const; - void SetBlocks (const BLOCKTYPE * a_src); - void SetMeta (const NIBBLETYPE * a_src); - void SetBlockLight(const NIBBLETYPE * a_src); - void SetSkyLight (const NIBBLETYPE * a_src); + /** 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. */ + void SetBlockTypes(const BLOCKTYPE * a_Src); + + /** Copies the metadata from the specified flat array into the internal representation. + Allocates sectios that are needed for the operation. + Requires that a_Src is a valid pointer. */ + void SetMetas(const NIBBLETYPE * a_Src); + + /** Copies the blocklight data from the specified flat array into the internal representation. + Allocates sectios that are needed for the operation. + Allows a_Src to be NULL, in which case it doesn't do anything. */ + void SetBlockLight(const NIBBLETYPE * a_Src); + + /** Copies the skylight data from the specified flat array into the internal representation. + Allocates sectios that are needed for the operation. + Allows a_Src to be NULL, in which case it doesn't do anything. */ + void SetSkyLight(const NIBBLETYPE * a_Src); private: - static const size_t CHUNK_SECTION_HEIGHT = 16; - static const size_t CHUNK_SECTION_COUNT = (256 / CHUNK_SECTION_HEIGHT); + static const size_t SectionHeight = 16; + static const size_t NumSections = (cChunkDef::Height / SectionHeight); + static const size_t SegmentLength = cChunkDef::Width * cChunkDef::Height * SectionHeight; + static const size_t SectionBlockCount = SectionHeight * cChunkDef::Width * cChunkDef::Width; #if __cplusplus < 201103L // auto_ptr style interface for memory management @@ -69,13 +100,13 @@ private: #endif struct sChunkSection { - BLOCKTYPE m_BlockTypes [CHUNK_SECTION_HEIGHT * 16 * 16]; - NIBBLETYPE m_BlockMeta [CHUNK_SECTION_HEIGHT * 16 * 16 / 2]; - NIBBLETYPE m_BlockLight [CHUNK_SECTION_HEIGHT * 16 * 16 / 2]; - NIBBLETYPE m_BlockSkyLight[CHUNK_SECTION_HEIGHT * 16 * 16 / 2]; + BLOCKTYPE m_BlockTypes [SectionBlockCount]; + NIBBLETYPE m_BlockMeta [SectionBlockCount / 2]; + NIBBLETYPE m_BlockLight [SectionBlockCount / 2]; + NIBBLETYPE m_BlockSkyLight[SectionBlockCount / 2]; }; - sChunkSection * m_Sections[CHUNK_SECTION_COUNT]; + sChunkSection * m_Sections[NumSections]; /** Allocates a new section. Entry-point to custom allocators. */ static sChunkSection * Allocate(void); diff --git a/src/ChunkDataCallback.h b/src/ChunkDataCallback.h index e916d6486..0c8b1098f 100644 --- a/src/ChunkDataCallback.h +++ b/src/ChunkDataCallback.h @@ -1,11 +1,20 @@ +// ChunkDataCallback.h + +// Declares the cChunkDataCallback interface and several trivial descendants, for reading chunk data + + + + #pragma once - #include "ChunkData.h" + + + /** Interface class used for getting data out of a chunk using the GetAllData() function. Implementation must use the pointers immediately and NOT store any of them for later use The virtual methods are called in the same order as they're declared here. @@ -41,6 +50,10 @@ public: virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); }; } ; + + + + /** A simple implementation of the cChunkDataCallback interface that collects all block data into a buffer */ class cChunkDataCollector : @@ -59,6 +72,9 @@ protected: }; + + + /** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer */ class cChunkDataArrayCollector : @@ -73,15 +89,18 @@ protected: virtual void ChunkData(const cChunkData & a_ChunkBuffer) override { - a_ChunkBuffer.CopyBlocks(m_BlockData); - a_ChunkBuffer.CopyMeta(m_BlockData + cChunkDef::NumBlocks); + a_ChunkBuffer.CopyBlockTypes(m_BlockData); + a_ChunkBuffer.CopyMetas(m_BlockData + cChunkDef::NumBlocks); a_ChunkBuffer.CopyBlockLight(m_BlockData + 3 * cChunkDef::NumBlocks / 2); a_ChunkBuffer.CopySkyLight(m_BlockData + 2 * cChunkDef::NumBlocks); } }; -/** A simple implementation of the cChunkDataCallback interface that collects all block data into a separate buffers -*/ + + + + +/** A simple implementation of the cChunkDataCallback interface that collects all block data into separate buffers */ class cChunkDataSeparateCollector : public cChunkDataCallback { @@ -96,10 +115,13 @@ protected: virtual void ChunkData(const cChunkData & a_ChunkBuffer) override { - a_ChunkBuffer.CopyBlocks(m_BlockTypes); - a_ChunkBuffer.CopyMeta(m_BlockMetas); - a_ChunkBuffer.CopyBlockLight(m_BlockLight); - a_ChunkBuffer.CopySkyLight(m_BlockSkyLight); + a_ChunkBuffer.CopyBlockTypes(m_BlockTypes); + a_ChunkBuffer.CopyMetas(m_BlockMetas); + a_ChunkBuffer.CopyBlockLight(m_BlockLight); + a_ChunkBuffer.CopySkyLight(m_BlockSkyLight); } } ; + + + diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp index 879252c34..dc19bf500 100644 --- a/src/LightingThread.cpp +++ b/src/LightingThread.cpp @@ -27,7 +27,7 @@ class cReader : { for (int z = 0; z < cChunkDef::Width; z++) { - a_ChunkBuffer.CopyBlocks(OutputRows + OutputIdx * 16, InputIdx * 16, 16); + a_ChunkBuffer.CopyBlockTypes(OutputRows + OutputIdx * 16, InputIdx * 16, 16); InputIdx++; OutputIdx += 3; } // for z