From 2df14a04962037b93352c2fc53349af54ab3b14d Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Sun, 4 Feb 2018 22:15:31 +0000 Subject: [PATCH] cChunk and cChunkData: Use vectors for block get and set functions (#4172) * cChunkData: Change interface to use Vector3i * cChunk: Add Vector3i overloads for bounded block get and set functions. --- src/BlockArea.cpp | 8 +- src/Chunk.cpp | 31 +++---- src/Chunk.h | 65 +++++++++----- src/ChunkData.cpp | 140 +++++++++++++++---------------- src/ChunkData.h | 12 +-- src/ChunkDef.h | 10 +++ tests/ChunkData/ArraytoCoord.cpp | 54 ++++++------ tests/ChunkData/Coordinates.cpp | 84 +++++++++---------- tests/ChunkData/Copies.cpp | 58 ++++++------- 9 files changed, 243 insertions(+), 219 deletions(-) diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp index 5e66e4aec..bd9ba3a9f 100644 --- a/src/BlockArea.cpp +++ b/src/BlockArea.cpp @@ -2895,7 +2895,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) { int InChunkX = BaseX + x; int AreaX = OffX + x; - m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlock(InChunkX, InChunkY, InChunkZ); + m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlock({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y @@ -2916,7 +2916,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) { int InChunkX = BaseX + x; int AreaX = OffX + x; - m_Area.m_BlockMetas[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetMeta(InChunkX, InChunkY, InChunkZ); + m_Area.m_BlockMetas[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetMeta({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y @@ -2937,7 +2937,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) { int InChunkX = BaseX + x; int AreaX = OffX + x; - m_Area.m_BlockLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlockLight(InChunkX, InChunkY, InChunkZ); + m_Area.m_BlockLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlockLight({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y @@ -2958,7 +2958,7 @@ void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) { int InChunkX = BaseX + x; int AreaX = OffX + x; - m_Area.m_BlockSkyLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetSkyLight(InChunkX, InChunkY, InChunkZ); + m_Area.m_BlockSkyLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetSkyLight({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 8d88ed3a4..ff3ff7243 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1659,7 +1659,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT ASSERT(IsValid()); const BLOCKTYPE OldBlockType = GetBlock(a_RelX, a_RelY, a_RelZ); - const BLOCKTYPE OldBlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ); + const BLOCKTYPE OldBlockMeta = m_ChunkData.GetMeta({ a_RelX, a_RelY, a_RelZ }); if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta)) { return; @@ -1677,7 +1677,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT MarkDirty(); } - m_ChunkData.SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType); + m_ChunkData.SetBlock({ a_RelX, a_RelY, a_RelZ }, a_BlockType); // Queue block to be sent only if ... if ( @@ -1696,7 +1696,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta)); } - m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta); + m_ChunkData.SetMeta({ a_RelX, a_RelY, a_RelZ }, a_BlockMeta); // ONLY recalculate lighting if it's necessary! if ( @@ -2471,31 +2471,22 @@ bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_ -BLOCKTYPE cChunk::GetBlock(int a_RelX, int a_RelY, int a_RelZ) const +void cChunk::GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { - return m_ChunkData.GetBlock(a_RelX, a_RelY, a_RelZ); + a_BlockType = GetBlock(a_RelPos); + a_BlockMeta = GetMeta(a_RelPos); } -void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const +void cChunk::GetBlockInfo(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) { - a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ); - a_BlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ); -} - - - - - -void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) -{ - a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ); - a_Meta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ); - a_SkyLight = m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ); - a_BlockLight = m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ); + a_BlockType = GetBlock(a_RelPos); + a_Meta = m_ChunkData.GetMeta(a_RelPos); + a_SkyLight = m_ChunkData.GetSkyLight(a_RelPos); + a_BlockLight = m_ChunkData.GetBlockLight(a_RelPos); } diff --git a/src/Chunk.h b/src/Chunk.h index d6856f911..18b3e9482 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -154,7 +154,7 @@ public: void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true); // SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense - void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta); } + void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta); } /** Queues block for ticking (m_ToTickQueue) */ void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ); @@ -163,10 +163,25 @@ public: void QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ); void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients = true); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc. - BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const; - BLOCKTYPE GetBlock(const Vector3i & a_RelCoords) const { return GetBlock(a_RelCoords.x, a_RelCoords.y, a_RelCoords.z); } - void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; - void GetBlockInfo (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight); + void FastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients = true) + { + FastSetBlock(a_RelPos.x, a_RelPos.y, a_RelPos.z, a_BlockType, a_BlockMeta, a_SendToClients); + } + + BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const { return m_ChunkData.GetBlock({ a_RelX, a_RelY, a_RelZ }); } + BLOCKTYPE GetBlock(Vector3i a_RelCoords) const { return m_ChunkData.GetBlock(a_RelCoords); } + + void GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; + void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const + { + GetBlockTypeMeta({ a_RelX, a_RelY, a_RelZ }, a_BlockType, a_BlockMeta); + } + + void GetBlockInfo(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight); + void GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) + { + GetBlockInfo({ a_RelX, a_RelY, a_RelZ }, a_BlockType, a_Meta, a_SkyLight, a_BlockLight); + } /** Convert absolute coordinates into relative coordinates. Returns false on failure to obtain a valid chunk. Returns true otherwise. @@ -392,39 +407,49 @@ public: inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { - return m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ); + return m_ChunkData.GetMeta({ a_RelX, a_RelY, a_RelZ }); + } + + NIBBLETYPE GetMeta(Vector3i a_RelPos) const { return m_ChunkData.GetMeta(a_RelPos); } + + void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta, bool a_ShouldMarkDirty = true, bool a_ShouldInformClients = true) + { + SetMeta({ a_RelX, a_RelY, a_RelZ }, a_Meta, a_ShouldMarkDirty, a_ShouldInformClients); } /** Set a meta value, with the option of not informing the client and / or not marking dirty. Used for setting metas that are of little value for saving to disk and / or for sending to the client, such as leaf decay flags. */ - inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta, bool a_ShouldMarkDirty = true, bool a_ShouldInformClients = true) + inline void SetMeta(Vector3i a_RelPos, NIBBLETYPE a_Meta, bool a_ShouldMarkDirty = true, bool a_ShouldInformClients = true) { - bool hasChanged = m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_Meta); - if (hasChanged) + bool hasChanged = m_ChunkData.SetMeta(a_RelPos, a_Meta); + if (hasChanged) + { + if (a_ShouldMarkDirty) { - if (a_ShouldMarkDirty) - { - MarkDirty(); - } - if (a_ShouldInformClients) - { - m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), a_Meta)); - } + MarkDirty(); } + if (a_ShouldInformClients) + { + m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelPos.x, a_RelPos.y, a_RelPos.z, GetBlock(a_RelPos), a_Meta)); + } + } } /** Light alterations based on time */ NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const; /** Get the level of artificial light illuminating the block (0 - 15) */ - inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ); } + inline NIBBLETYPE GetBlockLight(Vector3i a_RelPos) const { return m_ChunkData.GetBlockLight(a_RelPos); } + inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const { return m_ChunkData.GetBlockLight({ a_RelX, a_RelY, a_RelZ }); } /** Get the level of sky light illuminating the block (0 - 15) independent of daytime. */ - inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ); } + inline NIBBLETYPE GetSkyLight(Vector3i a_RelPos) const { return m_ChunkData.GetSkyLight(a_RelPos); } + inline NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const { return m_ChunkData.GetSkyLight({ a_RelX, a_RelY, a_RelZ }); } /** Get the level of sky light illuminating the block (0 - 15), taking daytime into a account. */ - inline NIBBLETYPE GetSkyLightAltered (int a_RelX, int a_RelY, int a_RelZ) const {return GetTimeAlteredLight(m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ)); } + inline NIBBLETYPE GetSkyLightAltered(Vector3i a_RelPos) const { return GetTimeAlteredLight(m_ChunkData.GetSkyLight(a_RelPos)); } + inline NIBBLETYPE GetSkyLightAltered(int a_RelX, int a_RelY, int a_RelZ) const { return GetSkyLightAltered({ a_RelX, a_RelY, a_RelZ }); } /** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */ bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; diff --git a/src/ChunkData.cpp b/src/ChunkData.cpp index 310945f17..70e06b032 100644 --- a/src/ChunkData.cpp +++ b/src/ChunkData.cpp @@ -10,18 +10,41 @@ -/** 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) +namespace { - for (size_t i = 0; i < a_NumElements; i++) + /** Returns true if all a_Array's elements between [0] and [a_NumElements - 1] are equal to a_Value. */ + template + bool IsAllValue(const T * a_Array, size_t a_NumElements, T a_Value) { - if (a_Array[i] != a_Value) + for (size_t i = 0; i < a_NumElements; i++) { - return false; + if (a_Array[i] != a_Value) + { + return false; + } } + return true; } - return true; -} + + + + + + struct sSectionIndices + { + int Section = 0; // Index into m_Sections + int Index = 0; // Index into a single sChunkSection + }; + + sSectionIndices IndicesFromRelPos(Vector3i a_RelPos) + { + ASSERT(cChunkDef::IsValidRelPos(a_RelPos)); + sSectionIndices Ret; + Ret.Section = a_RelPos.y / cChunkData::SectionHeight; + Ret.Index = cChunkDef::MakeIndexNoCheck(a_RelPos.x, a_RelPos.y % cChunkData::SectionHeight, a_RelPos.z); + return Ret; + } +} // namespace (anonymous) @@ -110,21 +133,16 @@ void cChunkData::Assign(cChunkData && a_Other) -BLOCKTYPE cChunkData::GetBlock(int a_X, int a_Y, int a_Z) const +BLOCKTYPE cChunkData::GetBlock(Vector3i a_RelPos) const { - if ( - (a_X < 0) || (a_X >= cChunkDef::Width) || - (a_Y < 0) || (a_Y >= cChunkDef::Height) || - (a_Z < 0) || (a_Z >= cChunkDef::Width) - ) + if (!cChunkDef::IsValidRelPos(a_RelPos)) { return E_BLOCK_AIR; // Coordinates are outside outside the world, so this must be an air block } - int Section = a_Y / SectionHeight; - if (m_Sections[Section] != nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] != nullptr) { - int Index = cChunkDef::MakeIndexNoCheck(a_X, static_cast(static_cast(a_Y) - (static_cast(Section) * SectionHeight)), a_Z); - return m_Sections[Section]->m_BlockTypes[Index]; + return m_Sections[Idxs.Section]->m_BlockTypes[Idxs.Index]; } else { @@ -136,53 +154,44 @@ BLOCKTYPE cChunkData::GetBlock(int a_X, int a_Y, int a_Z) const -void cChunkData::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block) +void cChunkData::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_Block) { - if ( - (a_RelX >= cChunkDef::Width) || (a_RelX < 0) || - (a_RelY >= cChunkDef::Height) || (a_RelY < 0) || - (a_RelZ >= cChunkDef::Width) || (a_RelZ < 0) - ) + if (!cChunkDef::IsValidRelPos(a_RelPos)) { ASSERT(!"cChunkData::SetMeta(): index out of range!"); return; } - int Section = static_cast(static_cast(a_RelY) / SectionHeight); - if (m_Sections[Section] == nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] == nullptr) { if (a_Block == 0x00) { return; } - m_Sections[Section] = Allocate(); - if (m_Sections[Section] == nullptr) + m_Sections[Idxs.Section] = Allocate(); + if (m_Sections[Idxs.Section] == nullptr) { ASSERT(!"Failed to allocate a new section in Chunkbuffer"); return; } - ZeroSection(m_Sections[Section]); + ZeroSection(m_Sections[Idxs.Section]); } - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, static_cast(static_cast(a_RelY) - (static_cast(Section) * SectionHeight)), a_RelZ); - m_Sections[Section]->m_BlockTypes[Index] = a_Block; + m_Sections[Idxs.Section]->m_BlockTypes[Idxs.Index] = a_Block; } -NIBBLETYPE cChunkData::GetMeta(int a_RelX, int a_RelY, int a_RelZ) const +NIBBLETYPE cChunkData::GetMeta(Vector3i a_RelPos) const { - if ( - (a_RelX < cChunkDef::Width) && (a_RelX > -1) && - (a_RelY < cChunkDef::Height) && (a_RelY > -1) && - (a_RelZ < cChunkDef::Width) && (a_RelZ > -1)) + if (cChunkDef::IsValidRelPos(a_RelPos)) { - int Section = static_cast(static_cast(a_RelY) / SectionHeight); - if (m_Sections[Section] != nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] != nullptr) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, static_cast(static_cast(a_RelY) - (static_cast(Section) * SectionHeight)), a_RelZ); - return (m_Sections[Section]->m_BlockMetas[Index / 2] >> ((Index & 1) * 4)) & 0x0f; + return (m_Sections[Idxs.Section]->m_BlockMetas[Idxs.Index / 2] >> ((Idxs.Index & 1) * 4)) & 0x0f; } else { @@ -197,38 +206,33 @@ NIBBLETYPE cChunkData::GetMeta(int a_RelX, int a_RelY, int a_RelZ) const -bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble) +bool cChunkData::SetMeta(Vector3i a_RelPos, NIBBLETYPE a_Nibble) { - if ( - (a_RelX >= cChunkDef::Width) || (a_RelX < 0) || - (a_RelY >= cChunkDef::Height) || (a_RelY < 0) || - (a_RelZ >= cChunkDef::Width) || (a_RelZ < 0) - ) + if (!cChunkDef::IsValidRelPos(a_RelPos)) { ASSERT(!"cChunkData::SetMeta(): index out of range!"); return false; } - int Section = static_cast(static_cast(a_RelY) / SectionHeight); - if (m_Sections[Section] == nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] == nullptr) { if ((a_Nibble & 0xf) == 0x00) { return false; } - m_Sections[Section] = Allocate(); - if (m_Sections[Section] == nullptr) + m_Sections[Idxs.Section] = Allocate(); + if (m_Sections[Idxs.Section] == nullptr) { ASSERT(!"Failed to allocate a new section in Chunkbuffer"); return false; } - ZeroSection(m_Sections[Section]); + ZeroSection(m_Sections[Idxs.Section]); } - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, static_cast(static_cast(a_RelY) - (static_cast(Section) * SectionHeight)), a_RelZ); - NIBBLETYPE oldval = m_Sections[Section]->m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0xf; - m_Sections[Section]->m_BlockMetas[Index / 2] = static_cast( - (m_Sections[Section]->m_BlockMetas[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble - ((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set + NIBBLETYPE oldval = m_Sections[Idxs.Section]->m_BlockMetas[Idxs.Index / 2] >> ((Idxs.Index & 1) * 4) & 0xf; + m_Sections[Idxs.Section]->m_BlockMetas[Idxs.Index / 2] = static_cast( + (m_Sections[Idxs.Section]->m_BlockMetas[Idxs.Index / 2] & (0xf0 >> ((Idxs.Index & 1) * 4))) | // The untouched nibble + ((a_Nibble & 0x0f) << ((Idxs.Index & 1) * 4)) // The nibble being set ); return oldval != a_Nibble; } @@ -237,19 +241,14 @@ bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble -NIBBLETYPE cChunkData::GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const +NIBBLETYPE cChunkData::GetBlockLight(Vector3i a_RelPos) const { - if ( - (a_RelX < cChunkDef::Width) && (a_RelX > -1) && - (a_RelY < cChunkDef::Height) && (a_RelY > -1) && - (a_RelZ < cChunkDef::Width) && (a_RelZ > -1) - ) + if (cChunkDef::IsValidRelPos(a_RelPos)) { - int Section = static_cast(static_cast(a_RelY) / SectionHeight); - if (m_Sections[Section] != nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] != nullptr) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, static_cast(static_cast(a_RelY) - (static_cast(Section) * SectionHeight)), a_RelZ); - return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f; + return (m_Sections[Idxs.Section]->m_BlockLight[Idxs.Index / 2] >> ((Idxs.Index & 1) * 4)) & 0x0f; } else { @@ -264,15 +263,14 @@ NIBBLETYPE cChunkData::GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const -NIBBLETYPE cChunkData::GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const +NIBBLETYPE cChunkData::GetSkyLight(Vector3i a_RelPos) const { - if ((a_RelX < cChunkDef::Width) && (a_RelX > -1) && (a_RelY < cChunkDef::Height) && (a_RelY > -1) && (a_RelZ < cChunkDef::Width) && (a_RelZ > -1)) + if (cChunkDef::IsValidRelPos(a_RelPos)) { - int Section = static_cast(static_cast(a_RelY) / SectionHeight); - if (m_Sections[Section] != nullptr) + auto Idxs = IndicesFromRelPos(a_RelPos); + if (m_Sections[Idxs.Section] != nullptr) { - int Index = cChunkDef::MakeIndexNoCheck(a_RelX, static_cast(static_cast(a_RelY) - (static_cast(Section) * SectionHeight)), a_RelZ); - return (m_Sections[Section]->m_BlockSkyLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f; + return (m_Sections[Idxs.Section]->m_BlockSkyLight[Idxs.Index / 2] >> ((Idxs.Index & 1) * 4)) & 0x0f; } else { diff --git a/src/ChunkData.h b/src/ChunkData.h index 6bc2b5366..95a38b194 100644 --- a/src/ChunkData.h +++ b/src/ChunkData.h @@ -48,15 +48,15 @@ public: /** Move assign from another cChunkData */ void Assign(cChunkData && a_Other); - BLOCKTYPE GetBlock(int a_X, int a_Y, int a_Z) const; - void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block); + BLOCKTYPE GetBlock(Vector3i a_RelPos) const; + void SetBlock(Vector3i a_RelPos, BLOCKTYPE a_Block); - NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const; - bool SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble); + NIBBLETYPE GetMeta(Vector3i a_RelPos) const; + bool SetMeta(Vector3i a_RelPos, NIBBLETYPE a_Nibble); - NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const; + NIBBLETYPE GetBlockLight(Vector3i a_RelPos) const; - NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const; + NIBBLETYPE GetSkyLight(Vector3i a_RelPos) const; /** Return a pointer to the chunk section or nullptr if all air */ const sChunkSection * GetSection(size_t a_SectionNum) const; diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 188ad33d8..bdba4061f 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -144,6 +144,16 @@ public: return ((a_Width >= 0) && (a_Width < Width)); } + /** Validates a chunk relative coordinate. Returns false if the coordiante is out of bounds for a chunk. */ + inline static bool IsValidRelPos(Vector3i a_RelPos) + { + return ( + IsValidWidth(a_RelPos.x) && + IsValidHeight(a_RelPos.y) && + IsValidWidth(a_RelPos.z) + ); + } + /** Converts absolute block coords to chunk coords: */ inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ) { diff --git a/tests/ChunkData/ArraytoCoord.cpp b/tests/ChunkData/ArraytoCoord.cpp index 19f7ef105..1591bc9a7 100644 --- a/tests/ChunkData/ArraytoCoord.cpp +++ b/tests/ChunkData/ArraytoCoord.cpp @@ -10,19 +10,19 @@ int main(int argc, char** argv) class cMockAllocationPool : public cAllocationPool - { + { virtual cChunkData::sChunkSection * Allocate() { return new cChunkData::sChunkSection(); } - + virtual void Free(cChunkData::sChunkSection * a_Ptr) { delete a_Ptr; } } Pool; { - + // Test first segment cChunkData buffer(Pool); @@ -30,25 +30,25 @@ int main(int argc, char** argv) memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); SrcBlockBuffer[7 + (4 * 16) + (5 * 16 * 16)] = 0xcd; buffer.SetBlockTypes(SrcBlockBuffer); - testassert(buffer.GetBlock(7, 5, 4) == 0xcd); - + testassert(buffer.GetBlock({ 7, 5, 4 }) == 0xcd); + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe; buffer.SetMetas(SrcNibbleBuffer); - testassert(buffer.GetMeta(6, 2, 1) == 0xe); - + testassert(buffer.GetMeta({ 6, 2, 1 }) == 0xe); + memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe; buffer.SetBlockLight(SrcNibbleBuffer); - testassert(buffer.GetBlockLight(6, 2, 1) == 0xe); - + testassert(buffer.GetBlockLight({ 6, 2, 1 }) == 0xe); + memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe; buffer.SetSkyLight(SrcNibbleBuffer); - testassert(buffer.GetSkyLight(6, 2, 1) == 0xe); + testassert(buffer.GetSkyLight({ 6, 2, 1 }) == 0xe); } - + { // test following segment cChunkData buffer(Pool); @@ -57,25 +57,25 @@ int main(int argc, char** argv) memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); SrcBlockBuffer[7 + (4 * 16) + (24 * 16 * 16)] = 0xcd; buffer.SetBlockTypes(SrcBlockBuffer); - testassert(buffer.GetBlock(7, 24, 4) == 0xcd); - + testassert(buffer.GetBlock({ 7, 24, 4 }) == 0xcd); + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe; buffer.SetMetas(SrcNibbleBuffer); - testassert(buffer.GetMeta(6, 24, 1) == 0xe); - + testassert(buffer.GetMeta({ 6, 24, 1 }) == 0xe); + memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + 1 * 16 + 24 * 16 * 16) / 2] = 0xe; buffer.SetBlockLight(SrcNibbleBuffer); - testassert(buffer.GetBlockLight(6, 24, 1) == 0xe); - + testassert(buffer.GetBlockLight({ 6, 24, 1 }) == 0xe); + memset(SrcNibbleBuffer, 0xff, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe; buffer.SetSkyLight(SrcNibbleBuffer); - testassert(buffer.GetSkyLight(6, 24, 1) == 0xe); + testassert(buffer.GetSkyLight({ 6, 24, 1 }) == 0xe); } - + { // test zeros cChunkData buffer(Pool); @@ -83,22 +83,22 @@ int main(int argc, char** argv) BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); buffer.SetBlockTypes(SrcBlockBuffer); - testassert(buffer.GetBlock(7, 24, 4) == 0x00); - + testassert(buffer.GetBlock({ 7, 24, 4 }) == 0x00); + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); buffer.SetMetas(SrcNibbleBuffer); - testassert(buffer.GetMeta(6, 24, 1) == 0x0); - + testassert(buffer.GetMeta({ 6, 24, 1 }) == 0x0); + memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); buffer.SetBlockLight(SrcNibbleBuffer); - testassert(buffer.GetBlockLight(6, 24, 1) == 0x0); - + testassert(buffer.GetBlockLight({ 6, 24, 1 }) == 0x0); + memset(SrcNibbleBuffer, 0xff, sizeof(SrcNibbleBuffer)); buffer.SetSkyLight(SrcNibbleBuffer); - testassert(buffer.GetSkyLight(6, 24, 1) == 0xf); + testassert(buffer.GetSkyLight({ 6, 24, 1 }) == 0xf); } - + // All tests passed: return 0; } diff --git a/tests/ChunkData/Coordinates.cpp b/tests/ChunkData/Coordinates.cpp index 384af7e03..31aa1179e 100644 --- a/tests/ChunkData/Coordinates.cpp +++ b/tests/ChunkData/Coordinates.cpp @@ -25,98 +25,98 @@ int main(int argc, char** argv) cChunkData buffer(Pool); // Empty chunks - buffer.SetBlock(0, 0, 0, 0xAB); - testassert(buffer.GetBlock(0, 0, 0) == 0xAB); - buffer.SetMeta(0, 16, 0, 0xC); - testassert(buffer.GetMeta(0, 16, 0) == 0xC); + buffer.SetBlock({ 0, 0, 0 }, 0xAB); + testassert(buffer.GetBlock({ 0, 0, 0 }) == 0xAB); + buffer.SetMeta({ 0, 16, 0 }, 0xC); + testassert(buffer.GetMeta({ 0, 16, 0 }) == 0xC); // loaded but not written segments - testassert(buffer.GetBlock(1, 0, 0) == 0x0); - testassert(buffer.GetMeta(1, 16, 0) == 0x0); + testassert(buffer.GetBlock({ 1, 0, 0 }) == 0x0); + testassert(buffer.GetMeta({ 1, 16, 0 }) == 0x0); // Notloaded segments - testassert(buffer.GetBlock(0, 32, 0) == 0x0); - testassert(buffer.GetMeta(0, 48, 0) == 0x0); + testassert(buffer.GetBlock({ 0, 32, 0 }) == 0x0); + testassert(buffer.GetMeta({ 0, 48, 0 }) == 0x0); // Out of range SetBlock CheckAsserts( - buffer.SetBlock(-1, 0, 0, 0); + buffer.SetBlock({ -1, 0, 0 }, 0); ); CheckAsserts( - buffer.SetBlock(0, -1, 0, 0); + buffer.SetBlock({ 0, -1, 0 }, 0); ); CheckAsserts( - buffer.SetBlock(0, 0, -1, 0); + buffer.SetBlock({ 0, 0, -1 }, 0); ); CheckAsserts( - buffer.SetBlock(256, 0, 0, 0); + buffer.SetBlock({ 256, 0, 0 }, 0); ); CheckAsserts( - buffer.SetBlock(0, 256, 0, 0); + buffer.SetBlock({ 0, 256, 0 }, 0); ); CheckAsserts( - buffer.SetBlock(0, 0, 256, 0); + buffer.SetBlock({ 0, 0, 256 }, 0); ); // Out of range SetMeta CheckAsserts( - buffer.SetMeta(-1, 0, 0, 0); + buffer.SetMeta({ -1, 0, 0 }, 0); ); CheckAsserts( - buffer.SetMeta(0, -1, 0, 0); + buffer.SetMeta({ 0, -1, 0 }, 0); ); CheckAsserts( - buffer.SetMeta(0, 0, -1, 0); + buffer.SetMeta({ 0, 0, -1 }, 0); ); CheckAsserts( - buffer.SetMeta(256, 0, 0, 0); + buffer.SetMeta({ 256, 0, 0 }, 0); ); CheckAsserts( - buffer.SetMeta(0, 256, 0, 0); + buffer.SetMeta({ 0, 256, 0 }, 0); ); CheckAsserts( - buffer.SetMeta(0, 0, 256, 0); + buffer.SetMeta({ 0, 0, 256 }, 0); ); // Reading out of range blocks should return air - testassert(buffer.GetBlock(-1, 0, 0) == 0); - testassert(buffer.GetBlock(0, -1, 0) == 0); - testassert(buffer.GetBlock(0, 0, -1) == 0); - testassert(buffer.GetBlock(256, 0, 0) == 0); - testassert(buffer.GetBlock(0, 256, 0) == 0); - testassert(buffer.GetBlock(0, 0, 256) == 0); + testassert(buffer.GetBlock({ -1, 0, 0 }) == 0); + testassert(buffer.GetBlock({ 0, -1, 0 }) == 0); + testassert(buffer.GetBlock({ 0, 0, -1 }) == 0); + testassert(buffer.GetBlock({ 256, 0, 0 }) == 0); + testassert(buffer.GetBlock({ 0, 256, 0 }) == 0); + testassert(buffer.GetBlock({ 0, 0, 256 }) == 0); // Reading out of range metas should return 0 - testassert(buffer.GetMeta(-1, 0, 0) == 0); - testassert(buffer.GetMeta(0, -1, 0) == 0); - testassert(buffer.GetMeta(0, 0, -1) == 0); - testassert(buffer.GetMeta(256, 0, 0) == 0); - testassert(buffer.GetMeta(0, 256, 0) == 0); - testassert(buffer.GetMeta(0, 0, 256) == 0); + testassert(buffer.GetMeta({ -1, 0, 0 }) == 0); + testassert(buffer.GetMeta({ 0, -1, 0 }) == 0); + testassert(buffer.GetMeta({ 0, 0, -1 }) == 0); + testassert(buffer.GetMeta({ 256, 0, 0 }) == 0); + testassert(buffer.GetMeta({ 0, 256, 0 }) == 0); + testassert(buffer.GetMeta({ 0, 0, 256 }) == 0); } { cChunkData buffer(Pool); // Zero's - buffer.SetBlock(0, 0, 0, 0x0); - buffer.SetBlock(0, 0, 1, 0xab); - testassert(buffer.GetBlock(0, 0, 0) == 0x0); - testassert(buffer.GetBlock(0, 0, 1) == 0xab); + buffer.SetBlock({ 0, 0, 0 }, 0x0); + buffer.SetBlock({ 0, 0, 1 }, 0xab); + testassert(buffer.GetBlock({ 0, 0, 0 }) == 0x0); + testassert(buffer.GetBlock({ 0, 0, 1 }) == 0xab); - buffer.SetMeta(0, 16, 0, 0x0); - buffer.SetMeta(0, 16, 1, 0xc); - testassert(buffer.GetMeta(0, 16, 0) == 0x0); - testassert(buffer.GetMeta(0, 16, 1) == 0xc); + buffer.SetMeta({ 0, 16, 0 }, 0x0); + buffer.SetMeta({ 0, 16, 1 }, 0xc); + testassert(buffer.GetMeta({ 0, 16, 0 }) == 0x0); + testassert(buffer.GetMeta({ 0, 16, 1 }) == 0xc); } { // Operator = cChunkData buffer(Pool); - buffer.SetBlock(0, 0, 0, 0x42); + buffer.SetBlock({ 0, 0, 0 }, 0x42); cChunkData copy(Pool); copy = std::move(buffer); - testassert(copy.GetBlock(0, 0, 0) == 0x42); + testassert(copy.GetBlock({ 0, 0, 0 }) == 0x42); } return 0; diff --git a/tests/ChunkData/Copies.cpp b/tests/ChunkData/Copies.cpp index 03d88da97..b4d9c3721 100644 --- a/tests/ChunkData/Copies.cpp +++ b/tests/ChunkData/Copies.cpp @@ -10,12 +10,12 @@ int main(int argc, char** argv) class cMockAllocationPool : public cAllocationPool - { + { virtual cChunkData::sChunkSection * Allocate() { return new cChunkData::sChunkSection(); } - + virtual void Free(cChunkData::sChunkSection * a_Ptr) { delete a_Ptr; @@ -23,15 +23,15 @@ int main(int argc, char** argv) } Pool; { cChunkData buffer(Pool); - - buffer.SetBlock(3, 1, 4, 0xDE); - buffer.SetMeta(3, 1, 4, 0xA); - + + buffer.SetBlock({ 3, 1, 4 }, 0xDE); + buffer.SetMeta({ 3, 1, 4 }, 0xA); + cChunkData copy(Pool); copy.Assign(buffer); - testassert(copy.GetBlock(3, 1, 4) == 0xDE); - testassert(copy.GetMeta(3, 1, 4) == 0xA); - + testassert(copy.GetBlock({ 3, 1, 4 }) == 0xDE); + testassert(copy.GetMeta({ 3, 1, 4 }) == 0xA); + BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; for (int i = 0; i < 16 * 16 * 256; i += 4) { @@ -40,21 +40,21 @@ int main(int argc, char** argv) SrcBlockBuffer[i + 2] = 0xbe; SrcBlockBuffer[i + 3] = 0xef; } - + buffer.SetBlockTypes(SrcBlockBuffer); BLOCKTYPE DstBlockBuffer[16 * 16 * 256]; buffer.CopyBlockTypes(DstBlockBuffer); testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0); - + memset(SrcBlockBuffer, 0x00, 16 * 16 * 256); buffer.SetBlockTypes(SrcBlockBuffer); buffer.CopyBlockTypes(DstBlockBuffer); testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0); } - + { cChunkData buffer(Pool); - + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; for (int i = 0; i < 16 * 16 * 256 / 2; i += 4) { @@ -63,21 +63,21 @@ int main(int argc, char** argv) SrcNibbleBuffer[i + 2] = 0xbe; SrcNibbleBuffer[i + 3] = 0xef; } - + buffer.SetMetas(SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2]; buffer.CopyMetas(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); - + memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2); buffer.SetMetas(SrcNibbleBuffer); buffer.CopyMetas(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); } - + { cChunkData buffer(Pool); - + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; for (int i = 0; i < 16 * 16 * 256 / 2; i += 4) { @@ -86,21 +86,21 @@ int main(int argc, char** argv) SrcNibbleBuffer[i + 2] = 0xbe; SrcNibbleBuffer[i + 3] = 0xef; } - + buffer.SetBlockLight(SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2]; buffer.CopyBlockLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1) == 0); - + memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2); buffer.SetBlockLight(SrcNibbleBuffer); buffer.CopyBlockLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1) == 0); } - + { cChunkData buffer(Pool); - + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; for (int i = 0; i < 16 * 16 * 256 / 2; i += 4) { @@ -109,42 +109,42 @@ int main(int argc, char** argv) SrcNibbleBuffer[i + 2] = 0xbe; SrcNibbleBuffer[i + 3] = 0xef; } - + buffer.SetSkyLight(SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2]; buffer.CopySkyLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); - + memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2); buffer.SetSkyLight(SrcNibbleBuffer); buffer.CopySkyLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); } - + { cChunkData buffer(Pool); - + BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, 16 * 16 * 256); BLOCKTYPE DstBlockBuffer[16 * 16 * 256]; buffer.CopyBlockTypes(DstBlockBuffer); testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0); - + NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 / 2); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2]; buffer.CopyMetas(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); - + memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 / 2); buffer.CopyBlockLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); - + memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2); buffer.CopySkyLight(DstNibbleBuffer); testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0); } - + // All tests successful: return 0; }