1
0

Merge pull request #1922 from mc-server/BlockAreaExt

cBlockArea extensions
This commit is contained in:
Mattes D 2015-04-30 10:39:15 +02:00
commit 4bf3b874e3
6 changed files with 242 additions and 10 deletions

View File

@ -120,6 +120,7 @@ g_APIDesc =
GetOriginX = { Params = "", Return = "number", Notes = "Returns the origin x-coord" },
GetOriginY = { Params = "", Return = "number", Notes = "Returns the origin y-coord" },
GetOriginZ = { Params = "", Return = "number", Notes = "Returns the origin z-coord" },
GetNonAirCropRelCoords = { Params = "[IgnoreBlockType]", Return = "MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ", Notes = "Returns the minimum and maximum coords in each direction for the first non-ignored block in each direction. If there are no non-ignored blocks within the area, or blocktypes are not present, the returned values are reverse-ranges (MinX <- m_RangeX, MaxX <- 0 etc.). IgnoreBlockType defaults to air." },
GetRelBlockLight = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the blocklight at the specified relative coords" },
GetRelBlockMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the block meta at the specified relative coords" },
GetRelBlockSkyLight = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the skylight at the specified relative coords" },
@ -197,13 +198,14 @@ g_APIDesc =
baMetas = { Notes = "Operations should work on block metas" },
baLight = { Notes = "Operations should work on block (emissive) light" },
baSkyLight = { Notes = "Operations should work on skylight" },
msDifference = { Notes = "Block becomes air if Src and Dst are the same. Otherwise it becomes the source block." },
msOverwrite = { Notes = "Src overwrites anything in Dst" },
msFillAir = { Notes = "Dst is overwritten by Src only where Src has air blocks" },
msImprint = { Notes = "Src overwrites Dst anywhere where Dst has non-air blocks" },
msDifference = { Notes = "Block becomes air if 'self' and src are the same. Otherwise it becomes the src block." },
msFillAir = { Notes = "'self' is overwritten by Src only where 'self' has air blocks" },
msImprint = { Notes = "Src overwrites 'self' anywhere where 'self' has non-air blocks" },
msLake = { Notes = "Special mode for merging lake images" },
msMask = { Notes = "The blocks that are exactly the same are kept in 'self', all differing blocks are replaced by air"},
msOverwrite = { Notes = "Src overwrites anything in 'self'" },
msSimpleCompare = { Notes = "The blocks that are exactly the same are replaced with air, all differing blocks are replaced by stone"},
msSpongePrint = { Notes = "Similar to msImprint, sponge block doesn't overwrite anything, all other blocks overwrite everything"},
msMask = { Notes = "The blocks that are exactly the same are kept in Dst, all differing blocks are replaced by air"},
},
ConstantGroups =
{
@ -287,7 +289,7 @@ g_APIDesc =
<table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr>
<th> this </th><th> Src </th><th> result </th><th> </th>
<th> self </th><th> Src </th><th> result </th><th> </th>
</tr><tr>
<td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td>
</tr><tr>
@ -321,7 +323,7 @@ g_APIDesc =
<table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr>
<th> this </th><th> Src </th><th> result </th><th> </th>
<th> self </th><th> Src </th><th> result </th><th> </th>
</tr><tr>
<td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td>
</tr><tr>
@ -337,13 +339,45 @@ g_APIDesc =
<table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr>
<th> this </th><th> Src </th><th> result </th><th> </th>
<th> self </th><th> Src </th><th> result </th><th> </th>
</tr><tr>
<td> A </td><td> A </td><td> A </td><td> Same blocks are kept </td>
</tr><tr>
<td> A </td><td> non-A </td><td> air </td><td> Differing blocks are replaced with air </td>
</tr>
</tbody></table>
<p>
<strong>msDifference</strong> - the blocks that are the same in both areas are replaced with air, all the
differing blocks are kept from the first area. Meta is used in the comparison, too, two blocks of the
same type but different meta are considered different.
</p>
<table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr>
<th> self </th><th> Src </th><th> result </th><th> </th>
</tr><tr>
<td> A </td><td> A </td><td> air </td><td> Same blocks are replaced with air </td>
</tr><tr>
<td> A </td><td> non-A </td><td> A </td><td> Differing blocks are kept from 'self' </td>
</tr>
</tbody></table>
<p>
<strong>msSimpleCompare</strong> - the blocks that are the same in both areas are replaced with air, all the
differing blocks are replaced with stone. Meta is used in the comparison, too, two blocks of the
same type but different meta are considered different.
</p>
<table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr>
<th> self </th><th> Src </th><th> result </th><th> </th>
</tr><tr>
<td> A </td><td> A </td><td> air </td><td> Same blocks are replaced with air </td>
</tr><tr>
<td> A </td><td> non-A </td><td> stone </td><td> Differing blocks are replaced with stone </td>
</tr>
</tbody></table>
]],
}, -- Merge strategies
}, -- AdditionalInfo

View File

@ -937,6 +937,18 @@ void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
void cLuaState::GetStackValue(int a_StackPos, BLOCKTYPE & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
a_ReturnedVal = static_cast<BLOCKTYPE>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
}
}
void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
{
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
@ -995,6 +1007,24 @@ void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, pBlockArea & a_ReturnedVal)
{
if (lua_isnil(m_LuaState, a_StackPos))
{
a_ReturnedVal = nullptr;
return;
}
tolua_Error err;
if (tolua_isusertype(m_LuaState, a_StackPos, "cBlockArea", false, &err))
{
a_ReturnedVal = *(reinterpret_cast<cBlockArea **>(lua_touserdata(m_LuaState, a_StackPos)));
}
}
void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
{
if (lua_isnil(m_LuaState, a_StackPos))
@ -1005,7 +1035,7 @@ void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
tolua_Error err;
if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &err))
{
a_ReturnedVal = *((cBoundingBox **)lua_touserdata(m_LuaState, a_StackPos));
a_ReturnedVal = *(reinterpret_cast<cBoundingBox **>(lua_touserdata(m_LuaState, a_StackPos)));
}
}

View File

@ -37,6 +37,7 @@ extern "C"
class cBlockArea;
class cBlockEntity;
class cBoundingBox;
class cChunkDesc;
@ -68,6 +69,7 @@ struct HTTPRequest;
struct HTTPTemplateRequest;
struct TakeDamageInfo;
typedef cBlockArea * pBlockArea;
typedef cBoundingBox * pBoundingBox;
typedef cMapManager * pMapManager;
typedef cPluginManager * pPluginManager;
@ -244,11 +246,13 @@ public:
// GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged.
// Enum values are clamped to their allowed range.
void GetStackValue(int a_StackPos, AString & a_Value);
void GetStackValue(int a_StackPos, BLOCKTYPE & a_Value);
void GetStackValue(int a_StackPos, bool & a_Value);
void GetStackValue(int a_StackPos, cRef & a_Ref);
void GetStackValue(int a_StackPos, double & a_Value);
void GetStackValue(int a_StackPos, eWeather & a_Value);
void GetStackValue(int a_StackPos, int & a_Value);
void GetStackValue(int a_StackPos, pBlockArea & a_Value);
void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
void GetStackValue(int a_StackPos, pMapManager & a_Value);
void GetStackValue(int a_StackPos, pPluginManager & a_Value);

View File

@ -3187,6 +3187,44 @@ static int tolua_cBlockArea_GetOrigin(lua_State * tolua_S)
static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * tolua_S)
{
// function cBlockArea::GetNonAirCropRelCoords()
// Exported manually because tolua would generate extra input params for the outputs
cLuaState L(tolua_S);
if (!L.CheckParamUserType(1, "cBlockArea"))
{
return 0;
}
cBlockArea * self = nullptr;
BLOCKTYPE IgnoreBlockType = E_BLOCK_AIR;
L.GetStackValues(1, self, IgnoreBlockType);
if (self == nullptr)
{
tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetNonAirCropRelCoords'", nullptr);
return 0;
}
// Calculate the crop coords:
int MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ;
self->GetNonAirCropRelCoords(MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ, IgnoreBlockType);
// Push the six crop coords:
L.Push(MinRelX);
L.Push(MinRelY);
L.Push(MinRelZ);
L.Push(MaxRelX);
L.Push(MaxRelY);
L.Push(MaxRelZ);
return 6;
}
static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * tolua_S)
{
// function cBlockArea::GetRelBlockTypeMeta()
@ -3687,6 +3725,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
tolua_function(tolua_S, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin);
tolua_function(tolua_S, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords);
tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);

View File

@ -245,6 +245,26 @@ void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBL
/** Combinator used for cBlockArea::msSimpleCompare merging */
template <bool MetaValid>
void MergeCombinatorSimpleCompare(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
if ((a_DstType == a_SrcType) && (!MetaValid || (a_DstMeta == a_SrcMeta)))
{
// The blocktypes are the same, and the blockmetas are not present or are the same
a_DstType = E_BLOCK_AIR;
}
else
{
// The blocktypes or blockmetas differ
a_DstType = E_BLOCK_STONE;
}
}
/** Combinator used for cBlockArea::msMask merging */
template <bool MetaValid>
void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
@ -1614,6 +1634,73 @@ void cBlockArea::GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTY
void cBlockArea::GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType)
{
// Check if blocktypes are valid:
if (m_BlockTypes == nullptr)
{
LOGWARNING("%s: BlockTypes have not been read!", __FUNCTION__);
a_MinRelX = 1;
a_MaxRelX = 0;
return;
}
// Walk all the blocks and find the min and max coords for the non-ignored ones:
int MaxX = 0, MinX = m_Size.x - 1;
int MaxY = 0, MinY = m_Size.y - 1;
int MaxZ = 0, MinZ = m_Size.z - 1;
for (int y = 0; y < m_Size.y; y++)
{
for (int z = 0; z < m_Size.z; z++)
{
for (int x = 0; x < m_Size.x; x++)
{
if (m_BlockTypes[MakeIndex(x, y, z)] == a_IgnoreBlockType)
{
continue;
}
// The block is not ignored, update any coords that need updating:
if (x < MinX)
{
MinX = x;
}
if (x > MaxX)
{
MaxX = x;
}
if (y < MinY)
{
MinY = y;
}
if (y > MaxY)
{
MaxY = y;
}
if (z < MinZ)
{
MinZ = z;
}
if (z > MaxZ)
{
MaxZ = z;
}
} // for x
} // for z
} // for y
// Assign to the output:
a_MinRelX = MinX;
a_MinRelY = MinY;
a_MinRelZ = MinZ;
a_MaxRelX = MaxX;
a_MaxRelY = MaxY;
a_MaxRelZ = MaxZ;
}
int cBlockArea::GetDataTypes(void) const
{
int res = 0;
@ -2121,10 +2208,12 @@ 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
// Block types are compulsory, block metas are optional
if (!HasBlockTypes() || !a_Src.HasBlockTypes())
{
LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__);
@ -2230,6 +2319,20 @@ void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_Rel
return;
} // case msDifference
case cBlockArea::msSimpleCompare:
{
InternalMergeBlocks<MetasValid, MergeCombinatorSimpleCompare<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 msSimpleCompare
case cBlockArea::msMask:
{
InternalMergeBlocks<MetasValid, MergeCombinatorMask<MetasValid> >(

View File

@ -54,6 +54,7 @@ public:
msLake,
msSpongePrint,
msDifference,
msSimpleCompare,
msMask,
} ;
@ -156,6 +157,22 @@ public:
| A | sponge | A | Sponge is the NOP block
| * | B | B | Everything else overwrites anything
msDifference:
Used to determine the differences between two areas. Only the differring blocks are preserved:
| area block | |
| this | Src | result |
+------+-------+--------+
| A | A | air | Same blocks are replaced with air
| A | non-A | A | Differring blocks are kept from "this"
msSimpleCompare:
Used to determine the differences between two areas. Blocks that differ are replaced with stone, same blocks are replaced with air
| area block | |
| this | Src | result |
+------+-------+--------+
| A | A | air | Same blocks are replaced with air
| A | non-A | stone | Differring blocks are replaced with stone
msMask:
Combines two areas, the blocks that are the same are kept, differing ones are reset to air
| area block | |
@ -289,6 +306,11 @@ public:
// tolua_end
/** Returns the minimum and maximum coords in each direction for the first non-ignored block in each direction.
If there are no non-ignored blocks within the area, or blocktypes are not present, the returned values are reverse-ranges (MinX <- m_RangeX, MaxX <- 0 etc.)
Exported to Lua in ManualBindings.cpp. */
void GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType = E_BLOCK_AIR);
// Clients can use these for faster access to all blocktypes. Be careful though!
/** Returns the internal pointer to the block types */
BLOCKTYPE * GetBlockTypes (void) const { return m_BlockTypes; }