Moved command API into cPluginManager.

As specified in http://forum.mc-server.org/showthread.php?tid=765 , commands are now bound using a single function, cPluginManager:BindCommand().

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1183 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2013-02-01 19:55:42 +00:00
parent 71bbf2d44b
commit 019c8b5bc7
15 changed files with 685 additions and 687 deletions

View File

@ -1,56 +1,40 @@
function HandleHelpCommand( Split, Player )
function HandleHelpCommand(Split, Player)
local PluginManager = cRoot:Get():GetPluginManager()
local LinesPerPage = 9
local CurrentPage = 1
local CurrentLine = 0
local LinesPerPage = 9;
local CurrentPage = 1;
local CurrentLine = 0;
local PageRequested = 1;
local Output = {};
if( #Split == 2 ) then
CurrentPage = tonumber(Split[2])
if (#Split == 2) then
PageRequested = tonumber(Split[2]);
end
local Pages = {}
local Process = function(Command, Permission, HelpString)
if not(Player:HasPermission(Permission)) then
return false;
end;
if (HelpString == "") then
return false;
end;
local PluginList = PluginManager:GetAllPlugins()
for k, Plugin in pairs(PluginList) do
if( Plugin ) then
local Commands = Plugin:GetCommands()
for i, v in ipairs( Commands ) do
if( Player:HasPermission( v.Permission ) ) then
local PageNum = math.floor( CurrentLine/LinesPerPage )+1
if( Pages[ PageNum ] == nil ) then Pages[ PageNum ] = {} end -- Create page
if( Pages[ PageNum ].ShownName ~= Plugin:GetName() and SHOW_PLUGIN_NAMES == true ) then
if( CurrentLine == LinesPerPage * PageNum -1 ) then -- Don't add if it's the last line of the page, it looks silly
-- Add it to the next page instead
CurrentLine = CurrentLine+1
PageNum = math.floor( CurrentLine/LinesPerPage )+1
if( Pages[ PageNum ] == nil ) then Pages[ PageNum ] = {} end -- Create page
table.insert( Pages[ PageNum ], cChatColor.Gold .. Plugin:GetName() )
else
Pages[ PageNum ].ShownName = Plugin:GetName()
table.insert( Pages[ PageNum ], cChatColor.Gold .. Plugin:GetName() )
end
CurrentLine = CurrentLine+1
PageNum = math.floor( CurrentLine/LinesPerPage )+1
if( Pages[ PageNum ] == nil ) then Pages[ PageNum ] = {} end -- Create page
end
local Message = cChatColor.Blue .. v.Command .. v.Description;
table.insert( Pages[ PageNum ], Message )
CurrentLine = CurrentLine+1
end
end
end
end
Player:SendMessage( cChatColor.Purple .. "- All commands - " .. cChatColor.Gold .. "[Page " .. (CurrentPage) .."/"..#Pages.."]" )
if( Pages[CurrentPage] ~= nil ) then
for i, v in ipairs(Pages[CurrentPage]) do
Player:SendMessage( v )
end
CurrentLine = CurrentLine + 1;
CurrentPage = math.floor(CurrentLine / LinesPerPage) + 1;
if (CurrentPage ~= PageRequested) then
return false;
end;
table.insert(Output, cChatColor.Blue .. Command .. HelpString);
end
PluginManager:ForEachCommand(Process);
-- CurrentPage now contains the total number of pages, and Output has the individual help lines to be sent
Player:SendMessage(cChatColor.Purple .. "- All commands - " .. cChatColor.Gold .. "[Page " .. PageRequested .. " / " .. CurrentPage .. "]");
for idx, msg in ipairs(Output) do
Player:SendMessage(msg);
end;
return true
end

View File

@ -8,11 +8,15 @@ PLUGIN = {} -- Reference to own plugin object
BannedPlayersIni = {}
WhiteListIni = {}
function Initialize( Plugin )
function Initialize(Plugin)
PLUGIN = Plugin
Plugin:SetName( "Core" )
Plugin:SetVersion(9)
Plugin:SetName("Core")
Plugin:SetVersion(10)
PluginManager = cRoot:Get():GetPluginManager()
PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_JOINED)
@ -22,50 +26,29 @@ function Initialize( Plugin )
PluginManager:AddHook(Plugin, cPluginManager.HOOK_KILLING)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_CRAFTING_NO_RECIPE)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT) -- used in web_chat.lua
Plugin:AddCommand("/help", " - [Page] Show this message", "core.help")
Plugin:AddCommand("/pluginlist", " - Show list of plugins", "core.pluginlist")
Plugin:AddCommand("/tp", " - [Player] - Teleport yourself to a player", "core.teleport")
Plugin:AddCommand("/item", " - [ItemType/Name] <Amount> - Give yourself an item", "core.item")
Plugin:AddCommand("/list", " - Shows list of connected players", "core.playerlist")
Plugin:AddCommand("/motd", " - Show message of the day", "core.motd")
Plugin:AddCommand("/reload", " - Reload all plugins", "core.reload")
Plugin:AddCommand("/stop", " - Stops the server", "core.stop")
Plugin:AddCommand("/time", " - [Day/Night] - Sets the time of day", "core.time")
Plugin:AddCommand("/spawn", " - Return to the spawn", "core.spawn")
Plugin:AddCommand("/kick", " - [Player] - Kick a player", "core.kick")
Plugin:AddCommand("/ban", " - [Player] - Ban a player", "core.ban")
Plugin:AddCommand("/unban", " - [Player] - Unban a player", "core.unban")
Plugin:AddCommand("/top", " - Teleport yourself to the top most block", "core.top")
Plugin:AddCommand("/gm", " - [Gamemode (0|1)] - Change your gamemode", "core.changegm")
Plugin:AddCommand("/gotoworld", " - Move to a different world!", "core.gotoworld")
Plugin:AddCommand("/coords", " - Show your current server coordinates", "core.coords")
Plugin:AddCommand("/viewdistance", " - [".. cClientHandle.MIN_VIEW_DISTANCE .."-".. cClientHandle.MAX_VIEW_DISTANCE .."] - Change your view distance", "core.viewdistance")
Plugin:AddCommand("/regeneratechunk", " - <X [Z]> - Regenerates a chunk", "core.regeneratechunk")
Plugin:BindCommand( "/help", "core.help", HandleHelpCommand )
Plugin:BindCommand( "/pluginlist", "core.pluginlist", HandlePluginListCommand )
Plugin:BindCommand( "/tp", "core.teleport", HandleTPCommand )
Plugin:BindCommand( "/item", "core.item", HandleItemCommand )
Plugin:BindCommand( "/i", "core.item", HandleItemCommand )
Plugin:BindCommand( "/list", "core.playerlist", HandlePlayerListCommand )
Plugin:BindCommand( "/who", "core.playerlist", HandlePlayerListCommand )
Plugin:BindCommand( "/playerlist", "core.playerlist", HandlePlayerListCommand )
Plugin:BindCommand( "/motd", "core.motd", HandleMOTDCommand )
Plugin:BindCommand( "/reload", "core.reload", HandleReloadCommand )
Plugin:BindCommand( "/stop", "core.stop", HandleStopCommand )
Plugin:BindCommand( "/time", "core.time", HandleTimeCommand )
Plugin:BindCommand( "/spawn", "core.spawn", HandleSpawnCommand )
Plugin:BindCommand( "/kick", "core.kick", HandleKickCommand )
Plugin:BindCommand( "/ban", "core.ban", HandleBanCommand )
Plugin:BindCommand( "/unban", "core.unban", HandleUnbanCommand )
Plugin:BindCommand( "/top", "core.top", HandleTopCommand )
Plugin:BindCommand( "/gm", "core.changegm", HandleChangeGMCommand )
Plugin:BindCommand( "/gotoworld", "core.gotoworld", HandleGotoWorldCommand )
Plugin:BindCommand( "/coords", "core.coords", HandleCoordsCommand )
Plugin:BindCommand( "/viewdistance", "core.viewdistance", HandleViewDistanceCommand )
Plugin:BindCommand( "/regeneratechunk", "core.regeneratechunk", HandleRegenerateChunkCommand )
PluginManager:BindCommand("/help", "core.help", HandleHelpCommand, " [Page] - Show available commands");
PluginManager:BindCommand("/pluginlist", "core.pluginlist", HandlePluginListCommand, " - Show list of plugins");
PluginManager:BindCommand("/tp", "core.teleport", HandleTPCommand, " [Player] - Teleport yourself to a player");
PluginManager:BindCommand("/item", "core.item", HandleItemCommand, " [ItemType/Name] <Amount> - Give yourself an item");
PluginManager:BindCommand("/list", "core.playerlist", HandlePlayerListCommand, " - Shows list of connected players");
PluginManager:BindCommand("/who", "core.playerlist", HandlePlayerListCommand, " - Shows list of connected players");
PluginManager:BindCommand("/playerlist", "core.playerlist", HandlePlayerListCommand, " - Shows list of connected players");
PluginManager:BindCommand("/motd", "core.motd", HandleMOTDCommand, " - Show message of the day");
PluginManager:BindCommand("/reload", "core.reload", HandleReloadCommand, " - Reload all plugins");
PluginManager:BindCommand("/stop", "core.stop", HandleStopCommand, " - Stops the server");
PluginManager:BindCommand("/time", "core.time", HandleTimeCommand, " [Day/Night] - Sets the time of day");
PluginManager:BindCommand("/spawn", "core.spawn", HandleSpawnCommand, " - Return to the spawn");
PluginManager:BindCommand("/kick", "core.kick", HandleKickCommand, " [Player] - Kick a player");
PluginManager:BindCommand("/ban", "core.ban", HandleBanCommand, " [Player] - Ban a player");
PluginManager:BindCommand("/unban", "core.unban", HandleUnbanCommand, " [Player] - Unban a player");
PluginManager:BindCommand("/top", "core.top", HandleTopCommand, " - Teleport yourself to the top most block");
PluginManager:BindCommand("/gm", "core.changegm", HandleChangeGMCommand, " [0|1] - Change your gamemode");
PluginManager:BindCommand("/gotoworld", "core.gotoworld", HandleGotoWorldCommand, " [WorldName] - Move to a different world!");
PluginManager:BindCommand("/coords", "core.coords", HandleCoordsCommand, " - Show your current server coordinates");
PluginManager:BindCommand("/regeneratechunk", "core.regeneratechunk", HandleRegenerateChunkCommand, " <[X] [Z]> - Regenerates a chunk, current or specified");
PluginManager:BindCommand("/viewdistance", "core.viewdistance", HandleViewDistanceCommand, " [".. cClientHandle.MIN_VIEW_DISTANCE .."-".. cClientHandle.MAX_VIEW_DISTANCE .."] - Change your view distance")
local IniFile = cIniFile("settings.ini")
if ( IniFile:ReadFile() == true ) then
SHOW_PLUGIN_NAMES = IniFile:GetValueB("HelpPlugin", "ShowPluginNames", true )

View File

@ -1,18 +1,18 @@
function HandleRegenerateChunkCommand( Split, Player )
if( (#Split == 2) or (#Split > 3) ) then
Player:SendMessage( cChatColor.Green .. "Usage: /regeneratechunk <X [Z]>" )
return true
function HandleRegenerateChunkCommand(Split, Player)
if ((#Split == 2) or (#Split > 3)) then
Player:SendMessage( cChatColor.Green .. "Usage: '/regeneratechunk' or '/regeneratechunk [X] [Z]'");
return true;
end
local X = Player:GetChunkX()
local Z = Player:GetChunkZ()
local X = Player:GetChunkX();
local Z = Player:GetChunkZ();
if( #Split == 3 ) then
X = Split[2]
Z = Split[3]
if (#Split == 3) then
X = Split[2];
Z = Split[3];
end
Player:SendMessage(cChatColor.Green .. "Regenerating chunk ["..X..", "..Z.."]")
Player:GetWorld():RegenerateChunk(X, Z)
return true
Player:SendMessage(cChatColor.Green .. "Regenerating chunk ["..X..", "..Z.."]");
Player:GetWorld():RegenerateChunk(X, Z);
return true;
end

View File

@ -1455,14 +1455,6 @@
RelativePath="..\source\Bindings.h"
>
</File>
<File
RelativePath="..\source\LuaCommandBinder.cpp"
>
</File>
<File
RelativePath="..\source\LuaCommandBinder.h"
>
</File>
<File
RelativePath="..\source\LuaFunctions.h"
>

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 01/28/13 17:46:12.
** Generated automatically by tolua++-1.0.92 on 02/01/13 20:11:44.
*/
#ifndef __cplusplus
@ -154,7 +154,6 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cPlugin::CommandStruct");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cGroup");
@ -167,7 +166,7 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"Vector3i");
tolua_usertype(tolua_S,"Lua__cWebPlugin");
tolua_usertype(tolua_S,"Lua__cPawn");
tolua_usertype(tolua_S,"cStairs");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
tolua_usertype(tolua_S,"Lua__cTCPLink");
@ -179,13 +178,13 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cGroupManager");
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"Lua__cPickup");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"Lua__cEntity");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cLadder");
tolua_usertype(tolua_S,"MTRand");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"HTTPRequest");
@ -193,10 +192,10 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"cTorch");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"Lua__cChestEntity");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"Lua__cEntity");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cStairs");
tolua_usertype(tolua_S,"Vector3d");
}
@ -8782,9 +8781,9 @@ static int tolua_AllToLua_Lua__cPlayer_cPlayer__MoveTo00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetPluginManager of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_GetPluginManager00
static int tolua_AllToLua_cPluginManager_GetPluginManager00(lua_State* tolua_S)
/* method: Get of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_Get00
static int tolua_AllToLua_cPluginManager_Get00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@ -8797,14 +8796,14 @@ static int tolua_AllToLua_cPluginManager_GetPluginManager00(lua_State* tolua_S)
#endif
{
{
cPluginManager* tolua_ret = (cPluginManager*) cPluginManager::GetPluginManager();
cPluginManager* tolua_ret = (cPluginManager*) cPluginManager::Get();
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPluginManager");
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetPluginManager'.",&tolua_err);
tolua_error(tolua_S,"#ferror in function 'Get'.",&tolua_err);
return 0;
#endif
}
@ -8990,7 +8989,7 @@ static int tolua_AllToLua_cPluginManager_DisablePlugin00(lua_State* tolua_S)
#endif
{
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
AString a_PluginName = ((AString) tolua_tocppstring(tolua_S,2,0));
const AString a_PluginName = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DisablePlugin'", NULL);
#endif
@ -9025,7 +9024,7 @@ static int tolua_AllToLua_cPluginManager_LoadPlugin00(lua_State* tolua_S)
#endif
{
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
AString a_PluginName = ((AString) tolua_tocppstring(tolua_S,2,0));
const AString a_PluginName = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LoadPlugin'", NULL);
#endif
@ -9044,93 +9043,73 @@ static int tolua_AllToLua_cPluginManager_LoadPlugin00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* get function: Command of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin__CommandStruct_Command
static int tolua_get_cPlugin__CommandStruct_Command(lua_State* tolua_S)
/* method: IsCommandBound of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_IsCommandBound00
static int tolua_AllToLua_cPluginManager_IsCommandBound00(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Command'",NULL);
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
tolua_pushcppstring(tolua_S,(const char*)self->Command);
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: Command of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_set_cPlugin__CommandStruct_Command
static int tolua_set_cPlugin__CommandStruct_Command(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
{
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
const AString a_Command = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Command'",NULL);
if (!tolua_iscppstring(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsCommandBound'", NULL);
#endif
self->Command = ((AString) tolua_tocppstring(tolua_S,2,0))
;
{
bool tolua_ret = (bool) self->IsCommandBound(a_Command);
tolua_pushboolean(tolua_S,(bool)tolua_ret);
tolua_pushcppstring(tolua_S,(const char*)a_Command);
}
}
return 2;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'IsCommandBound'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* get function: Description of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin__CommandStruct_Description
static int tolua_get_cPlugin__CommandStruct_Description(lua_State* tolua_S)
/* method: GetCommandPermission of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_GetCommandPermission00
static int tolua_AllToLua_cPluginManager_GetCommandPermission00(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Description'",NULL);
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
tolua_pushcppstring(tolua_S,(const char*)self->Description);
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: Description of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_set_cPlugin__CommandStruct_Description
static int tolua_set_cPlugin__CommandStruct_Description(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
{
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
const AString a_Command = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Description'",NULL);
if (!tolua_iscppstring(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetCommandPermission'", NULL);
#endif
self->Description = ((AString) tolua_tocppstring(tolua_S,2,0))
;
{
AString tolua_ret = (AString) self->GetCommandPermission(a_Command);
tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
tolua_pushcppstring(tolua_S,(const char*)a_Command);
}
}
return 2;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetCommandPermission'.",&tolua_err);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: Permission of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin__CommandStruct_Permission
static int tolua_get_cPlugin__CommandStruct_Permission(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Permission'",NULL);
#endif
tolua_pushcppstring(tolua_S,(const char*)self->Permission);
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: Permission of class CommandStruct */
#ifndef TOLUA_DISABLE_tolua_set_cPlugin__CommandStruct_Permission
static int tolua_set_cPlugin__CommandStruct_Permission(lua_State* tolua_S)
{
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Permission'",NULL);
if (!tolua_iscppstring(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
#endif
self->Permission = ((AString) tolua_tocppstring(tolua_S,2,0))
;
return 0;
}
#endif //#ifndef TOLUA_DISABLE
@ -9329,46 +9308,6 @@ static int tolua_AllToLua_cPlugin_GetLocalDirectory00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: AddCommand of class cPlugin */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlugin_AddCommand00
static int tolua_AllToLua_cPlugin_AddCommand00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cPlugin",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_iscppstring(tolua_S,3,0,&tolua_err) ||
!tolua_iscppstring(tolua_S,4,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,5,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cPlugin* self = (cPlugin*) tolua_tousertype(tolua_S,1,0);
const AString a_Command = ((const AString) tolua_tocppstring(tolua_S,2,0));
const AString a_Description = ((const AString) tolua_tocppstring(tolua_S,3,0));
const AString a_Permission = ((const AString) tolua_tocppstring(tolua_S,4,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddCommand'", NULL);
#endif
{
self->AddCommand(a_Command,a_Description,a_Permission);
tolua_pushcppstring(tolua_S,(const char*)a_Command);
tolua_pushcppstring(tolua_S,(const char*)a_Description);
tolua_pushcppstring(tolua_S,(const char*)a_Permission);
}
}
return 3;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'AddCommand'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* get function: __cWebPlugin__ of class cPlugin_NewLua */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin_NewLua___cWebPlugin__
static int tolua_get_cPlugin_NewLua___cWebPlugin__(lua_State* tolua_S)
@ -21285,7 +21224,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"HOOK_UPDATED_SIGN",cPluginManager::HOOK_UPDATED_SIGN);
tolua_constant(tolua_S,"HOOK_UPDATING_SIGN",cPluginManager::HOOK_UPDATING_SIGN);
tolua_constant(tolua_S,"HOOK_WEATHER_CHANGED",cPluginManager::HOOK_WEATHER_CHANGED);
tolua_function(tolua_S,"GetPluginManager",tolua_AllToLua_cPluginManager_GetPluginManager00);
tolua_function(tolua_S,"Get",tolua_AllToLua_cPluginManager_Get00);
tolua_function(tolua_S,"GetPlugin",tolua_AllToLua_cPluginManager_GetPlugin00);
tolua_function(tolua_S,"FindPlugins",tolua_AllToLua_cPluginManager_FindPlugins00);
tolua_function(tolua_S,"ReloadPlugins",tolua_AllToLua_cPluginManager_ReloadPlugins00);
@ -21293,22 +21232,17 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetNumPlugins",tolua_AllToLua_cPluginManager_GetNumPlugins00);
tolua_function(tolua_S,"DisablePlugin",tolua_AllToLua_cPluginManager_DisablePlugin00);
tolua_function(tolua_S,"LoadPlugin",tolua_AllToLua_cPluginManager_LoadPlugin00);
tolua_function(tolua_S,"IsCommandBound",tolua_AllToLua_cPluginManager_IsCommandBound00);
tolua_function(tolua_S,"GetCommandPermission",tolua_AllToLua_cPluginManager_GetCommandPermission00);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPlugin","cPlugin","",NULL);
tolua_beginmodule(tolua_S,"cPlugin");
tolua_cclass(tolua_S,"CommandStruct","cPlugin::CommandStruct","",NULL);
tolua_beginmodule(tolua_S,"CommandStruct");
tolua_variable(tolua_S,"Command",tolua_get_cPlugin__CommandStruct_Command,tolua_set_cPlugin__CommandStruct_Command);
tolua_variable(tolua_S,"Description",tolua_get_cPlugin__CommandStruct_Description,tolua_set_cPlugin__CommandStruct_Description);
tolua_variable(tolua_S,"Permission",tolua_get_cPlugin__CommandStruct_Permission,tolua_set_cPlugin__CommandStruct_Permission);
tolua_endmodule(tolua_S);
tolua_function(tolua_S,"GetName",tolua_AllToLua_cPlugin_GetName00);
tolua_function(tolua_S,"SetName",tolua_AllToLua_cPlugin_SetName00);
tolua_function(tolua_S,"GetVersion",tolua_AllToLua_cPlugin_GetVersion00);
tolua_function(tolua_S,"SetVersion",tolua_AllToLua_cPlugin_SetVersion00);
tolua_function(tolua_S,"GetDirectory",tolua_AllToLua_cPlugin_GetDirectory00);
tolua_function(tolua_S,"GetLocalDirectory",tolua_AllToLua_cPlugin_GetLocalDirectory00);
tolua_function(tolua_S,"AddCommand",tolua_AllToLua_cPlugin_AddCommand00);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPlugin_NewLua","cPlugin_NewLua","cPlugin",NULL);
tolua_beginmodule(tolua_S,"cPlugin_NewLua");

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 01/28/13 17:46:13.
** Generated automatically by tolua++-1.0.92 on 02/01/13 20:11:44.
*/
/* Exported function */

View File

@ -1,154 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "LuaCommandBinder.h"
#include "Player.h"
#include "Plugin.h"
#include "tolua++.h"
bool report_errors(lua_State * lua, int status)
{
if (status == 0)
{
// No error to report
return false;
}
LOGERROR("LUA: %s", lua_tostring(lua, -1));
lua_pop(lua, 1);
return true;
}
cLuaCommandBinder::cLuaCommandBinder()
{
}
cLuaCommandBinder::~cLuaCommandBinder()
{
}
void cLuaCommandBinder::ClearBindings()
{
m_BoundCommands.clear();
}
void cLuaCommandBinder::RemoveBindingsForPlugin( cPlugin* a_Plugin )
{
for( CommandMap::iterator itr = m_BoundCommands.begin(); itr != m_BoundCommands.end(); )
{
if( itr->second.Plugin == a_Plugin )
{
LOGINFO("Unbinding %s ", itr->first.c_str( ) );
luaL_unref( itr->second.LuaState, LUA_REGISTRYINDEX, itr->second.Reference ); // unreference
CommandMap::iterator eraseme = itr;
++itr;
m_BoundCommands.erase( eraseme );
continue;
}
++itr;
}
}
bool cLuaCommandBinder::BindCommand( const std::string & a_Command, const std::string & a_Permission, cPlugin* a_Plugin, lua_State * a_LuaState, int a_FunctionReference )
{
if( !a_Plugin->CanBindCommands() )
{
LOGERROR("ERROR: Trying to bind command \"%s\" to a plugin that is not initialized.", a_Command.c_str() );
return false;
}
if( m_BoundCommands.find( a_Command ) != m_BoundCommands.end() )
{
LOGERROR("ERROR: Trying to bind command \"%s\" that has already been bound.", a_Command.c_str() );
return false;
}
LOGINFO("Binding %s (%s)", a_Command.c_str(), a_Permission.c_str() );
m_BoundCommands[ a_Command ] = BoundFunction( a_Plugin, a_LuaState, a_FunctionReference, a_Permission );
return true;
}
bool cLuaCommandBinder::HandleCommand( const std::string & a_Command, cPlayer* a_Player )
{
AStringVector Split = StringSplit(a_Command, " ");
if (Split.size() == 0)
{
return false;
}
CommandMap::iterator FoundCommand = m_BoundCommands.find( Split[0] );
if( FoundCommand != m_BoundCommands.end() )
{
const BoundFunction & func = FoundCommand->second;
if( func.Permission.size() > 0 )
{
if( !a_Player->HasPermission( func.Permission.c_str() ) )
{
return false;
}
}
LOGD("1. Stack size: %i", lua_gettop(func.LuaState) );
lua_rawgeti( func.LuaState, LUA_REGISTRYINDEX, func.Reference); // same as lua_getref()
// Push the split
LOGD("2. Stack size: %i", lua_gettop(func.LuaState) );
lua_createtable(func.LuaState, Split.size(), 0);
int newTable = lua_gettop(func.LuaState);
int index = 1;
std::vector<std::string>::const_iterator iter = Split.begin();
while(iter != Split.end()) {
tolua_pushstring( func.LuaState, (*iter).c_str() );
lua_rawseti(func.LuaState, newTable, index);
++iter;
++index;
}
LOGD("3. Stack size: %i", lua_gettop(func.LuaState) );
// Push player
tolua_pushusertype( func.LuaState, a_Player, "cPlayer" );
LOGD("Calling bound function! :D");
int s = lua_pcall(func.LuaState, 2, 1, 0);
if( report_errors( func.LuaState, s ) )
{
LOGERROR("error. Stack size: %i", lua_gettop(func.LuaState) );
return false;
}
bool RetVal = (tolua_toboolean(func.LuaState, -1, 0) > 0);
lua_pop(func.LuaState, 1); // Pop return value
LOGD("ok. Stack size: %i", lua_gettop(func.LuaState) );
return RetVal;
}
return false;
}

View File

@ -1,42 +0,0 @@
#pragma once
struct lua_State;
class cPlugin;
class cPlayer;
class cLuaCommandBinder
{
public:
cLuaCommandBinder();
~cLuaCommandBinder();
bool HandleCommand( const std::string & a_Command, cPlayer* a_Player );
bool BindCommand( const std::string & a_Command, const std::string & a_Permission, cPlugin* a_Plugin, lua_State * a_LuaState, int a_FunctionReference );
void ClearBindings();
void RemoveBindingsForPlugin( cPlugin* a_Plugin );
private:
struct BoundFunction
{
BoundFunction() : Plugin( 0 ), LuaState( 0 ), Reference( 0 ) {}
BoundFunction( cPlugin* a_Plugin, lua_State * a_LuaState, int a_Reference, const std::string & a_Permission ) : Plugin( a_Plugin ), LuaState( a_LuaState ), Reference( a_Reference ), Permission( a_Permission ) {}
cPlugin* Plugin;
lua_State* LuaState;
int Reference;
std::string Permission;
};
typedef std::map< std::string, BoundFunction > CommandMap;
CommandMap m_BoundCommands;
};

View File

@ -9,7 +9,6 @@
#include "Plugin.h"
#include "Plugin_NewLua.h"
#include "PluginManager.h"
#include "LuaCommandBinder.h"
#include "Player.h"
#include "WebAdmin.h"
#include "StringMap.h"
@ -488,24 +487,74 @@ DEFINE_LUA_FOREACHINCHUNK(cWorld, cFurnaceEntity, ForEachFurnaceInChunk, tolua_c
static int tolua_cPlugin_GetCommands(lua_State * tolua_S)
static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{
cPlugin* self = (cPlugin*) tolua_tousertype(tolua_S,1,0);
const std::vector< cPlugin::CommandStruct > & AllCommands = self->GetCommands();
lua_createtable(tolua_S, AllCommands.size(), 0);
int newTable = lua_gettop(tolua_S);
int index = 1;
std::vector< cPlugin::CommandStruct >::const_iterator iter = AllCommands.begin();
while(iter != AllCommands.end())
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if( NumArgs != 1)
{
const cPlugin::CommandStruct & CS = *iter;
tolua_pushusertype( tolua_S, (void*)&CS, "const cPlugin::CommandStruct" );
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
LOGWARN("Error in function call 'ForEachCommand': Requires 1 argument, got %i", NumArgs);
return 0;
}
cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, 0);
if (self == NULL)
{
LOGWARN("Error in function call 'ForEachCommand': Not called on an object instance");
return 0;
}
if (!lua_isfunction(tolua_S, 2))
{
LOGWARN("Error in function call 'ForEachCommand': Expected a function for parameter #1");
return 0;
}
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
LOGWARN("Error in function call 'ForEachCommand': Could not get function reference of parameter #1");
return 0;
}
class cLuaCallback : public cPluginManager::cCommandEnumCallback
{
public:
cLuaCallback(lua_State * a_LuaState, int a_FuncRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
{}
private:
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushcppstring(LuaState, a_Command);
tolua_pushcppstring(LuaState, a_Permission);
tolua_pushcppstring(LuaState, a_HelpString);
int s = lua_pcall(LuaState, 3, 1, 0);
if (report_errors(LuaState, s))
{
return true; /* Abort enumeration */
}
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean( LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
} Callback(tolua_S, FuncRef);
bool bRetVal = self->ForEachCommand(Callback);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@ -547,6 +596,64 @@ static int tolua_cPluginManager_GetAllPlugins(lua_State* tolua_S)
static int tolua_cPluginManager_BindCommand(lua_State * L)
{
// Function signature: cPluginManager:BindCommand(Command, Permission, Function, HelpString)
// Get the plugin identification out of LuaState:
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
if (!lua_islightuserdata(L, -1))
{
LOGERROR("cPluginManager:BindCommand() cannot get plugin instance, what have you done to my Lua state? Command-binding aborted.");
}
cPlugin_NewLua * Plugin = (cPlugin_NewLua *)lua_topointer(L, -1);
lua_pop(L, 1);
// Read the arguments to this API call:
tolua_Error tolua_err;
if (
!tolua_isusertype (L, 1, "cPluginManager", 0, &tolua_err) ||
!tolua_iscppstring(L, 2, 0, &tolua_err) ||
!tolua_iscppstring(L, 3, 0, &tolua_err) ||
!tolua_iscppstring(L, 5, 0, &tolua_err) ||
!tolua_isnoobj (L, 6, &tolua_err)
)
{
tolua_error(L, "#ferror in function 'BindCommand'.", &tolua_err);
return 0;
}
if (!lua_isfunction(L, 4))
{
luaL_error(L, "\"BindCommand\" function expects a function as its 3rd parameter. Command-binding aborted.");
return 0;
}
cPluginManager * self = (cPluginManager *)tolua_tousertype(L, 1, 0);
AString Command (tolua_tocppstring(L, 2, ""));
AString Permission(tolua_tocppstring(L, 3, ""));
AString HelpString(tolua_tocppstring(L, 5, ""));
// Store the function reference:
lua_pop(L, 1); // Pop the help string off the stack
int FnRef = luaL_ref(L, LUA_REGISTRYINDEX); // Store function reference
if (FnRef == LUA_REFNIL)
{
LOGERROR("\"BindCommand\": Cannot create a function reference. Command \"%s\" not bound.", Command);
return 0;
}
if (!self->BindCommand(Command, Plugin, Permission, HelpString))
{
// Refused. Possibly already bound. Error message has been given, bail out silently.
return 0;
}
Plugin->BindCommand(Command, FnRef);
return 0;
}
static int tolua_cPlayer_GetGroups(lua_State* tolua_S)
{
@ -598,6 +705,8 @@ static int tolua_cPlayer_GetResolvedPermissions(lua_State* tolua_S)
/*
// TODO: rewrite this for the new API
static int tolua_cPlugin_BindCommand(lua_State* tolua_S)
{
cPlugin* self = (cPlugin*) tolua_tousertype(tolua_S,1,0);
@ -651,6 +760,7 @@ static int tolua_cPlugin_BindCommand(lua_State* tolua_S)
return 0;
}
*/
@ -927,13 +1037,13 @@ void ManualBindings::Bind( lua_State* tolua_S )
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlugin");
tolua_function(tolua_S, "GetCommands", tolua_cPlugin_GetCommands);
tolua_function(tolua_S, "BindCommand", tolua_cPlugin_BindCommand);
tolua_function(tolua_S, "Call", tolua_cPlugin_Call);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPluginManager");
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlayer");

View File

@ -10,10 +10,9 @@
cPlugin::cPlugin( const AString & a_PluginDirectory )
: m_Version( 0 )
, m_Language( E_CPP )
, m_bCanBindCommands( false )
, m_Directory( a_PluginDirectory )
: m_Version(0)
, m_Language(E_CPP)
, m_Directory(a_PluginDirectory)
{
}
@ -126,6 +125,17 @@ bool cPlugin::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
{
UNUSED(a_Client);
UNUSED(a_Username);
return false;
}
bool cPlugin::OnKilling(cPawn & a_Victim, cEntity * a_Killer)
{
UNUSED(a_Victim);
@ -464,10 +474,10 @@ bool cPlugin::OnWeatherChanged(cWorld * a_World)
bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
bool cPlugin::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player)
{
UNUSED(a_Client);
UNUSED(a_Username);
UNUSED(a_Split);
UNUSED(a_Player);
return false;
}
@ -475,19 +485,6 @@ bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
void cPlugin::AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission)
{
CommandStruct Command;
Command.Command = a_Command;
Command.Description = a_Description;
Command.Permission = a_Permission;
m_Commands.push_back( Command );
}
AString cPlugin::GetLocalDirectory(void) const
{
return std::string("Plugins/") + m_Directory;

View File

@ -81,6 +81,12 @@ public:
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
virtual bool OnWeatherChanged (cWorld * a_World);
/// Handles the command split into a_Split, issued by player a_Player. Command permissions have already been checked.
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player);
/// All bound commands are to be removed, do any language-dependent cleanup here
virtual void ClearCommands(void) {} ;
/** Called from cPluginManager::AddHook() to check if the hook can be added.
Plugin API providers may check if the plugin is written correctly (has the hook handler function)
Returns true if the hook can be added (handler exists)
@ -89,13 +95,6 @@ public:
virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) { return false; }
// tolua_begin
struct CommandStruct
{
AString Command;
AString Description;
AString Permission;
};
const AString & GetName(void) const { return m_Name; }
void SetName(const AString & a_Name) { m_Name = a_Name; }
@ -104,14 +103,8 @@ public:
const AString & GetDirectory(void) const {return m_Directory; }
AString GetLocalDirectory(void) const;
void AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission);
// tolua_end
typedef bool (FuncCommandHandler)( AString & a_Command, std::vector< std::string > & a_Split );
void BindCommand( FuncCommandHandler* a_Function, AString & a_Command ); // >> EXPORTED IN MANUALBINDINGS <<
const std::vector< CommandStruct > & GetCommands() const { return m_Commands; } // >> EXPORTED IN MANUALBINDINGS <<
/* This should not be exposed to scripting languages */
enum PluginLanguage
@ -123,13 +116,8 @@ public:
PluginLanguage GetLanguage() { return m_Language; }
void SetLanguage( PluginLanguage a_Language ) { m_Language = a_Language; }
bool CanBindCommands() { return m_bCanBindCommands; }
private:
friend class cPluginManager;
bool m_bCanBindCommands; // Only changed by cPluginManager
PluginLanguage m_Language;
std::vector< CommandStruct > m_Commands;
AString m_Name;
int m_Version;

View File

@ -1,3 +1,4 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "PluginManager.h"
@ -6,32 +7,17 @@
#include "WebAdmin.h"
#include "Item.h"
#include "Root.h"
#include "LuaCommandBinder.h"
#ifdef USE_SQUIRREL
#include "Plugin_Squirrel.h"
#include "SquirrelCommandBinder.h"
#endif
#include "../iniFile/iniFile.h"
#include "tolua++.h"
#include "Player.h"
#ifdef USE_SQUIRREL
#include "squirrelbindings/SquirrelBindings.h"
#include "squirrelbindings/SquirrelFunctions.h"
#pragma warning(disable:4100;disable:4127;disable:4510;disable:4610;disable:4244;disable:4512) // Getting A LOT of these warnings from SqPlus
#pragma warning(default:4100;default:4127;default:4510;default:4610;default:4244;default:4512)
#endif
cPluginManager* cPluginManager::GetPluginManager()
cPluginManager * cPluginManager::Get(void)
{
LOGWARN("WARNING: Using deprecated function cPluginManager::GetPluginManager() use cRoot::Get()->GetPluginManager() instead!");
return cRoot::Get()->GetPluginManager();
}
@ -39,12 +25,8 @@ cPluginManager* cPluginManager::GetPluginManager()
cPluginManager::cPluginManager()
: m_LuaCommandBinder( new cLuaCommandBinder() )
#ifdef USE_SQUIRREL
, m_SquirrelCommandBinder( new cSquirrelCommandBinder() )
#endif
, m_bReloadPlugins(false)
cPluginManager::cPluginManager(void) :
m_bReloadPlugins(false)
{
}
@ -55,18 +37,13 @@ cPluginManager::cPluginManager()
cPluginManager::~cPluginManager()
{
UnloadPluginsNow();
delete m_LuaCommandBinder;
#ifdef USE_SQUIRREL
delete m_SquirrelCommandBinder;
#endif
}
void cPluginManager::ReloadPlugins()
void cPluginManager::ReloadPlugins(void)
{
m_bReloadPlugins = true;
}
@ -75,12 +52,12 @@ void cPluginManager::ReloadPlugins()
void cPluginManager::FindPlugins()
void cPluginManager::FindPlugins(void)
{
AString PluginsPath = FILE_IO_PREFIX + AString( "Plugins/" );
// First get a clean list of only the currently running plugins, we don't want to mess those up
for( PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); )
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
{
if( itr->second == NULL )
{
@ -103,7 +80,7 @@ void cPluginManager::FindPlugins()
}
// Add plugin name/directory to the list
if( m_Plugins.find( *itr ) == m_Plugins.end() )
if (m_Plugins.find( *itr ) == m_Plugins.end())
{
m_Plugins[ *itr ] = NULL;
}
@ -114,71 +91,51 @@ void cPluginManager::FindPlugins()
void cPluginManager::ReloadPluginsNow()
void cPluginManager::ReloadPluginsNow(void)
{
LOG("Loading plugins");
m_bReloadPlugins = false;
UnloadPluginsNow();
#ifdef USE_SQUIRREL
CloseSquirrelVM();
OpenSquirrelVM();
#endif // USE_SQUIRREL
FindPlugins();
cIniFile IniFile("settings.ini");
if (!IniFile.ReadFile() )
if (!IniFile.ReadFile())
{
LOGWARNING("cPluginManager: Can't find settings.ini, so can't load any plugins.");
}
unsigned int KeyNum = IniFile.FindKey("Plugins");
unsigned int NumPlugins = IniFile.GetNumValues( KeyNum );
if( NumPlugins > 0 )
unsigned int NumPlugins = IniFile.GetNumValues(KeyNum);
if (NumPlugins > 0)
{
for(unsigned int i = 0; i < NumPlugins; i++)
{
AString ValueName = IniFile.GetValueName(KeyNum, i );
if( (ValueName.compare("NewPlugin") == 0) || (ValueName.compare("Plugin") == 0) ) // New plugin style
if (
(ValueName.compare("NewPlugin") == 0) ||
(ValueName.compare("Plugin") == 0)
)
{
AString PluginFile = IniFile.GetValue(KeyNum, i );
if( !PluginFile.empty() )
AString PluginFile = IniFile.GetValue(KeyNum, i);
if (!PluginFile.empty())
{
if( m_Plugins.find( PluginFile ) != m_Plugins.end() )
if (m_Plugins.find(PluginFile) != m_Plugins.end())
{
LoadPlugin( PluginFile );
}
}
}
#ifdef USE_SQUIRREL
else if( ValueName.compare("Squirrel") == 0 ) // Squirrel plugin
{
AString PluginFile = IniFile.GetValue(KeyNum, i );
if( !PluginFile.empty() )
{
LOGINFO("Loading Squirrel plugin: %s", PluginFile.c_str() );
cPlugin_Squirrel *Plugin = new cPlugin_Squirrel(PluginFile.c_str());
if( !AddPlugin( Plugin ) )
{
delete Plugin;
}
}
}
#endif // USE_SQUIRREL
}
}
if( GetNumPlugins() == 0 )
if (GetNumPlugins() == 0)
{
LOG("No plugins loaded");
}
else
{
LOG("Loaded %i plugin(s)", GetNumPlugins() );
LOG("Loaded %i plugin(s)", GetNumPlugins());
}
}
@ -188,23 +145,23 @@ void cPluginManager::ReloadPluginsNow()
void cPluginManager::Tick(float a_Dt)
{
while( m_DisablePluginList.size() > 0 )
while (!m_DisablePluginList.empty())
{
RemovePlugin( m_DisablePluginList.front(), true );
RemovePlugin(m_DisablePluginList.front());
m_DisablePluginList.pop_front();
}
if( m_bReloadPlugins )
if (m_bReloadPlugins)
{
ReloadPluginsNow();
}
HookMap::iterator Plugins = m_Hooks.find(HOOK_TICK);
if( Plugins != m_Hooks.end() )
if (Plugins != m_Hooks.end())
{
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
(*itr)->Tick( a_Dt );
(*itr)->Tick(a_Dt);
}
}
}
@ -240,22 +197,17 @@ bool cPluginManager::CallHookBlockToPickups(
bool cPluginManager::CallHookChat(cPlayer * a_Player, const AString & a_Message)
{
#ifdef USE_SQUIRREL
if (m_SquirrelCommandBinder->HandleCommand(a_Message, a_Player))
{
return true;
}
#endif // USE_SQUIRREL
if (m_LuaCommandBinder->HandleCommand(a_Message, a_Player))
if (ExecuteCommand(a_Player, a_Message))
{
return true;
}
// Check if it was a standard command (starts with a slash)
if (a_Message[0] == '/')
if (!a_Message.empty() && (a_Message[0] == '/'))
{
a_Player->SendMessage("Unknown Command");
AStringVector Split(StringSplit(a_Message, " "));
ASSERT(!Split.empty()); // This should not happen - we know there's at least one char in the message so the split needs to be at least one item long
a_Player->SendMessage(Printf("Unknown Command: \"%s\"", Split[0].c_str()));
LOGINFO("Player \"%s\" issued an unknown command: \"%s\"", a_Player->GetName().c_str(), a_Message.c_str());
return true; // Cancel sending
}
@ -911,7 +863,43 @@ bool cPluginManager::CallHookWeatherChanged(cWorld * a_World)
cPlugin* cPluginManager::GetPlugin( const AString & a_Plugin ) const
bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
{
ASSERT(a_Player != NULL);
AStringVector Split(StringSplit(a_Command, " "));
if (Split.empty())
{
return false;
}
CommandMap::iterator cmd = m_Commands.find(Split[0]);
if (cmd == m_Commands.end())
{
// Command not found
return false;
}
if (
a_ShouldCheckPermissions &&
!cmd->second.m_Permission.empty() &&
!a_Player->HasPermission(cmd->second.m_Permission)
)
{
LOGINFO("Player \"%s\" tried to execute forbidden command \"%s\".", a_Player->GetName().c_str(), Split[0].c_str());
return false;
}
ASSERT(cmd->second.m_Plugin != NULL);
return cmd->second.m_Plugin->HandleCommand(Split, a_Player);
}
cPlugin * cPluginManager::GetPlugin( const AString & a_Plugin ) const
{
for( PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr )
{
@ -941,9 +929,9 @@ void cPluginManager::UnloadPluginsNow()
{
m_Hooks.clear();
while( m_Plugins.size() > 0 )
while (!m_Plugins.empty())
{
RemovePlugin( m_Plugins.begin()->second, true );
RemovePlugin(m_Plugins.begin()->second);
}
//SquirrelVM::Shutdown(); // This breaks shit
@ -953,17 +941,19 @@ void cPluginManager::UnloadPluginsNow()
bool cPluginManager::DisablePlugin( AString & a_PluginName )
bool cPluginManager::DisablePlugin(const AString & a_PluginName)
{
PluginMap::iterator itr = m_Plugins.find( a_PluginName );
if (itr != m_Plugins.end())
PluginMap::iterator itr = m_Plugins.find(a_PluginName);
if (itr == m_Plugins.end())
{
if (itr->first.compare( a_PluginName ) == 0)
{
m_DisablePluginList.push_back( itr->second );
itr->second = NULL; // Get rid of this thing right away
return true;
}
return false;
}
if (itr->first.compare(a_PluginName) == 0) // _X 2013_02_01: wtf? Isn't this supposed to be what find() does?
{
m_DisablePluginList.push_back(itr->second);
itr->second = NULL; // Get rid of this thing right away
return true;
}
return false;
}
@ -972,15 +962,9 @@ bool cPluginManager::DisablePlugin( AString & a_PluginName )
bool cPluginManager::LoadPlugin( AString & a_PluginName )
bool cPluginManager::LoadPlugin(const AString & a_PluginName)
{
cPlugin_NewLua* Plugin = new cPlugin_NewLua( a_PluginName.c_str() );
if (!AddPlugin(Plugin))
{
delete Plugin;
return false;
}
return true;
return AddPlugin(new cPlugin_NewLua(a_PluginName.c_str()));
}
@ -999,47 +983,137 @@ void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
void cPluginManager::RemovePlugin( cPlugin * a_Plugin, bool a_bDelete /* = false */ )
void cPluginManager::RemovePlugin(cPlugin * a_Plugin)
{
if( a_bDelete )
for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
{
m_LuaCommandBinder->RemoveBindingsForPlugin( a_Plugin );
#ifdef USE_SQUIRREL
m_SquirrelCommandBinder->RemoveBindingsForPlugin( a_Plugin );
#endif
for( PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr )
if (itr->second == a_Plugin)
{
if( itr->second == a_Plugin )
{
m_Plugins.erase( itr );
break;
}
}
if( a_Plugin != NULL )
{
RemoveHooks( a_Plugin );
a_Plugin->OnDisable();
delete a_Plugin;
m_Plugins.erase(itr);
break;
}
}
RemovePluginCommands(a_Plugin);
RemoveHooks(a_Plugin);
if (a_Plugin != NULL)
{
a_Plugin->OnDisable();
}
delete a_Plugin;
}
bool cPluginManager::AddPlugin( cPlugin* a_Plugin )
void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
{
a_Plugin->m_bCanBindCommands = true;
if( a_Plugin->Initialize() )
if (a_Plugin != NULL)
{
m_Plugins[ a_Plugin->GetDirectory() ] = a_Plugin;
a_Plugin->ClearCommands();
}
for (CommandMap::iterator itr = m_Commands.begin(); itr != m_Commands.end();)
{
if (itr->second.m_Plugin == a_Plugin)
{
itr = m_Commands.erase(itr);
}
else
{
++itr;
}
} // for itr - m_Commands[]
}
bool cPluginManager::BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString)
{
CommandMap::iterator cmd = m_Commands.find(a_Command);
if (cmd != m_Commands.end())
{
LOGWARNING("Command \"%s\" is already bound to plugin \"%s\".", a_Command.c_str(), cmd->second.m_Plugin->GetName().c_str());
return false;
}
m_Commands[a_Command].m_Plugin = a_Plugin;
m_Commands[a_Command].m_Permission = a_Permission;
m_Commands[a_Command].m_HelpString = a_HelpString;
return true;
}
bool cPluginManager::ForEachCommand(cCommandEnumCallback & a_Callback)
{
for (CommandMap::iterator itr = m_Commands.begin(), end = m_Commands.end(); itr != end; ++itr)
{
if (a_Callback.Command(itr->first, itr->second.m_Plugin, itr->second.m_Permission, itr->second.m_HelpString))
{
return false;
}
} // for itr - m_Commands[]
return true;
}
bool cPluginManager::IsCommandBound(const AString & a_Command)
{
return (m_Commands.find(a_Command) != m_Commands.end());
}
AString cPluginManager::GetCommandPermission(const AString & a_Command)
{
CommandMap::iterator cmd = m_Commands.find(a_Command);
return (cmd == m_Commands.end()) ? "" : cmd->second.m_Permission;
}
bool cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, true);
}
bool cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, false);
}
bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
{
m_Plugins[a_Plugin->GetDirectory()] = a_Plugin;
if (a_Plugin->Initialize())
{
// Initialization OK
return true;
}
a_Plugin->m_bCanBindCommands = false;
RemoveHooks( a_Plugin ); // Undo any damage the Initialize() might have done
// Initialization failed
RemovePlugin(a_Plugin); // Also undoes any registrations that Initialize() might have made
return false;
}
@ -1075,17 +1149,3 @@ unsigned int cPluginManager::GetNumPlugins() const
bool cPluginManager::HasPlugin( cPlugin* a_Plugin ) const
{
for( PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr )
{
if( itr->second == a_Plugin )
return true;
}
return false;
}

View File

@ -3,13 +3,6 @@
#include "Item.h"
struct lua_State;
class cLuaCommandBinder;
#ifdef USE_SQUIRREL
class cSquirrelCommandBinder;
#endif // USE_SQUIRREL
class cPlugin;
// fwd: World.h
@ -84,7 +77,16 @@ public: // tolua_export
} ;
// tolua_end
static cPluginManager * GetPluginManager(); // tolua_export
/// Used as a callback for enumerating bound commands
class cCommandEnumCallback
{
public:
/// Called for each command; return true to abort enumeration
virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) = 0;
} ;
/// Returns the instance of the Plugin Manager (there is only ever one)
static cPluginManager * Get(void); // tolua_export
typedef std::map< AString, cPlugin * > PluginMap;
typedef std::list< cPlugin * > PluginList;
@ -93,7 +95,6 @@ public: // tolua_export
void FindPlugins(); // tolua_export
void ReloadPlugins(); // tolua_export
bool AddPlugin( cPlugin* a_Plugin );
void AddHook( cPlugin* a_Plugin, PluginHook a_Hook ); // tolua_export
unsigned int GetNumPlugins() const; // tolua_export
@ -130,46 +131,70 @@ public: // tolua_export
bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
bool CallHookWeatherChanged (cWorld * a_World);
bool DisablePlugin( AString & a_PluginName ); // tolua_export
bool LoadPlugin( AString & a_PluginName ); // tolua_export
void RemoveHooks( cPlugin * a_Plugin );
void RemovePlugin( cPlugin * a_Plugin, bool a_bDelete = false );
cLuaCommandBinder* GetLuaCommandBinder() const { return m_LuaCommandBinder; }
#ifdef USE_SQUIRREL
cSquirrelCommandBinder * GetSquirrelCommandBinder() { return m_SquirrelCommandBinder; }
#endif // USE_SQUIRREL
bool DisablePlugin(const AString & a_PluginName); // tolua_export
bool LoadPlugin (const AString & a_PluginName); // tolua_export
bool HasPlugin( cPlugin* a_Plugin ) const;
/// Removes all hooks the specified plugin has registered
void RemoveHooks(cPlugin * a_Plugin);
/// Removes the plugin from the internal structures and deletes its object.
void RemovePlugin(cPlugin * a_Plugin);
/// Removes all command bindings that the specified plugin has made
void RemovePluginCommands(cPlugin * a_Plugin);
/// Binds a command to the specified plugin. Returns true if successful, false if command already bound.
bool BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString); // Exported in ManualBindings.cpp, without the a_Plugin param
/// Calls a_Callback for each bound command, returns true if all commands were enumerated
bool ForEachCommand(cCommandEnumCallback & a_Callback); // Exported in ManualBindings.cpp
/// Returns true if the command is in the command map
bool IsCommandBound(const AString & a_Command); // tolua_export
/// Returns the permission needed for the specified command; empty string if command not found
AString GetCommandPermission(const AString & a_Command); // tolua_export
/// Executes the command, as if it was requested by a_Player. Checks permissions first. Returns true if executed.
bool ExecuteCommand(cPlayer * a_Player, const AString & a_Command);
/// Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns true if executed (false if not found)
bool ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command);
private:
friend class cRoot;
class cCommandReg
{
public:
cPlugin * m_Plugin;
AString m_Permission;
AString m_HelpString;
} ;
typedef std::map< cPluginManager::PluginHook, cPluginManager::PluginList > HookMap;
typedef std::map<AString, cCommandReg> CommandMap;
PluginList m_DisablePluginList;
PluginMap m_Plugins;
HookMap m_Hooks;
CommandMap m_Commands;
bool m_bReloadPlugins;
cPluginManager();
~cPluginManager();
typedef std::map< cPluginManager::PluginHook, cPluginManager::PluginList > HookMap;
void ReloadPluginsNow(void);
void UnloadPluginsNow(void);
PluginList m_DisablePluginList;
/// Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again.
bool AddPlugin(cPlugin * a_Plugin);
PluginMap m_Plugins;
HookMap m_Hooks;
void ReloadPluginsNow();
void UnloadPluginsNow();
cLuaCommandBinder * m_LuaCommandBinder;
#ifdef USE_SQUIRREL
cSquirrelCommandBinder * m_SquirrelCommandBinder;
#endif // USE_SQUIRREL
bool m_bReloadPlugins;
}; // tolua_export
/// Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns true if the command is handled.
bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
} ; // tolua_export

View File

@ -18,7 +18,18 @@ extern "C"
extern bool report_errors(lua_State * lua, int status);
bool report_errors(lua_State * lua, int status)
{
if (status == 0)
{
// No error to report
return false;
}
LOGERROR("LUA: %s", lua_tostring(lua, -1));
lua_pop(lua, 1);
return true;
}
@ -53,15 +64,21 @@ cPlugin_NewLua::~cPlugin_NewLua()
bool cPlugin_NewLua::Initialize()
bool cPlugin_NewLua::Initialize(void)
{
cCSLock Lock(m_CriticalSection);
if( !m_LuaState )
if (m_LuaState == NULL)
{
m_LuaState = lua_open();
luaL_openlibs( m_LuaState );
luaL_openlibs(m_LuaState);
tolua_AllToLua_open(m_LuaState);
ManualBindings::Bind( m_LuaState );
ManualBindings::Bind(m_LuaState);
// Inject the identification global variables into the state:
lua_pushlightuserdata(m_LuaState, this);
lua_setglobal(m_LuaState, LUA_PLUGIN_INSTANCE_VAR_NAME);
lua_pushstring(m_LuaState, GetName().c_str());
lua_setglobal(m_LuaState, LUA_PLUGIN_NAME_VAR_NAME);
}
std::string PluginPath = FILE_IO_PREFIX + GetLocalDirectory() + "/";
@ -1134,6 +1151,80 @@ bool cPlugin_NewLua::OnWeatherChanged(cWorld * a_World)
bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player)
{
ASSERT(!a_Split.empty());
CommandMap::iterator cmd = m_Commands.find(a_Split[0]);
if (cmd == m_Commands.end())
{
LOGWARNING("Command handler registered in cPluginManager but not in cPlugin, wtf? Command \"%s\".", a_Split[0].c_str());
return false;
}
cCSLock Lock(m_CriticalSection);
// Push the function to be called:
LOGD("1. Stack size: %i", lua_gettop(m_LuaState));
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref()
// Push the split:
LOGD("2. Stack size: %i", lua_gettop(m_LuaState));
lua_createtable(m_LuaState, a_Split.size(), 0);
int newTable = lua_gettop(m_LuaState);
int index = 1;
std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end();
while(iter != end)
{
tolua_pushstring(m_LuaState, (*iter).c_str());
lua_rawseti(m_LuaState, newTable, index);
++iter;
++index;
}
LOGD("3. Stack size: %i", lua_gettop(m_LuaState));
// Push player:
tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
// Call function:
LOGD("Calling bound function! :D");
int s = lua_pcall(m_LuaState, 2, 1, 0);
if (report_errors(m_LuaState, s))
{
LOGERROR("error. Stack size: %i", lua_gettop(m_LuaState));
return false;
}
// Handle return value:
bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
lua_pop(m_LuaState, 1); // Pop return value
LOGD("ok. Stack size: %i", lua_gettop(m_LuaState));
return RetVal;
}
void cPlugin_NewLua::ClearCommands(void)
{
cCSLock Lock(m_CriticalSection);
// Unreference the bound functions so that Lua can GC them
if (m_LuaState != NULL)
{
for (CommandMap::iterator itr = m_Commands.begin(), end = m_Commands.end(); itr != end; ++itr)
{
luaL_unref(m_LuaState, LUA_REGISTRYINDEX, itr->second);
}
}
m_Commands.clear();
}
bool cPlugin_NewLua::CanAddHook(cPluginManager::PluginHook a_Hook)
{
const char * FnName = GetHookFnName(a_Hook);
@ -1305,9 +1396,25 @@ bool cPlugin_NewLua::AddWebTab( const AString & a_Title, lua_State * a_LuaState,
void cPlugin_NewLua::BindCommand(const AString & a_Command, int a_FnRef)
{
ASSERT(m_Commands.find(a_Command) == m_Commands.end());
m_Commands[a_Command] = a_FnRef;
}
// Helper functions
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
{
if (m_LuaState == NULL)
{
// This happens if Initialize() fails with an error
return false;
}
lua_getglobal(m_LuaState, a_FunctionName);
if (!lua_isfunction(m_LuaState, -1))
{

View File

@ -4,6 +4,9 @@
#include "Plugin.h"
#include "WebPlugin.h"
// Names for the global variables through which the plugin is identified in its LuaState
#define LUA_PLUGIN_NAME_VAR_NAME "_MCServerInternal_PluginName"
#define LUA_PLUGIN_INSTANCE_VAR_NAME "_MCServerInternal_PluginInstance"
@ -63,6 +66,10 @@ public:
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnWeatherChanged (cWorld * a_World) override;
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player) override;
virtual void ClearCommands(void) override;
virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) override;
// cWebPlugin override
@ -71,21 +78,28 @@ public:
// cWebPlugin and WebAdmin stuff
virtual AString HandleWebRequest( HTTPRequest * a_Request ) override;
bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS <<
/// Binds the command to call the function specified by a Lua function reference. Simply adds to CommandMap.
void BindCommand(const AString & a_Command, int a_FnRef);
lua_State* GetLuaState() { return m_LuaState; }
cCriticalSection & GetCriticalSection() { return m_CriticalSection; }
protected:
cCriticalSection m_CriticalSection;
lua_State * m_LuaState;
/// Maps command name into Lua function reference
typedef std::map<AString, int> CommandMap;
CommandMap m_Commands;
bool PushFunction(const char * a_FunctionName, bool a_bLogError = true);
bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
/// Returns the name of Lua function that should handle the specified hook
const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
cCriticalSection m_CriticalSection;
lua_State * m_LuaState;
} ; // tolua_export