From 3d259667d706e76feb91b5faec2ba1e7f31c4805 Mon Sep 17 00:00:00 2001 From: AyeZeeBB Date: Wed, 7 Oct 2026 00:28:58 -0500 Subject: [PATCH] Sort servers by players by default; allow / in server names - The server browser opens sorted by most players, in the overlay and the native menu; official and friends' servers still come first - Dedicated server names may contain "/" (builds before this hide a server whose name has one) --- Engine/Game/Multiplayer/session_model.h | 6 +++--- Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp | 7 ++++--- Extension/UI/NativeMenu/native_menu_view.h | 3 ++- Extension/UI/Overlay/skate_menu.h | 2 +- Server/README.txt | 2 +- Server/Test/server_config_tests.cpp | 5 +++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Engine/Game/Multiplayer/session_model.h b/Engine/Game/Multiplayer/session_model.h index cb90d400..1e24eae1 100644 --- a/Engine/Game/Multiplayer/session_model.h +++ b/Engine/Game/Multiplayer/session_model.h @@ -13,16 +13,16 @@ namespace dingosdk { constexpr unsigned max_map_rotation = 1440; // minutes a server's rotation keeps one map, at most -// A dedicated server's name: 1 to 64 letters, digits, spaces and - _ [ ] ( ), with a +// A dedicated server's name: 1 to 64 letters, digits, spaces and - _ / [ ] ( ), with a // letter or digit among them and no space at either end. A server refuses any other // name, and the server browser does not show one. -inline constexpr char server_name_rule[] = "1 to 64 letters, numbers, spaces and - _ [ ] ( )"; +inline constexpr char server_name_rule[] = "1 to 64 letters, numbers, spaces and - _ / [ ] ( )"; [[nodiscard]] constexpr bool valid_server_name(std::string_view name) noexcept { if (name.empty() || name.size() > 64 || name.front() == ' ' || name.back() == ' ') return false; bool named{}; for (const auto c : name) { const bool word = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); - if (!word && std::string_view(" -_[]()").find(c) == std::string_view::npos) return false; + if (!word && std::string_view(" -_/[]()").find(c) == std::string_view::npos) return false; named |= word; } return named; diff --git a/Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp b/Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp index c3141ded..9eb463be 100644 --- a/Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp +++ b/Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp @@ -57,6 +57,7 @@ int main() { check(missing_tabs({1, 2, 3, 4}, 8, false) == std::vector{0}, "The Multiplayer page does not wait for the overlay's tool callbacks"); MultiplayerModel model; + const BrowserOptions by_name{{}, false, Sort::name}; model.local_id = 77; model.map = "Levels/San_Vansterdam"; for (unsigned i = 0; i < 14; ++i) { MultiplayerLobby lobby; @@ -66,7 +67,7 @@ int main() { lobby.players = static_cast(i + 1); lobby.capacity = 16; model.lobbies.push_back(lobby); } - auto result = browse(model, {}); + auto result = browse(model, by_name); check(result.total == 14 && result.lobbies.size() == 14, "All matching lobbies remain scrollable"); check(result.lobbies.front()->id == 100 && result.lobbies[6]->id == 112 && result.lobbies.back()->id == 113, "Stable ordering of duplicate names across the full list"); @@ -84,12 +85,12 @@ int main() { result = browse(model, options); check(result.lobbies[0]->id == 105 && result.lobbies[1]->id == 102 && result.lobbies[2]->players == 14, "Official servers are not first when sorting by players"); - result = browse(model, {}); + result = browse(model, by_name); check(result.lobbies[0]->id == 102 && result.lobbies[1]->id == 105 && result.lobbies[2]->id == 100, "Official servers are not first when sorting by name"); // Then the servers friends are in, which a search for a friend's name finds too. model.lobbies[9].friends = {"Ana"}; - result = browse(model, {}); + result = browse(model, by_name); check(result.lobbies[0]->id == 102 && result.lobbies[1]->id == 105 && result.lobbies[2]->id == 109 && result.lobbies[3]->id == 100, "A friend's server is not next after the official ones"); BrowserOptions by_friend; diff --git a/Extension/UI/NativeMenu/native_menu_view.h b/Extension/UI/NativeMenu/native_menu_view.h index 67986d2d..07076633 100644 --- a/Extension/UI/NativeMenu/native_menu_view.h +++ b/Extension/UI/NativeMenu/native_menu_view.h @@ -8,7 +8,8 @@ namespace dingosdk::multiplayer::menu_view { enum class Sort { name, players, map }; -struct BrowserOptions { std::string query; bool same_map{}; Sort sort{}; }; +// The busiest servers first, until the player picks another order. +struct BrowserOptions { std::string query; bool same_map{}; Sort sort = Sort::players; }; // Owned pages: Multiplayer and Custom Stuff (needs the overlay's tool callbacks). inline constexpr unsigned page_count = 2, tools_page = 1; diff --git a/Extension/UI/Overlay/skate_menu.h b/Extension/UI/Overlay/skate_menu.h index 111c6390..9fd1223a 100644 --- a/Extension/UI/Overlay/skate_menu.h +++ b/Extension/UI/Overlay/skate_menu.h @@ -31,7 +31,7 @@ struct SkateMenu { std::optional map_rotation_pending; // the rotation slider, likewise double map_rotation_until{}; bool ban_confirm_on_server{}; // the Ban popup bans from a dedicated server - int multiplayer_lobby_sort = 0; + int multiplayer_lobby_sort = 1; // most players first float multiplayer_code_height = 0; // what the join-by-code card took last frame // Bans: the manual add form, and the player a Ban button is asking about. std::array ban_id{}; diff --git a/Server/README.txt b/Server/README.txt index ac77a8dd..b3faa69b 100644 --- a/Server/README.txt +++ b/Server/README.txt @@ -42,7 +42,7 @@ straight away (players are told to rejoin). Turn this off with ReSkateServer.json ------------------ -name Shown in the browser: 1-64 letters, numbers, spaces and - _ [ ] ( ). +name Shown in the browser: 1-64 letters, numbers, spaces and - _ / [ ] ( ). map The map everyone skates, named like the game's load command: "San Vansterdam", "Isle of Grom", "Super Ultra Mega Resort", "Stadium 1", or a custom map such as "bbcity" (see Custom maps). diff --git a/Server/Test/server_config_tests.cpp b/Server/Test/server_config_tests.cpp index a16a5bd3..d887d295 100644 --- a/Server/Test/server_config_tests.cpp +++ b/Server/Test/server_config_tests.cpp @@ -62,8 +62,9 @@ int run() { check(token_refused(tokened), "An overlong steam_token was accepted"); save_config(reloaded); - // Server names: letters, digits, spaces and - _ [ ] ( ) only. - check(valid_server_name("Old Server") && valid_server_name("[EU] Skate_Park-2 (24x7)") && valid_server_name("a"), + // Server names: letters, digits, spaces and - _ / [ ] ( ) only. + check(valid_server_name("Old Server") && valid_server_name("[EU] Skate_Park-2 (24x7)") && valid_server_name("a") && + valid_server_name("EU/West 24/7") && !valid_server_name("///") && !valid_server_name("a\\b"), "A plain server name was refused"); check(!valid_server_name("") && !valid_server_name(std::string(65, 'a')) && !valid_server_name("Best! Server") && !valid_server_name("caf\xC3\xA9") && !valid_server_name("a.b") && !valid_server_name("x") &&