diff options
Diffstat (limited to 'builtin/mainmenu/pkgmgr.lua')
-rw-r--r-- | builtin/mainmenu/pkgmgr.lua | 119 |
1 files changed, 97 insertions, 22 deletions
diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index 60a496093..f87367689 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -285,17 +285,14 @@ function pkgmgr.identify_modname(modpath,filename) end -------------------------------------------------------------------------------- function pkgmgr.render_packagelist(render_list) - local retval = "" - - if render_list == nil then - if pkgmgr.global_mods == nil then + if not render_list then + if not pkgmgr.global_mods then pkgmgr.refresh_globals() end render_list = pkgmgr.global_mods end local list = render_list:get_list() - local last_modpack = nil local retval = {} for i, v in ipairs(list) do local color = "" @@ -332,11 +329,11 @@ end -------------------------------------------------------------------------------- function pkgmgr.get_dependencies(path) if path == nil then - return "", "" + return {}, {} end local info = core.get_content_info(path) - return table.concat(info.depends or {}, ","), table.concat(info.optional_depends or {}, ",") + return info.depends or {}, info.optional_depends or {} end ----------- tests whether all of the mods in the modpack are enabled ----------- @@ -350,35 +347,113 @@ function pkgmgr.is_modpack_entirely_enabled(data, name) return true end ----------- toggles or en/disables a mod or modpack ----------------------------- +---------- toggles or en/disables a mod or modpack and its dependencies -------- function pkgmgr.enable_mod(this, toset) - local mod = this.data.list:get_list()[this.data.selected_mod] + local list = this.data.list:get_list() + local mod = list[this.data.selected_mod] - -- game mods can't be enabled or disabled + -- Game mods can't be enabled or disabled if mod.is_game_content then return end - -- toggle or en/disable the mod + local toggled_mods = {} + + local enabled_mods = {} if not mod.is_modpack then + -- Toggle or en/disable the mod if toset == nil then - mod.enabled = not mod.enabled - else + toset = not mod.enabled + end + if mod.enabled ~= toset then mod.enabled = toset + toggled_mods[#toggled_mods+1] = mod.name + end + if toset then + -- Mark this mod for recursive dependency traversal + enabled_mods[mod.name] = true + end + else + -- Toggle or en/disable every mod in the modpack, + -- interleaved unsupported + for i = 1, #list do + if list[i].modpack == mod.name then + if toset == nil then + toset = not list[i].enabled + end + if list[i].enabled ~= toset then + list[i].enabled = toset + toggled_mods[#toggled_mods+1] = list[i].name + end + if toset then + enabled_mods[list[i].name] = true + end + end end + end + if not toset then + -- Mod(s) were disabled, so no dependencies need to be enabled + table.sort(toggled_mods) + minetest.log("info", "Following mods were disabled: " .. + table.concat(toggled_mods, ", ")) return end - -- toggle or en/disable every mod in the modpack, interleaved unsupported - local list = this.data.list:get_raw_list() - for i = 1, #list do - if list[i].modpack == mod.name then - if toset == nil then - toset = not list[i].enabled + -- Enable mods' depends after activation + + -- Make a list of mod ids indexed by their names + local mod_ids = {} + for id, mod in pairs(list) do + if mod.type == "mod" and not mod.is_modpack then + mod_ids[mod.name] = id + end + end + + -- to_enable is used as a DFS stack with sp as stack pointer + local to_enable = {} + local sp = 0 + for name in pairs(enabled_mods) do + local depends = pkgmgr.get_dependencies(list[mod_ids[name]].path) + for i = 1, #depends do + local dependency_name = depends[i] + if not enabled_mods[dependency_name] then + sp = sp+1 + to_enable[sp] = dependency_name + end + end + end + -- If sp is 0, every dependency is already activated + while sp > 0 do + local name = to_enable[sp] + sp = sp-1 + + if not enabled_mods[name] then + enabled_mods[name] = true + local mod = list[mod_ids[name]] + if not mod then + minetest.log("warning", "Mod dependency \"" .. name .. + "\" not found!") + else + if mod.enabled == false then + mod.enabled = true + toggled_mods[#toggled_mods+1] = mod.name + end + -- Push the dependencies of the dependency onto the stack + local depends = pkgmgr.get_dependencies(mod.path) + for i = 1, #depends do + if not enabled_mods[name] then + sp = sp+1 + to_enable[sp] = depends[i] + end + end end - list[i].enabled = toset end end + + -- Log the list of enabled mods + table.sort(toggled_mods) + minetest.log("info", "Following mods were enabled: " .. + table.concat(toggled_mods, ", ")) end -------------------------------------------------------------------------------- @@ -465,7 +540,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath) else return nil, fgettext("Install Mod: Unable to find suitable folder name for modpack $1", - modfilename) + path) end end elseif basefolder.type == "mod" then @@ -490,7 +565,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath) if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder else - return nil, fgettext("Install Mod: Unable to find real mod name for: $1", modfilename) + return nil, fgettext("Install Mod: Unable to find real mod name for: $1", path) end end |