Merge pull request #1892 from mc-server/DoWithPlugin
Implemented cPluginManager:DoWithPlugin(), fixed ForEachPlugin().
This commit is contained in:
commit
a41f21f76f
@ -66,12 +66,13 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
|||||||
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
{ Params = "Command, Callback, HelpString", Return = "[bool]", Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature: <pre class=\"prettyprint lang-lua\">function(Split)</pre> The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented)." },
|
||||||
},
|
},
|
||||||
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
|
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
|
||||||
|
DoWithPlugin = { Params = "PluginName, CallbackFn", Return = "bool", Notes = "(STATIC) Calls the CallbackFn for the specified plugin, if found. A plugin can be found even if it is currently unloaded, disabled or errored, the callback should check the plugin status. If the plugin is not found, this function returns false, otherwise it returns the bool value that the callback has returned. The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function ({{cPlugin|Plugin}})</pre>" },
|
||||||
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Executes the command as if given by the specified Player. Checks permissions." },
|
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Executes the command as if given by the specified Player. Checks permissions." },
|
||||||
FindPlugins = { Params = "", Return = "", Notes = "<b>OBSOLETE</b>, use RefreshPluginList() instead"},
|
FindPlugins = { Params = "", Return = "", Notes = "<b>OBSOLETE</b>, use RefreshPluginList() instead"},
|
||||||
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
|
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
|
||||||
ForEachCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function(Command, Permission, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
ForEachCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function(Command, Permission, HelpString)</pre> If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
||||||
ForEachConsoleCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function (Command, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
ForEachConsoleCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function (Command, HelpString)</pre> If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
||||||
ForEachPlugin = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function ({{cPlugin|Plugin}})</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
ForEachPlugin = { Params = "CallbackFn", Return = "bool", Notes = "(STATIC) Calls the CallbackFn function for each plugin that is currently discovered by MCServer (including disabled, unloaded and errrored plugins). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function ({{cPlugin|Plugin}})</pre> If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
||||||
Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
|
Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
|
||||||
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => value], where value is a valid {{cPlugin}} if the plugin is loaded, or the bool value false if the plugin is not loaded." },
|
GetAllPlugins = { Params = "", Return = "table", Notes = "Returns a table (dictionary) of all plugins, [name => value], where value is a valid {{cPlugin}} if the plugin is loaded, or the bool value false if the plugin is not loaded." },
|
||||||
GetCommandPermission = { Params = "Command", Return = "Permission", Notes = "Returns the permission needed for executing the specified command" },
|
GetCommandPermission = { Params = "Command", Return = "Permission", Notes = "Returns the permission needed for executing the specified command" },
|
||||||
|
@ -62,6 +62,7 @@ function Initialize(a_Plugin)
|
|||||||
-- TestRankMgr()
|
-- TestRankMgr()
|
||||||
TestFileExt()
|
TestFileExt()
|
||||||
TestFileLastMod()
|
TestFileLastMod()
|
||||||
|
TestPluginInterface()
|
||||||
|
|
||||||
local LastSelfMod = cFile:GetLastModificationTime(a_Plugin:GetLocalFolder() .. "/Debuggers.lua")
|
local LastSelfMod = cFile:GetLastModificationTime(a_Plugin:GetLocalFolder() .. "/Debuggers.lua")
|
||||||
LOG("Debuggers.lua last modified on " .. os.date("%Y-%m-%dT%H:%M:%S", LastSelfMod))
|
LOG("Debuggers.lua last modified on " .. os.date("%Y-%m-%dT%H:%M:%S", LastSelfMod))
|
||||||
@ -75,6 +76,18 @@ function Initialize(a_Plugin)
|
|||||||
)
|
)
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
|
-- Test the crash in #1889:
|
||||||
|
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY,
|
||||||
|
function (a_CBPlayer, a_CBEntity)
|
||||||
|
a_CBPlayer:GetWorld():DoWithEntityByID( -- This will crash the server in #1889
|
||||||
|
a_CBEntity:GetUniqueID(),
|
||||||
|
function(Entity)
|
||||||
|
LOG("RightClicking an entity, crash #1889 fixed")
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -82,6 +95,27 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function TestPluginInterface()
|
||||||
|
cPluginManager:DoWithPlugin("Core",
|
||||||
|
function (a_CBPlugin)
|
||||||
|
if (a_CBPlugin:GetStatus() == cPluginManager.psLoaded) then
|
||||||
|
LOG("Core plugin was found, version " .. a_CBPlugin:GetVersion())
|
||||||
|
else
|
||||||
|
LOG("Core plugin is not loaded")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
cPluginManager:ForEachPlugin(
|
||||||
|
function (a_CBPlugin)
|
||||||
|
LOG("Plugin in " .. a_CBPlugin:GetFolderName() .. " has an API name of " .. a_CBPlugin:GetName() .. " and status " .. a_CBPlugin:GetStatus())
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function TestFileExt()
|
function TestFileExt()
|
||||||
assert(cFile:ChangeFileExt("fileless_dir/", "new") == "fileless_dir/")
|
assert(cFile:ChangeFileExt("fileless_dir/", "new") == "fileless_dir/")
|
||||||
assert(cFile:ChangeFileExt("fileless_dir/", ".new") == "fileless_dir/")
|
assert(cFile:ChangeFileExt("fileless_dir/", ".new") == "fileless_dir/")
|
||||||
|
@ -740,6 +740,18 @@ void cLuaState::Push(cPlayer * a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::Push(cPlugin * a_Plugin)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
tolua_pushusertype(m_LuaState, a_Plugin, "cPlugin");
|
||||||
|
m_NumCurrentFunctionArgs += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::Push(cPluginLua * a_Plugin)
|
void cLuaState::Push(cPluginLua * a_Plugin)
|
||||||
{
|
{
|
||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
@ -911,15 +923,6 @@ void cLuaState::PushUserType(void * a_Object, const char * a_Type)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
|
|
||||||
{
|
|
||||||
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
|
void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@ -934,12 +937,18 @@ void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
|
void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
|
||||||
{
|
{
|
||||||
if (lua_isnumber(m_LuaState, a_StackPos))
|
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
|
||||||
{
|
}
|
||||||
a_ReturnedVal = (int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
|
||||||
|
{
|
||||||
|
a_Ref.RefStack(*this, a_StackPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -959,10 +968,26 @@ void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
|
void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (!lua_isnumber(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a_ReturnedVal = static_cast<eWeather>(Clamp(
|
||||||
|
static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)),
|
||||||
|
static_cast<int>(wSunny), static_cast<int>(wThunderstorm))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
|
||||||
{
|
{
|
||||||
if (lua_isnumber(m_LuaState, a_StackPos))
|
if (lua_isnumber(m_LuaState, a_StackPos))
|
||||||
{
|
{
|
||||||
a_ReturnedVal = (eWeather)Clamp((int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal), (int)wSunny, (int)wThunderstorm);
|
a_ReturnedVal = static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,6 +1013,60 @@ void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, pPluginManager & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (lua_isnil(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tolua_Error err;
|
||||||
|
if (tolua_isusertype(m_LuaState, a_StackPos, "cPluginManager", false, &err))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = *(reinterpret_cast<cPluginManager **>(lua_touserdata(m_LuaState, a_StackPos)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, pRoot & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (lua_isnil(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tolua_Error err;
|
||||||
|
if (tolua_isusertype(m_LuaState, a_StackPos, "cRoot", false, &err))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = *(reinterpret_cast<cRoot **>(lua_touserdata(m_LuaState, a_StackPos)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, pScoreboard & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (lua_isnil(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tolua_Error err;
|
||||||
|
if (tolua_isusertype(m_LuaState, a_StackPos, "cScoreboard", false, &err))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = *(reinterpret_cast<cScoreboard **>(lua_touserdata(m_LuaState, a_StackPos)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
|
void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
|
||||||
{
|
{
|
||||||
if (lua_isnil(m_LuaState, a_StackPos))
|
if (lua_isnil(m_LuaState, a_StackPos))
|
||||||
@ -998,7 +1077,7 @@ void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
|
|||||||
tolua_Error err;
|
tolua_Error err;
|
||||||
if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err))
|
if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err))
|
||||||
{
|
{
|
||||||
a_ReturnedVal = *((cWorld **)lua_touserdata(m_LuaState, a_StackPos));
|
a_ReturnedVal = *(reinterpret_cast<cWorld **>(lua_touserdata(m_LuaState, a_StackPos)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,15 +1085,6 @@ void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
|
|
||||||
{
|
|
||||||
a_Ref.RefStack(*this, a_StackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::CallFunction(int a_NumResults)
|
bool cLuaState::CallFunction(int a_NumResults)
|
||||||
{
|
{
|
||||||
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
||||||
|
@ -37,33 +37,40 @@ extern "C"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cWorld;
|
|
||||||
class cPlayer;
|
|
||||||
class cEntity;
|
|
||||||
class cProjectileEntity;
|
|
||||||
class cMonster;
|
|
||||||
class cItem;
|
|
||||||
class cItems;
|
|
||||||
class cClientHandle;
|
|
||||||
class cPickup;
|
|
||||||
class cChunkDesc;
|
|
||||||
class cCraftingGrid;
|
|
||||||
class cCraftingRecipe;
|
|
||||||
struct TakeDamageInfo;
|
|
||||||
class cWindow;
|
|
||||||
class cPluginLua;
|
|
||||||
struct HTTPRequest;
|
|
||||||
class cWebAdmin;
|
|
||||||
struct HTTPTemplateRequest;
|
|
||||||
class cTNTEntity;
|
|
||||||
class cHopperEntity;
|
|
||||||
class cBlockEntity;
|
class cBlockEntity;
|
||||||
class cBoundingBox;
|
class cBoundingBox;
|
||||||
class cLuaTCPLink;
|
class cChunkDesc;
|
||||||
|
class cClientHandle;
|
||||||
|
class cCraftingGrid;
|
||||||
|
class cCraftingRecipe;
|
||||||
|
class cEntity;
|
||||||
|
class cHopperEntity;
|
||||||
|
class cItem;
|
||||||
|
class cItems;
|
||||||
class cLuaServerHandle;
|
class cLuaServerHandle;
|
||||||
|
class cLuaTCPLink;
|
||||||
class cLuaUDPEndpoint;
|
class cLuaUDPEndpoint;
|
||||||
|
class cMonster;
|
||||||
|
class cPickup;
|
||||||
|
class cPlayer;
|
||||||
|
class cPlugin;
|
||||||
|
class cPluginLua;
|
||||||
|
class cPluginManager;
|
||||||
|
class cProjectileEntity;
|
||||||
|
class cRoot;
|
||||||
|
class cScoreboard;
|
||||||
|
class cTNTEntity;
|
||||||
|
class cWebAdmin;
|
||||||
|
class cWindow;
|
||||||
|
class cWorld;
|
||||||
|
struct HTTPRequest;
|
||||||
|
struct HTTPTemplateRequest;
|
||||||
|
struct TakeDamageInfo;
|
||||||
|
|
||||||
typedef cBoundingBox * pBoundingBox;
|
typedef cBoundingBox * pBoundingBox;
|
||||||
|
typedef cPluginManager * pPluginManager;
|
||||||
|
typedef cRoot * pRoot;
|
||||||
|
typedef cScoreboard * pScoreboard;
|
||||||
typedef cWorld * pWorld;
|
typedef cWorld * pWorld;
|
||||||
|
|
||||||
|
|
||||||
@ -217,6 +224,7 @@ public:
|
|||||||
void Push(cMonster * a_Monster);
|
void Push(cMonster * a_Monster);
|
||||||
void Push(cPickup * a_Pickup);
|
void Push(cPickup * a_Pickup);
|
||||||
void Push(cPlayer * a_Player);
|
void Push(cPlayer * a_Player);
|
||||||
|
void Push(cPlugin * a_Plugin);
|
||||||
void Push(cPluginLua * a_Plugin);
|
void Push(cPluginLua * a_Plugin);
|
||||||
void Push(cProjectileEntity * a_ProjectileEntity);
|
void Push(cProjectileEntity * a_ProjectileEntity);
|
||||||
void Push(cTNTEntity * a_TNTEntity);
|
void Push(cTNTEntity * a_TNTEntity);
|
||||||
@ -231,30 +239,19 @@ public:
|
|||||||
void Push(void * a_Ptr);
|
void Push(void * a_Ptr);
|
||||||
void Push(std::chrono::milliseconds a_time);
|
void Push(std::chrono::milliseconds a_time);
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid bool. 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.
|
||||||
void GetStackValue(int a_StackPos, bool & a_Value);
|
// Enum values are clamped to their allowed range.
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid string. If not, a_Value is unchanged */
|
|
||||||
void GetStackValue(int a_StackPos, AString & a_Value);
|
void GetStackValue(int a_StackPos, AString & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, bool & a_Value);
|
||||||
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
|
|
||||||
void GetStackValue(int a_StackPos, int & a_Value);
|
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
|
|
||||||
void GetStackValue(int a_StackPos, double & a_Value);
|
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather.
|
|
||||||
If not, a_Value is unchanged. */
|
|
||||||
void GetStackValue(int a_StackPos, eWeather & a_Value);
|
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid cBoundingBox class. If not, a_Value is unchanged */
|
|
||||||
void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
|
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */
|
|
||||||
void GetStackValue(int a_StackPos, pWorld & a_Value);
|
|
||||||
|
|
||||||
/** Store the value at a_StackPos as a reference. */
|
|
||||||
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, eWeather & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, int & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, pPluginManager & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, pRoot & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, pScoreboard & a_Value);
|
||||||
|
void GetStackValue(int a_StackPos, pWorld & a_Value);
|
||||||
|
|
||||||
/** Call the specified Lua function.
|
/** Call the specified Lua function.
|
||||||
Returns true if call succeeded, false if there was an error.
|
Returns true if call succeeded, false if there was an error.
|
||||||
|
@ -67,7 +67,7 @@ static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
|
|||||||
|
|
||||||
// Insert function name into error msg
|
// Insert function name into error msg
|
||||||
AString msg(a_pFormat);
|
AString msg(a_pFormat);
|
||||||
ReplaceString(msg, "#funcname#", entry.name?entry.name:"?");
|
ReplaceString(msg, "#funcname#", (entry.name != nullptr) ? entry.name : "?");
|
||||||
|
|
||||||
// Copied from luaL_error and modified
|
// Copied from luaL_error and modified
|
||||||
va_list argp;
|
va_list argp;
|
||||||
@ -493,94 +493,130 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Binds the DoWith(ItemName) functions of regular classes. */
|
||||||
template <
|
template <
|
||||||
class Ty1,
|
class Ty1,
|
||||||
class Ty2,
|
class Ty2,
|
||||||
bool (Ty1::*Func1)(const AString &, cItemCallback<Ty2> &)
|
bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
|
||||||
>
|
>
|
||||||
static int tolua_DoWith(lua_State* tolua_S)
|
static int tolua_DoWith(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
|
// Check params:
|
||||||
if ((NumArgs != 2) && (NumArgs != 3))
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamString(2) ||
|
||||||
|
!L.CheckParamFunction(3)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, nullptr);
|
// Get parameters:
|
||||||
|
Ty1 * Self;
|
||||||
const char * ItemName = tolua_tocppstring(tolua_S, 2, "");
|
AString ItemName;
|
||||||
if ((ItemName == nullptr) || (ItemName[0] == 0))
|
cLuaState::cRef FnRef;
|
||||||
|
L.GetStackValues(1, Self, ItemName, FnRef);
|
||||||
|
if (Self == nullptr)
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
|
||||||
}
|
}
|
||||||
if (!lua_isfunction(tolua_S, 3))
|
if (ItemName.empty() || (ItemName[0] == 0))
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1");
|
||||||
}
|
}
|
||||||
|
if (!FnRef.IsValid())
|
||||||
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
|
|
||||||
int TableRef = LUA_REFNIL;
|
|
||||||
if (NumArgs == 3)
|
|
||||||
{
|
{
|
||||||
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||||
if (TableRef == LUA_REFNIL)
|
|
||||||
{
|
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* table value is popped, and now function is on top of the stack */
|
|
||||||
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
|
|
||||||
if (FuncRef == LUA_REFNIL)
|
|
||||||
{
|
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||||
LuaState(a_LuaState),
|
m_LuaState(a_LuaState),
|
||||||
FuncRef(a_FuncRef),
|
m_FnRef(a_FnRef)
|
||||||
TableRef(a_TableRef)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
bool ret = false;
|
||||||
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||||
if (TableRef != LUA_REFNIL)
|
return ret;
|
||||||
|
}
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
cLuaState::cRef & m_FnRef;
|
||||||
|
} Callback(L, FnRef);
|
||||||
|
|
||||||
|
// Call the DoWith function:
|
||||||
|
bool res = (Self->*DoWithFn)(ItemName, Callback);
|
||||||
|
|
||||||
|
// Push the result as the return value:
|
||||||
|
L.Push(res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Template for static functions DoWith(ItemName), on a type that has a static ::Get() function. */
|
||||||
|
template <
|
||||||
|
class Ty1,
|
||||||
|
class Ty2,
|
||||||
|
bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
|
||||||
|
>
|
||||||
|
static int tolua_StaticDoWith(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamString(2) ||
|
||||||
|
!L.CheckParamFunction(3)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
// Get parameters:
|
||||||
if (cLuaState::ReportErrors(LuaState, s))
|
AString ItemName;
|
||||||
|
cLuaState::cRef FnRef;
|
||||||
|
L.GetStackValues(2, ItemName, FnRef);
|
||||||
|
if (ItemName.empty() || (ItemName[0] == 0))
|
||||||
{
|
{
|
||||||
return true; // Abort enumeration
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1");
|
||||||
}
|
}
|
||||||
if (lua_isboolean(LuaState, -1))
|
if (!FnRef.IsValid())
|
||||||
{
|
{
|
||||||
return (tolua_toboolean(LuaState, -1, 0) > 0);
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||||
}
|
}
|
||||||
return false; /* Continue enumeration */
|
|
||||||
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||||
|
m_LuaState(a_LuaState),
|
||||||
|
m_FnRef(a_FnRef)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
lua_State * LuaState;
|
|
||||||
int FuncRef;
|
|
||||||
int TableRef;
|
|
||||||
} Callback(tolua_S, FuncRef, TableRef);
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
cLuaState::cRef & m_FnRef;
|
||||||
|
} Callback(L, FnRef);
|
||||||
|
|
||||||
bool bRetVal = (self->*Func1)(ItemName, Callback);
|
// Call the DoWith function:
|
||||||
|
bool res = (Ty1::Get()->*DoWithFn)(ItemName, Callback);
|
||||||
|
|
||||||
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
|
// Push the result as the return value:
|
||||||
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
|
L.Push(res);
|
||||||
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
|
|
||||||
|
|
||||||
/* Push return value on stack */
|
|
||||||
tolua_pushboolean(tolua_S, bRetVal);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -916,6 +952,9 @@ static int tolua_ForEachInBox(lua_State * tolua_S)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
cLuaState::cRef & m_FnRef;
|
||||||
|
|
||||||
// cItemCallback<Ty2> overrides:
|
// cItemCallback<Ty2> overrides:
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
@ -929,8 +968,6 @@ static int tolua_ForEachInBox(lua_State * tolua_S)
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
cLuaState & m_LuaState;
|
|
||||||
cLuaState::cRef & m_FnRef;
|
|
||||||
} Callback(L, FnRef);
|
} Callback(L, FnRef);
|
||||||
|
|
||||||
bool bRetVal = (Self->*Func1)(*Box, Callback);
|
bool bRetVal = (Self->*Func1)(*Box, Callback);
|
||||||
@ -953,86 +990,105 @@ template <
|
|||||||
>
|
>
|
||||||
static int tolua_ForEach(lua_State * tolua_S)
|
static int tolua_ForEach(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
|
// Check params:
|
||||||
if ((NumArgs != 1) && (NumArgs != 2))
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamFunction(2) ||
|
||||||
|
!L.CheckParamEnd(3)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 1 or 2 arguments, got %i", NumArgs);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, nullptr);
|
// Get the params:
|
||||||
|
Ty1 * self;
|
||||||
|
L.GetStackValues(1, self);
|
||||||
|
cLuaState::cRef FnRef(L, 2);
|
||||||
if (self == nullptr)
|
if (self == nullptr)
|
||||||
{
|
{
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
|
return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'.");
|
||||||
}
|
|
||||||
|
|
||||||
if (!lua_isfunction(tolua_S, 2))
|
|
||||||
{
|
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
|
|
||||||
int TableRef = LUA_REFNIL;
|
|
||||||
if (NumArgs == 2)
|
|
||||||
{
|
|
||||||
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
|
|
||||||
if (TableRef == LUA_REFNIL)
|
|
||||||
{
|
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #2");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* table value is popped, and now function is on top of the stack */
|
|
||||||
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
|
|
||||||
if (FuncRef == LUA_REFNIL)
|
|
||||||
{
|
|
||||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class cLuaCallback : public cItemCallback<Ty2>
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef):
|
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||||
LuaState(a_LuaState),
|
m_LuaState(a_LuaState),
|
||||||
FuncRef(a_FuncRef),
|
m_FnRef(a_FnRef)
|
||||||
TableRef(a_TableRef)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
cLuaState::cRef & m_FnRef;
|
||||||
|
|
||||||
virtual bool Item(Ty2 * a_Item) override
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
{
|
{
|
||||||
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
|
bool res = false; // By default continue the enumeration
|
||||||
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
|
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
|
||||||
if (TableRef != LUA_REFNIL)
|
return res;
|
||||||
|
}
|
||||||
|
} Callback(L, FnRef);
|
||||||
|
|
||||||
|
// Call the enumeration:
|
||||||
|
bool res = (self->*Func1)(Callback);
|
||||||
|
|
||||||
|
// Push the return value:
|
||||||
|
L.Push(res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Implements bindings for ForEach() functions in a class that is static (has a ::Get() static function). */
|
||||||
|
template <
|
||||||
|
class Ty1,
|
||||||
|
class Ty2,
|
||||||
|
bool (Ty1::*Func1)(cItemCallback<Ty2> &)
|
||||||
|
>
|
||||||
|
static int tolua_StaticForEach(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Check params:
|
||||||
|
cLuaState L(tolua_S);
|
||||||
|
if (
|
||||||
|
!L.CheckParamFunction(2) ||
|
||||||
|
!L.CheckParamEnd(3)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
|
// Get the params:
|
||||||
if (cLuaState::ReportErrors(LuaState, s))
|
cLuaState::cRef FnRef(L, 2);
|
||||||
|
|
||||||
|
class cLuaCallback : public cItemCallback<Ty2>
|
||||||
{
|
{
|
||||||
return true; /* Abort enumeration */
|
public:
|
||||||
}
|
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
|
||||||
|
m_LuaState(a_LuaState),
|
||||||
if (lua_isboolean(LuaState, -1))
|
m_FnRef(a_FnRef)
|
||||||
{
|
{
|
||||||
return (tolua_toboolean(LuaState, -1, 0) > 0);
|
|
||||||
}
|
}
|
||||||
return false; /* Continue enumeration */
|
|
||||||
|
private:
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
cLuaState::cRef & m_FnRef;
|
||||||
|
|
||||||
|
virtual bool Item(Ty2 * a_Item) override
|
||||||
|
{
|
||||||
|
bool res = false; // By default continue the enumeration
|
||||||
|
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
lua_State * LuaState;
|
} Callback(L, FnRef);
|
||||||
int FuncRef;
|
|
||||||
int TableRef;
|
|
||||||
} Callback(tolua_S, FuncRef, TableRef);
|
|
||||||
|
|
||||||
bool bRetVal = (self->*Func1)(Callback);
|
// Call the enumeration:
|
||||||
|
bool res = (Ty1::Get()->*Func1)(Callback);
|
||||||
|
|
||||||
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
|
// Push the return value:
|
||||||
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
|
L.Push(res);
|
||||||
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
|
|
||||||
|
|
||||||
/* Push return value on stack */
|
|
||||||
tolua_pushboolean(tolua_S, bRetVal);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3814,10 +3870,11 @@ void ManualBindings::Bind(lua_State * tolua_S)
|
|||||||
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
|
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
|
||||||
tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand);
|
tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand);
|
||||||
tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin);
|
tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin);
|
||||||
|
tolua_function(tolua_S, "DoWithPlugin", tolua_StaticDoWith<cPluginManager, cPlugin, &cPluginManager::DoWithPlugin>);
|
||||||
tolua_function(tolua_S, "FindPlugins", tolua_cPluginManager_FindPlugins);
|
tolua_function(tolua_S, "FindPlugins", tolua_cPluginManager_FindPlugins);
|
||||||
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
|
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
|
||||||
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
|
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
|
||||||
tolua_function(tolua_S, "ForEachPlugin", tolua_ForEach<cPluginManager, cPlugin, &cPluginManager::ForEachPlugin>);
|
tolua_function(tolua_S, "ForEachPlugin", tolua_StaticForEach<cPluginManager, cPlugin, &cPluginManager::ForEachPlugin>);
|
||||||
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
|
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
|
||||||
tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin);
|
tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin);
|
||||||
tolua_function(tolua_S, "GetPlugin", tolua_cPluginManager_GetPlugin);
|
tolua_function(tolua_S, "GetPlugin", tolua_cPluginManager_GetPlugin);
|
||||||
|
Loading…
Reference in New Issue
Block a user