1
0

Bindings: Allow coercion between Vector3 subtypes. (#4646)

In manually bound functions, allows one to use any Vector3<T> value, as well as a {x, y, z} table, in Lua as any Vector3<T> parameter.
Has example in Debuggers' /vector command.
Unfortunately doesn't work in auto-bindings.
This commit is contained in:
Mattes D 2020-04-14 16:43:21 +02:00 committed by GitHub
parent 35299b8509
commit c9a9b3c9d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 204 additions and 166 deletions

View File

@ -1727,6 +1727,26 @@ end
function HandleVectorCmd(a_Split, a_Player)
a_Player:SendMessage("Testing the Vector3 APIs...")
-- Test the Vector3 coercion in ManualBindings - any Vector3 type should be accepted for any Vector3 parameter:
local pos = a_Player:GetPosition()
local c = cCuboid:new()
c:Assign(pos - Vector3d(2, 2, 2), pos + Vector3d(2, 2, 2))
assert(c:IsInside(Vector3d(pos)))
assert(c:IsInside(Vector3f(pos)))
assert(c:IsInside(Vector3i(pos)))
assert(c:IsInside({pos.x, pos.y, pos.z}))
a_Player:SendMessage("Test successful.")
return true
end
function HandleWESel(a_Split, a_Player)
-- Check if the selection is a cuboid:
local IsCuboid = cPluginManager:CallPlugin("WorldEdit", "IsPlayerSelectionCuboid")

View File

@ -260,6 +260,14 @@ g_PluginInfo =
Handler = HandleTestWndCmd,
HelpString = "Opens up a window using plugin API"
},
["/vector"] =
{
Permission = "debuggers",
Handler = HandleVectorCmd,
HelpString = "Tests the Vector3 API",
},
["/wesel"] =
{
Permission = "debuggers",

View File

@ -74,7 +74,20 @@ local access =
-- Map of classname -> true
local g_HasCustomPushImplementation =
{
cEntity = true
cEntity = true,
}
--- Defines classes that have a custom manual GetStackValue() implementation and should not generate the automatic one
-- Map of classname -> true
local g_HasCustomGetImplementation =
{
Vector3d = true,
Vector3f = true,
Vector3i = true,
}
@ -209,13 +222,15 @@ local function OutputLuaStateHelpers(a_Package)
f:write("// This file expects to be included form inside the cLuaState class definition\n")
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
if not(g_HasCustomPushImplementation[item.name]) then
if not(g_HasCustomPushImplementation[item.lname]) then
f:write("void Push(" .. item.name .. " * a_Value);\n")
end
end
for _, item in ipairs(types) do
f:write("bool GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n")
f:write("bool GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal);\n")
if not(g_HasCustomGetImplementation[item.lname]) then
f:write("bool GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n")
f:write("bool GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal);\n")
end
end
f:write("\n\n\n\n\n")
f:close()
@ -231,38 +246,40 @@ local function OutputLuaStateHelpers(a_Package)
f:write("#include \"Globals.h\"\n#include \"LuaState.h\"\n#include \"tolua++/include/tolua++.h\"\n")
f:write("\n\n\n\n\n")
for _, item in ipairs(types) do
if not(g_HasCustomPushImplementation[item.name]) then
if not(g_HasCustomPushImplementation[item.lname]) then
f:write("void cLuaState::Push(" .. item.name .. " * a_Value)\n{\n\tASSERT(IsValid());\n")
f:write("\ttolua_pushusertype(m_LuaState, a_Value, \"" .. item.name .. "\");\n");
f:write("}\n\n\n\n\n\n")
end
end
for _, item in ipairs(types) do
f:write("bool cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n")
f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n")
f:write("\t\ta_ReturnedVal = nullptr;\n")
f:write("\t\treturn false;\n\t}\n")
f:write("\ttolua_Error err;\n")
f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n")
f:write("\t{\n")
f:write("\t\ta_ReturnedVal = *(static_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n")
f:write("\t\treturn true;\n");
f:write("\t}\n")
f:write("\treturn false;\n")
f:write("}\n\n\n\n\n\n")
if not(g_HasCustomGetImplementation[item.lname]) then
f:write("bool cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n")
f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n")
f:write("\t\ta_ReturnedVal = nullptr;\n")
f:write("\t\treturn false;\n\t}\n")
f:write("\ttolua_Error err;\n")
f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n")
f:write("\t{\n")
f:write("\t\ta_ReturnedVal = *(static_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n")
f:write("\t\treturn true;\n");
f:write("\t}\n")
f:write("\treturn false;\n")
f:write("}\n\n\n\n\n\n")
f:write("bool cLuaState::GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n")
f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n")
f:write("\t\ta_ReturnedVal = nullptr;\n")
f:write("\t\treturn false;\n\t}\n")
f:write("\ttolua_Error err;\n")
f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"const " .. item.name .. "\", false, &err))\n")
f:write("\t{\n")
f:write("\t\ta_ReturnedVal = *(static_cast<const " .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n")
f:write("\t\treturn true;\n");
f:write("\t}\n")
f:write("\treturn false;\n")
f:write("}\n\n\n\n\n\n")
f:write("bool cLuaState::GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n")
f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n")
f:write("\t\ta_ReturnedVal = nullptr;\n")
f:write("\t\treturn false;\n\t}\n")
f:write("\ttolua_Error err;\n")
f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"const " .. item.name .. "\", false, &err))\n")
f:write("\t{\n")
f:write("\t\ta_ReturnedVal = *(static_cast<const " .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n")
f:write("\t\treturn true;\n");
f:write("\t}\n")
f:write("\treturn false;\n")
f:write("}\n\n\n\n\n\n")
end
end
f:close()
end

View File

@ -518,49 +518,6 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
template <typename T>
int tolua_Vector3_Abs(lua_State * a_LuaState)
{
// Retrieve the params, including self:
cLuaState L(a_LuaState);
Vector3<T> * self;
if (!L.GetStackValues(1, self))
{
tolua_error(a_LuaState, "invalid 'self' in function 'Vector3<T>:Abs'", nullptr);
return 0;
}
// Absolutize the vector:
self->Abs();
return 0;
}
template <typename T>
int tolua_Vector3_Clamp(lua_State * a_LuaState)
{
// Retrieve the params, including self:
cLuaState L(a_LuaState);
Vector3<T> * self;
T min, max;
if (!L.GetStackValues(1, self, min, max))
{
tolua_error(a_LuaState, "invalid parameters for function 'Vector3<T>:Clamp', expected a Vector3 and two numbers", nullptr);
return 0;
}
// Clamp the vector:
self->Clamp(min, max);
return 0;
}
void DeprecatedBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, nullptr);
@ -604,21 +561,6 @@ void DeprecatedBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "Vector3i");
tolua_function(tolua_S,"abs", tolua_Vector3_Abs<int>);
tolua_function(tolua_S,"clamp", tolua_Vector3_Clamp<int>);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "Vector3f");
tolua_function(tolua_S,"abs", tolua_Vector3_Abs<float>);
tolua_function(tolua_S,"clamp", tolua_Vector3_Clamp<float>);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "Vector3d");
tolua_function(tolua_S,"abs", tolua_Vector3_Abs<double>);
tolua_function(tolua_S,"clamp", tolua_Vector3_Clamp<double>);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
}

View File

@ -1451,6 +1451,57 @@ bool cLuaState::GetStackValue(int a_StackPos, cUUID & a_Value)
template <typename T>
bool cLuaState::GetStackValue(int a_StackPos, Vector3<T> & a_ReturnedVal)
{
tolua_Error err;
if (lua_isnil(m_LuaState, a_StackPos))
{
return false;
}
if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3<double>", 0, &err))
{
a_ReturnedVal = **(static_cast<const Vector3d **>(lua_touserdata(m_LuaState, a_StackPos)));
return true;
}
if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3<float>", 0, &err))
{
a_ReturnedVal = **(static_cast<const Vector3f **>(lua_touserdata(m_LuaState, a_StackPos)));
return true;
}
if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3<int>", 0, &err))
{
a_ReturnedVal = **(static_cast<const Vector3i **>(lua_touserdata(m_LuaState, a_StackPos)));
return true;
}
// Bonus: Allow simple tables to work as Vector3:
if (lua_istable(m_LuaState, a_StackPos))
{
lua_rawgeti(m_LuaState, a_StackPos, 1);
lua_rawgeti(m_LuaState, a_StackPos, 2);
lua_rawgeti(m_LuaState, a_StackPos, 3);
T x, y, z;
if (!GetStackValues(-3, x, y, z))
{
return false;
}
a_ReturnedVal = Vector3<T>(x, y, z);
return true;
}
return false;
}
// Explicitly instantiate the previous function for all Vector3 types:
template bool cLuaState::GetStackValue(int a_StackPos, Vector3d & a_ReturnedVal);
template bool cLuaState::GetStackValue(int a_StackPos, Vector3f & a_ReturnedVal);
template bool cLuaState::GetStackValue(int a_StackPos, Vector3i & a_ReturnedVal);
cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name)
{
// There needs to be at least one value on the stack:
@ -1937,24 +1988,40 @@ bool cLuaState::CheckParamStaticSelf(const char * a_SelfClassName)
bool cLuaState::IsParamUserType(int a_Param, AString a_UserType)
bool cLuaState::IsParamUserType(int a_ParamIdx, AString a_UserType)
{
ASSERT(IsValid());
tolua_Error tolua_err;
return (tolua_isusertype(m_LuaState, a_Param, a_UserType.c_str(), 0, &tolua_err) == 1);
return (tolua_isusertype(m_LuaState, a_ParamIdx, a_UserType.c_str(), 0, &tolua_err) == 1);
}
bool cLuaState::IsParamNumber(int a_Param)
bool cLuaState::IsParamNumber(int a_ParamIdx)
{
ASSERT(IsValid());
tolua_Error tolua_err;
return (tolua_isnumber(m_LuaState, a_Param, 0, &tolua_err) == 1);
return (tolua_isnumber(m_LuaState, a_ParamIdx, 0, &tolua_err) == 1);
}
bool cLuaState::IsParamVector3(int a_ParamIdx)
{
ASSERT(IsValid());
return (
IsParamUserType(a_ParamIdx, "Vector3<double>") ||
IsParamUserType(a_ParamIdx, "Vector3<float>") ||
IsParamUserType(a_ParamIdx, "Vector3<int>") ||
lua_istable(m_LuaState, a_ParamIdx) // Assume any table is good enough
);
}

View File

@ -696,6 +696,10 @@ public:
return GetStackValue(a_StackPos, a_ReturnedVal.GetDest());
}
/** Retrieves any Vector3 value and coerces it into a Vector3<T>. */
template <typename T>
bool GetStackValue(int a_StackPos, Vector3<T> & a_ReturnedVal);
/** Pushes the named value in the table at the top of the stack.
a_Name may be a path containing multiple table levels, such as "cChatColor.Blue".
If the value is found, it is pushed on top of the stack and the returned cStackValue is valid.
@ -805,9 +809,14 @@ public:
Returns false and logs a special warning ("wrong calling convention") if not. */
bool CheckParamStaticSelf(const char * a_SelfClassName);
bool IsParamUserType(int a_Param, AString a_UserType);
/** Returns true if the specified parameter is of the specified class. */
bool IsParamUserType(int a_ParamIdx, AString a_UserType);
bool IsParamNumber(int a_Param);
/** Returns true if the specified parameter is a number. */
bool IsParamNumber(int a_ParamIdx);
/** Returns true if the specified parameter is any of the Vector3 types. */
bool IsParamVector3(int a_ParamIdx);
/** If the status is nonzero, prints the text on the top of Lua stack and returns true */
bool ReportErrors(int status);
@ -1027,7 +1036,12 @@ protected:
/** Removes the specified reference from tracking.
The reference will no longer be invalidated when this Lua state is about to be closed. */
void UntrackRef(cTrackedRef & a_Ref);
} ;
}; // cLuaState
// Instantiate the GetStackValue(Vector3<>) function for all Vector3 types:
extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3d & a_ReturnedVal);
extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3f & a_ReturnedVal);
extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3i & a_ReturnedVal);

View File

@ -2963,9 +2963,9 @@ static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S)
return 4;
}
if (L.IsParamUserType(idx + 1, "Vector3<double>"))
if (L.IsParamVector3(idx + 1))
{
// This is the Vector3d-based variant of the call:
// This is the Vector3-based variant of the call:
if (
!L.CheckParamUserType(idx + 1, "Vector3<double>", idx + 2) ||
!L.CheckParamEnd(idx + 3)
@ -2975,8 +2975,8 @@ static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S)
}
// Get the params:
cWorld * world;
Vector3d * start;
Vector3d * end;
Vector3d start;
Vector3d end;
if (!L.GetStackValues(idx, world, start, end))
{
LOGWARNING("cLineBlockTracer:FirstSolidHitTrace(): Cannot read parameters, aborting the trace.");
@ -2987,7 +2987,7 @@ static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S)
Vector3d hitCoords;
Vector3i hitBlockCoords;
eBlockFace hitBlockFace;
auto isHit = cLineBlockTracer::FirstSolidHitTrace(*world, *start, *end, hitCoords, hitBlockCoords, hitBlockFace);
auto isHit = cLineBlockTracer::FirstSolidHitTrace(*world, start, end, hitCoords, hitBlockCoords, hitBlockFace);
L.Push(isHit);
if (!isHit)
{
@ -2999,7 +2999,7 @@ static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S)
return 4;
}
tolua_error(L, "cLineBlockTracer:FirstSolidHitTrace(): Invalid parameters, expected either a set of coords, or two Vector3d's", nullptr);
tolua_error(L, "cLineBlockTracer:FirstSolidHitTrace(): Invalid parameters, expected either a set of coords, or two Vector3's", nullptr);
return 0;
}
@ -3074,8 +3074,8 @@ static int tolua_cLineBlockTracer_LineOfSightTrace(lua_State * tolua_S)
}
// Get the params:
cWorld * world;
Vector3d * start;
Vector3d * end;
Vector3d start;
Vector3d end;
if (!L.GetStackValues(idx, world, start, end))
{
LOGWARNING("cLineBlockTracer:LineOfSightTrace(): Cannot read parameters, aborting the trace.");
@ -3085,7 +3085,7 @@ static int tolua_cLineBlockTracer_LineOfSightTrace(lua_State * tolua_S)
}
int lineOfSight = cLineBlockTracer::losAirWater;
L.GetStackValue(idx + 7, lineOfSight);
L.Push(cLineBlockTracer::LineOfSightTrace(*world, *start, *end, lineOfSight));
L.Push(cLineBlockTracer::LineOfSightTrace(*world, start, end, lineOfSight));
return 1;
}
@ -3497,19 +3497,19 @@ static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState)
{
/* Function signatures:
bbox:CalcLineIntersection(pt1, pt2) -> bool, [number, blockface]
cBoundingBox:CalcLineIntersection(min, max, pt1, pt2) -> bool, [number, blockface]
cBoundingBox:CalcLineIntersection(min, max, pt1, pt2) -> bool, [number, blockface] (static)
*/
cLuaState L(a_LuaState);
const Vector3d * min;
const Vector3d * max;
const Vector3d * pt1;
const Vector3d * pt2;
Vector3d min;
Vector3d max;
Vector3d pt1;
Vector3d pt2;
double lineCoeff;
eBlockFace blockFace;
bool res;
if (L.GetStackValues(2, min, max, pt1, pt2)) // Try the static signature first
{
res = cBoundingBox::CalcLineIntersection(*min, *max, *pt1, *pt2, lineCoeff, blockFace);
res = cBoundingBox::CalcLineIntersection(min, max, pt1, pt2, lineCoeff, blockFace);
}
else
{
@ -3520,7 +3520,7 @@ static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState)
tolua_error(a_LuaState, "Invalid function params. Expected either bbox:CalcLineIntersection(pt1, pt2) or cBoundingBox:CalcLineIntersection(min, max, pt1, pt2).", nullptr);
return 0;
}
res = bbox->CalcLineIntersection(*pt1, *pt2, lineCoeff, blockFace);
res = bbox->CalcLineIntersection(pt1, pt2, lineCoeff, blockFace);
}
L.Push(res);
if (res)
@ -3984,11 +3984,11 @@ static int tolua_cCuboid_Assign(lua_State * tolua_S)
}
// Try the (Vector3i, Vector3i) param version:
Vector3i * pt1 = nullptr;
Vector3i * pt2 = nullptr;
if (L.GetStackValues(2, pt1, pt2) && (pt1 != nullptr) && (pt2 != nullptr))
Vector3i pt1;
Vector3i pt2;
if (L.GetStackValues(2, pt1, pt2))
{
self->Assign(*pt1, *pt2);
self->Assign(pt1, pt2);
return 0;
}
return L.ApiParamError("Invalid parameter, expected either a cCuboid or two Vector3i-s.");
@ -4014,32 +4014,20 @@ static int tolua_cCuboid_IsInside(lua_State * tolua_S)
int x, y, z;
if (L.GetStackValues(2, x, y, z))
{
LOGWARNING("cCuboid:IsInside(x, y, z) is deprecated, use cCuboid:IsInside(Vector3d) instead.");
LOGWARNING("cCuboid:IsInside(x, y, z) is deprecated, use cCuboid:IsInside(Vector3) instead.");
L.LogStackTrace();
self->Move({x, y, z});
return 0;
L.Push(self->IsInside(Vector3i{x, y, z}));
return 1;
}
// Try the (Vector3i) param version:
// Try the Vector3 param version:
Vector3d pt;
if (L.GetStackValue(2, pt))
{
Vector3i * pt = nullptr;
if (L.GetStackValue(2, pt) && (pt != nullptr))
{
L.Push(self->IsInside(*pt));
return 1;
}
L.Push(self->IsInside(pt));
return 1;
}
// Try the (Vector3d) param version:
{
Vector3d * pt = nullptr;
if (L.GetStackValue(2, pt) && (pt != nullptr))
{
L.Push(self->IsInside(*pt));
return 1;
}
}
return L.ApiParamError("Invalid parameter #2, expected a Vector3i or a Vector3d.");
return L.ApiParamError("Invalid parameter #2, expected a Vector3.");
}
@ -4068,12 +4056,12 @@ static int tolua_cCuboid_Move(lua_State * tolua_S)
return 0;
}
Vector3i * offset = nullptr;
if (!L.GetStackValue(2, offset) || (offset == nullptr))
Vector3i offset;
if (!L.GetStackValue(2, offset))
{
return L.ApiParamError("Invalid parameter #2, expected a Vector3i.");
return L.ApiParamError("Invalid parameter #2, expected a Vector3.");
}
self->Move(*offset);
self->Move(offset);
return 0;
}

View File

@ -48,14 +48,10 @@ static int readCuboidOverloadParams(cLuaState & a_LuaState, int a_StartParam, cC
else
{
// Assume the 2-Vector3i version:
Vector3i * p1;
Vector3i * p2;
if (!a_LuaState.GetStackValues(a_StartParam, p1, p2))
if (!a_LuaState.GetStackValues(a_StartParam, a_Cuboid.p1, a_Cuboid.p2))
{
return a_LuaState.ApiParamError("Cannot read the bounds parameter, expected two Vector3i instances");
}
a_Cuboid.p1 = *p1;
a_Cuboid.p2 = *p2;
return a_StartParam + 2;
}
}
@ -85,12 +81,10 @@ static int readVector3iOverloadParams(cLuaState & a_LuaState, int a_StartParam,
else
{
// Assume the Vector3i version:
Vector3i * c;
if (!a_LuaState.GetStackValues(a_StartParam, c))
if (!a_LuaState.GetStackValues(a_StartParam, a_Coords))
{
return a_LuaState.ApiParamError("Cannot read the %s, expected a Vector3i instance", a_ParamName);
}
a_Coords = *c;
return a_StartParam + 1;
}
}

View File

@ -39,10 +39,8 @@ static bool CheckParamVectorOr3Numbers(cLuaState & L, const char * a_VectorName,
template <typename T>
static bool GetStackVectorOr3Numbers(cLuaState & L, int a_Index, Vector3<T> & a_Return)
{
Vector3<T> * UserType;
if (L.GetStackValue(a_Index, UserType))
if (L.GetStackValue(a_Index, a_Return))
{
a_Return = *UserType;
return true;
}
return L.GetStackValues(a_Index, a_Return.x, a_Return.y, a_Return.z);
@ -367,10 +365,10 @@ static int tolua_cWorld_DoExplosionAt(lua_State * tolua_S)
case esBed:
{
// esBed receives a Vector3i SourceData param:
Vector3i * pos = nullptr;
Vector3i pos;
L.GetStackValue(8, pos);
SourceType = esBed;
SourceData = pos;
SourceData = &pos;
break;
}
@ -481,24 +479,19 @@ static int tolua_cWorld_DoWithNearestPlayer(lua_State * tolua_S)
// Get parameters:
cWorld * Self;
Vector3d * Position;
Vector3d Position;
double RangeLimit;
cLuaState::cRef FnRef;
bool CheckLineOfSight = true, IgnoreSpectators = true; // Defaults for the optional params
L.GetStackValues(1, Self, Position, RangeLimit, FnRef, CheckLineOfSight, IgnoreSpectators);
if (Position == nullptr)
{
return L.ApiParamError("Expected a non-nil Vector3d for parameter #2");
}
if (!FnRef.IsValid())
{
return L.ApiParamError("Expected a valid callback function for parameter #3");
}
// Call the function:
bool res = Self->DoWithNearestPlayer(*Position, RangeLimit, [&](cPlayer & a_Player)
bool res = Self->DoWithNearestPlayer(Position, RangeLimit, [&](cPlayer & a_Player)
{
bool ret = false;
L.Call(FnRef, &a_Player, cLuaState::Return, ret);
@ -895,7 +888,7 @@ static int tolua_cWorld_SpawnSplitExperienceOrbs(lua_State* tolua_S)
}
cWorld * self = nullptr;
Vector3d * Position = nullptr;
Vector3d Position;
int Reward;
L.GetStackValues(1, self, Position, Reward);
if (self == nullptr)
@ -903,14 +896,9 @@ static int tolua_cWorld_SpawnSplitExperienceOrbs(lua_State* tolua_S)
tolua_error(tolua_S, "Invalid 'self' in function 'SpawnSplitExperienceOrbs'", nullptr);
return 0;
}
if (Position == nullptr)
{
tolua_error(tolua_S, "Error in function 'SpawnSplitExperienceOrbs' arg #2. Value must not be nil.", nullptr);
return 0;
}
// Execute and push result:
L.Push(self->SpawnExperienceOrb(Position->x, Position->y, Position->z, Reward));
L.Push(self->SpawnExperienceOrb(Position, Reward));
return 1;
}