summaryrefslogtreecommitdiffstats
path: root/src/Bindings
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings')
-rw-r--r--src/Bindings/.gitignore4
-rw-r--r--src/Bindings/AllToLua.bat2
-rw-r--r--src/Bindings/AllToLua.sh2
-rw-r--r--src/Bindings/AllToLua_lua.bat2
-rw-r--r--src/Bindings/BindingsProcessor.lua161
-rw-r--r--src/Bindings/CMakeLists.txt16
-rw-r--r--src/Bindings/LuaState.cpp363
-rw-r--r--src/Bindings/LuaState.h100
-rw-r--r--src/Bindings/LuaWindow.cpp6
-rw-r--r--src/Bindings/ManualBindings.cpp1663
-rw-r--r--src/Bindings/ManualBindings.h549
-rw-r--r--src/Bindings/ManualBindings_Network.cpp22
-rw-r--r--src/Bindings/ManualBindings_RankManager.cpp320
-rw-r--r--src/Bindings/ManualBindings_World.cpp588
-rw-r--r--src/Bindings/Plugin.cpp34
-rw-r--r--src/Bindings/Plugin.h99
-rw-r--r--src/Bindings/PluginLua.cpp375
-rw-r--r--src/Bindings/PluginLua.h22
-rw-r--r--src/Bindings/PluginManager.cpp435
-rw-r--r--src/Bindings/PluginManager.h171
-rw-r--r--src/Bindings/WebPlugin.cpp110
-rw-r--r--src/Bindings/WebPlugin.h61
-rw-r--r--src/Bindings/virtual_method_hooks.lua518
23 files changed, 2989 insertions, 2634 deletions
diff --git a/src/Bindings/.gitignore b/src/Bindings/.gitignore
index 0d00dd578..711ae9c3a 100644
--- a/src/Bindings/.gitignore
+++ b/src/Bindings/.gitignore
@@ -1,2 +1,4 @@
lua51.dll
-LuaState_Call.inc
+LuaState_Declaration.inc
+LuaState_Implementation.cpp
+LuaState_Typedefs.inc
diff --git a/src/Bindings/AllToLua.bat b/src/Bindings/AllToLua.bat
index f085af9e9..44675a886 100644
--- a/src/Bindings/AllToLua.bat
+++ b/src/Bindings/AllToLua.bat
@@ -12,7 +12,7 @@
:: Regenerate the files:
echo Regenerating LUA bindings . . .
-"tolua++.exe" -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+"tolua++.exe" -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
diff --git a/src/Bindings/AllToLua.sh b/src/Bindings/AllToLua.sh
index 887c2490c..625ae4300 100644
--- a/src/Bindings/AllToLua.sh
+++ b/src/Bindings/AllToLua.sh
@@ -1,2 +1,2 @@
#!/bin/bash
-/usr/bin/tolua++ -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+/usr/bin/tolua++ -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
diff --git a/src/Bindings/AllToLua_lua.bat b/src/Bindings/AllToLua_lua.bat
index 81c738f32..2d52c022d 100644
--- a/src/Bindings/AllToLua_lua.bat
+++ b/src/Bindings/AllToLua_lua.bat
@@ -13,7 +13,7 @@
:: Regenerate the files:
echo Regenerating LUA bindings . . .
-lua ..\..\lib\tolua++\src\bin\lua\_driver.lua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+lua ..\..\lib\tolua++\src\bin\lua\_driver.lua -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
diff --git a/src/Bindings/BindingsProcessor.lua b/src/Bindings/BindingsProcessor.lua
new file mode 100644
index 000000000..f86be6c6d
--- /dev/null
+++ b/src/Bindings/BindingsProcessor.lua
@@ -0,0 +1,161 @@
+
+-- BindingsProcessor.lua
+
+-- Implements additional processing that is done while generating the Lua bindings
+
+
+
+
+
+local access = {public = 0, protected = 1, private = 2}
+
+
+
+
+
+--- Defines classes that have a custom manual Push() implementation and should not generate the automatic one
+-- Map of classname -> true
+local g_HasCustomPushImplementation =
+{
+ cEntity = true
+}
+
+
+
+
+
+function parser_hook(s)
+ local container = classContainer.curr -- get the current container
+
+ -- process access-specifying labels (public, private, etc)
+ do
+ local b, e, label = string.find(s, "^%s*(%w*)%s*:[^:]") -- we need to check for [^:], otherwise it would match 'namespace::type'
+ if b then
+
+ -- found a label, get the new access value from the global 'access' table
+ if access[label] then
+ container.curr_member_access = access[label]
+ end -- else ?
+
+ return strsub(s, e) -- normally we would use 'e+1', but we need to preserve the [^:]
+ end
+ end
+end
+
+
+
+
+
+--- Outputs the helper files supplementing the cLuaState class
+-- Writes:
+-- LuaState_Declaration.inc
+-- LuaState_Implementation.cpp
+-- LuaState_Typedefs.inc
+local function OutputLuaStateHelpers(a_Package)
+ -- Collect all class types from ToLua:
+ local types = {}
+ for idx, item in ipairs(a_Package) do
+ local mt = getmetatable(item) or {}
+ if (mt.classtype == "class") then
+ table.insert(types, {name = item.name, lname = item.lname})
+ end
+ end
+ table.sort(types,
+ function(a_Item1, a_Item2)
+ return (a_Item1.name:lower() < a_Item2.name:lower())
+ end
+ )
+
+ -- Output the typedefs:
+ do
+ local f = assert(io.open("LuaState_Typedefs.inc", "w"))
+ f:write("\n// LuaState_Typedefs.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
+ f:write("// Provides a forward declaration and a typedef for a pointer to each class exported to the Lua API.\n")
+ f:write("\n\n\n\n\n")
+ for _, item in ipairs(types) do
+ if not(item.name:match(".*<.*")) then -- Skip templates altogether
+ -- Classes start with a "c", everything else is a struct:
+ if (item.name:sub(1, 1) == "c") then
+ f:write("class " .. item.name .. ";\n")
+ else
+ f:write("struct " .. item.name .. ";\n")
+ end
+ end
+ end
+ f:write("\n\n\n\n\n")
+ for _, item in ipairs(types) do
+ f:write("typedef " .. item.name .. " * Ptr" .. item.lname .. ";\n")
+ end
+ f:write("\n\n\n\n\n")
+ f:close()
+ end
+
+ -- Output the Push() and GetStackValue() function declarations:
+ do
+ local f = assert(io.open("LuaState_Declaration.inc", "w"))
+ f:write("\n// LuaState_Declaration.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
+ f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n")
+ 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")
+ end
+ for _, item in ipairs(types) do
+ f:write("void GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n")
+ end
+ f:write("\n\n\n\n\n")
+ f:close()
+ end
+
+ -- Output the Push() and GetStackValue() function implementations:
+ do
+ local f = assert(io.open("LuaState_Implementation.cpp", "w"))
+ f:write("\n// LuaState_Implementation.cpp\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n")
+ f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n")
+ f:write("// This file expects to be compiled as a separate translation unit\n")
+ f:write("\n\n\n\n\n")
+ f:write("#include \"Globals.h\"\n#include \"LuaState.h\"\n#include \"tolua++/include/tolua++.h\"\n")
+ f:write("\n\n\n\n\n")
+ for _, item in ipairs(types) do
+ if not(g_HasCustomPushImplementation[item.name]) then
+ f:write("void cLuaState::Push(" .. item.name .. " * a_Value)\n{\n\tASSERT(IsValid());\n")
+ f:write("\ttolua_pushusertype(m_LuaState, a_Value, \"" .. item.name .. "\");\n");
+ f:write("\tm_NumCurrentFunctionArgs += 1;\n")
+ f:write("}\n\n\n\n\n\n")
+ 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("\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("\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}\n")
+ f:write("}\n\n\n\n\n\n")
+ end
+ f:close()
+ end
+end
+
+
+
+
+
+function pre_output_hook(a_Package)
+ OutputLuaStateHelpers(a_Package)
+end
+
+
+
+
+
+function post_output_hook()
+ print("Bindings have been generated.")
+end
+
+
+
+
diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt
index 4cc73b350..133c2224d 100644
--- a/src/Bindings/CMakeLists.txt
+++ b/src/Bindings/CMakeLists.txt
@@ -11,12 +11,14 @@ SET (SRCS
LuaNameLookup.cpp
LuaServerHandle.cpp
LuaState.cpp
+ LuaState_Implementation.cpp
LuaTCPLink.cpp
LuaUDPEndpoint.cpp
LuaWindow.cpp
ManualBindings.cpp
ManualBindings_Network.cpp
ManualBindings_RankManager.cpp
+ ManualBindings_World.cpp
Plugin.cpp
PluginLua.cpp
PluginManager.cpp
@@ -31,6 +33,8 @@ SET (HDRS
LuaNameLookup.h
LuaServerHandle.h
LuaState.h
+ LuaState_Declaration.inc
+ LuaState_Typedefs.inc
LuaTCPLink.h
LuaUDPEndpoint.h
LuaWindow.h
@@ -46,12 +50,15 @@ SET (HDRS
set (BINDING_OUTPUTS
${CMAKE_CURRENT_SOURCE_DIR}/Bindings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bindings.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaState_Declaration.inc
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaState_Implementation.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaState_Typedefs.inc
)
set(BINDING_DEPENDENCIES
tolua
- ../Bindings/virtual_method_hooks.lua
../Bindings/AllToLua.pkg
+ ../Bindings/BindingsProcessor.lua
../Bindings/LuaFunctions.h
../Bindings/LuaWindow.h
../Bindings/Plugin.h
@@ -126,7 +133,7 @@ if (NOT MSVC)
OUTPUT ${BINDING_OUTPUTS}
# Regenerate bindings:
- COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+ COMMAND tolua -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
# add any new generation dependencies here
@@ -134,13 +141,12 @@ if (NOT MSVC)
)
endif ()
-set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPERTIES GENERATED TRUE)
-set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.h PROPERTIES GENERATED TRUE)
+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(NOT MSVC)
add_library(Bindings ${SRCS} ${HDRS})
- target_link_libraries(Bindings lua sqlite tolualib polarssl)
+ target_link_libraries(Bindings lua sqlite tolualib mbedtls)
endif()
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 25c77a652..08c7e19d7 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -19,13 +19,13 @@ extern "C"
#include "../Entities/Entity.h"
#include "../BlockEntities/BlockEntity.h"
-// fwd: SQLite/lsqlite3.c
+// fwd: "SQLite/lsqlite3.c"
extern "C"
{
int luaopen_lsqlite3(lua_State * L);
}
-// fwd: LuaExpat/lxplib.c:
+// fwd: "LuaExpat/lxplib.c":
extern "C"
{
int luaopen_lxp(lua_State * L);
@@ -107,7 +107,7 @@ void cLuaState::Create(void)
void cLuaState::RegisterAPILibs(void)
{
tolua_AllToLua_open(m_LuaState);
- ManualBindings::Bind(m_LuaState);
+ cManualBindings::Bind(m_LuaState);
DeprecatedBindings::Bind(m_LuaState);
luaopen_lsqlite3(m_LuaState);
luaopen_lxp(m_LuaState);
@@ -530,42 +530,6 @@ void cLuaState::Push(bool a_Value)
-void cLuaState::Push(cBlockEntity * a_BlockEntity)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_BlockEntity, (a_BlockEntity == nullptr) ? "cBlockEntity" : a_BlockEntity->GetClass());
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cChunkDesc * a_ChunkDesc)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_ChunkDesc, "cChunkDesc");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cClientHandle * a_Client)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Client, "cClientHandle");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
void cLuaState::Push(cEntity * a_Entity)
{
ASSERT(IsValid());
@@ -632,42 +596,6 @@ void cLuaState::Push(cEntity * a_Entity)
-void cLuaState::Push(cHopperEntity * a_Hopper)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Hopper, "cHopperEntity");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cItem * a_Item)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Item, "cItem");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cItems * a_Items)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Items, "cItems");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
void cLuaState::Push(cLuaServerHandle * a_ServerHandle)
{
ASSERT(IsValid());
@@ -704,114 +632,6 @@ void cLuaState::Push(cLuaUDPEndpoint * a_UDPEndpoint)
-void cLuaState::Push(cMonster * a_Monster)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Monster, "cMonster");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cPickup * a_Pickup)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Pickup, "cPickup");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cPlayer * a_Player)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cPluginLua * a_Plugin)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Plugin, "cPluginLua");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cProjectileEntity * a_ProjectileEntity)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_ProjectileEntity, "cProjectileEntity");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cTNTEntity * a_TNTEntity)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_TNTEntity, "cTNTEntity");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cWebAdmin * a_WebAdmin)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_WebAdmin, "cWebAdmin");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cWindow * a_Window)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Window, "cWindow");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
-void cLuaState::Push(cWorld * a_World)
-{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- m_NumCurrentFunctionArgs += 1;
-}
-
-
-
-
-
void cLuaState::Push(double a_Value)
{
ASSERT(IsValid());
@@ -836,11 +656,18 @@ void cLuaState::Push(int a_Value)
-void cLuaState::Push(TakeDamageInfo * a_TDI)
+void cLuaState::Push(void * a_Ptr)
{
+ UNUSED(a_Ptr);
ASSERT(IsValid());
- tolua_pushusertype(m_LuaState, a_TDI, "TakeDamageInfo");
+ // Investigate the cause of this - what is the callstack?
+ // One code path leading here is the OnHookExploding / OnHookExploded with exotic parameters. Need to decide what to do with them
+ LOGWARNING("Lua engine: attempting to push a plain pointer, pushing nil instead.");
+ LOGWARNING("This indicates an unimplemented part of MCS bindings");
+ LogStackTrace();
+
+ lua_pushnil(m_LuaState);
m_NumCurrentFunctionArgs += 1;
}
@@ -848,11 +675,11 @@ void cLuaState::Push(TakeDamageInfo * a_TDI)
-void cLuaState::Push(Vector3d * a_Vector)
+void cLuaState::Push(std::chrono::milliseconds a_Value)
{
ASSERT(IsValid());
- tolua_pushusertype(m_LuaState, a_Vector, "Vector3<double>");
+ tolua_pushnumber(m_LuaState, static_cast<lua_Number>(a_Value.count()));
m_NumCurrentFunctionArgs += 1;
}
@@ -860,51 +687,40 @@ void cLuaState::Push(Vector3d * a_Vector)
-void cLuaState::Push(Vector3i * a_Vector)
+/*
+void cLuaState::PushUserType(void * a_Object, const char * a_Type)
{
ASSERT(IsValid());
- tolua_pushusertype(m_LuaState, a_Vector, "Vector3<int>");
+ tolua_pushusertype(m_LuaState, a_Object, a_Type);
m_NumCurrentFunctionArgs += 1;
}
+*/
-void cLuaState::Push(void * a_Ptr)
-{
- UNUSED(a_Ptr);
- ASSERT(IsValid());
-
- // Investigate the cause of this - what is the callstack?
- // One code path leading here is the OnHookExploding / OnHookExploded with exotic parameters. Need to decide what to do with them
- LOGWARNING("Lua engine: attempting to push a plain pointer, pushing nil instead.");
- LOGWARNING("This indicates an unimplemented part of MCS bindings");
- LogStackTrace();
-
- lua_pushnil(m_LuaState);
- m_NumCurrentFunctionArgs += 1;
-}
-
-void cLuaState::Push(std::chrono::milliseconds a_Value)
+void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
{
- ASSERT(IsValid());
-
- tolua_pushnumber(m_LuaState, static_cast<lua_Number>(a_Value.count()));
- m_NumCurrentFunctionArgs += 1;
+ size_t len = 0;
+ const char * data = lua_tolstring(m_LuaState, a_StackPos, &len);
+ if (data != nullptr)
+ {
+ a_Value.assign(data, len);
+ }
}
-void cLuaState::PushUserType(void * a_Object, const char * a_Type)
+void cLuaState::GetStackValue(int a_StackPos, BLOCKTYPE & a_ReturnedVal)
{
- ASSERT(IsValid());
-
- tolua_pushusertype(m_LuaState, a_Object, a_Type);
- m_NumCurrentFunctionArgs += 1;
+ if (lua_isnumber(m_LuaState, a_StackPos))
+ {
+ a_ReturnedVal = static_cast<BLOCKTYPE>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
+ }
}
@@ -920,13 +736,11 @@ void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
-void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
+void cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result)
{
- size_t len = 0;
- const char * data = lua_tolstring(m_LuaState, a_StackPos, &len);
- if (data != nullptr)
+ if (lua_isnumber(m_LuaState, a_StackPos))
{
- a_Value.assign(data, len);
+ a_Result = static_cast<cPluginManager::CommandResult>(static_cast<int>((tolua_tonumber(m_LuaState, a_StackPos, a_Result))));
}
}
@@ -934,12 +748,9 @@ void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
-void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
{
- if (lua_isnumber(m_LuaState, a_StackPos))
- {
- a_ReturnedVal = (int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal);
- }
+ a_Ref.RefStack(*this, a_StackPos);
}
@@ -958,11 +769,11 @@ void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
-void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
- a_ReturnedVal = (eWeather)Clamp((int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal), (int)wSunny, (int)wThunderstorm);
+ a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
}
}
@@ -970,35 +781,27 @@ void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
-void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
{
- if (lua_isnil(m_LuaState, a_StackPos))
+ if (!lua_isnumber(m_LuaState, a_StackPos))
{
- a_ReturnedVal = nullptr;
return;
}
- tolua_Error err;
- if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &err))
- {
- a_ReturnedVal = *((cBoundingBox **)lua_touserdata(m_LuaState, a_StackPos));
- }
+ 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))
+ );
}
-void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
{
- if (lua_isnil(m_LuaState, a_StackPos))
- {
- a_ReturnedVal = nullptr;
- return;
- }
- tolua_Error err;
- if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err))
+ if (lua_isnumber(m_LuaState, a_StackPos))
{
- a_ReturnedVal = *((cWorld **)lua_touserdata(m_LuaState, a_StackPos));
+ a_ReturnedVal = static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
}
}
@@ -1006,15 +809,6 @@ void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
-void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
-{
- a_Ref.RefStack(*this, a_StackPos);
-}
-
-
-
-
-
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@@ -1133,6 +927,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
@@ -1280,7 +1077,7 @@ bool cLuaState::CheckParamFunctionOrNil(int a_StartParam, int a_EndParam)
bool cLuaState::CheckParamEnd(int a_Param)
{
tolua_Error tolua_err;
- if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err))
+ if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err) == 1)
{
return true;
}
@@ -1297,6 +1094,30 @@ bool cLuaState::CheckParamEnd(int a_Param)
+bool cLuaState::IsParamUserType(int a_Param, AString a_UserType)
+{
+ ASSERT(IsValid());
+
+ tolua_Error tolua_err;
+ return (tolua_isusertype(m_LuaState, a_Param, a_UserType.c_str(), 0, &tolua_err) == 1);
+}
+
+
+
+
+
+bool cLuaState::IsParamNumber(int a_Param)
+{
+ ASSERT(IsValid());
+
+ tolua_Error tolua_err;
+ return (tolua_isnumber(m_LuaState, a_Param, 0, &tolua_err) == 1);
+}
+
+
+
+
+
bool cLuaState::ReportErrors(int a_Status)
{
return ReportErrors(m_LuaState, a_Status);
@@ -1376,7 +1197,7 @@ int cLuaState::CallFunctionWithForeignParams(
if (!PushFunction(a_FunctionName.c_str()))
{
LOGWARNING("Function '%s' not found", a_FunctionName.c_str());
- lua_pop(m_LuaState, 2);
+ lua_settop(m_LuaState, OldTop);
return -1;
}
@@ -1384,7 +1205,7 @@ int cLuaState::CallFunctionWithForeignParams(
if (CopyStackFrom(a_SrcLuaState, a_SrcParamStart, a_SrcParamEnd) < 0)
{
// Something went wrong, fix the stack and exit
- lua_pop(m_LuaState, 2);
+ lua_settop(m_LuaState, OldTop);
m_NumCurrentFunctionArgs = -1;
m_CurrentFunctionName.clear();
return -1;
@@ -1395,13 +1216,8 @@ int cLuaState::CallFunctionWithForeignParams(
if (ReportErrors(s))
{
LOGWARN("Error while calling function '%s' in '%s'", a_FunctionName.c_str(), m_SubsystemName.c_str());
- // Fix the stack.
- // We don't know how many values have been pushed, so just get rid of any that weren't there initially
- int CurTop = lua_gettop(m_LuaState);
- if (CurTop > OldTop)
- {
- lua_pop(m_LuaState, CurTop - OldTop);
- }
+ // Reset the stack:
+ lua_settop(m_LuaState, OldTop);
// Reset the internal checking mechanisms:
m_NumCurrentFunctionArgs = -1;
@@ -1553,6 +1369,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
}
@@ -1560,6 +1377,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 159483634..5b4ec3ae4 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -32,40 +32,14 @@ extern "C"
#include "../Vector3.h"
#include "../Defines.h"
+#include "PluginManager.h"
+#include "LuaState_Typedefs.inc"
-
-
-
-
-class cWorld;
-class cPlayer;
-class cEntity;
-class cProjectileEntity;
-class cMonster;
-class cItem;
-class cItems;
-class cClientHandle;
-class cPickup;
-class cChunkDesc;
-class cCraftingGrid;
-class cCraftingRecipe;
-struct TakeDamageInfo;
-class cWindow;
-class cPluginLua;
-struct HTTPRequest;
-class cWebAdmin;
-struct HTTPTemplateRequest;
-class cTNTEntity;
-class cHopperEntity;
-class cBlockEntity;
-class cBoundingBox;
-class cLuaTCPLink;
+// fwd:
class cLuaServerHandle;
+class cLuaTCPLink;
class cLuaUDPEndpoint;
-typedef cBoundingBox * pBoundingBox;
-typedef cWorld * pWorld;
-
@@ -202,59 +176,30 @@ public:
void Push(const Vector3i & a_Vector);
void Push(const Vector3i * a_Vector);
- // Push a value onto the stack (keep alpha-sorted):
+ // Push a simple value onto the stack (keep alpha-sorted):
void Push(bool a_Value);
- void Push(cBlockEntity * a_BlockEntity);
- void Push(cChunkDesc * a_ChunkDesc);
- void Push(cClientHandle * a_ClientHandle);
- void Push(cEntity * a_Entity);
- void Push(cHopperEntity * a_Hopper);
- void Push(cItem * a_Item);
- void Push(cItems * a_Items);
- void Push(cLuaServerHandle * a_ServerHandle);
- void Push(cLuaTCPLink * a_TCPLink);
- void Push(cLuaUDPEndpoint * a_UDPEndpoint);
- void Push(cMonster * a_Monster);
- void Push(cPickup * a_Pickup);
- void Push(cPlayer * a_Player);
- void Push(cPluginLua * a_Plugin);
- void Push(cProjectileEntity * a_ProjectileEntity);
- void Push(cTNTEntity * a_TNTEntity);
- void Push(cWebAdmin * a_WebAdmin);
- void Push(cWindow * a_Window);
- void Push(cWorld * a_World);
void Push(double a_Value);
void Push(int a_Value);
- void Push(TakeDamageInfo * a_TDI);
- void Push(Vector3d * a_Vector);
- void Push(Vector3i * a_Vector);
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);
- /** Retrieve value at a_StackPos, if it is a valid bool. If not, a_Value is unchanged */
- void GetStackValue(int a_StackPos, bool & a_Value);
-
- /** Retrieve value at a_StackPos, if it is a valid string. If not, a_Value is unchanged */
+ // 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);
-
- /** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
- void GetStackValue(int a_StackPos, int & a_Value);
-
- /** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
+ 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);
-
- /** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather.
- If not, a_Value is unchanged. */
void GetStackValue(int a_StackPos, eWeather & a_Value);
+ void GetStackValue(int a_StackPos, float & a_ReturnedVal);
+ void GetStackValue(int a_StackPos, int & a_Value);
- /** Retrieve value at a_StackPos, if it is a valid cBoundingBox class. If not, a_Value is unchanged */
- void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
-
- /** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */
- void GetStackValue(int a_StackPos, pWorld & a_Value);
-
- /** Store the value at a_StackPos as a reference. */
- void GetStackValue(int a_StackPos, cRef & a_Ref);
+ // Include the auto-generated Push and GetStackValue() functions:
+ #include "LuaState_Declaration.inc"
/** Call the specified Lua function.
Returns true if call succeeded, false if there was an error.
@@ -303,6 +248,10 @@ public:
/** Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters) */
bool CheckParamEnd(int a_Param);
+ bool IsParamUserType(int a_Param, AString a_UserType);
+
+ bool IsParamNumber(int a_Param);
+
/** If the status is nonzero, prints the text on the top of Lua stack and returns true */
bool ReportErrors(int status);
@@ -429,7 +378,7 @@ protected:
bool PushFunction(const cTableRef & a_TableRef);
/** Pushes a usertype of the specified class type onto the stack */
- void PushUserType(void * a_Object, const char * a_Type);
+ // void PushUserType(void * a_Object, const char * a_Type);
/**
Calls the function that has been pushed onto the stack by PushFunction(),
@@ -440,6 +389,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/LuaWindow.cpp b/src/Bindings/LuaWindow.cpp
index d4014059b..5f7832ef5 100644
--- a/src/Bindings/LuaWindow.cpp
+++ b/src/Bindings/LuaWindow.cpp
@@ -159,7 +159,7 @@ void cLuaWindow::Destroy(void)
m_Plugin->Unreference(m_LuaRef);
}
- // Lua will take care of this object, it will garbage-collect it, so we *must not* delete it!
+ // Lua will take care of this object, it will garbage-collect it, so we must not delete it!
m_IsDestroyed = false;
}
@@ -167,10 +167,10 @@ void cLuaWindow::Destroy(void)
-void cLuaWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer& a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
+void cLuaWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas Areas;
- for (auto Area : m_SlotAreas)
+ for (auto && Area : m_SlotAreas)
{
if (Area != a_ClickedArea)
{
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 6e579b364..ff904d74a 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -5,6 +5,7 @@
#undef TOLUA_TEMPLATE_BIND
#include <sstream>
#include <iomanip>
+#include <array>
#include "tolua++/include/tolua++.h"
#include "polarssl/md5.h"
#include "polarssl/sha1.h"
@@ -32,13 +33,14 @@
#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
#include "../StringCompression.h"
+#include "../CommandOutput.h"
// Better error reporting for Lua
-static int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
+int cManualBindings::tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError)
{
// Retrieve current function name
lua_Debug entry;
@@ -58,7 +60,7 @@ static int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pTo
-static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
+int cManualBindings::lua_do_error(lua_State * L, const char * a_pFormat, ...)
{
// Retrieve current function name
lua_Debug entry;
@@ -67,7 +69,7 @@ static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
// Insert function name into error msg
AString msg(a_pFormat);
- ReplaceString(msg, "#funcname#", entry.name?entry.name:"?");
+ ReplaceString(msg, "#funcname#", (entry.name != nullptr) ? entry.name : "?");
// Copied from luaL_error and modified
va_list argp;
@@ -90,12 +92,12 @@ static int tolua_Clamp(lua_State * tolua_S)
int NumArgs = lua_gettop(LuaState);
if (NumArgs != 3)
{
- return lua_do_error(LuaState, "Error in function call '#funcname#': Requires 3 arguments, got %i", NumArgs);
+ 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 lua_do_error(LuaState, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #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);
@@ -253,12 +255,13 @@ static int tolua_InflateString(lua_State * tolua_S)
static int tolua_StringSplit(lua_State * tolua_S)
{
+ // Get the params:
cLuaState LuaState(tolua_S);
- std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0);
- std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
+ AString str, delim;
+ LuaState.GetStackValues(1, str, delim);
- AStringVector Split = StringSplit(str, delim);
- LuaState.Push(Split);
+ // Execute and push the result:
+ LuaState.Push(StringSplit(str, delim));
return 1;
}
@@ -286,12 +289,20 @@ static int tolua_StringSplitWithQuotes(lua_State * tolua_S)
static int tolua_StringSplitAndTrim(lua_State * tolua_S)
{
- cLuaState LuaState(tolua_S);
- std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0);
- std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamString(1, 2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
- AStringVector Split = StringSplitAndTrim(str, delim);
- LuaState.Push(Split);
+ // Process:
+ AString str, delim;
+ L.GetStackValues(1, str, delim);
+ L.Push(StringSplitAndTrim(str, delim));
return 1;
}
@@ -450,7 +461,7 @@ static int tolua_Base64Decode(lua_State * tolua_S)
-cPluginLua * GetLuaPlugin(lua_State * L)
+cPluginLua * cManualBindings::GetLuaPlugin(lua_State * L)
{
// Get the plugin identification out of LuaState:
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
@@ -472,6 +483,7 @@ cPluginLua * GetLuaPlugin(lua_State * L)
static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
{
+ // Check params:
cLuaState LuaState(tolua_S);
if (
!LuaState.CheckParamUserTable(1, "cFile") ||
@@ -482,10 +494,12 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
return 0;
}
- AString Folder = (AString)tolua_tocppstring(LuaState, 2, 0);
+ // Get params:
+ AString Folder;
+ LuaState.GetStackValues(2, Folder);
- AStringVector Contents = cFile::GetFolderContents(Folder);
- LuaState.Push(Contents);
+ // Execute and push result:
+ LuaState.Push(cFile::GetFolderContents(Folder));
return 1;
}
@@ -493,447 +507,25 @@ static int tolua_cFile_GetFolderContents(lua_State * tolua_S)
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(const AString &, cItemCallback<Ty2> &)
->
-static int tolua_DoWith(lua_State* tolua_S)
-{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if ((NumArgs != 2) && (NumArgs != 3))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
- }
-
- Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, nullptr);
-
- const char * ItemName = tolua_tocppstring(tolua_S, 2, "");
- if ((ItemName == nullptr) || (ItemName[0] == 0))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
- }
- if (!lua_isfunction( tolua_S, 3))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
- }
-
- /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
- int TableRef = LUA_REFNIL;
- if (NumArgs == 3)
- {
- TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (TableRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
- }
- }
-
- /* table value is popped, and now function is on top of the stack */
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
- }
-
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- , TableRef( a_TableRef)
- {}
-
- private:
- virtual bool Item(Ty2 * a_Item) override
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
- if (TableRef != LUA_REFNIL)
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
- }
-
- int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; // Abort enumeration
- }
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean(LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
- }
- lua_State * LuaState;
- int FuncRef;
- int TableRef;
- } Callback(tolua_S, FuncRef, TableRef);
-
-
- bool bRetVal = (self->*Func1)(ItemName, Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
- return 1;
-}
-
-
-
-
-
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(UInt32, cItemCallback<Ty2> &)
->
-static int tolua_DoWithID(lua_State* tolua_S)
-{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if ((NumArgs != 2) && (NumArgs != 3))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
- }
-
- Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, nullptr);
-
- int ItemID = (int)tolua_tonumber(tolua_S, 2, 0);
- if (!lua_isfunction(tolua_S, 3))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
- }
-
- /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
- int TableRef = LUA_REFNIL;
- if (NumArgs == 3)
- {
- TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (TableRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
- }
- }
-
- /* table value is popped, and now function is on top of the stack */
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
- }
-
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(lua_State * a_LuaState, int a_FuncRef, int a_TableRef) :
- LuaState(a_LuaState),
- FuncRef(a_FuncRef),
- TableRef(a_TableRef)
- {}
-
- private:
- virtual bool Item(Ty2 * a_Item) override
- {
- lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); // Push function to call
- tolua_pushusertype(LuaState, a_Item, a_Item->GetClass()); // Push the item
- if (TableRef != LUA_REFNIL)
- {
- lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); // Push the optional callbackdata param
- }
-
- int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; // Abort enumeration
- }
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean(LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
- }
- lua_State * LuaState;
- int FuncRef;
- int TableRef;
- } Callback(tolua_S, FuncRef, TableRef);
-
-
- bool bRetVal = (self->*Func1)(ItemID, Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
- return 1;
-}
-
-
-
-
-
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &)
->
-static int tolua_DoWithXYZ(lua_State* tolua_S)
-{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if ((NumArgs != 4) && (NumArgs != 5))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 4 or 5 arguments, got %i", NumArgs);
- }
-
- Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, nullptr);
- if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3");
- }
-
- int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
- int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
- int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
- if (!lua_isfunction( tolua_S, 5))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
- }
-
- /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
- int TableRef = LUA_REFNIL;
- if (NumArgs == 5)
- {
- TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (TableRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #5");
- }
- }
-
- /* table value is popped, and now function is on top of the stack */
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #4");
- }
-
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- , TableRef( a_TableRef)
- {}
-
- private:
- virtual bool Item(Ty2 * a_Item) override
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
- if (TableRef != LUA_REFNIL)
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
- }
-
- int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; // Abort enumeration
- }
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean(LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
- }
- lua_State * LuaState;
- int FuncRef;
- int TableRef;
- } Callback(tolua_S, FuncRef, TableRef);
-
- bool bRetVal = (self->*Func1)(ItemX, ItemY, ItemZ, Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
- return 1;
-}
-
-
-
-
-
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &)
->
-static int tolua_ForEachInChunk(lua_State * tolua_S)
-{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if ((NumArgs != 3) && (NumArgs != 4))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 3 or 4 arguments, got %i", NumArgs);
- }
-
- Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, nullptr);
- if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1 and #2");
- }
-
- int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
- int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
-
- if (!lua_isfunction( tolua_S, 4))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #3");
- }
-
- /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
- int TableRef = LUA_REFNIL;
- if (NumArgs == 4)
- {
- TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (TableRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #4");
- }
- }
-
- /* table value is popped, and now function is on top of the stack */
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #3");
- }
-
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- , TableRef( a_TableRef)
- {}
-
- private:
- virtual bool Item(Ty2 * a_Item) override
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
- if (TableRef != LUA_REFNIL)
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
- }
-
- int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; /* Abort enumeration */
- }
-
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean(LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
- }
- lua_State * LuaState;
- int FuncRef;
- int TableRef;
- } Callback(tolua_S, FuncRef, TableRef);
-
- bool bRetVal = (self->*Func1)(ChunkX, ChunkZ, Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
- return 1;
-}
-
-
-
-
-
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(const cBoundingBox &, cItemCallback<Ty2> &)
->
-static int tolua_ForEachInBox(lua_State * tolua_S)
+static int tolua_cFile_ReadWholeFile(lua_State * tolua_S)
{
// Check params:
- cLuaState L(tolua_S);
+ cLuaState LuaState(tolua_S);
if (
- !L.CheckParamUserType(1, "cWorld") ||
- !L.CheckParamUserType(2, "cBoundingBox") ||
- !L.CheckParamFunction(3) ||
- !L.CheckParamEnd(4)
+ !LuaState.CheckParamUserTable(1, "cFile") ||
+ !LuaState.CheckParamString (2) ||
+ !LuaState.CheckParamEnd (3)
)
{
return 0;
}
-
- // Get the params:
- Ty1 * Self = nullptr;
- cBoundingBox * Box = nullptr;
- L.GetStackValues(1, Self, Box);
- if ((Self == nullptr) || (Box == nullptr))
- {
- LOGWARNING("Invalid world (%p) or boundingbox (%p)", Self, Box);
- L.LogStackTrace();
- return 0;
- }
- // Create a reference for the function:
- cLuaState::cRef FnRef(L, 3);
+ // Get params:
+ AString FileName;
+ LuaState.GetStackValues(2, FileName);
- // Callback wrapper for the Lua function:
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
- m_LuaState(a_LuaState),
- m_FnRef(a_FuncRef)
- {}
-
- private:
- // cItemCallback<Ty2> overrides:
- virtual bool Item(Ty2 * a_Item) override
- {
- bool res = false;
- if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res))
- {
- LOGWARNING("Failed to call Lua callback");
- m_LuaState.LogStackTrace();
- return true; // Abort enumeration
- }
-
- return res;
- }
- cLuaState & m_LuaState;
- cLuaState::cRef & m_FnRef;
- } Callback(L, FnRef);
-
- bool bRetVal = (Self->*Func1)(*Box, Callback);
-
- FnRef.UnRef();
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
+ // Execute and push result:
+ LuaState.Push(cFile::ReadWholeFile(FileName));
return 1;
}
@@ -941,535 +533,30 @@ static int tolua_ForEachInBox(lua_State * tolua_S)
-template <
- class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(cItemCallback<Ty2> &)
->
-static int tolua_ForEach(lua_State * tolua_S)
-{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if ((NumArgs != 1) && (NumArgs != 2))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 1 or 2 arguments, got %i", NumArgs);
- }
-
- Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, nullptr);
- if (self == nullptr)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
- }
-
- if (!lua_isfunction( tolua_S, 2))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
- }
-
- /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
- int TableRef = LUA_REFNIL;
- if (NumArgs == 2)
- {
- TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (TableRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #2");
- }
- }
-
- /* table value is popped, and now function is on top of the stack */
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
- }
-
- class cLuaCallback : public cItemCallback<Ty2>
- {
- public:
- cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- , TableRef( a_TableRef)
- {}
-
- private:
- virtual bool Item(Ty2 * a_Item) override
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushusertype( LuaState, a_Item, Ty2::GetClassStatic());
- if (TableRef != LUA_REFNIL)
- {
- lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
- }
-
- int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; /* Abort enumeration */
- }
-
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean( LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
- }
- lua_State * LuaState;
- int FuncRef;
- int TableRef;
- } Callback(tolua_S, FuncRef, TableRef);
-
- bool bRetVal = (self->*Func1)(Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
-
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
- return 1;
-}
-
-
-
-
-
-static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
-{
- // Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight)
- // Function signature: GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight]
- #ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 4, 0, &tolua_err) ||
- !tolua_isnoobj (tolua_S, 5, &tolua_err)
- )
- goto tolua_lerror;
- else
- #endif
- {
- cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, nullptr);
- int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
- int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
- int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
- #ifndef TOLUA_RELEASE
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'GetBlockInfo'", nullptr);
- }
- #endif
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight;
- bool res = self->GetBlockInfo(BlockX, BlockY, BlockZ, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight);
- tolua_pushboolean(tolua_S, res ? 1 : 0);
- if (res)
- {
- tolua_pushnumber(tolua_S, BlockType);
- tolua_pushnumber(tolua_S, BlockMeta);
- tolua_pushnumber(tolua_S, BlockSkyLight);
- tolua_pushnumber(tolua_S, BlockBlockLight);
- return 5;
- }
- }
- }
- return 1;
-
- #ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S, "#ferror in function 'GetBlockInfo'.", &tolua_err);
- return 0;
- #endif
-}
-
-
-
-
-
-static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S)
-{
- // Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta)
- // Function signature: GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta]
- #ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 4, 0, &tolua_err) ||
- !tolua_isnoobj (tolua_S, 5, &tolua_err)
- )
- goto tolua_lerror;
- else
- #endif
- {
- cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, nullptr);
- int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
- int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
- int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
- #ifndef TOLUA_RELEASE
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'GetBlockTypeMeta'", nullptr);
- }
- #endif
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- bool res = self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta);
- tolua_pushboolean(tolua_S, res ? 1 : 0);
- if (res)
- {
- tolua_pushnumber(tolua_S, BlockType);
- tolua_pushnumber(tolua_S, BlockMeta);
- return 3;
- }
- }
- }
- return 1;
-
- #ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S, "#ferror in function 'GetBlockTypeMeta'.", &tolua_err);
- return 0;
- #endif
-}
-
-
-
-
-
-static int tolua_cWorld_GetSignLines(lua_State * tolua_S)
-{
- // Exported manually, because tolua would generate useless additional parameters (a_Line1 .. a_Line4)
- #ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 4, 0, &tolua_err) ||
- !tolua_isnoobj (tolua_S, 10, &tolua_err)
- )
- goto tolua_lerror;
- else
- #endif
- {
- cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, nullptr);
- int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
- int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
- int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
- #ifndef TOLUA_RELEASE
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'GetSignLines'", nullptr);
- }
- #endif
- {
- AString Line1, Line2, Line3, Line4;
- bool res = self->GetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
- tolua_pushboolean(tolua_S, res ? 1 : 0);
- if (res)
- {
- tolua_pushstring(tolua_S, Line1.c_str());
- tolua_pushstring(tolua_S, Line2.c_str());
- tolua_pushstring(tolua_S, Line3.c_str());
- tolua_pushstring(tolua_S, Line4.c_str());
- return 5;
- }
- }
- }
- return 1;
-
- #ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S, "#ferror in function 'GetSignLines'.", &tolua_err);
- return 0;
- #endif
-}
-
-
-
-
-
-static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
+static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
{
- // Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4)
- #ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 4, 0, &tolua_err) ||
- !tolua_iscppstring(tolua_S, 5, 0, &tolua_err) ||
- !tolua_iscppstring(tolua_S, 6, 0, &tolua_err) ||
- !tolua_iscppstring(tolua_S, 7, 0, &tolua_err) ||
- !tolua_iscppstring(tolua_S, 8, 0, &tolua_err) ||
- !tolua_isusertype (tolua_S, 9, "cPlayer", 1, &tolua_err) ||
- !tolua_isnoobj (tolua_S, 10, &tolua_err)
- )
- goto tolua_lerror;
- else
- #endif
- {
- cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, nullptr);
- int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
- int BlockY = (int) tolua_tonumber (tolua_S, 3, 0);
- int BlockZ = (int) tolua_tonumber (tolua_S, 4, 0);
- const AString Line1 = tolua_tocppstring(tolua_S, 5, 0);
- const AString Line2 = tolua_tocppstring(tolua_S, 6, 0);
- const AString Line3 = tolua_tocppstring(tolua_S, 7, 0);
- const AString Line4 = tolua_tocppstring(tolua_S, 8, 0);
- cPlayer * Player = (cPlayer *)tolua_tousertype (tolua_S, 9, nullptr);
- #ifndef TOLUA_RELEASE
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'SetSignLines'", nullptr);
- }
- #endif
- {
- bool res = self->SetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4, Player);
- tolua_pushboolean(tolua_S, res ? 1 : 0);
- }
- }
- return 1;
-
- #ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S, "#ferror in function 'SetSignLines'.", &tolua_err);
- return 0;
- #endif
-}
-
-
-
+ // API function no longer available:
+ LOGWARNING("cPluginManager:GetAllPlugins() is no longer available, use cPluginManager:ForEachPlugin() instead");
+ cLuaState::LogStackTrace(tolua_S);
-static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
-{
- // Exported manually, because tolua would require the out-only param a_Height to be used when calling
- // Takes a_World, a_BlockX, a_BlockZ
- // Returns Height, IsValid
- #ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
- !tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
- !tolua_isnoobj (tolua_S, 4, &tolua_err)
- )
- goto tolua_lerror;
- else
- #endif
- {
- cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, nullptr);
- int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
- int BlockZ = (int) tolua_tonumber (tolua_S, 3, 0);
- #ifndef TOLUA_RELEASE
- if (self == nullptr)
- {
- tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", nullptr);
- }
- #endif
- {
- int Height = 0;
- bool res = self->TryGetHeight(BlockX, BlockZ, Height);
- tolua_pushboolean(tolua_S, res ? 1 : 0);
- if (res)
- {
- tolua_pushnumber(tolua_S, Height);
- return 2;
- }
- }
- }
+ // Return an empty table:
+ lua_newtable(tolua_S);
return 1;
-
- #ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S, "#ferror in function 'TryGetHeight'.", &tolua_err);
- return 0;
- #endif
}
-class cLuaWorldTask :
- public cWorld::cTask,
- public cPluginLua::cResettable
-{
-public:
- cLuaWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- cPluginLua::cResettable(a_Plugin),
- m_FnRef(a_FnRef)
- {
- }
-
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
- {
- cCSLock Lock(m_CSPlugin);
- if (m_Plugin != nullptr)
- {
- m_Plugin->Call(m_FnRef, &a_World);
- }
- }
-} ;
-
-
-
-
-
-static int tolua_cWorld_QueueTask(lua_State * tolua_S)
-{
- // Binding for cWorld::QueueTask
- // Params: function
-
- // Retrieve the cPlugin from the LuaState:
- cPluginLua * Plugin = GetLuaPlugin(tolua_S);
- if (Plugin == nullptr)
- {
- // An error message has been already printed in GetLuaPlugin()
- return 0;
- }
-
- // Retrieve the args:
- cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
- if (self == nullptr)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
- }
- if (!lua_isfunction(tolua_S, 2))
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
- }
-
- // Create a reference to the function:
- int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FnRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
- }
-
- auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- self->QueueTask(task);
- return 0;
-}
-
-
-
-
-
-class cLuaScheduledWorldTask :
- public cWorld::cTask,
- public cPluginLua::cResettable
-{
-public:
- cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- cPluginLua::cResettable(a_Plugin),
- m_FnRef(a_FnRef)
- {
- }
-
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
- {
- cCSLock Lock(m_CSPlugin);
- if (m_Plugin != nullptr)
- {
- m_Plugin->Call(m_FnRef, &a_World);
- }
- }
-};
-
-
-
-
-
-static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
+static int tolua_cPluginManager_GetCurrentPlugin(lua_State * S)
{
- // Binding for cWorld::ScheduleTask
- // Params: function, Ticks
-
- // Retrieve the cPlugin from the LuaState:
- cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S);
if (Plugin == nullptr)
{
- // An error message has been already printed in GetLuaPlugin()
- return 0;
- }
-
- // Retrieve the args:
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cWorld") ||
- !L.CheckParamNumber (2) ||
- !L.CheckParamFunction(3)
- )
- {
+ // An error message has already been printed in GetLuaPlugin()
return 0;
}
- cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
- if (World == nullptr)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
- }
-
- // Create a reference to the function:
- int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FnRef == LUA_REFNIL)
- {
- return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
- }
-
- int DelayTicks = (int)tolua_tonumber(tolua_S, 2, 0);
-
- auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- World->ScheduleTask(DelayTicks, task);
- return 0;
-}
-
-
-
-
-
-static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
-{
- cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, nullptr);
-
- const cPluginManager::PluginMap & AllPlugins = self->GetAllPlugins();
-
- lua_newtable(tolua_S);
- int index = 1;
- cPluginManager::PluginMap::const_iterator iter = AllPlugins.begin();
- while (iter != AllPlugins.end())
- {
- const cPlugin* Plugin = iter->second;
- tolua_pushstring(tolua_S, iter->first.c_str());
- if (Plugin != nullptr)
- {
- tolua_pushusertype(tolua_S, (void *)Plugin, "const cPlugin");
- }
- else
- {
- tolua_pushboolean(tolua_S, 0);
- }
- lua_rawset(tolua_S, -3);
- ++iter;
- ++index;
- }
+ tolua_pushusertype(S, Plugin, "cPluginLua");
return 1;
}
@@ -1477,16 +564,12 @@ static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
-static int tolua_cPluginManager_GetCurrentPlugin(lua_State * S)
+static int tolua_cPluginManager_GetPlugin(lua_State * tolua_S)
{
- cPluginLua * Plugin = GetLuaPlugin(S);
- if (Plugin == nullptr)
- {
- // An error message has already been printed in GetLuaPlugin()
- return 0;
- }
- tolua_pushusertype(S, Plugin, "cPluginLua");
- return 1;
+ // 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;
}
@@ -1510,7 +593,7 @@ static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager,
// The arg types have already been checked
// Retrieve the cPlugin from the LuaState:
- cPluginLua * Plugin = GetLuaPlugin(S);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -1557,7 +640,7 @@ static int tolua_cPluginManager_AddHook_DefFn(cPluginManager * a_PluginManager,
S.LogStackTrace();
return 0;
}
- if (Plugin != GetLuaPlugin(S))
+ 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.");
@@ -1664,74 +747,55 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if (NumArgs != 1)
- {
- LOGWARN("Error in function call 'ForEachCommand': Requires 1 argument, got %i", NumArgs);
- return 0;
- }
-
- cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, nullptr);
- if (self == nullptr)
- {
- LOGWARN("Error in function call 'ForEachCommand': Not called on an object instance");
- return 0;
- }
+ /*
+ Function signature:
+ cPluginManager:Get():ForEachCommand(a_CallbackFn) -> bool
+ */
- if (!lua_isfunction(tolua_S, 2))
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cPluginManager") ||
+ !L.CheckParamFunction(2) ||
+ !L.CheckParamEnd(3)
+ )
{
- LOGWARN("Error in function call 'ForEachCommand': Expected a function for parameter #1");
return 0;
}
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
+ // 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(lua_State * a_LuaState, int a_FuncRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- {}
+ 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);
-
- lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushcppstring(LuaState, a_Command);
- tolua_pushcppstring(LuaState, a_Permission);
- tolua_pushcppstring(LuaState, a_HelpString);
-
- int s = lua_pcall(LuaState, 3, 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; /* Abort enumeration */
- }
-
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean( LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Command, a_Permission, a_HelpString, cLuaState::Return, ret);
+ return ret;
}
- lua_State * LuaState;
- int FuncRef;
- } Callback(tolua_S, FuncRef);
-
- bool bRetVal = self->ForEachCommand(Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
+ // Execute and push the returned value:
+ L.Push(cPluginManager::Get()->ForEachCommand(Callback));
return 1;
}
@@ -1741,74 +805,56 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
{
- int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if (NumArgs != 1)
- {
- LOGWARN("Error in function call 'ForEachConsoleCommand': Requires 1 argument, got %i", NumArgs);
- return 0;
- }
-
- cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, nullptr);
- if (self == nullptr)
- {
- LOGWARN("Error in function call 'ForEachConsoleCommand': Not called on an object instance");
- return 0;
- }
+ /*
+ Function signature:
+ cPluginManager:Get():ForEachConsoleCommand(a_CallbackFn) -> bool
+ */
- if (!lua_isfunction(tolua_S, 2))
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cPluginManager") ||
+ !L.CheckParamFunction(2) ||
+ !L.CheckParamEnd(3)
+ )
{
- LOGWARN("Error in function call 'ForEachConsoleCommand': Expected a function for parameter #1");
return 0;
}
- int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- if (FuncRef == LUA_REFNIL)
+ // 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(lua_State * a_LuaState, int a_FuncRef)
- : LuaState( a_LuaState)
- , FuncRef( a_FuncRef)
- {}
+ 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);
-
- lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushcppstring(LuaState, a_Command);
- tolua_pushcppstring(LuaState, a_HelpString);
-
- int s = lua_pcall(LuaState, 2, 1, 0);
- if (cLuaState::ReportErrors(LuaState, s))
- {
- return true; /* Abort enumeration */
- }
-
- if (lua_isboolean(LuaState, -1))
- {
- return (tolua_toboolean( LuaState, -1, 0) > 0);
- }
- return false; /* Continue enumeration */
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Command, a_HelpString, cLuaState::Return, ret);
+ return ret;
}
- lua_State * LuaState;
- int FuncRef;
- } Callback(tolua_S, FuncRef);
-
- bool bRetVal = self->ForEachConsoleCommand(Callback);
-
- /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
- luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
- /* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal);
+ // Execute and push the returned value:
+ L.Push(cPluginManager::Get()->ForEachConsoleCommand(Callback));
return 1;
}
@@ -1822,7 +868,7 @@ static int tolua_cPluginManager_BindCommand(lua_State * L)
cPluginManager:BindCommand(Command, Permission, Function, HelpString)
cPluginManager.BindCommand(Command, Permission, Function, HelpString) -- without the "self" param
*/
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
return 0;
@@ -1892,7 +938,7 @@ static int tolua_cPluginManager_BindConsoleCommand(lua_State * L)
*/
// Get the plugin identification out of LuaState:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
return 0;
@@ -1980,7 +1026,7 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
}
// If requesting calling the current plugin, refuse:
- cPluginLua * ThisPlugin = GetLuaPlugin(L);
+ cPluginLua * ThisPlugin = cManualBindings::GetLuaPlugin(L);
if (ThisPlugin == nullptr)
{
return 0;
@@ -2011,7 +1057,11 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
virtual bool Item(cPlugin * a_Plugin) override
{
- m_NumReturns = ((cPluginLua *)a_Plugin)->CallFunctionFromForeignState(
+ if (!a_Plugin->IsLoaded())
+ {
+ return false;
+ }
+ m_NumReturns = static_cast<cPluginLua *>(a_Plugin)->CallFunctionFromForeignState(
m_FunctionName, m_SrcLuaState, 4, lua_gettop(m_SrcLuaState)
);
return true;
@@ -2019,9 +1069,11 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
} Callback(FunctionName, L);
if (!cPluginManager::Get()->DoWithPlugin(PluginName, Callback))
{
- // TODO 2014_01_20 _X: This might be too much logging, plugins cannot know if other plugins are loaded (async)
- LOGWARNING("cPluginManager::CallPlugin: No such plugin name (\"%s\")", PluginName.c_str());
- L.LogStackTrace();
+ return 0;
+ }
+ if (Callback.m_NumReturns < 0)
+ {
+ // The call has failed, there are zero return values. Do NOT return negative number (Lua considers that a "yield")
return 0;
}
return Callback.m_NumReturns;
@@ -2031,48 +1083,48 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S)
-static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
+static int tolua_cPluginManager_ExecuteConsoleCommand(lua_State * tolua_S)
{
- /* Function signature:
- World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable)
- ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... }
+ /*
+ Function signature:
+ cPluginManager:ExecuteConsoleCommand(EntireCommandStr) -> OutputString
*/
-
+
+ // Check params:
cLuaState L(tolua_S);
if (
- !L.CheckParamUserType (1, "cWorld") ||
- !L.CheckParamTable (2) ||
- !L.CheckParamFunctionOrNil(3, 4)
+ !L.CheckParamUserTable(1, "cPluginManager") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
)
{
return 0;
}
-
- cPluginLua * Plugin = GetLuaPlugin(tolua_S);
- if (Plugin == nullptr)
- {
- return 0;
- }
-
- // Read the params:
- cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
- if (World == nullptr)
- {
- LOGWARNING("World:ChunkStay(): invalid world parameter");
- L.LogStackTrace();
- return 0;
- }
- cLuaChunkStay * ChunkStay = new cLuaChunkStay(*Plugin);
+ // 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;
+}
- if (!ChunkStay->AddChunks(2))
- {
- delete ChunkStay;
- ChunkStay = nullptr;
- return 0;
- }
- ChunkStay->Enable(*World->GetChunkMap(), 3, 4);
+
+
+
+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;
}
@@ -2080,75 +1132,40 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
-static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
+static int tolua_cPlayer_GetPermissions(lua_State * tolua_S)
{
- /* Function signature:
- World:PrepareChunk(ChunkX, ChunkZ, Callback)
- */
-
- // Check the param types:
+ // Function signature: cPlayer:GetPermissions() -> {permissions-array}
+
+ // Check the params:
cLuaState L(tolua_S);
if (
- !L.CheckParamUserType (1, "cWorld") ||
- !L.CheckParamNumber (2, 3) ||
- !L.CheckParamFunctionOrNil(4)
+ !L.CheckParamUserType(1, "cPlayer") ||
+ !L.CheckParamEnd (2)
)
{
return 0;
}
-
- // Read the params:
- cWorld * world = nullptr;
- int chunkX = 0, chunkZ = 0;
- L.GetStackValues(1, world, chunkX, chunkZ);
- if (world == nullptr)
+
+ // Get the params:
+ cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, nullptr);
+ if (self == nullptr)
{
- LOGWARNING("World:PrepareChunk(): invalid world parameter");
- L.LogStackTrace();
+ LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
return 0;
}
-
- // Wrap the Lua callback inside a C++ callback class:
- class cCallback:
- public cChunkCoordCallback
- {
- public:
- cCallback(lua_State * a_LuaState):
- m_LuaState(a_LuaState),
- m_Callback(m_LuaState, 4)
- {
- }
-
- // cChunkCoordCallback override:
- virtual void Call(int a_CBChunkX, int a_CBChunkZ) override
- {
- if (m_Callback.IsValid())
- {
- m_LuaState.Call(m_Callback, a_CBChunkX, a_CBChunkZ);
- }
-
- // This is the last reference of this object, we must delete it so that it doesn't leak:
- delete this;
- }
-
- protected:
- cLuaState m_LuaState;
- cLuaState::cRef m_Callback;
- };
- cCallback * callback = new cCallback(tolua_S);
-
- // Call the chunk preparation:
- world->PrepareChunk(chunkX, chunkZ, callback);
- return 0;
+
+ // Push the permissions:
+ L.Push(self->GetPermissions());
+ return 1;
}
-static int tolua_cPlayer_GetPermissions(lua_State * tolua_S)
+static int tolua_cPlayer_GetRestrictions(lua_State * tolua_S)
{
- // Function signature: cPlayer:GetPermissions() -> {permissions-array}
+ // Function signature: cPlayer:GetRestrictions() -> {restrictions-array}
// Check the params:
cLuaState L(tolua_S);
@@ -2169,7 +1186,7 @@ static int tolua_cPlayer_GetPermissions(lua_State * tolua_S)
}
// Push the permissions:
- L.Push(self->GetPermissions());
+ L.Push(self->GetRestrictions());
return 1;
}
@@ -2182,7 +1199,7 @@ static int tolua_cPlayer_OpenWindow(lua_State * tolua_S)
// Function signature: cPlayer:OpenWindow(Window)
// Retrieve the plugin instance from the Lua state
- cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
if (Plugin == nullptr)
{
return 0;
@@ -2263,7 +1280,7 @@ static int tolua_SetObjectCallback(lua_State * tolua_S)
// Function signature: OBJTYPE:SetWhateverCallback(CallbackFunction)
// Retrieve the plugin instance from the Lua state
- cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
if (Plugin == nullptr)
{
// Warning message has already been printed by GetLuaPlugin(), bail out silently
@@ -2315,7 +1332,7 @@ static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S)
}
else
{
- return tolua_do_error(tolua_S, "#ferror calling function '#funcname#'", &tolua_err);
+ return cManualBindings::tolua_do_error(tolua_S, "#ferror calling function '#funcname#'", &tolua_err);
}
if (Reference != LUA_REFNIL)
@@ -2337,40 +1354,40 @@ static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S)
-static int tolua_cPluginLua_AddTab(lua_State* tolua_S)
+static int tolua_cPlugin_GetDirectory(lua_State * tolua_S)
{
- cPluginLua * self = (cPluginLua *) tolua_tousertype(tolua_S, 1, nullptr);
- LOGWARN("WARNING: Using deprecated function AddTab()! Use AddWebTab() instead. (plugin \"%s\" in folder \"%s\")",
- self->GetName().c_str(), self->GetDirectory().c_str()
- );
- return tolua_cPluginLua_AddWebTab( 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<cPluginLua *>(tolua_tousertype(tolua_S, 1, nullptr));
+
+ // Get the folder name:
+ L.Push(Plugin->GetFolderName());
+ return 1;
}
-static int tolua_cPlugin_Call(lua_State * tolua_S)
+static int tolua_cPlugin_GetLocalDirectory(lua_State * tolua_S)
{
cLuaState L(tolua_S);
// Log the obsoletion warning:
- LOGWARNING("cPlugin:Call() is obsolete and unsafe, use cPluginManager:CallPlugin() instead.");
+ LOGWARNING("cPlugin:GetLocalDirectory() is obsolete, use cPlugin:GetLocalFolder() instead.");
L.LogStackTrace();
- // Retrieve the params: plugin and the function name to call
- cPluginLua * TargetPlugin = (cPluginLua *) tolua_tousertype(tolua_S, 1, nullptr);
- AString FunctionName = tolua_tostring(tolua_S, 2, "");
+ // Retrieve the params:
+ cPlugin * Plugin = static_cast<cPluginLua *>(tolua_tousertype(tolua_S, 1, nullptr));
- // Call the function:
- int NumReturns = TargetPlugin->CallFunctionFromForeignState(FunctionName, L, 3, lua_gettop(L));
- if (NumReturns < 0)
- {
- LOGWARNING("cPlugin::Call() failed to call destination function");
- L.LogStackTrace();
- return 0;
- }
- return NumReturns;
+ // Get the folder:
+ L.Push(Plugin->GetLocalFolder());
+ return 1;
}
@@ -2488,8 +1505,8 @@ static int tolua_push_StringStringMap(lua_State* tolua_S, std::map< std::string,
for (std::map<std::string, std::string>::iterator it = a_StringStringMap.begin(); it != a_StringStringMap.end(); ++it)
{
- const char* key = it->first.c_str();
- const char* value = it->second.c_str();
+ const char * key = it->first.c_str();
+ const char * value = it->second.c_str();
lua_pushstring(tolua_S, key);
lua_pushstring(tolua_S, value);
lua_settable(tolua_S, top);
@@ -2504,7 +1521,7 @@ static int tolua_push_StringStringMap(lua_State* tolua_S, std::map< std::string,
static int tolua_get_HTTPRequest_Params(lua_State* tolua_S)
{
- HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, nullptr);
+ HTTPRequest * self = reinterpret_cast<HTTPRequest *>(tolua_tousertype(tolua_S, 1, nullptr));
return tolua_push_StringStringMap(tolua_S, self->Params);
}
@@ -2514,7 +1531,7 @@ static int tolua_get_HTTPRequest_Params(lua_State* tolua_S)
static int tolua_get_HTTPRequest_PostParams(lua_State* tolua_S)
{
- HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, nullptr);
+ HTTPRequest * self = reinterpret_cast<HTTPRequest *>(tolua_tousertype(tolua_S, 1, nullptr));
return tolua_push_StringStringMap(tolua_S, self->PostParams);
}
@@ -2524,8 +1541,8 @@ static int tolua_get_HTTPRequest_PostParams(lua_State* tolua_S)
static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S)
{
- HTTPRequest* self = (HTTPRequest*) tolua_tousertype(tolua_S, 1, nullptr);
- std::map< std::string, HTTPFormData >& FormData = self->FormData;
+ HTTPRequest * self = reinterpret_cast<HTTPRequest *>(tolua_tousertype(tolua_S, 1, nullptr));
+ std::map<std::string, HTTPFormData> & FormData = self->FormData;
lua_newtable(tolua_S);
int top = lua_gettop(tolua_S);
@@ -2628,22 +1645,16 @@ static int tolua_AllToLua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S)
static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
{
- cWebPlugin* self = (cWebPlugin*) tolua_tousertype(tolua_S, 1, nullptr);
-
- const cWebPlugin::TabNameList & TabNames = self->GetTabNames();
-
+ // Returns a map of (SafeTitle -> Title) for the plugin's web tabs.
+ auto self = reinterpret_cast<cWebPlugin *>(tolua_tousertype(tolua_S, 1, nullptr));
+ auto TabNames = self->GetTabNames();
lua_newtable(tolua_S);
int index = 1;
- cWebPlugin::TabNameList::const_iterator iter = TabNames.begin();
- while (iter != TabNames.end())
- {
- const AString & FancyName = iter->first;
- const AString & WebName = iter->second;
- tolua_pushstring( tolua_S, WebName.c_str()); // Because the WebName is supposed to be unique, use it as key
- tolua_pushstring( tolua_S, FancyName.c_str());
- //
+ for (auto itr = TabNames.cbegin(), end = TabNames.cend(); itr != end; ++itr)
+ {
+ tolua_pushstring(tolua_S, itr->second.c_str()); // Because the SafeTitle is supposed to be unique, use it as key
+ tolua_pushstring(tolua_S, itr->first.c_str());
lua_rawset(tolua_S, -3);
- ++iter;
++index;
}
return 1;
@@ -3214,6 +2225,44 @@ static int tolua_cBlockArea_GetOrigin(lua_State * tolua_S)
+static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * tolua_S)
+{
+ // function cBlockArea::GetNonAirCropRelCoords()
+ // Exported manually because tolua would generate extra input params for the outputs
+
+ cLuaState L(tolua_S);
+ if (!L.CheckParamUserType(1, "cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self = nullptr;
+ BLOCKTYPE IgnoreBlockType = E_BLOCK_AIR;
+ L.GetStackValues(1, self, IgnoreBlockType);
+ if (self == nullptr)
+ {
+ tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetNonAirCropRelCoords'", nullptr);
+ return 0;
+ }
+
+ // Calculate the crop coords:
+ int MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ;
+ self->GetNonAirCropRelCoords(MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ, IgnoreBlockType);
+
+ // Push the six crop coords:
+ L.Push(MinRelX);
+ L.Push(MinRelY);
+ L.Push(MinRelZ);
+ L.Push(MaxRelX);
+ L.Push(MaxRelY);
+ L.Push(MaxRelZ);
+ return 6;
+}
+
+
+
+
+
static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * tolua_S)
{
// function cBlockArea::GetRelBlockTypeMeta()
@@ -3680,17 +2729,17 @@ static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S)
-void ManualBindings::Bind(lua_State * tolua_S)
+void cManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, nullptr);
// Create the new classes:
tolua_usertype(tolua_S, "cCryptoHash");
- tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr);
+ tolua_usertype(tolua_S, "cLineBlockTracer");
tolua_usertype(tolua_S, "cStringCompression");
+ tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr);
+ tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr);
tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr);
- tolua_usertype(tolua_S, "cLineBlockTracer");
- tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr);
// Globals:
tolua_function(tolua_S, "Clamp", tolua_Clamp);
@@ -3705,15 +2754,12 @@ void ManualBindings::Bind(lua_State * tolua_S)
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, "cFile");
- tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents);
- tolua_endmodule(tolua_S);
-
+
tolua_beginmodule(tolua_S, "cBlockArea");
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
tolua_function(tolua_S, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin);
+ tolua_function(tolua_S, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords);
tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
@@ -3721,7 +2767,13 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
tolua_function(tolua_S, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
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, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cCompositeChat");
tolua_function(tolua_S, "AddRunCommandPart", tolua_cCompositeChat_AddRunCommandPart);
tolua_function(tolua_S, "AddSuggestCommandPart", tolua_cCompositeChat_AddSuggestCommandPart);
@@ -3731,105 +2783,105 @@ void ManualBindings::Bind(lua_State * tolua_S)
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, "cEntity");
+ tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID);
+ tolua_endmodule(tolua_S);
+
+ tolua_beginmodule(tolua_S, "cFile");
+ tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents);
+ tolua_function(tolua_S, "ReadWholeFile", tolua_cFile_ReadWholeFile);
+ 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, "cItemGrid");
+ tolua_function(tolua_S, "GetSlotCoords", Lua_ItemGrid_GetSlotCoords);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cLineBlockTracer");
tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace);
tolua_endmodule(tolua_S);
-
- tolua_beginmodule(tolua_S, "cRoot");
- tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
- tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_DoWith <cRoot, cPlayer, &cRoot::DoWithPlayerByUUID>);
- tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
- tolua_function(tolua_S, "ForEachWorld", tolua_ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
- tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe);
- tolua_endmodule(tolua_S);
-
- tolua_beginmodule(tolua_S, "cWorld");
- tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
- tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
- tolua_function(tolua_S, "DoWithBeaconAt", tolua_DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
- tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
- tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
- tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);
- tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>);
- tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>);
- tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>);
- tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);
- tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>);
- tolua_function(tolua_S, "DoWithMobHeadAt", tolua_DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>);
- tolua_function(tolua_S, "DoWithFlowerPotAt", tolua_DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
- tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
- tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
- tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayerByUUID>);
- tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
- tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
- tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);
- tolua_function(tolua_S, "ForEachEntityInBox", tolua_ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>);
- tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
- tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
- tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
- tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
- tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
- tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
- tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk);
- tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
- tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
- tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
- tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
+
+ tolua_beginmodule(tolua_S, "cLuaWindow");
+ tolua_function(tolua_S, "SetOnClosing", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnClosing>);
+ tolua_function(tolua_S, "SetOnSlotChanged", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnSlotChanged>);
tolua_endmodule(tolua_S);
-
+
tolua_beginmodule(tolua_S, "cMapManager");
- tolua_function(tolua_S, "DoWithMap", tolua_DoWithID<cMapManager, cMap, &cMapManager::DoWithMap>);
+ tolua_function(tolua_S, "DoWithMap", DoWithID<cMapManager, cMap, &cMapManager::DoWithMap>);
tolua_endmodule(tolua_S);
- tolua_beginmodule(tolua_S, "cScoreboard");
- tolua_function(tolua_S, "ForEachObjective", tolua_ForEach<cScoreboard, cObjective, &cScoreboard::ForEachObjective>);
- tolua_function(tolua_S, "ForEachTeam", tolua_ForEach<cScoreboard, cTeam, &cScoreboard::ForEachTeam>);
+ 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, "OpenWindow", tolua_cPlayer_OpenWindow);
+ tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cPlugin");
- tolua_function(tolua_S, "Call", tolua_cPlugin_Call);
+ 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<cPluginManager, cPlugin, &cPluginManager::DoWithPlugin>);
+ 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<cPluginManager, cPlugin, &cPluginManager::ForEachPlugin>);
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, "cPlayer");
- tolua_function(tolua_S, "GetPermissions", tolua_cPlayer_GetPermissions);
- tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
- tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches);
- tolua_endmodule(tolua_S);
-
- tolua_beginmodule(tolua_S, "cLuaWindow");
- tolua_function(tolua_S, "SetOnClosing", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnClosing>);
- tolua_function(tolua_S, "SetOnSlotChanged", tolua_SetObjectCallback<cLuaWindow, &cLuaWindow::SetOnSlotChanged>);
+
+ tolua_beginmodule(tolua_S, "cRoot");
+ tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
+ 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, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe);
tolua_endmodule(tolua_S);
- tolua_beginmodule(tolua_S, "cPluginLua");
- tolua_function(tolua_S, "AddTab", tolua_cPluginLua_AddTab);
- tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab);
+ tolua_beginmodule(tolua_S, "cScoreboard");
+ tolua_function(tolua_S, "ForEachObjective", ForEach<cScoreboard, cObjective, &cScoreboard::ForEachObjective>);
+ tolua_function(tolua_S, "ForEachTeam", ForEach<cScoreboard, cTeam, &cScoreboard::ForEachTeam>);
tolua_endmodule(tolua_S);
- tolua_cclass(tolua_S, "HTTPRequest", "HTTPRequest", "", nullptr);
- tolua_beginmodule(tolua_S, "HTTPRequest");
- // tolua_variable(tolua_S, "Method", tolua_get_HTTPRequest_Method, tolua_set_HTTPRequest_Method);
- // tolua_variable(tolua_S, "Path", tolua_get_HTTPRequest_Path, tolua_set_HTTPRequest_Path);
- tolua_variable(tolua_S, "FormData", tolua_get_HTTPRequest_FormData, 0);
- tolua_variable(tolua_S, "Params", tolua_get_HTTPRequest_Params, 0);
- tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, 0);
+ 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_UncompressStringGZIP);
+ tolua_function(tolua_S, "InflateString", tolua_InflateString);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWebAdmin");
@@ -3841,47 +2893,16 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cWebPlugin");
tolua_function(tolua_S, "GetTabNames", tolua_cWebPlugin_GetTabNames);
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, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
- 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, "cItemGrid");
- tolua_function(tolua_S, "GetSlotCoords", Lua_ItemGrid_GetSlotCoords);
+ 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, "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, "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_UncompressStringGZIP);
- tolua_function(tolua_S, "InflateString", tolua_InflateString);
- tolua_endmodule(tolua_S);
-
- BindRankManager(tolua_S);
BindNetwork(tolua_S);
-
- tolua_beginmodule(tolua_S, "cEntity");
- tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID);
- tolua_endmodule(tolua_S);
+ BindRankManager(tolua_S);
+ BindWorld(tolua_S);
tolua_endmodule(tolua_S);
}
diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h
index 74d24d5f5..e7a576588 100644
--- a/src/Bindings/ManualBindings.h
+++ b/src/Bindings/ManualBindings.h
@@ -1,33 +1,566 @@
+
+// ManualBindings.h
+
+// Declares the cManualBindings class used as a namespace for functions exported to the Lua API manually
+
+
+
+
+
#pragma once
-struct lua_State;
-class cPluginLua;
+#include "LuaState.h"
+
+
+
+
+// fwd:
+struct tolua_Error;
/** Provides namespace for the bindings. */
-class ManualBindings
+class cManualBindings
{
public:
/** Binds all the manually implemented functions to tolua_S. */
static void Bind(lua_State * tolua_S);
protected:
+ /** Binds the manually implemented cNetwork-related API to tolua_S.
+ Implemented in ManualBindings_Network.cpp. */
+ static void BindNetwork(lua_State * tolua_S);
+
/** Binds the manually implemented cRankManager glue code to tolua_S.
Implemented in ManualBindings_RankManager.cpp. */
static void BindRankManager(lua_State * tolua_S);
- /** Binds the manually implemented cNetwork-related API to tolua_S.
- Implemented in ManualBindings_Network.cpp. */
- static void BindNetwork(lua_State * tolua_S);
-};
+ /** Binds the manually implemented cWorld API functions to tolua_S.
+ Implemented in ManualBindings_World.cpp. */
+ static void BindWorld(lua_State * tolua_S);
+
+
+public:
+ // Helper functions:
+ static cPluginLua * GetLuaPlugin(lua_State * L);
+ static int tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError);
+ static int lua_do_error(lua_State * L, const char * a_pFormat, ...);
+
+
+ /** Binds the DoWith(ItemName) functions of regular classes. */
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
+ >
+ static int DoWith(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamString(2) ||
+ !L.CheckParamFunction(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ Ty1 * Self;
+ AString ItemName;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, ItemName, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+ if (ItemName.empty() || (ItemName[0] == 0))
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Self->*DoWithFn)(ItemName, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ /** Template for static functions DoWith(ItemName), on a type that has a static ::Get() function. */
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &)
+ >
+ static int StaticDoWith(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamString(2) ||
+ !L.CheckParamFunction(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ AString ItemName;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(2, ItemName, FnRef);
+ if (ItemName.empty() || (ItemName[0] == 0))
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Ty1::Get()->*DoWithFn)(ItemName, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*DoWithFn)(UInt32, cItemCallback<Ty2> &)
+ >
+ static int DoWithID(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamNumber(2) ||
+ !L.CheckParamFunction(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ Ty1 * Self = nullptr;
+ int ItemID;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, ItemID, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Self->*DoWithFn)(ItemID, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
-extern cPluginLua * GetLuaPlugin(lua_State * L);
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*DoWithFn)(int, int, int, cItemCallback<Ty2> &)
+ >
+ static int DoWithXYZ(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamNumber(2, 5) ||
+ !L.CheckParamFunction(6)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ Ty1 * Self = nullptr;
+ int BlockX, BlockY, BlockZ;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*ForEachFn)(int, int, cItemCallback<Ty2> &)
+ >
+ static int ForEachInChunk(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamFunction(5)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ Ty1 * Self = nullptr;
+ int ChunkX, ChunkZ;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #4");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*ForEachFn)(const cBoundingBox &, cItemCallback<Ty2> &)
+ >
+ static int ForEachInBox(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamUserType(2, "cBoundingBox") ||
+ !L.CheckParamFunction(3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ Ty1 * Self = nullptr;
+ cBoundingBox * Box = nullptr;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, Box, FnRef);
+ if ((Self == nullptr) || (Box == nullptr))
+ {
+ LOGWARNING("Invalid world (%p) or boundingbox (%p)", Self, Box);
+ L.LogStackTrace();
+ return 0;
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
+ }
+
+ // Callback wrapper for the Lua function:
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FuncRef)
+ {
+ }
+
+ private:
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+
+ // cItemCallback<Ty2> overrides:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool res = false;
+ if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res))
+ {
+ LOGWARNING("Failed to call Lua callback");
+ m_LuaState.LogStackTrace();
+ return true; // Abort enumeration
+ }
+
+ return res;
+ }
+ } Callback(L, FnRef);
+
+ bool res = (Self->*ForEachFn)(*Box, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &)
+ >
+ static int ForEach(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamFunction(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ Ty1 * Self = nullptr;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'.");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool res = false; // By default continue the enumeration
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
+ return res;
+ }
+ } Callback(L, FnRef);
+
+ // Call the enumeration:
+ bool res = (Self->*ForEachFn)(Callback);
+
+ // Push the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ /** Implements bindings for ForEach() functions in a class that is static (has a ::Get() static function). */
+ template <
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &)
+ >
+ static int StaticForEach(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamFunction(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ cLuaState::cRef FnRef(L, 2);
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1");
+ }
+
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool res = false; // By default continue the enumeration
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res);
+ return res;
+ }
+ } Callback(L, FnRef);
+
+ // Call the enumeration:
+ bool res = (Ty1::Get()->*ForEachFn)(Callback);
+
+ // Push the return value:
+ L.Push(res);
+ return 1;
+ }
+};
diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp
index 628cda7f0..df97d60b3 100644
--- a/src/Bindings/ManualBindings_Network.cpp
+++ b/src/Bindings/ManualBindings_Network.cpp
@@ -39,7 +39,7 @@ static int tolua_cNetwork_Connect(lua_State * L)
}
// Get the plugin instance:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -92,7 +92,7 @@ static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L)
}
// Get the plugin instance:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -171,7 +171,7 @@ static int tolua_cNetwork_HostnameToIP(lua_State * L)
}
// Get the plugin instance:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -212,7 +212,7 @@ static int tolua_cNetwork_IPToHostname(lua_State * L)
}
// Get the plugin instance:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -253,7 +253,7 @@ static int tolua_cNetwork_Listen(lua_State * L)
}
// Get the plugin instance:
- cPluginLua * Plugin = GetLuaPlugin(L);
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L);
if (Plugin == nullptr)
{
// An error message has been already printed in GetLuaPlugin()
@@ -913,17 +913,17 @@ static int tolua_cUDPEndpoint_Send(lua_State * L)
////////////////////////////////////////////////////////////////////////////////
// Register the bindings:
-void ManualBindings::BindNetwork(lua_State * tolua_S)
+void cManualBindings::BindNetwork(lua_State * tolua_S)
{
// Create the cNetwork API classes:
tolua_usertype(tolua_S, "cNetwork");
- tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr);
- tolua_usertype(tolua_S, "cTCPLink");
- tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr);
tolua_usertype(tolua_S, "cServerHandle");
- tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle);
+ tolua_usertype(tolua_S, "cTCPLink");
tolua_usertype(tolua_S, "cUDPEndpoint");
- tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint);
+ tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr);
+ tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle);
+ tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr);
+ tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint);
// Fill in the functions (alpha-sorted):
tolua_beginmodule(tolua_S, "cNetwork");
diff --git a/src/Bindings/ManualBindings_RankManager.cpp b/src/Bindings/ManualBindings_RankManager.cpp
index fa1b88b6a..7797d1887 100644
--- a/src/Bindings/ManualBindings_RankManager.cpp
+++ b/src/Bindings/ManualBindings_RankManager.cpp
@@ -100,6 +100,35 @@ static int tolua_cRankManager_AddPermissionToGroup(lua_State * L)
+/** Binds cRankManager::AddRestrictionToGroup */
+static int tolua_cRankManager_AddRestrictionToGroup(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:AddRestrictionToGroup(Permission, GroupName) -> bool
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2, 3) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Read the params:
+ AString GroupName, Permission;
+ S.GetStackValues(2, Permission, GroupName);
+
+ // Add the group to the rank:
+ S.Push(cRoot::Get()->GetRankManager()->AddRestrictionToGroup(Permission, GroupName));
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::AddRank */
static int tolua_cRankManager_AddRank(lua_State * L)
{
@@ -204,6 +233,60 @@ static int tolua_cRankManager_GetAllPermissions(lua_State * L)
+/** Binds cRankManager::GetAllPermissions */
+static int tolua_cRankManager_GetAllRestrictions(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:GetAllRestrictions() -> arraytable of Permissions
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamEnd(2)
+ )
+ {
+ return 0;
+ }
+
+ // Get the permissions:
+ AStringVector Permissions = cRoot::Get()->GetRankManager()->GetAllRestrictions();
+
+ // Push the results:
+ S.Push(Permissions);
+ return 1;
+}
+
+
+
+
+
+/** Binds cRankManager::GetAllPermissionsRestrictions */
+static int tolua_cRankManager_GetAllPermissionsRestrictions(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:GetAllPermissionsRestrictions() -> arraytable of Permissions and Restrictions
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamEnd(2)
+ )
+ {
+ return 0;
+ }
+
+ // Get the permissions:
+ AStringVector Permissions = cRoot::Get()->GetRankManager()->GetAllPermissionsRestrictions();
+
+ // Push the results:
+ S.Push(Permissions);
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::GetAllPlayerUUIDs */
static int tolua_cRankManager_GetAllPlayerUUIDs(lua_State * L)
{
@@ -314,6 +397,38 @@ static int tolua_cRankManager_GetGroupPermissions(lua_State * L)
+/** Binds cRankManager::GetGroupRestrictions */
+static int tolua_cRankManager_GetGroupRestrictions(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:GetGroupRestrictions(GroupName) -> arraytable of restrictions
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ AString GroupName;
+ S.GetStackValue(2, GroupName);
+
+ // Get the restrictions:
+ AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetGroupRestrictions(GroupName);
+
+ // Push the results:
+ S.Push(Restrictions);
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::GetPlayerGroups */
static int tolua_cRankManager_GetPlayerGroups(lua_State * L)
{
@@ -416,6 +531,38 @@ static int tolua_cRankManager_GetPlayerPermissions(lua_State * L)
+/** Binds cRankManager::GetPlayerRestrictions */
+static int tolua_cRankManager_GetPlayerRestrictions(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:GetPlayerRestrictions(PlayerUUID) -> arraytable of restrictions
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ AString PlayerUUID;
+ S.GetStackValue(2, PlayerUUID);
+
+ // Get the permissions:
+ AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetPlayerRestrictions(PlayerUUID);
+
+ // Push the results:
+ S.Push(Restrictions);
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::GetPlayerRankName */
static int tolua_cRankManager_GetPlayerRankName(lua_State * L)
{
@@ -544,6 +691,38 @@ static int tolua_cRankManager_GetRankPermissions(lua_State * L)
+/** Binds cRankManager::GetRankRestrictions */
+static int tolua_cRankManager_GetRankRestrictions(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:GetRankRestrictions(RankName) -> arraytable of restrictions
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ AString RankName;
+ S.GetStackValue(2, RankName);
+
+ // Get the permissions:
+ AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetRankRestrictions(RankName);
+
+ // Push the results:
+ S.Push(Restrictions);
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::GetRankVisuals */
static int tolua_cRankManager_GetRankVisuals(lua_State * L)
{
@@ -679,6 +858,38 @@ static int tolua_cRankManager_IsPermissionInGroup(lua_State * L)
+/** Binds cRankManager::IsRestrictionInGroup */
+static int tolua_cRankManager_IsRestrictionInGroup(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:IsRestrictionInGroup(Restriction, GroupName) -> bool
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2, 3) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ AString GroupName, Restriction;
+ S.GetStackValues(2, Restriction, GroupName);
+
+ // Get the response:
+ bool res = cRoot::Get()->GetRankManager()->IsRestrictionInGroup(Restriction, GroupName);
+
+ // Push the result:
+ S.Push(res);
+ return 1;
+}
+
+
+
+
+
/** Binds cRankManager::IsPlayerRankSet */
static int tolua_cRankManager_IsPlayerRankSet(lua_State * L)
{
@@ -821,7 +1032,7 @@ static int tolua_cRankManager_RemovePermissionFromGroup(lua_State * L)
AString GroupName, Permission;
S.GetStackValues(2, Permission, GroupName);
- // Remove the group:
+ // Remove the permission:
cRoot::Get()->GetRankManager()->RemovePermissionFromGroup(Permission, GroupName);
return 0;
}
@@ -830,6 +1041,35 @@ static int tolua_cRankManager_RemovePermissionFromGroup(lua_State * L)
+/** Binds cRankManager::RemoveRestrictionFromGroup */
+static int tolua_cRankManager_RemoveRestrictionFromGroup(lua_State * L)
+{
+ // Function signature:
+ // cRankManager:RemoveRestrictionFromGroup(Restriction, GroupName)
+
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cRankManager") ||
+ !S.CheckParamString(2, 3) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ AString GroupName, Restriction;
+ S.GetStackValues(2, Restriction, GroupName);
+
+ // Remove the restriction:
+ cRoot::Get()->GetRankManager()->RemoveRestrictionFromGroup(Restriction, GroupName);
+ return 0;
+}
+
+
+
+
+
/** Binds cRankManager::RemovePlayerRank */
static int tolua_cRankManager_RemovePlayerRank(lua_State * L)
{
@@ -1040,7 +1280,7 @@ static int tolua_cRankManager_SetRankVisuals(lua_State * L)
-void ManualBindings::BindRankManager(lua_State * tolua_S)
+void cManualBindings::BindRankManager(lua_State * tolua_S)
{
// Create the cRankManager class in the API:
tolua_usertype(tolua_S, "cRankManager");
@@ -1048,40 +1288,48 @@ void ManualBindings::BindRankManager(lua_State * tolua_S)
// Fill in the functions (alpha-sorted):
tolua_beginmodule(tolua_S, "cRankManager");
- tolua_function(tolua_S, "AddGroup", tolua_cRankManager_AddGroup);
- tolua_function(tolua_S, "AddGroupToRank", tolua_cRankManager_AddGroupToRank);
- tolua_function(tolua_S, "AddPermissionToGroup", tolua_cRankManager_AddPermissionToGroup);
- tolua_function(tolua_S, "AddRank", tolua_cRankManager_AddRank);
- tolua_function(tolua_S, "ClearPlayerRanks", tolua_cRankManager_ClearPlayerRanks);
- tolua_function(tolua_S, "GetAllGroups", tolua_cRankManager_GetAllGroups);
- tolua_function(tolua_S, "GetAllPermissions", tolua_cRankManager_GetAllPermissions);
- tolua_function(tolua_S, "GetAllPlayerUUIDs", tolua_cRankManager_GetAllPlayerUUIDs);
- tolua_function(tolua_S, "GetAllRanks", tolua_cRankManager_GetAllRanks);
- tolua_function(tolua_S, "GetDefaultRank", tolua_cRankManager_GetDefaultRank);
- tolua_function(tolua_S, "GetGroupPermissions", tolua_cRankManager_GetGroupPermissions);
- tolua_function(tolua_S, "GetPlayerGroups", tolua_cRankManager_GetPlayerGroups);
- tolua_function(tolua_S, "GetPlayerMsgVisuals", tolua_cRankManager_GetPlayerMsgVisuals);
- tolua_function(tolua_S, "GetPlayerPermissions", tolua_cRankManager_GetPlayerPermissions);
- tolua_function(tolua_S, "GetPlayerRankName", tolua_cRankManager_GetPlayerRankName);
- tolua_function(tolua_S, "GetPlayerName", tolua_cRankManager_GetPlayerName);
- tolua_function(tolua_S, "GetRankGroups", tolua_cRankManager_GetRankGroups);
- tolua_function(tolua_S, "GetRankPermissions", tolua_cRankManager_GetRankPermissions);
- tolua_function(tolua_S, "GetRankVisuals", tolua_cRankManager_GetRankVisuals);
- tolua_function(tolua_S, "GroupExists", tolua_cRankManager_GroupExists);
- tolua_function(tolua_S, "IsGroupInRank", tolua_cRankManager_IsGroupInRank);
- tolua_function(tolua_S, "IsPermissionInGroup", tolua_cRankManager_IsPermissionInGroup);
- tolua_function(tolua_S, "IsPlayerRankSet", tolua_cRankManager_IsPlayerRankSet);
- tolua_function(tolua_S, "RankExists", tolua_cRankManager_RankExists);
- tolua_function(tolua_S, "RemoveGroup", tolua_cRankManager_RemoveGroup);
- tolua_function(tolua_S, "RemoveGroupFromRank", tolua_cRankManager_RemoveGroupFromRank);
- tolua_function(tolua_S, "RemovePermissionFromGroup", tolua_cRankManager_RemovePermissionFromGroup);
- tolua_function(tolua_S, "RemovePlayerRank", tolua_cRankManager_RemovePlayerRank);
- tolua_function(tolua_S, "RemoveRank", tolua_cRankManager_RemoveRank);
- tolua_function(tolua_S, "RenameGroup", tolua_cRankManager_RenameGroup);
- tolua_function(tolua_S, "RenameRank", tolua_cRankManager_RenameRank);
- tolua_function(tolua_S, "SetDefaultRank", tolua_cRankManager_SetDefaultRank);
- tolua_function(tolua_S, "SetPlayerRank", tolua_cRankManager_SetPlayerRank);
- tolua_function(tolua_S, "SetRankVisuals", tolua_cRankManager_SetRankVisuals);
+ tolua_function(tolua_S, "AddGroup", tolua_cRankManager_AddGroup);
+ tolua_function(tolua_S, "AddGroupToRank", tolua_cRankManager_AddGroupToRank);
+ tolua_function(tolua_S, "AddPermissionToGroup", tolua_cRankManager_AddPermissionToGroup);
+ tolua_function(tolua_S, "AddRestrictionToGroup", tolua_cRankManager_AddRestrictionToGroup);
+ tolua_function(tolua_S, "AddRank", tolua_cRankManager_AddRank);
+ tolua_function(tolua_S, "ClearPlayerRanks", tolua_cRankManager_ClearPlayerRanks);
+ tolua_function(tolua_S, "GetAllGroups", tolua_cRankManager_GetAllGroups);
+ tolua_function(tolua_S, "GetAllPermissions", tolua_cRankManager_GetAllPermissions);
+ tolua_function(tolua_S, "GetAllRestrictions", tolua_cRankManager_GetAllRestrictions);
+ tolua_function(tolua_S, "GetAllPermissionsRestrictions", tolua_cRankManager_GetAllPermissionsRestrictions);
+ tolua_function(tolua_S, "GetAllPlayerUUIDs", tolua_cRankManager_GetAllPlayerUUIDs);
+ tolua_function(tolua_S, "GetAllRanks", tolua_cRankManager_GetAllRanks);
+ tolua_function(tolua_S, "GetDefaultRank", tolua_cRankManager_GetDefaultRank);
+ tolua_function(tolua_S, "GetGroupPermissions", tolua_cRankManager_GetGroupPermissions);
+ tolua_function(tolua_S, "GetGroupRestrictions", tolua_cRankManager_GetGroupRestrictions);
+ tolua_function(tolua_S, "GetPlayerGroups", tolua_cRankManager_GetPlayerGroups);
+ tolua_function(tolua_S, "GetPlayerMsgVisuals", tolua_cRankManager_GetPlayerMsgVisuals);
+ tolua_function(tolua_S, "GetPlayerPermissions", tolua_cRankManager_GetPlayerPermissions);
+ tolua_function(tolua_S, "GetPlayerPermissions", tolua_cRankManager_GetPlayerRestrictions);
+ tolua_function(tolua_S, "GetPlayerRankName", tolua_cRankManager_GetPlayerRankName);
+ tolua_function(tolua_S, "GetPlayerName", tolua_cRankManager_GetPlayerName);
+ tolua_function(tolua_S, "GetRankGroups", tolua_cRankManager_GetRankGroups);
+ tolua_function(tolua_S, "GetRankPermissions", tolua_cRankManager_GetRankPermissions);
+ tolua_function(tolua_S, "GetRankRestrictions", tolua_cRankManager_GetRankRestrictions);
+ tolua_function(tolua_S, "GetRankVisuals", tolua_cRankManager_GetRankVisuals);
+ tolua_function(tolua_S, "GroupExists", tolua_cRankManager_GroupExists);
+ tolua_function(tolua_S, "IsGroupInRank", tolua_cRankManager_IsGroupInRank);
+ tolua_function(tolua_S, "IsPermissionInGroup", tolua_cRankManager_IsPermissionInGroup);
+ tolua_function(tolua_S, "IsRestrictionInGroup", tolua_cRankManager_IsRestrictionInGroup);
+ tolua_function(tolua_S, "IsPlayerRankSet", tolua_cRankManager_IsPlayerRankSet);
+ tolua_function(tolua_S, "RankExists", tolua_cRankManager_RankExists);
+ tolua_function(tolua_S, "RemoveGroup", tolua_cRankManager_RemoveGroup);
+ tolua_function(tolua_S, "RemoveGroupFromRank", tolua_cRankManager_RemoveGroupFromRank);
+ tolua_function(tolua_S, "RemovePermissionFromGroup", tolua_cRankManager_RemovePermissionFromGroup);
+ tolua_function(tolua_S, "RemoveRestrictionFromGroup", tolua_cRankManager_RemoveRestrictionFromGroup);
+ tolua_function(tolua_S, "RemovePlayerRank", tolua_cRankManager_RemovePlayerRank);
+ tolua_function(tolua_S, "RemoveRank", tolua_cRankManager_RemoveRank);
+ tolua_function(tolua_S, "RenameGroup", tolua_cRankManager_RenameGroup);
+ tolua_function(tolua_S, "RenameRank", tolua_cRankManager_RenameRank);
+ tolua_function(tolua_S, "SetDefaultRank", tolua_cRankManager_SetDefaultRank);
+ tolua_function(tolua_S, "SetPlayerRank", tolua_cRankManager_SetPlayerRank);
+ tolua_function(tolua_S, "SetRankVisuals", tolua_cRankManager_SetRankVisuals);
tolua_endmodule(tolua_S);
}
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp
new file mode 100644
index 000000000..5becbba92
--- /dev/null
+++ b/src/Bindings/ManualBindings_World.cpp
@@ -0,0 +1,588 @@
+
+// ManualBindings_World.cpp
+
+// Implements the manual Lua API bindings for the cWorld class
+
+#include "Globals.h"
+#include "tolua++/include/tolua++.h"
+#include "../World.h"
+#include "../Broadcaster.h"
+#include "ManualBindings.h"
+#include "LuaState.h"
+#include "PluginLua.h"
+#include "LuaChunkStay.h"
+
+
+
+
+
+static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S)
+{
+ /* Function signature:
+ World:BroadcastParticleEffect("Name", PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2]
+ */
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamString (2) ||
+ !L.CheckParamNumber (3, 10)
+ )
+ {
+ return 0;
+ }
+
+ // Read the params:
+ cWorld * World = nullptr;
+ AString Name;
+ float PosX, PosY, PosZ, OffX, OffY, OffZ;
+ float ParticleData;
+ int ParticleAmmount;
+ cClientHandle * ExcludeClient = nullptr;
+ L.GetStackValues(1, World, Name, PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmmount, ExcludeClient);
+ if (World == nullptr)
+ {
+ LOGWARNING("World:BroadcastParticleEffect(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+
+ // Read up to 2 more optional data params:
+ std::array<int, 2> data;
+ for (int i = 0; (i < 2) && L.IsParamNumber(11 + i); i++)
+ {
+ L.GetStackValue(11 + i, data[i]);
+ }
+
+ World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmmount, ExcludeClient);
+
+ return 0;
+}
+
+
+
+
+
+static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
+{
+ /* Function signature:
+ World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable)
+ ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... }
+ */
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType (1, "cWorld") ||
+ !L.CheckParamTable (2) ||
+ !L.CheckParamFunctionOrNil(3, 4)
+ )
+ {
+ return 0;
+ }
+
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
+ if (Plugin == nullptr)
+ {
+ return 0;
+ }
+
+ // Read the params:
+ cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
+ if (World == nullptr)
+ {
+ LOGWARNING("World:ChunkStay(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+
+ cLuaChunkStay * ChunkStay = new cLuaChunkStay(*Plugin);
+
+ if (!ChunkStay->AddChunks(2))
+ {
+ delete ChunkStay;
+ ChunkStay = nullptr;
+ return 0;
+ }
+
+ ChunkStay->Enable(*World->GetChunkMap(), 3, 4);
+ return 0;
+}
+
+
+
+
+
+static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight)
+ // Function signature: GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight]
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamEnd(5)
+ )
+ {
+ return 0;
+ }
+
+ // Get params:
+ cWorld * Self = nullptr;
+ int BlockX, BlockY, BlockZ;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ);
+ if (Self == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+
+ // Call the function:
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight;
+ bool res = Self->GetBlockInfo(BlockX, BlockY, BlockZ, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight);
+
+ // Push the returned values:
+ L.Push(res);
+ if (res)
+ {
+ L.Push(BlockType);
+ L.Push(BlockMeta);
+ L.Push(BlockSkyLight);
+ L.Push(BlockBlockLight);
+ return 5;
+ }
+ return 1;
+}
+
+
+
+
+
+static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta)
+ // Function signature: GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta]
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamEnd(5)
+ )
+ {
+ return 0;
+ }
+
+ // Get params:
+ cWorld * Self = nullptr;
+ int BlockX, BlockY, BlockZ;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ);
+ if (Self == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+
+ // Call the function:
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ bool res = Self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta);
+
+ // Push the returned values:
+ L.Push(res);
+ if (res)
+ {
+ L.Push(BlockType);
+ L.Push(BlockMeta);
+ return 3;
+ }
+ return 1;
+}
+
+
+
+
+
+static int tolua_cWorld_GetSignLines(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional parameters (a_Line1 .. a_Line4)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamEnd(5)
+ )
+ {
+ return 0;
+ }
+
+ // Get params:
+ cWorld * Self = nullptr;
+ int BlockX, BlockY, BlockZ;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ);
+ if (Self == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+
+ // Call the function:
+ AString Line1, Line2, Line3, Line4;
+ bool res = Self->GetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
+
+ // Push the returned values:
+ L.Push(res);
+ if (res)
+ {
+ L.Push(Line1);
+ L.Push(Line2);
+ L.Push(Line3);
+ L.Push(Line4);
+ return 5;
+ }
+ return 1;
+}
+
+
+
+
+
+static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
+{
+ /* Function signature:
+ World:PrepareChunk(ChunkX, ChunkZ, Callback)
+ */
+
+ // Check the param types:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType (1, "cWorld") ||
+ !L.CheckParamNumber (2, 3) ||
+ !L.CheckParamFunctionOrNil(4)
+ )
+ {
+ return 0;
+ }
+
+ // Read the params:
+ cWorld * world = nullptr;
+ int chunkX = 0, chunkZ = 0;
+ L.GetStackValues(1, world, chunkX, chunkZ);
+ if (world == nullptr)
+ {
+ LOGWARNING("World:PrepareChunk(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+
+ // Wrap the Lua callback inside a C++ callback class:
+ class cCallback:
+ public cChunkCoordCallback
+ {
+ public:
+ cCallback(lua_State * a_LuaState):
+ m_LuaState(a_LuaState),
+ m_Callback(m_LuaState, 4)
+ {
+ }
+
+ // cChunkCoordCallback override:
+ virtual void Call(int a_CBChunkX, int a_CBChunkZ) override
+ {
+ if (m_Callback.IsValid())
+ {
+ m_LuaState.Call(m_Callback, a_CBChunkX, a_CBChunkZ);
+ }
+
+ // This is the last reference of this object, we must delete it so that it doesn't leak:
+ delete this;
+ }
+
+ protected:
+ cLuaState m_LuaState;
+ cLuaState::cRef m_Callback;
+ };
+ cCallback * callback = new cCallback(tolua_S);
+
+ // Call the chunk preparation:
+ world->PrepareChunk(chunkX, chunkZ, callback);
+ return 0;
+}
+
+
+
+
+
+class cLuaWorldTask :
+ public cWorld::cTask,
+ public cPluginLua::cResettable
+{
+public:
+ cLuaWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
+ cPluginLua::cResettable(a_Plugin),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+protected:
+ int m_FnRef;
+
+ // cWorld::cTask overrides:
+ virtual void Run(cWorld & a_World) override
+ {
+ cCSLock Lock(m_CSPlugin);
+ if (m_Plugin != nullptr)
+ {
+ m_Plugin->Call(m_FnRef, &a_World);
+ }
+ }
+} ;
+
+
+
+
+
+static int tolua_cWorld_QueueTask(lua_State * tolua_S)
+{
+ // Binding for cWorld::QueueTask
+ // Params: function
+
+ // Retrieve the cPlugin from the LuaState:
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
+ if (Plugin == nullptr)
+ {
+ // An error message has been already printed in GetLuaPlugin()
+ return 0;
+ }
+
+ // Retrieve the args:
+ cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
+ if (self == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
+ }
+ if (!lua_isfunction(tolua_S, 2))
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
+ }
+
+ // Create a reference to the function:
+ int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
+ if (FnRef == LUA_REFNIL)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
+ }
+
+ auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(task);
+ self->QueueTask(task);
+ return 0;
+}
+
+
+
+
+
+static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
+{
+ // Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4)
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamString(5, 8) ||
+ !L.CheckParamEnd(9)
+ )
+ {
+ return 0;
+ }
+
+ // Get params:
+ cWorld * Self = nullptr;
+ int BlockX, BlockY, BlockZ;
+ AString Line1, Line2, Line3, Line4;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
+ if (Self == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+
+ // Call the function:
+ bool res = Self->SetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
+
+ // Push the returned values:
+ L.Push(res);
+ return 1;
+}
+
+
+
+
+
+class cLuaScheduledWorldTask :
+ public cWorld::cTask,
+ public cPluginLua::cResettable
+{
+public:
+ cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
+ cPluginLua::cResettable(a_Plugin),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+protected:
+ int m_FnRef;
+
+ // cWorld::cTask overrides:
+ virtual void Run(cWorld & a_World) override
+ {
+ cCSLock Lock(m_CSPlugin);
+ if (m_Plugin != nullptr)
+ {
+ m_Plugin->Call(m_FnRef, &a_World);
+ }
+ }
+};
+
+
+
+
+
+static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
+{
+ // Binding for cWorld::ScheduleTask
+ // Params: function, Ticks
+
+ // Retrieve the cPlugin from the LuaState:
+ cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
+ if (Plugin == nullptr)
+ {
+ // An error message has been already printed in GetLuaPlugin()
+ return 0;
+ }
+
+ // Retrieve the args:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber (2) ||
+ !L.CheckParamFunction(3)
+ )
+ {
+ return 0;
+ }
+ cWorld * World = (cWorld *)tolua_tousertype(tolua_S, 1, nullptr);
+ if (World == nullptr)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
+ }
+
+ // Create a reference to the function:
+ int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
+ if (FnRef == LUA_REFNIL)
+ {
+ return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
+ }
+
+ int DelayTicks = (int)tolua_tonumber(tolua_S, 2, 0);
+
+ auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(task);
+ World->ScheduleTask(DelayTicks, task);
+ return 0;
+}
+
+
+
+
+
+
+static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
+{
+ /* Exported manually, because tolua would require the out-only param a_Height to be used when calling
+ Function signature: world:TryGetHeight(a_World, a_BlockX, a_BlockZ) -> IsValid, Height
+ */
+
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamNumber(2, 3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Get params:
+ cWorld * self = nullptr;
+ int BlockX, BlockZ;
+ L.GetStackValues(1, self, BlockX, BlockZ);
+ if (self == nullptr)
+ {
+ tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", nullptr);
+ return 0;
+ }
+
+ // Call the implementation:
+ int Height = 0;
+ bool res = self->TryGetHeight(BlockX, BlockZ, Height);
+ L.Push(res);
+ if (res)
+ {
+ L.Push(Height);
+ return 2;
+ }
+ return 1;
+}
+
+
+
+
+
+void cManualBindings::BindWorld(lua_State * tolua_S)
+{
+ tolua_beginmodule(tolua_S, nullptr);
+ tolua_beginmodule(tolua_S, "cWorld");
+ tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect);
+ tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
+ tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
+ tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
+ tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
+ tolua_function(tolua_S, "DoWithDispenserAt", DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
+ tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);
+ tolua_function(tolua_S, "DoWithDropperAt", DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>);
+ tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>);
+ tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>);
+ tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);
+ tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>);
+ tolua_function(tolua_S, "DoWithMobHeadAt", DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>);
+ tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
+ tolua_function(tolua_S, "DoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
+ tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
+ tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayerByUUID>);
+ tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
+ tolua_function(tolua_S, "ForEachChestInChunk", ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
+ tolua_function(tolua_S, "ForEachEntity", ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);
+ tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>);
+ tolua_function(tolua_S, "ForEachEntityInChunk", ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
+ tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
+ tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
+ tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
+ tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
+ tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
+ tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk);
+ tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
+ tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
+ tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
+ tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
+ tolua_endmodule(tolua_S);
+ tolua_endmodule(tolua_S);
+}
+
+
+
+
diff --git a/src/Bindings/Plugin.cpp b/src/Bindings/Plugin.cpp
index 98ccfb88c..2f2771e38 100644
--- a/src/Bindings/Plugin.cpp
+++ b/src/Bindings/Plugin.cpp
@@ -7,11 +7,11 @@
-cPlugin::cPlugin(const AString & a_PluginDirectory) :
- m_Language(E_CPP),
- m_Name(a_PluginDirectory),
+cPlugin::cPlugin(const AString & a_FolderName) :
+ m_Status(cPluginManager::psDisabled),
+ m_Name(a_FolderName),
m_Version(0),
- m_Directory(a_PluginDirectory)
+ m_FolderName(a_FolderName)
{
}
@@ -28,9 +28,33 @@ cPlugin::~cPlugin()
+void cPlugin::Unload(void)
+{
+ auto pm = cPluginManager::Get();
+ pm->RemovePluginCommands(this);
+ pm->RemovePluginConsoleCommands(this);
+ pm->RemoveHooks(this);
+ OnDisable();
+ m_Status = cPluginManager::psUnloaded;
+ m_LoadError.clear();
+}
+
+
+
+
+
AString cPlugin::GetLocalFolder(void) const
{
- return std::string("Plugins/") + m_Directory;
+ return std::string("Plugins/") + m_FolderName;
+}
+
+
+
+
+void cPlugin::SetLoadError(const AString & a_LoadError)
+{
+ m_Status = cPluginManager::psError;
+ m_LoadError = a_LoadError;
}
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index 3f9fa7655..1330bca0d 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -1,30 +1,16 @@
-#pragma once
-
-#include "Defines.h"
+// Plugin.h
-class cCommandOutputCallback;
-class cItems;
-class cHopperEntity;
+// Declares the cPlugin class representing an interface that a plugin implementation needs to expose, with some helping functions
-class cBlockEntityWithItems;
-class cClientHandle;
-class cPickup;
-class cPlayer;
-class cProjectileEntity;
-class cEntity;
-class cMonster;
-class cWorld;
-class cChunkDesc;
-struct TakeDamageInfo;
-// fwd: CraftingRecipes.h
-class cCraftingGrid;
-class cCraftingRecipe;
+#pragma once
+#include "Defines.h"
+#include "PluginManager.h"
@@ -35,11 +21,23 @@ class cPlugin
public:
// tolua_end
- cPlugin( const AString & a_PluginDirectory);
+ /** Creates a new instance.
+ a_FolderName is the name of the folder (in the Plugins folder) from which the plugin is loaded.
+ The plugin's name defaults to the folder name. */
+ cPlugin(const AString & a_FolderName);
+
virtual ~cPlugin();
+ /** Called as the last call into the plugin before it is unloaded. */
virtual void OnDisable(void) {}
- virtual bool Initialize(void) = 0;
+
+ /** Loads and initializes the plugin. Sets m_Status to psLoaded or psError accordingly.
+ Returns true if the initialization succeeded, false otherwise. */
+ virtual bool Load(void) = 0;
+
+ /** Unloads the plugin. Sets m_Status to psDisabled.
+ The default implementation removes the plugin's associations with cPluginManager, descendants should call it as well. */
+ virtual void Unload(void);
// Called each tick
virtual void Tick(float a_Dt) = 0;
@@ -58,7 +56,9 @@ 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 OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 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;
@@ -109,19 +109,17 @@ public:
/** Handles the command split into a_Split, issued by player a_Player.
Command permissions have already been checked.
- Returns true if command handled successfully
- */
+ Returns true if command handled successfully. */
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) = 0;
/** Handles the console command split into a_Split.
- Returns true if command handled successfully. Output is to be sent to the a_Output callback.
- */
+ Returns true if command handled successfully. Output is to be sent to the a_Output callback. */
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) = 0;
- /// All bound commands are to be removed, do any language-dependent cleanup here
+ /** All bound commands are to be removed, do any language-dependent cleanup here */
virtual void ClearCommands(void) {}
- /// All bound console commands are to be removed, do any language-dependent cleanup here
+ /** All bound console commands are to be removed, do any language-dependent cleanup here */
virtual void ClearConsoleCommands(void) {}
// tolua_begin
@@ -131,28 +129,43 @@ public:
int GetVersion(void) const { return m_Version; }
void SetVersion(int a_Version) { m_Version = a_Version; }
- const AString & GetDirectory(void) const {return m_Directory; }
- AString GetLocalDirectory(void) const {return GetLocalFolder(); } // OBSOLETE, use GetLocalFolder() instead
+ /** Returns the name of the folder (in the Plugins folder) from which the plugin is loaded. */
+ const AString & GetFolderName(void) const {return m_FolderName; }
+
+ /** Returns the folder relative to the MCS Executable, from which the plugin is loaded. */
AString GetLocalFolder(void) const;
+
+ /** Returns the error encountered while loading the plugin. Only valid if m_Status == psError. */
+ const AString & GetLoadError(void) const { return m_LoadError; }
+
+ cPluginManager::ePluginStatus GetStatus(void) const { return m_Status; }
+
+ bool IsLoaded(void) const { return (m_Status == cPluginManager::psLoaded); }
// tolua_end
+ // Needed for ManualBindings' tolua_ForEach<>
+ static const char * GetClassStatic(void) { return "cPlugin"; }
+
+protected:
+ friend class cPluginManager;
+
+ cPluginManager::ePluginStatus m_Status;
- /* This should not be exposed to scripting languages */
- enum PluginLanguage
- {
- E_CPP,
- E_LUA,
- E_SQUIRREL, // OBSOLETE, but kept in place to remind us of the horrors lurking in the history
- };
- PluginLanguage GetLanguage() { return m_Language; }
- void SetLanguage( PluginLanguage a_Language) { m_Language = a_Language; }
-
-private:
- PluginLanguage m_Language;
+ /** The name of the plugin, used to identify the plugin in the system and for inter-plugin calls. */
AString m_Name;
+
int m_Version;
- AString m_Directory;
+ /** Name of the folder (in the Plugins folder) from which the plugin is loaded. */
+ AString m_FolderName;
+
+ /** The error encountered while loading the plugin.
+ Only valid if m_Status == psError. */
+ AString m_LoadError;
+
+
+ /** Sets m_LoadError to the specified string and m_Status to psError. */
+ void SetLoadError(const AString & a_LoadError);
}; // tolua_export
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 0a2a8411d..234bf579b 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -63,6 +63,11 @@ void cPluginLua::Close(void)
return;
}
+ // Remove the command bindings and web tabs:
+ ClearCommands();
+ ClearConsoleCommands();
+ ClearTabs();
+
// Notify and remove all m_Resettables (unlock the m_CriticalSection while resetting them):
cResettablePtrs resettables;
std::swap(m_Resettables, resettables);
@@ -93,7 +98,7 @@ void cPluginLua::Close(void)
-bool cPluginLua::Initialize(void)
+bool cPluginLua::Load(void)
{
cCSLock Lock(m_CriticalSection);
if (!m_LuaState.IsValid())
@@ -144,6 +149,7 @@ bool cPluginLua::Initialize(void)
// Warn if there are no Lua files in the plugin folder:
if (LuaFiles.empty())
{
+ SetLoadError("No lua files found, plugin is probably missing.");
LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str());
Close();
return false;
@@ -155,6 +161,7 @@ bool cPluginLua::Initialize(void)
AString Path = PluginPath + *itr;
if (!m_LuaState.LoadFile(Path))
{
+ SetLoadError(Printf("Failed to load file %s.", itr->c_str()));
Close();
return false;
}
@@ -164,6 +171,8 @@ bool cPluginLua::Initialize(void)
AString Path = PluginPath + "Info.lua";
if (!m_LuaState.LoadFile(Path))
{
+ SetLoadError("Failed to load file Info.lua.");
+ m_Status = cPluginManager::psError;
Close();
return false;
}
@@ -173,17 +182,20 @@ bool cPluginLua::Initialize(void)
bool res = false;
if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res))
{
+ SetLoadError("Cannot call the Initialize() function.");
LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str());
Close();
return false;
}
if (!res)
{
+ SetLoadError("The Initialize() function failed.");
LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str());
Close();
return false;
}
+ m_Status = cPluginManager::psLoaded;
return true;
}
@@ -191,6 +203,17 @@ bool cPluginLua::Initialize(void)
+void cPluginLua::Unload(void)
+{
+ ClearTabs();
+ super::Unload();
+ Close();
+}
+
+
+
+
+
void cPluginLua::OnDisable(void)
{
cCSLock Lock(m_CriticalSection);
@@ -208,6 +231,10 @@ void cPluginLua::OnDisable(void)
void cPluginLua::Tick(float a_Dt)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return;
+ }
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_TICK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
@@ -222,6 +249,10 @@ void cPluginLua::Tick(float a_Dt)
bool cPluginLua::OnBlockSpread(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_BLOCK_SPREAD];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -242,6 +273,10 @@ bool cPluginLua::OnBlockSpread(cWorld & a_World, int a_BlockX, int a_BlockY, int
bool cPluginLua::OnBlockToPickups(cWorld & a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_BLOCK_TO_PICKUPS];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -262,6 +297,10 @@ bool cPluginLua::OnBlockToPickups(cWorld & a_World, cEntity * a_Digger, int a_Bl
bool cPluginLua::OnChat(cPlayer & a_Player, AString & a_Message)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHAT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -282,6 +321,10 @@ bool cPluginLua::OnChat(cPlayer & a_Player, AString & a_Message)
bool cPluginLua::OnChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_AVAILABLE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -302,6 +345,10 @@ bool cPluginLua::OnChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
bool cPluginLua::OnChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -322,6 +369,10 @@ bool cPluginLua::OnChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ,
bool cPluginLua::OnChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_GENERATING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -342,6 +393,10 @@ bool cPluginLua::OnChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ,
bool cPluginLua::OnChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -362,6 +417,10 @@ bool cPluginLua::OnChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
bool cPluginLua::OnChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CHUNK_UNLOADING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -382,6 +441,10 @@ bool cPluginLua::OnChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ)
bool cPluginLua::OnCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_COLLECTING_PICKUP];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -402,6 +465,10 @@ bool cPluginLua::OnCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup)
bool cPluginLua::OnCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_CRAFTING_NO_RECIPE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -422,6 +489,10 @@ bool cPluginLua::OnCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid,
bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -442,6 +513,10 @@ bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason
bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_ADD_EFFECT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -459,14 +534,66 @@ bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_E
-bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
+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);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXECUTE_COMMAND];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), a_Player, a_Split, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), a_Player, a_Split, a_EntireCommand, cLuaState::Return, res, a_Result);
if (res)
{
return true;
@@ -482,6 +609,10 @@ bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Sp
bool cPluginLua::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)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXPLODED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -519,6 +650,10 @@ bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_Can
bool cPluginLua::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)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXPLODING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -556,6 +691,10 @@ bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool &
bool cPluginLua::OnHandshake(cClientHandle & a_Client, const AString & a_Username)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HANDSHAKE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -576,8 +715,11 @@ bool cPluginLua::OnHandshake(cClientHandle & a_Client, const AString & a_Usernam
bool cPluginLua::OnHopperPullingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
-
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HOPPER_PULLING_ITEM];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
@@ -597,6 +739,10 @@ bool cPluginLua::OnHopperPullingItem(cWorld & a_World, cHopperEntity & a_Hopper,
bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_HOPPER_PUSHING_ITEM];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -617,6 +763,10 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper,
bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_KILLING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -637,6 +787,10 @@ bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInf
bool cPluginLua::OnLogin(cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_LOGIN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -657,6 +811,10 @@ bool cPluginLua::OnLogin(cClientHandle & a_Client, int a_ProtocolVersion, const
bool cPluginLua::OnPlayerAnimation(cPlayer & a_Player, int a_Animation)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_ANIMATION];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -677,6 +835,10 @@ bool cPluginLua::OnPlayerAnimation(cPlayer & a_Player, int a_Animation)
bool cPluginLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_BREAKING_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -697,6 +859,10 @@ bool cPluginLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_B
bool cPluginLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_BROKEN_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -717,6 +883,10 @@ bool cPluginLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_Blo
bool cPluginLua::OnPlayerDestroyed(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_DESTROYED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -737,6 +907,10 @@ bool cPluginLua::OnPlayerDestroyed(cPlayer & a_Player)
bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_EATING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -757,6 +931,10 @@ bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
bool cPluginLua::OnPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FOOD_LEVEL_CHANGE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -777,6 +955,10 @@ bool cPluginLua::OnPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FISHED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -797,6 +979,10 @@ bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
bool cPluginLua::OnPlayerFishing(cPlayer & a_Player, cItems & a_Reward)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FISHING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -817,6 +1003,10 @@ bool cPluginLua::OnPlayerFishing(cPlayer & a_Player, cItems & a_Reward)
bool cPluginLua::OnPlayerJoined(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_JOINED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -837,6 +1027,10 @@ bool cPluginLua::OnPlayerJoined(cPlayer & a_Player)
bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_LEFT_CLICK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -857,6 +1051,10 @@ bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_Block
bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_MOVING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -877,6 +1075,10 @@ bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPositi
bool cPluginLua::OnEntityTeleport(cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_TELEPORT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -897,6 +1099,10 @@ bool cPluginLua::OnEntityTeleport(cEntity & a_Entity, const Vector3d & a_OldPosi
bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACED_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -922,6 +1128,10 @@ bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_Blo
bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACING_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -947,6 +1157,10 @@ bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_Bl
bool cPluginLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_RIGHT_CLICK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -967,6 +1181,10 @@ bool cPluginLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_Bloc
bool cPluginLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -987,6 +1205,10 @@ bool cPluginLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Ent
bool cPluginLua::OnPlayerShooting(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_SHOOTING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1007,6 +1229,10 @@ bool cPluginLua::OnPlayerShooting(cPlayer & a_Player)
bool cPluginLua::OnPlayerSpawned(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_SPAWNED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1027,6 +1253,10 @@ bool cPluginLua::OnPlayerSpawned(cPlayer & a_Player)
bool cPluginLua::OnPlayerTossingItem(cPlayer & a_Player)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_TOSSING_ITEM];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1047,6 +1277,10 @@ bool cPluginLua::OnPlayerTossingItem(cPlayer & a_Player)
bool cPluginLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USED_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1067,6 +1301,10 @@ bool cPluginLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_Block
bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USED_ITEM];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1087,6 +1325,10 @@ bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY
bool cPluginLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USING_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1107,6 +1349,10 @@ bool cPluginLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_Bloc
bool cPluginLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_USING_ITEM];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1127,6 +1373,10 @@ bool cPluginLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_Block
bool cPluginLua::OnPluginMessage(cClientHandle & a_Client, const AString & a_Channel, const AString & a_Message)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLUGIN_MESSAGE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1147,6 +1397,10 @@ bool cPluginLua::OnPluginMessage(cClientHandle & a_Client, const AString & a_Cha
bool cPluginLua::OnPluginsLoaded(void)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLUGINS_LOADED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1165,6 +1419,10 @@ bool cPluginLua::OnPluginsLoaded(void)
bool cPluginLua::OnPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_POST_CRAFTING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1185,6 +1443,10 @@ bool cPluginLua::OnPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCra
bool cPluginLua::OnPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PRE_CRAFTING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1205,6 +1467,10 @@ bool cPluginLua::OnPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraf
bool cPluginLua::OnProjectileHitBlock(cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PROJECTILE_HIT_BLOCK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1225,6 +1491,10 @@ bool cPluginLua::OnProjectileHitBlock(cProjectileEntity & a_Projectile, int a_Bl
bool cPluginLua::OnProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity & a_HitEntity)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PROJECTILE_HIT_ENTITY];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1245,6 +1515,10 @@ bool cPluginLua::OnProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity
bool cPluginLua::OnServerPing(cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SERVER_PING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1265,6 +1539,10 @@ bool cPluginLua::OnServerPing(cClientHandle & a_ClientHandle, AString & a_Server
bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNED_ENTITY];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1285,6 +1563,10 @@ bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
bool cPluginLua::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNED_MONSTER];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1305,6 +1587,10 @@ bool cPluginLua::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster)
bool cPluginLua::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNING_ENTITY];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1325,6 +1611,10 @@ bool cPluginLua::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity)
bool cPluginLua::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SPAWNING_MONSTER];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1345,6 +1635,10 @@ bool cPluginLua::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster)
bool cPluginLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_TAKE_DAMAGE];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1370,6 +1664,10 @@ bool cPluginLua::OnUpdatedSign(
)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATED_SIGN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1395,6 +1693,10 @@ bool cPluginLua::OnUpdatingSign(
)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_UPDATING_SIGN];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1415,6 +1717,10 @@ bool cPluginLua::OnUpdatingSign(
bool cPluginLua::OnWeatherChanged(cWorld & a_World)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1435,6 +1741,10 @@ bool cPluginLua::OnWeatherChanged(cWorld & a_World)
bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
@@ -1455,6 +1765,10 @@ bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
bool cPluginLua::OnWorldStarted(cWorld & a_World)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WORLD_STARTED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
@@ -1470,6 +1784,10 @@ bool cPluginLua::OnWorldStarted(cWorld & a_World)
bool cPluginLua::OnWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
{
cCSLock Lock(m_CriticalSection);
+ if (!m_LuaState.IsValid())
+ {
+ return false;
+ }
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WORLD_TICK];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
@@ -1614,6 +1932,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";
@@ -1736,40 +2056,29 @@ void cPluginLua::AddResettable(cPluginLua::cResettablePtr a_Resettable)
-AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request)
+AString cPluginLua::HandleWebRequest(const HTTPRequest & a_Request)
{
- cCSLock Lock(m_CriticalSection);
- std::string RetVal = "";
-
- std::pair< std::string, std::string > TabName = GetTabNameForRequest(a_Request);
- std::string SafeTabName = TabName.second;
- if (SafeTabName.empty())
+ // Find the tab to use for the request:
+ auto TabName = GetTabNameForRequest(a_Request);
+ AString SafeTabTitle = TabName.second;
+ if (SafeTabTitle.empty())
{
return "";
}
-
- sWebPluginTab * Tab = 0;
- for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
+ auto Tab = GetTabBySafeTitle(SafeTabTitle);
+ if (Tab == nullptr)
{
- if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr
- {
- Tab = *itr;
- break;
- }
+ return "";
}
- if (Tab != nullptr)
+ // Get the page content from the plugin:
+ cCSLock Lock(m_CriticalSection);
+ AString Contents = Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->m_Title.c_str());
+ if (!m_LuaState.Call(Tab->m_UserData, &a_Request, cLuaState::Return, Contents))
{
- AString Contents = Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str());
- if (!m_LuaState.Call(Tab->UserData, a_Request, cLuaState::Return, Contents))
- {
- return "Lua encountered error while processing the page request";
- }
-
- RetVal += Contents;
+ return "Lua encountered error while processing the page request";
}
-
- return RetVal;
+ return Contents;
}
@@ -1784,13 +2093,7 @@ bool cPluginLua::AddWebTab(const AString & a_Title, lua_State * a_LuaState, int
LOGERROR("Only allowed to add a tab to a WebPlugin of your own Plugin!");
return false;
}
- sWebPluginTab * Tab = new sWebPluginTab();
- Tab->Title = a_Title;
- Tab->SafeTitle = SafeString(a_Title);
-
- Tab->UserData = a_FunctionReference;
-
- GetTabs().push_back(Tab);
+ AddNewWebTab(a_Title, a_FunctionReference);
return true;
}
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index c14b02687..a763cdfdf 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -20,7 +20,7 @@
-// fwd: UI/Window.h
+// fwd: "UI/Window.h"
class cWindow;
@@ -32,6 +32,8 @@ class cPluginLua :
public cPlugin,
public cWebPlugin
{
+ typedef cPlugin super;
+
public:
// tolua_end
@@ -96,7 +98,8 @@ public:
~cPluginLua();
virtual void OnDisable(void) override;
- virtual bool Initialize(void) override;
+ virtual bool Load(void) override;
+ virtual void Unload(void) override;
virtual void Tick(float a_Dt) override;
@@ -112,7 +115,9 @@ 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 OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) 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;
@@ -173,12 +178,13 @@ public:
/** Returns true if the plugin contains the function for the specified hook type, using the old-style registration (#121) */
bool CanAddOldStyleHook(int a_HookType);
- // cWebPlugin override
- virtual const AString GetWebTitle(void) const {return GetName(); }
+ // cWebPlugin overrides
+ virtual const AString GetWebTitle(void) const override {return GetName(); }
+ virtual AString HandleWebRequest(const HTTPRequest & a_Request) override;
- // cWebPlugin and WebAdmin stuff
- virtual AString HandleWebRequest(const HTTPRequest * a_Request) override;
- bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS <<
+ /** Adds a new web tab to webadmin.
+ Displaying the tab calls the referenced function. */
+ bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // Exported in ManualBindings.cpp
/** Binds the command to call the function specified by a Lua function reference. Simply adds to CommandMap. */
void BindCommand(const AString & a_Command, int a_FnRef);
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 8935f7dd3..5b6bec728 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -59,39 +59,48 @@ void cPluginManager::ReloadPlugins(void)
-void cPluginManager::FindPlugins(void)
+void cPluginManager::RefreshPluginList(void)
{
+ // Get a list of currently available folders:
AString PluginsPath = GetPluginsPath() + "/";
-
- // First get a clean list of only the currently running plugins, we don't want to mess those up
- for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
+ AStringVector Contents = cFile::GetFolderContents(PluginsPath.c_str());
+ AStringVector Folders;
+ for (auto & item: Contents)
{
- if (itr->second == nullptr)
+ if ((item == ".") || (item == "..") || (!cFile::IsFolder(PluginsPath + item)))
{
- PluginMap::iterator thiz = itr;
- ++thiz;
- m_Plugins.erase( itr);
- itr = thiz;
+ // We only want folders, and don't want "." or ".."
continue;
}
- ++itr;
- }
+ Folders.push_back(item);
+ } // for item - Contents[]
- AStringVector Files = cFile::GetFolderContents(PluginsPath.c_str());
- for (AStringVector::const_iterator itr = Files.begin(); itr != Files.end(); ++itr)
+ // Set all plugins with invalid folders as psNotFound:
+ for (auto & plugin: m_Plugins)
{
- if ((*itr == ".") || (*itr == "..") || (!cFile::IsFolder(PluginsPath + *itr)))
+ if (std::find(Folders.cbegin(), Folders.cend(), plugin->GetFolderName()) == Folders.end())
{
- // We only want folders, and don't want "." or ".."
- continue;
+ plugin->m_Status = psNotFound;
}
+ } // for plugin - m_Plugins[]
- // Add plugin name/directory to the list
- if (m_Plugins.find(*itr) == m_Plugins.end())
+ // Add all newly discovered plugins:
+ for (auto & folder: Folders)
+ {
+ bool hasFound = false;
+ for (auto & plugin: m_Plugins)
{
- m_Plugins[*itr] = nullptr;
+ if (plugin->GetFolderName() == folder)
+ {
+ hasFound = true;
+ break;
+ }
+ } // for plugin - m_Plugins[]
+ if (!hasFound)
+ {
+ m_Plugins.push_back(std::make_shared<cPluginLua>(folder));
}
- }
+ } // for folder - Folders[]
}
@@ -109,60 +118,26 @@ void cPluginManager::ReloadPluginsNow(void)
-void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
+void cPluginManager::ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings)
{
LOG("-- Loading Plugins --");
+
+ // Unload any existing plugins:
m_bReloadPlugins = false;
UnloadPluginsNow();
- FindPlugins();
-
- cServer::BindBuiltInConsoleCommands();
-
- // Check if the Plugins section exists.
- int KeyNum = a_SettingsIni.FindKey("Plugins");
-
- if (KeyNum == -1)
- {
- InsertDefaultPlugins(a_SettingsIni);
- KeyNum = a_SettingsIni.FindKey("Plugins");
- }
-
- // How many plugins are there?
- int NumPlugins = a_SettingsIni.GetNumValues(KeyNum);
-
- for (int i = 0; i < NumPlugins; i++)
- {
- AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
- if (ValueName.compare("Plugin") == 0)
- {
- AString PluginFile = a_SettingsIni.GetValue(KeyNum, i);
- if (!PluginFile.empty())
- {
- if (m_Plugins.find(PluginFile) != m_Plugins.end())
- {
- LoadPlugin(PluginFile);
- }
- }
- }
- }
-
+ // Refresh the list of plugins to load new ones from disk / remove the deleted ones:
+ RefreshPluginList();
- // Remove invalid plugins from the PluginMap.
- for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
+ // Load the plugins:
+ AStringVector ToLoad = GetFoldersToLoad(a_Settings);
+ for (auto & pluginFolder: ToLoad)
{
- if (itr->second == nullptr)
- {
- PluginMap::iterator thiz = itr;
- ++thiz;
- m_Plugins.erase(itr);
- itr = thiz;
- continue;
- }
- ++itr;
- }
+ LoadPlugin(pluginFolder);
+ } // for pluginFolder - ToLoad[]
- size_t NumLoadedPlugins = GetNumPlugins();
+ // Log a report of the loading process
+ size_t NumLoadedPlugins = GetNumLoadedPlugins();
if (NumLoadedPlugins == 0)
{
LOG("-- No Plugins Loaded --");
@@ -173,7 +148,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
}
else
{
- LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
+ LOG("-- Loaded %u Plugins --", static_cast<unsigned>(NumLoadedPlugins));
}
CallHookPluginsLoaded();
}
@@ -182,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");
}
@@ -200,12 +175,39 @@ void cPluginManager::InsertDefaultPlugins(cIniFile & a_SettingsIni)
void cPluginManager::Tick(float a_Dt)
{
- while (!m_DisablePluginList.empty())
+ // Unload plugins that have been scheduled for unloading:
+ AStringVector PluginsToUnload;
{
- RemovePlugin(m_DisablePluginList.front());
- m_DisablePluginList.pop_front();
+ cCSLock Lock(m_CSPluginsToUnload);
+ std::swap(m_PluginsToUnload, PluginsToUnload);
}
+ for (auto & folder: PluginsToUnload)
+ {
+ bool HasUnloaded = false;
+ bool HasFound = false;
+ for (auto & plugin: m_Plugins)
+ {
+ if (plugin->GetFolderName() == folder)
+ {
+ HasFound = true;
+ if (plugin->IsLoaded())
+ {
+ plugin->Unload();
+ HasUnloaded = true;
+ }
+ }
+ }
+ if (!HasFound)
+ {
+ LOG("Cannot unload plugin in folder \"%s\", there's no such plugin folder", folder.c_str());
+ }
+ else if (!HasUnloaded)
+ {
+ LOG("Cannot unload plugin in folder \"%s\", it has not been loaded.", folder.c_str());
+ }
+ } // for plugin - m_Plugins[]
+ // If a plugin reload has been scheduled, reload now:
if (m_bReloadPlugins)
{
ReloadPluginsNow();
@@ -523,14 +525,50 @@ bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d &
-bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
+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);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnExecuteCommand(a_Player, a_Split))
+ if ((*itr)->OnExecuteCommand(a_Player, a_Split, a_EntireCommand, a_Result))
{
return true;
}
@@ -1443,14 +1481,25 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player,
if (cmd == m_Commands.end())
{
// Command not found
+ // If it started with a slash, ask the plugins if they still want to handle it:
+ if (!a_Command.empty() && (a_Command[0] == '/'))
+ {
+ CommandResult Result = crUnknownCommand;
+ CallHookExecuteCommand(&a_Player, Split, a_Command, Result);
+ return Result;
+ }
return crUnknownCommand;
}
// Ask plugins first if a command is okay to execute the command:
- if (CallHookExecuteCommand(&a_Player, Split))
+ CommandResult Result = crBlocked;
+ if (CallHookExecuteCommand(&a_Player, Split, a_Command, Result))
{
- LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str());
- return crBlocked;
+ if (Result == crBlocked)
+ {
+ LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str());
+ }
+ return Result;
}
if (
@@ -1477,68 +1526,56 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player,
-cPlugin * cPluginManager::GetPlugin(const AString & a_Plugin) const
+void cPluginManager::UnloadPluginsNow()
{
- for (PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
- {
- if (itr->second == nullptr)
- {
- // The plugin is currently unloaded
- continue;
- }
+ // Remove all bindings:
+ m_Hooks.clear();
+ m_Commands.clear();
+ m_ConsoleCommands.clear();
- if (itr->second->GetName().compare(a_Plugin) == 0)
+ // Re-bind built-in console commands:
+ cServer::BindBuiltInConsoleCommands();
+
+ // Unload all loaded plugins:
+ for (auto & plugin: m_Plugins)
+ {
+ if (plugin->IsLoaded())
{
- return itr->second;
+ plugin->Unload();
}
}
- return 0;
}
-const cPluginManager::PluginMap & cPluginManager::GetAllPlugins() const
+void cPluginManager::UnloadPlugin(const AString & a_PluginFolder)
{
- return m_Plugins;
+ cCSLock Lock(m_CSPluginsToUnload);
+ m_PluginsToUnload.push_back(a_PluginFolder);
}
-void cPluginManager::UnloadPluginsNow()
+bool cPluginManager::LoadPlugin(const AString & a_FolderName)
{
- m_Hooks.clear();
-
- while (!m_Plugins.empty())
+ for (auto & plugin: m_Plugins)
{
- RemovePlugin(m_Plugins.begin()->second);
- }
-
- m_Commands.clear();
- m_ConsoleCommands.clear();
-}
-
-
-
-
-
-bool cPluginManager::DisablePlugin(const AString & a_PluginName)
-{
- PluginMap::iterator itr = m_Plugins.find(a_PluginName);
- if (itr == m_Plugins.end())
- {
- return false;
- }
+ if (plugin->GetFolderName() == a_FolderName)
+ {
+ if (!plugin->IsLoaded())
+ {
+ return plugin->Load();
+ }
+ return true;
+ }
+ } // for plugin - m_Plugins[]
- if (itr->first.compare(a_PluginName) == 0) // _X 2013_02_01: wtf? Isn't this supposed to be what find() does?
- {
- m_DisablePluginList.push_back(itr->second);
- itr->second = nullptr; // Get rid of this thing right away
- return true;
- }
+ // Plugin not found
+ LOG("Cannot load plugin, folder \"%s\" not found.", a_FolderName.c_str());
return false;
}
@@ -1546,15 +1583,6 @@ bool cPluginManager::DisablePlugin(const AString & a_PluginName)
-bool cPluginManager::LoadPlugin(const AString & a_PluginName)
-{
- return AddPlugin(new cPluginLua(a_PluginName.c_str()));
-}
-
-
-
-
-
void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
{
for (HookMap::iterator itr = m_Hooks.begin(), end = m_Hooks.end(); itr != end; ++itr)
@@ -1567,32 +1595,6 @@ void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
-void cPluginManager::RemovePlugin(cPlugin * a_Plugin)
-{
- for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
- {
- if (itr->second == a_Plugin)
- {
- m_Plugins.erase(itr);
- break;
- }
- }
-
- RemovePluginCommands(a_Plugin);
- RemovePluginConsoleCommands(a_Plugin);
- RemoveHooks(a_Plugin);
- if (a_Plugin != nullptr)
- {
- a_Plugin->OnDisable();
- }
- delete a_Plugin;
- a_Plugin = nullptr;
-}
-
-
-
-
-
void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
{
if (a_Plugin != nullptr)
@@ -1619,6 +1621,22 @@ void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin)
+bool cPluginManager::IsPluginLoaded(const AString & a_PluginName)
+{
+ for (auto & plugin: m_Plugins)
+ {
+ if (plugin->GetName() == a_PluginName)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginManager::BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString)
{
CommandMap::iterator cmd = m_Commands.find(a_Command);
@@ -1779,7 +1797,10 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cComma
if (cmd == m_ConsoleCommands.end())
{
// Command not found
- return false;
+ // Still notify the plugins (so that plugins such as Aliases can intercept unknown commands).
+ CommandResult res = crBlocked;
+ CallHookExecuteCommand(nullptr, a_Split, a_Command, res);
+ return (res == crExecuted);
}
if (cmd->second.m_Plugin == nullptr)
@@ -1789,10 +1810,10 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cComma
}
// Ask plugins first if a command is okay to execute the console command:
- if (CallHookExecuteCommand(nullptr, a_Split))
+ CommandResult res = crBlocked;
+ if (CallHookExecuteCommand(nullptr, a_Split, a_Command, res))
{
- a_Output.Out("Command \"%s\" was stopped by the HOOK_EXECUTE_COMMAND hook", a_Split[0].c_str());
- return false;
+ return (res == crExecuted);
}
return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output, a_Command);
@@ -1836,31 +1857,31 @@ bool cPluginManager::IsValidHookType(int a_HookType)
bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback)
{
// TODO: Implement locking for plugins
- PluginMap::iterator itr = m_Plugins.find(a_PluginName);
- if ((itr == m_Plugins.end()) || (itr->second == nullptr))
+ for (auto & plugin: m_Plugins)
{
- return false;
+ if (plugin->GetName() == a_PluginName)
+ {
+ return a_Callback.Item(plugin.get());
+ }
}
- return a_Callback.Item(itr->second);
+ return false;
}
-bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
+bool cPluginManager::ForEachPlugin(cPluginCallback & a_Callback)
{
- m_Plugins[a_Plugin->GetDirectory()] = a_Plugin;
-
- if (a_Plugin->Initialize())
+ // TODO: Implement locking for plugins
+ for (auto & plugin: m_Plugins)
{
- // Initialization OK
- return true;
+ if (a_Callback.Item(plugin.get()))
+ {
+ return false;
+ }
}
-
- // Initialization failed
- RemovePlugin(a_Plugin); // Also undoes any registrations that Initialize() might have made
- return false;
+ return true;
}
@@ -1869,21 +1890,23 @@ bool cPluginManager::AddPlugin(cPlugin * a_Plugin)
void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
{
- if (!a_Plugin)
+ if (a_Plugin == nullptr)
{
LOGWARN("Called cPluginManager::AddHook() with a_Plugin == nullptr");
return;
}
PluginList & Plugins = m_Hooks[a_Hook];
- Plugins.remove(a_Plugin);
- Plugins.push_back(a_Plugin);
+ if (std::find(Plugins.cbegin(), Plugins.cend(), a_Plugin) == Plugins.cend())
+ {
+ Plugins.push_back(a_Plugin);
+ }
}
-size_t cPluginManager::GetNumPlugins() const
+size_t cPluginManager::GetNumPlugins(void) const
{
return m_Plugins.size();
}
@@ -1891,3 +1914,51 @@ size_t cPluginManager::GetNumPlugins() const
+
+size_t cPluginManager::GetNumLoadedPlugins(void) const
+{
+ size_t res = 0;
+ for (auto & plugin: m_Plugins)
+ {
+ if (plugin->IsLoaded())
+ {
+ res += 1;
+ }
+ }
+ return res;
+}
+
+
+
+
+
+AStringVector cPluginManager::GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings)
+{
+ // Check if the Plugins section exists.
+ if (!a_Settings.KeyExists("Plugins"))
+ {
+ InsertDefaultPlugins(a_Settings);
+ }
+
+ // Get the list of plugins to load:
+ AStringVector res;
+ auto Values = a_Settings.GetValues("Plugins");
+ for (auto NameValue : Values)
+ {
+ AString ValueName = NameValue.first;
+ if (ValueName.compare("Plugin") == 0)
+ {
+ AString PluginFile = NameValue.second;
+ if (!PluginFile.empty())
+ {
+ res.push_back(PluginFile);
+ }
+ }
+ } // for i - ini values
+
+ return res;
+}
+
+
+
+
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index 4efcbb6f3..6bcef87bf 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -6,48 +6,31 @@
-class cPlugin;
-// fwd: World.h
-class cWorld;
-// fwd: ChunkDesc.h
+// fwd:
+class cBlockEntityWithItems;
class cChunkDesc;
-
-// fwd: Entities/Entity.h
-class cEntity;
-
-// fwd: Entities/ProjectileEntity.h
-class cProjectileEntity;
-
-// fwd: Mobs/Monster.h
-class cMonster;
-
-// fwd: Player.h
-class cPlayer;
-
-// fwd: CraftingRecipes.h
+class cClientHandle;
+class cCommandOutputCallback;
class cCraftingGrid;
class cCraftingRecipe;
-
-// fwd: Pickup.h
+class cEntity;
+class cHopperEntity;
+class cItems;
+class cMonster;
class cPickup;
-
-// fwd: Pawn.h
+class cPlayer;
+class cPlugin;
+class cProjectileEntity;
+class cWorld;
+class cSettingsRepositoryInterface;
struct TakeDamageInfo;
-// fwd: CommandOutput.h
-class cCommandOutputCallback;
-
-// fwd: BlockEntities/HopperEntity.h
-class cHopperEntity;
-
-// fwd: BlockEntities/BlockEntityWithItems.h
-class cBlockEntityWithItems;
-
+typedef SharedPtr<cPlugin> cPluginPtr;
+typedef std::vector<cPluginPtr> cPluginPtrs;
-class cItems;
@@ -55,12 +38,7 @@ class cItems;
class cPluginManager
{
public:
- // tolua_end
-
- // Called each tick
- virtual void Tick(float a_Dt);
-
- // tolua_begin
+
enum CommandResult
{
crExecuted,
@@ -70,6 +48,29 @@ public:
crNoPermission,
} ;
+
+ /** Defines the status of a single plugin - whether it is loaded, disabled or errored. */
+ enum ePluginStatus
+ {
+ /** The plugin has been loaded successfully. */
+ psLoaded,
+
+ /** The plugin is disabled in settings.ini. */
+ psDisabled,
+
+ /** The plugin is enabled in settings.ini but has been unloaded (by a command). */
+ psUnloaded,
+
+ /** The plugin is enabled in settings.ini but has failed to load.
+ m_LoadError is the description of the error. */
+ psError,
+
+ /** The plugin has been loaded before, but after a folder refresh it is no longer present.
+ The plugin will be unloaded in the next call to ReloadPlugins(). */
+ psNotFound,
+ };
+
+
enum PluginHook
{
HOOK_BLOCK_SPREAD,
@@ -85,6 +86,8 @@ 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,
@@ -134,6 +137,8 @@ public:
HOOK_WEATHER_CHANGING,
HOOK_WORLD_STARTED,
HOOK_WORLD_TICK,
+
+ // tolua_end
// Note that if a hook type is added, it may need processing in cPlugin::CanAddHook() descendants,
// and it definitely needs adding in cPluginLua::GetHookFnName() !
@@ -141,8 +146,7 @@ public:
// Keep these two as the last items, they are used for validity checking and get their values automagically
HOOK_NUM_HOOKS,
HOOK_MAX = HOOK_NUM_HOOKS - 1,
- } ;
- // tolua_end
+ } ; // tolua_export
/** Used as a callback for enumerating bound commands */
class cCommandEnumCallback
@@ -159,24 +163,31 @@ public:
/** The interface used for enumerating and extern-calling plugins */
typedef cItemCallback<cPlugin> cPluginCallback;
+ typedef std::list<cPlugin *> PluginList;
+
+
+ /** Called each tick, calls the plugins' OnTick hook, as well as processes plugin events (addition, removal) */
+ void Tick(float a_Dt);
/** Returns the instance of the Plugin Manager (there is only ever one) */
static cPluginManager * Get(void); // tolua_export
- typedef std::map< AString, cPlugin * > PluginMap;
- typedef std::list< cPlugin * > PluginList;
- cPlugin * GetPlugin( const AString & a_Plugin) const; // tolua_export
- const PluginMap & GetAllPlugins() const; // >> EXPORTED IN MANUALBINDINGS <<
+ /** Refreshes the m_Plugins list based on the current contents of the Plugins folder.
+ If an active plugin's folder is not found anymore, the plugin is set as psNotFound, but not yet unloaded. */
+ void RefreshPluginList(); // tolua_export
- // tolua_begin
- void FindPlugins();
- void ReloadPlugins();
- // tolua_end
+ /** Schedules a reload of the plugins to happen within the next call to Tick(). */
+ void ReloadPlugins(); // tolua_export
- /** Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add */
+ /** Adds the plugin to the list of plugins called for the specified hook type.
+ If a plugin adds multiple handlers for a single hook, it is added only once (ignore-duplicates). */
void AddHook(cPlugin * a_Plugin, int a_HookType);
+ /** Returns the number of all plugins in m_Plugins (includes disabled, unloaded and errored plugins). */
size_t GetNumPlugins() const; // tolua_export
+
+ /** Returns the number of plugins that are psLoaded. */
+ size_t GetNumLoadedPlugins(void) const; // tolua_export
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
bool CallHookBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
@@ -192,7 +203,9 @@ 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 CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == nullptr, it is a console cmd
+ 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);
@@ -241,18 +254,26 @@ public:
bool CallHookWorldStarted (cWorld & a_World);
bool CallHookWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
- bool DisablePlugin(const AString & a_PluginName); // tolua_export
- bool LoadPlugin (const AString & a_PluginName); // tolua_export
+ /** Queues the specified plugin to be unloaded in the next call to Tick().
+ Note that this function returns before the plugin is unloaded, to avoid deadlocks. */
+ void UnloadPlugin(const AString & a_PluginFolder); // tolua_export
+
+ /** Loads the plugin from the specified plugin folder.
+ Returns true if the plugin was loaded successfully or was already loaded before, false otherwise. */
+ bool LoadPlugin(const AString & a_PluginFolder); // tolua_export
/** Removes all hooks the specified plugin has registered */
void RemoveHooks(cPlugin * a_Plugin);
- /** Removes the plugin from the internal structures and deletes its object. */
- void RemovePlugin(cPlugin * a_Plugin);
+ /** Removes the plugin of the specified name from the internal structures and deletes its object. */
+ void RemovePlugin(const AString & a_PluginName);
/** Removes all command bindings that the specified plugin has made */
void RemovePluginCommands(cPlugin * a_Plugin);
-
+
+ /** Returns true if the specified plugin is loaded. */
+ bool IsPluginLoaded(const AString & a_PluginName); // tolua_export
+
/** Binds a command to the specified plugin. Returns true if successful, false if command already bound. */
bool BindCommand(const AString & a_Command, cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString); // Exported in ManualBindings.cpp, without the a_Plugin param
@@ -283,7 +304,9 @@ public:
/** Returns true if the console command is in the command map */
bool IsConsoleCommandBound(const AString & a_Command); // tolua_export
- /** Executes the command split into a_Split, as if it was given on the console. Returns true if executed. Output is sent to the a_Output callback */
+ /** Executes the command split into a_Split, as if it was given on the console.
+ Returns true if executed. Output is sent to the a_Output callback
+ Exported in ManualBindings.cpp with a different signature. */
bool ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command);
/** Appends all commands beginning with a_Text (case-insensitive) into a_Results.
@@ -295,8 +318,12 @@ public:
static bool IsValidHookType(int a_HookType);
/** Calls the specified callback with the plugin object of the specified plugin.
- Returns false if plugin not found, and the value that the callback has returned otherwise. */
+ Returns false if plugin not found, otherwise returns the value that the callback has returned. */
bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback);
+
+ /** Calls the specified callback for each plugin in m_Plugins.
+ Returns true if all plugins have been reported, false if the callback has aborted the enumeration by returning true. */
+ bool ForEachPlugin(cPluginCallback & a_Callback);
/** Returns the path where individual plugins' folders are expected.
The path doesn't end in a slash. */
@@ -316,34 +343,46 @@ private:
typedef std::map<int, cPluginManager::PluginList> HookMap;
typedef std::map<AString, cCommandReg> CommandMap;
- PluginList m_DisablePluginList;
- PluginMap m_Plugins;
+
+ /** FolderNames of plugins that should be unloaded.
+ The plugins will be unloaded within the next call to Tick(), to avoid multithreading issues.
+ Protected against multithreaded access by m_CSPluginsToUnload. */
+ AStringVector m_PluginsToUnload;
+
+ /** Protects m_PluginsToUnload against multithreaded access. */
+ mutable cCriticalSection m_CSPluginsToUnload;
+
+ /** All plugins that have been found in the Plugins folder. */
+ cPluginPtrs m_Plugins;
+
HookMap m_Hooks;
CommandMap m_Commands;
CommandMap m_ConsoleCommands;
+ /** If set to true, all the plugins will be reloaded within the next call to Tick(). */
bool m_bReloadPlugins;
+
cPluginManager();
virtual ~cPluginManager();
/** 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);
-
- /** Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again. */
- bool AddPlugin(cPlugin * a_Plugin);
+ /** 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(cSettingsRepositoryInterface & a_Settings);
} ; // tolua_export
diff --git a/src/Bindings/WebPlugin.cpp b/src/Bindings/WebPlugin.cpp
index 5759b20e7..1eca7de93 100644
--- a/src/Bindings/WebPlugin.cpp
+++ b/src/Bindings/WebPlugin.cpp
@@ -24,75 +24,82 @@ cWebPlugin::cWebPlugin()
cWebPlugin::~cWebPlugin()
{
+ ASSERT(m_Tabs.empty()); // Has ClearTabs() been called?
+
+ // Remove from WebAdmin:
cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin();
if (WebAdmin != nullptr)
{
WebAdmin->RemovePlugin(this);
}
+}
+
+
+
- for (TabList::iterator itr = m_Tabs.begin(); itr != m_Tabs.end(); ++itr)
+
+cWebPlugin::cTabNames cWebPlugin::GetTabNames(void) const
+{
+ std::list< std::pair<AString, AString>> NameList;
+ for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
{
- delete *itr;
+ NameList.push_back(std::make_pair((*itr)->m_Title, (*itr)->m_SafeTitle));
}
- m_Tabs.clear();
+ return NameList;
}
-std::list<std::pair<AString, AString> > cWebPlugin::GetTabNames(void)
+cWebPlugin::cTabPtr cWebPlugin::GetTabBySafeTitle(const AString & a_SafeTitle) const
{
- std::list< std::pair< AString, AString > > NameList;
- for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
+ cCSLock Lock(m_CSTabs);
+ for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
{
- std::pair< AString, AString > StringPair;
- StringPair.first = (*itr)->Title;
- StringPair.second = (*itr)->SafeTitle;
- NameList.push_back( StringPair);
+ if ((*itr)->m_SafeTitle == a_SafeTitle)
+ {
+ return *itr;
+ }
}
- return NameList;
+ return nullptr;
}
-std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest * a_Request)
+std::pair<AString, AString> cWebPlugin::GetTabNameForRequest(const HTTPRequest & a_Request)
{
- std::pair< AString, AString > Names;
- AStringVector Split = StringSplit(a_Request->Path, "/");
+ AStringVector Split = StringSplit(a_Request.Path, "/");
+ if (Split.empty())
+ {
+ return std::make_pair(AString(), AString());
+ }
- if (Split.size() > 1)
+ cCSLock Lock(m_CSTabs);
+ cTabPtr Tab;
+ if (Split.size() > 2) // If we got the tab name, show that page
{
- sWebPluginTab * Tab = nullptr;
- if (Split.size() > 2) // If we got the tab name, show that page
+ for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr)
{
- for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
+ if ((*itr)->m_SafeTitle.compare(Split[2]) == 0) // This is the one!
{
- if ((*itr)->SafeTitle.compare(Split[2]) == 0) // This is the one!
- {
- Tab = *itr;
- break;
- }
- }
- }
- else // Otherwise show the first tab
- {
- if (GetTabs().size() > 0)
- {
- Tab = *GetTabs().begin();
+ return std::make_pair((*itr)->m_Title, (*itr)->m_SafeTitle);
}
}
+ // Tab name not found, display an "empty" page:
+ return std::make_pair(AString(), AString());
+ }
- if (Tab != nullptr)
- {
- Names.first = Tab->Title;
- Names.second = Tab->SafeTitle;
- }
+ // Show the first tab:
+ if (!m_Tabs.empty())
+ {
+ return std::make_pair(m_Tabs.front()->m_SafeTitle, m_Tabs.front()->m_SafeTitle);
}
- return Names;
+ // No tabs at all:
+ return std::make_pair(AString(), AString());
}
@@ -101,14 +108,16 @@ std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest
AString cWebPlugin::SafeString(const AString & a_String)
{
AString RetVal;
- for (unsigned int i = 0; i < a_String.size(); ++i)
+ auto len = a_String.size();
+ RetVal.reserve(len);
+ for (size_t i = 0; i < len; ++i)
{
char c = a_String[i];
if (c == ' ')
{
c = '_';
}
- RetVal.push_back( c);
+ RetVal.push_back(c);
}
return RetVal;
}
@@ -116,3 +125,28 @@ AString cWebPlugin::SafeString(const AString & a_String)
+
+void cWebPlugin::AddNewWebTab(const AString & a_Title, int a_UserData)
+{
+ auto Tab = std::make_shared<cTab>(a_Title, a_UserData);
+ cCSLock Lock(m_CSTabs);
+ m_Tabs.push_back(Tab);
+}
+
+
+
+
+
+void cWebPlugin::ClearTabs(void)
+{
+ // Remove the webadmin tabs:
+ cTabPtrs Tabs;
+ {
+ cCSLock Lock(m_CSTabs);
+ std::swap(Tabs, m_Tabs);
+ }
+}
+
+
+
+
diff --git a/src/Bindings/WebPlugin.h b/src/Bindings/WebPlugin.h
index 9b825b918..ade4f4359 100644
--- a/src/Bindings/WebPlugin.h
+++ b/src/Bindings/WebPlugin.h
@@ -12,34 +12,67 @@ class cWebPlugin
{
public:
// tolua_end
+
+ struct cTab
+ {
+ AString m_Title;
+ AString m_SafeTitle;
+ int m_UserData;
+
+ cTab(const AString & a_Title, int a_UserData):
+ m_Title(a_Title),
+ m_SafeTitle(cWebPlugin::SafeString(a_Title)),
+ m_UserData(a_UserData)
+ {
+ }
+ };
+
+ typedef SharedPtr<cTab> cTabPtr;
+ typedef std::list<cTabPtr> cTabPtrs;
+ typedef std::list<std::pair<AString, AString>> cTabNames;
+
+
cWebPlugin();
+
virtual ~cWebPlugin();
// tolua_begin
+
+ /** Returns the title of the plugin, as it should be presented in the webadmin's pages tree. */
virtual const AString GetWebTitle(void) const = 0;
- virtual AString HandleWebRequest(const HTTPRequest * a_Request) = 0;
+ /** Sanitizes the input string, replacing spaces with underscores. */
+ static AString SafeString(const AString & a_String);
- static AString SafeString( const AString & a_String);
// tolua_end
- struct sWebPluginTab
- {
- std::string Title;
- std::string SafeTitle;
+ virtual AString HandleWebRequest(const HTTPRequest & a_Request) = 0;
- int UserData;
- };
+ /** Adds a new web tab with the specified contents. */
+ void AddNewWebTab(const AString & a_Title, int a_UserData);
+
+ /** Removes all the tabs. */
+ void ClearTabs(void);
- typedef std::list< sWebPluginTab* > TabList;
- TabList & GetTabs() { return m_Tabs; }
+ /** Returns all the tabs that this plugin has registered. */
+ const cTabPtrs & GetTabs(void) const { return m_Tabs; }
- typedef std::list< std::pair<AString, AString> > TabNameList;
- TabNameList GetTabNames(); // >> EXPORTED IN MANUALBINDINGS <<
- std::pair< AString, AString > GetTabNameForRequest(const HTTPRequest* a_Request);
+ /** Returns all of the tabs that this plugin has registered. */
+ cTabNames GetTabNames(void) const; // Exported in ManualBindings.cpp
+
+ /** Returns the tab that has the specified SafeTitle.
+ Returns nullptr if no such tab. */
+ cTabPtr GetTabBySafeTitle(const AString & a_SafeTitle) const;
+
+ std::pair<AString, AString> GetTabNameForRequest(const HTTPRequest & a_Request);
private:
- TabList m_Tabs;
+ /** All tabs that this plugin has registered.
+ Protected against multithreaded access by m_CSTabs. */
+ cTabPtrs m_Tabs;
+
+ /** Protects m_Tabs against multithreaded access. */
+ mutable cCriticalSection m_CSTabs;
}; // tolua_export
diff --git a/src/Bindings/virtual_method_hooks.lua b/src/Bindings/virtual_method_hooks.lua
deleted file mode 100644
index a52728ff8..000000000
--- a/src/Bindings/virtual_method_hooks.lua
+++ /dev/null
@@ -1,518 +0,0 @@
--- flags
-local disable_virtual_hooks = true
-local enable_pure_virtual = true
-local default_private_access = false
-
-
-
-
-
-local access = {public = 0, protected = 1, private = 2}
-
-function preparse_hook(p)
-
- if default_private_access then
- -- we need to make all structs 'public' by default
- p.code = string.gsub(p.code, "(struct[^;]*{)", "%1\npublic:\n")
- end
-end
-
-
-function parser_hook(s)
-
- local container = classContainer.curr -- get the current container
-
- if default_private_access then
- if not container.curr_member_access and container.classtype == 'class' then
- -- default access for classes is private
- container.curr_member_access = access.private
- end
- end
-
- -- try labels (public, private, etc)
- do
- local b,e,label = string.find(s, "^%s*(%w*)%s*:[^:]") -- we need to check for [^:], otherwise it would match 'namespace::type'
- if b then
-
- -- found a label, get the new access value from the global 'access' table
- if access[label] then
- container.curr_member_access = access[label]
- end -- else ?
-
- return strsub(s, e) -- normally we would use 'e+1', but we need to preserve the [^:]
- end
- end
-
-
- local ret = nil
-
- if disable_virtual_hooks then
-
- return ret
- end
-
- local b,e,decl,arg = string.find(s, "^%s*virtual%s+([^%({~]+)(%b())")
- local const
- if b then
- local ret = string.sub(s, e+1)
- if string.find(ret, "^%s*const") then
- const = "const"
- ret = string.gsub(ret, "^%s*const", "")
- end
- local purev = false
- if string.find(ret, "^%s*=%s*0") then
- purev = true
- ret = string.gsub(ret, "^%s*=%s*0", "")
- end
- ret = string.gsub(ret, "^%s*%b{}", "")
-
- local func = Function(decl, arg, const)
- func.pure_virtual = purev
- --func.access = access
- func.original_sig = decl
-
- local curflags = classContainer.curr.flags
- if not curflags.virtual_class then
-
- curflags.virtual_class = VirtualClass()
- end
- curflags.virtual_class:add(func)
- curflags.pure_virtual = curflags.pure_virtual or purev
-
- return ret
- end
-
- return ret
-end
-
-
--- class VirtualClass
-classVirtualClass = {
- classtype = 'class',
- name = '',
- base = '',
- type = '',
- btype = '',
- ctype = '',
-}
-classVirtualClass.__index = classVirtualClass
-setmetatable(classVirtualClass,classClass)
-
-function classVirtualClass:add(f)
-
- local parent = classContainer.curr
- pop()
-
- table.insert(self.methods, {f=f})
-
- local name,sig
-
- -- doble negative means positive
- if f.name == 'new' and ((not self.flags.parent_object.flags.pure_virtual) or (enable_pure_virtual)) then
-
- name = self.original_name
- elseif f.name == 'delete' then
- name = '~'..self.original_name
- else
- if f.access ~= 2 and (not f.pure_virtual) and f.name ~= 'new' and f.name ~= 'delete' then
- name = f.mod.." "..f.type..f.ptr.." "..self.flags.parent_object.lname.."__"..f.name
- end
- end
-
- if name then
- sig = name..self:get_arg_list(f, true)..";\n"
- push(self)
- sig = preprocess(sig)
- self:parse(sig)
- pop()
- end
-
- push(parent)
-end
-
-function preprocess(sig)
-
- sig = gsub(sig,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
- sig = gsub(sig,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
- sig = gsub(sig,"([^%w_])char%s*%*","%1_cstring ") -- substitute 'char*'
- sig = gsub(sig,"([^%w_])lua_State%s*%*","%1_lstate ") -- substitute 'lua_State*'
-
- return sig
-end
-
-function classVirtualClass:get_arg_list(f, decl)
-
- local ret = ""
- local sep = ""
- local i=1
- while f.args[i] do
-
- local arg = f.args[i]
- if decl then
- local ptr
- if arg.ret ~= '' then
- ptr = arg.ret
- else
- ptr = arg.ptr
- end
- local def = ""
- if arg.def and arg.def ~= "" then
-
- def = " = "..arg.def
- end
- ret = ret..sep..arg.mod.." "..arg.type..ptr.." "..arg.name..def
- else
- ret = ret..sep..arg.name
- end
-
- sep = ","
- i = i+1
- end
-
- return "("..ret..")"
-end
-
-function classVirtualClass:add_parent_virtual_methods(parent)
-
- parent = parent or _global_classes[self.flags.parent_object.btype]
-
- if not parent then return end
-
- if parent.flags.virtual_class then
-
- local vclass = parent.flags.virtual_class
- for k,v in ipairs(vclass.methods) do
- if v.f.name ~= 'new' and v.f.name ~= 'delete' and (not self:has_method(v.f)) then
- table.insert(self.methods, {f=v.f})
- end
- end
- end
-
- parent = _global_classes[parent.btype]
- if parent then
- self:add_parent_virtual_methods(parent)
- end
-end
-
-function classVirtualClass:has_method(f)
-
- for k,v in pairs(self.methods) do
- -- just match name for now
- if v.f.name == f.name then
- return true
- end
- end
-
- return false
-end
-
-function classVirtualClass:add_constructors()
-
- local i=1
- while self.flags.parent_object[i] do
-
- local v = self.flags.parent_object[i]
- if getmetatable(v) == classFunction and (v.name == 'new' or v.name == 'delete') then
-
- self:add(v)
- end
-
- i = i+1
- end
-
-end
-
---[[
-function classVirtualClass:requirecollection(t)
-
- self:add_constructors()
- local req = classClass.requirecollection(self, t)
- if req then
- output('class ',self.name,";")
- end
- return req
-end
---]]
-
-function classVirtualClass:supcode()
-
- -- pure virtual classes can have no default constructors on gcc 4
-
- if self.flags.parent_object.flags.pure_virtual and not enable_pure_virtual then
- output('#if (__GNUC__ == 4) || (__GNUC__ > 4 ) // I hope this works on Microsoft Visual studio .net server 2003 XP Compiler\n')
- end
-
- local ns
- if self.prox.classtype == 'namespace' then
- output('namespace ',self.prox.name, " {")
- ns = true
- end
-
- output("class "..self.original_name.." : public "..self.btype..", public ToluaBase {")
-
- output("public:\n")
-
- self:add_parent_virtual_methods()
-
- self:output_methods(self.btype)
- self:output_parent_methods()
-
- self:add_constructors()
-
- -- no constructor for pure virtual classes
- if (not self.flags.parent_object.flags.pure_virtual) or enable_pure_virtual then
-
- self:output_constructors()
- end
-
- output("};\n\n")
-
- if ns then
- output("};")
- end
-
- classClass.supcode(self)
-
- if self.flags.parent_object.flags.pure_virtual and not enable_pure_virtual then
- output('#endif // __GNUC__ >= 4\n')
- end
-
- -- output collector for custom class if required
- if self:requirecollection(_collect) and _collect[self.type] then
-
- output('\n')
- output('/* function to release collected object via destructor */')
- output('#ifdef __cplusplus\n')
- --for i,v in pairs(collect) do
- i,v = self.type, _collect[self.type]
- output('\nstatic int '..v..' (lua_State* tolua_S)')
- output('{')
- output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
- output(' delete self;')
- output(' return 0;')
- output('}')
- --end
- output('#endif\n\n')
- end
-
-end
-
-function classVirtualClass:register(pre)
-
- -- pure virtual classes can have no default constructors on gcc 4
- if self.flags.parent_object.flags.pure_virtual and not enable_pure_virtual then
- output('#if (__GNUC__ == 4) || (__GNUC__ > 4 )\n')
- end
-
- classClass.register(self, pre)
-
- if self.flags.parent_object.flags.pure_virtual and not enable_pure_virtual then
- output('#endif // __GNUC__ >= 4\n')
- end
-end
-
-
---function classVirtualClass:requirecollection(_c)
--- if self.flags.parent_object.flags.pure_virtual then
--- return false
--- end
--- return classClass.requirecollection(self, _c)
---end
-
-function classVirtualClass:output_parent_methods()
-
- for k,v in ipairs(self.methods) do
-
- if v.f.access ~= 2 and (not v.f.pure_virtual) and v.f.name ~= 'new' and v.f.name ~= 'delete' then
-
- local rettype = v.f.mod.." "..v.f.type..v.f.ptr.." "
- local parent_name = rettype..self.btype.."__"..v.f.name
-
- local par_list = self:get_arg_list(v.f, true)
- local var_list = self:get_arg_list(v.f, false)
-
- -- the parent's virtual function
- output("\t"..parent_name..par_list.." {")
-
- output("\t\treturn (",rettype,")"..self.btype.."::"..v.f.name..var_list..";")
- output("\t};")
- end
- end
-end
-
-function classVirtualClass:output_methods(btype)
-
- for k,v in ipairs(self.methods) do
-
- if v.f.name ~= 'new' and v.f.name ~= 'delete' then
-
- self:output_method(v.f, btype)
- end
- end
- output("\n")
-end
-
-function classVirtualClass:output_constructors()
-
- for k,v in ipairs(self.methods) do
-
- if v.f.name == 'new' then
-
- local par_list = self:get_arg_list(v.f, true)
- local var_list = self:get_arg_list(v.f, false)
-
- output("\t",self.original_name,par_list,":",self.btype,var_list,"{};")
- end
- end
-end
-
-function classVirtualClass:output_method(f, btype)
-
- if f.access == 2 then -- private
- return
- end
-
- local ptr
- if f.ret ~= '' then
- ptr = f.ret
- else
- ptr = f.ptr
- end
-
- local rettype = f.mod.." "..f.type..f.ptr.." "
- local par_list = self:get_arg_list(f, true)
- local var_list = self:get_arg_list(f, false)
-
- if string.find(rettype, "%s*LuaQtGenericFlags%s*") then
-
- _,_,rettype = string.find(f.original_sig, "^%s*([^%s]+)%s+")
- end
-
- -- the caller of the lua method
- output("\t"..rettype.." "..f.name..par_list..f.const.." {")
- local fn = f.cname
- if f.access == 1 then
- fn = "NULL"
- end
- output('\t\tif (push_method("',f.lname,'", ',fn,')) {')
-
- --if f.type ~= 'void' then
- -- output("\t\t\tint top = lua_gettop(lua_state)-1;")
- --end
-
- -- push the parameters
- local argn = 0
- for i,arg in ipairs(f.args) do
- if arg.type ~= 'void' then
- local t,ct = isbasic(arg.type)
- if t and t ~= '' then
- if arg.ret == "*" then
- t = 'userdata'
- ct = 'void*'
- end
- output("\t\t\ttolua_push"..t.."(lua_state, ("..ct..")"..arg.name..");");
- else
- local m = arg.ptr
- if m and m~= "" then
- if m == "*" then m = "" end
- output("\t\t\ttolua_pushusertype(lua_state, (void*)"..m..arg.name..", \""..arg.type.."\");")
- else
- output("\t\t\tvoid* tolua_obj" .. argn .." = (void*)new "..arg.type.."("..arg.name..");\n")
- output('\t\t\ttolua_pushusertype_and_takeownership(lua_state, tolua_obj' .. argn .. ', "'..arg.type..'");\n')
- end
- end
- argn = argn+1
- end
- end
-
- -- call the function
- output("\t\t\tToluaBase::dbcall(lua_state, ",argn+1,", ")
-
- -- return value
- if f.type ~= 'void' then
- output("1);")
-
- local t,ct = isbasic(f.type)
- if t and t ~= '' then
- --output("\t\t\treturn ("..rettype..")tolua_to"..t.."(lua_state, top, 0);")
- output("\t\t\t",rettype,"tolua_ret = ("..rettype..")tolua_to"..t.."(lua_state, -1, 0);")
- else
-
- local mod = ""
- if f.ptr ~= "*" then
- mod = "*("..f.type.."*)"
- end
-
- --output("\t\t\treturn ("..rettype..")"..mod.."tolua_tousertype(lua_state, top, 0);")
- output("\t\t\t",rettype,"tolua_ret = ("..rettype..")"..mod.."tolua_tousertype(lua_state, -1, 0);")
- end
- output("\t\t\tlua_pop(lua_state, 1);")
- output("\t\t\treturn tolua_ret;")
- else
- output("0);")
- end
-
- -- handle non-implemeted function
- output("\t\t} else {")
-
- if f.pure_virtual then
-
- output('\t\t\tif (lua_state)')
- --output('\t\t\t\ttolua_error(lua_state, "pure-virtual method '..btype.."::"..f.name..' not implemented.", NULL);')
- output('\t\t\t\tLOG("pure-virtual method '..btype.."::"..f.name..' not implemented.");')
- output('\t\t\telse {')
- output('\t\t\t\tLOG("pure-virtual method '..btype.."::"..f.name..' called with no lua_state. Aborting");')
- output('\t\t\t\t::abort();')
- output('\t\t\t};')
- if( rettype == " std::string " ) then
- output('\t\t\treturn "";')
- else
- output('\t\t\treturn (',rettype,')0;')
- end
- else
-
- output('\t\t\treturn (',rettype,')',btype,'::',f.name,var_list,';')
- end
-
- output("\t\t};")
-
- output("\t};")
-end
-
-function VirtualClass()
-
- local parent = classContainer.curr
- pop()
-
- local name = "Lua__"..parent.original_name
-
- local c = _Class(_Container{name=name, base=parent.name, extra_bases=nil})
- setmetatable(c, classVirtualClass)
-
- local ft = getnamespace(c.parent)..c.original_name
- append_global_type(ft, c)
-
- push(parent)
-
- c.flags.parent_object = parent
- c.methods = {}
-
- push(c)
- c:parse("\nvoid tolua__set_instance(_lstate L, lua_Object lo);\n")
- pop()
-
- return c
-end
-
-
-
-
-
-
-function post_output_hook()
- print("Bindings have been generated.")
-end
-
-
-
-