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 14:25:43 -04:00
|
|
|
utils::concurrency::container<profile_map, std::recursive_mutex> 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
|
|
|
|
|
|
|
void send_profile_info(const game::netadr_t& address, const std::string& buffer)
|
|
|
|
{
|
|
|
|
network::send(address, "profileInfo", 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);
|
|
|
|
|
2023-04-07 08:25:56 -04:00
|
|
|
const std::string data = buffer.move_buffer();
|
|
|
|
|
|
|
|
game::foreach_connected_client([&](const game::client_s& client)
|
2023-04-07 03:01:36 -04:00
|
|
|
{
|
2023-04-07 08:25:56 -04:00
|
|
|
send_profile_info(client.address, data);
|
|
|
|
});
|
2023-04-07 03:01:36 -04:00
|
|
|
}
|
2023-04-07 06:12:19 -04:00
|
|
|
|
2023-04-07 08:25:56 -04:00
|
|
|
std::unordered_set<uint64_t> get_connected_client_xuids()
|
|
|
|
{
|
|
|
|
std::unordered_set<uint64_t> 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;
|
|
|
|
}
|
|
|
|
|
2023-04-07 06:12:19 -04:00
|
|
|
void clean_cached_profile_infos()
|
|
|
|
{
|
2023-04-07 08:25:56 -04:00
|
|
|
if (!game::is_server_running())
|
2023-04-07 06:12:19 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-07 14:25:43 -04:00
|
|
|
profile_mapping.access([](profile_map& profiles)
|
2023-04-07 08:25:56 -04:00
|
|
|
{
|
2023-04-07 14:25:43 -04:00
|
|
|
const auto xuids = get_connected_client_xuids();
|
|
|
|
|
2023-04-07 08:25:56 -04:00
|
|
|
for (auto i = profiles.begin(); i != profiles.end();)
|
|
|
|
{
|
|
|
|
if (xuids.contains(i->first))
|
|
|
|
{
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i = profiles.erase(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2023-04-07 06:12:19 -04:00
|
|
|
}
|
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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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 14:25:43 -04:00
|
|
|
std::unique_lock<std::recursive_mutex> acquire_profile_lock()
|
|
|
|
{
|
|
|
|
return profile_mapping.acquire_lock();
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
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)
|