From 39cc8548ff4db3e18470cccea630da7144563d8f Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Thu, 24 Jul 2025 16:56:06 -0500 Subject: [PATCH] fix mod manager in appdata mode these changes allow the mod manager to work, even in appdata mode, accounting for structure changes in 52.01 --- docs/changelog.txt | 1 + docs/dev/Lua API.rst | 10 ++++++++++ library/LuaApi.cpp | 2 ++ library/LuaTypes.cpp | 3 ++- library/include/modules/Filesystem.h | 5 ++++- library/lua/script-manager.lua | 6 +++--- library/modules/Filesystem.cpp | 19 +++++++++++++++++++ library/modules/Persistence.cpp | 8 +------- 8 files changed, 42 insertions(+), 12 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 750670a79e..24cfa47f03 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -56,6 +56,7 @@ Template for new versions: ## New Features ## Fixes +- several fixes related to changes in file system handling in DF 52.01 ## Misc Improvements - `autoclothing`: added a ``clear`` option to unset previously set orders diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index e810a18440..e2d65d4465 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -3206,6 +3206,16 @@ unless otherwise noted. following it for each entry. Set ``include_prefix`` to false if you don't want the ``path`` string prepended to the returned filenames. +* ``dfhack.filesystem.getBaseDir()`` + + Returns a directory to which DF (and thus DFHack) can save files. This will either + be DF's install directory, or the path returned by ``SDLGetPrefDir``, depending on whether + DF is in "portable mode" or not. + +* ``dfhack.filesystem.getInstallDir()`` + + Returns the the directory in which DF is installed. + Console API ----------- diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 1d3f4075a2..10568f7ea0 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -3159,6 +3159,8 @@ static const LuaWrapper::FunctionReg dfhack_filesystem_module[] = { WRAPM(Filesystem, isdir), WRAPM(Filesystem, mtime), WRAPM(Filesystem, canonicalize), + WRAPM(Filesystem, getInstallDir), + WRAPM(Filesystem, getBaseDir), {NULL, NULL} }; diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 81914a7185..cdacd5ebfe 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -41,6 +41,7 @@ distribution. #include "PluginManager.h" #include "MiscUtils.h" +#include "modules/Filesystem.h" #include #include @@ -191,7 +192,7 @@ void df::stl_string_identity::lua_write(lua_State *state, int fname_idx, void *p void df::path_identity::lua_read(lua_State* state, int fname_idx, void* ptr) const { auto ppath = (std::filesystem::path*)ptr; - auto str = ppath->u8string(); + auto str = DFHack::Filesystem::as_string(*ppath); lua_pushlstring(state, (char*)str.data(), str.size()); } diff --git a/library/include/modules/Filesystem.h b/library/include/modules/Filesystem.h index 7c68983a3a..407579926f 100644 --- a/library/include/modules/Filesystem.h +++ b/library/include/modules/Filesystem.h @@ -75,7 +75,7 @@ namespace DFHack { DFHACK_EXPORT int listdir_recursive(std::filesystem::path dir, std::map& files, int depth = 10, bool include_prefix = true) noexcept; DFHACK_EXPORT std::filesystem::path canonicalize(std::filesystem::path p) noexcept; - inline std::string as_string(std::filesystem::path path) noexcept + inline std::string as_string(const std::filesystem::path path) noexcept { auto pStr = path.string(); if constexpr (std::filesystem::path::preferred_separator != '/') @@ -84,5 +84,8 @@ namespace DFHack { } return pStr; } + DFHACK_EXPORT std::filesystem::path getInstallDir() noexcept; + DFHACK_EXPORT std::filesystem::path getBaseDir() noexcept; + } } diff --git a/library/lua/script-manager.lua b/library/lua/script-manager.lua index 9a1ecb1df0..72b0aae951 100644 --- a/library/lua/script-manager.lua +++ b/library/lua/script-manager.lua @@ -80,8 +80,8 @@ end -- this perhaps could/should be queried from the Steam API -- are there any installation configurations where this will be wrong, though? local WORKSHOP_MODS_PATH = '../../workshop/content/975370/' -local MODS_PATH = 'mods/' -local INSTALLED_MODS_PATH = 'data/installed_mods/' +local MODS_PATH = dfhack.filesystem.getBaseDir() .. 'mods/' +local INSTALLED_MODS_PATH = dfhack.filesystem.getBaseDir() .. 'data/installed_mods/' -- last instance of the same version of the same mod wins, so read them in this -- order (in increasing order of liklihood that players may have made custom @@ -214,7 +214,7 @@ function get_active_mods() local ol = df.global.world.object_loader for idx=0,#ol.object_load_order_id-1 do - local path = ol.object_load_order_src_dir[idx].value + local path = ol.object_load_order_src_dir[idx] table.insert(mods, { id=ol.object_load_order_id[idx].value, name=ol.object_load_order_name[idx].value, diff --git a/library/modules/Filesystem.cpp b/library/modules/Filesystem.cpp index 55a7fd2194..3b1deb67ed 100644 --- a/library/modules/Filesystem.cpp +++ b/library/modules/Filesystem.cpp @@ -51,8 +51,11 @@ SOFTWARE. #include #include +#include "modules/DFSDL.h" #include "modules/Filesystem.h" +#include "df/init.h" + using namespace DFHack; static bool initialized = false; @@ -226,3 +229,19 @@ std::filesystem::path Filesystem::canonicalize(std::filesystem::path p) noexcept return p; } } + +std::filesystem::path Filesystem::getInstallDir() noexcept +{ + return std::filesystem::path{ DFSDL::DFSDL_GetBasePath() }; +} + +std::filesystem::path Filesystem::getBaseDir() noexcept +{ + auto getsavebase = []() { + if (df::global::init->media.flag.is_set(df::enums::init_media_flags::PORTABLE_MODE)) + return DFSDL::DFSDL_GetBasePath(); + else + return DFSDL::DFSDL_GetPrefPath("Bay 12 Games", "Dwarf Fortress"); + }; + return std::filesystem::path{ getsavebase() }; +} diff --git a/library/modules/Persistence.cpp b/library/modules/Persistence.cpp index e2db24d5fd..cd67ff59dc 100644 --- a/library/modules/Persistence.cpp +++ b/library/modules/Persistence.cpp @@ -186,13 +186,7 @@ static std::string filterSaveFileName(std::string s) { } static std::filesystem::path getSavePath(const std::string &world) { - auto getsavebase = []() { - if (df::global::init->media.flag.is_set(df::enums::init_media_flags::PORTABLE_MODE)) - return DFSDL::DFSDL_GetPrefPath("Bay 12 Games", "Dwarf Fortress"); - else - return DFSDL::DFSDL_GetBasePath(); - }; - std::filesystem::path base{ getsavebase() }; + auto base{ Filesystem::getBaseDir() }; return base / "save" / world; }