diff options
Diffstat (limited to 'src/BlockArea.cpp')
-rw-r--r-- | src/BlockArea.cpp | 578 |
1 files changed, 333 insertions, 245 deletions
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp index 40cca8882..a0dcb5ec8 100644 --- a/src/BlockArea.cpp +++ b/src/BlockArea.cpp @@ -9,22 +9,34 @@ #include "OSSupport/GZipFile.h" #include "Blocks/BlockHandler.h" #include "Cuboid.h" +#include "ChunkData.h" +// Disable MSVC warnings: "conditional expression is constant" +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) +#endif + + + + + +typedef void (CombinatorFunc)(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta); // This wild construct allows us to pass a function argument and still have it inlined by the compiler :) /// Merges two blocktypes and blockmetas of the specified sizes and offsets using the specified combinator function -template<typename Combinator> void InternalMergeBlocks( +template<bool MetasValid, CombinatorFunc Combinator> +void InternalMergeBlocks( BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes, - NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas, + NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas, int a_SizeX, int a_SizeY, int a_SizeZ, int a_SrcOffX, int a_SrcOffY, int a_SrcOffZ, int a_DstOffX, int a_DstOffY, int a_DstOffZ, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, - int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ, - Combinator a_Combinator + int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ ) { UNUSED(a_SrcSizeY); @@ -41,7 +53,15 @@ template<typename Combinator> void InternalMergeBlocks( int DstIdx = DstBaseZ + a_DstOffX; for (int x = 0; x < a_SizeX; x++) { - a_Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], a_DstMetas[DstIdx], a_SrcMetas[SrcIdx]); + if (MetasValid) + { + Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], a_DstMetas[DstIdx], a_SrcMetas[SrcIdx]); + } + else + { + NIBBLETYPE FakeDestMeta = 0; + Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], FakeDestMeta, (NIBBLETYPE)0); + } ++DstIdx; ++SrcIdx; } // for x @@ -54,10 +74,14 @@ template<typename Combinator> void InternalMergeBlocks( /// Combinator used for cBlockArea::msOverwrite merging -static inline void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } } @@ -65,12 +89,16 @@ static inline void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_S /// Combinator used for cBlockArea::msFillAir merging -static inline void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if (a_DstType == E_BLOCK_AIR) { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } } // "else" is the default, already in place } @@ -80,12 +108,16 @@ static inline void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_Src /// Combinator used for cBlockArea::msImprint merging -static inline void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if (a_SrcType != E_BLOCK_AIR) { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } } // "else" is the default, already in place } @@ -95,7 +127,8 @@ static inline void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_Src /// Combinator used for cBlockArea::msLake merging -static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // Sponge is the NOP block if (a_SrcType == E_BLOCK_SPONGE) @@ -103,11 +136,14 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp return; } - // Air is always hollowed out + // Air is always hollowed out if (a_SrcType == E_BLOCK_AIR) { a_DstType = E_BLOCK_AIR; - a_DstMeta = 0; + if (MetaValid) + { + a_DstMeta = 0; + } return; } @@ -132,7 +168,10 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp case E_BLOCK_STATIONARY_LAVA: { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } return; } } @@ -146,7 +185,10 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp case E_BLOCK_MYCELIUM: { a_DstType = E_BLOCK_STONE; - a_DstMeta = 0; + if (MetaValid) + { + a_DstMeta = 0; + } return; } } @@ -159,13 +201,17 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp /** Combinator used for cBlockArea::msSpongePrint merging */ -static inline void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // Sponge overwrites nothing, everything else overwrites anything if (a_SrcType != E_BLOCK_SPONGE) { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } } } @@ -174,17 +220,24 @@ static inline void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a /** Combinator used for cBlockArea::msDifference merging */ -static inline void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { - if ((a_DstType == a_SrcType) && (a_DstMeta == a_SrcMeta)) + if ((a_DstType == a_SrcType) && (!MetaValid || (a_DstMeta == a_SrcMeta))) { a_DstType = E_BLOCK_AIR; - a_DstMeta = 0; + if (MetaValid) + { + a_DstMeta = 0; + } } else { a_DstType = a_SrcType; - a_DstMeta = a_SrcMeta; + if (MetaValid) + { + a_DstMeta = a_SrcMeta; + } } } @@ -193,21 +246,30 @@ static inline void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_ /** Combinator used for cBlockArea::msMask merging */ -static inline void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) +template<bool MetaValid> +void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // If the blocks are the same, keep the dest; otherwise replace with air - if ((a_SrcType != a_DstType) || (a_SrcMeta != a_DstMeta)) + if ((a_SrcType != a_DstType) || !MetaValid || (a_SrcMeta != a_DstMeta)) { a_DstType = E_BLOCK_AIR; - a_DstMeta = 0; + if (MetaValid) + { + a_DstMeta = 0; + } } } +// Re-enable previously disabled MSVC warnings +#ifdef _MSC_VER + #pragma warning(pop) +#endif + -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // cBlockArea: cBlockArea::cBlockArea(void) : @@ -233,9 +295,9 @@ cBlockArea::~cBlockArea() void cBlockArea::Clear(void) { - delete[] m_BlockTypes; m_BlockTypes = NULL; - delete[] m_BlockMetas; m_BlockMetas = NULL; - delete[] m_BlockLight; m_BlockLight = NULL; + delete[] m_BlockTypes; m_BlockTypes = NULL; + delete[] m_BlockMetas; m_BlockMetas = NULL; + delete[] m_BlockLight; m_BlockLight = NULL; delete[] m_BlockSkyLight; m_BlockSkyLight = NULL; m_Origin.Set(0, 0, 0); m_Size.Set(0, 0, 0); @@ -247,6 +309,14 @@ void cBlockArea::Clear(void) void cBlockArea::Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) { + if ((a_SizeX < 0) || (a_SizeY < 0) || (a_SizeZ < 0)) + { + LOGWARNING("Creating a cBlockArea with a negative size! Call to Create ignored. (%d, %d, %d)", + a_SizeX, a_SizeY, a_SizeZ + ); + return; + } + Clear(); int BlockCount = a_SizeX * a_SizeY * a_SizeZ; if ((a_DataTypes & baTypes) != 0) @@ -484,7 +554,7 @@ void cBlockArea::CopyTo(cBlockArea & a_Into) const a_Into.Clear(); a_Into.SetSize(m_Size.x, m_Size.y, m_Size.z, GetDataTypes()); a_Into.m_Origin = m_Origin; - int BlockCount = GetBlockCount(); + size_t BlockCount = GetBlockCount(); if (HasBlockTypes()) { memcpy(a_Into.m_BlockTypes, m_BlockTypes, BlockCount * sizeof(BLOCKTYPE)); @@ -532,7 +602,7 @@ void cBlockArea::DumpToRawFile(const AString & a_FileName) f.Write(&SizeZ, 4); unsigned char DataTypes = (unsigned char)GetDataTypes(); f.Write(&DataTypes, 1); - int NumBlocks = GetBlockCount(); + size_t NumBlocks = GetBlockCount(); if (HasBlockTypes()) { f.Write(m_BlockTypes, NumBlocks * sizeof(BLOCKTYPE)); @@ -637,155 +707,19 @@ void cBlockArea::Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMa void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy) { - // Block types are compulsory, block metas are voluntary - if (!HasBlockTypes() || !a_Src.HasBlockTypes()) - { - LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); - return; - } - - // Dst is *this, Src is a_Src - int SrcOffX = std::max(0, -a_RelX); // Offset in Src where to start reading - int DstOffX = std::max(0, a_RelX); // Offset in Dst where to start writing - int SizeX = std::min(a_Src.GetSizeX() - SrcOffX, GetSizeX() - DstOffX); // How many blocks to copy - - int SrcOffY = std::max(0, -a_RelY); // Offset in Src where to start reading - int DstOffY = std::max(0, a_RelY); // Offset in Dst where to start writing - int SizeY = std::min(a_Src.GetSizeY() - SrcOffY, GetSizeY() - DstOffY); // How many blocks to copy - - int SrcOffZ = std::max(0, -a_RelZ); // Offset in Src where to start reading - int DstOffZ = std::max(0, a_RelZ); // Offset in Dst where to start writing - int SizeZ = std::min(a_Src.GetSizeZ() - SrcOffZ, GetSizeZ() - DstOffZ); // How many blocks to copy const NIBBLETYPE * SrcMetas = a_Src.GetBlockMetas(); NIBBLETYPE * DstMetas = m_BlockMetas; + bool IsDummyMetas = ((SrcMetas == NULL) || (DstMetas == NULL)); if (IsDummyMetas) { - SrcMetas = new NIBBLETYPE[a_Src.GetBlockCount()]; - DstMetas = new NIBBLETYPE[GetBlockCount()]; + MergeByStrategy<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas); } - - switch (a_Strategy) - { - case msOverwrite: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorOverwrite - ); - break; - } // case msOverwrite - - case msFillAir: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorFillAir - ); - break; - } // case msFillAir - - case msImprint: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorImprint - ); - break; - } // case msImprint - - case msLake: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorLake - ); - break; - } // case msLake - - case msSpongePrint: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorSpongePrint - ); - break; - } // case msSpongePrint - - case msDifference: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorDifference - ); - break; - } // case msDifference - - case msMask: - { - InternalMergeBlocks( - m_BlockTypes, a_Src.GetBlockTypes(), - DstMetas, SrcMetas, - SizeX, SizeY, SizeZ, - SrcOffX, SrcOffY, SrcOffZ, - DstOffX, DstOffY, DstOffZ, - a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), - m_Size.x, m_Size.y, m_Size.z, - MergeCombinatorMask - ); - break; - } // case msMask - - default: - { - LOGWARNING("Unknown block area merge strategy: %d", a_Strategy); - ASSERT(!"Unknown block area merge strategy"); - break; - } - } // switch (a_Strategy) - - if (IsDummyMetas) + else { - delete[] SrcMetas; - delete[] DstMetas; + MergeByStrategy<true>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas); } } @@ -812,31 +746,31 @@ void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_Block a_DataTypes = a_DataTypes & GetDataTypes(); } - int BlockCount = GetBlockCount(); + size_t BlockCount = GetBlockCount(); if ((a_DataTypes & baTypes) != 0) { - for (int i = 0; i < BlockCount; i++) + for (size_t i = 0; i < BlockCount; i++) { m_BlockTypes[i] = a_BlockType; } } if ((a_DataTypes & baMetas) != 0) { - for (int i = 0; i < BlockCount; i++) + for (size_t i = 0; i < BlockCount; i++) { m_BlockMetas[i] = a_BlockMeta; } } if ((a_DataTypes & baLight) != 0) { - for (int i = 0; i < BlockCount; i++) + for (size_t i = 0; i < BlockCount; i++) { m_BlockLight[i] = a_BlockLight; } } if ((a_DataTypes & baSkyLight) != 0) { - for (int i = 0; i < BlockCount; i++) + for (size_t i = 0; i < BlockCount; i++) { m_BlockSkyLight[i] = a_BlockSkyLight; } @@ -847,7 +781,7 @@ void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_Block -void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ, +void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) @@ -1079,8 +1013,8 @@ void cBlockArea::RotateCCW(void) } // for x std::swap(m_BlockTypes, NewTypes); std::swap(m_BlockMetas, NewMetas); - delete[] NewTypes; - delete[] NewMetas; + delete[] NewTypes; NewTypes = NULL; + delete[] NewMetas; NewMetas = NULL; std::swap(m_Size.x, m_Size.z); } @@ -1124,8 +1058,8 @@ void cBlockArea::RotateCW(void) } // for x std::swap(m_BlockTypes, NewTypes); std::swap(m_BlockMetas, NewMetas); - delete[] NewTypes; - delete[] NewMetas; + delete[] NewTypes; NewTypes = NULL; + delete[] NewMetas; NewMetas = NULL; std::swap(m_Size.x, m_Size.z); } @@ -1272,7 +1206,7 @@ void cBlockArea::RotateCCWNoMeta(void) } // for z } // for x std::swap(m_BlockTypes, NewTypes); - delete[] NewTypes; + delete[] NewTypes; NewTypes = NULL; } if (HasBlockMetas()) { @@ -1290,7 +1224,7 @@ void cBlockArea::RotateCCWNoMeta(void) } // for z } // for x std::swap(m_BlockMetas, NewMetas); - delete[] NewMetas; + delete[] NewMetas; NewMetas = NULL; } std::swap(m_Size.x, m_Size.z); } @@ -1317,7 +1251,7 @@ void cBlockArea::RotateCWNoMeta(void) } // for x } // for z std::swap(m_BlockTypes, NewTypes); - delete[] NewTypes; + delete[] NewTypes; NewTypes = NULL; } if (HasBlockMetas()) { @@ -1335,7 +1269,7 @@ void cBlockArea::RotateCWNoMeta(void) } // for x } // for z std::swap(m_BlockMetas, NewMetas); - delete[] NewMetas; + delete[] NewMetas; NewMetas = NULL; } std::swap(m_Size.x, m_Size.z); } @@ -1724,6 +1658,7 @@ bool cBlockArea::SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) if (m_BlockMetas == NULL) { delete[] m_BlockTypes; + m_BlockTypes = NULL; return false; } } @@ -1733,7 +1668,9 @@ bool cBlockArea::SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) if (m_BlockLight == NULL) { delete[] m_BlockMetas; + m_BlockMetas = NULL; delete[] m_BlockTypes; + m_BlockTypes = NULL; return false; } } @@ -1743,8 +1680,11 @@ bool cBlockArea::SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) if (m_BlockSkyLight == NULL) { delete[] m_BlockLight; + m_BlockLight = NULL; delete[] m_BlockMetas; + m_BlockMetas = NULL; delete[] m_BlockTypes; + m_BlockTypes = NULL; return false; } } @@ -1819,7 +1759,7 @@ NIBBLETYPE cBlockArea::GetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBL -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // cBlockArea::cChunkReader: cBlockArea::cChunkReader::cChunkReader(cBlockArea & a_Area) : @@ -1909,18 +1849,12 @@ bool cBlockArea::cChunkReader::Coords(int a_ChunkX, int a_ChunkZ) -void cBlockArea::cChunkReader::BlockTypes(const BLOCKTYPE * a_BlockTypes) +void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer) { - if (m_Area.m_BlockTypes == NULL) - { - // Don't want BlockTypes - return; - } - int SizeY = m_Area.m_Size.y; int MinY = m_Origin.y; - - // SizeX, SizeZ are the dmensions of the block data to copy from the current chunk (size of the geometric union) + + // SizeX, SizeZ are the dimensions of the block data to copy from the current chunk (size of the geometric union) // OffX, OffZ are the offsets of the current chunk data from the area origin // BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders int SizeX = cChunkDef::Width; @@ -1958,71 +1892,95 @@ void cBlockArea::cChunkReader::BlockTypes(const BLOCKTYPE * a_BlockTypes) { SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_Origin.z + m_Area.m_Size.z); } - - for (int y = 0; y < SizeY; y++) + + // Copy the blocktypes: + if (m_Area.m_BlockTypes != NULL) { - int ChunkY = MinY + y; - int AreaY = y; - for (int z = 0; z < SizeZ; z++) + for (int y = 0; y < SizeY; y++) { - int ChunkZ = BaseZ + z; - int AreaZ = OffZ + z; - for (int x = 0; x < SizeX; x++) + int InChunkY = MinY + y; + int AreaY = y; + for (int z = 0; z < SizeZ; z++) { - int ChunkX = BaseX + x; - int AreaX = OffX + x; - m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetBlock(a_BlockTypes, ChunkX, ChunkY, ChunkZ); - } // for x - } // for z - } // for y -} - - - - + int InChunkZ = BaseZ + z; + int AreaZ = OffZ + z; + for (int x = 0; x < SizeX; x++) + { + int InChunkX = BaseX + x; + int AreaX = OffX + x; + m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlock(InChunkX, InChunkY, InChunkZ); + } // for x + } // for z + } // for y + } -void cBlockArea::cChunkReader::BlockMeta(const NIBBLETYPE * a_BlockMetas) -{ - if (m_Area.m_BlockMetas == NULL) + // Copy the block metas: + if (m_Area.m_BlockMetas != NULL) { - // Don't want metas - return; + for (int y = 0; y < SizeY; y++) + { + int InChunkY = MinY + y; + int AreaY = y; + for (int z = 0; z < SizeZ; z++) + { + int InChunkZ = BaseZ + z; + int AreaZ = OffZ + z; + for (int x = 0; x < SizeX; x++) + { + int InChunkX = BaseX + x; + int AreaX = OffX + x; + m_Area.m_BlockMetas[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetMeta(InChunkX, InChunkY, InChunkZ); + } // for x + } // for z + } // for y } - CopyNibbles(m_Area.m_BlockMetas, a_BlockMetas); -} - - - - -void cBlockArea::cChunkReader::BlockLight(const NIBBLETYPE * a_BlockLight) -{ - if (m_Area.m_BlockLight == NULL) + // Copy the blocklight: + if (m_Area.m_BlockLight != NULL) { - // Don't want light - return; + for (int y = 0; y < SizeY; y++) + { + int InChunkY = MinY + y; + int AreaY = y; + for (int z = 0; z < SizeZ; z++) + { + int InChunkZ = BaseZ + z; + int AreaZ = OffZ + z; + for (int x = 0; x < SizeX; x++) + { + int InChunkX = BaseX + x; + int AreaX = OffX + x; + m_Area.m_BlockLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlockLight(InChunkX, InChunkY, InChunkZ); + } // for x + } // for z + } // for y } - CopyNibbles(m_Area.m_BlockLight, a_BlockLight); -} - - - - -void cBlockArea::cChunkReader::BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) -{ - if (m_Area.m_BlockSkyLight == NULL) + // Copy the skylight: + if (m_Area.m_BlockSkyLight != NULL) { - // Don't want skylight - return; + for (int y = 0; y < SizeY; y++) + { + int InChunkY = MinY + y; + int AreaY = y; + for (int z = 0; z < SizeZ; z++) + { + int InChunkZ = BaseZ + z; + int AreaZ = OffZ + z; + for (int x = 0; x < SizeX; x++) + { + int InChunkX = BaseX + x; + int AreaX = OffX + x; + m_Area.m_BlockSkyLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetSkyLight(InChunkX, InChunkY, InChunkZ); + } // for x + } // for z + } // for y } - CopyNibbles(m_Area.m_BlockSkyLight, a_BlockSkyLight); } - void cBlockArea::CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) { int NewSizeX = GetSizeX() - a_AddMinX - a_SubMaxX; @@ -2079,7 +2037,7 @@ void cBlockArea::ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, i int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; - int BlockCount = NewSizeX * NewSizeY * NewSizeZ; + size_t BlockCount = (size_t)(NewSizeX * NewSizeY * NewSizeZ); BLOCKTYPE * NewBlockTypes = new BLOCKTYPE[BlockCount]; memset(NewBlockTypes, 0, BlockCount * sizeof(BLOCKTYPE)); int OldIndex = 0; @@ -2109,7 +2067,7 @@ void cBlockArea::ExpandNibbles(NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMa int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; - int BlockCount = NewSizeX * NewSizeY * NewSizeZ; + size_t BlockCount = (size_t)(NewSizeX * NewSizeY * NewSizeZ); NIBBLETYPE * NewNibbles = new NIBBLETYPE[BlockCount]; memset(NewNibbles, 0, BlockCount * sizeof(NIBBLETYPE)); int OldIndex = 0; @@ -2161,4 +2119,134 @@ void cBlockArea::RelSetData( +template<bool MetasValid> +void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas) +{ + // Block types are compulsory, block metas are voluntary + if (!HasBlockTypes() || !a_Src.HasBlockTypes()) + { + LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); + return; + } + + // Dst is *this, Src is a_Src + int SrcOffX = std::max(0, -a_RelX); // Offset in Src where to start reading + int DstOffX = std::max(0, a_RelX); // Offset in Dst where to start writing + int SizeX = std::min(a_Src.GetSizeX() - SrcOffX, GetSizeX() - DstOffX); // How many blocks to copy + + int SrcOffY = std::max(0, -a_RelY); // Offset in Src where to start reading + int DstOffY = std::max(0, a_RelY); // Offset in Dst where to start writing + int SizeY = std::min(a_Src.GetSizeY() - SrcOffY, GetSizeY() - DstOffY); // How many blocks to copy + + int SrcOffZ = std::max(0, -a_RelZ); // Offset in Src where to start reading + int DstOffZ = std::max(0, a_RelZ); // Offset in Dst where to start writing + int SizeZ = std::min(a_Src.GetSizeZ() - SrcOffZ, GetSizeZ() - DstOffZ); // How many blocks to copy + + switch (a_Strategy) + { + case cBlockArea::msOverwrite: + { + InternalMergeBlocks<MetasValid, MergeCombinatorOverwrite<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msOverwrite + + case cBlockArea::msFillAir: + { + InternalMergeBlocks<MetasValid, MergeCombinatorFillAir<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msFillAir + + case cBlockArea::msImprint: + { + InternalMergeBlocks<MetasValid, MergeCombinatorImprint<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msImprint + + case cBlockArea::msLake: + { + InternalMergeBlocks<MetasValid, MergeCombinatorLake<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msLake + + case cBlockArea::msSpongePrint: + { + InternalMergeBlocks<MetasValid, MergeCombinatorSpongePrint<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msSpongePrint + + case cBlockArea::msDifference: + { + InternalMergeBlocks<MetasValid, MergeCombinatorDifference<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msDifference + + case cBlockArea::msMask: + { + InternalMergeBlocks<MetasValid, MergeCombinatorMask<MetasValid> >( + m_BlockTypes, a_Src.GetBlockTypes(), + DstMetas, SrcMetas, + SizeX, SizeY, SizeZ, + SrcOffX, SrcOffY, SrcOffZ, + DstOffX, DstOffY, DstOffZ, + a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), + m_Size.x, m_Size.y, m_Size.z + ); + return; + } // case msMask + } // switch (a_Strategy) + + LOGWARNING("Unknown block area merge strategy: %d", a_Strategy); + ASSERT(!"Unknown block area merge strategy"); + return; +} + + |