diff options
Diffstat (limited to 'src/Bindings/LuaState.cpp')
-rw-r--r-- | src/Bindings/LuaState.cpp | 138 |
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: |