summaryrefslogtreecommitdiffstats
path: root/src/BlockArea.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/BlockArea.cpp343
1 files changed, 175 insertions, 168 deletions
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index e4b122fa2..359f5cb81 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -13,18 +13,20 @@
-
// 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(
+
+typedef void (CombinatorFunc)(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta);
+
+template<bool MetasValid, CombinatorFunc Combinator>
+void InternalMergeBlocks(
BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes,
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 +43,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
+ {
+ BLOCKTYPE FakeDestMeta = 0;
+ Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], FakeDestMeta, (NIBBLETYPE)0);
+ }
++DstIdx;
++SrcIdx;
} // for x
@@ -51,13 +61,12 @@ template<typename Combinator> void InternalMergeBlocks(
-
-
/// Combinator used for cBlockArea::msOverwrite merging
+template<bool MetaValid>
static inline 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 +74,13 @@ static inline void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_S
/// Combinator used for cBlockArea::msFillAir merging
+template<bool MetaValid>
static inline 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 +90,13 @@ static inline void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_Src
/// Combinator used for cBlockArea::msImprint merging
+template<bool MetaValid>
static inline 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,6 +106,7 @@ static inline void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_Src
/// Combinator used for cBlockArea::msLake merging
+template<bool MetaValid>
static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
// Sponge is the NOP block
@@ -107,7 +119,7 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp
if (a_SrcType == E_BLOCK_AIR)
{
a_DstType = E_BLOCK_AIR;
- a_DstMeta = 0;
+ if (MetaValid) a_DstMeta = 0;
return;
}
@@ -132,7 +144,7 @@ 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 +158,7 @@ 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 +171,14 @@ static inline void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcTyp
/** Combinator used for cBlockArea::msSpongePrint merging */
+template<bool MetaValid>
static inline 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 +187,18 @@ static inline void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a
/** Combinator used for cBlockArea::msDifference merging */
+template<bool MetaValid>
static inline 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,13 +207,14 @@ static inline void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_
/** Combinator used for cBlockArea::msMask merging */
+template<bool MetaValid>
static inline 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;
}
}
@@ -484,7 +499,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 +547,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,160 +652,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)
{
- size_t SrcCount = a_Src.GetBlockCount();
- size_t DestCount = GetBlockCount();
- NIBBLETYPE * tempSrcMetas = new NIBBLETYPE[SrcCount];
- memset(tempSrcMetas, 0, SrcCount);
- SrcMetas = tempSrcMetas;
- DstMetas = new NIBBLETYPE[DestCount];
- memset(DstMetas, 0, DestCount);
+ MergeByStrategy<true>(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<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
}
}
@@ -2084,7 +1958,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;
@@ -2114,7 +1988,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;
@@ -2166,4 +2040,137 @@ 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // 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
+ );
+ break;
+ } // case msMask
+
+ default:
+ {
+ LOGWARNING("Unknown block area merge strategy: %d", a_Strategy);
+ ASSERT(!"Unknown block area merge strategy");
+ break;
+ }
+ } // switch (a_Strategy)
+}
+
+