1
0

Added comments, reformatted code.

This commit is contained in:
madmaxoft 2014-05-29 18:25:08 +02:00
parent d9c667d28f
commit f7777e8c75
6 changed files with 226 additions and 280 deletions

View File

@ -1903,7 +1903,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer)
if (m_Area.m_BlockMetas != NULL) 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) if (m_Area.m_BlockLight != NULL)

View File

@ -282,8 +282,8 @@ void cChunk::SetAllData(
CalculateHeightmap(a_BlockTypes); CalculateHeightmap(a_BlockTypes);
} }
m_ChunkData.SetBlocks(a_BlockTypes); m_ChunkData.SetBlockTypes(a_BlockTypes);
m_ChunkData.SetMeta(a_BlockMeta); m_ChunkData.SetMetas(a_BlockMeta);
m_ChunkData.SetBlockLight(a_BlockLight); m_ChunkData.SetBlockLight(a_BlockLight);
m_ChunkData.SetSkyLight(a_BlockSkyLight); m_ChunkData.SetSkyLight(a_BlockSkyLight);
@ -339,7 +339,7 @@ void cChunk::SetLight(
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes) void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
{ {
m_ChunkData.CopyBlocks(a_BlockTypes); m_ChunkData.CopyBlockTypes(a_BlockTypes);
} }

View File

@ -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 "Globals.h"
#include "ChunkData.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 <typename T> 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 #if __cplusplus < 201103L
// auto_ptr style interface for memory management // auto_ptr style interface for memory management
: m_IsOwner(true) : m_IsOwner(true)
#endif #endif
{ {
for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) for (size_t i = 0; i < NumSections; i++)
{ {
m_Sections[i] = NULL; m_Sections[i] = NULL;
} }
@ -27,7 +52,7 @@ cChunkData::~cChunkData()
return; return;
} }
#endif #endif
for (size_t i = 0; i < CHUNK_SECTION_COUNT; i++) for (size_t i = 0; i < NumSections; i++)
{ {
Free(m_Sections[i]); Free(m_Sections[i]);
} }
@ -43,7 +68,7 @@ cChunkData::~cChunkData()
m_IsOwner(true) m_IsOwner(true)
{ {
// Move contents and ownership from a_Other to this, pointer-wise: // 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]; m_Sections[i] = a_Other.m_Sections[i];
} }
@ -65,7 +90,7 @@ cChunkData::~cChunkData()
// Free any currently held contents: // Free any currently held contents:
if (m_IsOwner) 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]); Free(m_Sections[i]);
} }
@ -73,7 +98,7 @@ cChunkData::~cChunkData()
// Move contents and ownership from a_Other to this, pointer-wise: // Move contents and ownership from a_Other to this, pointer-wise:
m_IsOwner = true; 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]; m_Sections[i] = a_Other.m_Sections[i];
} }
@ -86,7 +111,7 @@ cChunkData::~cChunkData()
// unique_ptr style interface for memory management // unique_ptr style interface for memory management
cChunkData::cChunkData(cChunkData && other) 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]; m_Sections[i] = other.m_Sections[i];
other.m_Sections[i] = NULL; other.m_Sections[i] = NULL;
@ -101,7 +126,7 @@ cChunkData::~cChunkData()
{ {
if (&other != this) 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]); Free(m_Sections[i]);
m_Sections[i] = other.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_X >= 0) && (a_X < cChunkDef::Width));
ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height)); ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
ASSERT((a_Z >= 0) && (a_Z < cChunkDef::Width)); 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) 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]; return m_Sections[Section]->m_BlockTypes[Index];
} }
else else
@ -149,7 +174,7 @@ void cChunkData::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block)
return; return;
} }
int Section = a_RelY / CHUNK_SECTION_HEIGHT; int Section = a_RelY / SectionHeight;
if (m_Sections[Section] == NULL) if (m_Sections[Section] == NULL)
{ {
if (a_Block == 0x00) 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]); 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; 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_RelY < cChunkDef::Height) && (a_RelY > -1) &&
(a_RelZ < cChunkDef::Width) && (a_RelZ > -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) 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; return (m_Sections[Section]->m_BlockMeta[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
} }
else else
@ -210,7 +235,7 @@ bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble
return false; return false;
} }
int Section = a_RelY / CHUNK_SECTION_HEIGHT; int Section = a_RelY / SectionHeight;
if (m_Sections[Section] == NULL) if (m_Sections[Section] == NULL)
{ {
if ((a_Nibble & 0xf) == 0x00) 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]); 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; NIBBLETYPE oldval = m_Sections[Section]->m_BlockMeta[Index / 2] >> ((Index & 1) * 4) & 0xf;
m_Sections[Section]->m_BlockMeta[Index / 2] = static_cast<NIBBLETYPE>( m_Sections[Section]->m_BlockMeta[Index / 2] = static_cast<NIBBLETYPE>(
(m_Sections[Section]->m_BlockMeta[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble (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) (a_RelZ < cChunkDef::Width) && (a_RelZ > -1)
) )
{ {
int Section = a_RelY / CHUNK_SECTION_HEIGHT; int Section = a_RelY / SectionHeight;
if (m_Sections[Section] != NULL) 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; return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
} }
else 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)) 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) 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; return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
} }
else else
@ -291,7 +316,7 @@ NIBBLETYPE cChunkData::GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const
cChunkData cChunkData::Copy(void) const cChunkData cChunkData::Copy(void) const
{ {
cChunkData copy; 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) 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) if (a_Idx > 0)
{ {
a_Idx = std::max(a_Idx - a_Length, (size_t) 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; a_Length -= ToCopy;
if (m_Sections[i] != NULL) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockTypes, sizeof(BLOCKTYPE) * ToCopy);
&a_Dest[i * SegmentLength],
&m_Sections[i]->m_BlockTypes,
sizeof(BLOCKTYPE) * ToCopy
);
} }
else else
{ {
memset( memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * ToCopy);
&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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockMeta, sizeof(NIBBLETYPE) * SegmentLength);
&a_Dest[i * SegmentLength],
&m_Sections[i]->m_BlockMeta,
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else else
{ {
memset( memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * SegmentLength);
&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 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockLight, sizeof(NIBBLETYPE) * SegmentLength);
&a_Dest[i * SegmentLength],
&m_Sections[i]->m_BlockLight,
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else else
{ {
memset( memset(&a_Dest[i * SegmentLength], 0, sizeof(BLOCKTYPE) * SegmentLength);
&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 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&a_Dest[i * SegmentLength], &m_Sections[i]->m_BlockSkyLight, sizeof(NIBBLETYPE) * SegmentLength);
&a_Dest[i * SegmentLength],
&m_Sections[i]->m_BlockSkyLight,
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else else
{ {
memset( memset(&a_Dest[i * SegmentLength], 0xff, sizeof(BLOCKTYPE) * SegmentLength);
&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); 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&m_Sections[i]->m_BlockTypes, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength);
&m_Sections[i]->m_BlockTypes, continue;
&a_Src[i * SegmentLength],
sizeof(BLOCKTYPE) * SegmentLength
);
} }
else
{ // The section doesn't exist, find out if it is needed:
// j counts how many of leading zeros the buffer has if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (const BLOCKTYPE)0))
// 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)
{ {
// No need for the section, the data is all-air
continue;
}
// Allocate the section and copy the data into it:
m_Sections[i] = Allocate(); m_Sections[i] = Allocate();
memcpy( memcpy(&m_Sections[i]->m_BlockTypes, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength);
&m_Sections[i]->m_BlockTypes, memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta));
&a_Src[i * SegmentLength], memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
sizeof(BLOCKTYPE) * SegmentLength memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
); } // for i - m_Sections[]
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)
);
}
}
}
} }
void cChunkData::SetMeta(const NIBBLETYPE * a_Src) void cChunkData::SetMetas(const NIBBLETYPE * a_Src)
{ {
ASSERT(a_Src != NULL); 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&m_Sections[i]->m_BlockMeta, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength);
&m_Sections[i]->m_BlockMeta, continue;
&a_Src[i * SegmentLength],
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else
{ // The section doesn't exist, find out if it is needed:
// j counts how many of leading zeros the buffer has if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0))
// 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)
{ {
// No need for the section, the data is all zeroes
continue;
}
// Allocate the section and copy the data into it:
m_Sections[i] = Allocate(); m_Sections[i] = Allocate();
memcpy( memcpy(&m_Sections[i]->m_BlockMeta, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength);
&m_Sections[i]->m_BlockMeta, memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
&a_Src[i * SegmentLength], memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
sizeof(BLOCKTYPE) * SegmentLength memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
); } // for i - m_Sections[]
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)
);
}
}
}
} }
void cChunkData::SetBlockLight(const NIBBLETYPE * a_Src) void cChunkData::SetBlockLight(const NIBBLETYPE * a_Src)
{ {
if (a_Src == NULL) if (a_Src == NULL)
{ {
return; 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&m_Sections[i]->m_BlockLight, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength);
&m_Sections[i]->m_BlockLight, continue;
&a_Src[i * SegmentLength],
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else
{ // The section doesn't exist, find out if it is needed:
// j counts how many of leading zeros the buffer has if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0))
// 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)
{ {
// No need for the section, the data is all zeroes
continue;
}
// Allocate the section and copy the data into it:
m_Sections[i] = Allocate(); m_Sections[i] = Allocate();
memcpy( memcpy(&m_Sections[i]->m_BlockLight, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength);
&m_Sections[i]->m_BlockLight, memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
&a_Src[i * SegmentLength], memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta));
sizeof(BLOCKTYPE) * SegmentLength memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
); } // for i - m_Sections[]
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)
);
}
}
}
} }
@ -598,51 +529,29 @@ void cChunkData::SetSkyLight(const NIBBLETYPE * a_Src)
return; 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) if (m_Sections[i] != NULL)
{ {
memcpy( memcpy(&m_Sections[i]->m_BlockSkyLight, &a_Src[i * SegmentLength], sizeof(NIBBLETYPE) * SegmentLength);
&m_Sections[i]->m_BlockSkyLight, continue;
&a_Src[i * SegmentLength],
sizeof(NIBBLETYPE) * SegmentLength
);
} }
else
{ // The section doesn't exist, find out if it is needed:
// j counts how many of leading zeros the buffer has if (IsAllValue(a_Src + i * SegmentLength, SegmentLength, (NIBBLETYPE)0xff))
// 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)
{ {
// No need for the section, the data is all zeroes
continue;
}
// Allocate the section and copy the data into it:
m_Sections[i] = Allocate(); m_Sections[i] = Allocate();
memcpy( memcpy(&m_Sections[i]->m_BlockSkyLight, &a_Src[i * SegmentLength], sizeof(BLOCKTYPE) * SegmentLength);
&m_Sections[i]->m_BlockSkyLight, memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
&a_Src[i * SegmentLength], memset(m_Sections[i]->m_BlockMeta, 0x00, sizeof(m_Sections[i]->m_BlockMeta));
sizeof(BLOCKTYPE) * SegmentLength memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
); } // for i - m_Sections[]
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)
);
}
}
}
} }
@ -671,26 +580,10 @@ void cChunkData::Free(cChunkData::sChunkSection * a_Section)
void cChunkData::ZeroSection(cChunkData::sChunkSection * a_Section) const void cChunkData::ZeroSection(cChunkData::sChunkSection * a_Section) const
{ {
memset( memset(a_Section->m_BlockTypes, 0x00, sizeof(a_Section->m_BlockTypes));
a_Section->m_BlockTypes, memset(a_Section->m_BlockMeta, 0x00, sizeof(a_Section->m_BlockMeta));
0x00, memset(a_Section->m_BlockLight, 0x00, sizeof(a_Section->m_BlockLight));
sizeof(a_Section->m_BlockTypes) memset(a_Section->m_BlockSkyLight, 0xff, sizeof(a_Section->m_BlockSkyLight));
);
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)
);
} }

View File

@ -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 #pragma once
@ -20,7 +28,7 @@ class cChunkData
{ {
public: public:
cChunkData(); cChunkData(void);
~cChunkData(); ~cChunkData();
#if __cplusplus < 201103L #if __cplusplus < 201103L
@ -43,25 +51,48 @@ public:
NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const; NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const;
/** Creates a (deep) copy of self. */
cChunkData Copy(void) const; cChunkData Copy(void) const;
// Copys data from this object into the buffer in the a_Dest param /** Copies the blocktype data into the specified flat array.
// CopyBlocks also povides the optional parameters a_Idx and a_Length which specify an offset and length for Optionally, only a part of the data is copied, as specified by the a_Idx and a_Length parameters. */
// copying part of the BlockTypes array. void CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx = 0, size_t a_Length = cChunkDef::NumBlocks) const;
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 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; void CopyBlockLight(NIBBLETYPE * a_Dest) const;
/** Copies the skylight data into the specified flat array. */
void CopySkyLight (NIBBLETYPE * a_Dest) const; void CopySkyLight (NIBBLETYPE * a_Dest) const;
void SetBlocks (const BLOCKTYPE * a_src); /** Copies the blocktype data from the specified flat array into the internal representation.
void SetMeta (const NIBBLETYPE * a_src); Allocates sections that are needed for the operation.
void SetBlockLight(const NIBBLETYPE * a_src); Requires that a_Src is a valid pointer. */
void SetSkyLight (const NIBBLETYPE * a_src); 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: private:
static const size_t CHUNK_SECTION_HEIGHT = 16; static const size_t SectionHeight = 16;
static const size_t CHUNK_SECTION_COUNT = (256 / CHUNK_SECTION_HEIGHT); 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 #if __cplusplus < 201103L
// auto_ptr style interface for memory management // auto_ptr style interface for memory management
@ -69,13 +100,13 @@ private:
#endif #endif
struct sChunkSection { struct sChunkSection {
BLOCKTYPE m_BlockTypes [CHUNK_SECTION_HEIGHT * 16 * 16]; BLOCKTYPE m_BlockTypes [SectionBlockCount];
NIBBLETYPE m_BlockMeta [CHUNK_SECTION_HEIGHT * 16 * 16 / 2]; NIBBLETYPE m_BlockMeta [SectionBlockCount / 2];
NIBBLETYPE m_BlockLight [CHUNK_SECTION_HEIGHT * 16 * 16 / 2]; NIBBLETYPE m_BlockLight [SectionBlockCount / 2];
NIBBLETYPE m_BlockSkyLight[CHUNK_SECTION_HEIGHT * 16 * 16 / 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. */ /** Allocates a new section. Entry-point to custom allocators. */
static sChunkSection * Allocate(void); static sChunkSection * Allocate(void);

View File

@ -1,11 +1,20 @@
// ChunkDataCallback.h
// Declares the cChunkDataCallback interface and several trivial descendants, for reading chunk data
#pragma once #pragma once
#include "ChunkData.h" #include "ChunkData.h"
/** Interface class used for getting data out of a chunk using the GetAllData() function. /** 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 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. 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); }; virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); };
} ; } ;
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a buffer /** A simple implementation of the cChunkDataCallback interface that collects all block data into a buffer
*/ */
class cChunkDataCollector : class cChunkDataCollector :
@ -59,6 +72,9 @@ protected:
}; };
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer /** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer
*/ */
class cChunkDataArrayCollector : class cChunkDataArrayCollector :
@ -73,15 +89,18 @@ protected:
virtual void ChunkData(const cChunkData & a_ChunkBuffer) override virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
{ {
a_ChunkBuffer.CopyBlocks(m_BlockData); a_ChunkBuffer.CopyBlockTypes(m_BlockData);
a_ChunkBuffer.CopyMeta(m_BlockData + cChunkDef::NumBlocks); a_ChunkBuffer.CopyMetas(m_BlockData + cChunkDef::NumBlocks);
a_ChunkBuffer.CopyBlockLight(m_BlockData + 3 * cChunkDef::NumBlocks / 2); a_ChunkBuffer.CopyBlockLight(m_BlockData + 3 * cChunkDef::NumBlocks / 2);
a_ChunkBuffer.CopySkyLight(m_BlockData + 2 * cChunkDef::NumBlocks); 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 : class cChunkDataSeparateCollector :
public cChunkDataCallback public cChunkDataCallback
{ {
@ -96,10 +115,13 @@ protected:
virtual void ChunkData(const cChunkData & a_ChunkBuffer) override virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
{ {
a_ChunkBuffer.CopyBlocks(m_BlockTypes); a_ChunkBuffer.CopyBlockTypes(m_BlockTypes);
a_ChunkBuffer.CopyMeta(m_BlockMetas); a_ChunkBuffer.CopyMetas(m_BlockMetas);
a_ChunkBuffer.CopyBlockLight(m_BlockLight); a_ChunkBuffer.CopyBlockLight(m_BlockLight);
a_ChunkBuffer.CopySkyLight(m_BlockSkyLight); a_ChunkBuffer.CopySkyLight(m_BlockSkyLight);
} }
} ; } ;

View File

@ -27,7 +27,7 @@ class cReader :
{ {
for (int z = 0; z < cChunkDef::Width; z++) 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++; InputIdx++;
OutputIdx += 3; OutputIdx += 3;
} // for z } // for z