1
0

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
This commit is contained in:
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 PluginManager = cRoot:Get():GetPluginManager()
local LinesPerPage = 9 local LinesPerPage = 9;
local CurrentPage = 1 local CurrentPage = 1;
local CurrentLine = 0 local CurrentLine = 0;
local PageRequested = 1;
local Output = {};
if (#Split == 2) then if (#Split == 2) then
CurrentPage = tonumber(Split[2]) PageRequested = tonumber(Split[2]);
end 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() CurrentLine = CurrentLine + 1;
for k, Plugin in pairs(PluginList) do CurrentPage = math.floor(CurrentLine / LinesPerPage) + 1;
if( Plugin ) then if (CurrentPage ~= PageRequested) then
local Commands = Plugin:GetCommands() return false;
for i, v in ipairs( Commands ) do end;
if( Player:HasPermission( v.Permission ) ) then table.insert(Output, cChatColor.Blue .. Command .. HelpString);
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 end
Player:SendMessage( cChatColor.Purple .. "- All commands - " .. cChatColor.Gold .. "[Page " .. (CurrentPage) .."/"..#Pages.."]" ) PluginManager:ForEachCommand(Process);
if( Pages[CurrentPage] ~= nil ) then -- CurrentPage now contains the total number of pages, and Output has the individual help lines to be sent
for i, v in ipairs(Pages[CurrentPage]) do
Player:SendMessage( v ) Player:SendMessage(cChatColor.Purple .. "- All commands - " .. cChatColor.Gold .. "[Page " .. PageRequested .. " / " .. CurrentPage .. "]");
end for idx, msg in ipairs(Output) do
end Player:SendMessage(msg);
end;
return true return true
end end

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** 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 #ifndef __cplusplus
@ -154,7 +154,6 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cInventory"); tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot"); tolua_usertype(tolua_S,"cRoot");
tolua_usertype(tolua_S,"cCraftingGrid"); tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cPlugin::CommandStruct");
tolua_usertype(tolua_S,"cPickup"); tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"cItems"); tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cGroup"); 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,"Vector3i");
tolua_usertype(tolua_S,"Lua__cWebPlugin"); tolua_usertype(tolua_S,"Lua__cWebPlugin");
tolua_usertype(tolua_S,"Lua__cPawn"); 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,"cItem");
tolua_usertype(tolua_S,"Vector3f"); tolua_usertype(tolua_S,"Vector3f");
tolua_usertype(tolua_S,"Lua__cTCPLink"); 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,"cGroupManager");
tolua_usertype(tolua_S,"cBlockEntity"); tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"Lua__cPickup"); 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,"cPluginManager");
tolua_usertype(tolua_S,"cPlugin"); tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"HTTPFormData"); tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cLadder"); tolua_usertype(tolua_S,"cLadder");
tolua_usertype(tolua_S,"MTRand"); tolua_usertype(tolua_S,"MTRand");
tolua_usertype(tolua_S,"cWorld"); tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cIniFile"); tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cEntity"); tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"HTTPRequest"); 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,"cPlayer");
tolua_usertype(tolua_S,"cTorch"); tolua_usertype(tolua_S,"cTorch");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner"); 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,"Lua__cChestEntity");
tolua_usertype(tolua_S,"cPawn"); tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"Lua__cEntity"); tolua_usertype(tolua_S,"cStairs");
tolua_usertype(tolua_S,"Vector3d"); 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 #endif //#ifndef TOLUA_DISABLE
/* method: GetPluginManager of class cPluginManager */ /* method: Get of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_GetPluginManager00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_Get00
static int tolua_AllToLua_cPluginManager_GetPluginManager00(lua_State* tolua_S) static int tolua_AllToLua_cPluginManager_Get00(lua_State* tolua_S)
{ {
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
@ -8797,14 +8796,14 @@ static int tolua_AllToLua_cPluginManager_GetPluginManager00(lua_State* tolua_S)
#endif #endif
{ {
{ {
cPluginManager* tolua_ret = (cPluginManager*) cPluginManager::GetPluginManager(); cPluginManager* tolua_ret = (cPluginManager*) cPluginManager::Get();
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPluginManager"); tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPluginManager");
} }
} }
return 1; return 1;
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_lerror: tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'GetPluginManager'.",&tolua_err); tolua_error(tolua_S,"#ferror in function 'Get'.",&tolua_err);
return 0; return 0;
#endif #endif
} }
@ -8990,7 +8989,7 @@ static int tolua_AllToLua_cPluginManager_DisablePlugin00(lua_State* tolua_S)
#endif #endif
{ {
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0); 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 #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DisablePlugin'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'DisablePlugin'", NULL);
#endif #endif
@ -9025,7 +9024,7 @@ static int tolua_AllToLua_cPluginManager_LoadPlugin00(lua_State* tolua_S)
#endif #endif
{ {
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0); 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 #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LoadPlugin'", NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LoadPlugin'", NULL);
#endif #endif
@ -9044,93 +9043,73 @@ static int tolua_AllToLua_cPluginManager_LoadPlugin00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* get function: Command of class CommandStruct */ /* method: IsCommandBound of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin__CommandStruct_Command #ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_IsCommandBound00
static int tolua_get_cPlugin__CommandStruct_Command(lua_State* tolua_S) 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);
#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);
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Command'",NULL); if (
if (!tolua_iscppstring(tolua_S,2,0,&tolua_err)) !tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err); !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif #endif
self->Command = ((AString) tolua_tocppstring(tolua_S,2,0))
;
return 0;
}
#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)
{ {
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 #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Description'",NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsCommandBound'", NULL);
#endif
{
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
tolua_pushcppstring(tolua_S,(const char*)self->Description);
return 1;
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* set function: Description of class CommandStruct */ /* method: GetCommandPermission of class cPluginManager */
#ifndef TOLUA_DISABLE_tolua_set_cPlugin__CommandStruct_Description #ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_GetCommandPermission00
static int tolua_set_cPlugin__CommandStruct_Description(lua_State* tolua_S) static int tolua_AllToLua_cPluginManager_GetCommandPermission00(lua_State* tolua_S)
{ {
cPlugin::CommandStruct* self = (cPlugin::CommandStruct*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_Error tolua_err;
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Description'",NULL); if (
if (!tolua_iscppstring(tolua_S,2,0,&tolua_err)) !tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err); !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif #endif
self->Description = ((AString) tolua_tocppstring(tolua_S,2,0))
;
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); cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
const AString a_Command = ((const AString) tolua_tocppstring(tolua_S,2,0));
#ifndef TOLUA_RELEASE #ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Permission'",NULL); if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetCommandPermission'", NULL);
#endif #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); 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 #ifndef TOLUA_RELEASE
tolua_Error tolua_err; tolua_lerror:
if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'Permission'",NULL); tolua_error(tolua_S,"#ferror in function 'GetCommandPermission'.",&tolua_err);
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; return 0;
#endif
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
@ -9329,46 +9308,6 @@ static int tolua_AllToLua_cPlugin_GetLocalDirectory00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #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 */ /* get function: __cWebPlugin__ of class cPlugin_NewLua */
#ifndef TOLUA_DISABLE_tolua_get_cPlugin_NewLua___cWebPlugin__ #ifndef TOLUA_DISABLE_tolua_get_cPlugin_NewLua___cWebPlugin__
static int tolua_get_cPlugin_NewLua___cWebPlugin__(lua_State* tolua_S) 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_UPDATED_SIGN",cPluginManager::HOOK_UPDATED_SIGN);
tolua_constant(tolua_S,"HOOK_UPDATING_SIGN",cPluginManager::HOOK_UPDATING_SIGN); tolua_constant(tolua_S,"HOOK_UPDATING_SIGN",cPluginManager::HOOK_UPDATING_SIGN);
tolua_constant(tolua_S,"HOOK_WEATHER_CHANGED",cPluginManager::HOOK_WEATHER_CHANGED); 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,"GetPlugin",tolua_AllToLua_cPluginManager_GetPlugin00);
tolua_function(tolua_S,"FindPlugins",tolua_AllToLua_cPluginManager_FindPlugins00); tolua_function(tolua_S,"FindPlugins",tolua_AllToLua_cPluginManager_FindPlugins00);
tolua_function(tolua_S,"ReloadPlugins",tolua_AllToLua_cPluginManager_ReloadPlugins00); 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,"GetNumPlugins",tolua_AllToLua_cPluginManager_GetNumPlugins00);
tolua_function(tolua_S,"DisablePlugin",tolua_AllToLua_cPluginManager_DisablePlugin00); tolua_function(tolua_S,"DisablePlugin",tolua_AllToLua_cPluginManager_DisablePlugin00);
tolua_function(tolua_S,"LoadPlugin",tolua_AllToLua_cPluginManager_LoadPlugin00); 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_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPlugin","cPlugin","",NULL); tolua_cclass(tolua_S,"cPlugin","cPlugin","",NULL);
tolua_beginmodule(tolua_S,"cPlugin"); 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,"GetName",tolua_AllToLua_cPlugin_GetName00);
tolua_function(tolua_S,"SetName",tolua_AllToLua_cPlugin_SetName00); tolua_function(tolua_S,"SetName",tolua_AllToLua_cPlugin_SetName00);
tolua_function(tolua_S,"GetVersion",tolua_AllToLua_cPlugin_GetVersion00); tolua_function(tolua_S,"GetVersion",tolua_AllToLua_cPlugin_GetVersion00);
tolua_function(tolua_S,"SetVersion",tolua_AllToLua_cPlugin_SetVersion00); tolua_function(tolua_S,"SetVersion",tolua_AllToLua_cPlugin_SetVersion00);
tolua_function(tolua_S,"GetDirectory",tolua_AllToLua_cPlugin_GetDirectory00); tolua_function(tolua_S,"GetDirectory",tolua_AllToLua_cPlugin_GetDirectory00);
tolua_function(tolua_S,"GetLocalDirectory",tolua_AllToLua_cPlugin_GetLocalDirectory00); tolua_function(tolua_S,"GetLocalDirectory",tolua_AllToLua_cPlugin_GetLocalDirectory00);
tolua_function(tolua_S,"AddCommand",tolua_AllToLua_cPlugin_AddCommand00);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPlugin_NewLua","cPlugin_NewLua","cPlugin",NULL); tolua_cclass(tolua_S,"cPlugin_NewLua","cPlugin_NewLua","cPlugin",NULL);
tolua_beginmodule(tolua_S,"cPlugin_NewLua"); tolua_beginmodule(tolua_S,"cPlugin_NewLua");

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** 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 */ /* 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.h"
#include "Plugin_NewLua.h" #include "Plugin_NewLua.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "LuaCommandBinder.h"
#include "Player.h" #include "Player.h"
#include "WebAdmin.h" #include "WebAdmin.h"
#include "StringMap.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); int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if( NumArgs != 1)
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())
{ {
const cPlugin::CommandStruct & CS = *iter; LOGWARN("Error in function call 'ForEachCommand': Requires 1 argument, got %i", NumArgs);
tolua_pushusertype( tolua_S, (void*)&CS, "const cPlugin::CommandStruct" ); return 0;
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
} }
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; 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) 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) static int tolua_cPlugin_BindCommand(lua_State* tolua_S)
{ {
cPlugin* self = (cPlugin*) tolua_tousertype(tolua_S,1,0); cPlugin* self = (cPlugin*) tolua_tousertype(tolua_S,1,0);
@ -651,6 +760,7 @@ static int tolua_cPlugin_BindCommand(lua_State* tolua_S)
return 0; return 0;
} }
*/
@ -927,13 +1037,13 @@ void ManualBindings::Bind( lua_State* tolua_S )
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlugin"); 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_function(tolua_S, "Call", tolua_cPlugin_Call);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPluginManager"); tolua_beginmodule(tolua_S, "cPluginManager");
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins); 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_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlayer"); tolua_beginmodule(tolua_S, "cPlayer");

View File

@ -12,7 +12,6 @@
cPlugin::cPlugin( const AString & a_PluginDirectory ) cPlugin::cPlugin( const AString & a_PluginDirectory )
: m_Version(0) : m_Version(0)
, m_Language(E_CPP) , m_Language(E_CPP)
, m_bCanBindCommands( false )
, m_Directory(a_PluginDirectory) , 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) bool cPlugin::OnKilling(cPawn & a_Victim, cEntity * a_Killer)
{ {
UNUSED(a_Victim); 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_Split);
UNUSED(a_Username); UNUSED(a_Player);
return false; 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 AString cPlugin::GetLocalDirectory(void) const
{ {
return std::string("Plugins/") + m_Directory; 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 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); 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. /** 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) 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) Returns true if the hook can be added (handler exists)
@ -89,13 +95,6 @@ public:
virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) { return false; } virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) { return false; }
// tolua_begin // tolua_begin
struct CommandStruct
{
AString Command;
AString Description;
AString Permission;
};
const AString & GetName(void) const { return m_Name; } const AString & GetName(void) const { return m_Name; }
void SetName(const AString & a_Name) { m_Name = a_Name; } void SetName(const AString & a_Name) { m_Name = a_Name; }
@ -104,14 +103,8 @@ public:
const AString & GetDirectory(void) const {return m_Directory; } const AString & GetDirectory(void) const {return m_Directory; }
AString GetLocalDirectory(void) const; AString GetLocalDirectory(void) const;
void AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission);
// tolua_end // 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 */ /* This should not be exposed to scripting languages */
enum PluginLanguage enum PluginLanguage
@ -123,13 +116,8 @@ public:
PluginLanguage GetLanguage() { return m_Language; } PluginLanguage GetLanguage() { return m_Language; }
void SetLanguage( PluginLanguage a_Language ) { m_Language = a_Language; } void SetLanguage( PluginLanguage a_Language ) { m_Language = a_Language; }
bool CanBindCommands() { return m_bCanBindCommands; }
private: private:
friend class cPluginManager;
bool m_bCanBindCommands; // Only changed by cPluginManager
PluginLanguage m_Language; PluginLanguage m_Language;
std::vector< CommandStruct > m_Commands;
AString m_Name; AString m_Name;
int m_Version; 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 "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "PluginManager.h" #include "PluginManager.h"
@ -6,32 +7,17 @@
#include "WebAdmin.h" #include "WebAdmin.h"
#include "Item.h" #include "Item.h"
#include "Root.h" #include "Root.h"
#include "LuaCommandBinder.h"
#ifdef USE_SQUIRREL
#include "Plugin_Squirrel.h"
#include "SquirrelCommandBinder.h"
#endif
#include "../iniFile/iniFile.h" #include "../iniFile/iniFile.h"
#include "tolua++.h" #include "tolua++.h"
#include "Player.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::Get(void)
cPluginManager* cPluginManager::GetPluginManager()
{ {
LOGWARN("WARNING: Using deprecated function cPluginManager::GetPluginManager() use cRoot::Get()->GetPluginManager() instead!");
return cRoot::Get()->GetPluginManager(); return cRoot::Get()->GetPluginManager();
} }
@ -39,12 +25,8 @@ cPluginManager* cPluginManager::GetPluginManager()
cPluginManager::cPluginManager() cPluginManager::cPluginManager(void) :
: m_LuaCommandBinder( new cLuaCommandBinder() ) m_bReloadPlugins(false)
#ifdef USE_SQUIRREL
, m_SquirrelCommandBinder( new cSquirrelCommandBinder() )
#endif
, m_bReloadPlugins(false)
{ {
} }
@ -55,18 +37,13 @@ cPluginManager::cPluginManager()
cPluginManager::~cPluginManager() cPluginManager::~cPluginManager()
{ {
UnloadPluginsNow(); UnloadPluginsNow();
delete m_LuaCommandBinder;
#ifdef USE_SQUIRREL
delete m_SquirrelCommandBinder;
#endif
} }
void cPluginManager::ReloadPlugins() void cPluginManager::ReloadPlugins(void)
{ {
m_bReloadPlugins = true; m_bReloadPlugins = true;
} }
@ -75,7 +52,7 @@ void cPluginManager::ReloadPlugins()
void cPluginManager::FindPlugins() void cPluginManager::FindPlugins(void)
{ {
AString PluginsPath = FILE_IO_PREFIX + AString( "Plugins/" ); AString PluginsPath = FILE_IO_PREFIX + AString( "Plugins/" );
@ -114,17 +91,12 @@ void cPluginManager::FindPlugins()
void cPluginManager::ReloadPluginsNow() void cPluginManager::ReloadPluginsNow(void)
{ {
LOG("Loading plugins"); LOG("Loading plugins");
m_bReloadPlugins = false; m_bReloadPlugins = false;
UnloadPluginsNow(); UnloadPluginsNow();
#ifdef USE_SQUIRREL
CloseSquirrelVM();
OpenSquirrelVM();
#endif // USE_SQUIRREL
FindPlugins(); FindPlugins();
cIniFile IniFile("settings.ini"); cIniFile IniFile("settings.ini");
@ -140,7 +112,10 @@ void cPluginManager::ReloadPluginsNow()
for(unsigned int i = 0; i < NumPlugins; i++) for(unsigned int i = 0; i < NumPlugins; i++)
{ {
AString ValueName = IniFile.GetValueName(KeyNum, 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); AString PluginFile = IniFile.GetValue(KeyNum, i);
if (!PluginFile.empty()) if (!PluginFile.empty())
@ -151,24 +126,6 @@ void cPluginManager::ReloadPluginsNow()
} }
} }
} }
#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
} }
} }
@ -188,9 +145,9 @@ void cPluginManager::ReloadPluginsNow()
void cPluginManager::Tick(float a_Dt) 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(); m_DisablePluginList.pop_front();
} }
@ -240,22 +197,17 @@ bool cPluginManager::CallHookBlockToPickups(
bool cPluginManager::CallHookChat(cPlayer * a_Player, const AString & a_Message) bool cPluginManager::CallHookChat(cPlayer * a_Player, const AString & a_Message)
{ {
#ifdef USE_SQUIRREL if (ExecuteCommand(a_Player, a_Message))
if (m_SquirrelCommandBinder->HandleCommand(a_Message, a_Player))
{
return true;
}
#endif // USE_SQUIRREL
if (m_LuaCommandBinder->HandleCommand(a_Message, a_Player))
{ {
return true; return true;
} }
// Check if it was a standard command (starts with a slash) // 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()); LOGINFO("Player \"%s\" issued an unknown command: \"%s\"", a_Player->GetName().c_str(), a_Message.c_str());
return true; // Cancel sending return true; // Cancel sending
} }
@ -911,6 +863,42 @@ bool cPluginManager::CallHookWeatherChanged(cWorld * a_World)
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 cPlugin * cPluginManager::GetPlugin( const AString & a_Plugin ) const
{ {
for( PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr ) for( PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr )
@ -941,9 +929,9 @@ void cPluginManager::UnloadPluginsNow()
{ {
m_Hooks.clear(); 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 //SquirrelVM::Shutdown(); // This breaks shit
@ -953,18 +941,20 @@ void cPluginManager::UnloadPluginsNow()
bool cPluginManager::DisablePlugin( AString & a_PluginName ) bool cPluginManager::DisablePlugin(const AString & a_PluginName)
{ {
PluginMap::iterator itr = m_Plugins.find(a_PluginName); PluginMap::iterator itr = m_Plugins.find(a_PluginName);
if (itr != m_Plugins.end()) if (itr == m_Plugins.end())
{ {
if (itr->first.compare( a_PluginName ) == 0) 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); m_DisablePluginList.push_back(itr->second);
itr->second = NULL; // Get rid of this thing right away itr->second = NULL; // Get rid of this thing right away
return true; return true;
} }
}
return false; 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() ); return AddPlugin(new cPlugin_NewLua(a_PluginName.c_str()));
if (!AddPlugin(Plugin))
{
delete Plugin;
return false;
}
return true;
} }
@ -999,15 +983,8 @@ 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 )
{
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) for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
{ {
if (itr->second == a_Plugin) if (itr->second == a_Plugin)
@ -1016,13 +993,110 @@ void cPluginManager::RemovePlugin( cPlugin * a_Plugin, bool a_bDelete /* = false
break; break;
} }
} }
RemovePluginCommands(a_Plugin);
RemoveHooks(a_Plugin);
if (a_Plugin != NULL) if (a_Plugin != NULL)
{ {
RemoveHooks( a_Plugin );
a_Plugin->OnDisable(); a_Plugin->OnDisable();
}
delete a_Plugin; delete a_Plugin;
} }
void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
{
if (a_Plugin != NULL)
{
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);
} }
@ -1031,15 +1105,15 @@ void cPluginManager::RemovePlugin( cPlugin * a_Plugin, bool a_bDelete /* = false
bool cPluginManager::AddPlugin(cPlugin * a_Plugin) bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
{ {
a_Plugin->m_bCanBindCommands = true; m_Plugins[a_Plugin->GetDirectory()] = a_Plugin;
if (a_Plugin->Initialize()) if (a_Plugin->Initialize())
{ {
m_Plugins[ a_Plugin->GetDirectory() ] = a_Plugin; // Initialization OK
return true; return true;
} }
a_Plugin->m_bCanBindCommands = false; // Initialization failed
RemoveHooks( a_Plugin ); // Undo any damage the Initialize() might have done RemovePlugin(a_Plugin); // Also undoes any registrations that Initialize() might have made
return false; 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" #include "Item.h"
struct lua_State;
class cLuaCommandBinder;
#ifdef USE_SQUIRREL
class cSquirrelCommandBinder;
#endif // USE_SQUIRREL
class cPlugin; class cPlugin;
// fwd: World.h // fwd: World.h
@ -84,7 +77,16 @@ public: // tolua_export
} ; } ;
// tolua_end // 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::map< AString, cPlugin * > PluginMap;
typedef std::list< cPlugin * > PluginList; typedef std::list< cPlugin * > PluginList;
@ -93,7 +95,6 @@ public: // tolua_export
void FindPlugins(); // tolua_export void FindPlugins(); // tolua_export
void ReloadPlugins(); // tolua_export void ReloadPlugins(); // tolua_export
bool AddPlugin( cPlugin* a_Plugin );
void AddHook( cPlugin* a_Plugin, PluginHook a_Hook ); // tolua_export void AddHook( cPlugin* a_Plugin, PluginHook a_Hook ); // tolua_export
unsigned int GetNumPlugins() const; // tolua_export unsigned int GetNumPlugins() const; // tolua_export
@ -131,44 +132,68 @@ public: // tolua_export
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 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 CallHookWeatherChanged (cWorld * a_World);
bool DisablePlugin( AString & a_PluginName ); // tolua_export bool DisablePlugin(const AString & a_PluginName); // tolua_export
bool LoadPlugin( AString & a_PluginName ); // tolua_export bool LoadPlugin (const AString & a_PluginName); // tolua_export
/// Removes all hooks the specified plugin has registered
void RemoveHooks(cPlugin * a_Plugin); void RemoveHooks(cPlugin * a_Plugin);
void RemovePlugin( cPlugin * a_Plugin, bool a_bDelete = false );
cLuaCommandBinder* GetLuaCommandBinder() const { return m_LuaCommandBinder; } /// Removes the plugin from the internal structures and deletes its object.
void RemovePlugin(cPlugin * a_Plugin);
#ifdef USE_SQUIRREL /// Removes all command bindings that the specified plugin has made
cSquirrelCommandBinder * GetSquirrelCommandBinder() { return m_SquirrelCommandBinder; } void RemovePluginCommands(cPlugin * a_Plugin);
#endif // USE_SQUIRREL
bool HasPlugin( cPlugin* a_Plugin ) const; /// 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: private:
friend class cRoot; 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();
~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; /// 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.
HookMap m_Hooks; bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
void ReloadPluginsNow();
void UnloadPluginsNow();
cLuaCommandBinder * m_LuaCommandBinder;
#ifdef USE_SQUIRREL
cSquirrelCommandBinder * m_SquirrelCommandBinder;
#endif // USE_SQUIRREL
bool m_bReloadPlugins;
} ; // tolua_export } ; // 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); cCSLock Lock(m_CriticalSection);
if( !m_LuaState ) if (m_LuaState == NULL)
{ {
m_LuaState = lua_open(); m_LuaState = lua_open();
luaL_openlibs(m_LuaState); luaL_openlibs(m_LuaState);
tolua_AllToLua_open(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() + "/"; 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) bool cPlugin_NewLua::CanAddHook(cPluginManager::PluginHook a_Hook)
{ {
const char * FnName = GetHookFnName(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 // Helper functions
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */) 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); lua_getglobal(m_LuaState, a_FunctionName);
if (!lua_isfunction(m_LuaState, -1)) if (!lua_isfunction(m_LuaState, -1))
{ {

View File

@ -4,6 +4,9 @@
#include "Plugin.h" #include "Plugin.h"
#include "WebPlugin.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 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 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; virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) override;
// cWebPlugin override // cWebPlugin override
@ -72,20 +79,27 @@ public:
virtual AString HandleWebRequest( HTTPRequest * a_Request ) override; virtual AString HandleWebRequest( HTTPRequest * a_Request ) override;
bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS << 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; } lua_State* GetLuaState() { return m_LuaState; }
cCriticalSection & GetCriticalSection() { return m_CriticalSection; } cCriticalSection & GetCriticalSection() { return m_CriticalSection; }
protected: 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 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 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 /// Returns the name of Lua function that should handle the specified hook
const char * GetHookFnName(cPluginManager::PluginHook a_Hook); const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
cCriticalSection m_CriticalSection;
lua_State * m_LuaState;
} ; // tolua_export } ; // tolua_export