summaryrefslogtreecommitdiffstats
path: root/src/Bindings/LuaState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings/LuaState.cpp')
-rw-r--r--src/Bindings/LuaState.cpp138
1 files changed, 109 insertions, 29 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index ccf812417..a0fdecb8b 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -211,23 +211,31 @@ void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a
-bool cLuaState::LoadFile(const AString & a_FileName)
+bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings)
{
ASSERT(IsValid());
// Load the file:
int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
- if (ReportErrors(s))
+ if (s != 0)
{
- LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
+ if (a_LogWarnings)
+ {
+ LOGWARNING("Can't load %s because of a load error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
+ }
+ lua_pop(m_LuaState, 1);
return false;
}
// Execute the globals:
s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
- if (ReportErrors(s))
+ if (s != 0)
{
- LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
+ if (a_LogWarnings)
+ {
+ LOGWARNING("Can't load %s because of an initialization error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
+ }
+ lua_pop(m_LuaState, 1);
return false;
}
@@ -446,6 +454,18 @@ void cLuaState::Push(const cPlayer * a_Player)
+void cLuaState::Push(const cLuaState::cRef & a_Ref)
+{
+ ASSERT(IsValid());
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast<int>(a_Ref));
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
void cLuaState::Push(const HTTPRequest * a_Request)
{
ASSERT(IsValid());
@@ -701,108 +721,142 @@ void cLuaState::PushUserType(void * a_Object, const char * a_Type)
-void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
+bool cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
{
size_t len = 0;
const char * data = lua_tolstring(m_LuaState, a_StackPos, &len);
if (data != nullptr)
{
a_Value.assign(data, len);
+ return true;
}
+ return false;
}
-void cLuaState::GetStackValue(int a_StackPos, BLOCKTYPE & a_ReturnedVal)
-{
- if (lua_isnumber(m_LuaState, a_StackPos))
- {
- a_ReturnedVal = static_cast<BLOCKTYPE>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
- }
-}
-
-
-
-
-
-void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
+bool cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
{
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
+ return true;
}
-void cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result)
+bool cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
a_Result = static_cast<cPluginManager::CommandResult>(static_cast<int>((tolua_tonumber(m_LuaState, a_StackPos, a_Result))));
+ return true;
}
+ return false;
}
-void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
+bool cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref)
{
a_Ref.RefStack(*this, a_StackPos);
+ return true;
}
-void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
+bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
a_ReturnedVal = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal);
+ return true;
}
+ return false;
}
-void cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal)
+bool cLuaState::GetStackValue(int a_StackPos, eBlockFace & a_ReturnedVal)
{
- if (lua_isnumber(m_LuaState, a_StackPos))
+ if (!lua_isnumber(m_LuaState, a_StackPos))
{
- a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
+ return false;
}
+ a_ReturnedVal = static_cast<eBlockFace>(Clamp(
+ static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)),
+ static_cast<int>(BLOCK_FACE_MIN), static_cast<int>(BLOCK_FACE_MAX))
+ );
+ return true;
}
-void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
+bool cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
{
if (!lua_isnumber(m_LuaState, a_StackPos))
{
- return;
+ return false;
}
a_ReturnedVal = static_cast<eWeather>(Clamp(
static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)),
static_cast<int>(wSunny), static_cast<int>(wThunderstorm))
);
+ return true;
}
-void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
+bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
- a_ReturnedVal = static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
+ a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
+ return true;
}
+ return false;
+}
+
+
+
+
+
+cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name)
+{
+ // There needs to be at least one value on the stack:
+ ASSERT(lua_gettop(m_LuaState) > 0);
+
+ // Iterate over path and replace the top of the stack with the walked element
+ lua_pushvalue(m_LuaState, -1); // Copy the stack value into the "working area"
+ auto path = StringSplit(a_Name, ".");
+ for (const auto & elem: path)
+ {
+ // If the value is not a table, bail out (error):
+ if (!lua_istable(m_LuaState, -1))
+ {
+ lua_pop(m_LuaState, 1);
+ return cStackValue();
+ }
+
+ // Get the next part of the path:
+ lua_getfield(m_LuaState, -1, elem.c_str());
+
+ // Remove the previous value from the stack (keep only the new one):
+ lua_remove(m_LuaState, -2);
+ } // for elem - path[]
+ return std::move(cStackValue(*this));
}
@@ -927,6 +981,9 @@ bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam)
VERIFY(lua_getstack(m_LuaState, 0, &entry));
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != nullptr) ? entry.name : "?");
+
+ BreakIntoDebugger(m_LuaState);
+
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
return false;
} // for i - Param
@@ -1366,6 +1423,7 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState)
{
LOGWARNING("LUA: %s", lua_tostring(a_LuaState, -1));
LogStackTrace(a_LuaState, 1);
+ BreakIntoDebugger(a_LuaState);
return 1; // We left the error message on the stack as the return value
}
@@ -1373,6 +1431,28 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState)
+int cLuaState::BreakIntoDebugger(lua_State * a_LuaState)
+{
+ // Call the BreakIntoDebugger function, if available:
+ lua_getglobal(a_LuaState, "BreakIntoDebugger");
+ if (!lua_isfunction(a_LuaState, -1))
+ {
+ LOGD("LUA: BreakIntoDebugger() not found / not a function");
+ lua_pop(a_LuaState, 1);
+ return 1;
+ }
+ lua_insert(a_LuaState, -2); // Copy the string that has been passed to us
+ LOGD("Calling BreakIntoDebugger()...");
+ lua_call(a_LuaState, 1, 0);
+ LOGD("Returned from BreakIntoDebugger().");
+
+ return 0;
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef: