diff options
Diffstat (limited to 'builtin/mainmenu')
-rw-r--r-- | builtin/mainmenu/common.lua | 18 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_config_world.lua | 117 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_contentstore.lua | 28 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_create_world.lua | 89 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_delete_content.lua | 13 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_delete_world.lua | 12 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_register.lua | 123 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_settings_advanced.lua | 105 | ||||
-rw-r--r-- | builtin/mainmenu/dlg_version_info.lua | 172 | ||||
-rw-r--r-- | builtin/mainmenu/generate_from_settingtypes.lua | 17 | ||||
-rw-r--r-- | builtin/mainmenu/init.lua | 7 | ||||
-rw-r--r-- | builtin/mainmenu/pkgmgr.lua | 165 | ||||
-rw-r--r-- | builtin/mainmenu/tab_about.lua | 144 | ||||
-rw-r--r-- | builtin/mainmenu/tab_content.lua | 35 | ||||
-rw-r--r-- | builtin/mainmenu/tab_local.lua | 167 | ||||
-rw-r--r-- | builtin/mainmenu/tab_online.lua | 57 | ||||
-rw-r--r-- | builtin/mainmenu/tab_settings.lua | 49 | ||||
-rw-r--r-- | builtin/mainmenu/tests/serverlistmgr_spec.lua | 1 |
18 files changed, 950 insertions, 369 deletions
diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 8db8bb8d1..81e28f2bb 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -125,18 +125,12 @@ os.tmpname = function() end -------------------------------------------------------------------------------- -function menu_render_worldlist(show_gameid) +function menu_render_worldlist() local retval = {} local current_worldlist = menudata.worldlist:get_list() - local row for i, v in ipairs(current_worldlist) do - row = v.name - if show_gameid == nil or show_gameid == true then - row = row .. " [" .. v.gameid .. "]" - end - retval[#retval+1] = core.formspec_escape(row) - + retval[#retval+1] = core.formspec_escape(v.name) end return table.concat(retval, ",") @@ -242,3 +236,11 @@ function menu_worldmt_legacy(selected) end end end + +function confirmation_formspec(message, confirm_id, confirm_label, cancel_id, cancel_label) + return "size[10,2.5,true]" .. + "label[0.5,0.5;" .. message .. "]" .. + "style[" .. confirm_id .. ";bgcolor=red]" .. + "button[0.5,1.5;2.5,0.5;" .. confirm_id .. ";" .. confirm_label .. "]" .. + "button[7.0,1.5;2.5,0.5;" .. cancel_id .. ";" .. cancel_label .. "]" +end diff --git a/builtin/mainmenu/dlg_config_world.lua b/builtin/mainmenu/dlg_config_world.lua index 9bdf92a74..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;" .. @@ -163,10 +241,16 @@ local function get_formspec(data) "button[8.95,0.125;2.5,0.5;btn_enable_all_mods;" .. fgettext("Enable all") .. "]" end + + 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) .. ";" .. data.selected_mod .."]" + pkgmgr.render_packagelist(data.list, use_technical_names, with_error) .. ";" .. data.selected_mod .."]" end local function handle_buttons(this, fields) @@ -205,14 +289,19 @@ local function handle_buttons(this, fields) local mods = worldfile:to_table() local rawlist = this.data.list:get_raw_list() + local was_set = {} for i = 1, #rawlist do local mod = rawlist[i] if not mod.is_modpack and not mod.is_game_content then if modname_valid(mod.name) then - worldfile:set("load_mod_" .. mod.name, - mod.enabled and "true" or "false") + if mod.enabled then + worldfile:set("load_mod_" .. mod.name, mod.virtual_path) + was_set[mod.name] = true + elseif not was_set[mod.name] then + worldfile:set("load_mod_" .. mod.name, "false") + end elseif mod.enabled then gamedata.errormessage = fgettext_ne("Failed to enable mo" .. "d \"$1\" as it contains disallowed characters. " .. @@ -256,12 +345,26 @@ local function handle_buttons(this, fields) if fields.btn_enable_all_mods then local list = this.data.list:get_raw_list() + -- When multiple copies of a mod are installed, we need to avoid enabling multiple of them + -- at a time. So lets first collect all the enabled mods, and then use this to exclude + -- multiple enables. + + local was_enabled = {} for i = 1, #list do if not list[i].is_game_content - and not list[i].is_modpack then + and not list[i].is_modpack and list[i].enabled then + was_enabled[list[i].name] = true + end + end + + for i = 1, #list do + if not list[i].is_game_content and not list[i].is_modpack and + not was_enabled[list[i].name] then list[i].enabled = true + was_enabled[list[i].name] = true end end + enabled_all = true return true end diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 276a7b096..2152b8a39 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -151,11 +151,9 @@ local function start_install(package, reason) if conf_path then local conf = Settings(conf_path) - if name_is_title then - conf:set("name", package.title) - else - conf:set("title", package.title) - conf:set("name", package.name) + conf:set("title", package.title) + if not name_is_title then + conf:set("name", package.name) end if not conf:get("description") then conf:set("description", package.short_description) @@ -193,7 +191,7 @@ end local function queue_download(package, reason) local max_concurrent_downloads = tonumber(core.settings:get("contentdb_max_concurrent_downloads")) - if number_downloading < max_concurrent_downloads then + if number_downloading < math.max(max_concurrent_downloads, 1) then start_install(package, reason) else table.insert(download_queue, { package = package, reason = reason }) @@ -360,7 +358,7 @@ function install_dialog.get_formspec() selected_game_idx = i end - games[i] = core.formspec_escape(games[i].name) + games[i] = core.formspec_escape(games[i].title) end local selected_game = pkgmgr.games[selected_game_idx] @@ -410,7 +408,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;gameid;", table.concat(games, ","), ";", selected_game_idx, "]", + "dropdown[2,0;4.25,0.5;selected_game;", table.concat(games, ","), ";", selected_game_idx, "]", "label[0,0.8;", fgettext("Dependencies:"), "]", @@ -461,9 +459,9 @@ function install_dialog.handle_submit(this, fields) return true end - if fields.gameid then + if fields.selected_game then for _, game in pairs(pkgmgr.games) do - if game.name == fields.gameid then + if game.title == fields.selected_game then core.settings:set("menu_last_game", game.id) break end @@ -490,12 +488,10 @@ local confirm_overwrite = {} function confirm_overwrite.get_formspec() local package = confirm_overwrite.package - return "size[11.5,4.5,true]" .. - "label[2,2;" .. - fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name) .. "]".. - "style[install;bgcolor=red]" .. - "button[3.25,3.5;2.5,0.5;install;" .. fgettext("Overwrite") .. "]" .. - "button[5.75,3.5;2.5,0.5;cancel;" .. fgettext("Cancel") .. "]" + return confirmation_formspec( + fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name), + 'install', fgettext("Overwrite"), + 'cancel', fgettext("Cancel")) end function confirm_overwrite.handle_submit(this, fields) diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 8d1509f33..806e019a9 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -15,9 +15,6 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --- cf. tab_local, the gamebar already provides game selection so we hide the list from here -local hide_gamelist = PLATFORM ~= "Android" - local function table_to_flags(ftable) -- Convert e.g. { jungles = true, caves = false } to "jungles,nocaves" local str = {} @@ -94,14 +91,14 @@ local mgv6_biomes = { local function create_world_formspec(dialogdata) - -- Error out when no games found + -- Point the player to ContentDB when no games are found if #pkgmgr.games == 0 then - return "size[12.25,3,true]" .. - "box[0,0;12,2;" .. mt_color_orange .. "]" .. - "textarea[0.3,0;11.7,2;;;".. - fgettext("You have no games installed.") .. "\n" .. - fgettext("Download one from minetest.net") .. "]" .. - "button[4.75,2.5;3,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" + return "size[8,2.5,true]" .. + "style[label_button;border=false]" .. + "button[0.5,0.5;7,0.5;label_button;" .. + fgettext("You have no games installed.") .. "]" .. + "button[0.5,1.5;2.5,0.5;world_create_open_cdb;" .. fgettext("Install a game") .. "]" .. + "button[5.0,1.5;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" end local current_mg = dialogdata.mg @@ -111,14 +108,11 @@ local function create_world_formspec(dialogdata) local flags = dialogdata.flags - local game, gameidx = pkgmgr.find_by_gameid(gameid) - if game == nil and hide_gamelist then + local game = pkgmgr.find_by_gameid(gameid) + if game == nil then -- should never happen but just pick the first game game = pkgmgr.get_game(1) - gameidx = 1 core.settings:set("menu_last_game", game.id) - elseif game == nil then - gameidx = 0 end local disallowed_mapgen_settings = {} @@ -296,17 +290,6 @@ local function create_world_formspec(dialogdata) label_spflags = "label[0,"..y_start..";" .. fgettext("Mapgen-specific flags") .. "]" end - -- Warning if only devtest is installed - local devtest_only = "" - local gamelist_height = 2.3 - if #pkgmgr.games == 1 and pkgmgr.games[1].id == "devtest" then - devtest_only = "box[0,0;5.8,1.7;#ff8800]" .. - "textarea[0.3,0;6,1.8;;;".. - fgettext("Warning: The Development Test is meant for developers.") .. "\n" .. - fgettext("Download a game, such as Minetest Game, from minetest.net") .. "]" - gamelist_height = 0.5 - end - local retval = "size[12.25,7,true]" .. @@ -315,22 +298,28 @@ local function create_world_formspec(dialogdata) "field[0.3,0.6;6,0.5;te_world_name;" .. fgettext("World name") .. ";" .. core.formspec_escape(dialogdata.worldname) .. "]" .. - "set_focus[te_world_name;false]" .. + "set_focus[te_world_name;false]" - "field[0.3,1.7;6,0.5;te_seed;" .. - fgettext("Seed") .. - ";".. core.formspec_escape(dialogdata.seed) .. "]" .. + if not disallowed_mapgen_settings["seed"] then + retval = retval .. "field[0.3,1.7;6,0.5;te_seed;" .. + fgettext("Seed") .. + ";".. core.formspec_escape(dialogdata.seed) .. "]" + + end + + retval = retval .. "label[0,2;" .. fgettext("Mapgen") .. "]".. "dropdown[0,2.5;6.3;dd_mapgen;" .. mglist .. ";" .. selindex .. "]" - if not hide_gamelist or devtest_only ~= "" then + -- Warning if only devtest is installed + if #pkgmgr.games == 1 and pkgmgr.games[1].id == "devtest" then retval = retval .. - "label[0,3.35;" .. fgettext("Game") .. "]".. - "textlist[0,3.85;5.8,"..gamelist_height..";games;" .. - pkgmgr.gamelist() .. ";" .. gameidx .. ";false]" .. - "container[0,4.5]" .. - devtest_only .. + "container[0,3.5]" .. + "box[0,0;5.8,1.7;#ff8800]" .. + "textarea[0.4,0.1;6,1.8;;;".. + fgettext("Development Test is meant for developers.") .. "]" .. + "button[1,1;4,0.5;world_create_open_cdb;" .. fgettext("Install another game") .. "]" .. "container_end[]" end @@ -353,17 +342,20 @@ end local function create_world_buttonhandler(this, fields) + if fields["world_create_open_cdb"] then + local dlg = create_store_dlg("game") + dlg:set_parent(this.parent) + this:delete() + this.parent:hide() + dlg:show() + return true + end + if fields["world_create_confirm"] or fields["key_enter"] then local worldname = fields["te_world_name"] - local game, gameindex - if hide_gamelist then - game, gameindex = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) - else - gameindex = core.get_textlist_index("games") - game = pkgmgr.get_game(gameindex) - end + local game, gameindex = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) local message if game == nil then @@ -391,7 +383,7 @@ local function create_world_buttonhandler(this, fields) end if message == nil then - this.data.seed = fields["te_seed"] + this.data.seed = fields["te_seed"] or "" this.data.mg = fields["dd_mapgen"] -- actual names as used by engine @@ -412,9 +404,7 @@ local function create_world_buttonhandler(this, fields) if message == nil then core.settings:set("menu_last_game", game.id) - if this.data.update_worldlist_filter then - menudata.worldlist:set_filtercriteria(game.id) - end + menudata.worldlist:set_filtercriteria(game.id) menudata.worldlist:refresh() core.settings:set("mainmenu_last_selected_world", menudata.worldlist:raw_index_by_uid(worldname)) @@ -426,7 +416,7 @@ local function create_world_buttonhandler(this, fields) end this.data.worldname = fields["te_world_name"] - this.data.seed = fields["te_seed"] + this.data.seed = fields["te_seed"] or "" if fields["games"] then local gameindex = core.get_textlist_index("games") @@ -472,13 +462,12 @@ local function create_world_buttonhandler(this, fields) end -function create_create_world_dlg(update_worldlistfilter) +function create_create_world_dlg() local retval = dialog_create("sp_create_world", create_world_formspec, create_world_buttonhandler, nil) retval.data = { - update_worldlist_filter = update_worldlistfilter, worldname = "", -- settings the world is created with: seed = core.settings:get("fixed_map_seed") or "", diff --git a/builtin/mainmenu/dlg_delete_content.lua b/builtin/mainmenu/dlg_delete_content.lua index a24171541..4463825f7 100644 --- a/builtin/mainmenu/dlg_delete_content.lua +++ b/builtin/mainmenu/dlg_delete_content.lua @@ -18,15 +18,10 @@ -------------------------------------------------------------------------------- local function delete_content_formspec(dialogdata) - local retval = - "size[11.5,4.5,true]" .. - "label[2,2;" .. - fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]".. - "style[dlg_delete_content_confirm;bgcolor=red]" .. - "button[3.25,3.5;2.5,0.5;dlg_delete_content_confirm;" .. fgettext("Delete") .. "]" .. - "button[5.75,3.5;2.5,0.5;dlg_delete_content_cancel;" .. fgettext("Cancel") .. "]" - - return retval + return confirmation_formspec( + fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name), + 'dlg_delete_content_confirm', fgettext("Delete"), + 'dlg_delete_content_cancel', fgettext("Cancel")) end -------------------------------------------------------------------------------- diff --git a/builtin/mainmenu/dlg_delete_world.lua b/builtin/mainmenu/dlg_delete_world.lua index 33e7bc945..67c0612bd 100644 --- a/builtin/mainmenu/dlg_delete_world.lua +++ b/builtin/mainmenu/dlg_delete_world.lua @@ -17,14 +17,10 @@ local function delete_world_formspec(dialogdata) - local retval = - "size[10,2.5,true]" .. - "label[0.5,0.5;" .. - fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" .. - "style[world_delete_confirm;bgcolor=red]" .. - "button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" .. - "button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]" - return retval + return confirmation_formspec( + fgettext("Delete World \"$1\"?", dialogdata.delete_name), + 'world_delete_confirm', fgettext("Delete"), + 'world_delete_cancel', fgettext("Cancel")) end local function delete_world_buttonhandler(this, fields) diff --git a/builtin/mainmenu/dlg_register.lua b/builtin/mainmenu/dlg_register.lua new file mode 100644 index 000000000..a7658249c --- /dev/null +++ b/builtin/mainmenu/dlg_register.lua @@ -0,0 +1,123 @@ +--Minetest +--Copyright (C) 2022 rubenwardy +-- +--This program is free software; you can redistribute it and/or modify +--it under the terms of the GNU Lesser General Public License as published by +--the Free Software Foundation; either version 2.1 of the License, or +--(at your option) any later version. +-- +--This program is distributed in the hope that it will be useful, +--but WITHOUT ANY WARRANTY; without even the implied warranty of +--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +--GNU Lesser General Public License for more details. +-- +--You should have received a copy of the GNU Lesser General Public License along +--with this program; if not, write to the Free Software Foundation, Inc., +--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +-------------------------------------------------------------------------------- + +local function register_formspec(dialogdata) + local title = fgettext("Joining $1", dialogdata.server and dialogdata.server.name or dialogdata.address) + local buttons_y = 4 + 1.3 + if dialogdata.error then + buttons_y = buttons_y + 0.8 + end + + local retval = { + "formspec_version[4]", + "size[8,", tostring(buttons_y + 1.175), "]", + "set_focus[", (dialogdata.name ~= "" and "password" or "name"), "]", + "label[0.375,0.8;", title, "]", + "field[0.375,1.575;7.25,0.8;name;", core.formspec_escape(fgettext("Name")), ";", + core.formspec_escape(dialogdata.name), "]", + "pwdfield[0.375,2.875;7.25,0.8;password;", core.formspec_escape(fgettext("Password")), "]", + "pwdfield[0.375,4.175;7.25,0.8;password_2;", core.formspec_escape(fgettext("Confirm Password")), "]" + } + + if dialogdata.error then + table.insert_all(retval, { + "box[0.375,", tostring(buttons_y - 0.9), ";7.25,0.6;darkred]", + "label[0.625,", tostring(buttons_y - 0.6), ";", core.formspec_escape(dialogdata.error), "]", + }) + end + + table.insert_all(retval, { + "container[0.375,", tostring(buttons_y), "]", + "button[0,0;2.5,0.8;dlg_register_confirm;", fgettext("Register"), "]", + "button[4.75,0;2.5,0.8;dlg_register_cancel;", fgettext("Cancel"), "]", + "container_end[]", + }) + + return table.concat(retval, "") +end + +-------------------------------------------------------------------------------- +local function register_buttonhandler(this, fields) + this.data.name = fields.name + this.data.error = nil + + if fields.dlg_register_confirm or fields.key_enter then + if fields.name == "" then + this.data.error = fgettext("Missing name") + return true + end + if fields.password ~= fields.password_2 then + this.data.error = fgettext("Passwords do not match") + return true + end + + gamedata.playername = fields.name + gamedata.password = fields.password + gamedata.address = this.data.address + gamedata.port = this.data.port + gamedata.allow_login_or_register = "register" + gamedata.selected_world = 0 + + assert(gamedata.address and gamedata.port) + + local server = this.data.server + if server then + serverlistmgr.add_favorite(server) + gamedata.servername = server.name + gamedata.serverdescription = server.description + else + gamedata.servername = "" + gamedata.serverdescription = "" + + serverlistmgr.add_favorite({ + address = gamedata.address, + port = gamedata.port, + }) + end + + core.settings:set("name", fields.name) + core.settings:set("address", gamedata.address) + core.settings:set("remote_port", gamedata.port) + + core.start() + end + + if fields["dlg_register_cancel"] then + this:delete() + return true + end + + return false +end + +-------------------------------------------------------------------------------- +function create_register_dialog(address, port, server) + assert(address) + assert(type(port) == "number") + + local retval = dialog_create("dlg_register", + register_formspec, + register_buttonhandler, + nil) + retval.data.address = address + retval.data.port = port + retval.data.server = server + retval.data.name = core.settings:get("name") or "" + return retval +end diff --git a/builtin/mainmenu/dlg_settings_advanced.lua b/builtin/mainmenu/dlg_settings_advanced.lua index 06fd32d84..69562e6a5 100644 --- a/builtin/mainmenu/dlg_settings_advanced.lua +++ b/builtin/mainmenu/dlg_settings_advanced.lua @@ -351,9 +351,9 @@ local function parse_config_file(read_all, parse_mods) local file = io.open(path, "r") if file then if not games_category_initialized then - fgettext_ne("Games") -- not used, but needed for xgettext + fgettext_ne("Content: Games") -- not used, but needed for xgettext table.insert(settings, { - name = "Games", + name = "Content: Games", level = 0, type = "category", }) @@ -378,15 +378,15 @@ local function parse_config_file(read_all, parse_mods) -- Parse mods local mods_category_initialized = false local mods = {} - get_mods(core.get_modpath(), mods) + 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") if file then if not mods_category_initialized then - fgettext_ne("Mods") -- not used, but needed for xgettext + fgettext_ne("Content: Mods") -- not used, but needed for xgettext table.insert(settings, { - name = "Mods", + name = "Content: Mods", level = 0, type = "category", }) @@ -395,6 +395,37 @@ local function parse_config_file(read_all, parse_mods) table.insert(settings, { name = mod.name, + readable_name = mod.title, + level = 1, + type = "category", + }) + + parse_single_file(file, path, read_all, settings, 2, false) + + file:close() + end + end + + -- Parse client mods + local clientmods_category_initialized = false + local clientmods = {} + 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") + if file then + if not clientmods_category_initialized then + fgettext_ne("Client Mods") -- not used, but needed for xgettext + table.insert(settings, { + name = "Client Mods", + level = 0, + type = "category", + }) + clientmods_category_initialized = true + end + + table.insert(settings, { + name = mod.name, level = 1, type = "category", }) @@ -497,44 +528,40 @@ end local function get_current_np_group(setting) local value = core.settings:get_np_group(setting.name) - local t = {} if value == nil then - t = setting.values - else - table.insert(t, value.offset) - table.insert(t, value.scale) - table.insert(t, value.spread.x) - table.insert(t, value.spread.y) - table.insert(t, value.spread.z) - table.insert(t, value.seed) - table.insert(t, value.octaves) - table.insert(t, value.persistence) - table.insert(t, value.lacunarity) - table.insert(t, value.flags) + return setting.values end - return t + local p = "%g" + return { + p:format(value.offset), + p:format(value.scale), + p:format(value.spread.x), + p:format(value.spread.y), + p:format(value.spread.z), + p:format(value.seed), + p:format(value.octaves), + p:format(value.persistence), + p:format(value.lacunarity), + value.flags + } end local function get_current_np_group_as_string(setting) local value = core.settings:get_np_group(setting.name) - local t if value == nil then - t = setting.default - else - t = value.offset .. ", " .. - value.scale .. ", (" .. - value.spread.x .. ", " .. - value.spread.y .. ", " .. - value.spread.z .. "), " .. - value.seed .. ", " .. - value.octaves .. ", " .. - value.persistence .. ", " .. - value.lacunarity - if value.flags ~= "" then - t = t .. ", " .. value.flags - end + return setting.default end - return t + return ("%g, %g, (%g, %g, %g), %g, %g, %g, %g"):format( + value.offset, + value.scale, + value.spread.x, + value.spread.y, + value.spread.z, + value.seed, + value.octaves, + value.persistence, + value.lacunarity + ) .. (value.flags ~= "" and (", " .. value.flags) or "") end local checkboxes = {} -- handle checkboxes events @@ -667,7 +694,7 @@ local function create_change_setting_formspec(dialogdata) elseif setting.type == "v3f" then local val = get_current_value(setting) local v3f = {} - for line in val:gmatch("[+-]?[%d.-e]+") do -- All numeric characters + for line in val:gmatch("[+-]?[%d.+-eE]+") do -- All numeric characters table.insert(v3f, line) end @@ -960,7 +987,7 @@ local function create_settings_formspec(tabview, _, tabdata) local current_level = 0 for _, entry in ipairs(settings) do local name - if not core.settings:get_bool("main_menu_technical_settings") and entry.readable_name then + if not core.settings:get_bool("show_technical_names") and entry.readable_name then name = fgettext_ne(entry.readable_name) else name = entry.name @@ -1001,7 +1028,7 @@ local function create_settings_formspec(tabview, _, tabdata) "button[10,4.9;2,1;btn_edit;" .. fgettext("Edit") .. "]" .. "button[7,4.9;3,1;btn_restore;" .. fgettext("Restore Default") .. "]" .. "checkbox[0,4.3;cb_tech_settings;" .. fgettext("Show technical names") .. ";" - .. dump(core.settings:get_bool("main_menu_technical_settings")) .. "]" + .. dump(core.settings:get_bool("show_technical_names")) .. "]" return formspec end @@ -1084,7 +1111,7 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) end if fields["cb_tech_settings"] then - core.settings:set("main_menu_technical_settings", fields["cb_tech_settings"]) + core.settings:set("show_technical_names", fields["cb_tech_settings"]) core.settings:write() core.update_formspec(this:get_formspec()) return true diff --git a/builtin/mainmenu/dlg_version_info.lua b/builtin/mainmenu/dlg_version_info.lua new file mode 100644 index 000000000..568fca3f4 --- /dev/null +++ b/builtin/mainmenu/dlg_version_info.lua @@ -0,0 +1,172 @@ +--[[ +Minetest +Copyright (C) 2018-2020 SmallJoker, 2022 rubenwardy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +]] + +if not core.get_http_api then + function check_new_version() + end + return +end + +local function version_info_formspec(data) + local cur_ver = core.get_version() + local title = fgettext("A new $1 version is available", cur_ver.project) + local message = + fgettext("Installed version: $1\nNew version: $2\n" .. + "Visit $3 to find out how to get the newest version and stay up to date" .. + " with features and bugfixes.", + cur_ver.string, data.new_version or "", data.url or "") + + local fs = { + "formspec_version[3]", + "size[12.8,7]", + "style_type[label;textcolor=#0E0]", + "label[0.5,0.8;", core.formspec_escape(title), "]", + "textarea[0.4,1.6;12,3.4;;;", + core.formspec_escape(message), "]", + "container[0.4,5.8]", + "button[0.0,0;4.0,0.8;version_check_visit;", fgettext("Visit website"), "]", + "button[4.5,0;3.5,0.8;version_check_remind;", fgettext("Later"), "]", + "button[8.5.5,0;3.5,0.8;version_check_never;", fgettext("Never"), "]", + "container_end[]", + } + + return table.concat(fs, "") +end + +local function version_info_buttonhandler(this, fields) + if fields.version_check_remind then + -- Erase last known, user will be reminded again at next check + core.settings:set("update_last_known", "") + this:delete() + return true + end + if fields.version_check_never then + core.settings:set("update_last_checked", "disabled") + this:delete() + return true + end + if fields.version_check_visit then + if type(this.data.url) == "string" then + core.open_url(this.data.url) + end + this:delete() + return true + end + + return false +end + +local function create_version_info_dlg(new_version, url) + assert(type(new_version) == "string") + assert(type(url) == "string") + + local retval = dialog_create("version_info", + version_info_formspec, + version_info_buttonhandler, + nil) + + retval.data.new_version = new_version + retval.data.url = url + + return retval +end + +local function get_current_version_code() + -- Format: Major.Minor.Patch + -- Convert to MMMNNNPPP + local cur_string = core.get_version().string + local cur_major, cur_minor, cur_patch = cur_string:match("^(%d+).(%d+).(%d+)") + + if not cur_patch then + core.log("error", "Failed to parse version numbers (invalid tag format?)") + return + end + + return (cur_major * 1000 + cur_minor) * 1000 + cur_patch +end + +local function on_version_info_received(json) + local maintab = ui.find_by_name("maintab") + if maintab.hidden then + -- Another dialog is open, abort. + return + end + + local known_update = tonumber(core.settings:get("update_last_known")) or 0 + + -- Format: MMNNPPP (Major, Minor, Patch) + local new_number = type(json.latest) == "table" and json.latest.version_code + if type(new_number) ~= "number" then + core.log("error", "Failed to read version number (invalid response?)") + return + end + + local cur_number = get_current_version_code() + if new_number <= known_update or new_number < cur_number then + return + end + + -- Also consider updating from 1.2.3-dev to 1.2.3 + if new_number == cur_number and not core.get_version().is_dev then + return + end + + core.settings:set("update_last_known", tostring(new_number)) + + -- Show version info dialog (once) + maintab:hide() + + local version_info_dlg = create_version_info_dlg(json.latest.version, json.latest.url) + version_info_dlg:set_parent(maintab) + version_info_dlg:show() + + ui.update() +end + +function check_new_version() + local url = core.settings:get("update_information_url") + if core.settings:get("update_last_checked") == "disabled" or + url == "" then + -- Never show any updates + return + end + + local time_now = os.time() + local time_checked = tonumber(core.settings:get("update_last_checked")) or 0 + if time_now - time_checked < 2 * 24 * 3600 then + -- Check interval of 2 entire days + return + end + + core.settings:set("update_last_checked", tostring(time_now)) + + core.handle_async(function(params) + local http = core.get_http_api() + return http.fetch_sync(params) + end, { url = url }, function(result) + local json = result.succeeded and core.parse_json(result.data) + if type(json) ~= "table" or not json.latest then + core.log("error", "Failed to read JSON output from " .. url .. + ", status code = " .. result.code) + return + end + + on_version_info_received(json) + end) +end diff --git a/builtin/mainmenu/generate_from_settingtypes.lua b/builtin/mainmenu/generate_from_settingtypes.lua index 43fc57bb9..0f551fbb1 100644 --- a/builtin/mainmenu/generate_from_settingtypes.lua +++ b/builtin/mainmenu/generate_from_settingtypes.lua @@ -31,7 +31,7 @@ local group_format_template = [[ # octaves = %s, # persistence = %s, # lacunarity = %s, -# flags = %s +# flags =%s # } ]] @@ -55,7 +55,11 @@ local function create_minetest_conf_example() end if entry.comment ~= "" then for _, comment_line in ipairs(entry.comment:split("\n", true)) do - insert(result, "# " .. comment_line .. "\n") + if comment_line == "" then + insert(result, "#\n") + else + insert(result, "# " .. comment_line .. "\n") + end end end insert(result, "# type: " .. entry.type) @@ -73,10 +77,14 @@ local function create_minetest_conf_example() end insert(result, "\n") if group_format == true then + local flags = entry.values[10] + if flags ~= "" then + flags = " "..flags + end insert(result, sprintf(group_format_template, entry.name, entry.values[1], entry.values[2], entry.values[3], entry.values[4], entry.values[5], entry.values[6], entry.values[7], entry.values[8], entry.values[9], - entry.values[10])) + flags)) else local append if entry.default ~= "" then @@ -91,7 +99,7 @@ end local translation_file_header = [[ // This file is automatically generated -// It conatins a bunch of fake gettext calls, to tell xgettext about the strings in config files +// It contains a bunch of fake gettext calls, to tell xgettext about the strings in config files // To update it, refer to the bottom of builtin/mainmenu/dlg_settings_advanced.lua fake_function() {]] @@ -126,4 +134,3 @@ file = assert(io.open("src/settings_translation_file.cpp", "w")) --file = assert(io.open("settings_translation_file.cpp", "w")) file:write(create_translation_file()) file:close() - diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 8e716c2eb..c3a28a570 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -17,9 +17,11 @@ mt_color_grey = "#AAAAAA" mt_color_blue = "#6389FF" +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() @@ -43,7 +45,9 @@ dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua") dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") +dofile(menupath .. DIR_DELIM .. "dlg_register.lua") dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") +dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua") local tabs = {} @@ -91,6 +95,7 @@ local function init_globals() -- Create main tabview local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0}) + -- note: size would be 15.5,7.1 in real coordinates mode tv_main:set_autosave_tab(true) tv_main:add(tabs.local_game) @@ -118,8 +123,8 @@ local function init_globals() end ui.set_default("maintab") + check_new_version() tv_main:show() - ui.update() end diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index 23f24d617..32a65fd08 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -78,34 +78,35 @@ local function load_texture_packs(txtpath, retval) 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") + local enabled = path == current_texture_path + local title = conf:get("title") or item + + -- list_* is only used if non-nil, else the regular versions are used. retval[#retval + 1] = { name = item, + title = title, + list_name = enabled and fgettext("$1 (Enabled)", item) or nil, + list_title = enabled and fgettext("$1 (Enabled)", title) or nil, author = conf:get("author"), release = tonumber(conf:get("release")) or 0, - list_name = name, type = "txp", path = path, - enabled = path == current_texture_path, + enabled = enabled, } end end end -function get_mods(path,retval,modpack) +function get_mods(path, virtual_path, retval, modpack) local mods = core.get_dir_list(path, true) for _, name in ipairs(mods) do if name:sub(1, 1) ~= "." then - local prefix = path .. DIR_DELIM .. name + local mod_path = path .. DIR_DELIM .. name + local mod_virtual_path = virtual_path .. "/" .. name local toadd = { dir_name = name, parent_dir = path, @@ -114,18 +115,18 @@ function get_mods(path,retval,modpack) -- Get config file local mod_conf - local modpack_conf = io.open(prefix .. DIR_DELIM .. "modpack.conf") + local modpack_conf = io.open(mod_path .. DIR_DELIM .. "modpack.conf") if modpack_conf then toadd.is_modpack = true modpack_conf:close() - mod_conf = Settings(prefix .. DIR_DELIM .. "modpack.conf"):to_table() + mod_conf = Settings(mod_path .. DIR_DELIM .. "modpack.conf"):to_table() if mod_conf.name then name = mod_conf.name toadd.is_name_explicit = true end else - mod_conf = Settings(prefix .. DIR_DELIM .. "mod.conf"):to_table() + mod_conf = Settings(mod_path .. DIR_DELIM .. "mod.conf"):to_table() if mod_conf.name then name = mod_conf.name toadd.is_name_explicit = true @@ -134,14 +135,16 @@ function get_mods(path,retval,modpack) -- Read from config toadd.name = name + toadd.title = mod_conf.title toadd.author = mod_conf.author toadd.release = tonumber(mod_conf.release) or 0 - toadd.path = prefix + toadd.path = mod_path + toadd.virtual_path = mod_virtual_path toadd.type = "mod" -- Check modpack.txt -- Note: modpack.conf is already checked above - local modpackfile = io.open(prefix .. DIR_DELIM .. "modpack.txt") + local modpackfile = io.open(mod_path .. DIR_DELIM .. "modpack.txt") if modpackfile then modpackfile:close() toadd.is_modpack = true @@ -153,7 +156,7 @@ function get_mods(path,retval,modpack) elseif toadd.is_modpack then toadd.type = "modpack" toadd.is_modpack = true - get_mods(prefix, retval, name) + get_mods(mod_path, mod_virtual_path, retval, name) end end end @@ -334,7 +337,7 @@ function pkgmgr.identify_modname(modpath,filename) return nil end -------------------------------------------------------------------------------- -function pkgmgr.render_packagelist(render_list) +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() @@ -346,31 +349,75 @@ function pkgmgr.render_packagelist(render_list) 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" else retval[#retval + 1] = "0" end - retval[#retval + 1] = core.formspec_escape(v.list_name or v.name) + + 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 + retval[#retval + 1] = core.formspec_escape(v.list_title or v.list_name or v.title or v.name) + end end return table.concat(retval, ",") @@ -397,6 +444,14 @@ function pkgmgr.is_modpack_entirely_enabled(data, name) return true end +local function disable_all_by_name(list, name, except) + for i=1, #list do + if list[i].name == name and list[i] ~= except then + list[i].enabled = false + end + end +end + ---------- 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 @@ -405,13 +460,16 @@ local function toggle_mod_or_modpack(list, toggled_mods, enabled_mods, toset, mo 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 + + -- Disable other mods with the same name + disable_all_by_name(list, mod.name, mod) end + mod.enabled = toset else -- Toggle or en/disable every mod in the modpack, -- interleaved unsupported @@ -472,6 +530,7 @@ function pkgmgr.enable_mod(this, toset) end end end + -- If sp is 0, every dependency is already activated while sp > 0 do local name = to_enable[sp] @@ -483,8 +542,8 @@ function pkgmgr.enable_mod(this, toset) if not mod_to_enable then core.log("warning", "Mod dependency \"" .. name .. "\" not found!") - else - if not mod_to_enable.enabled then + 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 end @@ -626,6 +685,8 @@ function pkgmgr.install_dir(type, path, basename, targetpath) else targetpath = core.get_gamepath() .. DIR_DELIM .. basename end + else + error("basefolder didn't return a recognised type, this shouldn't happen") end -- Copy it @@ -652,13 +713,14 @@ function pkgmgr.preparemodlist(data) --read global mods local modpaths = core.get_modpaths() - for _, modpath in ipairs(modpaths) do - get_mods(modpath, global_mods) + for key, modpath in pairs(modpaths) do + get_mods(modpath, key, global_mods) end for i=1,#global_mods,1 do global_mods[i].type = "mod" global_mods[i].loc = "global" + global_mods[i].enabled = false retval[#retval + 1] = global_mods[i] end @@ -671,7 +733,7 @@ function pkgmgr.preparemodlist(data) retval[#retval + 1] = { type = "game", is_game_content = true, - name = fgettext("$1 mods", gamespec.name), + name = fgettext("$1 mods", gamespec.title), path = gamespec.path } end @@ -692,22 +754,37 @@ function pkgmgr.preparemodlist(data) DIR_DELIM .. "world.mt" local worldfile = Settings(filename) - - for key,value in pairs(worldfile:to_table()) do + for key, value in pairs(worldfile:to_table()) do if key:sub(1, 9) == "load_mod_" then key = key:sub(10) - local element = nil - for i=1,#retval,1 do + local mod_found = false + + local fallback_found = false + local fallback_mod = nil + + for i=1, #retval do if retval[i].name == key and - not retval[i].is_modpack then - element = retval[i] - break + not retval[i].is_modpack then + if core.is_yes(value) or retval[i].virtual_path == value then + retval[i].enabled = true + mod_found = true + break + elseif fallback_found then + -- Only allow fallback if only one mod matches + fallback_mod = nil + else + fallback_found = true + fallback_mod = retval[i] + end end end - if element ~= nil then - element.enabled = value ~= "false" and value ~= "nil" and value - else - core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") + + if not mod_found then + if fallback_mod and value:find("/") then + fallback_mod.enabled = true + else + core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found") + end end end end @@ -801,7 +878,7 @@ 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, retval) + get_mods(gamespec.gamemods_path, ("games/%s/mods"):format(gamespec.id), retval) end end @@ -837,10 +914,10 @@ end function pkgmgr.gamelist() local retval = "" if #pkgmgr.games > 0 then - retval = retval .. core.formspec_escape(pkgmgr.games[1].name) + retval = retval .. core.formspec_escape(pkgmgr.games[1].title) for i=2,#pkgmgr.games,1 do - retval = retval .. "," .. core.formspec_escape(pkgmgr.games[i].name) + retval = retval .. "," .. core.formspec_escape(pkgmgr.games[i].title) end end return retval diff --git a/builtin/mainmenu/tab_about.lua b/builtin/mainmenu/tab_about.lua index ba258fd2d..a84ebce3f 100644 --- a/builtin/mainmenu/tab_about.lua +++ b/builtin/mainmenu/tab_about.lua @@ -15,48 +15,46 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --------------------------------------------------------------------------------- +-- https://github.com/orgs/minetest/teams/engine/members local core_developers = { - "Perttu Ahola (celeron55) <celeron55@gmail.com>", + "Perttu Ahola (celeron55) <celeron55@gmail.com> [Project founder]", "sfan5 <sfan5@live.de>", - "Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>", + "ShadowNinja <shadowninja@minetest.net>", + "Nathanaëlle Courant (Nore/Ekdohibs) <nore@mesecons.net>", "Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>", - "paramat", "Andrew Ward (rubenwardy) <rw@rubenwardy.com>", "Krock/SmallJoker <mk939@ymail.com>", "Lars Hofhansl <larsh@apache.org>", - "Pierre-Yves Rollo <dev@pyrollo.com>", "v-rob <robinsonvincent89@gmail.com>", "hecks", "Hugues Ross <hugues.ross@gmail.com>", "Dmitry Kostenko (x2048) <codeforsmile@gmail.com>", } +local core_team = { + "Zughy [Issue triager]", +} + -- For updating active/previous contributors, see the script in ./util/gather_git_credits.py local active_contributors = { - "Wuzzy [I18n for builtin, liquid features, fixes]", - "Zughy [Various features and fixes]", - "numzero [Graphics and rendering]", - "Desour [Internal fixes, Clipboard on X11]", - "Lars Müller [Various internal fixes]", - "JosiahWI [CMake, cleanups and fixes]", - "HybridDog [builtin, documentation]", - "Jude Melton-Houghton [Database implementation]", - "savilli [Fixes]", + "Wuzzy [Features, translations, devtest]", + "Lars Müller [Lua optimizations and fixes]", + "Jude Melton-Houghton [Optimizations, bugfixes]", + "paradust7 [Performance, fixes, Irrlicht refactoring]", + "Desour [Fixes]", + "ROllerozxa [Main menu]", + "savilli [Bugfixes]", + "Lexi Hale [Particlespawner animation]", "Liso [Shadow Mapping]", - "MoNTE48 [Build fix]", - "Jean-Patrick Guerrero (kilbith) [Fixes]", - "ROllerozxa [Code cleanups]", - "Lejo [bitop library integration]", - "LoneWolfHT [Build fixes]", + "JosiahWI [Fixes, build system]", + "numzero [Graphics and rendering]", + "HybridDog [Fixes]", "NeroBurner [Joystick]", - "Elias Fleckenstein [Internal fixes]", - "David CARLIER [Unix & Haiku build fixes]", "pecksin [Clickable web links]", - "srfqi [Android & rendering fixes]", - "EvidenceB [Formspec]", + "Daroc Alden [Fixes]", + "Jean-Patrick Guerrero (kilbith) [Fixes]", } local previous_core_developers = { @@ -71,33 +69,50 @@ local previous_core_developers = { "Ryan Kwolek (kwolekr) <kwolekr@minetest.net>", "sapier", "Zeno", - "ShadowNinja <shadowninja@minetest.net>", "Auke Kok (sofar) <sofar@foo-projects.org>", "Aaron Suen <warr1024@gmail.com>", + "paramat", + "Pierre-Yves Rollo <dev@pyrollo.com>", } local previous_contributors = { - "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest Logo]", + "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest logo]", "red-001 <red-001@outlook.ie>", "Giuseppe Bilotta", + "ClobberXD", "Dániel Juhász (juhdanad) <juhdanad@gmail.com>", "MirceaKitsune <mirceakitsune@gmail.com>", + "MoNTE48", "Constantin Wenger (SpeedProg)", "Ciaran Gultnieks (CiaranG)", "Paul Ouellette (pauloue)", "stujones11", + "srifqi", "Rogier <rogier777@gmail.com>", "Gregory Currie (gregorycu)", "JacobF", - "Jeija <jeija@mesecons.net> [HTTP, particles]", + "Jeija <jeija@mesecons.net>", } -local function buildCreditList(source) +local function prepare_credits(dest, source) + for _, s in ipairs(source) do + -- if there's text inside brackets make it gray-ish + s = s:gsub("%[.-%]", core.colorize("#aaa", "%1")) + dest[#dest+1] = s + end +end + +local function build_hacky_list(items, spacing) + spacing = spacing or 0.5 + local y = spacing / 2 local ret = {} - for i = 1, #source do - ret[i] = core.formspec_escape(source[i]) + for _, item in ipairs(items) do + if item ~= "" then + ret[#ret+1] = ("label[0,%f;%s]"):format(y, core.formspec_escape(item)) + end + y = y + spacing end - return table.concat(ret, ",,") + return table.concat(ret, ""), y end return { @@ -106,42 +121,73 @@ return { cbf_formspec = function(tabview, name, tabdata) local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() - local fs = "image[0.75,0.5;2.2,2.2;" .. core.formspec_escape(logofile) .. "]" .. + + local credit_list = {} + table.insert_all(credit_list, { + core.colorize("#ff0", fgettext("Core Developers")) + }) + prepare_credits(credit_list, core_developers) + table.insert_all(credit_list, { + "", + core.colorize("#ff0", fgettext("Core Team")) + }) + prepare_credits(credit_list, core_team) + table.insert_all(credit_list, { + "", + core.colorize("#ff0", fgettext("Active Contributors")) + }) + prepare_credits(credit_list, active_contributors) + table.insert_all(credit_list, { + "", + core.colorize("#ff0", fgettext("Previous Core Developers")) + }) + prepare_credits(credit_list, previous_core_developers) + table.insert_all(credit_list, { + "", + core.colorize("#ff0", fgettext("Previous Contributors")) + }) + prepare_credits(credit_list, previous_contributors) + local credit_fs, scroll_height = build_hacky_list(credit_list) + -- account for the visible portion + scroll_height = math.max(0, scroll_height - 6.9) + + local fs = "image[1.5,0.6;2.5,2.5;" .. core.formspec_escape(logofile) .. "]" .. "style[label_button;border=false]" .. - "button[0.5,2;2.5,2;label_button;" .. version.project .. " " .. version.string .. "]" .. - "button[0.75,2.75;2,2;homepage;minetest.net]" .. - "tablecolumns[color;text]" .. - "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. - "table[3.5,-0.25;8.5,6.05;list_credits;" .. - "#FFFF00," .. fgettext("Core Developers") .. ",," .. - buildCreditList(core_developers) .. ",,," .. - "#FFFF00," .. fgettext("Active Contributors") .. ",," .. - buildCreditList(active_contributors) .. ",,," .. - "#FFFF00," .. fgettext("Previous Core Developers") ..",," .. - buildCreditList(previous_core_developers) .. ",,," .. - "#FFFF00," .. fgettext("Previous Contributors") .. ",," .. - buildCreditList(previous_contributors) .. "," .. - ";1]" + "button[0.1,3.4;5.3,0.5;label_button;" .. + core.formspec_escape(version.project .. " " .. version.string) .. "]" .. + "button[1.5,4.1;2.5,0.8;homepage;minetest.net]" .. + "scroll_container[5.5,0.1;9.5,6.9;scroll_credits;vertical;" .. + tostring(scroll_height / 1000) .. "]" .. credit_fs .. + "scroll_container_end[]".. + "scrollbar[15,0.1;0.4,6.9;vertical;scroll_credits;0]" -- Render information - fs = fs .. "label[0.75,4.9;" .. + fs = fs .. "style[label_button2;border=false]" .. + "button[0.1,6;5.3,1;label_button2;" .. fgettext("Active renderer:") .. "\n" .. core.formspec_escape(core.get_screen_info().render_info) .. "]" - if PLATFORM ~= "Android" then + if PLATFORM == "Android" then + fs = fs .. "button[0.5,5.1;4.5,0.8;share_debug;" .. fgettext("Share debug log") .. "]" + else fs = fs .. "tooltip[userdata;" .. fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" .. "and texture packs in a file manager / explorer.") .. "]" - fs = fs .. "button[0,4;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]" + fs = fs .. "button[0.5,5.1;4.5,0.8;userdata;" .. fgettext("Open User Data Directory") .. "]" end - return fs + return fs, "size[15.5,7.1,false]real_coordinates[true]" end, cbf_button_handler = function(this, fields, name, tabdata) if fields.homepage then core.open_url("https://www.minetest.net") end + if fields.share_debug then + local path = core.get_user_path() .. DIR_DELIM .. "debug.txt" + core.share_file(path) + end + if fields.userdata then core.open_dir(core.get_user_path()) end diff --git a/builtin/mainmenu/tab_content.lua b/builtin/mainmenu/tab_content.lua index fb7f121f8..5e14d1902 100644 --- a/builtin/mainmenu/tab_content.lua +++ b/builtin/mainmenu/tab_content.lua @@ -51,12 +51,14 @@ local function get_formspec(tabview, name, tabdata) tabdata.selected_pkg = 1 end + local use_technical_names = core.settings:get_bool("show_technical_names") + local retval = "label[0.05,-0.25;".. fgettext("Installed Packages:") .. "]" .. "tablecolumns[color;tree;text]" .. "table[0,0.25;5.1,4.3;pkglist;" .. - pkgmgr.render_packagelist(packages) .. + pkgmgr.render_packagelist(packages, use_technical_names) .. ";" .. tabdata.selected_pkg .. "]" .. "button[0,4.85;5.25,0.5;btn_contentdb;".. fgettext("Browse online content") .. "]" @@ -87,9 +89,17 @@ local function get_formspec(tabview, name, tabdata) desc = info.description end + local title_and_name + if selected_pkg.type == "game" then + title_and_name = selected_pkg.name + else + title_and_name = (selected_pkg.title or selected_pkg.name) .. "\n" .. + core.colorize("#BFBFBF", selected_pkg.name) + end + retval = retval .. "image[5.5,0;3,2;" .. core.formspec_escape(modscreenshot) .. "]" .. - "label[8.25,0.6;" .. core.formspec_escape(selected_pkg.name) .. "]" .. + "label[8.25,0.6;" .. core.formspec_escape(title_and_name) .. "]" .. "box[5.5,2.2;6.15,2.35;#000]" if selected_pkg.type == "mod" then @@ -154,6 +164,9 @@ local function handle_doubleclick(pkg) core.settings:set("texture_path", pkg.path) end packages = nil + + mm_game_theme.init() + mm_game_theme.reset() end end @@ -197,17 +210,17 @@ local function handle_buttons(tabview, fields, tabname, tabdata) return true end - if fields.btn_mod_mgr_use_txp then - local txp = packages:get_list()[tabdata.selected_pkg] - core.settings:set("texture_path", txp.path) - packages = nil - return true - end - + if fields.btn_mod_mgr_use_txp or fields.btn_mod_mgr_disable_txp then + local txp_path = "" + if fields.btn_mod_mgr_use_txp then + txp_path = packages:get_list()[tabdata.selected_pkg].path + end - if fields.btn_mod_mgr_disable_txp then - core.settings:set("texture_path", "") + core.settings:set("texture_path", txp_path) packages = nil + + mm_game_theme.init() + mm_game_theme.reset() return true end diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index e77c6f04d..f8de10db6 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -16,7 +16,6 @@ --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -local enable_gamebar = PLATFORM ~= "Android" local current_game, singleplayer_refresh_gamebar local valid_disabled_settings = { ["enable_damage"]=true, @@ -24,95 +23,88 @@ local valid_disabled_settings = { ["enable_server"]=true, } -if enable_gamebar then - -- Currently chosen game in gamebar for theming and filtering - function current_game() - local last_game_id = core.settings:get("menu_last_game") - local game = pkgmgr.find_by_gameid(last_game_id) +-- Currently chosen game in gamebar for theming and filtering +function current_game() + local last_game_id = core.settings:get("menu_last_game") + local game = pkgmgr.find_by_gameid(last_game_id) - return game - end + return game +end - -- Apply menu changes from given game - function apply_game(game) - core.set_topleft_text(game.name) - core.settings:set("menu_last_game", game.id) - menudata.worldlist:set_filtercriteria(game.id) +-- Apply menu changes from given game +function apply_game(game) + core.set_topleft_text(game.name) + core.settings:set("menu_last_game", game.id) + menudata.worldlist:set_filtercriteria(game.id) - mm_game_theme.update("singleplayer", game) -- this refreshes the formspec + mm_game_theme.update("singleplayer", game) -- this refreshes the formspec - local index = filterlist.get_current_index(menudata.worldlist, - tonumber(core.settings:get("mainmenu_last_selected_world"))) - if not index or index < 1 then - local selected = core.get_textlist_index("sp_worlds") - if selected ~= nil and selected < #menudata.worldlist:get_list() then - index = selected - else - index = #menudata.worldlist:get_list() - end + local index = filterlist.get_current_index(menudata.worldlist, + tonumber(core.settings:get("mainmenu_last_selected_world"))) + if not index or index < 1 then + local selected = core.get_textlist_index("sp_worlds") + if selected ~= nil and selected < #menudata.worldlist:get_list() then + index = selected + else + index = #menudata.worldlist:get_list() end - menu_worldmt_legacy(index) end + menu_worldmt_legacy(index) +end - function singleplayer_refresh_gamebar() +function singleplayer_refresh_gamebar() - local old_bar = ui.find_by_name("game_button_bar") - if old_bar ~= nil then - old_bar:delete() + local old_bar = ui.find_by_name("game_button_bar") + if old_bar ~= nil then + old_bar:delete() + end + + local function game_buttonbar_button_handler(fields) + if fields.game_open_cdb then + local maintab = ui.find_by_name("maintab") + local dlg = create_store_dlg("game") + dlg:set_parent(maintab) + maintab:hide() + dlg:show() + return true end - local function game_buttonbar_button_handler(fields) - if fields.game_open_cdb then - local maintab = ui.find_by_name("maintab") - local dlg = create_store_dlg("game") - dlg:set_parent(maintab) - maintab:hide() - dlg:show() + for _, game in ipairs(pkgmgr.games) do + if fields["game_btnbar_" .. game.id] then + apply_game(game) return true end - - for _, game in ipairs(pkgmgr.games) do - if fields["game_btnbar_" .. game.id] then - apply_game(game) - return true - end - end end + end - local btnbar = buttonbar_create("game_button_bar", - game_buttonbar_button_handler, - {x=-0.3,y=5.9}, "horizontal", {x=12.4,y=1.15}) + local btnbar = buttonbar_create("game_button_bar", + game_buttonbar_button_handler, + {x=-0.3,y=5.9}, "horizontal", {x=12.4,y=1.15}) - for _, game in ipairs(pkgmgr.games) do - local btn_name = "game_btnbar_" .. game.id + for _, game in ipairs(pkgmgr.games) do + local btn_name = "game_btnbar_" .. game.id - local image = nil - local text = nil - local tooltip = core.formspec_escape(game.name) + local image = nil + local text = nil + local tooltip = core.formspec_escape(game.title) - if (game.menuicon_path or "") ~= "" then - image = core.formspec_escape(game.menuicon_path) - else - local part1 = game.id:sub(1,5) - local part2 = game.id:sub(6,10) - local part3 = game.id:sub(11) + if (game.menuicon_path or "") ~= "" then + image = core.formspec_escape(game.menuicon_path) + else + local part1 = game.id:sub(1,5) + local part2 = game.id:sub(6,10) + local part3 = game.id:sub(11) - text = part1 .. "\n" .. part2 - if part3 ~= "" then - text = text .. "\n" .. part3 - end + text = part1 .. "\n" .. part2 + if part3 ~= "" then + text = text .. "\n" .. part3 end - btnbar:add_button(btn_name, text, image, tooltip) end - - local plus_image = core.formspec_escape(defaulttexturedir .. "plus.png") - btnbar:add_button("game_open_cdb", "", plus_image, fgettext("Install games from ContentDB")) - end -else - -- Currently chosen game in gamebar: no gamebar -> no "current" game - function current_game() - return nil + btnbar:add_button(btn_name, text, image, tooltip) end + + local plus_image = core.formspec_escape(defaulttexturedir .. "plus.png") + btnbar:add_button("game_open_cdb", "", plus_image, fgettext("Install games from ContentDB")) end local function get_disabled_settings(game) @@ -187,7 +179,7 @@ local function get_formspec(tabview, name, tabdata) damage .. host .. "textlist[3.9,0.4;7.9,3.45;sp_worlds;" .. - menu_render_worldlist(not enable_gamebar) .. + menu_render_worldlist() .. ";" .. index .. "]" if core.settings:get_bool("enable_server") and disabled_settings["enable_server"] == nil then @@ -324,7 +316,7 @@ local function main_button_handler(this, fields, name, tabdata) end if fields["world_create"] ~= nil then - local create_world_dlg = create_create_world_dlg(enable_gamebar) + local create_world_dlg = create_create_world_dlg() create_world_dlg:set_parent(this) this:hide() create_world_dlg:show() @@ -371,26 +363,23 @@ local function main_button_handler(this, fields, name, tabdata) end end -local on_change -if enable_gamebar then - function on_change(type, old_tab, new_tab) - if (type == "ENTER") then - local game = current_game() - if game then - apply_game(game) - end +local function on_change(type, old_tab, new_tab) + if (type == "ENTER") then + local game = current_game() + if game then + apply_game(game) + end - singleplayer_refresh_gamebar() - ui.find_by_name("game_button_bar"):show() - else - menudata.worldlist:set_filtercriteria(nil) - local gamebar = ui.find_by_name("game_button_bar") - if gamebar then - gamebar:hide() - end - core.set_topleft_text("") - mm_game_theme.update(new_tab,nil) + singleplayer_refresh_gamebar() + ui.find_by_name("game_button_bar"):show() + else + menudata.worldlist:set_filtercriteria(nil) + local gamebar = ui.find_by_name("game_button_bar") + if gamebar then + gamebar:hide() end + core.set_topleft_text("") + mm_game_theme.update(new_tab,nil) end end diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index fb7409864..899f30bd1 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -87,27 +87,34 @@ local function get_formspec(tabview, name, tabdata) "field[4.25,0.5;1.25,0.75;te_port;;" .. core.formspec_escape(core.settings:get("remote_port")) .. "]" .. - -- Name / Password - "label[0.25,1.55;" .. fgettext("Name") .. "]" .. - "label[3,1.55;" .. fgettext("Password") .. "]" .. - "field[0.25,1.75;2.75,0.75;te_name;;" .. - core.formspec_escape(core.settings:get("name")) .. "]" .. - "pwdfield[3,1.75;2.5,0.75;te_pwd;]" .. - -- Description Background - "label[0.25,2.75;" .. fgettext("Server Description") .. "]" .. - "box[0.25,3;5.25,2.75;#999999]".. + "label[0.25,1.6;" .. fgettext("Server Description") .. "]" .. + "box[0.25,1.85;5.25,2.7;#999999]".. + + -- Name / Password + "container[0,4.8]" .. + "label[0.25,0;" .. fgettext("Name") .. "]" .. + "label[3,0;" .. fgettext("Password") .. "]" .. + "field[0.25,0.2;2.625,0.75;te_name;;" .. core.formspec_escape(core.settings:get("name")) .. "]" .. + "pwdfield[2.875,0.2;2.625,0.75;te_pwd;]" .. + "container_end[]" .. -- Connect - "button[3,6;2.5,0.75;btn_mp_connect;" .. fgettext("Connect") .. "]" + "button[3,6;2.5,0.75;btn_mp_login;" .. fgettext("Login") .. "]" + + if core.settings:get_bool("enable_split_login_register") then + retval = retval .. "button[0.25,6;2.5,0.75;btn_mp_register;" .. fgettext("Register") .. "]" + end if tabdata.selected then if gamedata.fav then - retval = retval .. "button[0.25,6;2.5,0.75;btn_delete_favorite;" .. - fgettext("Del. Favorite") .. "]" + retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]" + retval = retval .. "style[btn_delete_favorite;padding=6]" + retval = retval .. "image_button[5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir .. + "server_favorite_delete.png") .. ";btn_delete_favorite;]" end if gamedata.serverdescription then - retval = retval .. "textarea[0.25,3;5.25,2.75;;;" .. + retval = retval .. "textarea[0.25,1.85;5.2,2.75;;;" .. core.formspec_escape(gamedata.serverdescription) .. "]" end end @@ -339,12 +346,15 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end - if (fields.btn_mp_connect or fields.key_enter) + if (fields.btn_mp_login or fields.key_enter) and fields.te_address ~= "" and fields.te_port then gamedata.playername = fields.te_name gamedata.password = fields.te_pwd gamedata.address = fields.te_address gamedata.port = tonumber(fields.te_port) + + local enable_split_login_register = core.settings:get_bool("enable_split_login_register") + gamedata.allow_login_or_register = enable_split_login_register and "login" or "any" gamedata.selected_world = 0 local idx = core.get_table_index("servers") @@ -381,6 +391,25 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end + if fields.btn_mp_register and fields.te_address ~= "" and fields.te_port then + local idx = core.get_table_index("servers") + local server = idx and tabdata.lookup[idx] + if server and (server.address ~= fields.te_address or server.port ~= tonumber(fields.te_port)) then + server = nil + end + + if server and not is_server_protocol_compat_or_error( + server.proto_min, server.proto_max) then + return true + end + + local dlg = create_register_dialog(fields.te_address, tonumber(fields.te_port), server) + dlg:set_parent(tabview) + tabview:hide() + dlg:show() + return true + end + return false end diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 700b7390f..21c77aa8e 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -50,7 +50,7 @@ local labels = { fgettext("Low"), fgettext("Medium"), fgettext("High"), - fgettext("Ultra High") + fgettext("Very High") } } @@ -160,7 +160,7 @@ local function formspec(tabview, name, tabdata) .. getSettingIndex.NodeHighlighting() .. "]" .. "dropdown[0.25,3.6;3.5;dd_leaves_style;" .. dd_options.leaves[1] .. ";" .. getSettingIndex.Leaves() .. "]" .. - "box[4,0;3.75,4.5;#999999]" .. + "box[4,0;3.75,4.9;#999999]" .. "label[4.25,0.1;" .. fgettext("Texturing:") .. "]" .. "dropdown[4.25,0.55;3.5;dd_filters;" .. dd_options.filters[1] .. ";" .. getSettingIndex.Filter() .. "]" .. @@ -169,9 +169,6 @@ local function formspec(tabview, name, tabdata) "label[4.25,2.15;" .. fgettext("Antialiasing:") .. "]" .. "dropdown[4.25,2.6;3.5;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";" .. getSettingIndex.Antialiasing() .. "]" .. - "label[4.25,3.45;" .. fgettext("Screen:") .. "]" .. - "checkbox[4.25,3.6;cb_autosave_screensize;" .. fgettext("Autosave Screen Size") .. ";" - .. dump(core.settings:get_bool("autosave_screensize")) .. "]" .. "box[8,0;3.75,4.5;#999999]" local video_driver = core.settings:get("video_driver") @@ -203,10 +200,15 @@ local function formspec(tabview, name, tabdata) if core.settings:get("touchscreen_threshold") ~= nil then tab_string = tab_string .. - "label[4.3,4.2;" .. fgettext("Touchthreshold: (px)") .. "]" .. - "dropdown[4.25,4.65;3.5;dd_touchthreshold;0,10,20,30,40,50;" .. + "label[4.25,3.5;" .. fgettext("Touch threshold (px):") .. "]" .. + "dropdown[4.25,3.95;3.5;dd_touchthreshold;0,10,20,30,40,50;" .. ((tonumber(core.settings:get("touchscreen_threshold")) / 10) + 1) .. - "]box[4.0,4.5;3.75,1.0;#999999]" + "]" + else + tab_string = tab_string .. + "label[4.25,3.65;" .. fgettext("Screen:") .. "]" .. + "checkbox[4.25,3.9;cb_autosave_screensize;" .. fgettext("Autosave Screen Size") .. ";" + .. dump(core.settings:get_bool("autosave_screensize")) .. "]" end if shaders_enabled then @@ -219,9 +221,18 @@ local function formspec(tabview, name, tabdata) .. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" .. "checkbox[8.25,2;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" .. dump(core.settings:get_bool("enable_waving_plants")) .. "]" - --"label[8.25,3.0;" .. fgettext("Dynamic shadows: ") .. "]" .. - --"dropdown[8.25,3.5;3.5;dd_shadows;" .. dd_options.shadow_levels[1] .. ";" - -- .. getSettingIndex.ShadowMapping() .. "]" + + if video_driver == "opengl" then + tab_string = tab_string .. + "label[8.25,2.8;" .. fgettext("Dynamic shadows:") .. "]" .. + "label[8.25,3.2;" .. fgettext("(game support required)") .. "]" .. + "dropdown[8.25,3.7;3.5;dd_shadows;" .. dd_options.shadow_levels[1] .. ";" + .. getSettingIndex.ShadowMapping() .. "]" + else + tab_string = tab_string .. + "label[8.38,2.7;" .. core.colorize("#888888", + fgettext("Dynamic shadows")) .. "]" + end else tab_string = tab_string .. "label[8.38,0.7;" .. core.colorize("#888888", @@ -231,9 +242,9 @@ local function formspec(tabview, name, tabdata) "label[8.38,1.7;" .. core.colorize("#888888", fgettext("Waving Leaves")) .. "]" .. "label[8.38,2.2;" .. core.colorize("#888888", - fgettext("Waving Plants")) .. "]" - --"label[8.38,2.7;" .. core.colorize("#888888", - -- fgettext("Dynamic shadows")) .. "]" + fgettext("Waving Plants")) .. "]".. + "label[8.38,2.7;" .. core.colorize("#888888", + fgettext("Dynamic shadows")) .. "]" end return tab_string @@ -364,11 +375,11 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.settings:set("enable_dynamic_shadows", "false") else local shadow_presets = { - [2] = { 80, 512, "true", 0, "false" }, - [3] = { 120, 1024, "true", 1, "false" }, - [4] = { 350, 2048, "true", 1, "false" }, - [5] = { 350, 2048, "true", 2, "true" }, - [6] = { 450, 4096, "true", 2, "true" }, + [2] = { 62, 512, "true", 0, "false" }, + [3] = { 93, 1024, "true", 0, "false" }, + [4] = { 140, 2048, "true", 1, "false" }, + [5] = { 210, 4096, "true", 2, "true" }, + [6] = { 300, 8192, "true", 2, "true" }, } local s = shadow_presets[table.indexof(labels.shadow_levels, fields["dd_shadows"])] if s then diff --git a/builtin/mainmenu/tests/serverlistmgr_spec.lua b/builtin/mainmenu/tests/serverlistmgr_spec.lua index a091959fb..ab7a6c60c 100644 --- a/builtin/mainmenu/tests/serverlistmgr_spec.lua +++ b/builtin/mainmenu/tests/serverlistmgr_spec.lua @@ -1,4 +1,5 @@ _G.core = {} +_G.vector = {metatable = {}} _G.unpack = table.unpack _G.serverlistmgr = {} |