diff --git a/docs/about/Removed.rst b/docs/about/Removed.rst index 5f73b86be3..9ef7781ebf 100644 --- a/docs/about/Removed.rst +++ b/docs/about/Removed.rst @@ -258,6 +258,11 @@ gui/hack-wish ============= Replaced by `gui/create-item`. +gui/log-cleaner +=============== +Removed because changes to Dwarf Fortress internals made the functionality +impossible to implement safely. + .. _gui/manager-quantity: gui/manager-quantity @@ -278,6 +283,13 @@ Tool that warned the user when the ``dfhack.init`` file did not exist. Now that ``dfhack.init`` is autogenerated in ``dfhack-config/init``, this warning is no longer necessary. +.. _logcleaner: + +logcleaner +=============== +Removed because changes to Dwarf Fortress internals made the functionality +impossible to implement safely. + .. _masspit: masspit diff --git a/docs/changelog.txt b/docs/changelog.txt index 735ddddf4e..cddef2d75c 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -70,6 +70,7 @@ Template for new versions: ## Lua ## Removed +- `logcleaner`: Removed (cannot be safely implemented at this time) # 53.14-r1 diff --git a/docs/plugins/logcleaner.rst b/docs/plugins/logcleaner.rst deleted file mode 100644 index 6e4cba07d6..0000000000 --- a/docs/plugins/logcleaner.rst +++ /dev/null @@ -1,62 +0,0 @@ -logcleaner -========== -.. dfhack-tool:: - :summary: Automatically clear combat, sparring, and hunting reports. - :tags: fort auto units - -This plugin prevents spam from cluttering your announcement history and filling -the 3000-item reports buffer. It runs approximately every 100 ticks and clears -selected report types from both the global reports buffer and per-unit logs. - -Usage ------ - -Basic commands -~~~~~~~~~~~~~~ - -``logcleaner`` - Show the current status of the plugin. -``logcleaner enable`` - Enable the plugin (persists per save). -``logcleaner disable`` - Disable the plugin. - -Configuring filters -~~~~~~~~~~~~~~~~~~~ - -``logcleaner combat`` - Clear combat reports (also enables the plugin if disabled). -``logcleaner sparring`` - Clear sparring reports. -``logcleaner hunting`` - Clear hunting reports. -``logcleaner combat,sparring`` - Clear multiple report types (comma-separated). -``logcleaner all`` - Enable all three filter types. -``logcleaner none`` - Disable all filter types. - -Examples -~~~~~~~~ - -Clear only sparring reports:: - - logcleaner sparring - -Clear combat and hunting, but not sparring:: - - logcleaner combat,hunting - -Overlay UI ----------- - -Run ``gui/logcleaner`` to open the settings overlay, or access it from the -control panel under the Gameplay tab. - -The overlay provides: - -- **Enable toggle**: Turn the plugin on or off (``Shift+E``) -- **Combat toggle**: Clear combat reports (``Shift+C``) -- **Sparring toggle**: Clear sparring reports (``Shift+S``) -- **Hunting toggle**: Clear hunting reports (``Shift+H``) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4a4423f48f..355cc0ac4c 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -66,7 +66,6 @@ if(BUILD_SUPPORTED) dfhack_plugin(createitem createitem.cpp) dfhack_plugin(cursecheck cursecheck.cpp) dfhack_plugin(cxxrandom cxxrandom.cpp LINK_LIBRARIES lua) - dfhack_plugin(logcleaner logcleaner/logcleaner.cpp LINK_LIBRARIES lua) dfhack_plugin(deramp deramp.cpp) dfhack_plugin(debug debug.cpp LINK_LIBRARIES jsoncpp_static) dfhack_plugin(dig dig.cpp LINK_LIBRARIES lua) diff --git a/plugins/logcleaner/logcleaner.cpp b/plugins/logcleaner/logcleaner.cpp deleted file mode 100644 index 89f84cf32f..0000000000 --- a/plugins/logcleaner/logcleaner.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "LuaTools.h" -#include "PluginManager.h" -#include "PluginLua.h" - -#include "modules/Persistence.h" -#include "modules/World.h" - -#include -#include -#include -#include - -using namespace DFHack; - -DFHACK_PLUGIN("logcleaner"); -DFHACK_PLUGIN_IS_ENABLED(is_enabled); - -REQUIRE_GLOBAL(world); - -static const std::string CONFIG_KEY = std::string(plugin_name) + "/config"; -static PersistentDataItem config; - -enum ConfigValues { - CONFIG_IS_ENABLED = 0, - CONFIG_CLEAR_COMBAT = 1, - CONFIG_CLEAR_SPARING = 2, - CONFIG_CLEAR_HUNTING = 3, -}; - -static bool clear_combat = false; -static bool clear_sparring = true; -static bool clear_hunting = false; - -static constexpr int32_t CYCLE_TICKS = 97; -static int32_t cycle_timestamp = 0; - -static void cleanupLogs(); -static command_result do_command(color_ostream& out, std::vector& params); - -// Getter functions for Lua -static bool logcleaner_getCombat() { return clear_combat; } -static bool logcleaner_getSparring() { return clear_sparring; } -static bool logcleaner_getHunting() { return clear_hunting; } - -// Setter functions for Lua (also persist to config) -static void logcleaner_setCombat(bool val) { - clear_combat = val; - config.set_bool(CONFIG_CLEAR_COMBAT, clear_combat); -} - -static void logcleaner_setSparring(bool val) { - clear_sparring = val; - config.set_bool(CONFIG_CLEAR_SPARING, clear_sparring); -} - -static void logcleaner_setHunting(bool val) { - clear_hunting = val; - config.set_bool(CONFIG_CLEAR_HUNTING, clear_hunting); -} - -DFhackCExport command_result plugin_init(color_ostream& out, std::vector& commands) { - commands.push_back(PluginCommand( - plugin_name, - "Prevent report buffer from filling up by clearing selected report types (combat, sparring, hunting).", - do_command)); - - return CR_OK; -} - -static command_result do_command(color_ostream& out, std::vector& params) { - if (!Core::getInstance().isMapLoaded() || !World::isFortressMode()) { - out.printerr("Cannot use {} without a loaded fort.\n", plugin_name); - return CR_FAILURE; - } - - bool show_help = false; - if (!Lua::CallLuaModuleFunction(out, "plugins.logcleaner", "parse_commandline", params, - 1, [&](lua_State *L) { - show_help = !lua_toboolean(L, -1); - })) { - return CR_FAILURE; - } - - return show_help ? CR_WRONG_USAGE : CR_OK; -} - -DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { - if (!Core::getInstance().isMapLoaded() || !World::isFortressMode()) { - out.printerr("Cannot enable {} without a loaded fort.\n", plugin_name); - return CR_FAILURE; - } - - if (enable != is_enabled) { - is_enabled = enable; - config.set_bool(CONFIG_IS_ENABLED, is_enabled); - } - return CR_OK; -} - -DFhackCExport command_result plugin_shutdown(color_ostream& out) { - return CR_OK; -} - -DFhackCExport command_result plugin_load_site_data(color_ostream& out) { - config = World::GetPersistentSiteData(CONFIG_KEY); - - if (!config.isValid()) { - config = World::AddPersistentSiteData(CONFIG_KEY); - config.set_bool(CONFIG_IS_ENABLED, is_enabled); - config.set_bool(CONFIG_CLEAR_COMBAT, clear_combat); - config.set_bool(CONFIG_CLEAR_SPARING, clear_sparring); - config.set_bool(CONFIG_CLEAR_HUNTING, clear_hunting); - } - - is_enabled = config.get_bool(CONFIG_IS_ENABLED); - clear_combat = config.get_bool(CONFIG_CLEAR_COMBAT); - clear_sparring = config.get_bool(CONFIG_CLEAR_SPARING); - clear_hunting = config.get_bool(CONFIG_CLEAR_HUNTING); - - cycle_timestamp = 0; - return CR_OK; -} - -DFhackCExport command_result plugin_onstatechange(color_ostream& out, state_change_event event) { - if (event == DFHack::SC_WORLD_UNLOADED && is_enabled) { - is_enabled = false; - } - return CR_OK; -} - -static void cleanupLogs() { - if (!is_enabled || !world) - return; - - if (!clear_combat && !clear_sparring && !clear_hunting) - return; - - // Collect all report IDs from unit combat/sparring/hunting logs - std::unordered_set report_ids_to_remove; - bool log_types[] = {clear_combat, clear_sparring, clear_hunting}; - - for (auto unit : world->units.all) { - for (int log_idx = 0; log_idx < 3; log_idx++) { - if (log_types[log_idx]) { - auto& log = unit->reports.log[log_idx]; - for (auto report_id : log) { - report_ids_to_remove.insert(report_id); - } - log.clear(); - } - } - } - - if (report_ids_to_remove.empty()) - return; - - // Remove collected reports from global buffers - auto& reports = world->status.reports; - - std::erase_if(reports, [&](df::report* report) { - if (!report || !report_ids_to_remove.contains(report->id)) - return false; - if (report->flags.bits.announcement) - erase_from_vector(world->status.announcements, &df::report::id, report->id); - delete report; - return true; - }); -} - -DFhackCExport command_result plugin_onupdate(color_ostream& out, state_change_event event) { - if (!is_enabled || !world) - return CR_OK; - else if (world->frame_counter - cycle_timestamp < CYCLE_TICKS) - return CR_OK; - - cycle_timestamp = world->frame_counter; - cleanupLogs(); - - return CR_OK; -} - -DFHACK_PLUGIN_LUA_FUNCTIONS { - DFHACK_LUA_FUNCTION(logcleaner_getCombat), - DFHACK_LUA_FUNCTION(logcleaner_getSparring), - DFHACK_LUA_FUNCTION(logcleaner_getHunting), - DFHACK_LUA_FUNCTION(logcleaner_setCombat), - DFHACK_LUA_FUNCTION(logcleaner_setSparring), - DFHACK_LUA_FUNCTION(logcleaner_setHunting), - DFHACK_LUA_END -}; diff --git a/plugins/lua/logcleaner.lua b/plugins/lua/logcleaner.lua deleted file mode 100644 index 104c23ab88..0000000000 --- a/plugins/lua/logcleaner.lua +++ /dev/null @@ -1,85 +0,0 @@ -local _ENV = mkmodule('plugins.logcleaner') - -local function print_status() - print(('logcleaner is %s'):format(isEnabled() and "enabled" or "disabled")) - print(' Combat: ' .. (logcleaner_getCombat() and 'enabled' or 'disabled')) - print(' Sparring: ' .. (logcleaner_getSparring() and 'enabled' or 'disabled')) - print(' Hunting: ' .. (logcleaner_getHunting() and 'enabled' or 'disabled')) -end - -function parse_commandline(...) - local args = {...} - local command = args[1] - - -- Show status if no command or "status" - if not command or command == 'status' then - print_status() - return true - end - - -- Handle enable/disable commands - if command == 'enable' then - if isEnabled() then - print('logcleaner is already enabled') - else - dfhack.run_command('enable', 'logcleaner') - print('logcleaner enabled') - end - return true - end - - if command == 'disable' then - if not isEnabled() then - print('logcleaner is already disabled') - else - dfhack.run_command('disable', 'logcleaner') - print('logcleaner disabled') - end - return true - end - - -- Start with all disabled, enable only what's specified - local new_combat, new_sparring, new_hunting = false, false, false - local has_filter = false - - if command == 'all' then - new_combat, new_sparring, new_hunting = true, true, true - has_filter = true - elseif command == 'none' then - new_combat, new_sparring, new_hunting = false, false, false - else - -- Split by comma for multiple options in one parameter - for token in command:gmatch('([^,]+)') do - if token == 'combat' then - new_combat = true - has_filter = true - elseif token == 'sparring' then - new_sparring = true - has_filter = true - elseif token == 'hunting' then - new_hunting = true - has_filter = true - else - dfhack.printerr('Unknown option: ' .. token) - return false - end - end - end - - -- Auto-enable plugin when filters are being configured - if has_filter and not isEnabled() then - dfhack.run_command('enable', 'logcleaner') - print('logcleaner enabled') - end - - logcleaner_setCombat(new_combat) - logcleaner_setSparring(new_sparring) - logcleaner_setHunting(new_hunting) - - print('Log cleaning config updated:') - print_status() - - return true -end - -return _ENV