mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-15 18:57:08 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
80c0410442
769 changed files with 137450 additions and 85683 deletions
|
@ -1,19 +1,6 @@
|
|||
--Luanti
|
||||
--Copyright (C) 2014 sapier
|
||||
--
|
||||
--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.
|
||||
-- Luanti
|
||||
-- Copyright (C) 2014 sapier
|
||||
-- SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
local function get_sorted_servers()
|
||||
local servers = {
|
||||
|
@ -129,6 +116,7 @@ local function get_formspec(tabview, name, tabdata)
|
|||
local retval =
|
||||
-- Search
|
||||
"field[0.25,0.25;7,0.75;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" ..
|
||||
"tooltip[te_search;" .. fgettext("Possible filters\ngame:<name>\nmod:<name>\nplayer:<name>") .. "]" ..
|
||||
"field_enter_after_edit[te_search;true]" ..
|
||||
"container[7.25,0.25]" ..
|
||||
"image_button[0,0;0.75,0.75;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" ..
|
||||
|
@ -177,6 +165,26 @@ local function get_formspec(tabview, name, tabdata)
|
|||
core.formspec_escape(gamedata.serverdescription) .. "]"
|
||||
end
|
||||
|
||||
-- Mods button
|
||||
local mods = selected_server.mods
|
||||
if mods and #mods > 0 then
|
||||
local tooltip = ""
|
||||
if selected_server.gameid then
|
||||
tooltip = fgettext("Game: $1", selected_server.gameid) .. "\n"
|
||||
end
|
||||
tooltip = tooltip .. fgettext("Number of mods: $1", #mods)
|
||||
|
||||
retval = retval ..
|
||||
"tooltip[btn_view_mods;" .. tooltip .. "]" ..
|
||||
"style[btn_view_mods;padding=6]" ..
|
||||
"image_button[4,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
|
||||
"server_view_mods.png") .. ";btn_view_mods;]"
|
||||
else
|
||||
retval = retval .. "image[4.1,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
|
||||
"server_view_mods_unavailable.png") .. "]"
|
||||
end
|
||||
|
||||
-- Clients list button
|
||||
local clients_list = selected_server.clients_list
|
||||
local can_view_clients_list = clients_list and #clients_list > 0
|
||||
if can_view_clients_list then
|
||||
|
@ -186,23 +194,31 @@ local function get_formspec(tabview, name, tabdata)
|
|||
local max_clients = 5
|
||||
if #clients_list > max_clients then
|
||||
retval = retval .. "tooltip[btn_view_clients;" ..
|
||||
fgettext("Clients:\n$1", table.concat(clients_list, "\n", 1, max_clients)) .. "\n..." .. "]"
|
||||
fgettext("Players:\n$1", table.concat(clients_list, "\n", 1, max_clients)) .. "\n..." .. "]"
|
||||
else
|
||||
retval = retval .. "tooltip[btn_view_clients;" ..
|
||||
fgettext("Clients:\n$1", table.concat(clients_list, "\n")) .. "]"
|
||||
fgettext("Players:\n$1", table.concat(clients_list, "\n")) .. "]"
|
||||
end
|
||||
retval = retval .. "style[btn_view_clients;padding=6]"
|
||||
retval = retval .. "image_button[4.5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
|
||||
"server_view_clients.png") .. ";btn_view_clients;]"
|
||||
else
|
||||
retval = retval .. "image[4.6,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
|
||||
"server_view_clients_unavailable.png") .. "]"
|
||||
end
|
||||
|
||||
-- URL button
|
||||
if selected_server.url then
|
||||
retval = retval .. "tooltip[btn_server_url;" .. fgettext("Open server website") .. "]"
|
||||
retval = retval .. "style[btn_server_url;padding=6]"
|
||||
retval = retval .. "image_button[" .. (can_view_clients_list and "4" or "4.5") .. ",1.3;0.5,0.5;" ..
|
||||
retval = retval .. "image_button[3.5,1.3;0.5,0.5;" ..
|
||||
core.formspec_escape(defaulttexturedir .. "server_url.png") .. ";btn_server_url;]"
|
||||
else
|
||||
retval = retval .. "image[3.6,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
|
||||
"server_url_unavailable.png") .. "]"
|
||||
end
|
||||
|
||||
-- Favorites toggle button
|
||||
if is_selected_fav() then
|
||||
retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]"
|
||||
retval = retval .. "style[btn_delete_favorite;padding=6]"
|
||||
|
@ -289,19 +305,109 @@ end
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function search_server_list(input)
|
||||
local function parse_search_input(input)
|
||||
if not input:find("%S") then
|
||||
return -- Return nil if nothing to search for
|
||||
end
|
||||
|
||||
-- Search is not case sensitive
|
||||
input = input:lower()
|
||||
|
||||
local query = {keywords = {}, mods = {}, players = {}}
|
||||
|
||||
-- Process quotation enclosed parts
|
||||
input = input:gsub('(%S?)"([^"]*)"(%S?)', function(before, match, after)
|
||||
if before == "" and after == "" then -- Also have be separated by spaces
|
||||
table.insert(query.keywords, match)
|
||||
return " "
|
||||
end
|
||||
return before..'"'..match..'"'..after
|
||||
end)
|
||||
|
||||
-- Separate by space characters and handle special prefixes
|
||||
-- (words with special prefixes need an exact match and none of them can contain spaces)
|
||||
for word in input:gmatch("%S+") do
|
||||
local mod = word:match("^mod:(.*)")
|
||||
table.insert(query.mods, mod)
|
||||
local player = word:match("^player:(.*)")
|
||||
table.insert(query.players, player)
|
||||
local game = word:match("^game:(.*)")
|
||||
query.game = query.game or game
|
||||
if not (mod or player or game) then
|
||||
table.insert(query.keywords, word)
|
||||
end
|
||||
end
|
||||
|
||||
return query
|
||||
end
|
||||
|
||||
-- Prepares the server to be used for searching
|
||||
local function uncapitalize_server(server)
|
||||
local function table_lower(t)
|
||||
local r = {}
|
||||
for i, s in ipairs(t or {}) do
|
||||
r[i] = s:lower()
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
return {
|
||||
name = (server.name or ""):lower(),
|
||||
description = (server.description or ""):lower(),
|
||||
gameid = (server.gameid or ""):lower(),
|
||||
mods = table_lower(server.mods),
|
||||
clients_list = table_lower(server.clients_list),
|
||||
}
|
||||
end
|
||||
|
||||
-- Returns false if the query does not match
|
||||
-- otherwise returns a number to adjust the sorting priority
|
||||
local function matches_query(server, query)
|
||||
-- Search is not case sensitive
|
||||
server = uncapitalize_server(server)
|
||||
|
||||
-- Check if mods found
|
||||
for _, mod in ipairs(query.mods) do
|
||||
if table.indexof(server.mods, mod) < 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if players found
|
||||
for _, player in ipairs(query.players) do
|
||||
if table.indexof(server.clients_list, player) < 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if game matches
|
||||
if query.game and query.game ~= server.gameid then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check if keyword found
|
||||
local name_matches = true
|
||||
local description_matches = true
|
||||
for _, keyword in ipairs(query.keywords) do
|
||||
name_matches = name_matches and server.name:find(keyword, 1, true)
|
||||
description_matches = description_matches and server.description:find(keyword, 1, true)
|
||||
end
|
||||
|
||||
return name_matches and 50 or description_matches and 0
|
||||
end
|
||||
|
||||
local function search_server_list(input, tabdata)
|
||||
menudata.search_result = nil
|
||||
if #serverlistmgr.servers < 2 then
|
||||
return
|
||||
end
|
||||
|
||||
-- setup the keyword list
|
||||
local keywords = {}
|
||||
for word in input:gmatch("%S+") do
|
||||
table.insert(keywords, word:lower())
|
||||
end
|
||||
|
||||
if #keywords == 0 then
|
||||
tabdata.pre_search_selection = tabdata.pre_search_selection or find_selected_server()
|
||||
|
||||
-- setup the search query
|
||||
local query = parse_search_input(input)
|
||||
if not query then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -310,16 +416,9 @@ local function search_server_list(input)
|
|||
-- Search the serverlist
|
||||
local search_result = {}
|
||||
for i, server in ipairs(serverlistmgr.servers) do
|
||||
local name_matches, description_matches = true, true
|
||||
for _, keyword in ipairs(keywords) do
|
||||
name_matches = name_matches and not not
|
||||
(server.name or ""):lower():find(keyword, 1, true)
|
||||
description_matches = description_matches and not not
|
||||
(server.description or ""):lower():find(keyword, 1, true)
|
||||
end
|
||||
if name_matches or description_matches then
|
||||
server.points = #serverlistmgr.servers - i
|
||||
+ (name_matches and 50 or 0)
|
||||
local match = matches_query(server, query)
|
||||
if match then
|
||||
server.points = #serverlistmgr.servers - i + match
|
||||
table.insert(search_result, server)
|
||||
end
|
||||
end
|
||||
|
@ -328,10 +427,32 @@ local function search_server_list(input)
|
|||
return
|
||||
end
|
||||
|
||||
local current_server = find_selected_server()
|
||||
|
||||
table.sort(search_result, function(a, b)
|
||||
return a.points > b.points
|
||||
end)
|
||||
menudata.search_result = search_result
|
||||
|
||||
-- Keep current selection if it's in search results
|
||||
if current_server then
|
||||
for _, server in ipairs(search_result) do
|
||||
if server.address == current_server.address and
|
||||
server.port == current_server.port then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Find first compatible server (favorite or public)
|
||||
for _, server in ipairs(search_result) do
|
||||
if is_server_protocol_compat(server.proto_min, server.proto_max) then
|
||||
set_selected_server(server)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- If no compatible server found, clear selection
|
||||
set_selected_server(nil)
|
||||
end
|
||||
|
||||
local function main_button_handler(tabview, fields, name, tabdata)
|
||||
|
@ -371,6 +492,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||
end
|
||||
if event.type == "CHG" then
|
||||
set_selected_server(server)
|
||||
tabdata.pre_search_selection = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -384,11 +506,9 @@ 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
|
||||
|
||||
serverlistmgr.delete_favorite(server)
|
||||
set_selected_server(server)
|
||||
serverlistmgr.delete_favorite(tabdata.lookup[idx])
|
||||
set_selected_server(tabdata.lookup[idx+1])
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -405,20 +525,27 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||
return true
|
||||
end
|
||||
|
||||
if fields.btn_view_mods then
|
||||
local dlg = create_server_list_mods_dialog(find_selected_server())
|
||||
dlg:set_parent(tabview)
|
||||
tabview:hide()
|
||||
dlg:show()
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mp_clear then
|
||||
tabdata.search_for = ""
|
||||
menudata.search_result = nil
|
||||
if tabdata.pre_search_selection then
|
||||
set_selected_server(tabdata.pre_search_selection)
|
||||
tabdata.pre_search_selection = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mp_search or fields.key_enter_field == "te_search" then
|
||||
tabdata.search_for = fields.te_search
|
||||
search_server_list(fields.te_search:lower())
|
||||
if menudata.search_result then
|
||||
-- Note: This clears the selection if there are no results
|
||||
set_selected_server(menudata.search_result[1])
|
||||
end
|
||||
|
||||
search_server_list(fields.te_search, tabdata)
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue