t7x/src/client/component/profile_infos.cpp

259 lines
5.4 KiB
C++
Raw Normal View History

2023-04-02 03:10:18 -04:00
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "profile_infos.hpp"
#include "network.hpp"
2023-04-06 16:04:20 -04:00
#include "party.hpp"
2023-04-07 06:12:19 -04:00
#include "scheduler.hpp"
2023-04-02 03:10:18 -04:00
#include <utils/nt.hpp>
#include <utils/properties.hpp>
#include <utils/concurrency.hpp>
#include "../steam/steam.hpp"
#include <utils/io.hpp>
2023-04-07 03:01:36 -04:00
#include "game/utils.hpp"
2023-04-02 03:10:18 -04:00
namespace profile_infos
{
namespace
{
using profile_map = std::unordered_map<uint64_t, profile_info>;
2023-04-07 03:01:36 -04:00
utils::concurrency::container<profile_map> profile_mapping{};
2023-04-02 03:10:18 -04:00
std::optional<profile_info> load_profile_info()
{
std::string data{};
if (!utils::io::read_file("players/user/profile_info", &data))
{
return {};
}
profile_info info{};
constexpr auto version_size = sizeof(info.version);
2023-04-06 16:04:20 -04:00
if (data.size() < sizeof(version_size))
2023-04-02 03:10:18 -04:00
{
return {};
}
memcpy(&info.version, data.data(), version_size);
info.ddl.assign(data.begin() + version_size, data.end());
2023-04-06 16:04:20 -04:00
return {std::move(info)};
2023-04-02 03:10:18 -04:00
}
2023-04-07 03:01:36 -04:00
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 <typename T>
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)
{
2023-04-07 04:46:09 -04:00
if (user_id == steam::SteamUser()->GetSteamID().bits)
{
return;
}
2023-04-07 03:01:36 -04:00
utils::byte_buffer buffer{};
buffer.write(user_id);
info.serialize(buffer);
if (game::is_server())
{
distribute_profile_info(*game::svs_clients, buffer.get_buffer());
}
else
{
distribute_profile_info(*game::svs_clients_cl, buffer.get_buffer());
}
}
2023-04-07 06:12:19 -04:00
void schedule_pcache_update()
{
static std::atomic_bool update_triggered{false};
if (game::is_server() || update_triggered.exchange(true))
{
return;
}
scheduler::once([]
{
game::PCache_DeleteEntries(game::CONTROLLER_INDEX_FIRST);
update_triggered = false;
}, scheduler::main, 5s);
}
void clean_cached_profile_infos()
{
if (!game::get_dvar_bool("sv_running"))
{
return;
}
// TODO
}
2023-04-02 03:10:18 -04:00
}
2023-04-06 16:04:20 -04:00
profile_info::profile_info(utils::byte_buffer& buffer)
{
this->version = buffer.read<int32_t>();
this->ddl = buffer.read_string();
}
void profile_info::serialize(utils::byte_buffer& buffer) const
{
buffer.write(this->version);
buffer.write_string(this->ddl);
}
2023-04-07 03:01:36 -04:00
void add_profile_info(const uint64_t user_id, const profile_info& info)
2023-04-06 16:04:20 -04:00
{
if (user_id == steam::SteamUser()->GetSteamID().bits)
{
return;
}
profile_mapping.access([&](profile_map& profiles)
{
2023-04-07 03:01:36 -04:00
profiles[user_id] = info;
});
2023-04-07 06:12:19 -04:00
schedule_pcache_update();
2023-04-07 03:01:36 -04:00
}
void distribute_profile_info_to_user(const game::netadr_t& addr, const uint64_t user_id, const profile_info& info)
{
utils::byte_buffer buffer{};
buffer.write(user_id);
info.serialize(buffer);
send_profile_info(addr, buffer.get_buffer());
}
void distribute_profile_infos_to_user(const game::netadr_t& addr)
{
profile_mapping.access([&](const profile_map& profiles)
{
for (const auto& entry : profiles)
{
distribute_profile_info_to_user(addr, entry.first, entry.second);
}
2023-04-06 16:04:20 -04:00
});
2023-04-07 04:46:09 -04:00
if (!game::is_server())
{
const auto info = get_profile_info();
if (info)
{
distribute_profile_info_to_user(addr, steam::SteamUser()->GetSteamID().bits, *info);
}
}
2023-04-06 16:04:20 -04:00
}
2023-04-07 03:01:36 -04:00
void add_and_distribute_profile_info(const game::netadr_t& addr, const uint64_t user_id, const profile_info& info)
2023-04-06 16:04:20 -04:00
{
2023-04-07 03:01:36 -04:00
distribute_profile_infos_to_user(addr);
add_profile_info(user_id, info);
distribute_profile_info(user_id, info);
2023-04-06 16:04:20 -04:00
}
2023-04-07 03:01:36 -04:00
void clear_profile_infos()
2023-04-02 03:10:18 -04:00
{
2023-04-07 03:01:36 -04:00
profile_mapping.access([&](profile_map& profiles)
{
profiles = {};
});
}
2023-04-07 04:46:09 -04:00
std::optional<profile_info> get_profile_info()
{
return load_profile_info();
}
2023-04-07 03:01:36 -04:00
std::optional<profile_info> get_profile_info(const uint64_t user_id)
{
printf("Requesting profile info: %llX\n", user_id);
2023-04-02 03:10:18 -04:00
if (user_id == steam::SteamUser()->GetSteamID().bits)
{
2023-04-07 04:46:09 -04:00
return get_profile_info();
2023-04-02 03:10:18 -04:00
}
return profile_mapping.access<std::optional<profile_info>>([user_id](const profile_map& profiles)
{
std::optional<profile_info> result{};
const auto profile_entry = profiles.find(user_id);
if (profile_entry != profiles.end())
{
result = profile_entry->second;
}
return result;
});
}
void update_profile_info(const profile_info& info)
{
std::string data{};
data.reserve(4 + info.ddl.size());
data.append(reinterpret_cast<const char*>(&info.version), sizeof(info.version));
data.append(info.ddl);
utils::io::write_file("players/user/profile_info", data);
}
2023-04-07 06:12:19 -04:00
struct component final : generic_component
2023-04-02 03:10:18 -04:00
{
void post_unpack() override
{
2023-04-07 06:12:19 -04:00
scheduler::loop(clean_cached_profile_infos, scheduler::main, 5s);
if (game::is_client())
2023-04-02 03:10:18 -04:00
{
2023-04-07 06:12:19 -04:00
network::on("profileInfo", [](const game::netadr_t& server, const network::data_view& data)
2023-04-06 16:04:20 -04:00
{
2023-04-07 06:12:19 -04:00
if (!party::is_host(server))
{
return;
}
2023-04-06 16:04:20 -04:00
2023-04-07 06:12:19 -04:00
utils::byte_buffer buffer(data);
const auto user_id = buffer.read<uint64_t>();
const profile_info info(buffer);
2023-04-06 16:04:20 -04:00
2023-04-07 06:12:19 -04:00
add_profile_info(user_id, info);
});
}
2023-04-02 03:10:18 -04:00
}
};
}
REGISTER_COMPONENT(profile_infos::component)