diff options
Diffstat (limited to 'src/Bindings')
-rw-r--r-- | src/Bindings/BindingsProcessor.lua | 16 | ||||
-rw-r--r-- | src/Bindings/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/Bindings/LuaChunkStay.cpp | 6 | ||||
-rw-r--r-- | src/Bindings/LuaState.cpp | 138 | ||||
-rw-r--r-- | src/Bindings/LuaState.h | 187 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 62 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.h | 12 | ||||
-rw-r--r-- | src/Bindings/ManualBindings_Network.cpp | 7 | ||||
-rw-r--r-- | src/Bindings/ManualBindings_World.cpp | 9 | ||||
-rw-r--r-- | src/Bindings/Plugin.h | 3 | ||||
-rw-r--r-- | src/Bindings/PluginLua.cpp | 84 | ||||
-rw-r--r-- | src/Bindings/PluginLua.h | 5 | ||||
-rw-r--r-- | src/Bindings/PluginManager.cpp | 93 | ||||
-rw-r--r-- | src/Bindings/PluginManager.h | 17 |
14 files changed, 523 insertions, 125 deletions
diff --git a/src/Bindings/BindingsProcessor.lua b/src/Bindings/BindingsProcessor.lua index f86be6c6d..a398f5026 100644 --- a/src/Bindings/BindingsProcessor.lua +++ b/src/Bindings/BindingsProcessor.lua @@ -98,10 +98,12 @@ local function OutputLuaStateHelpers(a_Package) f:write("// This file expects to be included form inside the cLuaState class definition\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do - f:write("void Push(" .. item.name .. " * a_Value);\n") + if not(g_HasCustomPushImplementation[item.name]) then + f:write("void Push(" .. item.name .. " * a_Value);\n") + end end for _, item in ipairs(types) do - f:write("void GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") + f:write("bool GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") end f:write("\n\n\n\n\n") f:close() @@ -125,15 +127,17 @@ local function OutputLuaStateHelpers(a_Package) end end for _, item in ipairs(types) do - f:write("void cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") + f:write("bool cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n") - f:write("\t a_ReturnedVal = nullptr;\n") - f:write("\t return;\n\t}\n") + f:write("\t\ta_ReturnedVal = nullptr;\n") + f:write("\t\treturn false;\n\t}\n") f:write("\ttolua_Error err;\n") f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n") f:write("\t{\n") - f:write("\t a_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") + f:write("\t\ta_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") + f:write("\t\treturn true;\n"); f:write("\t}\n") + f:write("\treturn false;\n") f:write("}\n\n\n\n\n\n") end f:close() diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index 133c2224d..0a069ad85 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -145,6 +145,15 @@ set_source_files_properties(${BINDING_OUTPUTS} PROPERTIES GENERATED TRUE) set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPERTIES COMPILE_FLAGS -Wno-error) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set_source_files_properties(DeprecatedBindings.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") + set_source_files_properties(LuaState.cpp COMPILE_FLAGS "-Wno-error=old-style-cast") + set_source_files_properties(LuaWindow.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=switch-enum") + set_source_files_properties(ManualBindings.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") + set_source_files_properties(ManualBindings_World.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") + set_source_files_properties(PluginLua.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast") +endif() + if(NOT MSVC) add_library(Bindings ${SRCS} ${HDRS}) diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp index e50ffb75b..1afd09d11 100644 --- a/src/Bindings/LuaChunkStay.cpp +++ b/src/Bindings/LuaChunkStay.cpp @@ -41,7 +41,7 @@ bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos) // Add each set of coords: int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos); - m_Chunks.reserve((size_t)NumChunks); + m_Chunks.reserve(static_cast<size_t>(NumChunks)); for (int idx = 1; idx <= NumChunks; idx++) { // Push the idx-th element of the array onto stack top, check that it's a table: @@ -133,7 +133,7 @@ void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) if (m_OnChunkAvailable.IsValid()) { cPluginLua::cOperation Op(m_Plugin); - Op().Call((int)m_OnChunkAvailable, a_ChunkX, a_ChunkZ); + Op().Call(static_cast<int>(m_OnChunkAvailable), a_ChunkX, a_ChunkZ); } } @@ -147,7 +147,7 @@ bool cLuaChunkStay::OnAllChunksAvailable(void) { // Call the callback: cPluginLua::cOperation Op(m_Plugin); - Op().Call((int)m_OnAllChunksAvailable); + Op().Call(static_cast<int>(m_OnAllChunksAvailable)); // Remove the callback references - they won't be needed anymore m_OnChunkAvailable.UnRef(); diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index ccf812417..a0fdecb8b 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -211,23 +211,31 @@ void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a -bool cLuaState::LoadFile(const AString & a_FileName) +bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings) { ASSERT(IsValid()); // Load the file: int s = luaL_loadfile(m_LuaState, a_FileName.c_str()); - if (ReportErrors(s)) + if (s != 0) { - LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str()); + if (a_LogWarnings) + { + LOGWARNING("Can't load %s because of a load error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); + } + lua_pop(m_LuaState, 1); return false; } // Execute the globals: s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0); - if (ReportErrors(s)) + if (s != 0) { - LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str()); + if (a_LogWarnings) + { + LOGWARNING("Can't load %s because of an initialization error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); + } + lua_pop(m_LuaState, 1); return false; } @@ -446,6 +454,18 @@ void cLuaState::Push(const cPlayer * a_Player) +void cLuaState::Push(const cLuaState::cRef & a_Ref) +{ + ASSERT(IsValid()); + + lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast<int>(a_Ref)); + m_NumCurrentFunctionArgs += 1; +} + + + + + void cLuaState::Push(const HTTPRequest * a_Request) { ASSERT(IsValid()); @@ -701,108 +721,142 @@ void cLuaState::PushUserType(void * a_Object, const char * a_Type) -void cLuaState::GetStackValue(int a_StackPos, AString & a_Value) +bool cLuaState::GetStackValue(int a_StackPos, AString & a_Value) { size_t len = 0; const char * data = lua_tolstring(m_LuaState, a_StackPos, &len); if (data != nullptr) { a_Value.assign(data, len); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, BLOCKTYPE & a_ReturnedVal) -{ - if (lua_isnumber(m_LuaState, a_StackPos)) - { - a_ReturnedVal = static_cast<BLOCKTYPE>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); - } -} - - - - - -void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) { a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0); + return true; } -void cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) +bool cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_Result = static_cast<cPluginManager::CommandResult>(static_cast<int>((tolua_tonumber(m_LuaState, a_StackPos, a_Result)))); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) +bool cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) { a_Ref.RefStack(*this, a_StackPos); + return true; } -void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_ReturnedVal = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal); + return true; } + return false; } -void cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, eBlockFace & a_ReturnedVal) { - if (lua_isnumber(m_LuaState, a_StackPos)) + if (!lua_isnumber(m_LuaState, a_StackPos)) { - a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); + return false; } + a_ReturnedVal = static_cast<eBlockFace>(Clamp( + static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)), + static_cast<int>(BLOCK_FACE_MIN), static_cast<int>(BLOCK_FACE_MAX)) + ); + return true; } -void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) { if (!lua_isnumber(m_LuaState, a_StackPos)) { - return; + return false; } a_ReturnedVal = static_cast<eWeather>(Clamp( static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)), static_cast<int>(wSunny), static_cast<int>(wThunderstorm)) ); + return true; } -void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal) +bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { - a_ReturnedVal = static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); + a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); + return true; } + return false; +} + + + + + +cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name) +{ + // There needs to be at least one value on the stack: + ASSERT(lua_gettop(m_LuaState) > 0); + + // Iterate over path and replace the top of the stack with the walked element + lua_pushvalue(m_LuaState, -1); // Copy the stack value into the "working area" + auto path = StringSplit(a_Name, "."); + for (const auto & elem: path) + { + // If the value is not a table, bail out (error): + if (!lua_istable(m_LuaState, -1)) + { + lua_pop(m_LuaState, 1); + return cStackValue(); + } + + // Get the next part of the path: + lua_getfield(m_LuaState, -1, elem.c_str()); + + // Remove the previous value from the stack (keep only the new one): + lua_remove(m_LuaState, -2); + } // for elem - path[] + return std::move(cStackValue(*this)); } @@ -927,6 +981,9 @@ bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam) VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != nullptr) ? entry.name : "?"); + + BreakIntoDebugger(m_LuaState); + tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param @@ -1366,6 +1423,7 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState) { LOGWARNING("LUA: %s", lua_tostring(a_LuaState, -1)); LogStackTrace(a_LuaState, 1); + BreakIntoDebugger(a_LuaState); return 1; // We left the error message on the stack as the return value } @@ -1373,6 +1431,28 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState) +int cLuaState::BreakIntoDebugger(lua_State * a_LuaState) +{ + // Call the BreakIntoDebugger function, if available: + lua_getglobal(a_LuaState, "BreakIntoDebugger"); + if (!lua_isfunction(a_LuaState, -1)) + { + LOGD("LUA: BreakIntoDebugger() not found / not a function"); + lua_pop(a_LuaState, 1); + return 1; + } + lua_insert(a_LuaState, -2); // Copy the string that has been passed to us + LOGD("Calling BreakIntoDebugger()..."); + lua_call(a_LuaState, 1, 0); + LOGD("Returned from BreakIntoDebugger()."); + + return 0; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cLuaState::cRef: diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index b38401fd8..cc8214646 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -78,11 +78,14 @@ public: bool IsValid(void) const {return (m_Ref != LUA_REFNIL); } /** Allows to use this class wherever an int (i. e. ref) is to be used */ - operator int(void) const { return m_Ref; } - + explicit operator int(void) const { return m_Ref; } + protected: cLuaState * m_LuaState; int m_Ref; + + // Remove the copy-constructor: + cRef(const cRef &) = delete; } ; @@ -98,6 +101,12 @@ public: { } + cTableRef(const cRef & a_TableRef, const char * a_FnName) : + m_TableRef(static_cast<int>(a_TableRef)), + m_FnName(a_FnName) + { + } + int GetTableRef(void) const { return m_TableRef; } const char * GetFnName(void) const { return m_FnName; } } ; @@ -111,6 +120,61 @@ public: static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call() + /** A RAII class for values pushed onto the Lua stack. + Will pop the value off the stack in the destructor. */ + class cStackValue + { + public: + cStackValue(void): + m_LuaState(nullptr) + { + } + + cStackValue(cLuaState & a_LuaState): + m_LuaState(a_LuaState) + { + m_StackLen = lua_gettop(a_LuaState); + } + + cStackValue(cStackValue && a_Src): + m_LuaState(nullptr), + m_StackLen(-1) + { + std::swap(m_LuaState, a_Src.m_LuaState); + std::swap(m_StackLen, a_Src.m_StackLen); + } + + ~cStackValue() + { + if (m_LuaState != nullptr) + { + auto top = lua_gettop(m_LuaState); + ASSERT(m_StackLen == top); + lua_pop(m_LuaState, 1); + } + } + + void Set(cLuaState & a_LuaState) + { + m_LuaState = a_LuaState; + m_StackLen = lua_gettop(a_LuaState); + } + + bool IsValid(void) const + { + return (m_LuaState != nullptr); + } + + protected: + lua_State * m_LuaState; + + int m_StackLen; + + // Remove the copy-constructor: + cStackValue(const cStackValue &) = delete; + }; + + /** Creates a new instance. The LuaState is not initialized. a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins, or "LuaScript" for the cLuaScript template @@ -151,10 +215,9 @@ public: void AddPackagePath(const AString & a_PathVariable, const AString & a_Path); /** Loads the specified file - Returns false and logs a warning to the console if not successful (but the LuaState is kept open). - m_SubsystemName is displayed in the warning log message. - */ - bool LoadFile(const AString & a_FileName); + Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open). + m_SubsystemName is displayed in the warning log message. */ + bool LoadFile(const AString & a_FileName, bool a_LogWarnings = true); /** Returns true if a_FunctionName is a valid Lua function that can be called */ bool HasFunction(const char * a_FunctionName); @@ -169,6 +232,7 @@ public: void Push(const char * a_Value); void Push(const cItems & a_Items); void Push(const cPlayer * a_Player); + void Push(const cRef & a_Ref); void Push(const HTTPRequest * a_Request); void Push(const HTTPTemplateRequest * a_Request); void Push(const Vector3d & a_Vector); @@ -178,25 +242,80 @@ public: // Push a simple value onto the stack (keep alpha-sorted): void Push(bool a_Value); + void Push(cEntity * a_Entity); + void Push(cLuaServerHandle * a_ServerHandle); + void Push(cLuaTCPLink * a_TCPLink); + void Push(cLuaUDPEndpoint * a_UDPEndpoint); void Push(double a_Value); void Push(int a_Value); void Push(void * a_Ptr); void Push(std::chrono::milliseconds a_time); - void Push(cLuaServerHandle * a_ServerHandle); - void Push(cLuaTCPLink * a_TCPLink); - void Push(cLuaUDPEndpoint * a_UDPEndpoint); // GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged. - // Enum values are clamped to their allowed range. - void GetStackValue(int a_StackPos, AString & a_Value); - void GetStackValue(int a_StackPos, BLOCKTYPE & a_Value); - void GetStackValue(int a_StackPos, bool & a_Value); - void GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); - void GetStackValue(int a_StackPos, cRef & a_Ref); - void GetStackValue(int a_StackPos, double & a_Value); - void GetStackValue(int a_StackPos, eWeather & a_Value); - void GetStackValue(int a_StackPos, float & a_ReturnedVal); - void GetStackValue(int a_StackPos, int & a_Value); + // Returns whether value was changed + // Enum values are checked for their allowed values and fail if the value is not assigned. + bool GetStackValue(int a_StackPos, AString & a_Value); + bool GetStackValue(int a_StackPos, bool & a_Value); + bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); + bool GetStackValue(int a_StackPos, cRef & a_Ref); + bool GetStackValue(int a_StackPos, double & a_Value); + bool GetStackValue(int a_StackPos, eBlockFace & a_Value); + bool GetStackValue(int a_StackPos, eWeather & a_Value); + bool GetStackValue(int a_StackPos, float & a_ReturnedVal); + + // template to catch all of the various c++ integral types without overload conflicts + template <class T> + bool GetStackValue(int a_StackPos, T & a_ReturnedVal, typename std::enable_if<std::is_integral<T>::value>::type * unused = nullptr) + { + UNUSED(unused); + if (!lua_isnumber(m_LuaState, a_StackPos)) // Also accepts strings representing a number: http://pgl.yoyo.org/luai/i/lua_isnumber + { + return false; + } + lua_Number Val = lua_tonumber(m_LuaState, a_StackPos); + if (Val > std::numeric_limits<T>::max()) + { + return false; + } + if (Val < std::numeric_limits<T>::min()) + { + return false; + } + a_ReturnedVal = static_cast<T>(Val); + return true; + } + + /** Pushes the named value in the table at the top of the stack. + a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue". + If the value is found, it is pushed on top of the stack and the returned cStackValue is valid. + If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */ + cStackValue WalkToValue(const AString & a_Name); + + /** Retrieves the named value in the table at the top of the Lua stack. + a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue". + Returns true if the value was successfully retrieved, false on error. */ + template <typename T> bool GetNamedValue(const AString & a_Name, T & a_Value) + { + auto stk = WalkToValue(a_Name); + if (!stk.IsValid()) + { + // Name not found + return false; + } + return GetStackValue(-1, a_Value); + } + + /** Retrieves the named global value. a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue". + Returns true if the value was successfully retrieved, false on error. */ + template <typename T> bool GetNamedGlobal(const AString & a_Name, T & a_Value) + { + // Push the globals table onto the stack and make it RAII-removed: + lua_getglobal(m_LuaState, "_G"); + cStackValue stk(*this); + + // Get the named global: + return GetNamedValue(a_Name, a_Value); + } // Include the auto-generated Push and GetStackValue() functions: #include "LuaState_Declaration.inc" @@ -208,20 +327,23 @@ public: template <typename FnT, typename... Args> bool Call(const FnT & a_Function, Args &&... args) { - if (!PushFunction(a_Function)) + if (!PushFunction(std::forward<const FnT &>(a_Function))) { // Pushing the function failed return false; } - return PushCallPop(args...); + return PushCallPop(std::forward<Args>(args)...); } /** Retrieves a list of values from the Lua stack, starting at the specified index. */ template <typename T, typename... Args> - inline void GetStackValues(int a_StartStackPos, T & a_Ret, Args &&... args) + inline bool GetStackValues(int a_StartStackPos, T & a_Ret, Args &&... args) { - GetStackValue(a_StartStackPos, a_Ret); - GetStackValues(a_StartStackPos + 1, args...); + if (!GetStackValue(a_StartStackPos, a_Ret)) + { + return false; + } + return GetStackValues(a_StartStackPos + 1, args...); } /** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */ @@ -319,10 +441,10 @@ protected: /** Variadic template recursor: More params to push. Push them and recurse. */ template <typename T, typename... Args> - inline bool PushCallPop(T a_Param, Args &&... args) + inline bool PushCallPop(T && a_Param, Args &&... args) { - Push(a_Param); - return PushCallPop(args...); + Push(std::forward<T>(a_Param)); + return PushCallPop(std::forward<Args>(args)...); } /** Variadic template terminator: If there's nothing more to push, but return values to collect, call the function and collect the returns. */ @@ -339,7 +461,7 @@ protected: } // Collect the return values: - GetStackValues(-NumReturns, args...); + GetStackValues(-NumReturns, std::forward<Args>(args)...); lua_pop(m_LuaState, NumReturns); // All successful: @@ -349,9 +471,9 @@ protected: /** Variadic template terminator: If there are no more values to get, bail out. This function is not available in the public API, because it's an error to request no values directly; only internal functions can do that. If you get a compile error saying this function is not accessible, check your calling code, you aren't reading any stack values. */ - void GetStackValues(int a_StartingStackPos) + bool GetStackValues(int a_StartingStackPos) { - // Do nothing + return true; } /** Pushes the function of the specified name onto the stack. @@ -369,7 +491,7 @@ protected: */ bool PushFunction(const cRef & a_FnRef) { - return PushFunction((int)a_FnRef); + return PushFunction(static_cast<int>(a_FnRef)); } /** Pushes a function that is stored in a referenced table by name @@ -389,6 +511,9 @@ protected: /** Used as the error reporting function for function calls */ static int ReportFnCallErrors(lua_State * a_LuaState); + + /** Tries to break into the MobDebug debugger, if it is installed. */ + static int BreakIntoDebugger(lua_State * a_LuaState); } ; diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index ff904d74a..7655d8c83 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -34,6 +34,7 @@ #include "../CompositeChat.h" #include "../StringCompression.h" #include "../CommandOutput.h" +#include "../BuildInfo.h" @@ -158,7 +159,7 @@ static int tolua_UncompressStringZLIB(lua_State * tolua_S) // Get the params: AString ToUncompress; - int UncompressedSize; + size_t UncompressedSize; S.GetStackValues(1, ToUncompress, UncompressedSize); // Compress the string: @@ -1801,7 +1802,7 @@ static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L) // Convert the input table into AStringVector: AStringVector PlayerNames; int NumNames = luaL_getn(L, 2); - PlayerNames.reserve(NumNames); + PlayerNames.reserve(static_cast<size_t>(NumNames)); for (int i = 1; i <= NumNames; i++) { lua_rawgeti(L, 2, i); @@ -2079,6 +2080,50 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S) +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_GetFurnaceRecipe(lua_State * tolua_S) { cLuaState L(tolua_S); @@ -2092,7 +2137,8 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S) } // Check the input param: - cItem * Input = (cItem *)tolua_tousertype(L, 2, nullptr); + cItem * Input = nullptr; + L.GetStackValue(2, Input); if (Input == nullptr) { LOGWARNING("cRoot:GetFurnaceRecipe: the Input parameter is nil or missing."); @@ -2109,9 +2155,9 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S) } // Push the output, number of ticks and input as the three return values: - tolua_pushusertype(L, Recipe->Out, "const cItem"); - tolua_pushnumber (L, (lua_Number)(Recipe->CookTime)); - tolua_pushusertype(L, Recipe->In, "const cItem"); + L.Push(Recipe->Out); + L.Push(Recipe->CookTime); + L.Push(Recipe->In); return 3; } @@ -2868,6 +2914,10 @@ void cManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith <cRoot, cPlayer, &cRoot::DoWithPlayerByUUID>); tolua_function(tolua_S, "ForEachPlayer", ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>); tolua_function(tolua_S, "ForEachWorld", ForEach<cRoot, cWorld, &cRoot::ForEachWorld>); + 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); diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h index e7a576588..f8c9b96de 100644 --- a/src/Bindings/ManualBindings.h +++ b/src/Bindings/ManualBindings.h @@ -199,7 +199,7 @@ public: // Get parameters: Ty1 * Self = nullptr; - int ItemID; + UInt32 ItemID; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ItemID, FnRef); if (Self == nullptr) @@ -253,8 +253,9 @@ public: // Check params: cLuaState L(tolua_S); if ( - !L.CheckParamNumber(2, 5) || - !L.CheckParamFunction(6) + !L.CheckParamNumber(2, 4) || + !L.CheckParamFunction(5) || + !L.CheckParamEnd(6) ) { return 0; @@ -316,8 +317,9 @@ public: // Check params: cLuaState L(tolua_S); if ( - !L.CheckParamNumber(2, 4) || - !L.CheckParamFunction(5) + !L.CheckParamNumber(2, 3) || + !L.CheckParamFunction(4) || + !L.CheckParamEnd(5) ) { return 0; diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index df97d60b3..b5fb5b046 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -101,13 +101,12 @@ static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L) } // Read the params: - int Port; - S.GetStackValues(2, Port); + UInt16 Port; // Check validity: - if ((Port < 0) || (Port > 65535)) + if (!S.GetStackValues(2, Port)) { - LOGWARNING("cNetwork:CreateUDPEndpoint() called with invalid port (%d), failing the request.", Port); + LOGWARNING("cNetwork:CreateUDPEndpoint() called with invalid port, failing the request."); S.Push(false); return 1; } diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index 3ee5ca498..d9590de33 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -50,7 +50,7 @@ static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S) std::array<int, 2> data; for (int i = 0; (i < 2) && L.IsParamNumber(11 + i); i++) { - L.GetStackValue(11 + i, data[i]); + L.GetStackValue(11 + i, data[static_cast<size_t>(i)]); } World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmmount, ExcludeClient); @@ -303,10 +303,9 @@ static int tolua_cWorld_PrepareChunk(lua_State * tolua_S) cLuaState m_LuaState; cLuaState::cRef m_Callback; }; - cCallback * callback = new cCallback(tolua_S); // Call the chunk preparation: - world->PrepareChunk(chunkX, chunkZ, callback); + world->PrepareChunk(chunkX, chunkZ, cpp14::make_unique<cCallback>(tolua_S)); return 0; } @@ -491,7 +490,7 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S) auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef); Plugin->AddResettable(task); - World->ScheduleTask(DelayTicks, task); + World->ScheduleTask(DelayTicks, static_cast<cWorld::cTaskPtr>(task)); return 0; } @@ -530,7 +529,7 @@ static int tolua_cWorld_TryGetHeight(lua_State * tolua_S) // Call the implementation: int Height = 0; bool res = self->TryGetHeight(BlockX, BlockZ, Height); - L.Push(res ? 1 : 0); + L.Push(res); if (res) { L.Push(Height); diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h index d0c2bcefa..2fdf73a65 100644 --- a/src/Bindings/Plugin.h +++ b/src/Bindings/Plugin.h @@ -56,12 +56,15 @@ public: virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0; virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0; + virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) = 0; + virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) = 0; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0; + virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) = 0; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0; virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) = 0; virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0; diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 76d3557a4..9be4e0eb4 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -534,6 +534,54 @@ bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_E +bool cPluginLua::OnEntityChangingWorld(cEntity & a_Entity, cWorld & a_World) +{ + cCSLock Lock(m_CriticalSection); + if (!m_LuaState.IsValid()) + { + return false; + } + bool res = false; + cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGING_WORLD]; + for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr) + { + m_LuaState.Call((int)(**itr), &a_Entity, &a_World, cLuaState::Return, res); + if (res) + { + return true; + } + } + return false; +} + + + + + +bool cPluginLua::OnEntityChangedWorld(cEntity & a_Entity, cWorld & a_World) +{ + cCSLock Lock(m_CriticalSection); + if (!m_LuaState.IsValid()) + { + return false; + } + bool res = false; + cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGED_WORLD]; + for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr) + { + m_LuaState.Call((int)(**itr), &a_Entity, &a_World, res); + if (res) + { + return true; + } + } + return false; +} + + + + + bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) { cCSLock Lock(m_CriticalSection); @@ -581,11 +629,6 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res); break; - default: - { - ASSERT(!"Unhandled ExplosionSource"); - return false; - } } if (res) { @@ -622,11 +665,6 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool & case esWitherSkullBlue: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherBirth: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPlugin: m_LuaState.Call((int)(**itr), &a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; - default: - { - ASSERT(!"Unhandled ExplosionSource"); - return false; - } } if (res) { @@ -712,6 +750,30 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper, +bool cPluginLua::OnKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) +{ + cCSLock Lock(m_CriticalSection); + if (!m_LuaState.IsValid()) + { + return false; + } + bool res = false; + cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_KILLED]; + for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr) + { + m_LuaState.Call((int)(**itr), &a_Victim, &a_TDI, a_DeathMessage, cLuaState::Return, res, a_DeathMessage); + if (res) + { + return true; + } + } + return false; +} + + + + + bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) { cCSLock Lock(m_CriticalSection); @@ -1884,6 +1946,8 @@ const char * cPluginLua::GetHookFnName(int a_HookType) case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect"; case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation"; case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect"; + case cPluginManager::HOOK_ENTITY_CHANGING_WORLD: return "OnEntityChangingWorld"; + case cPluginManager::HOOK_ENTITY_CHANGED_WORLD: return "OnEntityChangedWorld"; case cPluginManager::HOOK_ENTITY_TELEPORT: return "OnEntityTeleport"; case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand"; case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake"; diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h index 524c249b0..7de70ef1f 100644 --- a/src/Bindings/PluginLua.h +++ b/src/Bindings/PluginLua.h @@ -115,12 +115,15 @@ public: virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override; + virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) override; + virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) override; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override; + virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) override; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override; virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) override; virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override; @@ -177,7 +180,7 @@ public: bool CanAddOldStyleHook(int a_HookType); // cWebPlugin overrides - virtual const AString GetWebTitle(void) const {return GetName(); } + virtual const AString GetWebTitle(void) const override {return GetName(); } virtual AString HandleWebRequest(const HTTPRequest & a_Request) override; /** Adds a new web tab to webadmin. diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index db2493955..712c385c7 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -118,7 +118,7 @@ void cPluginManager::ReloadPluginsNow(void) -void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni) +void cPluginManager::ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings) { LOG("-- Loading Plugins --"); @@ -130,7 +130,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni) RefreshPluginList(); // Load the plugins: - AStringVector ToLoad = GetFoldersToLoad(a_SettingsIni); + AStringVector ToLoad = GetFoldersToLoad(a_Settings); for (auto & pluginFolder: ToLoad) { LoadPlugin(pluginFolder); @@ -157,16 +157,16 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni) -void cPluginManager::InsertDefaultPlugins(cIniFile & a_SettingsIni) +void cPluginManager::InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings) { - a_SettingsIni.AddKeyName("Plugins"); - a_SettingsIni.AddKeyComment("Plugins", " Plugin=Debuggers"); - a_SettingsIni.AddKeyComment("Plugins", " Plugin=HookNotify"); - a_SettingsIni.AddKeyComment("Plugins", " Plugin=ChunkWorx"); - a_SettingsIni.AddKeyComment("Plugins", " Plugin=APIDump"); - a_SettingsIni.AddValue("Plugins", "Plugin", "Core"); - a_SettingsIni.AddValue("Plugins", "Plugin", "TransAPI"); - a_SettingsIni.AddValue("Plugins", "Plugin", "ChatLog"); + a_Settings.AddKeyName("Plugins"); + a_Settings.AddKeyComment("Plugins", " Plugin=Debuggers"); + a_Settings.AddKeyComment("Plugins", " Plugin=HookNotify"); + a_Settings.AddKeyComment("Plugins", " Plugin=ChunkWorx"); + a_Settings.AddKeyComment("Plugins", " Plugin=APIDump"); + a_Settings.AddValue("Plugins", "Plugin", "Core"); + a_Settings.AddValue("Plugins", "Plugin", "TransAPI"); + a_Settings.AddValue("Plugins", "Plugin", "ChatLog"); } @@ -525,6 +525,42 @@ bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d & +bool cPluginManager::CallHookEntityChangingWorld(cEntity & a_Entity, cWorld & a_World) +{ + FIND_HOOK(HOOK_ENTITY_CHANGING_WORLD); + VERIFY_HOOK; + + for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) + { + if ((*itr)->OnEntityChangingWorld(a_Entity, a_World)) + { + return true; + } + } + return false; +} + + + + +bool cPluginManager::CallHookEntityChangedWorld(cEntity & a_Entity, cWorld & a_World) +{ + FIND_HOOK(HOOK_ENTITY_CHANGED_WORLD); + VERIFY_HOOK; + + for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) + { + if ((*itr)->OnEntityChangedWorld(a_Entity, a_World)) + { + return true; + } + } + return false; +} + + + + bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result) { FIND_HOOK(HOOK_EXECUTE_COMMAND); @@ -639,6 +675,25 @@ bool cPluginManager::CallHookHopperPushingItem(cWorld & a_World, cHopperEntity & +bool cPluginManager::CallHookKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) +{ + FIND_HOOK(HOOK_KILLED); + VERIFY_HOOK; + + for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) + { + if ((*itr)->OnKilled(a_Victim, a_TDI, a_DeathMessage)) + { + return true; + } + } + return false; +} + + + + + bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) { FIND_HOOK(HOOK_KILLING); @@ -1896,25 +1951,23 @@ size_t cPluginManager::GetNumLoadedPlugins(void) const -AStringVector cPluginManager::GetFoldersToLoad(cIniFile & a_SettingsIni) +AStringVector cPluginManager::GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings) { // Check if the Plugins section exists. - int KeyNum = a_SettingsIni.FindKey("Plugins"); - if (KeyNum == -1) + if (!a_Settings.KeyExists("Plugins")) { - InsertDefaultPlugins(a_SettingsIni); - KeyNum = a_SettingsIni.FindKey("Plugins"); + InsertDefaultPlugins(a_Settings); } // Get the list of plugins to load: AStringVector res; - int NumPlugins = a_SettingsIni.GetNumValues(KeyNum); - for (int i = 0; i < NumPlugins; i++) + auto Values = a_Settings.GetValues("Plugins"); + for (auto NameValue : Values) { - AString ValueName = a_SettingsIni.GetValueName(KeyNum, i); + AString ValueName = NameValue.first; if (ValueName.compare("Plugin") == 0) { - AString PluginFile = a_SettingsIni.GetValue(KeyNum, i); + AString PluginFile = NameValue.second; if (!PluginFile.empty()) { res.push_back(PluginFile); diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index d8c886b62..153f4996d 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -24,6 +24,7 @@ class cPlayer; class cPlugin; class cProjectileEntity; class cWorld; +class cSettingsRepositoryInterface; struct TakeDamageInfo; typedef SharedPtr<cPlugin> cPluginPtr; @@ -85,12 +86,15 @@ public: HOOK_DISCONNECT, HOOK_PLAYER_ANIMATION, HOOK_ENTITY_ADD_EFFECT, + HOOK_ENTITY_CHANGING_WORLD, + HOOK_ENTITY_CHANGED_WORLD, HOOK_EXECUTE_COMMAND, HOOK_EXPLODED, HOOK_EXPLODING, HOOK_HANDSHAKE, HOOK_HOPPER_PULLING_ITEM, HOOK_HOPPER_PUSHING_ITEM, + HOOK_KILLED, HOOK_KILLING, HOOK_LOGIN, HOOK_PLAYER_BREAKING_BLOCK, @@ -200,12 +204,15 @@ public: bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason); bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier); bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition); + bool CallHookEntityChangingWorld (cEntity & a_Entity, cWorld & a_World); + bool CallHookEntityChangedWorld (cEntity & a_Entity, cWorld & a_World); bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username); bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum); bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum); + bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage); bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI); bool CallHookLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username); bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation); @@ -364,20 +371,20 @@ private: /** Reloads all plugins, defaulting to settings.ini for settings location */ void ReloadPluginsNow(void); - /** Reloads all plugins with a cIniFile object expected to be initialised to settings.ini */ - void ReloadPluginsNow(cIniFile & a_SettingsIni); + /** Reloads all plugins with a settings repo expected to be initialised to settings.ini */ + void ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings); /** Unloads all plugins */ void UnloadPluginsNow(void); - /** Handles writing default plugins if 'Plugins' key not found using a cIniFile object expected to be intialised to settings.ini */ - void InsertDefaultPlugins(cIniFile & a_SettingsIni); + /** Handles writing default plugins if 'Plugins' key not found using a settings repo expected to be intialised to settings.ini */ + void InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings); /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */ CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions); /** Returns the folders that are specified in the settings ini to load plugins from. */ - AStringVector GetFoldersToLoad(cIniFile & a_SettingsIni); + AStringVector GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings); } ; // tolua_export |