diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/Bindings.cpp | 51 | ||||
-rw-r--r-- | source/Bindings.h | 2 | ||||
-rw-r--r-- | source/BlockArea.cpp | 181 | ||||
-rw-r--r-- | source/BlockArea.h | 34 |
4 files changed, 259 insertions, 9 deletions
diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 49e54129d..eb4d9ef8f 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/09/13 10:54:12. +** Generated automatically by tolua++-1.0.92 on 02/10/13 14:41:15. */ #ifndef __cplusplus @@ -4601,14 +4601,14 @@ static int tolua_AllToLua_cEntity_GetLookVector00(lua_State* tolua_S) #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { - cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0); + const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetLookVector'", NULL); #endif @@ -18081,6 +18081,47 @@ static int tolua_AllToLua_cBlockArea_Expand00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: Merge of class cBlockArea */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_Merge00 +static int tolua_AllToLua_cBlockArea_Merge00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cBlockArea",0,&tolua_err) || + (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cBlockArea",0,&tolua_err)) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnumber(tolua_S,4,0,&tolua_err) || + !tolua_isnumber(tolua_S,5,0,&tolua_err) || + !tolua_isnumber(tolua_S,6,0,&tolua_err) || + !tolua_isnoobj(tolua_S,7,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cBlockArea* self = (cBlockArea*) tolua_tousertype(tolua_S,1,0); + const cBlockArea* a_Src = ((const cBlockArea*) tolua_tousertype(tolua_S,2,0)); + int a_RelX = ((int) tolua_tonumber(tolua_S,3,0)); + int a_RelY = ((int) tolua_tonumber(tolua_S,4,0)); + int a_RelZ = ((int) tolua_tonumber(tolua_S,5,0)); + cBlockArea::eMergeStrategy a_Strategy = ((cBlockArea::eMergeStrategy) (int) tolua_tonumber(tolua_S,6,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Merge'", NULL); +#endif + { + self->Merge(*a_Src,a_RelX,a_RelY,a_RelZ,a_Strategy); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'Merge'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: SetRelBlockType of class cBlockArea */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_SetRelBlockType00 static int tolua_AllToLua_cBlockArea_SetRelBlockType00(lua_State* tolua_S) @@ -22196,6 +22237,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_constant(tolua_S,"baMetas",cBlockArea::baMetas); tolua_constant(tolua_S,"baLight",cBlockArea::baLight); tolua_constant(tolua_S,"baSkyLight",cBlockArea::baSkyLight); + tolua_constant(tolua_S,"msOverwrite",cBlockArea::msOverwrite); + tolua_constant(tolua_S,"msFillAir",cBlockArea::msFillAir); + tolua_constant(tolua_S,"msImprint",cBlockArea::msImprint); tolua_function(tolua_S,"new",tolua_AllToLua_cBlockArea_new00); tolua_function(tolua_S,"new_local",tolua_AllToLua_cBlockArea_new00_local); tolua_function(tolua_S,".call",tolua_AllToLua_cBlockArea_new00_local); @@ -22212,6 +22256,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"SaveToSchematicFile",tolua_AllToLua_cBlockArea_SaveToSchematicFile00); tolua_function(tolua_S,"Crop",tolua_AllToLua_cBlockArea_Crop00); tolua_function(tolua_S,"Expand",tolua_AllToLua_cBlockArea_Expand00); + tolua_function(tolua_S,"Merge",tolua_AllToLua_cBlockArea_Merge00); tolua_function(tolua_S,"SetRelBlockType",tolua_AllToLua_cBlockArea_SetRelBlockType00); tolua_function(tolua_S,"SetBlockType",tolua_AllToLua_cBlockArea_SetBlockType00); tolua_function(tolua_S,"SetRelBlockMeta",tolua_AllToLua_cBlockArea_SetRelBlockMeta00); diff --git a/source/Bindings.h b/source/Bindings.h index 76536279e..1c5011759 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/09/13 10:54:12. +** Generated automatically by tolua++-1.0.92 on 02/10/13 14:41:16. */ /* Exported function */ diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp index 472b14c59..01c1cf4c1 100644 --- a/source/BlockArea.cpp +++ b/source/BlockArea.cpp @@ -14,6 +14,87 @@ +// 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(
+ 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
+)
+{
+ for (int y = 0; y < a_SizeY; y++)
+ {
+ int SrcBaseY = (y + a_SrcOffY) * a_SrcSizeX * a_SrcSizeZ;
+ int DstBaseY = (y + a_DstOffY) * a_DstSizeX * a_DstSizeZ;
+ for (int z = 0; z < a_SizeZ; z++)
+ {
+ int SrcBaseZ = SrcBaseY + (z + a_SrcOffZ) * a_SrcSizeX;
+ int DstBaseZ = DstBaseY + (z + a_DstOffZ) * a_DstSizeX;
+ int SrcIdx = SrcBaseZ + a_SrcOffX;
+ 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]);
+ ++DstIdx;
+ ++SrcIdx;
+ } // for x
+ } // for z
+ } // for y
+}
+
+
+
+
+
+/// Combinator used for cBlockArea::msOverwrite merging
+static void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
+{
+ a_DstType = a_SrcType;
+ a_DstMeta = a_SrcMeta;
+}
+
+
+
+
+
+/// Combinator used for cBlockArea::msFillAir merging
+static 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;
+ }
+ // "else" is the default, already in place
+}
+
+
+
+
+
+/// Combinator used for cBlockArea::msImprint merging
+static 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;
+ }
+ // "else" is the default, already in place
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cBlockArea:
+
cBlockArea::cBlockArea(void) :
m_SizeX(0),
m_SizeY(0),
@@ -300,7 +381,7 @@ bool cBlockArea::SaveToSchematicFile(const AString & a_FileName) Writer.EndList();
Writer.Finish();
- // TODO: Save to file
+ // Save to file
cGZipFile File;
if (!File.Open(a_FileName, cGZipFile::fmWrite))
{
@@ -392,6 +473,104 @@ 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()];
+ }
+
+ 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_SizeX, m_SizeY, m_SizeZ,
+ 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_SizeX, m_SizeY, m_SizeZ,
+ 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_SizeX, m_SizeY, m_SizeZ,
+ MergeCombinatorImprint
+ );
+ break;
+ } // case msImprint
+
+ default:
+ {
+ LOGWARNING("Unknown block area merge strategy: %d", a_Strategy);
+ ASSERT(!"Unknown block area merge strategy");
+ break;
+ }
+ } // switch (a_Strategy)
+
+ if (IsDummyMetas)
+ {
+ delete[] SrcMetas;
+ delete[] DstMetas;
+ }
+}
+
+
+
+
+
void cBlockArea::SetRelBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
{
if (m_BlockTypes == NULL)
diff --git a/source/BlockArea.h b/source/BlockArea.h index b1a2d9053..787731434 100644 --- a/source/BlockArea.h +++ b/source/BlockArea.h @@ -44,6 +44,13 @@ public: baSkyLight = 8,
} ;
+ enum eMergeStrategy
+ {
+ msOverwrite,
+ msFillAir,
+ msImprint,
+ } ;
+
cBlockArea(void);
~cBlockArea();
@@ -80,6 +87,25 @@ public: /// Expands the internal contents by the specified amount of blocks from each border
void Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ);
+ /** Merges another block area into this one, using the specified block combinating strategy
+ This function combines another BlockArea into the current object.
+ The strategy parameter specifies how individual blocks are combined together, using the table below.
+
+ | area block | result |
+ | this | Src | msOverwrite | msFillAir | msImprint |
+ +------+-----+-------------+-----------+-----------+
+ | air | air | air | air | air |
+ | A | air | air | A | A |
+ | air | B | B | B | B |
+ | A | B | B | A | B |
+
+ So to sum up:
+ - msOverwrite completely overwrites all blocks with the Src's blocks
+ - msFillAir overwrites only those blocks that were air
+ - msImprint overwrites with only those blocks that are non-air
+ */
+ void Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy);
+
// Setters:
void SetRelBlockType (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType);
void SetBlockType (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
@@ -125,10 +151,10 @@ public: // Clients can use these for faster access to all blocktypes. Be careful though!
/// Returns the internal pointer to the block types
- BLOCKTYPE * GetBlockTypes (void) { return m_BlockTypes; }
- NIBBLETYPE * GetBlockMetas (void) { return m_BlockMetas; } // NOTE: one byte per block!
- NIBBLETYPE * GetBlockLight (void) { return m_BlockLight; } // NOTE: one byte per block!
- NIBBLETYPE * GetBlockSkyLight(void) { return m_BlockSkyLight; } // NOTE: one byte per block!
+ BLOCKTYPE * GetBlockTypes (void) const { return m_BlockTypes; }
+ NIBBLETYPE * GetBlockMetas (void) const { return m_BlockMetas; } // NOTE: one byte per block!
+ NIBBLETYPE * GetBlockLight (void) const { return m_BlockLight; } // NOTE: one byte per block!
+ NIBBLETYPE * GetBlockSkyLight(void) const { return m_BlockSkyLight; } // NOTE: one byte per block!
int GetBlockCount(void) const { return m_SizeX * m_SizeY * m_SizeZ; }
int MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const;
|