summaryrefslogtreecommitdiffstats
path: root/src/Bindings
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings')
-rw-r--r--src/Bindings/BindingsProcessor.lua16
-rw-r--r--src/Bindings/CMakeLists.txt9
-rw-r--r--src/Bindings/LuaChunkStay.cpp6
-rw-r--r--src/Bindings/LuaState.cpp138
-rw-r--r--src/Bindings/LuaState.h187
-rw-r--r--src/Bindings/ManualBindings.cpp62
-rw-r--r--src/Bindings/ManualBindings.h12
-rw-r--r--src/Bindings/ManualBindings_Network.cpp7
-rw-r--r--src/Bindings/ManualBindings_World.cpp9
-rw-r--r--src/Bindings/Plugin.h3
-rw-r--r--src/Bindings/PluginLua.cpp84
-rw-r--r--src/Bindings/PluginLua.h5
-rw-r--r--src/Bindings/PluginManager.cpp93
-rw-r--r--src/Bindings/PluginManager.h17
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