From 2b04ab874d75711bc021a0cd8dc7fca68f4e6929 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Tue, 11 Aug 2015 22:27:54 -0400 Subject: SAPI: Track last executed mod and include in error messages --- src/script/cpp_api/s_base.cpp | 60 ++++++++++++++++++++++++++++++++++++-- src/script/cpp_api/s_base.h | 15 ++++++++++ src/script/cpp_api/s_entity.cpp | 20 +++++++++---- src/script/cpp_api/s_env.cpp | 6 ++-- src/script/cpp_api/s_inventory.cpp | 3 ++ src/script/cpp_api/s_item.cpp | 3 ++ src/script/cpp_api/s_player.cpp | 18 ++++++------ src/script/cpp_api/s_server.cpp | 7 +++-- 8 files changed, 109 insertions(+), 23 deletions(-) (limited to 'src/script/cpp_api') diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 680e661ea..dcfbac4bf 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_internal.h" #include "cpp_api/s_security.h" #include "lua_api/l_object.h" +#include "common/c_converter.h" #include "serverobject.h" #include "debug.h" #include "filesys.h" @@ -68,9 +69,9 @@ public: ScriptApiBase::ScriptApiBase() { - #ifdef SCRIPTAPI_LOCK_DEBUG +#ifdef SCRIPTAPI_LOCK_DEBUG m_locked = false; - #endif +#endif m_luastack = luaL_newstate(); FATAL_ERROR_IF(!m_luastack, "luaL_newstate() failed"); @@ -154,6 +155,43 @@ bool ScriptApiBase::loadScript(const std::string &script_path, std::string *erro return true; } +// Push the list of callbacks (a lua table). +// Then push nargs arguments. +// Then call this function, which +// - runs the callbacks +// - replaces the table and arguments with the return value, +// computed depending on mode +void ScriptApiBase::runCallbacksRaw(int nargs, + RunCallbacksMode mode, const char *fxn) +{ + lua_State *L = getStack(); + FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments"); + + // Insert error handler + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L) - nargs - 1; + lua_insert(L, errorhandler); + + // Insert run_callbacks between error handler and table + lua_getglobal(L, "core"); + lua_getfield(L, -1, "run_callbacks"); + lua_remove(L, -2); + lua_insert(L, errorhandler + 1); + + // Insert mode after table + lua_pushnumber(L, (int)mode); + lua_insert(L, errorhandler + 3); + + // Stack now looks like this: + // ... ... + + int result = lua_pcall(L, nargs + 2, 1, errorhandler); + if (result != 0) + scriptError(result, fxn); + + lua_remove(L, -2); // Remove error handler +} + void ScriptApiBase::realityCheck() { int top = lua_gettop(m_luastack); @@ -167,7 +205,7 @@ void ScriptApiBase::realityCheck() void ScriptApiBase::scriptError(int result, const char *fxn) { - script_error(getStack(), result, fxn); + script_error(getStack(), result, m_last_run_mod.c_str(), fxn); } void ScriptApiBase::stackDump(std::ostream &o) @@ -197,6 +235,22 @@ void ScriptApiBase::stackDump(std::ostream &o) o << std::endl; } +void ScriptApiBase::setOriginDirect(const char *origin) +{ + m_last_run_mod = origin ? origin : "??"; +} + +void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn) +{ +#ifdef SCRIPTAPI_DEBUG + lua_State *L = getStack(); + + m_last_run_mod = lua_istable(L, index) ? + getstringfield_default(L, index, "mod_origin", "") : ""; + //printf(">>>> running %s for mod: %s\n", fxn, m_last_run_mod.c_str()); +#endif +} + void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 0c2dfafd1..d653b5bac 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -34,6 +34,7 @@ extern "C" { #include "common/c_internal.h" #define SCRIPTAPI_LOCK_DEBUG +#define SCRIPTAPI_DEBUG #define SCRIPT_MOD_NAME_FIELD "current_mod_name" // MUST be an invalid mod name so that mods can't @@ -47,6 +48,12 @@ extern "C" { } \ } while (0) +#define runCallbacks(nargs, mode) \ + runCallbacksRaw((nargs), (mode), __FUNCTION__) + +#define setOriginFromTable(index) \ + setOriginFromTableRaw(index, __FUNCTION__) + class Server; class Environment; class GUIEngine; @@ -61,12 +68,19 @@ public: std::string *error=NULL); bool loadScript(const std::string &script_path, std::string *error=NULL); + void runCallbacksRaw(int nargs, + RunCallbacksMode mode, const char *fxn); + /* object */ void addObjectReference(ServerActiveObject *cobj); void removeObjectReference(ServerActiveObject *cobj); Server* getServer() { return m_server; } + std::string getOrigin() { return m_last_run_mod; } + void setOriginDirect(const char *origin); + void setOriginFromTableRaw(int index, const char *fxn); + protected: friend class LuaABM; friend class InvRef; @@ -95,6 +109,7 @@ protected: void objectrefGet(lua_State *L, u16 id); JMutex m_luastackmutex; + std::string m_last_run_mod; // Stack index of Lua error handler int m_errorhandler; bool m_secure; diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index 08e06ccbc..0d159846a 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -91,7 +91,8 @@ void ScriptApiEntity::luaentity_Activate(u16 id, lua_pushvalue(L, object); // self lua_pushlstring(L, staticdata.c_str(), staticdata.size()); lua_pushinteger(L, dtime_s); - // Call with 3 arguments, 0 results + + setOriginFromTable(object); PCALL_RES(lua_pcall(L, 3, 0, m_errorhandler)); } else { lua_pop(L, 1); @@ -135,11 +136,12 @@ std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id) lua_pop(L, 2); // Pop entity and get_staticdata return ""; } - luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self - // Call with 1 arguments, 1 results + + setOriginFromTable(object); PCALL_RES(lua_pcall(L, 1, 1, m_errorhandler)); + lua_remove(L, object); // Remove object size_t len = 0; @@ -207,8 +209,10 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime) luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self lua_pushnumber(L, dtime); // dtime - // Call with 2 arguments, 0 results + + setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 0, m_errorhandler)); + lua_pop(L, 1); // Pop object } @@ -238,8 +242,10 @@ void ScriptApiEntity::luaentity_Punch(u16 id, lua_pushnumber(L, time_from_last_punch); push_tool_capabilities(L, *toolcap); push_v3f(L, dir); - // Call with 5 arguments, 0 results + + setOriginFromTable(object); PCALL_RES(lua_pcall(L, 5, 0, m_errorhandler)); + lua_pop(L, 1); // Pop object } @@ -264,8 +270,10 @@ void ScriptApiEntity::luaentity_Rightclick(u16 id, luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, clicker); // Clicker reference - // Call with 2 arguments, 0 results + + setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 0, m_errorhandler)); + lua_pop(L, 1); // Pop object } diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index c171bbf02..9c733773a 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -38,7 +38,7 @@ void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp, push_v3s16(L, minp); push_v3s16(L, maxp); lua_pushnumber(L, blockseed); - script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(3, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiEnv::environment_Step(float dtime) @@ -52,7 +52,7 @@ void ScriptApiEnv::environment_Step(float dtime) // Call callbacks lua_pushnumber(L, dtime); try { - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } catch (LuaError &e) { getServer()->setAsyncFatalError(e.what()); } @@ -73,7 +73,7 @@ void ScriptApiEnv::player_event(ServerActiveObject* player, std::string type) objectrefGetOrCreate(L, player); // player lua_pushstring(L,type.c_str()); // event type try { - script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); } catch (LuaError &e) { getServer()->setAsyncFatalError(e.what()); } diff --git a/src/script/cpp_api/s_inventory.cpp b/src/script/cpp_api/s_inventory.cpp index c8c90fd8f..019d1ccc0 100644 --- a/src/script/cpp_api/s_inventory.cpp +++ b/src/script/cpp_api/s_inventory.cpp @@ -209,6 +209,9 @@ bool ScriptApiDetached::getDetachedInventoryCallback( lua_pop(L, 1); return false; } + + setOriginFromTable(-1); + lua_getfield(L, -1, callbackname); lua_remove(L, -2); // Should be a function or nil diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp index 1ca06de76..4d4d416ec 100644 --- a/src/script/cpp_api/s_item.cpp +++ b/src/script/cpp_api/s_item.cpp @@ -193,6 +193,9 @@ bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname) lua_remove(L, -2); luaL_checktype(L, -1, LUA_TTABLE); } + + setOriginFromTable(-1); + lua_getfield(L, -1, callbackname); lua_remove(L, -2); // Remove item def // Should be a function or nil diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index 676b07537..ef3c31cfd 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -32,7 +32,7 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_newplayers"); // Call callbacks objectrefGetOrCreate(L, player); - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) @@ -44,7 +44,7 @@ void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_dieplayers"); // Call callbacks objectrefGetOrCreate(L, player); - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, @@ -65,7 +65,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, push_tool_capabilities(L, *toolcap); push_v3f(L, dir); lua_pushnumber(L, damage); - script_run_callbacks(L, 6, RUN_CALLBACKS_MODE_OR); + runCallbacks(6, RUN_CALLBACKS_MODE_OR); return lua_toboolean(L, -1); } @@ -96,7 +96,7 @@ bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_respawnplayers"); // Call callbacks objectrefGetOrCreate(L, player); - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); + runCallbacks(1, RUN_CALLBACKS_MODE_OR); bool positioning_handled_by_some = lua_toboolean(L, -1); return positioning_handled_by_some; } @@ -113,7 +113,7 @@ bool ScriptApiPlayer::on_prejoinplayer( lua_getfield(L, -1, "registered_on_prejoinplayers"); lua_pushstring(L, name.c_str()); lua_pushstring(L, ip.c_str()); - script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR); + runCallbacks(2, RUN_CALLBACKS_MODE_OR); if (lua_isstring(L, -1)) { reason->assign(lua_tostring(L, -1)); return true; @@ -130,7 +130,7 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_joinplayers"); // Call callbacks objectrefGetOrCreate(L, player); - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) @@ -142,7 +142,7 @@ void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_leaveplayers"); // Call callbacks objectrefGetOrCreate(L, player); - script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_cheat(ServerActiveObject *player, @@ -158,7 +158,7 @@ void ScriptApiPlayer::on_cheat(ServerActiveObject *player, lua_newtable(L); lua_pushlstring(L, cheat_type.c_str(), cheat_type.size()); lua_setfield(L, -2, "type"); - script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, @@ -185,7 +185,7 @@ void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } - script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); + runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC); } ScriptApiPlayer::~ScriptApiPlayer() diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index 5b4626f40..ec2f9c0af 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -67,6 +67,9 @@ void ScriptApiServer::getAuthHandler() lua_pop(L, 1); lua_getfield(L, -1, "builtin_auth_handler"); } + + setOriginFromTable(-1); + lua_remove(L, -2); // Remove core if (lua_type(L, -1) != LUA_TTABLE) throw LuaError("Authentication handler table not valid"); @@ -133,7 +136,7 @@ bool ScriptApiServer::on_chat_message(const std::string &name, // Call callbacks lua_pushstring(L, name.c_str()); lua_pushstring(L, message.c_str()); - script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC); + runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC); bool ate = lua_toboolean(L, -1); return ate; } @@ -146,6 +149,6 @@ void ScriptApiServer::on_shutdown() lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_shutdown"); // Call callbacks - script_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST); + runCallbacks(0, RUN_CALLBACKS_MODE_FIRST); } -- cgit v1.2.3