#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ManualBindings.h" #undef TOLUA_TEMPLATE_BIND #include #include #include "tolua++/include/tolua++.h" #include "mbedtls/md5.h" #include "mbedtls/sha1.h" #include "PluginLua.h" #include "PluginManager.h" #include "LuaWindow.h" #include "../BlockArea.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/BrewingstandEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../BoundingBox.h" #include "BuildInfo.h" #include "../ClientHandle.h" #include "../CommandOutput.h" #include "../CompositeChat.h" #include "../Entities/Player.h" #include "../Generating/ChunkDesc.h" #include "../HTTP/UrlParser.h" #include "../Item.h" #include "../LineBlockTracer.h" #include "../Server.h" #include "../Root.h" #include "../StringCompression.h" #include "../WebAdmin.h" #include "../World.h" // Hotpatching the Macro to prevent a Clang Warning (0 for pointer used) #undef lua_tostring #define lua_tostring(L, i) lua_tolstring(L, (i), nullptr) //////////////////////////////////////////////////////////////////////////////// // LuaCommandHandler: /** Defines a bridge between cPluginManager::cCommandHandler and cLuaState::cCallback. */ class LuaCommandHandler : public cPluginManager::cCommandHandler { public: LuaCommandHandler(cLuaState::cCallbackPtr && a_Callback) : m_Callback(std::move(a_Callback)) { } virtual bool ExecuteCommand( const AStringVector & a_Split, cPlayer * a_Player, const AString & a_Command, cCommandOutputCallback * a_Output ) override { bool res = false; AString s; if (!m_Callback->Call(a_Split, a_Player, a_Command, cLuaState::Return, res, s)) { return false; } if (res && (a_Output != nullptr) && !s.empty()) { a_Output->Out(s); } return res; } protected: cLuaState::cCallbackPtr m_Callback; }; //////////////////////////////////////////////////////////////////////////////// // cManualBindings: // Better error reporting for Lua int cManualBindings::tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError) { // Retrieve current function name lua_Debug entry; VERIFY(lua_getstack(L, 0, &entry)); VERIFY(lua_getinfo(L, "n", &entry)); // Insert function name into error msg AString msg(a_pMsg); ReplaceString(msg, "#funcname#", entry.name ? entry.name : "?"); // Send the error to Lua tolua_error(L, msg.c_str(), a_pToLuaError); return 0; } int cManualBindings::vlua_do_error(lua_State * L, const char * a_pFormat, fmt::printf_args a_ArgList) { // Retrieve current function name lua_Debug entry; VERIFY(lua_getstack(L, 0, &entry)); VERIFY(lua_getinfo(L, "n", &entry)); // Insert function name into error msg AString msg(a_pFormat); ReplaceString(msg, "#funcname#", (entry.name != nullptr) ? entry.name : "?"); // Copied from luaL_error and modified luaL_where(L, 1); auto Msg = fmt::vsprintf(msg, a_ArgList); lua_pushlstring(L, Msg.data(), Msg.size()); lua_concat(L, 2); return lua_error(L); } // Lua bound functions with special return types static int tolua_Clamp(lua_State * tolua_S) { cLuaState LuaState(tolua_S); int NumArgs = lua_gettop(LuaState); if (NumArgs != 3) { return cManualBindings::lua_do_error( LuaState, "Error in function call '#funcname#': Requires 3 arguments, got %i", NumArgs ); } if (!lua_isnumber(LuaState, 1) || !lua_isnumber(LuaState, 2) || !lua_isnumber(LuaState, 3)) { return cManualBindings::lua_do_error( LuaState, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3" ); } lua_Number Number = tolua_tonumber(LuaState, 1, 0); lua_Number Min = tolua_tonumber(LuaState, 2, 0); lua_Number Max = tolua_tonumber(LuaState, 3, 0); lua_Number Result = Clamp(Number, Min, Max); LuaState.Push(Result); return 1; } static int tolua_CompressStringZLIB(lua_State * tolua_S) { cLuaState S(tolua_S); if (!S.CheckParamString(1) || (!S.CheckParamNumber(2) && !S.CheckParamEnd(2))) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: AString ToCompress; int CompressionLevel = 5; S.GetStackValues(1, ToCompress, CompressionLevel); // Compress the string: S.Push(Compression::Compressor(CompressionLevel).CompressZLib(ToCompress.data(), ToCompress.size()).GetView()); return 1; } static int tolua_UncompressStringZLIB(lua_State * tolua_S) { cLuaState S(tolua_S); if (!S.CheckParamString(1) || !S.CheckParamNumber(2)) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToUncompress; size_t UncompressedSize = 0; S.GetStackValues(1, ToUncompress, UncompressedSize); try { // Decompress the string: S.Push(Compression::Extractor().ExtractZLib(ToUncompress, UncompressedSize).GetView()); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); cLuaState::LogStackTrace(tolua_S); return 0; } return 1; } static int tolua_CompressStringGZIP(lua_State * tolua_S) { cLuaState S(tolua_S); if (!S.CheckParamString(1) || !S.CheckParamEnd(2)) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToCompress; S.GetStackValues(1, ToCompress); // Compress the string: S.Push(Compression::Compressor().CompressGZip(ToCompress).GetView()); return 1; } static int tolua_InflateString(lua_State * tolua_S) { cLuaState S(tolua_S); if (!S.CheckParamString(1) || !S.CheckParamEnd(2)) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToUncompress; S.GetStackValues(1, ToUncompress); try { // Decompress the string: S.Push(Compression::Extractor().ExtractZLib(ToUncompress).GetView()); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); cLuaState::LogStackTrace(tolua_S); return 0; } return 1; } static int tolua_StringSplit(lua_State * tolua_S) { // Get the params: cLuaState LuaState(tolua_S); AString str, delim; LuaState.GetStackValues(1, str, delim); // Execute and push the result: LuaState.Push(StringSplit(str, delim)); return 1; } static int tolua_StringSplitWithQuotes(lua_State * tolua_S) { cLuaState S(tolua_S); AString str; AString delim; S.GetStackValues(1, str, delim); AStringVector Split = StringSplitWithQuotes(str, delim); S.Push(Split); return 1; } static int tolua_StringSplitAndTrim(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamString(1, 2) || !L.CheckParamEnd(3)) { return 0; } // Process: AString str, delim; L.GetStackValues(1, str, delim); L.Push(StringSplitAndTrim(str, delim)); return 1; } /** Prints the message to the console, optionally formatting it with a plugin name prefix if the second param on the Lua * stack is true. */ static void LogFromLuaStack(lua_State * tolua_S, const std::string_view a_Message, const eLogLevel a_LogLevel) { if (lua_isboolean(tolua_S, 2) && (lua_toboolean(tolua_S, 2) == 1)) { Logger::LogSimple(a_Message, a_LogLevel); } else { Logger::LogSimple( fmt::format("[{}] {}", cManualBindings::GetLuaPlugin(tolua_S)->GetName(), a_Message), a_LogLevel ); } } /** Retrieves a string log message from the first param on the Lua stack, optionally prefixes it with plugin name, and * prints it to the console. */ static void LogFromLuaStack(lua_State * tolua_S, const eLogLevel a_LogLevel) { cLuaState L(tolua_S); // If there's no param, spit out an error message instead of crashing: if (!L.CheckParamString(1)) { return; } std::string_view Message; L.GetStackValue(1, Message); LogFromLuaStack(tolua_S, Message, a_LogLevel); } static int tolua_LOG(lua_State * tolua_S) { // If the param is a cCompositeChat, read the data from it: tolua_Error err; if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err)) { const auto CompositeChat = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (CompositeChat != nullptr) // isusertype returns true for nil values { LogFromLuaStack( tolua_S, CompositeChat->ExtractText(), cCompositeChat::MessageTypeToLogLevel(CompositeChat->GetMessageType()) ); return 0; } } // Log the message: LogFromLuaStack(tolua_S, eLogLevel::Regular); return 0; } static int tolua_LOGINFO(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Info); return 0; } static int tolua_LOGWARN(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Warning); return 0; } static int tolua_LOGERROR(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Error); return 0; } static int tolua_Base64Encode(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamString(1) || !L.CheckParamEnd(2)) { return 0; } AString Src; L.GetStackValue(1, Src); AString res = Base64Encode(Src); L.Push(res); return 1; } static int tolua_Base64Decode(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamString(1) || !L.CheckParamEnd(2)) { return 0; } AString Src; L.GetStackValue(1, Src); AString res = Base64Decode(Src); L.Push(res); return 1; } cPluginLua * cManualBindings::GetLuaPlugin(lua_State * L) { // Get the plugin identification out of LuaState: lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME); if (!lua_islightuserdata(L, -1)) { LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__); lua_pop(L, 1); return nullptr; } cPluginLua * Plugin = static_cast(const_cast(lua_topointer(L, -1))); lua_pop(L, 1); return Plugin; } static int tolua_cFile_ChangeFileExt(lua_State * tolua_S) { // API signature: // ChangeFileExt(string, string) -> string // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4)) { return 0; } // Execute: AString FileName, NewExt; VERIFY(L.GetStackValues(2, FileName, NewExt)); L.Push(cFile::ChangeFileExt(FileName, NewExt)); return 1; } static int tolua_cFile_Copy(lua_State * tolua_S) { // API signature: // cFile:Copy(string, string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4)) { return 0; } // Execute: AString SrcFile, DstFile; VERIFY(L.GetStackValues(2, SrcFile, DstFile)); L.Push(cFile::Copy(SrcFile, DstFile)); return 1; } static int tolua_cFile_CreateFolder(lua_State * tolua_S) { // API signature: // cFile:CreateFolder(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString FolderPath; VERIFY(L.GetStackValues(2, FolderPath)); L.Push(cFile::CreateFolder(FolderPath)); return 1; } static int tolua_cFile_CreateFolderRecursive(lua_State * tolua_S) { // API signature: // cFile:CreateFolderRecursive(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString FolderPath; VERIFY(L.GetStackValues(2, FolderPath)); L.Push(cFile::CreateFolderRecursive(FolderPath)); return 1; } static int tolua_cFile_Delete(lua_State * tolua_S) { // API signature: // cFile:Delete(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::Delete(Path)); return 1; } static int tolua_cFile_DeleteFile(lua_State * tolua_S) { // API signature: // cFile:DeleteFile(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFile(Path)); return 1; } static int tolua_cFile_DeleteFolder(lua_State * tolua_S) { // API signature: // cFile:DeleteFolder(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFolder(Path)); return 1; } static int tolua_cFile_DeleteFolderContents(lua_State * tolua_S) { // API signature: // cFile:DeleteFolderContents(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFolderContents(Path)); return 1; } static int tolua_cFile_Exists(lua_State * tolua_S) { // API signature: // cFile:Exists(string) -> bool // Obsolete, use IsFile() or IsFolder() instead cLuaState L(tolua_S); LOGWARNING("cFile:Exists() is obsolete, use cFile:IsFolder() or cFile:IsFile() instead!"); L.LogStackTrace(); // Check params: if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::Exists(Path)); return 1; } static int tolua_cFile_GetFolderContents(lua_State * tolua_S) { // API signature: // cFile:GetFolderContents(string) -> {string, string, ...} // Check params: cLuaState LuaState(tolua_S); if (!LuaState.CheckParamUserTable(1, "cFile") || !LuaState.CheckParamString(2) || !LuaState.CheckParamEnd(3)) { return 0; } // Get params: AString Folder; VERIFY(LuaState.GetStackValues(2, Folder)); // Execute and push result: LuaState.Push(cFile::GetFolderContents(Folder)); return 1; } static int tolua_cFile_GetLastModificationTime(lua_State * tolua_S) { // API signature: // cFile:GetLastModificationTime(string) -> number // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::GetLastModificationTime(Path)); return 1; } static int tolua_cFile_GetSize(lua_State * tolua_S) { // API signature: // cFile:GetSize(string) -> number // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::GetSize(Path)); return 1; } static int tolua_cFile_IsFile(lua_State * tolua_S) { // API signature: // cFile:IsFile(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::IsFile(Path)); return 1; } static int tolua_cFile_IsFolder(lua_State * tolua_S) { // API signature: // cFile:IsFolder(string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::IsFolder(Path)); return 1; } static int tolua_cFile_ReadWholeFile(lua_State * tolua_S) { // API signature: // cFile:ReadWholeFile(string) -> string // Check params: cLuaState LuaState(tolua_S); if (!LuaState.CheckParamUserTable(1, "cFile") || !LuaState.CheckParamString(2) || !LuaState.CheckParamEnd(3)) { return 0; } // Get params: AString FileName; VERIFY(LuaState.GetStackValues(2, FileName)); // Execute and push result: LuaState.Push(cFile::ReadWholeFile(FileName)); return 1; } static int tolua_cFile_Rename(lua_State * tolua_S) { // API signature: // cFile:Rename(string, string) -> bool // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4)) { return 0; } // Execute: AString SrcPath, DstPath; VERIFY(L.GetStackValues(2, SrcPath, DstPath)); L.Push(cFile::Rename(SrcPath, DstPath)); return 1; } static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S) { // API function no longer available: LOGWARNING("cPluginManager:GetAllPlugins() is no longer available, use cPluginManager:ForEachPlugin() instead"); cLuaState::LogStackTrace(tolua_S); // Return an empty table: lua_newtable(tolua_S); return 1; } static int tolua_cPluginManager_GetCurrentPlugin(lua_State * S) { cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S); if (Plugin == nullptr) { // An error message has already been printed in GetLuaPlugin() return 0; } tolua_pushusertype(S, Plugin, "cPluginLua"); return 1; } static int tolua_cPluginManager_GetPlugin(lua_State * tolua_S) { // API function no longer available: LOGWARNING("cPluginManager:GetPlugin() is no longer available. Use cPluginManager:DoWithPlugin() or " "cPluginManager:CallPlugin() instead."); cLuaState::LogStackTrace(tolua_S); return 0; } static int tolua_cPluginManager_LogStackTrace(lua_State * S) { cLuaState::LogStackTrace(S); return 0; } static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx) { // Helper function for cPluginmanager:AddHook() binding // Takes care of the new case (#121): args are HOOK_TYPE and CallbackFunction // The arg types have already been checked // Retrieve the cPlugin from the LuaState: cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S); if (Plugin == nullptr) { // An error message has been already printed in GetLuaPlugin() return 0; } // 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; } if (!a_PluginManager->IsValidHookType(HookType)) { LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType); S.LogStackTrace(); return 0; } // Add the hook to the plugin cLuaState::cCallbackPtr callback; if (!S.GetStackValue(a_ParamIdx + 1, callback)) { LOGWARNING("cPluginManager.AddHook(): Cannot read the callback parameter"); S.LogStackTrace(); return 0; } if (!Plugin->AddHookCallback(HookType, std::move(callback))) { LOGWARNING("cPluginManager.AddHook(): Cannot add hook %d, unknown error.", HookType); S.LogStackTrace(); return 0; } a_PluginManager->AddHook(Plugin, HookType); // Success return 0; } static int tolua_cPluginManager_AddHook_DefFn(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx) { // Helper function for cPluginmanager:AddHook() binding // Takes care of the old case (#121): args are cPluginLua and HOOK_TYPE // The arg types have already been checked // Retrieve and check the cPlugin parameter cPluginLua * Plugin = static_cast(tolua_tousertype(S, a_ParamIdx, nullptr)); if (Plugin == nullptr) { LOGWARNING("cPluginManager.AddHook(): Invalid Plugin parameter, expected a valid cPlugin object. Hook not added" ); S.LogStackTrace(); return 0; } if (Plugin != cManualBindings::GetLuaPlugin(S)) { // The plugin parameter passed to us is not our stored plugin. Disallow this! LOGWARNING( "cPluginManager.AddHook(): Invalid Plugin parameter, cannot add hook to foreign plugins. Hook not added." ); S.LogStackTrace(); return 0; } // Retrieve and check the hook type int HookType = static_cast(tolua_tonumber(S, a_ParamIdx + 1, -1)); if (!a_PluginManager->IsValidHookType(HookType)) { LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType); S.LogStackTrace(); return 0; } // Get the standard name for the callback function: const char * FnName = cPluginLua::GetHookFnName(HookType); if (FnName == nullptr) { LOGWARNING("cPluginManager.AddHook(): Unknown hook type (%d). Hook not added.", HookType); S.LogStackTrace(); return 0; } // Retrieve the function to call and add it to the plugin: cLuaState::cCallbackPtr callback; lua_getglobal(S, FnName); bool res = S.GetStackValue(-1, callback); lua_pop(S, 1); if (!res || !callback->IsValid()) { LOGWARNING("cPluginManager.AddHook(): Function %s not found. Hook not added.", FnName); S.LogStackTrace(); return 0; } a_PluginManager->AddHook(Plugin, HookType); // Success return 0; } static int tolua_cPluginManager_AddHook(lua_State * tolua_S) { /* Function signatures: cPluginManager:AddHook(HOOK_TYPE, CallbackFunction) -- (1) recommended cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) -- (2) accepted silently (#401 deprecates this) cPluginManager:Get():AddHook(HOOK_TYPE, CallbackFunction) -- (3) accepted silently cPluginManager:Get():AddHook(Plugin, HOOK_TYPE) -- (4) old style (#121), accepted but complained about in the console cPluginManager.AddHook(Plugin, HOOK_TYPE) -- (5) old style (#121) mangled, accepted but complained about in the console */ cLuaState S(tolua_S); cPluginManager * PlgMgr = cPluginManager::Get(); // If the first param is a cPluginManager instance, use it instead of the global one: int ParamIdx = 1; tolua_Error err; if (tolua_isusertype(S, 1, "cPluginManager", 0, &err)) { // Style 2 or 3, retrieve the PlgMgr instance PlgMgr = static_cast(tolua_tousertype(S, 1, nullptr)); if (PlgMgr == nullptr) { LOGWARNING( "Malformed plugin, use cPluginManager.AddHook(HOOK_TYPE, CallbackFunction). Fixing the call for you." ); S.LogStackTrace(); PlgMgr = cPluginManager::Get(); } ParamIdx += 1; } else if (tolua_isusertable(S, 1, "cPluginManager", 0, &err)) { // Style 1, use the global PlgMgr, but increment ParamIdx ParamIdx++; } if (lua_isnumber(S, ParamIdx) && lua_isfunction(S, ParamIdx + 1)) { // The next params are a number and a function, assume style 1 or 2 return tolua_cPluginManager_AddHook_FnRef(PlgMgr, S, ParamIdx); } else if (tolua_isusertype(S, ParamIdx, "cPlugin", 0, &err) && lua_isnumber(S, ParamIdx + 1)) { // The next params are a cPlugin and a number, assume style 3 or 4 LOGINFO("cPluginManager.AddHook(): Deprecated format used, use cPluginManager.AddHook(HOOK_TYPE, " "CallbackFunction) instead. Fixing the call for you."); S.LogStackTrace(); return tolua_cPluginManager_AddHook_DefFn(PlgMgr, S, ParamIdx); } auto ParamDesc = fmt::format(FMT_STRING("{}, {}, {}"), S.GetTypeText(1), S.GetTypeText(2), S.GetTypeText(3)); LOGWARNING( "cPluginManager:AddHook(): bad parameters. Expected HOOK_TYPE and CallbackFunction, got %s. Hook not added.", ParamDesc ); S.LogStackTrace(); return 0; } static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:Get():ForEachCommand(a_CallbackFn) -> bool */ // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cPluginManager") || !L.CheckParamFunction(2) || !L.CheckParamEnd(3)) { return 0; } // Get the params: cLuaState::cRef FnRef; L.GetStackValues(2, FnRef); if (!FnRef.IsValid()) { LOGWARN("Error in function call 'ForEachCommand': Could not get function reference of parameter #1"); return 0; } // Callback for enumerating all commands: class cLuaCallback : public cPluginManager::cCommandEnumCallback { public: cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef) : m_LuaState(a_LuaState), m_FnRef(a_FnRef) { } private: virtual bool Command( const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString ) override { UNUSED(a_Plugin); bool ret = false; m_LuaState.Call(m_FnRef, a_Command, a_Permission, a_HelpString, cLuaState::Return, ret); return ret; } cLuaState & m_LuaState; cLuaState::cRef & m_FnRef; } Callback(L, FnRef); // Execute and push the returned value: L.Push(cPluginManager::Get()->ForEachCommand(Callback)); return 1; } static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:Get():ForEachConsoleCommand(a_CallbackFn) -> bool */ // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cPluginManager") || !L.CheckParamFunction(2) || !L.CheckParamEnd(3)) { return 0; } // Get the params: cLuaState::cRef FnRef; L.GetStackValues(2, FnRef); if (!FnRef.IsValid()) { LOGWARN("Error in function call 'ForEachConsoleCommand': Could not get function reference of parameter #1"); return 0; } // Callback for enumerating all commands: class cLuaCallback : public cPluginManager::cCommandEnumCallback { public: cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef) : m_LuaState(a_LuaState), m_FnRef(a_FnRef) { } private: virtual bool Command( const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString ) override { UNUSED(a_Plugin); UNUSED(a_Permission); bool ret = false; m_LuaState.Call(m_FnRef, a_Command, a_HelpString, cLuaState::Return, ret); return ret; } cLuaState & m_LuaState; cLuaState::cRef & m_FnRef; } Callback(L, FnRef); // Execute and push the returned value: L.Push(cPluginManager::Get()->ForEachConsoleCommand(Callback)); return 1; } static int tolua_cPluginManager_BindCommand(lua_State * a_LuaState) { /* Function signatures: cPluginManager:Get():BindCommand(Command, Permission, Function, HelpString) -- regular cPluginManager:BindCommand(Command, Permission, Function, HelpString) -- static cPluginManager.BindCommand(Command, Permission, Function, HelpString) -- without the "self" param */ cLuaState L(a_LuaState); cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L); if (Plugin == nullptr) { return 0; } // Read the arguments to this API call: tolua_Error tolua_err; int idx = 1; if (tolua_isusertype(L, 1, "cPluginManager", 0, &tolua_err) || tolua_isusertable(L, 1, "cPluginManager", 0, &tolua_err)) { idx++; } if (!tolua_iscppstring(L, idx, 0, &tolua_err) || !tolua_iscppstring(L, idx + 1, 0, &tolua_err) || !tolua_iscppstring(L, idx + 3, 0, &tolua_err) || !tolua_isnoobj(L, idx + 4, &tolua_err)) { tolua_error(L, "#ferror in function 'BindCommand'.", &tolua_err); return 0; } if (!lua_isfunction(L, idx + 2)) { luaL_error(L, "\"BindCommand\" function expects a function as its 3rd parameter. Command-binding aborted."); return 0; } cPluginManager * self = cPluginManager::Get(); AString Command, Permission, HelpString; cLuaState::cCallbackPtr Handler; L.GetStackValues(idx, Command, Permission, Handler, HelpString); if (!Handler->IsValid()) { LOGERROR("\"BindCommand\": Cannot create a function reference. Command \"%s\" not bound.", Command.c_str()); return 0; } auto CommandHandler = std::make_shared(std::move(Handler)); if (!self->BindCommand(Command, Plugin, CommandHandler, Permission, HelpString)) { // Refused. Possibly already bound. Error message has been given, display the callstack: L.LogStackTrace(); return 0; } L.Push(true); return 1; } static int tolua_cPluginManager_BindConsoleCommand(lua_State * a_LuaState) { /* Function signatures: cPluginManager:Get():BindConsoleCommand(Command, Function, HelpString) -- regular cPluginManager:BindConsoleCommand(Command, Function, HelpString) -- static cPluginManager.BindConsoleCommand(Command, Function, HelpString) -- without the "self" param */ // Get the plugin identification out of LuaState: cLuaState L(a_LuaState); cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L); if (Plugin == nullptr) { return 0; } // Read the arguments to this API call: tolua_Error tolua_err; int idx = 1; if (tolua_isusertype(L, 1, "cPluginManager", 0, &tolua_err) || tolua_isusertable(L, 1, "cPluginManager", 0, &tolua_err)) { idx++; } if (!tolua_iscppstring(L, idx, 0, &tolua_err) || // Command !tolua_iscppstring(L, idx + 2, 0, &tolua_err) || // HelpString !tolua_isnoobj(L, idx + 3, &tolua_err)) { tolua_error(L, "#ferror in function 'BindConsoleCommand'.", &tolua_err); return 0; } if (!lua_isfunction(L, idx + 1)) { luaL_error( L, "\"BindConsoleCommand\" function expects a function as its 2nd parameter. Command-binding aborted." ); return 0; } cPluginManager * self = cPluginManager::Get(); AString Command, HelpString; cLuaState::cCallbackPtr Handler; L.GetStackValues(idx, Command, Handler, HelpString); if (!Handler->IsValid()) { LOGERROR( "\"BindConsoleCommand\": Cannot create a function reference. Console command \"%s\" not bound.", Command.c_str() ); return 0; } auto CommandHandler = std::make_shared(std::move(Handler)); if (!self->BindConsoleCommand(Command, Plugin, CommandHandler, HelpString)) { // Refused. Possibly already bound. Error message has been given, display the callstack: L.LogStackTrace(); return 0; } L.Push(true); return 1; } static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S) { /* Function signature: cPluginManager:CallPlugin("PluginName", "FunctionName", args...) */ // Check the parameters: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cPluginManager") || !L.CheckParamString(2, 3)) { return 0; } // Retrieve the plugin name and function name AString PluginName, FunctionName; L.ToString(2, PluginName); L.ToString(3, FunctionName); if (PluginName.empty() || FunctionName.empty()) { LOGWARNING("cPluginManager:CallPlugin(): Invalid plugin name or function name"); L.LogStackTrace(); return 0; } // If requesting calling the current plugin, refuse: cPluginLua * ThisPlugin = cManualBindings::GetLuaPlugin(L); if (ThisPlugin == nullptr) { return 0; } if (ThisPlugin->GetName() == PluginName) { LOGWARNING("cPluginManager::CallPlugin(): Calling self is not implemented (why would it?)"); L.LogStackTrace(); return 0; } // Call the destination plugin using a plugin callback: int NumReturns = 0; auto PluginCallback = [&](cPlugin & a_Plugin) { if (!a_Plugin.IsLoaded()) { return false; } NumReturns = static_cast(a_Plugin).CallFunctionFromForeignState(FunctionName, L, 4, lua_gettop(L)); return true; }; if (!cPluginManager::Get()->DoWithPlugin(PluginName, PluginCallback)) { return 0; } if (NumReturns < 0) { // The call has failed, there are zero return values. Do NOT return negative number (Lua considers that a // "yield") return 0; } return NumReturns; } static int tolua_cPluginManager_ExecuteConsoleCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:ExecuteConsoleCommand(EntireCommandStr) -> OutputString */ // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cPluginManager") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Get the params: AString Command; L.GetStackValues(2, Command); auto Split = StringSplit(Command, " "); // Store the command output in a string: cStringAccumCommandOutputCallback CommandOutput; L.Push(cPluginManager::Get()->ExecuteConsoleCommand(Split, CommandOutput, Command)); L.Push(CommandOutput.GetAccum()); return 2; } static int tolua_cPluginManager_FindPlugins(lua_State * tolua_S) { // API function no longer exists: LOGWARNING("cPluginManager:FindPlugins() is obsolete, use cPluginManager:RefreshPluginList() instead!"); cLuaState::LogStackTrace(tolua_S); // Still, do the actual work performed by the API function when it existed: cPluginManager::Get()->RefreshPluginList(); return 0; } static int tolua_cPlayer_GetPermissions(lua_State * tolua_S) { // Function signature: cPlayer:GetPermissions() -> {permissions-array} // Check the params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cPlayer") || !L.CheckParamEnd(2)) { return 0; } // Get the params: cPlayer * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } // Push the permissions: L.Push(self->GetPermissions()); return 1; } static int tolua_cPlayer_GetRestrictions(lua_State * tolua_S) { // Function signature: cPlayer:GetRestrictions() -> {restrictions-array} // Check the params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cPlayer") || !L.CheckParamEnd(2)) { return 0; } // Get the params: cPlayer * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } // Push the permissions: L.Push(self->GetRestrictions()); return 1; } static int tolua_cPlayer_GetUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cPlayer")) { return 0; } // Get the params: cPlayer * Self = nullptr; L.GetStackValue(1, Self); // Return the UUID as a string L.Push(Self->GetUUID().ToShortString()); return 1; } static int tolua_cPlayer_PlaceBlock(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cPlayer") || !L.CheckParamUserType(2, "Vector3") || !L.CheckParamNumber(3, 4) || !L.CheckParamEnd(5)) { return 0; } // Get the params: cPlayer * Self; Vector3i Position; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; L.GetStackValues(1, Self, Position, BlockType, BlockMeta); if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } // Return the result of placement: L.Push(Self->PlaceBlock(Position, BlockType, BlockMeta)); return 1; } static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S) { // Function signature: cPlayer:PermissionMatches(PermissionStr, TemplateStr) -> bool // Check the params: cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cPlayer") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4)) { return 0; } // Get the params: AString Permission, Template; L.GetStackValues(2, Permission, Template); // Push the result of the match: L.Push(cPlayer::PermissionMatches(StringSplit(Permission, "."), StringSplit(Template, "."))); return 1; } template static int tolua_SetObjectCallback(lua_State * tolua_S) { // Function signature: OBJTYPE:SetWhateverCallback(CallbackFunction) // Get the parameters - self and the function reference: cLuaState L(tolua_S); OBJTYPE * self; cLuaState::cCallbackPtr callback; if (!L.GetStackValues(1, self, callback)) { LOGWARNING("%s: Cannot get parameters", __FUNCTION__); L.LogStackTrace(); return 0; } // Set the callback (self->*SetCallback)(std::move(callback)); return 0; } // Callback class used for the WebTab: class cWebTabCallback : public cWebAdmin::cWebTabCallback { public: /** The Lua callback to call to generate the page contents. */ cLuaState::cCallback m_Callback; virtual bool Call( const HTTPRequest & a_Request, const AString & a_UrlPath, AString & a_Content, AString & a_ContentType ) override { AString content, contentType; return m_Callback .Call(const_cast(&a_Request), a_UrlPath, cLuaState::Return, a_Content, a_ContentType); } }; 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 // Check params: cLuaState LuaState(tolua_S); cPluginLua * self = cManualBindings::GetLuaPlugin(tolua_S); if (self == nullptr) { return 0; } if (!LuaState.CheckParamString(2) || !LuaState.CheckParamFunction(3) || // Optional string as param 4 !LuaState.CheckParamEnd(5)) { return 0; } // Read the params: AString title, urlPath; auto callback = std::make_shared(); if (!LuaState.GetStackValues(2, title, callback->m_Callback)) { LOGWARNING("cPlugin:AddWebTab(): Cannot read required parameters"); return 0; } if (!LuaState.GetStackValue(4, urlPath)) { urlPath = cWebAdmin::GetURLEncodedString(title); } cRoot::Get()->GetWebAdmin()->AddWebTab(title, urlPath, self->GetName(), callback); return 0; } static int tolua_cPlugin_GetDirectory(lua_State * tolua_S) { cLuaState L(tolua_S); // Log the obsoletion warning: LOGWARNING("cPlugin:GetDirectory() is obsolete, use cPlugin:GetFolderName() instead."); L.LogStackTrace(); // Retrieve the params: cPlugin * Plugin = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); // Get the folder name: L.Push(Plugin->GetFolderName()); return 1; } static int tolua_cPlugin_GetLocalDirectory(lua_State * tolua_S) { cLuaState L(tolua_S); // Log the obsoletion warning: LOGWARNING("cPlugin:GetLocalDirectory() is obsolete, use cPlugin:GetLocalFolder() instead."); L.LogStackTrace(); // Retrieve the params: cPlugin * Plugin = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); // Get the folder: L.Push(Plugin->GetLocalFolder()); return 1; } static int tolua_md5(lua_State * tolua_S) { // Calculate the raw md5 checksum byte array: unsigned char Output[16]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_md5(SourceString, len, Output); lua_pushlstring(tolua_S, reinterpret_cast(Output), ARRAYCOUNT(Output)); return 1; } /** Does the same as tolua_md5, but reports that the usage is obsolete and the plugin should use cCrypto.md5(). */ static int tolua_md5_obsolete(lua_State * tolua_S) { LOGWARNING("Using md5() is obsolete, please change your plugin to use cCryptoHash.md5()"); cLuaState::LogStackTrace(tolua_S); return tolua_md5(tolua_S); } static int tolua_md5HexString(lua_State * tolua_S) { // Calculate the raw md5 checksum byte array: unsigned char md5Output[16]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_md5(SourceString, len, md5Output); // Convert the md5 checksum to hex string: std::stringstream Output; Output << std::hex << std::setfill('0'); for (size_t i = 0; i < ARRAYCOUNT(md5Output); i++) { Output << std::setw(2) << static_cast(md5Output[i]); // Need to cast to a number, otherwise a char is output } lua_pushlstring(tolua_S, Output.str().c_str(), Output.str().size()); return 1; } static int tolua_sha1(lua_State * tolua_S) { // Calculate the raw SHA1 checksum byte array from the input string: unsigned char Output[20]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_sha1(SourceString, len, Output); lua_pushlstring(tolua_S, reinterpret_cast(Output), ARRAYCOUNT(Output)); return 1; } static int tolua_sha1HexString(lua_State * tolua_S) { // Calculate the raw SHA1 checksum byte array from the input string: unsigned char sha1Output[20]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_sha1(SourceString, len, sha1Output); // Convert the sha1 checksum to hex string: std::stringstream Output; Output << std::hex << std::setfill('0'); for (size_t i = 0; i < ARRAYCOUNT(sha1Output); i++) { Output << std::setw(2) << static_cast(sha1Output[i]); // Need to cast to a number, otherwise a char is output } lua_pushlstring(tolua_S, Output.str().c_str(), Output.str().size()); return 1; } static int tolua_get_HTTPRequest_Params(lua_State * a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } L.Push(self->Params); return 1; } static int tolua_get_HTTPRequest_PostParams(lua_State * a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } L.Push(self->PostParams); return 1; } static int tolua_get_HTTPRequest_FormData(lua_State * a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } auto & FormData = self->FormData; lua_newtable(a_LuaState); int top = lua_gettop(a_LuaState); for (auto & Data : FormData) { lua_pushstring(a_LuaState, Data.first.c_str()); tolua_pushusertype(a_LuaState, &Data.second, "HTTPFormData"); // lua_pushlstring(a_LuaState, Data.second.Value.c_str(), Data.second.Value.size()); // Might contain binary // data lua_settable(a_LuaState, top); } return 1; } static int tolua_cUrlParser_GetDefaultPort(lua_State * a_LuaState) { // API function signature: // cUrlParser:GetDefaultPort("scheme") -> number // Check params: cLuaState L(a_LuaState); if (!L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Read params from Lua: AString scheme; L.GetStackValue(2, scheme); // Execute and push result: L.Push(cUrlParser::GetDefaultPort(scheme)); return 1; } static int tolua_cUrlParser_IsKnownScheme(lua_State * a_LuaState) { // API function signature: // cUrlParser:IsKnownScheme("scheme") -> bool // Check params: cLuaState L(a_LuaState); if (!L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Read params from Lua: AString scheme; L.GetStackValue(2, scheme); // Execute and push result: L.Push(cUrlParser::IsKnownScheme(scheme)); return 1; } static int tolua_cUrlParser_Parse(lua_State * a_LuaState) { // API function signature: // cUrlParser:Parse("url") -> "scheme", "user", "password", "host", portnum, "path", "query", "fragment" // On error, returns nil and error message // Check params: cLuaState L(a_LuaState); if (!L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Read params from Lua: AString url; L.GetStackValue(2, url); // Execute and push result: AString scheme, username, password, host, path, query, fragment; UInt16 port; auto res = cUrlParser::Parse(url, scheme, username, password, host, port, path, query, fragment); if (!res.first) { // Error, return nil and error msg: L.Push(cLuaState::Nil, res.second); return 2; } L.Push(scheme, username, password, host, port, path, query, fragment); return 8; } static int tolua_cUrlParser_ParseAuthorityPart(lua_State * a_LuaState) { // API function signature: // cUrlParser:ParseAuthorityPart("authority") -> "user", "password", "host", portnum // On error, returns nil and error message // Parts not specified in the "authority" are left empty / zero // Check params: cLuaState L(a_LuaState); if (!L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Read params from Lua: AString authPart; L.GetStackValue(2, authPart); // Execute and push result: AString username, password, host; UInt16 port; auto res = cUrlParser::ParseAuthorityPart(authPart, username, password, host, port); if (!res.first) { // Error, return nil and error msg: L.Push(cLuaState::Nil, res.second); return 2; } L.Push(username, password, host, port); return 4; } static int tolua_cUrlParser_UrlDecode(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( // Don't care about the first param !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the parameters: AString Input; S.GetStackValue(2, Input); // Convert and return: auto res = URLDecode(Input); if (res.first) { S.Push(res.second); } else { S.Push(cLuaState::Nil); } return 1; } static int tolua_cUrlParser_UrlEncode(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( // Don't care about the first param !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the parameters: AString Input; S.GetStackValue(2, Input); // Convert and return: S.Push(URLEncode(Input)); return 1; } static int tolua_cWebAdmin_AddWebTab(lua_State * tolua_S) { // Function signatures: // cWebAdmin:AddWebTab(Title, UrlPath, CallbackFn) // 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; } // Read the params: AString title, urlPath; auto callback = std::make_shared(); 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(webTabs.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"); lua_rawseti(tolua_S, newTable, index); ++index; } 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"); return 1; } /** Binding for cWebAdmin::GetURLEncodedString. */ static int tolua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S) { // Emit the obsoletion warning: cLuaState S(tolua_S); LOGWARNING("cWebAdmin:GetURLEncodedString() is obsolete, use cUrlParser:UrlEncode() instead."); S.LogStackTrace(); return tolua_cUrlParser_UrlEncode(tolua_S); } static int tolua_cClientHandle_SendPluginMessage(lua_State * L) { cLuaState S(L); if (!S.CheckParamSelf("cClientHandle") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4)) { return 0; } cClientHandle * Client = static_cast(tolua_tousertype(L, 1, nullptr)); if (Client == nullptr) { LOGWARNING("ClientHandle is nil in cClientHandle:SendPluginMessage()"); S.LogStackTrace(); return 0; } AString Channel, Message; Channel.assign(lua_tostring(L, 2), lua_strlen(L, 2)); Message.assign(lua_tostring(L, 3), lua_strlen(L, 3)); Client->SendPluginMessage(Channel, Message); return 0; } static int tolua_cClientHandle_SendTimeUpdate(lua_State * L) { cLuaState S(L); if (!S.CheckParamSelf("cClientHandle") || !S.CheckParamNumber(2, 3) || !S.CheckParamBool(4) || !S.CheckParamEnd(5)) { return 0; } cClientHandle * Client; cTickTimeLong::rep WorldAge, WorldDate; bool DoDayLightCycle; S.GetStackValues(1, Client, WorldAge, WorldDate, DoDayLightCycle); if (Client == nullptr) { return S.ApiParamError("Invalid 'self'"); } Client->SendTimeUpdate(cTickTimeLong(WorldAge), cTickTimeLong(WorldDate), DoDayLightCycle); return 0; } static int tolua_cClientHandle_GetForgeMods(lua_State * L) { cLuaState S(L); if (!S.CheckParamSelf("cClientHandle") || !S.CheckParamEnd(2)) { return 0; } cClientHandle * Client; S.GetStackValue(1, Client); S.Push(Client->GetForgeMods()); return 1; } static int tolua_cClientHandle_GetUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cClientHandle") || !L.CheckParamEnd(2)) { return 0; } // Get the params: cClientHandle * Self; L.GetStackValue(1, Self); // Return the UUID as a string: L.Push(Self->GetUUID().ToShortString()); return 1; } static int tolua_cClientHandle_GenerateOfflineUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamStaticSelf("cClientHandle") || !L.CheckParamString(2) || !L.CheckParamEnd(3)) { return 0; } // Get the params: AString Username; L.GetStackValue(2, Username); // Return the UUID as a string: L.Push(cClientHandle::GenerateOfflineUUID(Username).ToShortString()); return 1; } static int tolua_cClientHandle_IsUUIDOnline(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamStaticSelf("cClientHandle") || !L.CheckParamUUID(2) || !L.CheckParamEnd(3)) { return 0; } // Get the params: cUUID UUID; L.GetStackValue(2, UUID); // Return the result: L.Push(cClientHandle::IsUUIDOnline(UUID)); return 1; } static int tolua_cMobHeadEntity_SetOwner(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cMobHeadEntity") || !L.CheckParamUUID(2) || !L.CheckParamString(3, 5) || !L.CheckParamEnd(6)) { return 0; } // Get the params: cMobHeadEntity * Self; cUUID OwnerUUID; AString OwnerName, OwnerTexture, OwnerTextureSignature; L.GetStackValues(1, Self, OwnerUUID, OwnerName, OwnerTexture, OwnerTextureSignature); // Set the owner: Self->SetOwner(OwnerUUID, OwnerName, OwnerTexture, OwnerTextureSignature); return 0; } static int tolua_cMobHeadEntity_GetOwnerUUID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cMobHeadEntity") || !L.CheckParamEnd(2)) { return 0; } // Get the params: cMobHeadEntity * Self; L.GetStackValue(1, Self); // Return the UUID as a string: cUUID Owner = Self->GetOwnerUUID(); L.Push(Owner.IsNil() ? AString {} : Owner.ToShortString()); return 1; } static int tolua_cMojangAPI_AddPlayerNameToUUIDMapping(lua_State * L) { cLuaState S(L); if (!S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamString(2) || !S.CheckParamUUID(3) || !S.CheckParamEnd(4)) { return 0; } // Retrieve the parameters: AString PlayerName; cUUID UUID; S.GetStackValues(2, PlayerName, UUID); // Store in the cache: cRoot::Get()->GetMojangAPI().AddPlayerNameToUUIDMapping(PlayerName, UUID); return 0; } static int tolua_cMojangAPI_GetPlayerNameFromUUID(lua_State * L) { cLuaState S(L); if (!S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(4)) { return 0; } cUUID UUID; S.GetStackValue(2, UUID); // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Return the PlayerName: AString PlayerName = cRoot::Get()->GetMojangAPI().GetPlayerNameFromUUID(UUID, ShouldUseCacheOnly); S.Push(PlayerName); return 1; } static int tolua_cMojangAPI_GetUUIDFromPlayerName(lua_State * L) { cLuaState S(L); if (!S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamString(2) || !S.CheckParamEnd(4)) { return 0; } AString PlayerName; S.GetStackValue(2, PlayerName); // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Return the UUID as a string: cUUID UUID = cRoot::Get()->GetMojangAPI().GetUUIDFromPlayerName(PlayerName, ShouldUseCacheOnly); S.Push(UUID.IsNil() ? AString {} : UUID.ToShortString()); return 1; } static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L) { cLuaState S(L); if (!S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamTable(2) || !S.CheckParamEnd(4)) { return 0; } // Convert the input table into AStringVector: AStringVector PlayerNames; int NumNames = luaL_getn(L, 2); PlayerNames.reserve(static_cast(NumNames)); for (int i = 1; i <= NumNames; i++) { lua_rawgeti(L, 2, i); AString Name; S.GetStackValue(-1, Name); if (!Name.empty()) { PlayerNames.push_back(Name); } lua_pop(L, 1); } // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Push the output table onto the stack: lua_newtable(L); // Get the UUIDs: auto UUIDs = cRoot::Get()->GetMojangAPI().GetUUIDsFromPlayerNames(PlayerNames, ShouldUseCacheOnly); if (UUIDs.size() != PlayerNames.size()) { // A hard error has occured while processing the request, no UUIDs were returned. Return an empty table: return 1; } // Convert to output table, PlayerName -> UUID string: size_t len = UUIDs.size(); for (size_t i = 0; i < len; i++) { if (UUIDs[i].IsNil()) { // No UUID was provided for PlayerName[i], skip it in the resulting table continue; } S.Push(UUIDs[i].ToShortString()); lua_setfield(L, 3, PlayerNames[i].c_str()); } return 1; } static int tolua_cMojangAPI_MakeUUIDDashed(lua_State * L) { // Function now non-existant but kept for API compatibility // Check params: cLuaState S(L); if (!S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3)) { return 0; } // Get the params: cUUID UUID; S.GetStackValue(2, UUID); // Push the result: S.Push(UUID.ToLongString()); return 1; } static int tolua_cMojangAPI_MakeUUIDShort(lua_State * L) { // Function now non-existant but kept for API compatibility // Check params: cLuaState S(L); if (!S.CheckParamUserTable(1, "cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3)) { return 0; } // Get the params: cUUID UUID; S.GetStackValue(2, UUID); // Push the result: S.Push(UUID.ToShortString()); return 1; } static int tolua_get_cItem_m_LoreTable(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("const cItem")) { return 0; } // Get the params: const cItem * Self = nullptr; L.GetStackValue(1, Self); // Push the result: L.Push(Self->m_LoreTable); return 1; } static int tolua_cItem_EnchantByXPLevels(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cItem") || !L.CheckParamNumber(2)) { return 0; } // Get the params: cItem * Self; unsigned NumXPLevels; L.GetStackValue(1, Self); L.GetStackValue(2, NumXPLevels); // Call: L.Push(Self->EnchantByXPLevels(NumXPLevels, GetRandomProvider())); return 1; } static int tolua_set_cItem_m_LoreTable(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cItem") || !L.CheckParamTable(2)) { return 0; } // Get the params: cItem * Self = nullptr; L.GetStackValue(1, Self); // Set the value: Self->m_LoreTable.clear(); if (!L.GetStackValue(2, Self->m_LoreTable)) { return L.ApiParamError("cItem.m_LoreTable: Could not read value as an array of strings"); } return 0; } static int Lua_ItemGrid_GetSlotCoords(lua_State * L) { tolua_Error tolua_err; if (!tolua_isusertype(L, 1, "const cItemGrid", 0, &tolua_err) || !tolua_isnumber(L, 2, 0, &tolua_err) || !tolua_isnoobj(L, 3, &tolua_err)) { goto tolua_lerror; } { const cItemGrid * self = static_cast(tolua_tousertype(L, 1, nullptr)); int SlotNum = static_cast(tolua_tonumber(L, 2, 0)); if (self == nullptr) { tolua_error(L, "invalid 'self' in function 'cItemGrid:GetSlotCoords'", nullptr); return 0; } int X, Y; self->GetSlotCoords(SlotNum, X, Y); tolua_pushnumber(L, static_cast(X)); tolua_pushnumber(L, static_cast(Y)); return 2; } tolua_lerror: tolua_error(L, "#ferror in function 'cItemGrid:GetSlotCoords'.", &tolua_err); return 0; } /** Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks */ class cLuaBlockTracerCallbacks : public cBlockTracer::cCallbacks { public: cLuaBlockTracerCallbacks(cLuaState::cTableRefPtr && a_Callbacks) : m_Callbacks(std::move(a_Callbacks)) { } virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks ->CallTableFn("OnNextBlock", a_BlockPos, a_BlockType, a_BlockMeta, a_EntryFace, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnNextBlockNoData(Vector3i a_BlockPos, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn("OnNextBlockNoData", a_BlockPos, a_EntryFace, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnOutOfWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn("OnOutOfWorld", a_BlockPos, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnIntoWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn("OnIntoWorld", a_BlockPos, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } virtual void OnNoMoreHits(void) override { m_Callbacks->CallTableFn("OnNoMoreHits"); } virtual void OnNoChunk(void) override { m_Callbacks->CallTableFn("OnNoChunk"); } protected: cLuaState::cTableRefPtr m_Callbacks; }; /** Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks This is the deprecated version of cLuaBlockTracerCallback, used when the plugin calls the Trace function with number-based coords. */ class cLuaBlockTracerCallbacksOld : public cLuaBlockTracerCallbacks { public: cLuaBlockTracerCallbacksOld(cLuaState::cTableRefPtr && a_Callbacks) : cLuaBlockTracerCallbacks(std::move(a_Callbacks)) { } virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlock", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockType, a_BlockMeta, a_EntryFace, cLuaState::Return, res )) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnNextBlockNoData(Vector3i a_BlockPos, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlockNoData", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_EntryFace, cLuaState::Return, res )) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnOutOfWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn("OnOutOfWorld", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnIntoWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn("OnIntoWorld", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, cLuaState::Return, res)) { return res; } // No such function in the table, skip the callback return false; } }; static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:FirstSolidHitTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ) -> bool, [Vector3d, Vector3i, eBlockFace] // Canonical cLineBlockTracer:FirstSolidHitTrace(World, Start, End) -> bool, [Vector3d, Vector3i, eBlockFace] // Canonical cLineBlockTracer.FirstSolidHitTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ) -> bool, [Vector3d, Vector3i, eBlockFace] cLineBlockTracer.FirstSolidHitTrace(World, Start, End) -> bool, [Vector3d, Vector3i, eBlockFace] */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(idx, "cWorld")) { return 0; } if (L.IsParamNumber(idx + 1)) { // This is the number variant of the call: if (!L.CheckParamNumber(idx + 1, idx + 6) || !L.CheckParamEnd(idx + 7)) { return 0; } // Get the params: cWorld * world; double startX, startY, startZ; double endX, endY, endZ; if (!L.GetStackValues(idx, world, startX, startY, startZ, endX, endY, endZ)) { LOGWARNING("cLineBlockTracer:FirstSolidHitTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } Vector3d hitCoords; Vector3i hitBlockCoords; eBlockFace hitBlockFace; auto isHit = cLineBlockTracer::FirstSolidHitTrace( *world, Vector3d(startX, startY, startZ), Vector3d(endX, endY, endZ), hitCoords, hitBlockCoords, hitBlockFace ); L.Push(isHit); if (!isHit) { return 1; } L.Push(hitCoords); L.Push(hitBlockCoords); L.Push(hitBlockFace); return 4; } if (L.IsParamVector3(idx + 1)) { // This is the Vector3-based variant of the call: if (!L.CheckParamVector3(idx + 1, idx + 2) || !L.CheckParamEnd(idx + 3)) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; if (!L.GetStackValues(idx, world, start, end)) { LOGWARNING("cLineBlockTracer:FirstSolidHitTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } Vector3d hitCoords; Vector3i hitBlockCoords; eBlockFace hitBlockFace; auto isHit = cLineBlockTracer::FirstSolidHitTrace(*world, start, end, hitCoords, hitBlockCoords, hitBlockFace); L.Push(isHit); if (!isHit) { return 1; } L.Push(hitCoords); L.Push(hitBlockCoords); L.Push(hitBlockFace); return 4; } tolua_error( L, "cLineBlockTracer:FirstSolidHitTrace(): Invalid parameters, expected either a set of coords, or two Vector3's", nullptr ); return 0; } static int tolua_cLineBlockTracer_LineOfSightTrace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:LineOfSightTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ, Sight) -> bool // Canonical cLineBlockTracer:LineOfSightTrace(World, Start, End, Sight) -> bool // Canonical cLineBlockTracer.LineOfSightTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ, Sight) -> bool cLineBlockTracer.LineOfSightTrace(World, Start, End, Sight) -> bool */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(idx, "cWorld")) { return 0; } if (L.IsParamNumber(idx + 1)) { // This is the number variant of the call: if (!L.CheckParamNumber(idx + 1, idx + 6) || // Optional param lineOfSight is not checked !L.CheckParamEnd(idx + 8)) { return 0; } // Get the params: cWorld * world; double startX, startY, startZ; double endX, endY, endZ; if (!L.GetStackValues(idx, world, startX, startY, startZ, endX, endY, endZ)) { LOGWARNING("cLineBlockTracer:LineOfSightTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } int lineOfSight = cLineBlockTracer::losAir | cLineBlockTracer::losWater; L.GetStackValue(idx + 7, lineOfSight); L.Push(cLineBlockTracer::LineOfSightTrace( *world, Vector3d(startX, startY, startZ), Vector3d(endX, endY, endZ), lineOfSight )); return 1; } if (L.IsParamVector3(idx + 1)) { // This is the Vector3-based variant of the call: if (!L.CheckParamVector3(idx + 1, idx + 2) || // Optional param lineOfSight is not checked !L.CheckParamEnd(idx + 4)) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; if (!L.GetStackValues(idx, world, start, end)) { LOGWARNING("cLineBlockTracer:LineOfSightTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } int lineOfSight = cLineBlockTracer::losAirWater; L.GetStackValue(idx + 7, lineOfSight); L.Push(cLineBlockTracer::LineOfSightTrace(*world, start, end, lineOfSight)); return 1; } tolua_error( L, "cLineBlockTracer:LineOfSightTrace(): Invalid parameters, expected either a set of coords, or two Vector3's", nullptr ); return 0; } static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // Canonical // DEPRECATED cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // DEPRECATED cLineBlockTracer:Trace(World, Callbacks, Start, End) // Canonical cLineBlockTracer.Trace(World, Callbacks, Start, End) */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(idx, "cWorld") || !L.CheckParamTable(idx + 1)) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; cLuaState::cTableRefPtr callbacks; if (L.IsParamNumber(idx + 2) && L.IsParamNumber(idx + 3) && L.IsParamNumber(idx + 4) && L.IsParamNumber(idx + 5) && L.IsParamNumber(idx + 6) && L.IsParamNumber(idx + 7) && L.CheckParamEnd(idx + 8)) { if (!L.GetStackValues(idx, world, callbacks, start.x, start.y, start.z, end.x, end.y, end.z)) { LOGWARNING( "cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx ); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } LOGWARNING("cLineBlockTracer:Trace(): Using plain numbers is deprecated, use Vector3 coords instead."); L.LogStackTrace(); // Trace: cLuaBlockTracerCallbacksOld tracerCallbacks(std::move(callbacks)); bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end); tolua_pushboolean(L, res ? 1 : 0); return 1; } else if (L.IsParamVector3(idx + 2) && L.IsParamVector3(idx + 3) && L.CheckParamEnd(idx + 4)) { if (!L.GetStackValues(idx, world, callbacks, start, end)) { LOGWARNING( "cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx ); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } // Trace: cLuaBlockTracerCallbacks tracerCallbacks(std::move(callbacks)); bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end); tolua_pushboolean(L, res ? 1 : 0); return 1; } return L.ApiParamError("Invalid overload of cLineBlockTracer:Trace()"); } 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(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(windowType), slotsX, slotsY, title)); tolua_register_gc(tolua_S, lua_gettop(tolua_S)); return 1; } static int tolua_cRoot_DoWithPlayerByUUID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cRoot") || !L.CheckParamUUID(2) || !L.CheckParamFunction(3) || !L.CheckParamEnd(4)) { return 0; } // Get parameters: cRoot * Self; cUUID PlayerUUID; cLuaState::cRef FnRef; L.GetStackValues(1, Self, PlayerUUID, FnRef); if (PlayerUUID.IsNil()) { return L.ApiParamError("Expected a non-nil UUID for parameter #1"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #2"); } // Call the function: bool res = Self->DoWithPlayerByUUID( PlayerUUID, [&](cPlayer & a_Player) { bool ret = false; L.Call(FnRef, &a_Player, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cRoot_GetBuildCommitID(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_COMMIT_ID); return 1; } static int tolua_cRoot_GetBuildDateTime(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_DATETIME); return 1; } static int tolua_cRoot_GetBuildID(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_ID); return 1; } static int tolua_cRoot_GetBuildSeriesName(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_SERIES_NAME); return 1; } static int tolua_cRoot_GetBrewingRecipe(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cRoot") || !L.CheckParamUserType(2, "const cItem") || !L.CheckParamUserType(3, "const cItem") || !L.CheckParamEnd(4)) { return 0; } // Check the bottle param: cItem * Bottle = nullptr; L.GetStackValue(2, Bottle); if (Bottle == nullptr) { LOGWARNING("cRoot:GetBrewingRecipe: the Bottle parameter is nil or missing."); return 0; } cItem * Ingredient = nullptr; L.GetStackValue(3, Ingredient); if (Ingredient == nullptr) { LOGWARNING("cRoot:GetBrewingRecipe: the Ingredient parameter is nil or missing."); return 0; } // Get the recipe for the input cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); const cBrewingRecipes::cRecipe * Recipe = BR->GetRecipeFrom(*Bottle, *Ingredient); if (Recipe == nullptr) { // There is no such brewing recipe for this bottle and ingredient, return no value return 0; } // Push the output item cItem & OutItem = const_cast(Recipe->Output); L.Push(&OutItem); return 1; } static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamUserTable(1, "cRoot") || !L.CheckParamUserType(2, "const cItem") || !L.CheckParamEnd(3)) { return 0; } // Check the input param: cItem * Input = nullptr; L.GetStackValue(2, Input); if (Input == nullptr) { LOGWARNING("cRoot:GetFurnaceRecipe: the Input parameter is nil or missing."); return 0; } // Get the recipe for the input cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); const cFurnaceRecipe::cRecipe * Recipe = FR->GetRecipeFrom(*Input); if (Recipe == nullptr) { // There is no such furnace recipe for this input, return no value return 0; } // Push the output, number of ticks and input as the three return values: L.Push(Recipe->Out, Recipe->CookTime, Recipe->In); return 3; } static int tolua_cServer_RegisterForgeMod(lua_State * a_LuaState) { cLuaState L(a_LuaState); if (!L.CheckParamSelf("cServer") || !L.CheckParamString(2, 3) || !L.CheckParamNumber(4) || !L.CheckParamEnd(5)) { return 0; } cServer * Server; AString Name, Version; UInt32 Protocol; L.GetStackValues(1, Server, Name, Version, Protocol); if (!Server->RegisterForgeMod(Name, Version, Protocol)) { tolua_error(L, "duplicate Forge mod name registration", nullptr); return 0; } return 0; } static int tolua_cServer_ScheduleTask(lua_State * a_LuaState) { // Function signature: // Server:ScheduleTask(NumTicks, Callback) // Retrieve the args: cLuaState L(a_LuaState); if (!L.CheckParamUserType(1, "cServer") || !L.CheckParamNumber(2) || !L.CheckParamFunction(3)) { return 0; } cServer * Server; int NumTicks; auto Task = std::make_shared(); if (!L.GetStackValues(1, Server, NumTicks, Task)) { return cManualBindings::lua_do_error(a_LuaState, "Error in function call '#funcname#': Cannot read parameters"); } if (Server == nullptr) { return cManualBindings::lua_do_error( a_LuaState, "Error in function call '#funcname#': Not called on an object instance" ); } if (!Task->IsValid()) { return cManualBindings::lua_do_error( a_LuaState, "Error in function call '#funcname#': Could not store the callback parameter" ); } Server->ScheduleTask(cTickTime(NumTicks), [Task](cServer & a_Server) { Task->Call(&a_Server); }); return 0; } static int tolua_cScoreboard_GetTeamNames(lua_State * L) { cLuaState S(L); if (!S.CheckParamUserType(1, "cScoreboard") || !S.CheckParamEnd(2)) { return 0; } // Get the groups: cScoreboard * Scoreboard = static_cast(tolua_tousertype(L, 1, nullptr)); AStringVector Teams = Scoreboard->GetTeamNames(); // Push the results: S.Push(Teams); return 1; } static int tolua_cHopperEntity_GetOutputBlockPos(lua_State * tolua_S) { // function cHopperEntity::GetOutputBlockPos() // Exported manually because tolua would require meaningless params cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cHopperEntity") || !L.CheckParamNumber(2) || !L.CheckParamEnd(3)) { return 0; } cHopperEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cHopperEntity::GetOutputBlockPos()'", nullptr); return 0; } NIBBLETYPE a_BlockMeta = static_cast(tolua_tonumber(tolua_S, 2, 0)); auto res = self->GetOutputBlockPos(a_BlockMeta); tolua_pushboolean(tolua_S, res.first); if (res.first) { tolua_pushnumber(tolua_S, static_cast(res.second.x)); tolua_pushnumber(tolua_S, static_cast(res.second.y)); tolua_pushnumber(tolua_S, static_cast(res.second.z)); return 4; } return 1; } static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState) { /* Function signatures: bbox:CalcLineIntersection(pt1, pt2) -> bool, [number, blockface] cBoundingBox:CalcLineIntersection(min, max, pt1, pt2) -> bool, [number, blockface] (static) */ cLuaState L(a_LuaState); Vector3d min; Vector3d max; Vector3d pt1; Vector3d pt2; double lineCoeff; eBlockFace blockFace; bool res; if (L.GetStackValues(2, min, max, pt1, pt2)) // Try the static signature first { res = cBoundingBox::CalcLineIntersection(min, max, pt1, pt2, lineCoeff, blockFace); } else { const cBoundingBox * bbox; if (!L.GetStackValues(1, bbox, pt1, pt2)) // Try the regular signature { L.LogStackValues(); tolua_error( a_LuaState, "Invalid function params. Expected either bbox:CalcLineIntersection(pt1, pt2) or " "cBoundingBox:CalcLineIntersection(min, max, pt1, pt2).", nullptr ); return 0; } res = bbox->CalcLineIntersection(pt1, pt2, lineCoeff, blockFace); } L.Push(res); if (res) { L.Push(lineCoeff, blockFace); return 3; } return 1; } static int tolua_cBoundingBox_Intersect(lua_State * a_LuaState) { /* Function signature: bbox:Intersect(a_OtherBbox) -> bool, cBoundingBox */ cLuaState L(a_LuaState); const cBoundingBox * self; const cBoundingBox * other; if (!L.GetStackValues(1, self, other)) { L.LogStackValues(); tolua_error(a_LuaState, "Invalid function params. Expected bbox:Intersect(otherBbox).", nullptr); return 0; } auto intersection = new cBoundingBox(*self); auto res = self->Intersect(*other, *intersection); L.Push(res); if (!res) { delete intersection; return 1; } L.Push(intersection); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the "intersection" object return 2; } static int tolua_cChunkDesc_GetBlockTypeMeta(lua_State * a_LuaState) { /* Function signature: ChunkDesc:GetBlockTypeMeta(RelX, RelY, RelZ) -> BlockType, BlockMeta */ cLuaState L(a_LuaState); const cChunkDesc * self; int relX, relY, relZ; if (!L.GetStackValues(1, self, relX, relY, relZ)) { L.LogStackValues(); tolua_error( a_LuaState, "Invalid function params. Expected chunkDesc:GetBlockTypeMeta(relX, relY, relZ)", nullptr ); return 0; } BLOCKTYPE blockType; NIBBLETYPE blockMeta; self->GetBlockTypeMeta(relX, relY, relZ, blockType, blockMeta); L.Push(blockType, blockMeta); return 2; } static int tolua_cColor_GetColor(lua_State * tolua_S) { cLuaState L(tolua_S); cColor * self; if (!L.CheckParamSelf("cColor") || !L.GetStackValue(1, self)) { return 0; } L.Push(self->GetRed(), self->GetGreen(), self->GetBlue()); return 3; } static int tolua_cCompositeChat_new(lua_State * a_LuaState) { /* Function signatures: cCompositeChat() cCompositeChat(a_ParseText, a_MessageType) */ // Check if it's the no-param version: cLuaState L(a_LuaState); if (lua_isnone(a_LuaState, 2)) { auto * res = static_cast(Mtolua_new(cCompositeChat())); L.Push(res); return 1; } // Check the second signature: AString parseText; if (!L.GetStackValue(2, parseText)) { tolua_Error err; tolua_error(a_LuaState, "Invalid ParseText parameter (1) in cCompositeChat constructor.", &err); return 0; } int messageTypeInt = mtCustom; if (!lua_isnone(a_LuaState, 3)) { if (!L.GetStackValue(3, messageTypeInt)) { tolua_Error err; tolua_error( a_LuaState, "Invalid type of the MessageType parameter (2) in cCompositeChat constructor.", &err ); return 0; } if ((messageTypeInt < 0) || (messageTypeInt >= mtMaxPlusOne)) { tolua_Error err; tolua_error(a_LuaState, "Invalid MessageType parameter (2) value in cCompositeChat constructor.", &err); return 0; } } L.Push(static_cast(Mtolua_new(cCompositeChat(parseText, static_cast(messageTypeInt)) ))); return 1; } static int tolua_cCompositeChat_new_local(lua_State * a_LuaState) { // Use the same constructor as global, just register it for GC: auto res = tolua_cCompositeChat_new(a_LuaState); if (res == 1) { tolua_register_gc(a_LuaState, lua_gettop(a_LuaState)); } return res; } static int tolua_cCompositeChat_AddShowAchievementPart(lua_State * tolua_S) { // function cCompositeChat:AddShowAchievementPart(PlayerName, Achievement, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error( tolua_S, "invalid 'self' in function call cCompositeChat::AddShowAchievementPart(string, string, string) const.", nullptr ); return 0; } // Add the part: AString PlayerName, Achievement, Style; L.GetStackValues(2, PlayerName); L.GetStackValues(3, Achievement); L.GetStackValues(4, Style); self->AddShowAchievementPart(PlayerName, Achievement, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(tolua_S, 1); return 1; } static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S) { // function cCompositeChat:AddRunCommandPart(Message, Command, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddRunCommandPart'", nullptr); return 0; } // Add the part: AString Text, Command, Style = "na"; L.GetStackValue(2, Text); L.GetStackValue(3, Command); L.GetStackValue(4, Style); self->AddRunCommandPart(Text, Command, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddSuggestCommandPart(lua_State * tolua_S) { // function cCompositeChat:AddSuggestCommandPart(Message, Command, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddSuggestCommandPart'", nullptr); return 0; } // Add the part: AString Text, Command, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Command); L.GetStackValue(4, Style); self->AddSuggestCommandPart(Text, Command, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddTextPart(lua_State * tolua_S) { // function cCompositeChat:AddTextPart(Message, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddTextPart'", nullptr); return 0; } // Add the part: AString Text, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Style); self->AddTextPart(Text, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddUrlPart(lua_State * tolua_S) { // function cCompositeChat:AddTextPart(Message, Url, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddUrlPart'", nullptr); return 0; } // Add the part: AString Text, Url, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Url); L.GetStackValue(4, Style); self->AddUrlPart(Text, Url, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_Clear(lua_State * tolua_S) { // function cCompositeChat:Clear() // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamEnd(2)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", nullptr); return 0; } // Clear all the parts: self->Clear(); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_ParseText(lua_State * tolua_S) { // function cCompositeChat:ParseText(TextMessage) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", nullptr); return 0; } // Parse the text: AString Text; L.GetStackValue(2, Text); self->ParseText(Text); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_SetMessageType(lua_State * tolua_S) { // function cCompositeChat:SetMessageType(MessageType) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamNumber(2)) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:SetMessageType'", nullptr); return 0; } // Set the type: int MessageType = mtCustom; L.GetStackValue(2, MessageType); self->SetMessageType(static_cast(MessageType)); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S) { // function cCompositeChat:UnderlineUrls() // Exported manually to support call-chaining (return self) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat")) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:UnderlineUrls'", nullptr); return 0; } // Call the processing self->UnderlineUrls(); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCuboid_Assign(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x1, y1, z1, x2, y2, z2; if (L.GetStackValues(2, x1, y1, z1, x2, y2, z2)) { LOGWARNING( "cCuboid:Assign(x1, y1, z1, x2, y2, z2) is deprecated, use cCuboid:Assign(Vector3i, Vector3i) instead." ); L.LogStackTrace(); self->Assign({x1, y1, z1}, {x2, y2, z2}); return 0; } // Try the (cCuboid) param version: cCuboid * other = nullptr; if (L.GetStackValue(2, other) && (other != nullptr)) { self->Assign(*other); return 0; } // Try the (Vector3i, Vector3i) param version: Vector3i pt1; Vector3i pt2; if (L.GetStackValues(2, pt1, pt2)) { self->Assign(pt1, pt2); return 0; } return L.ApiParamError("Invalid parameter, expected either a cCuboid or two Vector3i-s."); } static int tolua_cCuboid_IsInside(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x, y, z; if (L.GetStackValues(2, x, y, z)) { LOGWARNING("cCuboid:IsInside(x, y, z) is deprecated, use cCuboid:IsInside(Vector3) instead."); L.LogStackTrace(); L.Push(self->IsInside(Vector3i {x, y, z})); return 1; } // Try the Vector3 param version: Vector3d pt; if (L.GetStackValue(2, pt)) { L.Push(self->IsInside(pt)); return 1; } return L.ApiParamError("Invalid parameter #2, expected a Vector3."); } static int tolua_cCuboid_Move(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x, y, z; if (L.GetStackValues(2, x, y, z)) { LOGWARNING("cCuboid:Move(x, y, z) is deprecated, use cCuboid:Move(Vector3i) instead."); L.LogStackTrace(); self->Move({x, y, z}); return 0; } Vector3i offset; if (!L.GetStackValue(2, offset)) { return L.ApiParamError("Invalid parameter #2, expected a Vector3."); } self->Move(offset); return 0; } static int tolua_cEntity_Destroy(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); if (lua_gettop(L) == 2) { LOGWARNING("cEntity:Destroy(bool) is deprecated, use cEntity:Destroy() instead."); } if (self->IsPlayer()) { return L.ApiParamError("Cannot call cEntity:Destroy() on a cPlayer, use cClientHandle:Kick() instead."); } self->Destroy(); return 0; } static int tolua_cEntity_IsSubmerged(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); // API function deprecated: LOGWARNING("cEntity:IsSubmerged() is deprecated. Use cEntity:IsHeadInWater() instead."); cLuaState::LogStackTrace(tolua_S); L.Push(self->IsHeadInWater()); return 1; } static int tolua_cEntity_IsSwimming(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); // API function deprecated LOGWARNING("cEntity:IsSwimming() is deprecated. Use cEntity:IsInWater() instead."); cLuaState::LogStackTrace(tolua_S); L.Push(self->IsInWater()); return 1; } static int tolua_cEntity_GetPosition(lua_State * tolua_S) { cLuaState L(tolua_S); // Get the params: cEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } L.Push(Mtolua_new((Vector3d) (self->GetPosition()))); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the object return 1; } static int tolua_cEntity_GetSpeed(lua_State * tolua_S) { cLuaState L(tolua_S); // Get the params: cEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } L.Push(Mtolua_new((Vector3d) (self->GetSpeed()))); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the object return 1; } static int tolua_get_StatisticsManager_Custom(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamNumber(2)) { return 0; } // Get the params: lua_pushstring(tolua_S, ".self"); lua_rawget(tolua_S, 1); StatisticsManager * Self = static_cast(lua_touserdata(tolua_S, -1)); CustomStatistic Statistic; if (!L.GetStackValue(2, Statistic)) { return L.ApiParamError("Expected a valid custom statistic ID"); } // Push result if statistic exists: if (const auto Result = Self->Custom.find(Statistic); Result != Self->Custom.end()) { L.Push(Result->second); return 1; } return 0; } static int tolua_set_StatisticsManager_Custom(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamNumber(2)) { return 0; } // Get the params: lua_pushstring(tolua_S, ".self"); lua_rawget(tolua_S, 1); StatisticsManager * Self = static_cast(lua_touserdata(tolua_S, -1)); CustomStatistic Statistic; StatisticsManager::StatValue Value; if (!L.GetStackValues(2, Statistic, Value)) { return L.ApiParamError("Expected a valid custom statistic ID and value"); } // Set the value: Self->Custom[Statistic] = Value; return 0; } void cManualBindings::Bind(lua_State * tolua_S) { tolua_beginmodule(tolua_S, nullptr); // Create the new classes: tolua_usertype(tolua_S, "cCryptoHash"); tolua_usertype(tolua_S, "cLineBlockTracer"); tolua_usertype(tolua_S, "cStringCompression"); tolua_usertype(tolua_S, "cUrlParser"); // StatisticsManager was already created by cPlayer::GetStatistics' autogenerated bindings. tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr); tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr); tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr); tolua_cclass(tolua_S, "cUrlParser", "cUrlParser", "", nullptr); tolua_cclass(tolua_S, "StatisticsManager", "StatisticsManager", "", nullptr); // Globals: tolua_function(tolua_S, "Clamp", tolua_Clamp); tolua_function(tolua_S, "StringSplit", tolua_StringSplit); tolua_function(tolua_S, "StringSplitWithQuotes", tolua_StringSplitWithQuotes); tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim); tolua_function(tolua_S, "LOG", tolua_LOG); tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO); tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN); tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN); tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR); tolua_function(tolua_S, "Base64Encode", tolua_Base64Encode); tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode); tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead tolua_beginmodule(tolua_S, "cBoundingBox"); tolua_function(tolua_S, "CalcLineIntersection", tolua_cBoundingBox_CalcLineIntersection); tolua_function(tolua_S, "Intersect", tolua_cBoundingBox_Intersect); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cChunkDesc"); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cChunkDesc_GetBlockTypeMeta); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cClientHandle"); tolua_constant(tolua_S, "MAX_VIEW_DISTANCE", cClientHandle::MAX_VIEW_DISTANCE); tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE); tolua_function(tolua_S, "GetForgeMods", tolua_cClientHandle_GetForgeMods); tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage); tolua_function(tolua_S, "SendTimeUpdate", tolua_cClientHandle_SendTimeUpdate); tolua_function(tolua_S, "GetUUID", tolua_cClientHandle_GetUUID); tolua_function(tolua_S, "GenerateOfflineUUID", tolua_cClientHandle_GenerateOfflineUUID); tolua_function(tolua_S, "IsUUIDOnline", tolua_cClientHandle_IsUUIDOnline); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cColor"); tolua_function(tolua_S, "GetColor", tolua_cColor_GetColor); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCompositeChat"); tolua_function(tolua_S, "new", tolua_cCompositeChat_new); tolua_function(tolua_S, "new_local", tolua_cCompositeChat_new_local); tolua_function(tolua_S, ".call", tolua_cCompositeChat_new_local); tolua_function(tolua_S, "AddShowAchievementPart", tolua_cCompositeChat_AddShowAchievementPart); tolua_function(tolua_S, "AddRunCommandPart", tolua_cCompositeChat_AddRunCommandPart); tolua_function(tolua_S, "AddSuggestCommandPart", tolua_cCompositeChat_AddSuggestCommandPart); tolua_function(tolua_S, "AddTextPart", tolua_cCompositeChat_AddTextPart); tolua_function(tolua_S, "AddUrlPart", tolua_cCompositeChat_AddUrlPart); tolua_function(tolua_S, "Clear", tolua_cCompositeChat_Clear); tolua_function(tolua_S, "ParseText", tolua_cCompositeChat_ParseText); tolua_function(tolua_S, "SetMessageType", tolua_cCompositeChat_SetMessageType); tolua_function(tolua_S, "UnderlineUrls", tolua_cCompositeChat_UnderlineUrls); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCryptoHash"); tolua_function(tolua_S, "md5", tolua_md5); tolua_function(tolua_S, "md5HexString", tolua_md5HexString); tolua_function(tolua_S, "sha1", tolua_sha1); tolua_function(tolua_S, "sha1HexString", tolua_sha1HexString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCuboid"); tolua_function(tolua_S, "Assign", tolua_cCuboid_Assign); tolua_function(tolua_S, "IsInside", tolua_cCuboid_IsInside); tolua_function(tolua_S, "Move", tolua_cCuboid_Move); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cEntity"); tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID); tolua_function(tolua_S, "Destroy", tolua_cEntity_Destroy); tolua_function(tolua_S, "IsSubmerged", tolua_cEntity_IsSubmerged); tolua_function(tolua_S, "IsSwimming", tolua_cEntity_IsSwimming); tolua_function(tolua_S, "GetPosition", tolua_cEntity_GetPosition); tolua_function(tolua_S, "GetSpeed", tolua_cEntity_GetSpeed); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cFile"); tolua_function(tolua_S, "ChangeFileExt", tolua_cFile_ChangeFileExt); tolua_function(tolua_S, "Copy", tolua_cFile_Copy); tolua_function(tolua_S, "CreateFolder", tolua_cFile_CreateFolder); tolua_function(tolua_S, "CreateFolderRecursive", tolua_cFile_CreateFolderRecursive); tolua_function(tolua_S, "Delete", tolua_cFile_Delete); tolua_function(tolua_S, "DeleteFile", tolua_cFile_DeleteFile); tolua_function(tolua_S, "DeleteFolder", tolua_cFile_DeleteFolder); tolua_function(tolua_S, "DeleteFolderContents", tolua_cFile_DeleteFolderContents); tolua_function(tolua_S, "Exists", tolua_cFile_Exists); tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents); tolua_function(tolua_S, "GetLastModificationTime", tolua_cFile_GetLastModificationTime); tolua_function(tolua_S, "GetSize", tolua_cFile_GetSize); tolua_function(tolua_S, "IsFile", tolua_cFile_IsFile); tolua_function(tolua_S, "IsFolder", tolua_cFile_IsFolder); tolua_function(tolua_S, "ReadWholeFile", tolua_cFile_ReadWholeFile); tolua_function(tolua_S, "Rename", tolua_cFile_Rename); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cHopperEntity"); tolua_function(tolua_S, "GetOutputBlockPos", tolua_cHopperEntity_GetOutputBlockPos); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cItem"); tolua_function(tolua_S, "EnchantByXPLevels", tolua_cItem_EnchantByXPLevels); tolua_variable(tolua_S, "m_LoreTable", tolua_get_cItem_m_LoreTable, tolua_set_cItem_m_LoreTable); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cItemGrid"); tolua_function(tolua_S, "GetSlotCoords", Lua_ItemGrid_GetSlotCoords); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cLineBlockTracer"); tolua_function(tolua_S, "FirstSolidHitTrace", tolua_cLineBlockTracer_FirstSolidHitTrace); tolua_function(tolua_S, "LineOfSightTrace", tolua_cLineBlockTracer_LineOfSightTrace); tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace); tolua_constant(tolua_S, "losAir", cLineBlockTracer::losAir); tolua_constant(tolua_S, "losWater", cLineBlockTracer::losWater); tolua_constant(tolua_S, "losLava", cLineBlockTracer::losLava); 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, "SetOnClicked", tolua_SetObjectCallback); tolua_function(tolua_S, "SetOnClosing", tolua_SetObjectCallback); tolua_function(tolua_S, "SetOnSlotChanged", tolua_SetObjectCallback); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMapManager"); tolua_function(tolua_S, "DoWithMap", DoWithID); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMobHeadEntity"); tolua_function(tolua_S, "SetOwner", tolua_cMobHeadEntity_SetOwner); tolua_function(tolua_S, "GetOwnerUUID", tolua_cMobHeadEntity_GetOwnerUUID); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMojangAPI"); tolua_function(tolua_S, "AddPlayerNameToUUIDMapping", tolua_cMojangAPI_AddPlayerNameToUUIDMapping); tolua_function(tolua_S, "GetPlayerNameFromUUID", tolua_cMojangAPI_GetPlayerNameFromUUID); tolua_function(tolua_S, "GetUUIDFromPlayerName", tolua_cMojangAPI_GetUUIDFromPlayerName); tolua_function(tolua_S, "GetUUIDsFromPlayerNames", tolua_cMojangAPI_GetUUIDsFromPlayerNames); tolua_function(tolua_S, "MakeUUIDDashed", tolua_cMojangAPI_MakeUUIDDashed); tolua_function(tolua_S, "MakeUUIDShort", tolua_cMojangAPI_MakeUUIDShort); tolua_endmodule(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, "GetUUID", tolua_cPlayer_GetUUID); tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches); tolua_function(tolua_S, "PlaceBlock", tolua_cPlayer_PlaceBlock); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlugin"); tolua_function(tolua_S, "GetDirectory", tolua_cPlugin_GetDirectory); tolua_function(tolua_S, "GetLocalDirectory", tolua_cPlugin_GetLocalDirectory); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPluginLua"); tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPluginManager"); tolua_function(tolua_S, "AddHook", tolua_cPluginManager_AddHook); tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand); tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand); tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin); tolua_function(tolua_S, "DoWithPlugin", StaticDoWith); tolua_function(tolua_S, "ExecuteConsoleCommand", tolua_cPluginManager_ExecuteConsoleCommand); tolua_function(tolua_S, "FindPlugins", tolua_cPluginManager_FindPlugins); tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand); tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand); tolua_function(tolua_S, "ForEachPlugin", StaticForEach); tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins); tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin); tolua_function(tolua_S, "GetPlugin", tolua_cPluginManager_GetPlugin); tolua_function(tolua_S, "LogStackTrace", tolua_cPluginManager_LogStackTrace); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cRoot"); tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cRoot_DoWithPlayerByUUID); tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith); tolua_function(tolua_S, "ForEachPlayer", ForEach); tolua_function(tolua_S, "ForEachWorld", ForEach); tolua_function(tolua_S, "GetBrewingRecipe", tolua_cRoot_GetBrewingRecipe); tolua_function(tolua_S, "GetBuildCommitID", tolua_cRoot_GetBuildCommitID); tolua_function(tolua_S, "GetBuildDateTime", tolua_cRoot_GetBuildDateTime); tolua_function(tolua_S, "GetBuildID", tolua_cRoot_GetBuildID); tolua_function(tolua_S, "GetBuildSeriesName", tolua_cRoot_GetBuildSeriesName); tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cScoreboard"); tolua_function(tolua_S, "ForEachObjective", ForEach); tolua_function(tolua_S, "ForEachTeam", ForEach); tolua_function(tolua_S, "GetTeamNames", tolua_cScoreboard_GetTeamNames); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cServer"); tolua_function(tolua_S, "RegisterForgeMod", tolua_cServer_RegisterForgeMod); tolua_function(tolua_S, "ScheduleTask", tolua_cServer_ScheduleTask); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cStringCompression"); tolua_function(tolua_S, "CompressStringZLIB", tolua_CompressStringZLIB); tolua_function(tolua_S, "UncompressStringZLIB", tolua_UncompressStringZLIB); tolua_function(tolua_S, "CompressStringGZIP", tolua_CompressStringGZIP); tolua_function(tolua_S, "UncompressStringGZIP", tolua_InflateString); tolua_function(tolua_S, "InflateString", tolua_InflateString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cUrlParser"); tolua_function(tolua_S, "GetDefaultPort", tolua_cUrlParser_GetDefaultPort); tolua_function(tolua_S, "IsKnownScheme", tolua_cUrlParser_IsKnownScheme); tolua_function(tolua_S, "Parse", tolua_cUrlParser_Parse); tolua_function(tolua_S, "ParseAuthorityPart", tolua_cUrlParser_ParseAuthorityPart); tolua_function(tolua_S, "UrlDecode", tolua_cUrlParser_UrlDecode); tolua_function(tolua_S, "UrlEncode", tolua_cUrlParser_UrlEncode); 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, "GetPage", tolua_cWebAdmin_GetPage); tolua_function(tolua_S, "GetURLEncodedString", tolua_cWebAdmin_GetURLEncodedString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "HTTPRequest"); tolua_variable(tolua_S, "FormData", tolua_get_HTTPRequest_FormData, nullptr); tolua_variable(tolua_S, "Params", tolua_get_HTTPRequest_Params, nullptr); tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, nullptr); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "StatisticsManager"); tolua_array(tolua_S, "Custom", tolua_get_StatisticsManager_Custom, tolua_set_StatisticsManager_Custom); tolua_endmodule(tolua_S); BindNetwork(tolua_S); BindRankManager(tolua_S); BindWorld(tolua_S); BindBlockArea(tolua_S); tolua_endmodule(tolua_S); }