From d5e4f8eee5555d8d371217bf6a5324e02c55575f Mon Sep 17 00:00:00 2001 From: siliconsniffer Date: Wed, 8 Jan 2025 11:35:06 +0100 Subject: [PATCH 1/4] Add last visited servers section --- LICENSE.txt | 3 + builtin/mainmenu/serverlistmgr.lua | 86 ++++++++++++++++++++++++++ builtin/mainmenu/tab_online.lua | 38 ++++++++++-- textures/base/pack/server_visited.png | Bin 0 -> 333 bytes 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 textures/base/pack/server_visited.png diff --git a/LICENSE.txt b/LICENSE.txt index f7930f5283b8..7d45b8a24b85 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -55,6 +55,9 @@ srifqi: textures/base/pack/joystick_off.png textures/base/pack/minimap_btn.png +siliconsniffer: + textures/base/pack/server_visited.png + Zughy: textures/base/pack/cdb_downloading.png textures/base/pack/cdb_queued.png diff --git a/builtin/mainmenu/serverlistmgr.lua b/builtin/mainmenu/serverlistmgr.lua index 1b69d7a5551f..855dd82fffc2 100644 --- a/builtin/mainmenu/serverlistmgr.lua +++ b/builtin/mainmenu/serverlistmgr.lua @@ -22,6 +22,9 @@ serverlistmgr = { -- list of locally favorites servers favorites = nil, + -- list of last visited servers + last_visited = nil, + -- list of servers fetched from public list servers = nil, } @@ -231,6 +234,15 @@ local function get_favorites_path(folder) return base .. core.settings:get("serverlist_file") end +-------------------------------------------------------------------------------- +local function get_last_visited_path(folder) + local base = core.get_user_path() .. DIR_DELIM .. "client" .. DIR_DELIM .. "serverlist" .. DIR_DELIM + if folder then + return base + end + return base .. "last_visited.json" +end + -------------------------------------------------------------------------------- local function save_favorites(favorites) local filename = core.settings:get("serverlist_file") @@ -243,6 +255,12 @@ local function save_favorites(favorites) core.safe_file_write(get_favorites_path(), core.write_json(favorites)) end +-------------------------------------------------------------------------------- +local function save_last_visited(visited) + assert(core.create_dir(get_last_visited_path(true))) + core.safe_file_write(get_last_visited_path(), core.write_json(visited)) +end + -------------------------------------------------------------------------------- function serverlistmgr.read_legacy_favorites(path) local file = io.open(path, "r") @@ -326,6 +344,21 @@ local function read_favorites() return favs end +-------------------------------------------------------------------------------- +local function read_last_visited() + local path = get_last_visited_path() + + local file = io.open(path, "r") + if not file then + return {} + end + + local json = file:read("*all") + file:close() + + return core.parse_json(json) +end + -------------------------------------------------------------------------------- local function delete_favorite(favorites, del_favorite) for i=1, #favorites do @@ -338,6 +371,18 @@ local function delete_favorite(favorites, del_favorite) end end +-------------------------------------------------------------------------------- +local function delete_last_visited(visited, del_visited) + for i=1, #visited do + local vis = visited[i] + + if vis.address == del_visited.address and vis.port == del_visited.port then + table.remove(visited, i) + return + end + end +end + -------------------------------------------------------------------------------- function serverlistmgr.get_favorites() if serverlistmgr.favorites then @@ -359,6 +404,16 @@ function serverlistmgr.get_favorites() return serverlistmgr.favorites end +------------------------------------------------------------------------------- +function serverlistmgr.get_last_visited() + if serverlistmgr.last_visited then + return serverlistmgr.last_visited + end + + serverlistmgr.last_visited = read_last_visited() + return serverlistmgr.last_visited +end + -------------------------------------------------------------------------------- function serverlistmgr.add_favorite(new_favorite) assert(type(new_favorite.port) == "number") @@ -377,9 +432,40 @@ function serverlistmgr.add_favorite(new_favorite) save_favorites(favorites) end +------------------------------------------------------------------------------- +function serverlistmgr.add_last_visited(new_visited) + assert(type(new_visited.port) == "number") + assert(new_visited.address) + + -- Whitelist visited keys + new_visited = { + name = new_visited.name, + address = new_visited.address, + port = new_visited.port, + description = new_visited.description, + } + + local visited = serverlistmgr.get_last_visited() + delete_last_visited(visited, new_visited) + table.insert(visited, 1, new_visited) + + if #visited > 5 then + table.remove(visited, #visited) + end + + save_last_visited(visited) +end + -------------------------------------------------------------------------------- function serverlistmgr.delete_favorite(del_favorite) local favorites = serverlistmgr.get_favorites() delete_favorite(favorites, del_favorite) save_favorites(favorites) end + +------------------------------------------------------------------------------- +function serverlistmgr.delete_last_visited(del_visited) + local visited = serverlistmgr.get_last_visited() + delete_last_visited(visited, del_visited) + save_last_visited(visited) +end diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 02c6a9c24061..51c70ba137f5 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -18,15 +18,20 @@ local function get_sorted_servers() local servers = { fav = {}, + visited = {}, public = {}, incompatible = {} } local favs = serverlistmgr.get_favorites() local taken_favs = {} + local visited_list = serverlistmgr.get_last_visited() + local taken_visited = {} + local result = menudata.search_result or serverlistmgr.servers for _, server in ipairs(result) do server.is_favorite = false + server.is_visited = false for index, fav in ipairs(favs) do if server.address == fav.address and server.port == fav.port then taken_favs[index] = true @@ -34,9 +39,20 @@ local function get_sorted_servers() break end end + + for index, visited in ipairs(visited_list) do + if server.address == visited.address and server.port == visited.port then + taken_visited[index] = true + server.is_visited = true + break + end + end + server.is_compatible = is_server_protocol_compat(server.proto_min, server.proto_max) if server.is_favorite then table.insert(servers.fav, server) + elseif server.is_visited then + table.insert(servers.visited, server) elseif server.is_compatible then table.insert(servers.public, server) else @@ -50,6 +66,14 @@ local function get_sorted_servers() table.insert(servers.fav, fav) end end + for index, visited in ipairs(visited_list) do + if not taken_visited[index] then + table.insert(servers.visited, visited) + if #servers.visited >= 5 then + break -- Limit to 5 visited servers + end + end + end end return servers @@ -211,8 +235,9 @@ local function get_formspec(tabview, name, tabdata) "3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," .. "4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png") .. "," .. "5=" .. core.formspec_escape(defaulttexturedir .. "server_favorite.png") .. "," .. - "6=" .. core.formspec_escape(defaulttexturedir .. "server_public.png") .. "," .. - "7=" .. core.formspec_escape(defaulttexturedir .. "server_incompatible.png") .. ";" .. + "6=" .. core.formspec_escape(defaulttexturedir .. "server_visited.png") .. "," .. + "7=" .. core.formspec_escape(defaulttexturedir .. "server_public.png") .. "," .. + "8=" .. core.formspec_escape(defaulttexturedir .. "server_incompatible.png") .. ";" .. "color,span=1;" .. "text,align=inline;".. "color,span=1;" .. @@ -235,10 +260,11 @@ local function get_formspec(tabview, name, tabdata) local dividers = { fav = "5,#ffff00," .. fgettext("Favorites") .. ",,,0,0,,", - public = "6,#4bdd42," .. fgettext("Public Servers") .. ",,,0,0,,", - incompatible = "7,"..mt_color_grey.."," .. fgettext("Incompatible Servers") .. ",,,0,0,," + visited = "6,#ff9900," .. fgettext("Last Visited") .. ",,,0,0,,", + public = "7,#4bdd42," .. fgettext("Public Servers") .. ",,,0,0,,", + incompatible = "8,"..mt_color_grey.."," .. fgettext("Incompatible Servers") .. ",,,0,0,," } - local order = {"fav", "public", "incompatible"} + local order = {"fav", "visited", "public", "incompatible"} tabdata.lookup = {} -- maps row number to server local rows = {} @@ -509,7 +535,7 @@ local function main_button_handler(tabview, fields, name, tabdata) if server and server.address == gamedata.address and server.port == gamedata.port then - serverlistmgr.add_favorite(server) + serverlistmgr.add_last_visited(server) gamedata.servername = server.name gamedata.serverdescription = server.description diff --git a/textures/base/pack/server_visited.png b/textures/base/pack/server_visited.png new file mode 100644 index 0000000000000000000000000000000000000000..d785f187fa6afa2e6b3bd89646b6e4bc161b5f84 GIT binary patch literal 333 zcmV-T0kZyyP)5f8C0ruFaRt5vrYAD$3Sy^eI{nFHsu}YVTJ0`2^kSG7>*+lJYhl^@0&+W% z#ncViMJQa;Q^SXYl2;+Y#S~0!O{n*wP%)hMCi9ByPAT1iPJqlsA_}#jwu)jJ`oviB z7iU`C#QDp}my#ufIM(xEWjW|=TN4B=G%zsYioqwHtTp7^1YypSQq&9pG63SF^;xS3 zR$7eaP=o;Wt47mPZJM-69}G+$5Z2=vcpuJL!8ckkN5nE fKfC<3|9=KwJy(ShKHGLJ00000NkvXXu0mjfm8Fc& literal 0 HcmV?d00001 From 29731792ed9775909923aba5f0b76a395eab654e Mon Sep 17 00:00:00 2001 From: siliconsniffer Date: Wed, 8 Jan 2025 17:32:22 +0100 Subject: [PATCH 2/4] exclude last_visited from server ranking --- builtin/mainmenu/serverlistmgr.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/builtin/mainmenu/serverlistmgr.lua b/builtin/mainmenu/serverlistmgr.lua index 855dd82fffc2..cc1133cd35e8 100644 --- a/builtin/mainmenu/serverlistmgr.lua +++ b/builtin/mainmenu/serverlistmgr.lua @@ -116,12 +116,14 @@ local function order_server_list_internal(list) end local function order_server_list(list) - -- split the list into two parts and sort them separately, to keep empty + -- split the list into three parts and sort them separately, to keep empty -- servers at the bottom. - local nonempty, empty = {}, {} + local visited, nonempty, empty = {}, {}, {} for _, fav in ipairs(list) do - if (fav.clients or 0) > 0 then + if fav.last_visited then + table.insert(visited, fav) + elseif (fav.clients or 0) > 0 then table.insert(nonempty, fav) else table.insert(empty, fav) @@ -131,8 +133,11 @@ local function order_server_list(list) order_server_list_internal(nonempty) order_server_list_internal(empty) - table.insert_all(nonempty, empty) - return nonempty + local result = {} + table.insert_all(result, visited) + table.insert_all(result, nonempty) + table.insert_all(result, empty) + return result end local public_downloading = false From 217553988a2595ee106f4e4d85d90f8bb45a9d4f Mon Sep 17 00:00:00 2001 From: siliconsniffer Date: Wed, 8 Jan 2025 22:07:59 +0100 Subject: [PATCH 3/4] move selection down when removing server from favs --- builtin/mainmenu/tab_online.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 51c70ba137f5..7d598a586f7f 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -472,12 +472,10 @@ local function main_button_handler(tabview, fields, name, tabdata) if fields.btn_delete_favorite then local idx = core.get_table_index("servers") - if not idx then return end - local server = tabdata.lookup[idx] - if not server then return end + local server = find_selected_server() serverlistmgr.delete_favorite(server) - set_selected_server(server) + set_selected_server(tabdata.lookup[idx+1]) return true end From 1f02036a4f2a0f54bcca43d72024879e881dc13c Mon Sep 17 00:00:00 2001 From: siliconsniffer Date: Thu, 9 Jan 2025 09:37:59 +0100 Subject: [PATCH 4/4] make section collapsible --- builtin/mainmenu/tab_online.lua | 46 +++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 7d598a586f7f..e28436e2f83f 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -15,6 +15,7 @@ --with this program; if not, write to the Free Software Foundation, Inc., --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +local last_visited_collapsed = false local function get_sorted_servers() local servers = { fav = {}, @@ -51,7 +52,7 @@ local function get_sorted_servers() server.is_compatible = is_server_protocol_compat(server.proto_min, server.proto_max) if server.is_favorite then table.insert(servers.fav, server) - elseif server.is_visited then + elseif server.is_visited and not last_visited_collapsed then table.insert(servers.visited, server) elseif server.is_compatible then table.insert(servers.public, server) @@ -72,6 +73,12 @@ local function get_sorted_servers() if #servers.visited >= 5 then break -- Limit to 5 visited servers end + else + if visited.is_compatible ~= false then -- Only add if not explicitly incompatible + table.insert(servers.public, visited) + else + table.insert(servers.incompatible, visited) + end end end end @@ -260,7 +267,7 @@ local function get_formspec(tabview, name, tabdata) local dividers = { fav = "5,#ffff00," .. fgettext("Favorites") .. ",,,0,0,,", - visited = "6,#ff9900," .. fgettext("Last Visited") .. ",,,0,0,,", + visited = "6,#ff9900," .. fgettext("Last Visited") .. (last_visited_collapsed and " ►" or " ▼") .. ",,,0,0,,", public = "7,#4bdd42," .. fgettext("Public Servers") .. ",,,0,0,,", incompatible = "8,"..mt_color_grey.."," .. fgettext("Incompatible Servers") .. ",,,0,0,," } @@ -269,15 +276,27 @@ local function get_formspec(tabview, name, tabdata) tabdata.lookup = {} -- maps row number to server local rows = {} for _, section in ipairs(order) do - local section_servers = servers[section] - if next(section_servers) ~= nil then - rows[#rows + 1] = dividers[section] - for _, server in ipairs(section_servers) do - tabdata.lookup[#rows + 1] = server - rows[#rows + 1] = render_serverlist_row(server) - end - end - end + local section_servers = servers[section] + if section == "visited" then + -- Always show the visited divider, even when collapsed + tabdata.lookup[#rows + 1] = "last_visited_divider" + rows[#rows + 1] = dividers[section] + + -- Only add the servers if not collapsed and there are servers to show + if not last_visited_collapsed and next(section_servers) ~= nil then + for _, server in ipairs(section_servers) do + tabdata.lookup[#rows + 1] = server + rows[#rows + 1] = render_serverlist_row(server) + end + end + elseif next(section_servers) ~= nil then + rows[#rows + 1] = dividers[section] + for _, server in ipairs(section_servers) do + tabdata.lookup[#rows + 1] = server + rows[#rows + 1] = render_serverlist_row(server) + end + end +end retval = retval .. table.concat(rows, ",") @@ -440,6 +459,11 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end + if tabdata.lookup[event.row] == "last_visited_divider" then + last_visited_collapsed = not last_visited_collapsed + return true + end + gamedata.address = server.address gamedata.port = server.port gamedata.playername = fields.te_name