aboutsummaryrefslogtreecommitdiff
path: root/builtin/mainmenu/pkgmgr.lua
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/mainmenu/pkgmgr.lua')
-rw-r--r--builtin/mainmenu/pkgmgr.lua119
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