diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 3ad19efb4..78bf63903 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -154,6 +154,7 @@ if(BUILD_SUPPORTED) dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename) add_subdirectory(rendermax) dfhack_plugin(reveal reveal.cpp LINK_LIBRARIES lua) + dfhack_plugin(script-manager script-manager.cpp LINK_LIBRARIES lua) dfhack_plugin(search search.cpp) dfhack_plugin(seedwatch seedwatch.cpp) dfhack_plugin(showmood showmood.cpp) diff --git a/plugins/lua/script-manager.lua b/plugins/lua/script-manager.lua new file mode 100644 index 000000000..4d750091e --- /dev/null +++ b/plugins/lua/script-manager.lua @@ -0,0 +1,57 @@ +local _ENV = mkmodule('plugins.script-manager') + +local utils = require('utils') + +-- for each script that can be loaded as a module, calls cb(script_name, env) +function foreach_module_script(cb) + for _,script_path in ipairs(dfhack.internal.getScriptPaths()) do + local files = dfhack.filesystem.listdir_recursive( + script_path, nil, false) + if not files then goto skip_path end + for _,f in ipairs(files) do + if not f.isdir and + f.path:endswith('.lua') and + not f.path:startswith('test/') and + not f.path:startswith('internal/') then + local script_name = f.path:sub(1, #f.path - 4) -- remove '.lua' + local ok, script_env = pcall(reqscript, script_name) + if ok then + cb(script_name, script_env) + end + end + end + ::skip_path:: + end +end + +local enabled_map = {} + +local function process_global(env_name, env, global_name, target) + local fn = env[global_name] + if not fn then return end + if type(fn) ~= 'function' then + dfhack.printerr( + ('error registering %s() from "%s": global' .. + ' value is not a function'):format(global_name, env_name)) + return + end + target[env_name] = fn +end + +local function process_script(env_name, env) + process_global(env_name, env, 'onStateChange', dfhack.onStateChange) + process_global(env_name, env, 'isEnabled', enabled_map) +end + +function init() + enabled_map = utils.OrderedTable() + foreach_module_script(process_script) +end + +function list() + for name,fn in pairs(enabled_map) do + print(('%20s\t%-3s'):format(name..':', fn() and 'on' or 'off')) + end +end + +return _ENV diff --git a/plugins/script-manager.cpp b/plugins/script-manager.cpp new file mode 100644 index 000000000..27a1a9943 --- /dev/null +++ b/plugins/script-manager.cpp @@ -0,0 +1,31 @@ +#include "Debug.h" +#include "LuaTools.h" +#include "PluginManager.h" + +using std::string; +using std::vector; + +using namespace DFHack; + +DFHACK_PLUGIN("script-manager"); + +namespace DFHack { + DBG_DECLARE(script_manager, log, DebugCategory::LINFO); +} + +DFhackCExport command_result plugin_init(color_ostream &, std::vector &) { + return CR_OK; +} + +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { + if (event != SC_CORE_INITIALIZED) + return CR_OK; + + DEBUG(log,out).print("scanning scripts for onStateChange() functions\n"); + + auto L = Lua::Core::State; + Lua::StackUnwinder top(L); + Lua::CallLuaModuleFunction(out, L, "plugins.script-manager", "init"); + + return CR_OK; +}