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" }, GetOriginX = { Params = "", Return = "number", Notes = "Returns the origin x-coord" },
GetOriginY = { Params = "", Return = "number", Notes = "Returns the origin y-coord" }, GetOriginY = { Params = "", Return = "number", Notes = "Returns the origin y-coord" },
GetOriginZ = { Params = "", Return = "number", Notes = "Returns the origin z-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" }, 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" }, 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" }, 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" }, baMetas = { Notes = "Operations should work on block metas" },
baLight = { Notes = "Operations should work on block (emissive) light" }, baLight = { Notes = "Operations should work on block (emissive) light" },
baSkyLight = { Notes = "Operations should work on skylight" }, 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." }, msDifference = { Notes = "Block becomes air if 'self' and src are the same. Otherwise it becomes the src block." },
msOverwrite = { Notes = "Src overwrites anything in Dst" }, msFillAir = { Notes = "'self' is overwritten by Src only where 'self' has air blocks" },
msFillAir = { Notes = "Dst is overwritten by Src only where Src has air blocks" }, msImprint = { Notes = "Src overwrites 'self' anywhere where 'self' has non-air blocks" },
msImprint = { Notes = "Src overwrites Dst anywhere where Dst has non-air blocks" },
msLake = { Notes = "Special mode for merging lake images" }, 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"}, 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 = ConstantGroups =
{ {
@ -287,7 +289,7 @@ g_APIDesc =
<table><tbody><tr> <table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th> <th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr> </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> </tr><tr>
<td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td> <td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td>
</tr><tr> </tr><tr>
@ -321,7 +323,7 @@ g_APIDesc =
<table><tbody><tr> <table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th> <th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr> </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> </tr><tr>
<td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td> <td> A </td><td> sponge </td><td> A </td><td> Sponge is the NOP block </td>
</tr><tr> </tr><tr>
@ -337,13 +339,45 @@ g_APIDesc =
<table><tbody><tr> <table><tbody><tr>
<th colspan="2"> area block </th><th> </th><th> Notes </th> <th colspan="2"> area block </th><th> </th><th> Notes </th>
</tr><tr> </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> </tr><tr>
<td> A </td><td> A </td><td> A </td><td> Same blocks are kept </td> <td> A </td><td> A </td><td> A </td><td> Same blocks are kept </td>
</tr><tr> </tr><tr>
<td> A </td><td> non-A </td><td> air </td><td> Differing blocks are replaced with air </td> <td> A </td><td> non-A </td><td> air </td><td> Differing blocks are replaced with air </td>
</tr> </tr>
</tbody></table> </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 }, -- Merge strategies
}, -- AdditionalInfo }, -- 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) void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
{ {
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0); 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) void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
{ {
if (lua_isnil(m_LuaState, a_StackPos)) if (lua_isnil(m_LuaState, a_StackPos))
@ -1005,7 +1035,7 @@ void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
tolua_Error err; tolua_Error err;
if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &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 cBlockEntity;
class cBoundingBox; class cBoundingBox;
class cChunkDesc; class cChunkDesc;
@ -68,6 +69,7 @@ struct HTTPRequest;
struct HTTPTemplateRequest; struct HTTPTemplateRequest;
struct TakeDamageInfo; struct TakeDamageInfo;
typedef cBlockArea * pBlockArea;
typedef cBoundingBox * pBoundingBox; typedef cBoundingBox * pBoundingBox;
typedef cMapManager * pMapManager; typedef cMapManager * pMapManager;
typedef cPluginManager * pPluginManager; 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. // 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. // Enum values are clamped to their allowed range.
void GetStackValue(int a_StackPos, AString & a_Value); 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, bool & a_Value);
void GetStackValue(int a_StackPos, cRef & a_Ref); void GetStackValue(int a_StackPos, cRef & a_Ref);
void GetStackValue(int a_StackPos, double & a_Value); void GetStackValue(int a_StackPos, double & a_Value);
void GetStackValue(int a_StackPos, eWeather & a_Value); void GetStackValue(int a_StackPos, eWeather & a_Value);
void GetStackValue(int a_StackPos, int & 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, pBoundingBox & a_Value);
void GetStackValue(int a_StackPos, pMapManager & a_Value); void GetStackValue(int a_StackPos, pMapManager & a_Value);
void GetStackValue(int a_StackPos, pPluginManager & 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) static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * tolua_S)
{ {
// function cBlockArea::GetRelBlockTypeMeta() // 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, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
tolua_function(tolua_S, "GetCoordRange", tolua_cBlockArea_GetCoordRange); tolua_function(tolua_S, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin); 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, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize); tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile); 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 */ /** Combinator used for cBlockArea::msMask merging */
template <bool MetaValid> template <bool MetaValid>
void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) 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 cBlockArea::GetDataTypes(void) const
{ {
int res = 0; int res = 0;
@ -2121,10 +2208,12 @@ void cBlockArea::RelSetData(
template <bool MetasValid> 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) 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()) if (!HasBlockTypes() || !a_Src.HasBlockTypes())
{ {
LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); 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; return;
} // case msDifference } // 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: case cBlockArea::msMask:
{ {
InternalMergeBlocks<MetasValid, MergeCombinatorMask<MetasValid> >( InternalMergeBlocks<MetasValid, MergeCombinatorMask<MetasValid> >(

View File

@ -54,6 +54,7 @@ public:
msLake, msLake,
msSpongePrint, msSpongePrint,
msDifference, msDifference,
msSimpleCompare,
msMask, msMask,
} ; } ;
@ -156,6 +157,22 @@ public:
| A | sponge | A | Sponge is the NOP block | A | sponge | A | Sponge is the NOP block
| * | B | B | Everything else overwrites anything | * | 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: msMask:
Combines two areas, the blocks that are the same are kept, differing ones are reset to air Combines two areas, the blocks that are the same are kept, differing ones are reset to air
| area block | | | area block | |
@ -288,6 +305,11 @@ public:
bool HasBlockSkyLights(void) const { return (m_BlockSkyLight != nullptr); } bool HasBlockSkyLights(void) const { return (m_BlockSkyLight != nullptr); }
// tolua_end // 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! // Clients can use these for faster access to all blocktypes. Be careful though!
/** Returns the internal pointer to the block types */ /** Returns the internal pointer to the block types */