From 9f41b4f72d45b0ad1f9de2dfc28e426a2d05f137 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 7 May 2022 16:45:17 +0100 Subject: Add check_mod_configuration to main menu --- builtin/mainmenu/dlg_config_world.lua | 89 +++++++++++++++++++++++++++++++++-- builtin/mainmenu/init.lua | 1 + builtin/mainmenu/pkgmgr.lua | 55 ++++++++++++++++++---- 3 files changed, 133 insertions(+), 12 deletions(-) (limited to 'builtin/mainmenu') diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index f73256612..e76e10ef7 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -61,12 +61,68 @@ local function init_data(data) data.list:set_sortmode("alphabetic") end + +-- Returns errors errors and a list of all enabled mods (inc. game and world mods) +-- +-- `with_errors` is a table from mod virtual path to `{ type = "error" | "warning" }`. +-- `enabled_mods_by_name` is a table from mod virtual path to `true`. +-- +-- @param world_path Path to the world +-- @param all_mods List of mods, with `enabled` property. +-- @returns with_errors, enabled_mods_by_name +local function check_mod_configuration(world_path, all_mods) + -- Build up lookup tables for enabled mods and all mods by vpath + local enabled_mod_paths = {} + local all_mods_by_vpath = {} + for _, mod in ipairs(all_mods) do + if mod.type == "mod" then + all_mods_by_vpath[mod.virtual_path] = mod + end + if mod.enabled then + enabled_mod_paths[mod.virtual_path] = mod.path + end + end + + -- Use the engine's mod configuration code to resolve dependencies and return any errors + local config_status = core.check_mod_configuration(world_path, enabled_mod_paths) + + -- Build the list of enabled mod virtual paths + local enabled_mods_by_name = {} + for _, mod in ipairs(config_status.satisfied_mods) do + assert(mod.virtual_path ~= "") + enabled_mods_by_name[mod.name] = all_mods_by_vpath[mod.virtual_path] or mod + end + for _, mod in ipairs(config_status.unsatisfied_mods) do + assert(mod.virtual_path ~= "") + enabled_mods_by_name[mod.name] = all_mods_by_vpath[mod.virtual_path] or mod + end + + -- Build the table of errors + local with_error = {} + for _, mod in ipairs(config_status.unsatisfied_mods) do + local error = { type = "warning" } + with_error[mod.virtual_path] = error + + for _, depname in ipairs(mod.unsatisfied_depends) do + if not enabled_mods_by_name[depname] then + error.type = "error" + break + end + end + end + + return with_error, enabled_mods_by_name +end + local function get_formspec(data) if not data.list then init_data(data) end - local mod = data.list:get_list()[data.selected_mod] or {name = ""} + local all_mods = data.list:get_list() + local with_error, enabled_mods_by_name = check_mod_configuration(data.worldspec.path, all_mods) + + local mod = all_mods[data.selected_mod] or {name = ""} local retval = "size[11.5,7.5,true]" .. @@ -87,6 +143,29 @@ local function get_formspec(data) "textarea[0.25,0.7;5.75,7.2;;" .. info .. ";]" else local hard_deps, soft_deps = pkgmgr.get_dependencies(mod.path) + + -- Add error messages to dep lists + if mod.enabled or mod.is_game_content then + for i, dep_name in ipairs(hard_deps) do + local dep = enabled_mods_by_name[dep_name] + if not dep then + hard_deps[i] = mt_color_red .. dep_name .. " " .. fgettext("(Unsatisfied)") + elseif with_error[dep.virtual_path] then + hard_deps[i] = mt_color_orange .. dep_name .. " " .. fgettext("(Enabled, has error)") + else + hard_deps[i] = mt_color_green .. dep_name + end + end + for i, dep_name in ipairs(soft_deps) do + local dep = enabled_mods_by_name[dep_name] + if dep and with_error[dep.virtual_path] then + soft_deps[i] = mt_color_orange .. dep_name .. " " .. fgettext("(Enabled, has error)") + elseif dep then + soft_deps[i] = mt_color_green .. dep_name + end + end + end + local hard_deps_str = table.concat(hard_deps, ",") local soft_deps_str = table.concat(soft_deps, ",") @@ -138,7 +217,6 @@ local function get_formspec(data) if mod.name ~= "" and not mod.is_game_content then if mod.is_modpack then - if pkgmgr.is_modpack_entirely_enabled(data, mod.name) then retval = retval .. "button[5.5,0.125;3,0.5;btn_mp_disable;" .. @@ -167,9 +245,12 @@ local function get_formspec(data) local use_technical_names = core.settings:get_bool("show_technical_names") return retval .. - "tablecolumns[color;tree;text]" .. + "tablecolumns[color;tree;image,align=inline,width=1.5,0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. + ",1=" .. core.formspec_escape(defaulttexturedir .. "checkbox_16_white.png") .. + ",2=" .. core.formspec_escape(defaulttexturedir .. "error_icon_orange.png") .. + ",3=" .. core.formspec_escape(defaulttexturedir .. "error_icon_red.png") .. ";text]" .. "table[5.5,0.75;5.75,6;world_config_modlist;" .. - pkgmgr.render_packagelist(data.list, use_technical_names) .. ";" .. data.selected_mod .."]" + pkgmgr.render_packagelist(data.list, use_technical_names, with_error) .. ";" .. data.selected_mod .."]" end local function handle_buttons(this, fields) diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index d073f5a57..f890765fa 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -21,6 +21,7 @@ mt_color_lightblue = "#99CCFF" mt_color_green = "#72FF63" mt_color_dark_green = "#25C191" mt_color_orange = "#FF8800" +mt_color_red = "#FF3300" local menupath = core.get_mainmenu_path() local basepath = core.get_builtin_path() diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index b2f3243c4..32a65fd08 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -337,7 +337,7 @@ function pkgmgr.identify_modname(modpath,filename) return nil end -------------------------------------------------------------------------------- -function pkgmgr.render_packagelist(render_list, use_technical_names) +function pkgmgr.render_packagelist(render_list, use_technical_names, with_error) if not render_list then if not pkgmgr.global_mods then pkgmgr.refresh_globals() @@ -349,24 +349,59 @@ function pkgmgr.render_packagelist(render_list, use_technical_names) local retval = {} for i, v in ipairs(list) do local color = "" + local icon = 0 + local error = with_error and with_error[v.virtual_path] + local function update_error(val) + if val and (not error or (error.type == "warning" and val.type == "error")) then + error = val + end + end + if v.is_modpack then local rawlist = render_list:get_raw_list() color = mt_color_dark_green - for j = 1, #rawlist, 1 do - if rawlist[j].modpack == list[i].name and - not rawlist[j].enabled then - -- Modpack not entirely enabled so showing as grey - color = mt_color_grey - break + for j = 1, #rawlist do + if rawlist[j].modpack == list[i].name then + if with_error then + update_error(with_error[rawlist[j].virtual_path]) + end + + if rawlist[j].enabled then + icon = 1 + else + -- Modpack not entirely enabled so showing as grey + color = mt_color_grey + end end end elseif v.is_game_content or v.type == "game" then + icon = 1 color = mt_color_blue + + local rawlist = render_list:get_raw_list() + if v.type == "game" and with_error then + for j = 1, #rawlist do + if rawlist[j].is_game_content then + update_error(with_error[rawlist[j].virtual_path]) + end + end + end elseif v.enabled or v.type == "txp" then + icon = 1 color = mt_color_green end + if error then + if error.type == "warning" then + color = mt_color_orange + icon = 2 + else + color = mt_color_red + icon = 3 + end + end + retval[#retval + 1] = color if v.modpack ~= nil or v.loc == "game" then retval[#retval + 1] = "1" @@ -374,6 +409,10 @@ function pkgmgr.render_packagelist(render_list, use_technical_names) retval[#retval + 1] = "0" end + if with_error then + retval[#retval + 1] = icon + end + if use_technical_names then retval[#retval + 1] = core.formspec_escape(v.list_name or v.name) else @@ -503,7 +542,7 @@ function pkgmgr.enable_mod(this, toset) if not mod_to_enable then core.log("warning", "Mod dependency \"" .. name .. "\" not found!") - else + elseif not mod_to_enable.is_game_content then if not mod_to_enable.enabled then mod_to_enable.enabled = true toggled_mods[#toggled_mods+1] = mod_to_enable.name -- cgit v1.2.3