From b58c514261dac12836c8f4c0af932615eb6a821a Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Wed, 12 Apr 2023 23:41:45 +0200 Subject: [PATCH 1/8] feat: add support for favorites in the server browser --- src/client/component/server_list.cpp | 106 ++++++++++++++++-- src/client/component/server_list.hpp | 6 +- src/client/steam/interfaces/matchmaking.cpp | 13 ++- .../steam/interfaces/matchmaking_servers.cpp | 52 ++++++++- 4 files changed, 159 insertions(+), 18 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 7c0ca6ad..ebca233a 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -6,7 +6,8 @@ #include #include -#include +#include +#include #include "network.hpp" #include "scheduler.hpp" @@ -15,7 +16,7 @@ namespace server_list { namespace { - utils::hook::detour lua_serverinfo_to_table_hook; + utils::hook::detour lua_serverinfo_to_table_hook; struct state { @@ -25,7 +26,9 @@ namespace server_list callback callback{}; }; - utils::concurrency::container master_state; + utils::concurrency::container master_state; + + std::vector favorite_servers{}; void handle_server_list_response(const game::netadr_t& target, const network::data_view& data, state& s) @@ -75,17 +78,63 @@ namespace server_list } callback(true, result); + } + + void lua_serverinfo_to_table_stub(game::hks::lua_State* state, game::ServerInfo serverInfo, int index) + { + lua_serverinfo_to_table_hook.invoke(state, serverInfo, index); + + if (state) + { + auto botCount = atoi(game::Info_ValueForKey(serverInfo.tags, "bots")); + game::Lua_SetTableInt("botCount", botCount, state); + } } - void lua_serverinfo_to_table_stub(game::hks::lua_State* state, game::ServerInfo serverInfo, int index) - { - lua_serverinfo_to_table_hook.invoke(state, serverInfo, index); + std::string get_favorite_servers_file_path() + { + return "players/user/favorite_servers.csv"; + } - if (state) + void write_favorite_servers() + { + std::string servers_buffer = ""; + for (auto itr : favorite_servers) { - auto botCount = atoi(game::Info_ValueForKey(serverInfo.tags, "bots")); - game::Lua_SetTableInt("botCount", botCount, state); - } + servers_buffer.append(utils::string::va("%u,%u\n", itr.addr, itr.port)); + } + + if (servers_buffer.empty()) + { + return; + } + + utils::io::write_file(get_favorite_servers_file_path(), servers_buffer); + } + + void read_favorite_servers() + { + const std::string path = get_favorite_servers_file_path(); + if (!utils::io::file_exists(path)) + { + return; + } + + favorite_servers.clear(); + + std::string filedata; + if (utils::io::read_file(path, &filedata)) + { + auto servers = utils::string::split(filedata, '\n'); + for (auto server_data : servers) + { + auto data = utils::string::split(server_data, ','); + auto addr = std::stoul(data[0].c_str()); + auto port = (uint16_t)atoi(data[1].c_str()); + auto server = network::address_from_ip(addr, port); + favorite_servers.push_back(server); + } + } } } @@ -112,6 +161,37 @@ namespace server_list network::send(s.address, "getservers", utils::string::va("T7 %i full empty", PROTOCOL)); }); + } + + void add_favorite_server(game::netadr_t addr) + { + if (has_favorited_server(addr)) + { + return; + } + + favorite_servers.push_back(addr); + write_favorite_servers(); + } + + void remove_favorite_server(game::netadr_t addr) + { + for (auto it = favorite_servers.begin(); it != favorite_servers.end(); ++it) + { + if (network::are_addresses_equal(*it, addr)) + { + favorite_servers.erase(it); + break; + } + } + + write_favorite_servers(); + } + + bool has_favorited_server(game::netadr_t addr) + { + auto it = std::find_if(favorite_servers.begin(), favorite_servers.end(), [&addr](const game::netadr_t& obj) { return network::are_addresses_equal(addr, obj); }); + return it != favorite_servers.end(); } struct component final : client_component @@ -145,9 +225,11 @@ namespace server_list s.callback(false, {}); s.callback = {}; }); - }, scheduler::async, 200ms); + }, scheduler::async, 200ms); + + lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); - lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); + read_favorite_servers(); } void pre_destroy() override diff --git a/src/client/component/server_list.hpp b/src/client/component/server_list.hpp index 628795d9..d414f4fc 100644 --- a/src/client/component/server_list.hpp +++ b/src/client/component/server_list.hpp @@ -6,5 +6,9 @@ namespace server_list bool get_master_server(game::netadr_t& address); using callback = std::function&)>; - void request_servers(callback callback); + void request_servers(callback callback); + + void add_favorite_server(game::netadr_t addr); + void remove_favorite_server(game::netadr_t addr); + bool has_favorited_server(game::netadr_t addr); } diff --git a/src/client/steam/interfaces/matchmaking.cpp b/src/client/steam/interfaces/matchmaking.cpp index 8b8dec7b..298ab8fe 100644 --- a/src/client/steam/interfaces/matchmaking.cpp +++ b/src/client/steam/interfaces/matchmaking.cpp @@ -1,5 +1,8 @@ #include -#include "../steam.hpp" +#include "../steam.hpp" + +#include "component/network.hpp" +#include "component/server_list.hpp" namespace steam { @@ -18,13 +21,17 @@ namespace steam int matchmaking::AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags, unsigned int rTime32LastPlayedOnServer) - { + { + auto addr = network::address_from_ip(htonl(nIP), nConnPort); + server_list::add_favorite_server(addr); return 0; } bool matchmaking::RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags) - { + { + auto addr = network::address_from_ip(htonl(nIP), nConnPort); + server_list::remove_favorite_server(addr); return false; } diff --git a/src/client/steam/interfaces/matchmaking_servers.cpp b/src/client/steam/interfaces/matchmaking_servers.cpp index 79f0f784..f85f0711 100644 --- a/src/client/steam/interfaces/matchmaking_servers.cpp +++ b/src/client/steam/interfaces/matchmaking_servers.cpp @@ -21,7 +21,8 @@ namespace steam gameserveritem_t server_item{}; }; - auto* const internet_request = reinterpret_cast(1); + auto* const internet_request = reinterpret_cast(1); + auto* const favorites_request = reinterpret_cast(4); using servers = std::vector; @@ -198,7 +199,54 @@ namespace steam void* matchmaking_servers::RequestFavoritesServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters, matchmaking_server_list_response* pRequestServersResponse) { - return reinterpret_cast(4); + current_response = pRequestServersResponse; + + server_list::request_servers([](const bool success, const std::unordered_set& s) + { + const auto res = current_response.load(); + if (!res) + { + return; + } + + if (!success) + { + res->RefreshComplete(favorites_request, eServerFailedToRespond); + return; + } + + if (s.empty()) + { + res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); + return; + } + + queried_servers.access([&s](servers& srvs) + { + srvs = {}; + srvs.reserve(s.size()); + + for (auto& address : s) + { + if (!server_list::has_favorited_server(address)) + { + continue; + } + server new_server{}; + new_server.address = address; + new_server.server_item = create_server_item(address, {}, 0, false); + + srvs.push_back(new_server); + } + }); + + for (auto& srv : s) + { + ping_server(srv); + } + }); + + return favorites_request; } void* matchmaking_servers::RequestHistoryServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters, From 5b62f29942471f264aa55bee959c3d21394f210b Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Thu, 13 Apr 2023 22:13:05 +0200 Subject: [PATCH 2/8] changed favorites file to txt file --- src/client/component/server_list.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index ebca233a..386ee761 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -93,7 +93,7 @@ namespace server_list std::string get_favorite_servers_file_path() { - return "players/user/favorite_servers.csv"; + return "players/user/favorite_servers.txt"; } void write_favorite_servers() @@ -101,12 +101,7 @@ namespace server_list std::string servers_buffer = ""; for (auto itr : favorite_servers) { - servers_buffer.append(utils::string::va("%u,%u\n", itr.addr, itr.port)); - } - - if (servers_buffer.empty()) - { - return; + servers_buffer.append(utils::string::va("%i.%i.%i.%i:%u\n", itr.ipv4.a, itr.ipv4.b, itr.ipv4.c, itr.ipv4.d, itr.port)); } utils::io::write_file(get_favorite_servers_file_path(), servers_buffer); @@ -126,12 +121,9 @@ namespace server_list if (utils::io::read_file(path, &filedata)) { auto servers = utils::string::split(filedata, '\n'); - for (auto server_data : servers) + for (auto server_address : servers) { - auto data = utils::string::split(server_data, ','); - auto addr = std::stoul(data[0].c_str()); - auto port = (uint16_t)atoi(data[1].c_str()); - auto server = network::address_from_ip(addr, port); + auto server = network::address_from_string(server_address); favorite_servers.push_back(server); } } @@ -229,7 +221,10 @@ namespace server_list lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); - read_favorite_servers(); + scheduler::loop([] + { + read_favorite_servers(); + }, scheduler::main); } void pre_destroy() override From bb83d4b2f2c1f2c670f7ae85d343ec978d371fde Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Sat, 15 Apr 2023 21:55:36 +0200 Subject: [PATCH 3/8] fixed feedback, fixed internet servers going into favorites tab, query only favorites --- src/client/component/server_list.cpp | 20 +-- src/client/component/server_list.hpp | 2 +- .../steam/interfaces/matchmaking_servers.cpp | 150 ++++++++++-------- 3 files changed, 90 insertions(+), 82 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 386ee761..83debbf3 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -28,7 +28,7 @@ namespace server_list utils::concurrency::container master_state; - std::vector favorite_servers{}; + std::unordered_set favorite_servers{}; void handle_server_list_response(const game::netadr_t& target, const network::data_view& data, state& s) @@ -124,7 +124,7 @@ namespace server_list for (auto server_address : servers) { auto server = network::address_from_string(server_address); - favorite_servers.push_back(server); + favorite_servers.insert(server); } } } @@ -157,12 +157,7 @@ namespace server_list void add_favorite_server(game::netadr_t addr) { - if (has_favorited_server(addr)) - { - return; - } - - favorite_servers.push_back(addr); + favorite_servers.insert(addr); write_favorite_servers(); } @@ -180,11 +175,10 @@ namespace server_list write_favorite_servers(); } - bool has_favorited_server(game::netadr_t addr) + std::unordered_set* get_favorite_servers() { - auto it = std::find_if(favorite_servers.begin(), favorite_servers.end(), [&addr](const game::netadr_t& obj) { return network::are_addresses_equal(addr, obj); }); - return it != favorite_servers.end(); - } + return &favorite_servers; + } struct component final : client_component { @@ -221,7 +215,7 @@ namespace server_list lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); - scheduler::loop([] + scheduler::once([] { read_favorite_servers(); }, scheduler::main); diff --git a/src/client/component/server_list.hpp b/src/client/component/server_list.hpp index d414f4fc..b02acac3 100644 --- a/src/client/component/server_list.hpp +++ b/src/client/component/server_list.hpp @@ -10,5 +10,5 @@ namespace server_list void add_favorite_server(game::netadr_t addr); void remove_favorite_server(game::netadr_t addr); - bool has_favorited_server(game::netadr_t addr); + std::unordered_set* get_favorite_servers(); } diff --git a/src/client/steam/interfaces/matchmaking_servers.cpp b/src/client/steam/interfaces/matchmaking_servers.cpp index f85f0711..1a2903fc 100644 --- a/src/client/steam/interfaces/matchmaking_servers.cpp +++ b/src/client/steam/interfaces/matchmaking_servers.cpp @@ -26,8 +26,10 @@ namespace steam using servers = std::vector; - ::utils::concurrency::container queried_servers{}; - std::atomic current_response{}; + ::utils::concurrency::container internet_servers{}; + ::utils::concurrency::container favorites_servers{}; + std::atomic internet_response{}; + std::atomic favorites_response{}; gameserveritem_t create_server_item(const game::netadr_t& address, const ::utils::info_string& info, const uint32_t ping, const bool success) @@ -70,11 +72,12 @@ namespace steam } void handle_server_respone(const bool success, const game::netadr_t& host, const ::utils::info_string& info, - const uint32_t ping) + const uint32_t ping, ::utils::concurrency::container* server_list, + std::atomic* response, void* request) { bool all_handled = false; std::optional index{}; - queried_servers.access([&](servers& srvs) + server_list->access([&](servers& srvs) { size_t i = 0; for (; i < srvs.size(); ++i) @@ -108,7 +111,7 @@ namespace steam all_handled = true; }); - const auto res = current_response.load(); + const auto res = response->load(); if (!index || !res) { return; @@ -116,33 +119,46 @@ namespace steam if (success) { - res->ServerResponded(internet_request, *index); + res->ServerResponded(request, *index); } else { - res->ServerFailedToRespond(internet_request, *index); + res->ServerFailedToRespond(request, *index); } if (all_handled) { - res->RefreshComplete(internet_request, eServerResponded); + res->RefreshComplete(request, eServerResponded); } + } + + void handle_internet_server_response(const bool success, const game::netadr_t& host, const ::utils::info_string& info, + const uint32_t ping) + { + handle_server_respone(success, host, info, ping, &internet_servers, &internet_response, internet_request); + } + + + void handle_favorites_server_response(const bool success, const game::netadr_t& host, const ::utils::info_string& info, + const uint32_t ping) + { + handle_server_respone(success, host, info, ping, &favorites_servers, &favorites_response, favorites_request); } - void ping_server(const game::netadr_t& server) + void ping_server(const game::netadr_t& server, party::query_callback callback) { - party::query_server(server, handle_server_respone); + party::query_server(server, callback); } } void* matchmaking_servers::RequestInternetServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters, matchmaking_server_list_response* pRequestServersResponse) { - current_response = pRequestServersResponse; + internet_response = pRequestServersResponse; server_list::request_servers([](const bool success, const std::unordered_set& s) { - const auto res = current_response.load(); + const auto res = internet_response.load(); if (!res) { return; @@ -160,7 +176,7 @@ namespace steam return; } - queried_servers.access([&s](servers& srvs) + internet_servers.access([&s](servers& srvs) { srvs = {}; srvs.reserve(s.size()); @@ -177,7 +193,7 @@ namespace steam for (auto& srv : s) { - ping_server(srv); + ping_server(srv, handle_internet_server_response); } }); @@ -199,52 +215,41 @@ namespace steam void* matchmaking_servers::RequestFavoritesServerList(unsigned int iApp, void** ppchFilters, unsigned int nFilters, matchmaking_server_list_response* pRequestServersResponse) { - current_response = pRequestServersResponse; + favorites_response = pRequestServersResponse; - server_list::request_servers([](const bool success, const std::unordered_set& s) + const auto res = favorites_response.load(); + if (!res) + { + return favorites_request; + } + + auto s = server_list::get_favorite_servers(); + + if (s->empty()) + { + res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); + return favorites_request; + } + + favorites_servers.access([s](servers& srvs) + { + srvs = {}; + srvs.reserve(s->size()); + + for (auto& address : *s) { - const auto res = current_response.load(); - if (!res) - { - return; - } + server new_server{}; + new_server.address = address; + new_server.server_item = create_server_item(address, {}, 0, false); - if (!success) - { - res->RefreshComplete(favorites_request, eServerFailedToRespond); - return; - } + srvs.push_back(new_server); + } + }); - if (s.empty()) - { - res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); - return; - } - - queried_servers.access([&s](servers& srvs) - { - srvs = {}; - srvs.reserve(s.size()); - - for (auto& address : s) - { - if (!server_list::has_favorited_server(address)) - { - continue; - } - server new_server{}; - new_server.address = address; - new_server.server_item = create_server_item(address, {}, 0, false); - - srvs.push_back(new_server); - } - }); - - for (auto& srv : s) - { - ping_server(srv); - } - }); + for (auto& srv : *s) + { + ping_server(srv, handle_favorites_server_response); + } return favorites_request; } @@ -265,19 +270,25 @@ namespace steam { if (internet_request == hServerListRequest) { - current_response = nullptr; + internet_response = nullptr; + } + if (favorites_request == hServerListRequest) + { + favorites_response = nullptr; } } gameserveritem_t* matchmaking_servers::GetServerDetails(void* hRequest, int iServer) { - if (internet_request != hRequest) + if (internet_request != hRequest && favorites_request != hRequest) { return nullptr; - } + } + + auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers; static thread_local gameserveritem_t server_item{}; - return queried_servers.access([iServer](const servers& s) -> gameserveritem_t* + return servers_list->access([iServer](const servers& s) -> gameserveritem_t* { if (iServer < 0 || static_cast(iServer) >= s.size()) { @@ -304,12 +315,13 @@ namespace steam int matchmaking_servers::GetServerCount(void* hRequest) { - if (internet_request != hRequest) + if (internet_request != hRequest && favorites_request != hRequest) { return 0; } - - return queried_servers.access([](const servers& s) + + auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers; + return servers_list->access([](const servers& s) { return static_cast(s.size()); }); @@ -317,13 +329,14 @@ namespace steam void matchmaking_servers::RefreshServer(void* hRequest, const int iServer) { - if (internet_request != hRequest) + if (internet_request != hRequest && favorites_request != hRequest) { return; } - std::optional address{}; - queried_servers.access([&](const servers& s) + std::optional address{}; + auto servers_list = hRequest == favorites_request ? &favorites_servers : &internet_servers; + servers_list->access([&](const servers& s) { if (iServer < 0 || static_cast(iServer) >= s.size()) { @@ -334,8 +347,9 @@ namespace steam }); if (address) - { - ping_server(*address); + { + auto callback = hRequest == favorites_request ? handle_favorites_server_response : handle_internet_server_response; + ping_server(*address, callback); } } From f68c8269e3e6173b7c138b880e424574153a1442 Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Sun, 16 Apr 2023 13:47:31 +0200 Subject: [PATCH 4/8] changed pointers to references --- src/client/component/server_list.cpp | 4 ++-- src/client/component/server_list.hpp | 2 +- .../steam/interfaces/matchmaking_servers.cpp | 20 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 83debbf3..14ae7112 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -175,9 +175,9 @@ namespace server_list write_favorite_servers(); } - std::unordered_set* get_favorite_servers() + std::unordered_set& get_favorite_servers() { - return &favorite_servers; + return favorite_servers; } struct component final : client_component diff --git a/src/client/component/server_list.hpp b/src/client/component/server_list.hpp index b02acac3..a41ad1d4 100644 --- a/src/client/component/server_list.hpp +++ b/src/client/component/server_list.hpp @@ -10,5 +10,5 @@ namespace server_list void add_favorite_server(game::netadr_t addr); void remove_favorite_server(game::netadr_t addr); - std::unordered_set* get_favorite_servers(); + std::unordered_set& get_favorite_servers(); } diff --git a/src/client/steam/interfaces/matchmaking_servers.cpp b/src/client/steam/interfaces/matchmaking_servers.cpp index c44a4c46..91191e90 100644 --- a/src/client/steam/interfaces/matchmaking_servers.cpp +++ b/src/client/steam/interfaces/matchmaking_servers.cpp @@ -74,12 +74,12 @@ namespace steam } void handle_server_respone(const bool success, const game::netadr_t& host, const ::utils::info_string& info, - const uint32_t ping, ::utils::concurrency::container* server_list, - std::atomic* response, void* request) + const uint32_t ping, ::utils::concurrency::container& server_list, + std::atomic& response, void* request) { bool all_handled = false; std::optional index{}; - server_list->access([&](servers& srvs) + server_list.access([&](servers& srvs) { size_t i = 0; for (; i < srvs.size(); ++i) @@ -113,7 +113,7 @@ namespace steam all_handled = true; }); - const auto res = response->load(); + const auto res = response.load(); if (!index || !res) { return; @@ -137,14 +137,14 @@ namespace steam void handle_internet_server_response(const bool success, const game::netadr_t& host, const ::utils::info_string& info, const uint32_t ping) { - handle_server_respone(success, host, info, ping, &internet_servers, &internet_response, internet_request); + handle_server_respone(success, host, info, ping, internet_servers, internet_response, internet_request); } void handle_favorites_server_response(const bool success, const game::netadr_t& host, const ::utils::info_string& info, const uint32_t ping) { - handle_server_respone(success, host, info, ping, &favorites_servers, &favorites_response, favorites_request); + handle_server_respone(success, host, info, ping, favorites_servers, favorites_response, favorites_request); } void ping_server(const game::netadr_t& server, party::query_callback callback) @@ -227,7 +227,7 @@ namespace steam auto s = server_list::get_favorite_servers(); - if (s->empty()) + if (s.empty()) { res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); return favorites_request; @@ -236,9 +236,9 @@ namespace steam favorites_servers.access([s](servers& srvs) { srvs = {}; - srvs.reserve(s->size()); + srvs.reserve(s.size()); - for (auto& address : *s) + for (auto& address : s) { server new_server{}; new_server.address = address; @@ -248,7 +248,7 @@ namespace steam } }); - for (auto& srv : *s) + for (auto& srv : s) { ping_server(srv, handle_favorites_server_response); } From 5b71627d74f36f051854355717cb8f35ac1fa53f Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Sat, 22 Apr 2023 18:53:56 +0200 Subject: [PATCH 5/8] changed favorite servers list to concurrency container --- src/client/component/server_list.cpp | 66 +++++++++++-------- src/client/component/server_list.hpp | 9 ++- .../steam/interfaces/matchmaking_servers.cpp | 60 +++++++++-------- 3 files changed, 74 insertions(+), 61 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 14ae7112..332279ef 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -5,7 +5,6 @@ #include "game/game.hpp" #include -#include #include #include @@ -28,7 +27,7 @@ namespace server_list utils::concurrency::container master_state; - std::unordered_set favorite_servers{}; + utils::concurrency::container favorite_servers{}; void handle_server_list_response(const game::netadr_t& target, const network::data_view& data, state& s) @@ -98,13 +97,15 @@ namespace server_list void write_favorite_servers() { - std::string servers_buffer = ""; - for (auto itr : favorite_servers) + favorite_servers.access([&](std::unordered_set& servers) { - servers_buffer.append(utils::string::va("%i.%i.%i.%i:%u\n", itr.ipv4.a, itr.ipv4.b, itr.ipv4.c, itr.ipv4.d, itr.port)); - } - - utils::io::write_file(get_favorite_servers_file_path(), servers_buffer); + std::string servers_buffer = ""; + for (auto itr : servers) + { + servers_buffer.append(utils::string::va("%i.%i.%i.%i:%u\n", itr.ipv4.a, itr.ipv4.b, itr.ipv4.c, itr.ipv4.d, itr.port)); + } + utils::io::write_file(get_favorite_servers_file_path(), servers_buffer); + }); } void read_favorite_servers() @@ -115,18 +116,20 @@ namespace server_list return; } - favorite_servers.clear(); - - std::string filedata; - if (utils::io::read_file(path, &filedata)) - { - auto servers = utils::string::split(filedata, '\n'); - for (auto server_address : servers) + favorite_servers.access([&path](std::unordered_set& servers) + { + servers.clear(); + std::string filedata; + if (utils::io::read_file(path, &filedata)) { - auto server = network::address_from_string(server_address); - favorite_servers.insert(server); - } - } + auto srv = utils::string::split(filedata, '\n'); + for (auto server_address : srv) + { + auto server = network::address_from_string(server_address); + servers.insert(server); + } + } + }); } } @@ -157,25 +160,30 @@ namespace server_list void add_favorite_server(game::netadr_t addr) { - favorite_servers.insert(addr); + favorite_servers.access([&addr](std::unordered_set& servers) + { + servers.insert(addr); + }); write_favorite_servers(); } void remove_favorite_server(game::netadr_t addr) { - for (auto it = favorite_servers.begin(); it != favorite_servers.end(); ++it) - { - if (network::are_addresses_equal(*it, addr)) + favorite_servers.access([&addr](std::unordered_set& servers) + { + for (auto it = servers.begin(); it != servers.end(); ++it) { - favorite_servers.erase(it); - break; - } - } - + if (network::are_addresses_equal(*it, addr)) + { + servers.erase(it); + break; + } + } + }); write_favorite_servers(); } - std::unordered_set& get_favorite_servers() + utils::concurrency::container& get_favorite_servers() { return favorite_servers; } diff --git a/src/client/component/server_list.hpp b/src/client/component/server_list.hpp index a41ad1d4..aed5cc71 100644 --- a/src/client/component/server_list.hpp +++ b/src/client/component/server_list.hpp @@ -1,8 +1,10 @@ #pragma once -#include +#include + +#include namespace server_list -{ +{ bool get_master_server(game::netadr_t& address); using callback = std::function&)>; @@ -10,5 +12,6 @@ namespace server_list void add_favorite_server(game::netadr_t addr); void remove_favorite_server(game::netadr_t addr); - std::unordered_set& get_favorite_servers(); + using server_list = std::unordered_set; + utils::concurrency::container& get_favorite_servers(); } diff --git a/src/client/steam/interfaces/matchmaking_servers.cpp b/src/client/steam/interfaces/matchmaking_servers.cpp index 91191e90..e42d4a61 100644 --- a/src/client/steam/interfaces/matchmaking_servers.cpp +++ b/src/client/steam/interfaces/matchmaking_servers.cpp @@ -219,39 +219,41 @@ namespace steam { favorites_response = pRequestServersResponse; - const auto res = favorites_response.load(); - if (!res) + auto& srvs = server_list::get_favorite_servers(); + srvs.access([&](std::unordered_set s) { - return favorites_request; - } - - auto s = server_list::get_favorite_servers(); - - if (s.empty()) - { - res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); - return favorites_request; - } - - favorites_servers.access([s](servers& srvs) - { - srvs = {}; - srvs.reserve(s.size()); - - for (auto& address : s) + const auto res = favorites_response.load(); + if (!res) { - server new_server{}; - new_server.address = address; - new_server.server_item = create_server_item(address, {}, 0, false); - - srvs.push_back(new_server); + return; + } + + if (s.empty()) + { + res->RefreshComplete(favorites_request, eNoServersListedOnMasterServer); + return; } - }); - for (auto& srv : s) - { - ping_server(srv, handle_favorites_server_response); - } + favorites_servers.access([s](servers& srvs) + { + srvs = {}; + srvs.reserve(s.size()); + + for (auto& address : s) + { + server new_server{}; + new_server.address = address; + new_server.server_item = create_server_item(address, {}, 0, false); + + srvs.push_back(new_server); + } + }); + + for (auto& srv : s) + { + ping_server(srv, handle_favorites_server_response); + } + }); return favorites_request; } From dc463bc8122c6347583f17dce35ea1180c32836b Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Sat, 22 Apr 2023 21:34:32 +0200 Subject: [PATCH 6/8] fix merge --- src/client/component/server_list.cpp | 80 +++++++++++++++------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index d699fbc0..e21a5fc9 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "network.hpp" #include "scheduler.hpp" @@ -20,7 +21,7 @@ namespace server_list struct state { game::netadr_t address{}; - bool requesting{false}; + bool requesting{ false }; std::chrono::high_resolution_clock::time_point query_start{}; callback callback{}; }; @@ -30,7 +31,7 @@ namespace server_list utils::concurrency::container favorite_servers{}; void handle_server_list_response(const game::netadr_t& target, - const network::data_view& data, state& s) + const network::data_view& data, state& s) { if (!s.requesting || s.address != target) { @@ -142,20 +143,20 @@ namespace server_list void request_servers(callback callback) { master_state.access([&callback](state& s) - { - game::netadr_t addr{}; - if (!get_master_server(addr)) { - return; - } + game::netadr_t addr{}; + if (!get_master_server(addr)) + { + return; + } - s.requesting = true; - s.address = addr; - s.callback = std::move(callback); - s.query_start = std::chrono::high_resolution_clock::now(); + s.requesting = true; + s.address = addr; + s.callback = std::move(callback); + s.query_start = std::chrono::high_resolution_clock::now(); - network::send(s.address, "getservers", utils::string::va("T7 %i full empty", PROTOCOL)); - }); + network::send(s.address, "getservers", utils::string::va("T7 %i full empty", PROTOCOL)); + }); } void add_favorite_server(game::netadr_t addr) @@ -193,44 +194,49 @@ namespace server_list void post_unpack() override { network::on("getServersResponse", [](const game::netadr_t& target, const network::data_view& data) - { - master_state.access([&](state& s) { - handle_server_list_response(target, data, s); + master_state.access([&](state& s) + { + handle_server_list_response(target, data, s); + }); }); - }); scheduler::loop([] - { - master_state.access([](state& s) { - if (!s.requesting) - { - return; - } + master_state.access([](state& s) + { + if (!s.requesting) + { + return; + } - const auto now = std::chrono::high_resolution_clock::now(); - if ((now - s.query_start) < 2s) - { - return; - } + const auto now = std::chrono::high_resolution_clock::now(); + if ((now - s.query_start) < 2s) + { + return; + } - s.requesting = false; - s.callback(false, {}); - s.callback = {}; - }); - }, scheduler::async, 200ms); + s.requesting = false; + s.callback(false, {}); + s.callback = {}; + }); + }, scheduler::async, 200ms); lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); + + scheduler::once([] + { + read_favorite_servers(); + }, scheduler::main); } void pre_destroy() override { master_state.access([](state& s) - { - s.requesting = false; - s.callback = {}; - }); + { + s.requesting = false; + s.callback = {}; + }); } }; } From cc11aa25b73ee3aa6e69c58123079e5d07e13124 Mon Sep 17 00:00:00 2001 From: WantedDV <122710241+WantedDV@users.noreply.github.com> Date: Sun, 23 Apr 2023 00:25:30 -0230 Subject: [PATCH 7/8] check if button exists first --- data/ui_scripts/frontend_menus/utils.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/ui_scripts/frontend_menus/utils.lua b/data/ui_scripts/frontend_menus/utils.lua index 7abe1926..f394e0ae 100644 --- a/data/ui_scripts/frontend_menus/utils.lua +++ b/data/ui_scripts/frontend_menus/utils.lua @@ -17,6 +17,9 @@ local SetButtonState = function(button, state) end local RemoveButton = function(buttonTable, button) + if not button then + return + end for id, v in pairs(buttonTable) do if buttonTable[id].optionDisplay == button.stringRef then table.remove(buttonTable, id) @@ -31,6 +34,9 @@ local RemoveSpaces = function(buttonTable) end local GetButtonIndex = function(buttonTable, button) + if not button then + return nil + end for id, v in pairs(buttonTable) do if buttonTable[id].optionDisplay == button.stringRef then return id From 454ca4adf2205bf41a6cac45ec94f2364079399f Mon Sep 17 00:00:00 2001 From: WantedDV <122710241+WantedDV@users.noreply.github.com> Date: Sun, 23 Apr 2023 11:08:54 -0230 Subject: [PATCH 8/8] do not use arithmetic operator if button index nil - cleanup unnecessary explicit index --- data/ui_scripts/frontend_menus/__init__.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/data/ui_scripts/frontend_menus/__init__.lua b/data/ui_scripts/frontend_menus/__init__.lua index 7ee38ff2..30cba4f5 100644 --- a/data/ui_scripts/frontend_menus/__init__.lua +++ b/data/ui_scripts/frontend_menus/__init__.lua @@ -87,7 +87,10 @@ end local addCustomButtons = function(controller, menuId, buttonTable, isLeader) if menuId == LobbyData.UITargets.UI_MPLOBBYMAIN.id then utils.RemoveSpaces(buttonTable) - utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.THEATER_MP) - 1) + local theaterIndex = utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.THEATER_MP) + if theaterIndex ~= nil then + utils.AddSpacer(buttonTable, theaterIndex - 1) + end end if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then @@ -121,11 +124,14 @@ local addCustomButtons = function(controller, menuId, buttonTable, isLeader) if menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then utils.RemoveButton(buttonTable, CoD.LobbyButtons.THEATER_ZM) - utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.THEATER_ZM, #buttonTable + 1) + utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.THEATER_ZM) utils.RemoveSpaces(buttonTable) utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.SERVER_BROWSER)) - utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.ZM_BUBBLEGUM_BUFFS) - 1) + local bgbIndex = utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.ZM_BUBBLEGUM_BUFFS) + if bgbIndex ~= nil then + utils.AddSpacer(buttonTable, bgbIndex - 1) + end utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.STATS)) end end