diff --git a/changelog.txt b/changelog.txt index 2b0db42d7..bcf188da2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -32,6 +32,7 @@ Template for new versions: - `gui/mod-manager`: now supports arena mode ## Fixes +- `gui/mod-manager`: hide other versions of loaded mods and unhides them when unloaded - `gui/mod-manager`: gracefully handle vanilla mods with different versions from the user's preset ## Misc Improvements diff --git a/gui/mod-manager.lua b/gui/mod-manager.lua index 12029661b..a3a745963 100644 --- a/gui/mod-manager.lua +++ b/gui/mod-manager.lua @@ -72,9 +72,9 @@ function get_modlist_fields(kind, viewscreen) end end ----@return boolean # true if the mod entry was moved; false if the mod or mod version was not found. +---@return boolean # true if the mod entry was copied over; false if the mod or mod version was not found. ---@return string|nil # loaded version - DISPLAYED_VERSION from the mod's info.txt -local function move_mod_entry(viewscreen, to, from, mod_id, mod_version) +local function copy_mod_entry(viewscreen, to, from, mod_id, mod_version) local to_fields = get_modlist_fields(to, viewscreen) local from_fields = get_modlist_fields(from, viewscreen) @@ -106,23 +106,49 @@ local function move_mod_entry(viewscreen, to, from, mod_id, mod_version) end end - for _, v in pairs(from_fields) do - v:erase(mod_index) - end - return true, loaded_version end ----@return boolean # true if the mod entry was moved; false if the mod or mod version was not found. +---@return boolean # true if the mod entry was copied over; false if the mod or mod version was not found. ---@return string|nil # loaded version - DISPLAYED_VERSION from the mod's info.txt local function enable_mod(viewscreen, mod_id, mod_version) - return move_mod_entry(viewscreen, "object_load_order", "available", mod_id, mod_version) + return copy_mod_entry(viewscreen, "object_load_order", "base_available", mod_id, mod_version) end ----@return boolean # true if the mod entry was moved; false if the mod or mod version was not found. +---@return boolean # true if the mod entry was copied over; false if the mod or mod version was not found. ---@return string|nil # loaded version - DISPLAYED_VERSION from the mod's info.txt -local function disable_mod(viewscreen, mod_id, mod_version) - return move_mod_entry(viewscreen, "available", "object_load_order", mod_id, mod_version) +local function make_available_mod(viewscreen, mod_id, mod_version) + return copy_mod_entry(viewscreen, "available", "base_available", mod_id, mod_version) +end + +local function clear_mods(viewscreen) + local active_modlist = get_modlist_fields('object_load_order', viewscreen) + local avail_modlist = get_modlist_fields('available', viewscreen) + for _, modlist in ipairs({active_modlist, avail_modlist}) do + for _, v in pairs(modlist) do + for i = #v - 1, 0, -1 do + v:erase(i) + end + end + end +end + +local function set_available_mods(viewscreen, loaded) + local base_avail = get_modlist_fields('base_available', viewscreen) + local unused = {} + for i, id in ipairs(base_avail.id) do + if not loaded[id.value] then + local version = base_avail.numeric_version[i] + table.insert(unused, { id= id.value, version= version }) + end + end + + for _, v in ipairs(unused) do + local success, _ = make_available_mod(viewscreen, v.id, v.version) + if not success then + dfhack.printerr('failed to show '..v.id..' in available list') + end + end end local function get_active_modlist(viewscreen) @@ -138,21 +164,24 @@ end --- @return string[] --- @return { id: string, new: string }[] local function swap_modlist(viewscreen, modlist) - local current = get_active_modlist(viewscreen) - for _, v in ipairs(current) do - disable_mod(viewscreen, v.id, v.version) - end + clear_mods(viewscreen) local failures = {} local changed = {} + local loaded = {} for _, v in ipairs(modlist) do local success, version = enable_mod(viewscreen, v.id, v.version) if not success then table.insert(failures, v.id) - elseif version then - table.insert(changed, { id= v.id, new= version }) + else + if version then + table.insert(changed, { id= v.id, new= version }) + end + loaded[v.id] = true end end + + set_available_mods(viewscreen, loaded) return failures, changed end