From bc3dccca5c66019dfbd218f39f086f7384f97d88 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 12 Sep 2022 19:24:54 +0200 Subject: [PATCH] Mainmenu: Properly sort mods and games (#12758) This also removes trivial and unused pkgmgr functions Fixes a bug caused by sorting in 2133fc8 --- builtin/common/misc_helpers.lua | 12 --- builtin/mainmenu/dlg_config_world.lua | 3 +- builtin/mainmenu/dlg_contentstore.lua | 25 +++--- builtin/mainmenu/dlg_create_world.lua | 10 +-- builtin/mainmenu/dlg_settings_advanced.lua | 11 +-- builtin/mainmenu/pkgmgr.lua | 99 +++++----------------- doc/menu_lua_api.txt | 8 +- src/script/lua_api/l_mainmenu.cpp | 13 +-- 8 files changed, 54 insertions(+), 127 deletions(-) diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 467f18804..720df3998 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -519,18 +519,6 @@ end -------------------------------------------------------------------------------- -- mainmenu only functions -------------------------------------------------------------------------------- -if INIT == "mainmenu" then - function core.get_game(index) - local games = core.get_games() - - if index > 0 and index <= #games then - return games[index] - end - - return nil - end -end - if core.gettext then -- for client and mainmenu function fgettext_ne(text, ...) text = core.gettext(text) diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index e76e10ef7..9a5562a57 100644 --- a/builtin/mainmenu/dlg_config_world.lua +++ b/builtin/mainmenu/dlg_config_world.lua @@ -57,8 +57,7 @@ local function init_data(data) hide_game = data.hide_gamemods, hide_modpackcontents = data.hide_modpackcontents }) - data.list:add_sort_mechanism("alphabetic", sort_mod_list) - data.list:set_sortmode("alphabetic") + -- Sorting is already done by pgkmgr.get_mods end diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 32054fae3..b599cd075 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -346,22 +346,21 @@ end local install_dialog = {} function install_dialog.get_formspec() + local selected_game, selected_game_idx = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) + if not selected_game_idx then + selected_game_idx = 1 + selected_game = pkgmgr.games[1] + end + + local game_list = {} + for i, game in ipairs(pkgmgr.games) do + game_list[i] = core.formspec_escape(game[i].title) + end + local package = install_dialog.package local raw_deps = install_dialog.raw_deps local will_install_deps = install_dialog.will_install_deps - local selected_game_idx = 1 - local selected_gameid = core.settings:get("menu_last_game") - local games = table.copy(pkgmgr.games) - for i=1, #games do - if selected_gameid and games[i].id == selected_gameid then - selected_game_idx = i - end - - games[i] = core.formspec_escape(games[i].title) - end - - local selected_game = pkgmgr.games[selected_game_idx] local deps_to_install = 0 local deps_not_found = 0 @@ -408,7 +407,7 @@ function install_dialog.get_formspec() "container[0.375,0.70]", "label[0,0.25;", fgettext("Base Game:"), "]", - "dropdown[2,0;4.25,0.5;selected_game;", table.concat(games, ","), ";", selected_game_idx, "]", + "dropdown[2,0;4.25,0.5;selected_game;", table.concat(game_list, ","), ";", selected_game_idx, "]", "label[0,0.8;", fgettext("Dependencies:"), "]", diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 806e019a9..2f3ef596c 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -104,14 +104,12 @@ local function create_world_formspec(dialogdata) local current_mg = dialogdata.mg local mapgens = core.get_mapgen_names() - local gameid = core.settings:get("menu_last_game") - local flags = dialogdata.flags - local game = pkgmgr.find_by_gameid(gameid) + local game = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) if game == nil then -- should never happen but just pick the first game - game = pkgmgr.get_game(1) + game = pkgmgr.games[1] core.settings:set("menu_last_game", game.id) end @@ -355,7 +353,7 @@ local function create_world_buttonhandler(this, fields) fields["key_enter"] then local worldname = fields["te_world_name"] - local game, gameindex = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) + local game, _ = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) local message if game == nil then @@ -399,7 +397,7 @@ local function create_world_buttonhandler(this, fields) mgvalleys_spflags = table_to_flags(this.data.flags.valleys), mgflat_spflags = table_to_flags(this.data.flags.flat), } - message = core.create_world(worldname, gameindex, settings) + message = core.create_world(worldname, game.id, settings) end if message == nil then diff --git a/builtin/mainmenu/dlg_settings_advanced.lua b/builtin/mainmenu/dlg_settings_advanced.lua index 69562e6a5..32c051c26 100644 --- a/builtin/mainmenu/dlg_settings_advanced.lua +++ b/builtin/mainmenu/dlg_settings_advanced.lua @@ -344,9 +344,7 @@ local function parse_config_file(read_all, parse_mods) if parse_mods then -- Parse games local games_category_initialized = false - local index = 1 - local game = pkgmgr.get_game(index) - while game do + for _, game in ipairs(pkgmgr.games) do local path = game.path .. DIR_DELIM .. FILENAME local file = io.open(path, "r") if file then @@ -370,15 +368,12 @@ local function parse_config_file(read_all, parse_mods) file:close() end - - index = index + 1 - game = pkgmgr.get_game(index) end -- Parse mods local mods_category_initialized = false local mods = {} - get_mods(core.get_modpath(), "mods", mods) + pkgmgr.get_mods(core.get_modpath(), "mods", mods) for _, mod in ipairs(mods) do local path = mod.path .. DIR_DELIM .. FILENAME local file = io.open(path, "r") @@ -409,7 +404,7 @@ local function parse_config_file(read_all, parse_mods) -- Parse client mods local clientmods_category_initialized = false local clientmods = {} - get_mods(core.get_clientmodpath(), "clientmods", clientmods) + pkgmgr.get_mods(core.get_clientmodpath(), "clientmods", clientmods) for _, mod in ipairs(clientmods) do local path = mod.path .. DIR_DELIM .. FILENAME local file = io.open(path, "r") diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index 384870ae1..51f635962 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -100,7 +100,15 @@ local function load_texture_packs(txtpath, retval) end end -function get_mods(path, virtual_path, retval, modpack) +--modmanager implementation +pkgmgr = {} + +--- Scans a directory recursively for mods and adds them to `listing` +-- @param path Absolute directory path to scan recursively +-- @param virtual_path Prettified unique path (e.g. "mods", "mods/mt_modpack") +-- @param listing Input. Flat array to insert located mods and modpacks +-- @param modpack Currently processing modpack or nil/"" if none (recursion) +function pkgmgr.get_mods(path, virtual_path, listing, modpack) local mods = core.get_dir_list(path, true) for _, name in ipairs(mods) do @@ -111,7 +119,7 @@ function get_mods(path, virtual_path, retval, modpack) dir_name = name, parent_dir = path, } - retval[#retval + 1] = toadd + listing[#listing + 1] = toadd -- Get config file local mod_conf @@ -156,14 +164,18 @@ function get_mods(path, virtual_path, retval, modpack) elseif toadd.is_modpack then toadd.type = "modpack" toadd.is_modpack = true - get_mods(mod_path, mod_virtual_path, retval, name) + pkgmgr.get_mods(mod_path, mod_virtual_path, listing, name) end end end -end ---modmanager implementation -pkgmgr = {} + if not modpack then + -- Sort all when the recursion is done + table.sort(listing, function(a, b) + return a.virtual_path:lower() < b.virtual_path:lower() + end) + end +end function pkgmgr.get_texture_packs() local txtpath = core.get_texturepath() @@ -593,7 +605,7 @@ function pkgmgr.preparemodlist(data) --read global mods local modpaths = core.get_modpaths() for key, modpath in pairs(modpaths) do - get_mods(modpath, key, global_mods) + pkgmgr.get_mods(modpath, key, global_mods) end for i=1,#global_mods,1 do @@ -700,35 +712,6 @@ function pkgmgr.comparemod(elem1,elem2) return true end --------------------------------------------------------------------------------- -function pkgmgr.mod_exists(basename) - - if pkgmgr.global_mods == nil then - pkgmgr.refresh_globals() - end - - if pkgmgr.global_mods:raw_index_by_uid(basename) > 0 then - return true - end - - return false -end - --------------------------------------------------------------------------------- -function pkgmgr.get_global_mod(idx) - - if pkgmgr.global_mods == nil then - return nil - end - - if idx == nil or idx < 1 or - idx > pkgmgr.global_mods:size() then - return nil - end - - return pkgmgr.global_mods:get_list()[idx] -end - -------------------------------------------------------------------------------- function pkgmgr.refresh_globals() local function is_equal(element,uid) --uid match @@ -744,9 +727,9 @@ end -------------------------------------------------------------------------------- function pkgmgr.find_by_gameid(gameid) - for i=1,#pkgmgr.games,1 do - if pkgmgr.games[i].id == gameid then - return pkgmgr.games[i], i + for i, game in ipairs(pkgmgr.games) do + if game.id == gameid then + return game, i end end return nil, nil @@ -757,33 +740,10 @@ function pkgmgr.get_game_mods(gamespec, retval) if gamespec ~= nil and gamespec.gamemods_path ~= nil and gamespec.gamemods_path ~= "" then - get_mods(gamespec.gamemods_path, ("games/%s/mods"):format(gamespec.id), retval) + pkgmgr.get_mods(gamespec.gamemods_path, ("games/%s/mods"):format(gamespec.id), retval) end end --------------------------------------------------------------------------------- -function pkgmgr.get_game_modlist(gamespec) - local retval = "" - local game_mods = {} - pkgmgr.get_game_mods(gamespec, game_mods) - for i=1,#game_mods,1 do - if retval ~= "" then - retval = retval.."," - end - retval = retval .. game_mods[i].name - end - return retval -end - --------------------------------------------------------------------------------- -function pkgmgr.get_game(index) - if index > 0 and index <= #pkgmgr.games then - return pkgmgr.games[index] - end - - return nil -end - -------------------------------------------------------------------------------- function pkgmgr.update_gamelist() pkgmgr.games = core.get_games() @@ -792,19 +752,6 @@ function pkgmgr.update_gamelist() end) end --------------------------------------------------------------------------------- -function pkgmgr.gamelist() - local retval = "" - if #pkgmgr.games > 0 then - retval = retval .. core.formspec_escape(pkgmgr.games[1].title) - - for i=2,#pkgmgr.games,1 do - retval = retval .. "," .. core.formspec_escape(pkgmgr.games[i].title) - end - end - return retval -end - -------------------------------------------------------------------------------- -- read initial data -------------------------------------------------------------------------------- diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index a7722be6e..7c820b0cd 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -247,9 +247,9 @@ Package - content which is downloadable from the content db, may or may not be i * returns path to global gamepath * core.get_texturepath() (possible in async calls) * returns path to default textures -* core.get_game(index) +* core.get_games() -> table of all games (possible in async calls) * `name` in return value is deprecated, use `title` instead. - * returns: + * returns a table (ipairs) with values: { id = , @@ -261,8 +261,6 @@ Package - content which is downloadable from the content db, may or may not be i DEPRECATED: addon_mods_paths = {[1] = ,}, } - -* core.get_games() -> table of all games in upper format (possible in async calls) * core.get_content_info(path) * returns @@ -323,7 +321,7 @@ core.get_worlds() -> list of worlds (possible in async calls) gameid = , }, } -core.create_world(worldname, gameid) +core.create_world(worldname, gameid, init_settings) core.delete_world(index) diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index cf4a057e1..789096d23 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -522,8 +522,8 @@ int ModApiMainMenu::l_show_keys_menu(lua_State *L) /******************************************************************************/ int ModApiMainMenu::l_create_world(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - int gameidx = luaL_checkinteger(L,2) -1; + const char *name = luaL_checkstring(L, 1); + const char *gameid = luaL_checkstring(L, 2); StringMap use_settings; luaL_checktype(L, 3, LUA_TTABLE); @@ -540,8 +540,11 @@ int ModApiMainMenu::l_create_world(lua_State *L) + sanitizeDirName(name, "world_"); std::vector games = getAvailableGames(); - if (gameidx < 0 || gameidx >= (int) games.size()) { - lua_pushstring(L, "Invalid game index"); + auto game_it = std::find_if(games.begin(), games.end(), [gameid] (const SubgameSpec &spec) { + return spec.id == gameid; + }); + if (game_it == games.end()) { + lua_pushstring(L, "Game ID not found"); return 1; } @@ -556,7 +559,7 @@ int ModApiMainMenu::l_create_world(lua_State *L) // Create world if it doesn't exist try { - loadGameConfAndInitWorld(path, name, games[gameidx], true); + loadGameConfAndInitWorld(path, name, *game_it, true); lua_pushnil(L); } catch (const BaseException &e) { auto err = std::string("Failed to initialize world: ") + e.what();