--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
+local function get_last_folder(text,count)
+ local parts = text:split(DIR_DELIM)
+
+ if count == nil then
+ return parts[#parts]
+ end
+
+ local retval = ""
+ for i=1,count,1 do
+ retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
+ end
+
+ return retval
+end
+
+local function cleanup_path(temppath)
+
+ local parts = temppath:split("-")
+ temppath = ""
+ for i=1,#parts,1 do
+ if temppath ~= "" then
+ temppath = temppath .. "_"
+ end
+ temppath = temppath .. parts[i]
+ end
+
+ parts = temppath:split(".")
+ temppath = ""
+ for i=1,#parts,1 do
+ if temppath ~= "" then
+ temppath = temppath .. "_"
+ end
+ temppath = temppath .. parts[i]
+ end
+
+ parts = temppath:split("'")
+ temppath = ""
+ for i=1,#parts,1 do
+ if temppath ~= "" then
+ temppath = temppath .. ""
+ end
+ temppath = temppath .. parts[i]
+ end
+
+ parts = temppath:split(" ")
+ temppath = ""
+ for i=1,#parts,1 do
+ if temppath ~= "" then
+ temppath = temppath
+ end
+ temppath = temppath .. parts[i]
+ end
+
+ return temppath
+end
+
+local function load_texture_packs(txtpath, retval)
+ local list = core.get_dir_list(txtpath, true)
+ local current_texture_path = core.settings:get("texture_path")
+
+ for _, item in ipairs(list) do
+ if item ~= "base" then
+ local name = item
+
+ local path = txtpath .. DIR_DELIM .. item .. DIR_DELIM
+ if path == current_texture_path then
+ name = fgettext("$1 (Enabled)", name)
+ end
+
+ local conf = Settings(path .. "texture_pack.conf")
+
+ retval[#retval + 1] = {
+ name = item,
+ author = conf:get("author"),
+ release = tonumber(conf:get("release")) or 0,
+ list_name = name,
+ type = "txp",
+ path = path,
+ enabled = path == current_texture_path,
+ }
+ end
+ end
+end
+
function get_mods(path,retval,modpack)
local mods = core.get_dir_list(path, true)
-- Read from config
toadd.name = name
toadd.author = mod_conf.author
- toadd.release = tonumber(mod_conf.release or "0")
+ toadd.release = tonumber(mod_conf.release) or 0
toadd.path = prefix
toadd.type = "mod"
-- Check modpack.txt
- -- Note: modpack.conf is already checked above
+ -- Note: modpack.conf is already checked above
local modpackfile = io.open(prefix .. DIR_DELIM .. "modpack.txt")
if modpackfile then
modpackfile:close()
function pkgmgr.get_texture_packs()
local txtpath = core.get_texturepath()
- local list = core.get_dir_list(txtpath, true)
+ local txtpath_system = core.get_texturepath_share()
local retval = {}
- local current_texture_path = core.settings:get("texture_path")
-
- for _, item in ipairs(list) do
- if item ~= "base" then
- local name = item
-
- local path = txtpath .. DIR_DELIM .. item .. DIR_DELIM
- if path == current_texture_path then
- name = fgettext("$1 (Enabled)", name)
- end
-
- local conf = Settings(path .. "texture_pack.conf")
-
- retval[#retval + 1] = {
- name = item,
- author = conf:get("author"),
- release = tonumber(conf:get("release") or "0"),
- list_name = name,
- type = "txp",
- path = path,
- enabled = path == current_texture_path,
- }
- end
+ load_texture_packs(txtpath, retval)
+ -- on portable versions these two paths coincide. It avoids loading the path twice
+ if txtpath ~= txtpath_system then
+ load_texture_packs(txtpath_system, retval)
end
table.sort(retval, function(a, b)
end
--------------------------------------------------------------------------------
-function pkgmgr.extract(modfile)
- if modfile.type == "zip" then
- local tempfolder = os.tempfolder()
-
- if tempfolder ~= nil and
- tempfolder ~= "" then
- core.create_dir(tempfolder)
- if core.extract_zip(modfile.name,tempfolder) then
- return tempfolder
- end
- end
- end
- return nil
-end
-
function pkgmgr.get_folder_type(path)
local testfile = io.open(path .. DIR_DELIM .. "init.lua","r")
if testfile ~= nil then
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 = ""
return true
end
----------- toggles or en/disables a mod or modpack -----------------------------
+---------- toggles or en/disables a mod or modpack and its dependencies --------
+local function toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mod)
+ if not mod.is_modpack then
+ -- Toggle or en/disable the mod
+ if toset == nil then
+ 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
+ toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, list[i])
+ end
+ end
+ end
+end
+
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
- if not mod.is_modpack then
- if toset == nil then
- mod.enabled = not mod.enabled
- else
- mod.enabled = toset
- end
+ local toggled_mods = {}
+ local enabled_mods = {}
+ toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mod)
+
+ if not toset then
+ -- Mod(s) were disabled, so no dependencies need to be enabled
+ table.sort(toggled_mods)
+ core.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, mod2 in pairs(list) do
+ if mod2.type == "mod" and not mod2.is_modpack then
+ mod_ids[mod2.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
- list[i].enabled = toset
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_to_enable = list[mod_ids[name]]
+ if not mod_to_enable then
+ core.log("warning", "Mod dependency \"" .. name ..
+ "\" not found!")
+ else
+ if mod_to_enable.enabled == false then
+ mod_to_enable.enabled = true
+ toggled_mods[#toggled_mods+1] = mod_to_enable.name
+ end
+ -- Push the dependencies of the dependency onto the stack
+ local depends = pkgmgr.get_dependencies(mod_to_enable.path)
+ for i = 1, #depends do
+ if not enabled_mods[name] then
+ sp = sp+1
+ to_enable[sp] = depends[i]
+ end
+ end
+ end
+ end
+ end
+
+ -- Log the list of enabled mods
+ table.sort(toggled_mods)
+ core.log("info", "Following mods were enabled: " ..
+ table.concat(toggled_mods, ", "))
end
--------------------------------------------------------------------------------
local from = basefolder and basefolder.path or path
if targetpath then
core.delete_dir(targetpath)
- core.create_dir(targetpath)
else
targetpath = core.get_texturepath() .. DIR_DELIM .. basename
end
- if not core.copy_dir(from, targetpath) then
+ if not core.copy_dir(from, targetpath, false) then
return nil,
fgettext("Failed to install $1 to $2", basename, targetpath)
end
-- Get destination name for modpack
if targetpath then
core.delete_dir(targetpath)
- core.create_dir(targetpath)
else
local clean_path = nil
if basename ~= nil then
else
return nil,
fgettext("Install Mod: Unable to find suitable folder name for modpack $1",
- modfilename)
+ path)
end
end
elseif basefolder.type == "mod" then
if targetpath then
core.delete_dir(targetpath)
- core.create_dir(targetpath)
else
local targetfolder = basename
if targetfolder == nil then
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
if targetpath then
core.delete_dir(targetpath)
- core.create_dir(targetpath)
else
targetpath = core.get_gamepath() .. DIR_DELIM .. basename
end
end
-- Copy it
- if not core.copy_dir(basefolder.path, targetpath) then
+ if not core.copy_dir(basefolder.path, targetpath, false) then
return nil,
fgettext("Failed to install $1 to $2", basename, targetpath)
end
return targetpath, nil
end
---------------------------------------------------------------------------------
-function pkgmgr.install(type, modfilename, basename, dest)
- local archive_info = pkgmgr.identify_filetype(modfilename)
- local path = pkgmgr.extract(archive_info)
-
- if path == nil then
- return nil,
- fgettext("Install: file: \"$1\"", archive_info.name) .. "\n" ..
- fgettext("Install: Unsupported file type \"$1\" or broken archive",
- archive_info.type)
- end
-
- local targetpath, msg = pkgmgr.install_dir(type, path, basename, dest)
- core.delete_dir(path)
- return targetpath, msg
-end
-
--------------------------------------------------------------------------------
function pkgmgr.preparemodlist(data)
local retval = {}
local game_mods = {}
--read global mods
- local modpath = core.get_modpath()
-
- if modpath ~= nil and
- modpath ~= "" then
- get_mods(modpath,global_mods)
+ local modpaths = core.get_modpaths()
+ for _, modpath in ipairs(modpaths) do
+ get_mods(modpath, global_mods)
end
for i=1,#global_mods,1 do
pkgmgr.global_mods:set_sortmode("alphabetic")
end
---------------------------------------------------------------------------------
-function pkgmgr.identify_filetype(name)
-
- if name:sub(-3):lower() == "zip" then
- return {
- name = name,
- type = "zip"
- }
- end
-
- if name:sub(-6):lower() == "tar.gz" or
- name:sub(-3):lower() == "tgz"then
- return {
- name = name,
- type = "tgz"
- }
- end
-
- if name:sub(-6):lower() == "tar.bz2" then
- return {
- name = name,
- type = "tbz"
- }
- end
-
- if name:sub(-2):lower() == "7z" then
- return {
- name = name,
- type = "7z"
- }
- end
-
- return {
- name = name,
- type = "ukn"
- }
-end
-
-
--------------------------------------------------------------------------------
function pkgmgr.find_by_gameid(gameid)
for i=1,#pkgmgr.games,1 do