summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua14
-rw-r--r--source/Bindings.cpp51
-rw-r--r--source/Bindings.h2
-rw-r--r--source/BlockArea.cpp181
-rw-r--r--source/BlockArea.h34
5 files changed, 273 insertions, 9 deletions
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 1775c960e..018e56f29 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -53,6 +53,20 @@ function Initialize(Plugin)
end
f:close();
end
+
+
+ -- Debug block area merging:
+ local BA1 = cBlockArea();
+ local BA2 = cBlockArea();
+ if (BA1:LoadFromSchematicFile("schematics/test.schematic")) then
+ if (BA2:LoadFromSchematicFile("schematics/fountain.schematic")) then
+ BA2:SetRelBlockType(0, 0, 0, E_BLOCK_LAPIS_BLOCK);
+ BA2:SetRelBlockType(1, 0, 0, E_BLOCK_LAPIS_BLOCK);
+ BA2:SetRelBlockType(2, 0, 0, E_BLOCK_LAPIS_BLOCK);
+ BA1:Merge(BA2, 1, 10, 1, cBlockArea.msImprint);
+ BA1:SaveToSchematicFile("schematics/merge.schematic");
+ end
+ end
return true
end
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;