diff --git a/src/client/component/auth.cpp b/src/client/component/auth.cpp index 7385be95..d5e2d4f6 100644 --- a/src/client/component/auth.cpp +++ b/src/client/component/auth.cpp @@ -127,7 +127,7 @@ namespace auth void handle_connect_packet(const game::netadr_t& target, const network::data_view& data) { - if (!game::get_dvar_bool("sv_running")) + if (!game::is_server_running()) { return; } diff --git a/src/client/component/chat.cpp b/src/client/component/chat.cpp index 7bb8a52e..41b1b44a 100644 --- a/src/client/component/chat.cpp +++ b/src/client/component/chat.cpp @@ -122,7 +122,7 @@ namespace chat // Overwrite say command utils::hook::jump(0x14052A6C0_g, +[] { - if (!game::get_dvar_bool("sv_running")) + if (!game::is_server_running()) { printf("Server is not running\n"); return; @@ -138,7 +138,7 @@ namespace chat // Overwrite tell command utils::hook::jump(0x14052A7E0_g, +[] { - if (!game::get_dvar_bool("sv_running")) + if (!game::is_server_running()) { printf("Server is not running\n"); return; diff --git a/src/client/component/dedicated_info.cpp b/src/client/component/dedicated_info.cpp index c950a247..95089a2d 100644 --- a/src/client/component/dedicated_info.cpp +++ b/src/client/component/dedicated_info.cpp @@ -27,11 +27,11 @@ namespace dedicated_info const auto mapname = game::get_dvar_string("mapname"); - const std::string window_text = utils::string::va("%s on %s [%d/%d] (%d)", + const std::string window_text = utils::string::va("%s on %s [%zu/%zu] (%zu)", clean_server_name, mapname.data(), getinfo::get_client_count(), - getinfo::get_max_client_count(), + game::get_max_client_count(), getinfo::get_bot_count()); console::set_title(window_text); diff --git a/src/client/component/getinfo.cpp b/src/client/component/getinfo.cpp index 9e770266..17901992 100644 --- a/src/client/component/getinfo.cpp +++ b/src/client/component/getinfo.cpp @@ -41,33 +41,28 @@ namespace getinfo return count; } - int get_client_count() + size_t get_client_count() { - if (game::is_server()) + size_t count = 0; + game::foreach_connected_client([&count](const game::client_s&) { - return get_client_count(*game::svs_clients); - } + ++count; + }); - return get_client_count(*game::svs_clients_cl); + return count; } - int get_bot_count() + size_t get_bot_count() { - const auto client_states = game::is_server() ? *game::svs_clients : *game::svs_clients_cl; - if (!client_states) - { - return 0; - } + size_t count = 0; - int count = 0; - - for (int i = 0; i < get_max_client_count(); ++i) + game::foreach_connected_client([&count](const game::client_s&, const size_t index) { - if (game::SV_IsTestClient(i)) + if (game::SV_IsTestClient(static_cast(index))) { ++count; } - } + }); return count; } @@ -110,9 +105,9 @@ namespace getinfo info.set("xuid", utils::string::va("%llX", steam::SteamUser()->GetSteamID().bits)); info.set("mapname", game::get_dvar_string("mapname")); info.set("isPrivate", game::get_dvar_string("g_password").empty() ? "0" : "1"); - info.set("clients", utils::string::va("%i", get_client_count())); - info.set("bots", utils::string::va("%i", get_bot_count())); - info.set("sv_maxclients", utils::string::va("%i", get_max_client_count())); + info.set("clients", utils::string::va("%zu", get_client_count())); + info.set("bots", utils::string::va("%zu", get_bot_count())); + info.set("sv_maxclients", utils::string::va("%zu", get_max_client_count())); info.set("protocol", utils::string::va("%i", PROTOCOL)); info.set("playmode", utils::string::va("%i", game::Com_SessionMode_GetMode())); info.set("gamemode", utils::string::va("%i", Com_SessionMode_GetGameMode())); diff --git a/src/client/component/getinfo.hpp b/src/client/component/getinfo.hpp index 5d9d14be..0bf43b4d 100644 --- a/src/client/component/getinfo.hpp +++ b/src/client/component/getinfo.hpp @@ -2,8 +2,7 @@ namespace getinfo { - int get_max_client_count(); - int get_client_count(); - int get_bot_count(); + size_t get_client_count(); + size_t get_bot_count(); bool is_host(); } diff --git a/src/client/component/profile_infos.cpp b/src/client/component/profile_infos.cpp index 46fa2c6d..b72d192f 100644 --- a/src/client/component/profile_infos.cpp +++ b/src/client/component/profile_infos.cpp @@ -44,33 +44,11 @@ namespace profile_infos return {std::move(info)}; } - int get_max_client_count() - { - return game::get_dvar_int("com_maxclients"); - } - void send_profile_info(const game::netadr_t& address, const std::string& buffer) { network::send(address, "profileInfo", buffer); } - template - void distribute_profile_info(T* client_states, const std::string& buffer) - { - if (!client_states) - { - return; - } - - for (int i = 0; i < get_max_client_count(); ++i) - { - if (client_states[i].client_state > 0) - { - send_profile_info(client_states[i].address, buffer); - } - } - } - void distribute_profile_info(const uint64_t user_id, const profile_info& info) { if (user_id == steam::SteamUser()->GetSteamID().bits) @@ -82,14 +60,12 @@ namespace profile_infos buffer.write(user_id); info.serialize(buffer); - if (game::is_server()) + const std::string data = buffer.move_buffer(); + + game::foreach_connected_client([&](const game::client_s& client) { - distribute_profile_info(*game::svs_clients, buffer.get_buffer()); - } - else - { - distribute_profile_info(*game::svs_clients_cl, buffer.get_buffer()); - } + send_profile_info(client.address, data); + }); } void schedule_pcache_update() @@ -107,14 +83,42 @@ namespace profile_infos }, scheduler::main, 5s); } + std::unordered_set get_connected_client_xuids() + { + std::unordered_set connected_clients{}; + connected_clients.reserve(game::get_max_client_count()); + + game::foreach_connected_client([&](const game::client_s& client) + { + connected_clients.emplace(client.xuid); + }); + + return connected_clients; + } + void clean_cached_profile_infos() { - if (!game::get_dvar_bool("sv_running")) + if (!game::is_server_running()) { return; } - // TODO + const auto xuids = get_connected_client_xuids(); + + profile_mapping.access([&](profile_map& profiles) + { + for (auto i = profiles.begin(); i != profiles.end();) + { + if (xuids.contains(i->first)) + { + ++i; + } + else + { + i = profiles.erase(i); + } + } + }); } } diff --git a/src/client/game/utils.cpp b/src/client/game/utils.cpp index b33c08ef..051b3352 100644 --- a/src/client/game/utils.cpp +++ b/src/client/game/utils.cpp @@ -45,7 +45,8 @@ namespace game return dvar->current.value.enabled; } - const dvar_t* register_sessionmode_dvar_bool(const char* dvar_name, const bool value, const int flags, const char* description, const eModes mode) + const dvar_t* register_sessionmode_dvar_bool(const char* dvar_name, const bool value, const int flags, + const char* description, const eModes mode) { const auto hash = Dvar_GenerateHash(dvar_name); auto* registered_dvar = Dvar_SessionModeRegisterBool(hash, dvar_name, value, flags, description); @@ -83,7 +84,8 @@ namespace game return registered_dvar; } - const dvar_t* register_dvar_string(const char* dvar_name, const char* value, const int flags, const char* description) + const dvar_t* register_dvar_string(const char* dvar_name, const char* value, const int flags, + const char* description) { const auto hash = Dvar_GenerateHash(dvar_name); auto* registered_dvar = Dvar_RegisterString(hash, dvar_name, value, flags, description); @@ -135,4 +137,67 @@ namespace game dvar_to_change->flags = flags; } + + bool is_server_running() + { + return get_dvar_bool("sv_running"); + } + + size_t get_max_client_count() + { + return static_cast(get_dvar_int("com_maxclients")); + } + + template + static void foreach_client(T* client_states, const std::function& callback) + { + if (!client_states || !callback) + { + return; + } + + for (size_t i = 0; i < get_max_client_count(); ++i) + { + callback(client_states[i], i); + } + } + + void foreach_client(const std::function& callback) + { + if (is_server()) + { + foreach_client(*svs_clients, callback); + } + else + { + foreach_client(*svs_clients_cl, callback); + } + } + + void foreach_client(const std::function& callback) + { + foreach_client([&](client_s& client, size_t) + { + callback(client); + }); + } + + void foreach_connected_client(const std::function& callback) + { + foreach_client([&](client_s& client, const size_t index) + { + if (client.client_state > 0) + { + callback(client, index); + } + }); + } + + void foreach_connected_client(const std::function& callback) + { + foreach_connected_client([&](client_s& client, size_t) + { + callback(client); + }); + } } diff --git a/src/client/game/utils.hpp b/src/client/game/utils.hpp index c59bbfc7..a4e4de16 100644 --- a/src/client/game/utils.hpp +++ b/src/client/game/utils.hpp @@ -11,6 +11,16 @@ namespace game const dvar_t* register_dvar_bool(const char* dvar_name, bool value, int flags, const char* description); const dvar_t* register_sessionmode_dvar_bool(const char* dvar_name, bool value, int flags, const char* description, eModes mode = MODE_COUNT); const dvar_t* register_dvar_string(const char* dvar_name, const char* value, int flags, const char* description); + void dvar_add_flags(const char* dvar, dvarFlags_e flags); void dvar_set_flags(const char* dvar_name, dvarFlags_e flags); + + bool is_server_running(); + size_t get_max_client_count(); + + void foreach_client(const std::function& callback); + void foreach_client(const std::function& callback); + + void foreach_connected_client(const std::function& callback); + void foreach_connected_client(const std::function& callback); }