Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions docs/Core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,10 @@ on UNIX-like systems:
with the default, if this port cannot be used, the server is not started.
See `remote` for more details.

- ``DFHACK_DISABLE_CONSOLE``: if set, the DFHack console is not set up. This is
the default behavior if ``PRINT_MODE:TEXT`` is set in ``data/init/init.txt``.
Intended for situations where DFHack cannot run in a terminal window.
- ``DFHACK_DISABLE_CONSOLE``: if set, DFHack's external console is not set up.
This is the default behavior if ``PRINT_MODE:TEXT`` is set in
``data/init/init.txt``. Intended for situations where DFHack cannot run in a
terminal window.

- ``DFHACK_HEADLESS``: if set, and ``PRINT_MODE:TEXT`` is set, DF's display will
be hidden, and the console will be started unless ``DFHACK_DISABLE_CONSOLE``
Expand Down Expand Up @@ -409,19 +410,23 @@ Other (non-DFHack-specific) variables that affect DFHack:
Core preferences
================

There are a few settings that can be changed dynamically via
`gui/control-panel` to affect runtime behavior. You can also toggle these from
the commandline using the `lua` command, e.g.
``lua dfhack.HIDE_ARMOK_TOOLS=true`` or by editing the generated
``dfhack-config/init/dfhack.control-panel-preferences.init`` file and
restarting DF.

- ``dfhack.HIDE_CONSOLE_ON_STARTUP``: Whether to hide the external DFHack
terminal window on startup. This, of course, is not useful to change
dynamically. You'll have to use `gui/control-panel` or edit the init file
directly and restart DF for it to have an effect.

- ``dfhack.HIDE_ARMOK_TOOLS``: Whether to hide "armok" tools in command lists.
Settings that control DFHack's runtime behavior can be changed dynamically via
the "Preferences" tab in `gui/control-panel` or on the commandline with
`control-panel`. The two most important settings for the core are:

- ``HIDE_CONSOLE_ON_STARTUP``: On Windows, this controls whether to hide the
external DFHack terminal window on startup. The console is hidden by default
so it does not get in the way of gameplay, but it can be useful to enable for
debugging purposes or if you just prefer to use the external console instead
of the in-game `gui/launcher`. When you change this setting, the new behavior
will take effect the next time you start the game. If you are running the
native Linux version of DF (and DFHack), the terminal that you run the game
from becomes the DFHack console and this setting has no effect.

- ``HIDE_ARMOK_TOOLS``: Whether to hide "armok" tools in command lists. Also
known as "Mortal mode", this setting keeps god-mode tools out of sight and
out of mind. Highly recommended for players who would prefer if the god-mode
tools were not quite as obvious and accessible.

Performance monitoring
======================
Expand Down
6 changes: 6 additions & 0 deletions docs/dev/Lua API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3205,6 +3205,12 @@ and are only documented here for completeness:
Gets and sets the flag for whether to suppress DF key events when a DFHack
keybinding is matched and a command is launched.

* ``dfhack.internal.setMortalMode(value)``
* ``dfhack.internal.setArmokTools(tool_names)``

Used to sync mortal mode state to DFHack Core memory for use in keybinding
checks.

.. _lua-core-context:

Core interpreter context
Expand Down
28 changes: 10 additions & 18 deletions library/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2381,6 +2381,15 @@ void Core::setSuppressDuplicateKeyboardEvents(bool suppress) {
suppress_duplicate_keyboard_events = suppress;
}

void Core::setMortalMode(bool value) {
mortal_mode = value;
}

void Core::setArmokTools(const std::vector<std::string> &tool_names) {
armok_tools.clear();
armok_tools.insert(tool_names.begin(), tool_names.end());
}

Comment on lines +2384 to +2392
Copy link
Member

@lethosor lethosor Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a mutex guarding all of these accesses (not exclusive to these two functions) because SelectHotkey is called from the input thread. (I haven't looked to see if there is an existing appropriate mutex)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding that (07ad3a2)

// returns true if the event is handled
bool Core::DFH_SDL_Event(SDL_Event* ev) {
uint32_t start_ms = p->getTickCount();
Expand Down Expand Up @@ -2460,23 +2469,6 @@ bool Core::doSdlInputEvent(SDL_Event* ev)
return false;
}

static bool should_hide_from_mortals(const std::string &command) {
auto &out = Core::getInstance().getConsole();

bool is_mortal = false;
Lua::CallLuaModuleFunction(out, "dfhack", "getHideArmokTools", {}, 1,
[&](lua_State* L) { is_mortal = lua_toboolean(L, -1); });

if (!is_mortal)
return false;

bool is_armok = false;
Lua::CallLuaModuleFunction(out, "helpdb", "has_tag", std::make_tuple(command, "armok"), 1,
[&](lua_State* L) { is_armok = lua_toboolean(L, -1); });

return is_armok;
}

bool Core::SelectHotkey(int sym, int modifiers)
{
// Find the topmost viewscreen
Expand Down Expand Up @@ -2521,7 +2513,7 @@ bool Core::SelectHotkey(int sym, int modifiers)
binding.command[0].c_str());
continue;
}
if (should_hide_from_mortals(binding.command[0])) {
if (mortal_mode && armok_tools.contains(binding.command[0])) {
DEBUG(keybinding).print("skipping keybinding due to mortal mode (command: '%s')\n",
binding.command[0].c_str());
continue;
Expand Down
15 changes: 15 additions & 0 deletions library/LuaApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4002,6 +4002,19 @@ static int internal_setSuppressDuplicateKeyboardEvents(lua_State *L) {
return 0;
}

static int internal_setMortalMode(lua_State *L) {
bool value = lua_toboolean(L, 1);
Core::getInstance().setMortalMode(value);
return 0;
}

static int internal_setArmokTools(lua_State *L) {
std::vector<string> tool_names;
Lua::GetVector(L, tool_names);
Core::getInstance().setArmokTools(tool_names);
return 0;
}

template<typename T>
static std::map<const char *, T> translate_event_types(const std::unordered_map<int32_t, T> & in_map) {
std::map<const char *, T> out_map;
Expand Down Expand Up @@ -4096,6 +4109,8 @@ static const luaL_Reg dfhack_internal_funcs[] = {
{ "md5File", internal_md5file },
{ "getSuppressDuplicateKeyboardEvents", internal_getSuppressDuplicateKeyboardEvents },
{ "setSuppressDuplicateKeyboardEvents", internal_setSuppressDuplicateKeyboardEvents },
{ "setMortalMode", internal_setMortalMode },
{ "setArmokTools", internal_setArmokTools },
{ "getPerfCounters", internal_getPerfCounters },
{ NULL, NULL }
};
Expand Down
5 changes: 5 additions & 0 deletions library/include/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ distribution.
#include <stack>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <stdint.h>

Expand Down Expand Up @@ -192,6 +193,8 @@ namespace DFHack

bool getSuppressDuplicateKeyboardEvents();
void setSuppressDuplicateKeyboardEvents(bool suppress);
void setMortalMode(bool value);
void setArmokTools(const std::vector<std::string> &tool_names);

bool ClearKeyBindings(std::string keyspec);
bool AddKeyBinding(std::string keyspec, std::string cmdline);
Expand Down Expand Up @@ -285,6 +288,8 @@ namespace DFHack
int8_t modstate;

bool suppress_duplicate_keyboard_events;
bool mortal_mode;
std::unordered_set<std::string> armok_tools;
std::map<int, std::vector<KeyBinding> > key_bindings;
std::string hotkey_cmd;
enum hotkey_set_t {
Expand Down
9 changes: 8 additions & 1 deletion library/lua/dfhack.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,20 @@ dfhack.HIDE_CONSOLE_ON_STARTUP = true
function dfhack.getHideConsoleOnStartup()
return dfhack.HIDE_CONSOLE_ON_STARTUP
end
function dfhack.setHideConsoleOnStartup(value)
dfhack.HIDE_CONSOLE_ON_STARTUP = value
end

dfhack.HIDE_ARMOK_TOOLS = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this intended to be publicly accessible? If not, I would make it local instead of a member of dfhack. If you do want it publicly accessible, you should be aware that it is possible to set this variable without calling setMortalMode(), which would lead to an inconsistent state.

Same goes for HIDE_CONSOLE_ON_STARTUP, although I think the effects are more limited.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was intended to be publicly accessible, but this change makes it unwise to access directly. Now that I've removed references to it (gui/control-panel, docs), it's good to make it local. will make that change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in #4679

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right - I knew it was previously public - was meaning to ask "is this still intended"

---@nodiscard
---@return boolean
function dfhack.getHideArmokTools()
function dfhack.getMortalMode()
return dfhack.HIDE_ARMOK_TOOLS
end
function dfhack.setMortalMode(value)
dfhack.HIDE_ARMOK_TOOLS = value
dfhack.internal.setMortalMode(value)
end

-- Error handling

Expand Down
7 changes: 5 additions & 2 deletions library/lua/helpdb.lua
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ local function ensure_db()
scan_plugins(old_db)
scan_scripts(old_db)
index_tags()
if is_tag('armok') then
dfhack.internal.setArmokTools(get_tag_data('armok'))
end
end

function refresh()
Expand Down Expand Up @@ -795,7 +798,7 @@ function ls(filter_str, skip_tags, show_dev_commands, exclude_strs)
end
if not show_dev_commands then
local dev_tags = {'dev', 'unavailable'}
if filter_str ~= 'armok' and dfhack.getHideArmokTools() then
if filter_str ~= 'armok' and dfhack.getMortalMode() then
table.insert(dev_tags, 'armok')
end
table.insert(excludes, {tag=dev_tags})
Expand Down Expand Up @@ -828,7 +831,7 @@ function tags(tag)
if tag ~= 'unavailable' then
table.insert(excludes.tag, 'unavailable')
end
if tag ~= 'armok' and dfhack.getHideArmokTools() then
if tag ~= 'armok' and dfhack.getMortalMode() then
table.insert(excludes.tag, 'armok')
end

Expand Down
2 changes: 1 addition & 1 deletion plugins/lua/hotkeys.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ end

function should_hide_armok(cmdline)
local command = get_command(cmdline)
return dfhack.getHideArmokTools() and helpdb.has_tag(command, 'armok')
return dfhack.getMortalMode() and helpdb.has_tag(command, 'armok')
end

-- ----------------- --
Expand Down