diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index c24a4cedbb..c05d2cb6d1 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -55,6 +55,7 @@ set(MAIN_HEADERS include/ColorText.h include/Console.h include/Core.h + include/CoreDefs.h include/DataDefs.h include/DataFuncs.h include/DataIdentity.h diff --git a/library/Core.cpp b/library/Core.cpp index 951fb62f3a..d9910c41c8 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -346,7 +346,7 @@ static command_result runLuaScript(color_ostream &out, std::string name, std::ve data.pcmd = &name; data.pargs = &args; - bool ok = Lua::RunCoreQueryLoop(out, Lua::Core::State, init_run_script, &data); + bool ok = Lua::RunCoreQueryLoop(out, DFHack::Core::getInstance().getLuaState(true), init_run_script, &data); return ok ? CR_OK : CR_FAILURE; } @@ -370,7 +370,7 @@ static command_result enableLuaScript(color_ostream &out, std::string name, bool data.pcmd = &name; data.pstate = state; - bool ok = Lua::RunCoreQueryLoop(out, Lua::Core::State, init_enable_script, &data); + bool ok = Lua::RunCoreQueryLoop(out, DFHack::Core::getInstance().getLuaState(), init_enable_script, &data); return ok ? CR_OK : CR_FAILURE; } @@ -399,7 +399,7 @@ command_result Core::runCommand(color_ostream &out, const std::string &command) bool is_builtin(color_ostream &con, const std::string &command) { CoreSuspender suspend; - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, 1) || @@ -427,7 +427,7 @@ void get_commands(color_ostream &con, std::vector &commands) { return; } - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, 1) || @@ -632,7 +632,7 @@ void help_helper(color_ostream &con, const std::string &entry_name) { con.printerr("Failed Lua call to helpdb.help (could not acquire core lock).\n"); return; } - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, 2) || @@ -650,7 +650,7 @@ void help_helper(color_ostream &con, const std::string &entry_name) { void tags_helper(color_ostream &con, const std::string &tag) { CoreSuspender suspend; - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, 1) || @@ -687,7 +687,7 @@ void ls_helper(color_ostream &con, const std::vector ¶ms) { } CoreSuspender suspend; - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, 5) || @@ -1366,7 +1366,7 @@ static void run_dfhack_init(color_ostream &out, Core *core) loadScriptFiles(core, out, prefixes, CONFIG_PATH + "init"); // show the terminal if requested - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::CallLuaModuleFunction(out, L, "dfhack", "getHideConsoleOnStartup", 0, 1, Lua::DEFAULT_LUA_LAMBDA, [&](lua_State* L) { if (!lua_toboolean(L, -1)) @@ -1805,7 +1805,10 @@ bool Core::InitSimulationThread() loadScriptPaths(con); // initialize common lua context - if (!Lua::Core::Init(con)) + // Calls InitCoreContext after checking IsCoreContext + State = luaL_newstate(); + State = Lua::Open(con, State); + if (!State) { fatal("Lua failed to initialize"); return false; @@ -2319,7 +2322,7 @@ void Core::onStateChange(color_ostream &out, state_change_event event) Persistence::Internal::load(out); plug_mgr->doLoadWorldData(out); loadModScriptPaths(out); - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); Lua::CallLuaModuleFunction(con, "script-manager", "reload", std::make_tuple(true)); if (world && world->cur_savegame.save_dir.size()) diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 08b90bd61c..24b540d242 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -71,8 +71,6 @@ distribution. using namespace DFHack; using namespace DFHack::LuaWrapper; -lua_State *DFHack::Lua::Core::State = NULL; - void dfhack_printerr(lua_State *S, const std::string &str); inline bool is_null_userdata(lua_State *L, int idx) @@ -523,7 +521,7 @@ static void interrupt_hook (lua_State *L, lua_Debug *ar) bool DFHack::Lua::Interrupt (bool force) { - lua_State *L = Lua::Core::State; + lua_State *L = DFHack::Core::getInstance().getLuaState(); if (L->hook != interrupt_hook && !force) return false; if (force) @@ -1492,8 +1490,8 @@ bool Lua::IsCoreContext(lua_State *state) // This uses a private field of the lua state to // evaluate the condition without accessing the lua // stack, and thus requiring a lock on the core state. - return state && Lua::Core::State && - state->l_G == Lua::Core::State->l_G; + return state && DFHack::Core::getInstance().getLuaState() && + state->l_G == DFHack::Core::getInstance().getLuaState()->l_G; } static const luaL_Reg dfhack_funcs[] = { @@ -2029,7 +2027,7 @@ int dfhack_timeout_active(lua_State *L) static void cancel_timers(std::multimap &timers) { - using Lua::Core::State; + auto State = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder frame(State); lua_rawgetp(State, LUA_REGISTRYINDEX, &DFHACK_TIMEOUTS_TOKEN); @@ -2044,6 +2042,7 @@ static void cancel_timers(std::multimap &timers) } void DFHack::Lua::Core::onStateChange(color_ostream &out, int code) { + auto State = DFHack::Core::getInstance().getLuaState(); if (!State) return; switch (code) @@ -2084,6 +2083,7 @@ static void run_timers(color_ostream &out, lua_State *L, void DFHack::Lua::Core::onUpdate(color_ostream &out) { + auto State = DFHack::Core::getInstance().getLuaState(); using df::global::world; if (frame_timers.empty() && tick_timers.empty()) @@ -2098,21 +2098,9 @@ void DFHack::Lua::Core::onUpdate(color_ostream &out) run_timers(out, State, tick_timers, frame[1], world->frame_counter); } -bool DFHack::Lua::Core::Init(color_ostream &out) -{ - if (State) { - out.printerr("state already exists\n"); - return false; - } - - State = luaL_newstate(); - - // Calls InitCoreContext after checking IsCoreContext - return (Lua::Open(out, State) != NULL); -} - static void Lua::Core::InitCoreContext(color_ostream &out) { + auto State = DFHack::Core::getInstance().getLuaState(); lua_newtable(State); lua_rawsetp(State, LUA_REGISTRYINDEX, &DFHACK_TIMEOUTS_TOKEN); @@ -2150,6 +2138,7 @@ static void Lua::Core::InitCoreContext(color_ostream &out) void DFHack::Lua::Core::Reset(color_ostream &out, const char *where) { // This can happen if DFHack fails to initialize. + auto State = DFHack::Core::getInstance().getLuaState(); if (!State) return; diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index eb6ba803ea..458c0377c2 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -704,7 +704,7 @@ void Plugin::index_lua(DFLibrary *lib) cmd->event = evlist->event; if (cmd->active) { - cmd->event->bind(Lua::Core::State, cmd); + cmd->event->bind(DFHack::Core::getInstance().getLuaState(), cmd); if (cmd->count > 0) cmd->event->on_count_changed(cmd->count, 0); } @@ -830,7 +830,7 @@ void Plugin::open_lua(lua_State *state, int table) it->second->active = true; if (it->second->event) - it->second->event->bind(Lua::Core::State, it->second); + it->second->event->bind(DFHack::Core::getInstance().getLuaState(), it->second); lua_setfield(state, table, it->first.c_str()); } diff --git a/library/RemoteTools.cpp b/library/RemoteTools.cpp index c8fc810c8b..d8d5eb61e1 100644 --- a/library/RemoteTools.cpp +++ b/library/RemoteTools.cpp @@ -757,7 +757,7 @@ command_result CoreService::RunLua(color_ostream &stream, const dfproto::CoreRunLuaRequest *in, StringListMessage *out) { - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); LuaFunctionData data = { CR_FAILURE, in, out }; lua_pushcfunction(L, doRunLuaFunction); diff --git a/library/include/Core.h b/library/include/Core.h index 8b9afd9593..f7da6fcfb3 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -25,6 +25,7 @@ distribution. #pragma once #include "Console.h" +#include "CoreDefs.h" #include "Export.h" #include "Hooks.h" @@ -48,6 +49,7 @@ distribution. #define DFH_MOD_ALT 4 struct WINDOW; +struct lua_State; namespace df { @@ -75,31 +77,6 @@ namespace DFHack struct Hide; } - enum command_result - { - CR_LINK_FAILURE = -3, // RPC call failed due to I/O or protocol error - CR_NEEDS_CONSOLE = -2, // Attempt to call interactive command without console - CR_NOT_IMPLEMENTED = -1, // Command not implemented, or plugin not loaded - CR_OK = 0, // Success - CR_FAILURE = 1, // Failure - CR_WRONG_USAGE = 2, // Wrong arguments or ui state - CR_NOT_FOUND = 3 // Target object not found (for RPC mainly) - }; - - enum state_change_event - { - SC_UNKNOWN = -1, - SC_WORLD_LOADED = 0, - SC_WORLD_UNLOADED = 1, - SC_MAP_LOADED = 2, - SC_MAP_UNLOADED = 3, - SC_VIEWSCREEN_CHANGED = 4, - SC_CORE_INITIALIZED = 5, - SC_BEGIN_UNLOAD = 6, - SC_PAUSED = 7, - SC_UNPAUSED = 8 - }; - class DFHACK_EXPORT PerfCounters { public: @@ -243,6 +220,11 @@ namespace DFHack PerfCounters perf_counters; + lua_State* getLuaState(bool bypass_assertion = false) { + assert(bypass_assertion || isSuspended()); + return State; + } + private: DFHack::Console con; @@ -350,6 +332,8 @@ namespace DFHack std::thread::id df_render_thread; std::thread::id df_simulation_thread; + lua_State* State; + friend class CoreService; friend class ServerConnection; friend class CoreSuspender; @@ -395,9 +379,9 @@ namespace DFHack if (!owns_lock()) return; /* Restore core owner to previous value */ - core.ownerThread.store(tid, std::memory_order_release); if (tid == std::thread::id{}) Lua::Core::Reset(core.getConsole(), "suspend"); + core.ownerThread.store(tid, std::memory_order_release); parent_t::unlock(); } diff --git a/library/include/CoreDefs.h b/library/include/CoreDefs.h new file mode 100644 index 0000000000..dd78649394 --- /dev/null +++ b/library/include/CoreDefs.h @@ -0,0 +1,36 @@ +#pragma once + +/** + * Split off from Core.h to keep unnecessary class definitions out of compilation units that do not need them + * + */ + +namespace DFHack +{ + + enum command_result + { + CR_LINK_FAILURE = -3, // RPC call failed due to I/O or protocol error + CR_NEEDS_CONSOLE = -2, // Attempt to call interactive command without console + CR_NOT_IMPLEMENTED = -1, // Command not implemented, or plugin not loaded + CR_OK = 0, // Success + CR_FAILURE = 1, // Failure + CR_WRONG_USAGE = 2, // Wrong arguments or ui state + CR_NOT_FOUND = 3 // Target object not found (for RPC mainly) + }; + + enum state_change_event + { + SC_UNKNOWN = -1, + SC_WORLD_LOADED = 0, + SC_WORLD_UNLOADED = 1, + SC_MAP_LOADED = 2, + SC_MAP_UNLOADED = 3, + SC_VIEWSCREEN_CHANGED = 4, + SC_CORE_INITIALIZED = 5, + SC_BEGIN_UNLOAD = 6, + SC_PAUSED = 7, + SC_UNPAUSED = 8 + }; + +} diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index e2166f92d6..53c17e1b21 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -472,10 +472,10 @@ namespace DFHack {namespace Lua { * All accesses must be done under CoreSuspender. */ namespace Core { - DFHACK_EXPORT extern lua_State *State; +// DFHACK_EXPORT extern lua_State *State; // Not exported; for use by the Core class - bool Init(color_ostream &out); + lua_State* Init(color_ostream &out); DFHACK_EXPORT void Reset(color_ostream &out, const char *where); // Events signalled by the core @@ -483,17 +483,32 @@ namespace DFHack {namespace Lua { // Signals timers void onUpdate(color_ostream &out); - template inline void Push(T &arg) { Lua::Push(State, arg); } - template inline void Push(const T &arg) { Lua::Push(State, arg); } - template inline void PushVector(const T &arg) { Lua::PushVector(State, arg); } + template inline void Push(T &arg) + { + auto State = DFHack::Core::getInstance().getLuaState(); + Lua::Push(State, arg); + } + template inline void Push(const T &arg) + { + auto State = DFHack::Core::getInstance().getLuaState(); + Lua::Push(State, arg); + } + template inline void PushVector(const T &arg) + { + auto State = DFHack::Core::getInstance().getLuaState(); + Lua::PushVector(State, arg); + } inline bool SafeCall(color_ostream &out, int nargs, int nres, bool perr = true) { + auto State = DFHack::Core::getInstance().getLuaState(); return Lua::SafeCall(out, State, nargs, nres, perr); } inline bool PushModule(color_ostream &out, const char *module) { + auto State = DFHack::Core::getInstance().getLuaState(); return Lua::PushModule(out, State, module); } inline bool PushModulePublic(color_ostream &out, const char *module, const char *name) { + auto State = DFHack::Core::getInstance().getLuaState(); return Lua::PushModulePublic(out, State, module, name); } } @@ -507,7 +522,7 @@ namespace DFHack {namespace Lua { color_ostream &out, const char* module_name, const char* fn_name, std::tuple&& args = {}, size_t nres = 0, Lua::LuaLambda && res_lambda = Lua::DEFAULT_LUA_LAMBDA) { - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); bool ok; ok = Lua::CallLuaModuleFunction(out, L, module_name, fn_name, sizeof...(aT), nres, @@ -523,7 +538,7 @@ namespace DFHack {namespace Lua { color_ostream &out, const char* module_name, const char* fn_name, const std::vector &args, size_t nres = 0, Lua::LuaLambda && res_lambda = Lua::DEFAULT_LUA_LAMBDA) { - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); bool ok; ok = Lua::CallLuaModuleFunction(out, L, module_name, fn_name, args.size(), nres, diff --git a/library/include/RemoteClient.h b/library/include/RemoteClient.h index 449a743753..abcf61dc1e 100644 --- a/library/include/RemoteClient.h +++ b/library/include/RemoteClient.h @@ -25,7 +25,7 @@ distribution. #pragma once #include "Export.h" #include "ColorText.h" -#include "Core.h" +#include "CoreDefs.h" class CPassiveSocket; class CActiveSocket; diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index a3c8a2f781..1a98837739 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -863,7 +863,7 @@ bool dfhack_lua_viewscreen::safe_call_lua(int (*pf)(lua_State *), int args, int CoreSuspender suspend; color_ostream_proxy out(Core::getInstance().getConsole()); - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); lua_pushcfunction(L, pf); if (args > 0) lua_insert(L, -args-1); lua_pushlightuserdata(L, this); @@ -1065,7 +1065,7 @@ void dfhack_lua_viewscreen::logic() dfhack_viewscreen::logic(); - lua_pushstring(Lua::Core::State, "onIdle"); + lua_pushstring(DFHack::Core::getInstance().getLuaState(), "onIdle"); safe_call_lua(do_notify, 1, 0); } @@ -1080,7 +1080,7 @@ void dfhack_lua_viewscreen::help() { if (Screen::isDismissed(this)) return; - lua_pushstring(Lua::Core::State, "onHelp"); + lua_pushstring(DFHack::Core::getInstance().getLuaState(), "onHelp"); safe_call_lua(do_notify, 1, 0); } @@ -1088,7 +1088,7 @@ void dfhack_lua_viewscreen::resize(int w, int h) { if (Screen::isDismissed(this)) return; - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); lua_pushstring(L, "onResize"); lua_pushinteger(L, w); lua_pushinteger(L, h); @@ -1099,30 +1099,31 @@ void dfhack_lua_viewscreen::feed(std::set *keys) { if (Screen::isDismissed(this)) return; - lua_pushlightuserdata(Lua::Core::State, keys); + lua_pushlightuserdata(DFHack::Core::getInstance().getLuaState(), keys); safe_call_lua(do_input, 1, 0); df::global::enabler->last_text_input[0] = '\0'; } void dfhack_lua_viewscreen::onShow() { - lua_pushstring(Lua::Core::State, "onShow"); + lua_pushstring(DFHack::Core::getInstance().getLuaState(), "onShow"); safe_call_lua(do_notify, 1, 0); } void dfhack_lua_viewscreen::onDismiss() { - lua_pushstring(Lua::Core::State, "onDismiss"); + lua_pushstring(DFHack::Core::getInstance().getLuaState(), "onDismiss"); safe_call_lua(do_notify, 1, 0); } template T* dfhack_lua_viewscreen::getSelected(const char* method_name) { - Lua::StackUnwinder frame(Lua::Core::State); - lua_pushstring(Lua::Core::State, method_name); + auto L = DFHack::Core::getInstance().getLuaState(); + Lua::StackUnwinder frame(L); + lua_pushstring(L, method_name); safe_call_lua(do_notify, 1, 1); - return Lua::GetDFObject(Lua::Core::State, -1); + return Lua::GetDFObject(L, -1); } df::unit* dfhack_lua_viewscreen::getSelectedUnit() diff --git a/plugins/devel/check-structures-sanity/main.cpp b/plugins/devel/check-structures-sanity/main.cpp index 11bfc4bdd0..5bc7c09d6d 100644 --- a/plugins/devel/check-structures-sanity/main.cpp +++ b/plugins/devel/check-structures-sanity/main.cpp @@ -114,6 +114,7 @@ static command_result command(color_ostream & out, std::vector & pa using namespace DFHack::Lua::Core; using namespace DFHack::LuaWrapper; + auto State = DFHack::Core::getInstance().getLuaState(); StackUnwinder unwinder(State); PushModulePublic(out, "utils", "df_expr_to_ref"); Push(parameters.at(0)); diff --git a/plugins/dig-now.cpp b/plugins/dig-now.cpp index 9cd1676281..7e46b3e7cc 100644 --- a/plugins/dig-now.cpp +++ b/plugins/dig-now.cpp @@ -995,7 +995,7 @@ static void post_process_dug_tiles(color_ostream &out, static bool get_options(color_ostream &out, dig_now_options &opts, const std::vector ¶meters) { - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); Lua::StackUnwinder top(L); if (!lua_checkstack(L, parameters.size() + 2) || diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 2920f80fb1..8e95acad66 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -54,7 +54,7 @@ static void overlay_interpose_lua(const char *fn_name, int nargs = 0, int nres = CoreSuspender guard; color_ostream & out = Core::getInstance().getConsole(); - auto L = Lua::Core::State; + auto L = DFHack::Core::getInstance().getLuaState(); auto & core = Core::getInstance(); auto & counters = core.perf_counters; diff --git a/plugins/remotefortressreader/item_reader.cpp b/plugins/remotefortressreader/item_reader.cpp index d06c2473eb..1353243b2b 100644 --- a/plugins/remotefortressreader/item_reader.cpp +++ b/plugins/remotefortressreader/item_reader.cpp @@ -53,6 +53,7 @@ #include "modules/MapCache.h" #include "modules/Materials.h" #include "MiscUtils.h" +#include "Core.h" using namespace DFHack;