Merge pull request #1922 from mc-server/BlockAreaExt
cBlockArea extensions
This commit is contained in:
commit
4bf3b874e3
@ -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
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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> >(
|
||||
|
@ -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; }
|
||||
|
Loading…
Reference in New Issue
Block a user