diff options
author | Mattes D <github@xoft.cz> | 2016-03-21 10:40:38 +0100 |
---|---|---|
committer | Mattes D <github@xoft.cz> | 2016-03-21 10:40:38 +0100 |
commit | fa53e98419152a83b2a74c5ea45a60449abc59c2 (patch) | |
tree | 766f4703a8c30a01bfc5148fe54c6d6b4a3e3cc7 /src/Bindings/ManualBindings.cpp | |
parent | Merge pull request #3084 from cuberite/seadragon91-patch-1 (diff) | |
parent | Revert "Lua callback" (diff) | |
download | cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar.gz cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar.bz2 cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar.lz cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar.xz cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.tar.zst cuberite-fa53e98419152a83b2a74c5ea45a60449abc59c2.zip |
Diffstat (limited to '')
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 461 |
1 files changed, 135 insertions, 326 deletions
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index f041ef524..523244ed2 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -992,13 +992,7 @@ static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager, } // Retrieve and check the hook type - int HookType; - if (!S.GetStackValue(a_ParamIdx, HookType)) - { - LOGWARNING("cPluginManager.AddHook(): Cannot read the hook type."); - S.LogStackTrace(); - return 0; - } + int HookType = static_cast<int>(tolua_tonumber(S, a_ParamIdx, -1)); if (!a_PluginManager->IsValidHookType(HookType)) { LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType); @@ -1007,14 +1001,7 @@ static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager, } // Add the hook to the plugin - auto callback = std::make_shared<cLuaState::cCallback>(); - if (!S.GetStackValue(a_ParamIdx + 1, callback)) - { - LOGWARNING("cPluginManager.AddHook(): Cannot read the callback parameter"); - S.LogStackTrace(); - return 0; - } - if (!Plugin->AddHookCallback(HookType, callback)) + if (!Plugin->AddHookRef(HookType, a_ParamIdx + 1)) { LOGWARNING("cPluginManager.AddHook(): Cannot add hook %d, unknown error.", HookType); S.LogStackTrace(); @@ -1071,11 +1058,10 @@ static int tolua_cPluginManager_AddHook_DefFn(cPluginManager * a_PluginManager, } // Retrieve the function to call and add it to the plugin: - auto callback = std::make_shared<cLuaState::cCallback>(); - lua_getglobal(S, FnName); - bool res = S.GetStackValue(-1, callback); - lua_pop(S, 1); - if (!res || !callback->IsValid()) + lua_pushstring(S, FnName); + bool res = Plugin->AddHookRef(HookType, 1); + lua_pop(S, 1); // Pop the function off the stack + if (!res) { LOGWARNING("cPluginManager.AddHook(): Function %s not found. Hook not added.", FnName); S.LogStackTrace(); @@ -1599,6 +1585,55 @@ static int tolua_cPlayer_GetRestrictions(lua_State * tolua_S) +static int tolua_cPlayer_OpenWindow(lua_State * tolua_S) +{ + // Function signature: cPlayer:OpenWindow(Window) + + // Retrieve the plugin instance from the Lua state + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + return 0; + } + + // Get the parameters: + cPlayer * self = reinterpret_cast<cPlayer *>(tolua_tousertype(tolua_S, 1, nullptr)); + cWindow * wnd = reinterpret_cast<cWindow *>(tolua_tousertype(tolua_S, 2, nullptr)); + if ((self == nullptr) || (wnd == nullptr)) + { + LOGWARNING("%s: invalid self (%p) or wnd (%p)", __FUNCTION__, static_cast<void *>(self), static_cast<void *>(wnd)); + return 0; + } + + // If cLuaWindow, add a reference, so that Lua won't delete the cLuaWindow object mid-processing + tolua_Error err; + if (tolua_isusertype(tolua_S, 2, "cLuaWindow", 0, &err)) + { + cLuaWindow * LuaWnd = reinterpret_cast<cLuaWindow *>(wnd); + // Only if not already referenced + if (!LuaWnd->IsLuaReferenced()) + { + int LuaRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + if (LuaRef == LUA_REFNIL) + { + LOGWARNING("%s: Cannot create a window reference. Cannot open window \"%s\".", + __FUNCTION__, wnd->GetWindowTitle().c_str() + ); + return 0; + } + LuaWnd->SetLuaRef(Plugin, LuaRef); + } + } + + // Open the window + self->OpenWindow(wnd); + return 0; +} + + + + + static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S) { // Function signature: cPlayer:PermissionMatches(PermissionStr, TemplateStr) -> bool @@ -1629,25 +1664,36 @@ static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S) template < class OBJTYPE, - void (OBJTYPE::*SetCallback)(cLuaState::cCallbackPtr a_CallbackFn) + void (OBJTYPE::*SetCallback)(cPluginLua * a_Plugin, int a_FnRef) > static int tolua_SetObjectCallback(lua_State * tolua_S) { // Function signature: OBJTYPE:SetWhateverCallback(CallbackFunction) + // Retrieve the plugin instance from the Lua state + cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); + if (Plugin == nullptr) + { + // Warning message has already been printed by GetLuaPlugin(), bail out silently + return 0; + } + // Get the parameters - self and the function reference: - cLuaState L(tolua_S); - OBJTYPE * self; - cLuaState::cCallbackPtr callback; - if (!L.GetStackValues(1, self, callback)) + OBJTYPE * self = reinterpret_cast<OBJTYPE *>(tolua_tousertype(tolua_S, 1, nullptr)); + if (self == nullptr) { - LOGWARNING("%s: Cannot get parameters", __FUNCTION__); - L.LogStackTrace(); + LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast<void *>(self)); + return 0; + } + int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); // Store function reference for later retrieval + if (FnRef == LUA_REFNIL) + { + LOGERROR("%s: Cannot create a function reference. Callback not set.", __FUNCTION__); return 0; } // Set the callback - (self->*SetCallback)(callback); + (self->*SetCallback)(Plugin, FnRef); return 0; } @@ -1655,71 +1701,47 @@ static int tolua_SetObjectCallback(lua_State * tolua_S) -// Callback class used for the WebTab: -class cWebTabCallback: - public cWebAdmin::cWebTabCallback +static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S) { -public: - /** The Lua callback to call to generate the page contents. */ - cLuaState::cCallback m_Callback; + cLuaState LuaState(tolua_S); + cPluginLua * self = nullptr; - virtual bool Call( - const HTTPRequest & a_Request, - const AString & a_UrlPath, - AString & a_Content, - AString & a_ContentType - ) override + if (!LuaState.GetStackValue(1, self)) { - AString content, contentType; - return m_Callback.Call(&a_Request, a_UrlPath, cLuaState::Return, a_Content, a_ContentType); + LOGWARNING("cPluginLua:AddWebTab: invalid self as first argument"); + return 0; } -}; - - - + tolua_Error tolua_err; + tolua_err.array = 0; + tolua_err.index = 3; + tolua_err.type = "function"; -static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S) -{ - // OBSOLETE, use cWebAdmin:AddWebTab() instead! - // Function signature: - // cPluginLua:AddWebTab(Title, CallbackFn, [UrlPath]) - - // TODO: Warn about obsolete API usage - // Only implement after merging the new API change and letting some time for changes in the plugins + std::string Title; + int Reference = LUA_REFNIL; - // Check params: - cLuaState LuaState(tolua_S); - cPluginLua * self = cManualBindings::GetLuaPlugin(tolua_S); - if (self == nullptr) + if (LuaState.CheckParamString(2) && LuaState.CheckParamFunction(3)) { - return 0; + Reference = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + LuaState.GetStackValue(2, Title); } - if ( - !LuaState.CheckParamString(2) || - !LuaState.CheckParamFunction(3) || - // Optional string as param 4 - !LuaState.CheckParamEnd(5) - ) + else { - return 0; + return cManualBindings::tolua_do_error(tolua_S, "#ferror calling function '#funcname#'", &tolua_err); } - // Read the params: - AString title, urlPath; - auto callback = std::make_shared<cWebTabCallback>(); - if (!LuaState.GetStackValues(2, title, callback->m_Callback)) + if (Reference != LUA_REFNIL) { - LOGWARNING("cPlugin:AddWebTab(): Cannot read required parameters"); - return 0; + if (!self->AddWebTab(Title.c_str(), tolua_S, Reference)) + { + luaL_unref(tolua_S, LUA_REGISTRYINDEX, Reference); + } } - if (!LuaState.GetStackValue(4, urlPath)) + else { - urlPath = cWebAdmin::GetURLEncodedString(title); + LOGWARNING("cPluginLua:AddWebTab: invalid function reference in 2nd argument (Title: \"%s\")", Title.c_str()); } - cRoot::Get()->GetWebAdmin()->AddWebTab(title, urlPath, self->GetName(), callback); - return 0; } @@ -2084,68 +2106,22 @@ static int tolua_cUrlParser_ParseAuthorityPart(lua_State * a_LuaState) -static int tolua_cWebAdmin_AddWebTab(lua_State * tolua_S) +static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S) { - // Function signatures: - // cWebAdmin:AddWebTab(Title, UrlPath, CallbackFn) + cWebAdmin * self = reinterpret_cast<cWebAdmin *>(tolua_tousertype(tolua_S, 1, nullptr)); - // Check params: - cLuaState LuaState(tolua_S); - cPluginLua * self = cManualBindings::GetLuaPlugin(tolua_S); - if (self == nullptr) - { - return 0; - } - if ( - // Don't care whether the first param is a cWebAdmin instance or class - !LuaState.CheckParamString(2, 3) || - !LuaState.CheckParamFunction(4) || - !LuaState.CheckParamEnd(5) - ) - { - return 0; - } + const cWebAdmin::PluginList & AllPlugins = self->GetPlugins(); - // Read the params: - AString title, urlPath; - auto callback = std::make_shared<cWebTabCallback>(); - if (!LuaState.GetStackValues(2, title, urlPath, callback->m_Callback)) - { - LOGWARNING("cWebAdmin:AddWebTab(): Cannot read required parameters"); - return 0; - } - - cRoot::Get()->GetWebAdmin()->AddWebTab(title, urlPath, self->GetName(), callback); - - return 0; -} - - - - - -static int tolua_cWebAdmin_GetAllWebTabs(lua_State * tolua_S) -{ - // Function signature: - // cWebAdmin:GetAllWebTabs() -> { {"PluginName", "UrlPath", "Title"}, {"PluginName", "UrlPath", "Title"}, ...} - - // Don't care about params at all - - auto webTabs = cRoot::Get()->GetWebAdmin()->GetAllWebTabs(); - lua_createtable(tolua_S, static_cast<int>(webTabs.size()), 0); + lua_createtable(tolua_S, static_cast<int>(AllPlugins.size()), 0); int newTable = lua_gettop(tolua_S); int index = 1; - cLuaState L(tolua_S); - for (const auto & wt: webTabs) - { - lua_createtable(tolua_S, 0, 3); - L.Push(wt->m_PluginName); - lua_setfield(tolua_S, -2, "PluginName"); - L.Push(wt->m_UrlPath); - lua_setfield(tolua_S, -2, "UrlPath"); - L.Push(wt->m_Title); - lua_setfield(tolua_S, -2, "Title"); + cWebAdmin::PluginList::const_iterator iter = AllPlugins.begin(); + while (iter != AllPlugins.end()) + { + const cWebPlugin * Plugin = *iter; + tolua_pushusertype(tolua_S, reinterpret_cast<void *>(const_cast<cWebPlugin*>(Plugin)), "const cWebPlugin"); lua_rawseti(tolua_S, newTable, index); + ++iter; ++index; } return 1; @@ -2155,42 +2131,14 @@ static int tolua_cWebAdmin_GetAllWebTabs(lua_State * tolua_S) -/** Binding for cWebAdmin::GetBaseURL. -Manual code required because ToLua generates an extra return value */ -static int tolua_cWebAdmin_GetBaseURL(lua_State * tolua_S) -{ - // Check the param types: - cLuaState S(tolua_S); - if ( - // Don't care whether the first param is a cWebAdmin instance or class - !S.CheckParamString(2) || - !S.CheckParamEnd(3) - ) - { - return 0; - } - - // Get the parameters: - AString Input; - S.GetStackValue(2, Input); - - // Convert and return: - S.Push(cWebAdmin::GetBaseURL(Input)); - return 1; -} - - - - - -/** Binding for cWebAdmin::GetContentTypeFromFileExt. +/** Binding for cWebAdmin::GetHTMLEscapedString. Manual code required because ToLua generates an extra return value */ -static int tolua_cWebAdmin_GetContentTypeFromFileExt(lua_State * tolua_S) +static int tolua_AllToLua_cWebAdmin_GetHTMLEscapedString(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( - // Don't care whether the first param is a cWebAdmin instance or class + !S.CheckParamUserTable(1, "cWebAdmin") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) @@ -2203,7 +2151,7 @@ static int tolua_cWebAdmin_GetContentTypeFromFileExt(lua_State * tolua_S) S.GetStackValue(2, Input); // Convert and return: - S.Push(cWebAdmin::GetContentTypeFromFileExt(Input)); + S.Push(cWebAdmin::GetHTMLEscapedString(Input)); return 1; } @@ -2211,14 +2159,14 @@ static int tolua_cWebAdmin_GetContentTypeFromFileExt(lua_State * tolua_S) -/** Binding for cWebAdmin::GetHTMLEscapedString. +/** Binding for cWebAdmin::GetURLEncodedString. Manual code required because ToLua generates an extra return value */ -static int tolua_cWebAdmin_GetHTMLEscapedString(lua_State * tolua_S) +static int tolua_AllToLua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( - // Don't care whether the first param is a cWebAdmin instance or class + !S.CheckParamUserTable(1, "cWebAdmin") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) @@ -2231,64 +2179,7 @@ static int tolua_cWebAdmin_GetHTMLEscapedString(lua_State * tolua_S) S.GetStackValue(2, Input); // Convert and return: - S.Push(cWebAdmin::GetHTMLEscapedString(Input)); - return 1; -} - - - - - -/** Binding for cWebAdmin::GetPage. */ -static int tolua_cWebAdmin_GetPage(lua_State * tolua_S) -{ - /* - Function signature: - cWebAdmin:GetPage(a_HTTPRequest) -> - { - Content = "", // Content generated by the plugin - ContentType = "", // Content type generated by the plugin (default: "text/html") - UrlPath = "", // URL path of the tab - TabTitle = "", // Tab's title, as register via cWebAdmin:AddWebTab() - PluginName = "", // Plugin's API name - PluginFolder = "", // Plugin's folder name (display name) - } - */ - - // Check the param types: - cLuaState S(tolua_S); - if ( - // Don't care about first param, whether it's cWebAdmin instance or class - !S.CheckParamUserType(2, "HTTPRequest") || - !S.CheckParamEnd(3) - ) - { - return 0; - } - - // Get the parameters: - HTTPRequest * request = nullptr; - if (!S.GetStackValue(2, request)) - { - LOGWARNING("cWebAdmin:GetPage(): Cannot read the HTTPRequest parameter."); - return 0; - } - - // Generate the page and push the results as a dictionary-table: - auto page = cRoot::Get()->GetWebAdmin()->GetPage(*request); - lua_createtable(S, 0, 6); - S.Push(page.Content); - lua_setfield(S, -2, "Content"); - S.Push(page.ContentType); - lua_setfield(S, -2, "ContentType"); - S.Push(page.TabUrlPath); - lua_setfield(S, -2, "UrlPath"); - S.Push(page.TabTitle); - lua_setfield(S, -2, "TabTitle"); - S.Push(page.PluginName); - lua_setfield(S, -2, "PluginName"); - S.Push(cPluginManager::Get()->GetPluginFolderName(page.PluginName)); - lua_setfield(S, -2, "PluginFolder"); + S.Push(cWebAdmin::GetURLEncodedString(Input)); return 1; } @@ -2296,27 +2187,20 @@ static int tolua_cWebAdmin_GetPage(lua_State * tolua_S) -/** Binding for cWebAdmin::GetURLEncodedString. -Manual code required because ToLua generates an extra return value */ -static int tolua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S) +static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S) { - // Check the param types: - cLuaState S(tolua_S); - if ( - // Don't care whether the first param is a cWebAdmin instance or class - !S.CheckParamString(2) || - !S.CheckParamEnd(3) - ) + // Returns a map of (SafeTitle -> Title) for the plugin's web tabs. + auto self = reinterpret_cast<cWebPlugin *>(tolua_tousertype(tolua_S, 1, nullptr)); + auto TabNames = self->GetTabNames(); + lua_newtable(tolua_S); + int index = 1; + for (auto itr = TabNames.cbegin(), end = TabNames.cend(); itr != end; ++itr) { - return 0; + tolua_pushstring(tolua_S, itr->second.c_str()); // Because the SafeTitle is supposed to be unique, use it as key + tolua_pushstring(tolua_S, itr->first.c_str()); + lua_rawset(tolua_S, -3); + ++index; } - - // Get the parameters: - AString Input; - S.GetStackValue(2, Input); - - // Convert and return: - S.Push(cWebAdmin::GetURLEncodedString(Input)); return 1; } @@ -2739,79 +2623,6 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S) -static int tolua_cLuaWindow_new(lua_State * tolua_S) -{ - // Function signature: - // cLuaWindow:new(type, slotsX, slotsY, title) - - // Check params: - cLuaState L(tolua_S); - if ( - !L.CheckParamUserTable(1, "cLuaWindow") || - !L.CheckParamNumber(2, 4) || - !L.CheckParamString(5) || - !L.CheckParamEnd(6) - ) - { - return 0; - } - - // Read params: - int windowType, slotsX, slotsY; - AString title; - if (!L.GetStackValues(2, windowType, slotsX, slotsY, title)) - { - LOGWARNING("%s: Cannot read Lua parameters", __FUNCTION__); - L.LogStackValues(); - L.LogStackTrace(); - } - - // Create the window and return it: - L.Push(new cLuaWindow(L, static_cast<cLuaWindow::WindowType>(windowType), slotsX, slotsY, title)); - return 1; -} - - - - - -static int tolua_cLuaWindow_new_local(lua_State * tolua_S) -{ - // Function signature: - // cLuaWindow:new(type, slotsX, slotsY, title) - - // Check params: - cLuaState L(tolua_S); - if ( - !L.CheckParamUserTable(1, "cLuaWindow") || - !L.CheckParamNumber(2, 4) || - !L.CheckParamString(5) || - !L.CheckParamEnd(6) - ) - { - return 0; - } - - // Read params: - int windowType, slotsX, slotsY; - AString title; - if (!L.GetStackValues(2, windowType, slotsX, slotsY, title)) - { - LOGWARNING("%s: Cannot read Lua parameters", __FUNCTION__); - L.LogStackValues(); - L.LogStackTrace(); - } - - // Create the window, register it for GC and return it: - L.Push(new cLuaWindow(L, static_cast<cLuaWindow::WindowType>(windowType), slotsX, slotsY, title)); - tolua_register_gc(tolua_S, lua_gettop(tolua_S)); - return 1; -} - - - - - static int tolua_cRoot_GetBuildCommitID(lua_State * tolua_S) { cLuaState L(tolua_S); @@ -3655,9 +3466,6 @@ void cManualBindings::Bind(lua_State * tolua_S) tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cLuaWindow"); - tolua_function(tolua_S, "new", tolua_cLuaWindow_new); - tolua_function(tolua_S, "new_local", tolua_cLuaWindow_new_local); - tolua_function(tolua_S, ".call", tolua_cLuaWindow_new_local); tolua_function(tolua_S, "SetOnClosing", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnClosing>); tolua_function(tolua_S, "SetOnSlotChanged", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnSlotChanged>); tolua_endmodule(tolua_S); @@ -3678,6 +3486,7 @@ void cManualBindings::Bind(lua_State * tolua_S) tolua_beginmodule(tolua_S, "cPlayer"); tolua_function(tolua_S, "GetPermissions", tolua_cPlayer_GetPermissions); tolua_function(tolua_S, "GetRestrictions", tolua_cPlayer_GetRestrictions); + tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow); tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches); tolua_endmodule(tolua_S); @@ -3741,13 +3550,13 @@ void cManualBindings::Bind(lua_State * tolua_S) tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cWebAdmin"); - tolua_function(tolua_S, "AddWebTab", tolua_cWebAdmin_AddWebTab); - tolua_function(tolua_S, "GetAllWebTabs", tolua_cWebAdmin_GetAllWebTabs); - tolua_function(tolua_S, "GetBaseURL", tolua_cWebAdmin_GetBaseURL); - tolua_function(tolua_S, "GetContentTypeFromFileExt", tolua_cWebAdmin_GetContentTypeFromFileExt); - tolua_function(tolua_S, "GetHTMLEscapedString", tolua_cWebAdmin_GetHTMLEscapedString); - tolua_function(tolua_S, "GetPage", tolua_cWebAdmin_GetPage); - tolua_function(tolua_S, "GetURLEncodedString", tolua_cWebAdmin_GetURLEncodedString); + tolua_function(tolua_S, "GetHTMLEscapedString", tolua_AllToLua_cWebAdmin_GetHTMLEscapedString); + tolua_function(tolua_S, "GetPlugins", tolua_cWebAdmin_GetPlugins); + tolua_function(tolua_S, "GetURLEncodedString", tolua_AllToLua_cWebAdmin_GetURLEncodedString); + tolua_endmodule(tolua_S); + + tolua_beginmodule(tolua_S, "cWebPlugin"); + tolua_function(tolua_S, "GetTabNames", tolua_cWebPlugin_GetTabNames); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "HTTPRequest"); |