Merge branch 'main' into party
This commit is contained in:
commit
1442845658
Binary file not shown.
@ -3,11 +3,9 @@
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
|
||||
#insert scripts\shared\shared.gsh;
|
||||
|
||||
#namespace serversettings;
|
||||
|
||||
REGISTER_SYSTEM( "serversettings", &__init__, undefined )
|
||||
function autoexec __init__sytem__() { system::register("serversettings",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
@ -21,26 +19,29 @@ function init()
|
||||
level.hostname = "CoDHost";
|
||||
SetDvar("sv_hostname", level.hostname);
|
||||
SetDvar("ui_hostname", level.hostname);
|
||||
//makeDvarServerInfo("ui_hostname", "CoDHost");
|
||||
|
||||
level.motd = GetDvarString( "scr_motd" );
|
||||
if(level.motd == "")
|
||||
level.motd = "";
|
||||
SetDvar("scr_motd", level.motd);
|
||||
SetDvar("ui_motd", level.motd);
|
||||
//makeDvarServerInfo("ui_motd", "");
|
||||
|
||||
level.allowvote = GetDvarString( "g_allowvote");
|
||||
level.allowvote = GetDvarString( "g_allowvote" );
|
||||
if(level.allowvote == "")
|
||||
level.allowvote = "1";
|
||||
SetDvar("g_allowvote", level.allowvote);
|
||||
SetDvar("ui_allowvote", level.allowvote);
|
||||
//makeDvarServerInfo("ui_allowvote", "1");
|
||||
|
||||
level.allow_teamchange = "1";
|
||||
SetDvar("ui_allow_teamchange", level.allow_teamchange);
|
||||
|
||||
|
||||
level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
|
||||
|
||||
SetDvar("ui_friendlyfire", level.friendlyfire);
|
||||
//makeDvarServerInfo("ui_friendlyfire", "0");
|
||||
|
||||
if(GetDvarString( "scr_mapsize") == "")
|
||||
SetDvar("scr_mapsize", "64");
|
||||
@ -56,6 +57,8 @@ function init()
|
||||
|
||||
constrain_gametype(GetDvarString( "g_gametype"));
|
||||
constrain_map_size(level.mapsize);
|
||||
|
||||
thread setup_callbacks();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@ -80,7 +83,7 @@ function update()
|
||||
SetDvar("ui_motd", level.motd);
|
||||
}
|
||||
|
||||
g_allowvote = GetDvarString( "g_allowvote");
|
||||
g_allowvote = GetDvarString( "g_allowvote" );
|
||||
if(level.allowvote != g_allowvote)
|
||||
{
|
||||
level.allowvote = g_allowvote;
|
||||
@ -193,4 +196,14 @@ function constrain_map_size(mapsize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setup_callbacks()
|
||||
{
|
||||
level.onForfeit = &default_onForfeit;
|
||||
}
|
||||
|
||||
function default_onForfeit()
|
||||
{
|
||||
level.gameForfeited = false;
|
||||
}
|
@ -70,5 +70,6 @@ DataSources.StartMenuGameOptions = ListHelper_SetupDataSource("StartMenuGameOpti
|
||||
table.insert(options, {models = {displayText = "MENU_QUIT_GAME_CAPS", action = QuitGame_MP}})
|
||||
end
|
||||
end
|
||||
table.insert(options, {models = {displayText = "QUIT TO DESKTOP", action = OpenPCQuit}})
|
||||
return options
|
||||
end, true)
|
||||
|
@ -20,7 +20,7 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Loot",
|
||||
"Whether loot should be locked based on the player's stats or always unlocked.", "MPStatsSettings_unlock_loot",
|
||||
"Unlocks all Black Market loot.", "MPStatsSettings_unlock_loot",
|
||||
"cg_unlockall_loot", {
|
||||
{
|
||||
option = "MENU_DISABLED",
|
||||
@ -47,6 +47,20 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Class Slots",
|
||||
"Unlocks all create-a-class slots and sets.", "MPStatsSettings_unlockall_cac_slots",
|
||||
"cg_unlockall_cac_slots", {
|
||||
{
|
||||
option = "MENU_DISABLED",
|
||||
value = 0,
|
||||
default = true
|
||||
},
|
||||
{
|
||||
option = "MENU_ENABLED",
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
end
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
|
||||
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
||||
Subproject commit dc18b40b406e9946a2198d66b6edb62575660faf
|
||||
Subproject commit 6b1e4dc6cdd2c1fc1730dc64aa5e2d82615e5993
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
||||
Subproject commit eb0e038b297f2c9877ed8b3515c6718a4b65d485
|
||||
Subproject commit b8a8373ec195c8d286fe7e81e78b4a6d31bd859f
|
@ -2,8 +2,10 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "auth.hpp"
|
||||
#include "party.hpp"
|
||||
#include "command.hpp"
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "profile_infos.hpp"
|
||||
|
||||
#include <game/game.hpp>
|
||||
@ -17,10 +19,14 @@
|
||||
#include <utils/info_string.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
#include <game/fragment_handler.hpp>
|
||||
|
||||
namespace auth
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::array<uint64_t, 18> client_xuids{};
|
||||
|
||||
std::string get_hdd_serial()
|
||||
{
|
||||
DWORD serial{};
|
||||
@ -100,36 +106,45 @@ namespace auth
|
||||
std::string serialize_connect_data(const char* data, const int length)
|
||||
{
|
||||
utils::byte_buffer buffer{};
|
||||
profile_infos::profile_info info{};
|
||||
info.version = 4; // invalid
|
||||
info.serialize(buffer);
|
||||
//profile_infos::get_profile_info().value_or(profile_infos::profile_info{}).serialize(buffer);
|
||||
profile_infos::get_profile_info().value_or(profile_infos::profile_info{}).serialize(buffer);
|
||||
|
||||
buffer.write_string(data, static_cast<size_t>(length));
|
||||
|
||||
printf("Serialized with size: %llX\n", buffer.get_buffer().size());
|
||||
|
||||
return buffer.move_buffer();
|
||||
}
|
||||
|
||||
int send_connect_data_stub(const game::netsrc_t sock, game::netadr_t* adr, const char* data, int len)
|
||||
void send_fragmented_connect_packet(const game::netsrc_t sock, game::netadr_t* adr, const char* data,
|
||||
const int length)
|
||||
{
|
||||
const auto connect_data = serialize_connect_data(data, length);
|
||||
game::fragment_handler::fragment_data //
|
||||
(connect_data.data(), connect_data.size(), [&](const utils::byte_buffer& buffer)
|
||||
{
|
||||
utils::byte_buffer packet_buffer{};
|
||||
packet_buffer.write("connect");
|
||||
packet_buffer.write(" ");
|
||||
packet_buffer.write(buffer);
|
||||
|
||||
const auto& fragment_packet = packet_buffer.get_buffer();
|
||||
|
||||
game::NET_OutOfBandData(
|
||||
sock, adr, fragment_packet.data(),
|
||||
static_cast<int>(fragment_packet.size()));
|
||||
});
|
||||
}
|
||||
|
||||
int send_connect_data_stub(const game::netsrc_t sock, game::netadr_t* adr, const char* data, const int len)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string buffer{};
|
||||
|
||||
const auto is_connect_sequence = len >= 7 && strncmp("connect", data, 7) == 0;
|
||||
if (is_connect_sequence)
|
||||
if (!is_connect_sequence)
|
||||
{
|
||||
buffer.append("connect");
|
||||
buffer.push_back(' ');
|
||||
buffer.append(serialize_connect_data(data, len));
|
||||
|
||||
data = buffer.data();
|
||||
len = static_cast<int>(buffer.size());
|
||||
return game::NET_OutOfBandData(sock, adr, data, len);
|
||||
}
|
||||
|
||||
return reinterpret_cast<decltype(&send_connect_data_stub)>(0x142173600_g)(sock, adr, data, len);
|
||||
send_fragmented_connect_packet(sock, adr, data, len);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@ -139,16 +154,61 @@ namespace auth
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handle_connect_packet(const game::netadr_t& target, const network::data_view& data)
|
||||
void distribute_player_xuid(const game::netadr_t& target, const size_t player_index, const uint64_t xuid)
|
||||
{
|
||||
if (!game::is_server_running())
|
||||
if (player_index >= 18)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
utils::byte_buffer buffer{};
|
||||
buffer.write(static_cast<uint32_t>(player_index));
|
||||
buffer.write(xuid);
|
||||
|
||||
printf("Deserialized with size: %llX\n", data.size());
|
||||
game::foreach_connected_client([&](const game::client_s& client, const size_t index)
|
||||
{
|
||||
if (client.address.type != game::NA_BOT)
|
||||
{
|
||||
network::send(client.address, "playerXuid", buffer.get_buffer());
|
||||
}
|
||||
|
||||
if (index != player_index && target.type != game::NA_BOT)
|
||||
{
|
||||
utils::byte_buffer current_buffer{};
|
||||
current_buffer.write(static_cast<uint32_t>(index));
|
||||
current_buffer.write(client.xuid);
|
||||
|
||||
network::send(target, "playerXuid", current_buffer.get_buffer());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handle_new_player(const game::netadr_t& target)
|
||||
{
|
||||
const command::params_sv params{};
|
||||
if (params.size() < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const utils::info_string info_string(params[1]);
|
||||
const auto xuid = strtoull(info_string.get("xuid").data(), nullptr, 16);
|
||||
|
||||
size_t player_index = 18;
|
||||
game::foreach_connected_client([&](game::client_s& client, const size_t index)
|
||||
{
|
||||
if (client.address == target)
|
||||
{
|
||||
client.xuid = xuid;
|
||||
player_index = index;
|
||||
}
|
||||
});
|
||||
|
||||
distribute_player_xuid(target, player_index, xuid);
|
||||
}
|
||||
|
||||
void dispatch_connect_packet(const game::netadr_t& target, const std::string& data)
|
||||
{
|
||||
utils::byte_buffer buffer(data);
|
||||
const profile_infos::profile_info info(buffer);
|
||||
|
||||
@ -168,14 +228,50 @@ namespace auth
|
||||
profile_infos::add_and_distribute_profile_info(target, xuid, info);
|
||||
|
||||
game::SV_DirectConnect(target);
|
||||
handle_new_player(target);
|
||||
}
|
||||
|
||||
game::foreach_connected_client([&](game::client_s& client)
|
||||
void handle_connect_packet_fragment(const game::netadr_t& target, const network::data_view& data)
|
||||
{
|
||||
if (!game::is_server_running())
|
||||
{
|
||||
if (client.address == target)
|
||||
return;
|
||||
}
|
||||
|
||||
utils::byte_buffer buffer(data);
|
||||
|
||||
std::string final_packet{};
|
||||
if (game::fragment_handler::handle(target, buffer, final_packet))
|
||||
{
|
||||
scheduler::once([t = target, p = std::move(final_packet)]
|
||||
{
|
||||
client.xuid = xuid;
|
||||
}
|
||||
});
|
||||
dispatch_connect_packet(t, p);
|
||||
}, scheduler::server);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_player_xuid_packet(const game::netadr_t& target, const network::data_view& data)
|
||||
{
|
||||
if (game::is_server_running() || !party::is_host(target))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
utils::byte_buffer buffer(data);
|
||||
|
||||
const auto player_id = buffer.read<uint32_t>();
|
||||
const auto xuid = buffer.read<uint64_t>();
|
||||
|
||||
if (player_id < client_xuids.size())
|
||||
{
|
||||
client_xuids[player_id] = xuid;
|
||||
}
|
||||
}
|
||||
|
||||
void direct_connect_bots_stub(const game::netadr_t address)
|
||||
{
|
||||
game::SV_DirectConnect(address);
|
||||
handle_new_player(address);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,13 +290,51 @@ namespace auth
|
||||
return guid;
|
||||
}
|
||||
|
||||
uint64_t get_guid(const size_t client_num)
|
||||
{
|
||||
if (client_num >= 18)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!game::is_server_running())
|
||||
{
|
||||
return client_xuids[client_num];
|
||||
}
|
||||
|
||||
uint64_t xuid = 0;
|
||||
const auto callback = [&xuid](const game::client_s& client)
|
||||
{
|
||||
xuid = client.xuid;
|
||||
};
|
||||
|
||||
if (!game::access_connected_client(client_num, callback))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return xuid;
|
||||
}
|
||||
|
||||
void clear_stored_guids()
|
||||
{
|
||||
for (auto& xuid : client_xuids)
|
||||
{
|
||||
xuid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : generic_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// Skip connect handler
|
||||
utils::hook::set<uint8_t>(game::select(0x142253EFA, 0x14053714A), 0xEB);
|
||||
network::on("connect", handle_connect_packet);
|
||||
network::on("connect", handle_connect_packet_fragment);
|
||||
network::on("playerXuid", handle_player_xuid_packet);
|
||||
|
||||
// Intercept SV_DirectConnect in SV_AddTestClient
|
||||
utils::hook::call(game::select(0x1422490DC, 0x14052E582), direct_connect_bots_stub);
|
||||
|
||||
// Patch steam id bit check
|
||||
std::vector<std::pair<size_t, size_t>> patches{};
|
||||
|
@ -3,4 +3,6 @@
|
||||
namespace auth
|
||||
{
|
||||
uint64_t get_guid();
|
||||
uint64_t get_guid(size_t client_num);
|
||||
void clear_stored_guids();
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace bots
|
||||
entry = entry.substr(0, pos);
|
||||
}
|
||||
|
||||
bot_names.emplace_back(std::make_pair(entry, clan_abbrev));
|
||||
bot_names.emplace_back(entry, clan_abbrev);
|
||||
}
|
||||
|
||||
return bot_names;
|
||||
|
@ -116,6 +116,9 @@ namespace client_patches
|
||||
{
|
||||
fix_amd_cpu_stuttering();
|
||||
|
||||
// Don't modify process priority
|
||||
utils::hook::nop(0x142334C98_g, 6);
|
||||
|
||||
// Kill microphones for now
|
||||
utils::hook::set(0x15AAE9254_g, mixer_open_stub);
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "auth.hpp"
|
||||
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
@ -10,8 +14,25 @@ namespace colors
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour get_player_name_hook;
|
||||
utils::hook::detour get_gamer_tag_hook;
|
||||
utils::hook::detour cl_get_client_name_hook;
|
||||
|
||||
std::optional<int> get_color_for_xuid(const uint64_t xuid)
|
||||
{
|
||||
if (xuid == 0xCD02AF6448291209
|
||||
|| xuid == 0x10F0C433E08E1357
|
||||
|| xuid == 0x60E0FEFE42341715)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<int> get_color_for_client(const int client_num)
|
||||
{
|
||||
const auto xuid = auth::get_guid(static_cast<size_t>(client_num));
|
||||
return get_color_for_xuid(xuid);
|
||||
}
|
||||
|
||||
template <size_t index>
|
||||
void patch_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a = 255)
|
||||
@ -36,23 +57,39 @@ namespace colors
|
||||
utils::hook::copy(g_color_table + index * 4, color_float, sizeof(color_float));
|
||||
}
|
||||
|
||||
/*uint64_t get_player_name_stub(const uint64_t client, int client_num, char* buffer, const int size,
|
||||
const bool has_clan_tag)
|
||||
bool cl_get_client_name_stub(const int local_client_num, const int index, char* buf, const int size,
|
||||
const bool add_clan_name)
|
||||
{
|
||||
const auto res = get_player_name_hook.invoke<uint64_t>(client, client_num, buffer, size, has_clan_tag);
|
||||
const auto res = cl_get_client_name_hook.invoke<bool>(local_client_num, index, buf, size, add_clan_name);
|
||||
|
||||
if (_ReturnAddress() != reinterpret_cast<void*>(0x1406A7B56_g))
|
||||
if (_ReturnAddress() == reinterpret_cast<void*>(0x1406A7B56_g))
|
||||
{
|
||||
const auto val = utils::string::va("^%d%s", rand() % 7, buffer);
|
||||
strncpy_s(buffer, size, val, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}*/
|
||||
const auto color = get_color_for_client(index);
|
||||
if (!color)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
/*const char* get_gamer_tag_stub(const uint64_t num)
|
||||
const auto val = utils::string::va("^%d%s", *color, buf);
|
||||
utils::string::copy(buf, size, val);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*const char* get_gamer_tag_stub(const uint32_t num)
|
||||
{
|
||||
return utils::string::va("^3%s", get_gamer_tag_hook.invoke<const char*>(num));
|
||||
const auto color = get_color_for_xuid(steam::SteamUser()->GetSteamID().bits);
|
||||
const auto name = reinterpret_cast<const char* (*)(uint32_t)>(0x141EC6E80)(num) + 8;
|
||||
|
||||
if (!color || num)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
return utils::string::va("^1%s", *color, name);
|
||||
}*/
|
||||
}
|
||||
|
||||
@ -68,8 +105,8 @@ namespace colors
|
||||
patch_color<6>(151, 80, 221); // 6 - Pink
|
||||
|
||||
// Old addresses
|
||||
//get_player_name_hook.create(0x1413E3140_g, get_player_name_stub);
|
||||
//get_gamer_tag_hook.create(0x141EC7370_g, get_gamer_tag_stub);
|
||||
cl_get_client_name_hook.create(game::CL_GetClientName, cl_get_client_name_stub);
|
||||
//utils::hook::jump(0x141EC72E0_g, get_gamer_tag_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
#include "network.hpp"
|
||||
#include "workshop.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
@ -114,6 +115,8 @@ namespace getinfo
|
||||
info.set("sv_running", std::to_string(game::is_server_running()));
|
||||
info.set("dedicated", game::is_server() ? "1" : "0");
|
||||
info.set("hc", std::to_string(game::Com_GametypeSettings_GetUInt("hardcoremode", false)));
|
||||
info.set("modname", workshop::get_mod_name(game::get_dvar_string("fs_game")));
|
||||
info.set("fs_game", game::get_dvar_string("fs_game"));
|
||||
info.set("shortversion", SHORTVERSION);
|
||||
|
||||
network::send(target, "infoResponse", info.build(), '\n');
|
||||
|
@ -17,6 +17,7 @@ namespace loot
|
||||
const game::dvar_t* dvar_cg_unlockall_camos_and_reticles;
|
||||
const game::dvar_t* dvar_cg_unlockall_calling_cards;
|
||||
const game::dvar_t* dvar_cg_unlockall_specialists_outfits;
|
||||
const game::dvar_t* dvar_cg_unlockall_cac_slots;
|
||||
|
||||
utils::hook::detour loot_getitemquantity_hook;
|
||||
utils::hook::detour liveinventory_getitemquantity_hook;
|
||||
@ -30,7 +31,8 @@ namespace loot
|
||||
utils::hook::detour bg_unlockablescharactercustomizationitemlocked_hook;
|
||||
utils::hook::detour bg_emblemisentitlementbackgroundgranted_hook;
|
||||
utils::hook::detour liveentitlements_isentitlementactiveforcontroller_hook;
|
||||
|
||||
utils::hook::detour bg_unlockablesgetcustomclasscount_hook;
|
||||
|
||||
int loot_getitemquantity_stub(const game::ControllerIndex_t controller_index, const game::eModes mode, const int item_id)
|
||||
{
|
||||
if (!dvar_cg_unlockall_loot->current.value.enabled)
|
||||
@ -48,19 +50,25 @@ namespace loot
|
||||
|
||||
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
||||
{
|
||||
// Item id's for extra CaC slots, CWL camo's and paid specialist outfits
|
||||
// Item id's for CWL camo's and paid specialist outfits
|
||||
if (dvar_cg_unlockall_loot->current.value.enabled && (item_id == 99003 || item_id >= 99018 && item_id <= 99021 || item_id == 99025 ||
|
||||
item_id >= 90047 && item_id <= 90064))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Item id for extra CaC slots
|
||||
if (dvar_cg_unlockall_cac_slots->current.value.enabled && item_id == 99003)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return liveinventory_getitemquantity_hook.invoke<int>(controller_index, item_id);
|
||||
}
|
||||
|
||||
bool liveinventory_areextraslotspurchased_stub(const game::ControllerIndex_t controller_index)
|
||||
{
|
||||
if (dvar_cg_unlockall_loot->current.value.enabled)
|
||||
if (dvar_cg_unlockall_cac_slots->current.value.enabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -160,9 +168,19 @@ namespace loot
|
||||
|
||||
return liveentitlements_isentitlementactiveforcontroller_hook.invoke<bool>(controllerIndex, incentiveId);
|
||||
}
|
||||
|
||||
int bg_unlockablesgetcustomclasscount_stub(game::eModes mode, const game::ControllerIndex_t controllerIndex)
|
||||
{
|
||||
if (dvar_cg_unlockall_cac_slots->current.value.enabled)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
return bg_unlockablesgetcustomclasscount_hook.invoke<int>(mode, controllerIndex);
|
||||
}
|
||||
};
|
||||
|
||||
struct component final : client_component
|
||||
struct component final: client_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
@ -172,6 +190,7 @@ namespace loot
|
||||
dvar_cg_unlockall_camos_and_reticles = game::register_dvar_bool("cg_unlockall_camos_and_reticles", false, game::DVAR_ARCHIVE, "Unlocks all camos and reticles");
|
||||
dvar_cg_unlockall_calling_cards = game::register_dvar_bool("cg_unlockall_calling_cards", false, game::DVAR_ARCHIVE, "Unlocks all calling cards");
|
||||
dvar_cg_unlockall_specialists_outfits = game::register_dvar_bool("cg_unlockall_specialists_outfits", false, game::DVAR_ARCHIVE, "Unlocks all specialists outfits");
|
||||
dvar_cg_unlockall_cac_slots = game::register_dvar_bool("cg_unlockall_cac_slots", false, game::DVAR_ARCHIVE, "Unlocks all Create a Class Slots");
|
||||
|
||||
loot_getitemquantity_hook.create(0x141E82C00_g, loot_getitemquantity_stub);
|
||||
liveinventory_getitemquantity_hook.create(0x141E09030_g, liveinventory_getitemquantity_stub);
|
||||
@ -185,6 +204,7 @@ namespace loot
|
||||
bg_unlockablescharactercustomizationitemlocked_hook.create(0x1426A2030_g, bg_unlockablescharactercustomizationitemlocked_stub);
|
||||
bg_emblemisentitlementbackgroundgranted_hook.create(0x142667520_g, bg_emblemisentitlementbackgroundgranted_stub);
|
||||
liveentitlements_isentitlementactiveforcontroller_hook.create(0x141E124E0_g, liveentitlements_isentitlementactiveforcontroller_stub);
|
||||
bg_unlockablesgetcustomclasscount_hook.create(0x1426A5900_g, bg_unlockablesgetcustomclasscount_stub);
|
||||
|
||||
scheduler::once([]() {
|
||||
if (dvar_cg_unlockall_loot->current.value.enabled)
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "network.hpp"
|
||||
|
||||
#include "game/fragment_handler.hpp"
|
||||
|
||||
namespace network
|
||||
{
|
||||
namespace
|
||||
@ -161,7 +163,6 @@ namespace network
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t ret2()
|
||||
{
|
||||
return 2;
|
||||
@ -171,6 +172,15 @@ namespace network
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void com_error_oob_stub(const char* file, int line, int code, [[maybe_unused]] const char* fmt, const char* error)
|
||||
{
|
||||
char buffer[1024]{};
|
||||
|
||||
strncpy_s(buffer, error, _TRUNCATE);
|
||||
|
||||
game::Com_Error_(file, line, code, "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void on(const std::string& command, const callback& callback)
|
||||
@ -292,6 +302,8 @@ namespace network
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
scheduler::loop(game::fragment_handler::clean, scheduler::async, 5s);
|
||||
|
||||
utils::hook::nop(game::select(0x1423322B6, 0x140596DF6), 4);
|
||||
// don't increment data pointer to optionally skip socket byte
|
||||
utils::hook::call(game::select(0x142332283, 0x140596DC3), read_socket_byte_stub);
|
||||
@ -317,10 +329,21 @@ namespace network
|
||||
// NA_IP -> NA_RAWIP in NetAdr_ToString
|
||||
utils::hook::set<uint8_t>(game::select(0x142172ED4, 0x140515864), game::NA_RAWIP);
|
||||
|
||||
// Kill 'echo' OOB handler
|
||||
utils::hook::set<uint8_t>(game::select(0x14134D0FB, 0x14018EE82), 0xEB);
|
||||
|
||||
if (game::is_server())
|
||||
{
|
||||
// Remove restrictions for rcon commands
|
||||
utils::hook::call(0x140538D5C_g, &con_restricted_execute_buf_stub); // SVC_RemoteCommand
|
||||
utils::hook::call(0x140538D5C_g, con_restricted_execute_buf_stub); // SVC_RemoteCommand
|
||||
|
||||
// Kill 'error' OOB handler on the dedi
|
||||
utils::hook::nop(0x14018EF8B_g, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Truncate error string to make sure there are no buffer overruns later
|
||||
utils::hook::call(0x14134D206_g, com_error_oob_stub);
|
||||
}
|
||||
|
||||
// TODO: Fix that
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "party.hpp"
|
||||
#include "auth.hpp"
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "workshop.hpp"
|
||||
@ -37,12 +38,14 @@ namespace party
|
||||
}
|
||||
|
||||
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
||||
const std::string& pub_id)
|
||||
const std::string& usermap_id, const std::string& mod_id)
|
||||
{
|
||||
workshop::load_usermap_mod_if_needed(pub_id);
|
||||
auth::clear_stored_guids();
|
||||
|
||||
workshop::load_mod_if_needed(usermap_id, mod_id);
|
||||
|
||||
game::XSESSION_INFO info{};
|
||||
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, mapname.data(), gamemode.data(), pub_id.data());
|
||||
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, mapname.data(), gamemode.data(), usermap_id.data());
|
||||
}
|
||||
|
||||
void launch_mode(const game::eModes mode)
|
||||
@ -56,12 +59,13 @@ namespace party
|
||||
}
|
||||
|
||||
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
||||
const std::string& gametype, const std::string& pub_id,
|
||||
const std::string& gametype, const std::string& usermap_id,
|
||||
const std::string& mod_id,
|
||||
const bool was_retried = false)
|
||||
{
|
||||
if (game::Com_SessionMode_IsMode(mode))
|
||||
{
|
||||
connect_to_lobby(addr, mapname, gametype, pub_id);
|
||||
connect_to_lobby(addr, mapname, gametype, usermap_id, mod_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -69,7 +73,7 @@ namespace party
|
||||
{
|
||||
scheduler::once([=]
|
||||
{
|
||||
connect_to_lobby_with_mode(addr, mode, mapname, gametype, pub_id, true);
|
||||
connect_to_lobby_with_mode(addr, mode, mapname, gametype, usermap_id, mod_id, true);
|
||||
}, scheduler::main, 5s);
|
||||
|
||||
launch_mode(mode);
|
||||
@ -177,6 +181,8 @@ namespace party
|
||||
return;
|
||||
}
|
||||
|
||||
const auto mod_id = info.get("fs_game");
|
||||
|
||||
//const auto hostname = info.get("sv_hostname");
|
||||
const auto playmode = info.get("playmode");
|
||||
const auto mode = static_cast<game::eModes>(std::atoi(playmode.data()));
|
||||
@ -184,9 +190,10 @@ namespace party
|
||||
|
||||
scheduler::once([=]
|
||||
{
|
||||
const auto publisher_id = workshop::get_usermap_publisher_id(mapname);
|
||||
const auto usermap_id = workshop::get_usermap_publisher_id(mapname);
|
||||
|
||||
if (workshop::check_valid_publisher_id(mapname, publisher_id))
|
||||
if (workshop::check_valid_usermap_id(mapname, usermap_id) &&
|
||||
workshop::check_valid_mod_id(mod_id))
|
||||
{
|
||||
if (is_connecting_to_dedi)
|
||||
{
|
||||
@ -194,7 +201,7 @@ namespace party
|
||||
}
|
||||
|
||||
//connect_to_session(target, hostname, xuid, mode);
|
||||
connect_to_lobby_with_mode(target, mode, mapname, gametype, publisher_id);
|
||||
connect_to_lobby_with_mode(target, mode, mapname, gametype, usermap_id, mod_id);
|
||||
}
|
||||
}, scheduler::main);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <utils/info_string.hpp>
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace party
|
||||
{
|
||||
using query_callback_func = void(bool success, const game::netadr_t& host, const ::utils::info_string& info, uint32_t ping);
|
||||
|
@ -1,41 +1,68 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include <game/game.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace patches
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
||||
{
|
||||
char buffer[0x1000];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
game::Com_Error(game::ERROR_SCRIPT_DROP, "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : generic_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// don't make script errors fatal error
|
||||
utils::hook::call(game::select(0x1412CAC4D, 0x140158EB2), script_errors_stub);
|
||||
|
||||
// Change 4 character name limit to 3 characters
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DA53, 0x140531143), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(patches::component)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include <game/game.hpp>
|
||||
#include <game/utils.hpp>
|
||||
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace patches
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour sv_execute_client_messages_hook;
|
||||
|
||||
void sv_execute_client_messages_stub(game::client_s* client, game::msg_t* msg)
|
||||
{
|
||||
if ((client->reliableSequence - client->reliableAcknowledge) < 0)
|
||||
{
|
||||
client->reliableAcknowledge = client->reliableSequence;
|
||||
network::send(client->address, "error", "EXE_LOSTRELIABLECOMMANDS");
|
||||
return;
|
||||
}
|
||||
|
||||
sv_execute_client_messages_hook.invoke<void>(client, msg);
|
||||
}
|
||||
|
||||
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
||||
{
|
||||
char buffer[0x1000];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
game::Com_Error(game::ERROR_SCRIPT_DROP, "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : generic_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// don't make script errors fatal error
|
||||
utils::hook::call(game::select(0x1412CAC4D, 0x140158EB2), script_errors_stub);
|
||||
|
||||
// Change 4 character name limit to 3 characters
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DA53, 0x140531143), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);
|
||||
|
||||
// make sure client's reliableAck are not negative
|
||||
sv_execute_client_messages_hook.create(game::select(0x14224A460, 0x14052F840), sv_execute_client_messages_stub);
|
||||
|
||||
scheduler::once([]
|
||||
{
|
||||
game::register_dvar_string("password", "", game::DVAR_USERINFO, "password");
|
||||
}, scheduler::pipeline::main);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(patches::component)
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "party.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
#include <utils/properties.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
@ -14,6 +13,7 @@
|
||||
#include <utils/io.hpp>
|
||||
|
||||
#include "game/utils.hpp"
|
||||
#include "game/fragment_handler.hpp"
|
||||
|
||||
namespace profile_infos
|
||||
{
|
||||
@ -44,9 +44,12 @@ namespace profile_infos
|
||||
return {std::move(info)};
|
||||
}
|
||||
|
||||
void send_profile_info(const game::netadr_t& address, const std::string& buffer)
|
||||
void send_profile_info(const game::netadr_t& address, const std::string& data)
|
||||
{
|
||||
network::send(address, "profileInfo", buffer);
|
||||
game::fragment_handler::fragment_data(data.data(), data.size(), [&address](const utils::byte_buffer& buffer)
|
||||
{
|
||||
network::send(address, "profileInfo", buffer.get_buffer());
|
||||
});
|
||||
}
|
||||
|
||||
void distribute_profile_info(const uint64_t user_id, const profile_info& info)
|
||||
@ -253,10 +256,16 @@ namespace profile_infos
|
||||
}
|
||||
|
||||
utils::byte_buffer buffer(data);
|
||||
const auto user_id = buffer.read<uint64_t>();
|
||||
const profile_info info(buffer);
|
||||
|
||||
add_profile_info(user_id, info);
|
||||
std::string final_packet{};
|
||||
if (game::fragment_handler::handle(server, buffer, final_packet))
|
||||
{
|
||||
buffer = utils::byte_buffer(final_packet);
|
||||
const auto user_id = buffer.read<uint64_t>();
|
||||
const profile_info info(buffer);
|
||||
|
||||
add_profile_info(user_id, info);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,6 @@ namespace scheduler
|
||||
task_pipeline pipelines[pipeline::count];
|
||||
|
||||
utils::hook::detour r_end_frame_hook;
|
||||
utils::hook::detour g_run_frame_hook;
|
||||
utils::hook::detour main_frame_hook;
|
||||
|
||||
|
||||
@ -98,9 +97,9 @@ namespace scheduler
|
||||
r_end_frame_hook.invoke<void>();
|
||||
}
|
||||
|
||||
void server_frame_stub()
|
||||
void g_clear_vehicle_inputs_stub()
|
||||
{
|
||||
g_run_frame_hook.invoke<void>();
|
||||
game::G_ClearVehicleInputs();
|
||||
execute(pipeline::server);
|
||||
}
|
||||
|
||||
@ -168,12 +167,14 @@ namespace scheduler
|
||||
{
|
||||
if (!game::is_server())
|
||||
{
|
||||
r_end_frame_hook.create(0x142272B00_g, r_end_frame_stub);
|
||||
// some func called before R_EndFrame, maybe SND_EndFrame?
|
||||
r_end_frame_hook.create(0x142272B00_g, r_end_frame_stub);
|
||||
}
|
||||
|
||||
main_frame_hook.create(game::select(0x1420F8E00, 0x1405020E0), main_frame_stub);
|
||||
// Com_Frame_Try_Block_Function
|
||||
main_frame_hook.create(game::select(0x1420F8E00, 0x1405020E0), main_frame_stub);
|
||||
|
||||
utils::hook::call(game::select(0x14225522E, 0x140538427), g_clear_vehicle_inputs_stub);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
|
@ -5,48 +5,39 @@
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace workshop
|
||||
{
|
||||
const std::string get_usermap_publisher_id(const std::string& mapname)
|
||||
{
|
||||
const auto total_usermaps = *reinterpret_cast<unsigned int*>(0x1567B3580_g);
|
||||
|
||||
for (unsigned int i = 0; i < total_usermaps; ++i)
|
||||
{
|
||||
const auto usermap_data = reinterpret_cast<game::workshop_data*>(0x1567B3588_g + (sizeof(game::workshop_data) * i));
|
||||
if (usermap_data->folderName == mapname)
|
||||
{
|
||||
return usermap_data->publisherId;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool check_valid_publisher_id(const std::string& mapname, const std::string& pub_id)
|
||||
{
|
||||
if (!game::DB_FileExists(mapname.data(), 0) && pub_id.empty())
|
||||
{
|
||||
game::Com_Error(0, "Can't find usermap: %s!\nMake sure you're subscribed to the workshop item.", mapname.data());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_usermap_mod_if_needed(const std::string& pub_id)
|
||||
{
|
||||
if (!game::isModLoaded() && !pub_id.empty())
|
||||
{
|
||||
game::loadMod(0, "usermaps", 0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour setup_server_map_hook;
|
||||
|
||||
bool has_mod(const std::string& pub_id)
|
||||
{
|
||||
const auto total_mods = *reinterpret_cast<unsigned int*>(0x15678D170_g);
|
||||
|
||||
for (unsigned int i = 0; i < total_mods; ++i)
|
||||
{
|
||||
const auto mod_data = reinterpret_cast<game::workshop_data*>(0x15678D178_g + (sizeof(game::workshop_data) * i));
|
||||
if (mod_data->publisherId == pub_id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void load_usermap_mod_if_needed(const std::string& publisher_id)
|
||||
{
|
||||
if (!game::isModLoaded() && !publisher_id.empty())
|
||||
{
|
||||
game::loadMod(0, "usermaps", true);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_server_map_stub(int localClientNum, const char* mapname, const char* gametype)
|
||||
{
|
||||
const auto publisher_id = get_usermap_publisher_id(mapname);
|
||||
@ -72,6 +63,102 @@ namespace workshop
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_mod_name(const std::string& mod_id)
|
||||
{
|
||||
if (mod_id == "usermaps" || !game::is_server())
|
||||
{
|
||||
return mod_id;
|
||||
}
|
||||
|
||||
const utils::nt::library host{};
|
||||
const auto base_path = host.get_folder().generic_string();
|
||||
const auto path = utils::string::va("%s/mods/%s/zone/workshop.json", base_path.data(), mod_id.data());
|
||||
const auto json_str = utils::io::read_file(path);
|
||||
|
||||
if (json_str.empty())
|
||||
{
|
||||
printf("[ Workshop ] workshop.json has not been found in mod folder: %s\n", mod_id.data());
|
||||
return mod_id;
|
||||
}
|
||||
|
||||
rapidjson::Document doc;
|
||||
const rapidjson::ParseResult parse_result = doc.Parse(json_str);
|
||||
|
||||
if (parse_result.IsError() || !doc.IsObject())
|
||||
{
|
||||
printf("[ Workshop ] Unable to parse workshop.json\n");
|
||||
return mod_id;
|
||||
}
|
||||
|
||||
if (doc.HasMember("Title"))
|
||||
{
|
||||
std::string title = doc["Title"].GetString();
|
||||
|
||||
if (title.size() > 31)
|
||||
{
|
||||
title.resize(31);
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
printf("[ Workshop ] workshop.json has no \"Title\" member.\n");
|
||||
return mod_id;
|
||||
}
|
||||
|
||||
std::string get_usermap_publisher_id(const std::string& mapname)
|
||||
{
|
||||
const auto total_usermaps = *reinterpret_cast<unsigned int*>(0x1567B3580_g);
|
||||
|
||||
for (unsigned int i = 0; i < total_usermaps; ++i)
|
||||
{
|
||||
const auto usermap_data = reinterpret_cast<game::workshop_data*>(0x1567B3588_g + (sizeof(game::workshop_data) * i));
|
||||
if (usermap_data->folderName == mapname)
|
||||
{
|
||||
return usermap_data->publisherId;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool check_valid_usermap_id(const std::string& mapname, const std::string& pub_id)
|
||||
{
|
||||
if (!game::DB_FileExists(mapname.data(), 0) && pub_id.empty())
|
||||
{
|
||||
game::UI_OpenErrorPopupWithMessage(0, 0x100,
|
||||
utils::string::va("Can't find usermap: %s!\nMake sure you're subscribed to the workshop item.", mapname.data()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_valid_mod_id(const std::string& mod)
|
||||
{
|
||||
if (mod.empty() || mod == "usermaps")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!has_mod(mod))
|
||||
{
|
||||
game::UI_OpenErrorPopupWithMessage(0, 0x100,
|
||||
utils::string::va("Can't find mod with publisher id: %s!\nMake sure you're subscribed to the workshop item.", mod.data()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_mod_if_needed(const std::string& usermap, const std::string& mod)
|
||||
{
|
||||
if (!usermap.empty() || mod != "usermaps")
|
||||
{
|
||||
game::loadMod(0, mod.data(), true);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public client_component
|
||||
{
|
||||
public:
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace workshop
|
||||
{
|
||||
const std::string get_usermap_publisher_id(const std::string& mapname);
|
||||
bool check_valid_publisher_id(const std::string& mapname, const std::string& pub_id);
|
||||
void load_usermap_mod_if_needed(const std::string& pub_id);
|
||||
std::string get_usermap_publisher_id(const std::string& mapname);
|
||||
std::string get_mod_name(const std::string& mod_id);
|
||||
bool check_valid_usermap_id(const std::string& mapname, const std::string& pub_id);
|
||||
bool check_valid_mod_id(const std::string& pub_id);
|
||||
void load_mod_if_needed(const std::string& usermap, const std::string& mod);
|
||||
}
|
||||
|
155
src/client/game/fragment_handler.cpp
Normal file
155
src/client/game/fragment_handler.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
#include <std_include.hpp>
|
||||
#include "fragment_handler.hpp"
|
||||
|
||||
namespace game::fragment_handler
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr size_t MAX_FRAGMENTS = 100;
|
||||
|
||||
using fragments = std::unordered_map<size_t, std::string>;
|
||||
|
||||
struct fragmented_packet
|
||||
{
|
||||
size_t fragment_count{0};
|
||||
fragments fragments{};
|
||||
std::chrono::high_resolution_clock::time_point insertion_time = std::chrono::high_resolution_clock::now();
|
||||
};
|
||||
|
||||
using id_fragment_map = std::unordered_map<uint64_t, fragmented_packet>;
|
||||
using address_fragment_map = std::unordered_map<netadr_t, id_fragment_map>;
|
||||
|
||||
utils::concurrency::container<address_fragment_map> global_map{};
|
||||
|
||||
std::vector<std::string> construct_fragments(const void* data, const size_t length)
|
||||
{
|
||||
std::vector<std::string> fragments{};
|
||||
|
||||
constexpr size_t max_fragment_size = 0x400;
|
||||
|
||||
for (size_t i = 0; i < length; i += max_fragment_size)
|
||||
{
|
||||
const auto current_fragment_size = std::min(length - i, max_fragment_size);
|
||||
|
||||
std::string fragment(static_cast<const char*>(data) + i, current_fragment_size);
|
||||
fragments.push_back(std::move(fragment));
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle(const netadr_t& target, utils::byte_buffer& buffer, std::string& final_packet)
|
||||
{
|
||||
const auto fragment_id = buffer.read<uint64_t>();
|
||||
const size_t fragment_count = buffer.read<uint32_t>();
|
||||
const size_t fragment_index = buffer.read<uint32_t>();
|
||||
|
||||
auto fragment_data = buffer.get_remaining_data();
|
||||
|
||||
if (fragment_index > fragment_count || !fragment_count || fragment_count > MAX_FRAGMENTS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return global_map.access<bool>([&](address_fragment_map& map)
|
||||
{
|
||||
auto& user_map = map[target];
|
||||
if (!user_map.contains(fragment_id) && user_map.size() > MAX_FRAGMENTS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& packet_queue = user_map[fragment_id];
|
||||
|
||||
if (packet_queue.fragment_count == 0)
|
||||
{
|
||||
packet_queue.fragment_count = fragment_count;
|
||||
}
|
||||
|
||||
if (packet_queue.fragment_count != fragment_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packet_queue.fragments.size() + 1 < fragment_count)
|
||||
{
|
||||
packet_queue.fragments[fragment_index] = std::move(fragment_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
final_packet.clear();
|
||||
|
||||
for (size_t i = 0; i < fragment_count; ++i)
|
||||
{
|
||||
if (i == fragment_index)
|
||||
{
|
||||
final_packet.append(fragment_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
final_packet.append(packet_queue.fragments.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void clean()
|
||||
{
|
||||
global_map.access([](address_fragment_map& map)
|
||||
{
|
||||
for (auto i = map.begin(); i != map.end();)
|
||||
{
|
||||
auto& user_map = i->second;
|
||||
|
||||
for (auto j = user_map.begin(); j != user_map.end();)
|
||||
{
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto diff = now - j->second.insertion_time;
|
||||
|
||||
if (diff > 5s)
|
||||
{
|
||||
j = user_map.erase(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
if (user_map.empty())
|
||||
{
|
||||
i = map.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void fragment_handler::fragment_data(const void* data, const size_t size,
|
||||
const std::function<void(const utils::byte_buffer& buffer)>& callback)
|
||||
{
|
||||
static std::atomic_uint64_t current_id{0};
|
||||
const auto id = current_id++;
|
||||
|
||||
const auto fragments = construct_fragments(data, size);
|
||||
|
||||
for (size_t i = 0; i < fragments.size(); ++i)
|
||||
{
|
||||
utils::byte_buffer buffer{};
|
||||
buffer.write(id);
|
||||
buffer.write(static_cast<uint32_t>(fragments.size()));
|
||||
buffer.write(static_cast<uint32_t>(i));
|
||||
|
||||
auto& fragment = fragments.at(i);
|
||||
buffer.write(fragment.data(), fragment.size());
|
||||
|
||||
callback(buffer);
|
||||
}
|
||||
}
|
||||
}
|
17
src/client/game/fragment_handler.hpp
Normal file
17
src/client/game/fragment_handler.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <utils/byte_buffer.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
#include "../component/network.hpp"
|
||||
|
||||
namespace game::fragment_handler
|
||||
{
|
||||
bool handle(const netadr_t& target, utils::byte_buffer& buffer,
|
||||
std::string& final_packet);
|
||||
|
||||
void clean();
|
||||
|
||||
void fragment_data(const void* data, const size_t size,
|
||||
const std::function<void(const utils::byte_buffer& buffer)>& callback);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,269 +1,278 @@
|
||||
#pragma once
|
||||
|
||||
#include "structs.hpp"
|
||||
|
||||
#define WEAK __declspec(selectany)
|
||||
|
||||
namespace game
|
||||
{
|
||||
#define Com_Error(code, fmt, ...) Com_Error_(__FILE__, __LINE__, code, fmt, ##__VA_ARGS__)
|
||||
|
||||
// CL
|
||||
WEAK symbol<void(int controllerIndex, XSESSION_INFO* hostInfo, const netadr_t* addr, int numPublicSlots,
|
||||
int numPrivateSlots, const char* mapname, const char* gametype,
|
||||
const char* somethingWithUserMaps)> CL_ConnectFromLobby
|
||||
{0x14134C570};
|
||||
WEAK symbol<bool(int localClientNum, int index, char* buf, int size, bool addClanName)> CL_GetClientName{
|
||||
0x1413E3140
|
||||
};
|
||||
|
||||
// Game
|
||||
WEAK symbol<void(gentity_s* ent, gentity_s* target, int mode, const char* chatText)> G_Say{0x0, 0x140299170};
|
||||
WEAK symbol<void(const char* fmt, ...)> G_LogPrintf{0x0, 0x1402A7BB0};
|
||||
|
||||
// Com
|
||||
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x142148F60, 0x140505630};
|
||||
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8170, 0x140501470};
|
||||
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7370};
|
||||
WEAK symbol<void(eNetworkModes networkMode)> Com_SessionMode_SetNetworkMode{0x1420F75B0, 0x140500B80};
|
||||
WEAK symbol<eGameModes(eGameModes gameMode)> Com_SessionMode_SetGameMode{0x1420F7570, 0x140500B40};
|
||||
WEAK symbol<eModes(eModes mode)> Com_SessionMode_SetMode{0x1420F7570};
|
||||
WEAK symbol<void(const char* gametype, bool loadDefaultSettings)> Com_GametypeSettings_SetGametype{
|
||||
0x1420F5980
|
||||
};
|
||||
WEAK symbol<unsigned int(const char* settingName, bool getDefault)> Com_GametypeSettings_GetUInt{0x1420F4E00, 0x1404FE5C0};
|
||||
WEAK symbol<bool()> Com_IsRunningUILevel{0x142148350};
|
||||
WEAK symbol<void(int localClientNum, eModes fromMode, eModes toMode, uint32_t flags)> Com_SwitchMode{
|
||||
0x14214A4D0
|
||||
};
|
||||
WEAK symbol<const char*(const char* fullpath)> Com_LoadRawTextFile{0x1420F61B0};
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC010, 0x1404F75B0};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t controllerIndex, const char* buffer)> Cbuf_ExecuteBuffer{
|
||||
0x14133BE10, 0x1404F78D0
|
||||
};
|
||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
||||
0x1420ECC90, 0x1404F8210
|
||||
};
|
||||
WEAK symbol<void()> Cbuf_AddServerText_f{0x0, 0x1407DB4C0};
|
||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddServerCommandInternal
|
||||
{
|
||||
0x0, 0x1404F8280
|
||||
};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t controllerIndex, const char* text,
|
||||
bool fromRemoteConsole)> Cmd_ExecuteSingleCommand{
|
||||
0x1420ED380, 0x1404F8890
|
||||
};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t localControllerIndex, const char* text_in, int max_tokens,
|
||||
bool evalExpressions, CmdArgs* args)> Cmd_TokenizeStringKernel{0x1420EED60, 0x1404FA300};
|
||||
WEAK symbol<void()> Cmd_EndTokenizedString{0x1420ECED0, 0x1404F8420};
|
||||
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0, 0x140182C40};
|
||||
|
||||
// DB
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, uint32_t zoneCount, bool sync, bool suppressSync)> DB_LoadXAssets{
|
||||
0x1414236A0
|
||||
};
|
||||
WEAK symbol<void(XAssetType type, XAssetEnum* func, void* inData, bool includeOverride)> DB_EnumXAssets{
|
||||
0x141420970, 0x1401D5A50
|
||||
};
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char* name, bool errorIfMissing, int waitTime)> DB_FindXAssetHeader{
|
||||
0x141420ED0, 0x1401D5FB0
|
||||
};
|
||||
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x1413E9DA0, 0x14019F080};
|
||||
WEAK symbol<bool(const char* zoneName, int source)> DB_FileExists{0x141420B40};
|
||||
WEAK symbol<void()> DB_ReleaseXAssets{0x1414247C0};
|
||||
|
||||
// Live
|
||||
#pragma once
|
||||
|
||||
#include "structs.hpp"
|
||||
|
||||
#define WEAK __declspec(selectany)
|
||||
|
||||
namespace game
|
||||
{
|
||||
#define Com_Error(code, fmt, ...) Com_Error_(__FILE__, __LINE__, code, fmt, ##__VA_ARGS__)
|
||||
|
||||
// CL
|
||||
WEAK symbol<void(int controllerIndex, XSESSION_INFO* hostInfo, const netadr_t* addr, int numPublicSlots,
|
||||
int numPrivateSlots, const char* mapname, const char* gametype,
|
||||
const char* somethingWithUserMaps)> CL_ConnectFromLobby
|
||||
{0x14134C570};
|
||||
WEAK symbol<bool(int localClientNum, int index, char* buf, int size, bool addClanName)> CL_GetClientName{
|
||||
0x1413E3140
|
||||
};
|
||||
|
||||
// Game
|
||||
WEAK symbol<void(gentity_s* ent, gentity_s* target, int mode, const char* chatText)> G_Say{0x0, 0x140299170};
|
||||
WEAK symbol<void(const char* fmt, ...)> G_LogPrintf{0x0, 0x1402A7BB0};
|
||||
|
||||
// Com
|
||||
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x142148F60, 0x140505630};
|
||||
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8170, 0x140501470};
|
||||
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7370};
|
||||
WEAK symbol<void(eNetworkModes networkMode)> Com_SessionMode_SetNetworkMode{0x1420F75B0, 0x140500B80};
|
||||
WEAK symbol<eGameModes(eGameModes gameMode)> Com_SessionMode_SetGameMode{0x1420F7570, 0x140500B40};
|
||||
WEAK symbol<eModes(eModes mode)> Com_SessionMode_SetMode{0x1420F7570};
|
||||
WEAK symbol<void(const char* gametype, bool loadDefaultSettings)> Com_GametypeSettings_SetGametype{
|
||||
0x1420F5980
|
||||
};
|
||||
WEAK symbol<unsigned int(const char* settingName, bool getDefault)> Com_GametypeSettings_GetUInt{
|
||||
0x1420F4E00, 0x1404FE5C0
|
||||
};
|
||||
WEAK symbol<bool()> Com_IsRunningUILevel{0x142148350};
|
||||
WEAK symbol<void(int localClientNum, eModes fromMode, eModes toMode, uint32_t flags)> Com_SwitchMode{
|
||||
0x14214A4D0
|
||||
};
|
||||
WEAK symbol<const char*(const char* fullpath)> Com_LoadRawTextFile{0x1420F61B0};
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC010, 0x1404F75B0};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t controllerIndex, const char* buffer)> Cbuf_ExecuteBuffer{
|
||||
0x14133BE10, 0x1404F78D0
|
||||
};
|
||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
||||
0x1420ECC90, 0x1404F8210
|
||||
};
|
||||
WEAK symbol<void()> Cbuf_AddServerText_f{0x0, 0x1407DB4C0};
|
||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddServerCommandInternal
|
||||
{
|
||||
0x0, 0x1404F8280
|
||||
};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t controllerIndex, const char* text,
|
||||
bool fromRemoteConsole)> Cmd_ExecuteSingleCommand{
|
||||
0x1420ED380, 0x1404F8890
|
||||
};
|
||||
WEAK symbol<void(int localClientNum, ControllerIndex_t localControllerIndex, const char* text_in, int max_tokens,
|
||||
bool evalExpressions, CmdArgs* args)> Cmd_TokenizeStringKernel{0x1420EED60, 0x1404FA300};
|
||||
WEAK symbol<void()> Cmd_EndTokenizedString{0x1420ECED0, 0x1404F8420};
|
||||
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0, 0x140182C40};
|
||||
|
||||
// DB
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, uint32_t zoneCount, bool sync, bool suppressSync)> DB_LoadXAssets{
|
||||
0x1414236A0
|
||||
};
|
||||
WEAK symbol<void(XAssetType type, XAssetEnum* func, void* inData, bool includeOverride)> DB_EnumXAssets{
|
||||
0x141420970, 0x1401D5A50
|
||||
};
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char* name, bool errorIfMissing, int waitTime)> DB_FindXAssetHeader{
|
||||
0x141420ED0, 0x1401D5FB0
|
||||
};
|
||||
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x1413E9DA0, 0x14019F080};
|
||||
WEAK symbol<bool(const char* zoneName, int source)> DB_FileExists{0x141420B40};
|
||||
WEAK symbol<void()> DB_ReleaseXAssets{0x1414247C0};
|
||||
|
||||
// G
|
||||
WEAK symbol<void()> G_ClearVehicleInputs{0x1423812E0, 0x1405C1200};
|
||||
|
||||
WEAK symbol<qboolean(void* ent)> StuckInClient{0x1415A8360, 0x14023BFE0};
|
||||
|
||||
// Live
|
||||
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
||||
|
||||
// Info
|
||||
WEAK symbol<const char* (const char*, const char* key)> Info_ValueForKey{ 0x1422E87B0 };
|
||||
|
||||
// MSG
|
||||
WEAK symbol<uint8_t(msg_t* msg)> MSG_ReadByte{0x142155450, 0x14050D1B0};
|
||||
|
||||
// NET
|
||||
WEAK symbol<bool(netsrc_t sock, int length, const void* data, const netadr_t* to)> NET_SendPacket{
|
||||
0x1423323B0, 0x140596E40
|
||||
};
|
||||
WEAK symbol<bool(char const*, netadr_t*)> NET_StringToAdr{0x142172780, 0x140515110};
|
||||
|
||||
// Sys
|
||||
WEAK symbol<int()> Sys_Milliseconds{0x142332870};
|
||||
WEAK symbol<void()> Sys_ShowConsole{0x1423333C0, 0x140597E40};
|
||||
WEAK symbol<TLSData*()> Sys_GetTLS{0x1421837B0, 0x140525EB0};
|
||||
WEAK symbol<TLSData*()> Sys_IsDatabaseReady{0x142183A60};
|
||||
|
||||
// Unnamed
|
||||
WEAK symbol<const char*(const char* name)> CopyString{0x1422AC220, 0x14056BD70};
|
||||
|
||||
WEAK symbol<bool()> isModLoaded{0x1420D5020};
|
||||
WEAK symbol<void(int, const char*, int)> loadMod{0x1420D6930};
|
||||
|
||||
// Dvar
|
||||
WEAK symbol<bool(const dvar_t* dvar)> Dvar_IsSessionModeBaseDvar{0x1422C23A0, 0x140576890};
|
||||
WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BCCD0, 0x140575540};
|
||||
WEAK symbol<unsigned int(const char* str)> Dvar_GenerateHash{0x14133DBF0, 0x140185800};
|
||||
WEAK symbol<dvar_t*(unsigned int hash)> Dvar_FindMalleableVar{0x1422BCC40};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetDebugName{0x1422BD250};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetString{0x1422BF590, 0x140575E30};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_DisplayableValue{0x1422BC080};
|
||||
WEAK symbol<bool(const dvar_t* dvar)> Dvar_GetBool{0x1422BCED0};
|
||||
WEAK symbol<int(const dvar_t* dvar)> Dvar_GetInt{0x0, 0x140575C20};
|
||||
WEAK symbol<float(const dvar_t* dvar)> Dvar_GetFLoat{0x0, 0x140575B20};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, bool value, int flags,
|
||||
const char* description)> Dvar_RegisterBool{
|
||||
0x1422D0900, 0x14057B500
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, float value, float min, float max, unsigned int flags,
|
||||
const char* description)> Dvar_RegisterFloat{
|
||||
0x0, 0x14057B6B0
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, bool value, int flags,
|
||||
const char* description)> Dvar_SessionModeRegisterBool{
|
||||
0x1422D0D40, 0x14057BAA0
|
||||
};
|
||||
WEAK symbol<void(dvarStrHash_t hash, bool value, eModes mode)> Dvar_SessionModeSetDefaultBool{
|
||||
0x1422D0E90, 0x14057BCE0
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, const char* value, int flags,
|
||||
const char* description)> Dvar_RegisterString{
|
||||
0x1422D0B70, 0x14057B890
|
||||
};
|
||||
WEAK symbol<void(void (*callback)(const dvar_t*, void*), void* userData)> Dvar_ForEach{0x1422BCD00};
|
||||
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
|
||||
0x1422C7500
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvar_t* dvar, eModes mode)> Dvar_GetSessionModeSpecificDvar{
|
||||
0x1422BF500, 0x140575D90
|
||||
};
|
||||
|
||||
// UI
|
||||
WEAK symbol<void(bool frontend)> UI_CoD_Init{0x141F29010, 0x1404A0A50};
|
||||
WEAK symbol<void()> UI_CoD_LobbyUI_Init{0x141F2BD80, 0x1404A1F50};
|
||||
WEAK symbol<void()> UI_CoD_Shutdown{0x141F32E10, 0x0};
|
||||
WEAK symbol<void(const char*, const char*, int, game::hks::lua_State*)> UI_AddMenu{0x1427018F0, 0x0};
|
||||
WEAK symbol<const char*(int)> UI_CoD_GetRootNameForController{0x141F28940, 0x0};
|
||||
WEAK symbol<void(hks::lua_State*, const char*)> Lua_CoD_LoadLuaFile{0x141F11A20, 0x0};
|
||||
WEAK symbol<void(int localClientNum)> CG_LUIHUDRestart{0x140F7E970};
|
||||
WEAK symbol<const char*(const char*, const char* key)> Info_ValueForKey{0x1422E87B0};
|
||||
|
||||
// MSG
|
||||
WEAK symbol<uint8_t(msg_t* msg)> MSG_ReadByte{0x142155450, 0x14050D1B0};
|
||||
|
||||
// NET
|
||||
WEAK symbol<bool(netsrc_t sock, netadr_t* adr, const void* data, int len)> NET_OutOfBandData{0x142173600};
|
||||
WEAK symbol<bool(netsrc_t sock, int length, const void* data, const netadr_t* to)> NET_SendPacket{
|
||||
0x1423323B0, 0x140596E40
|
||||
};
|
||||
WEAK symbol<bool(char const*, netadr_t*)> NET_StringToAdr{0x142172780, 0x140515110};
|
||||
|
||||
// Sys
|
||||
WEAK symbol<int()> Sys_Milliseconds{0x142332870};
|
||||
WEAK symbol<void()> Sys_ShowConsole{0x1423333C0, 0x140597E40};
|
||||
WEAK symbol<TLSData*()> Sys_GetTLS{0x1421837B0, 0x140525EB0};
|
||||
WEAK symbol<TLSData*()> Sys_IsDatabaseReady{0x142183A60};
|
||||
|
||||
// Unnamed
|
||||
WEAK symbol<const char*(const char* name)> CopyString{0x1422AC220, 0x14056BD70};
|
||||
|
||||
WEAK symbol<bool()> isModLoaded{0x1420D5020};
|
||||
WEAK symbol<void(int, const char*, bool)> loadMod{0x1420D6930};
|
||||
|
||||
// Dvar
|
||||
WEAK symbol<bool(const dvar_t* dvar)> Dvar_IsSessionModeBaseDvar{0x1422C23A0, 0x140576890};
|
||||
WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BCCD0, 0x140575540};
|
||||
WEAK symbol<unsigned int(const char* str)> Dvar_GenerateHash{0x14133DBF0, 0x140185800};
|
||||
WEAK symbol<dvar_t*(unsigned int hash)> Dvar_FindMalleableVar{0x1422BCC40};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetDebugName{0x1422BD250};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetString{0x1422BF590, 0x140575E30};
|
||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_DisplayableValue{0x1422BC080};
|
||||
WEAK symbol<bool(const dvar_t* dvar)> Dvar_GetBool{0x1422BCED0};
|
||||
WEAK symbol<int(const dvar_t* dvar)> Dvar_GetInt{0x0, 0x140575C20};
|
||||
WEAK symbol<float(const dvar_t* dvar)> Dvar_GetFLoat{0x0, 0x140575B20};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, bool value, int flags,
|
||||
const char* description)> Dvar_RegisterBool{
|
||||
0x1422D0900, 0x14057B500
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, float value, float min, float max, unsigned int flags,
|
||||
const char* description)> Dvar_RegisterFloat{
|
||||
0x0, 0x14057B6B0
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, bool value, int flags,
|
||||
const char* description)> Dvar_SessionModeRegisterBool{
|
||||
0x1422D0D40, 0x14057BAA0
|
||||
};
|
||||
WEAK symbol<void(dvarStrHash_t hash, bool value, eModes mode)> Dvar_SessionModeSetDefaultBool{
|
||||
0x1422D0E90, 0x14057BCE0
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, const char* value, int flags,
|
||||
const char* description)> Dvar_RegisterString{
|
||||
0x1422D0B70, 0x14057B890
|
||||
};
|
||||
WEAK symbol<void(void (*callback)(const dvar_t*, void*), void* userData)> Dvar_ForEach{0x1422BCD00};
|
||||
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
|
||||
0x1422C7500
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvar_t* dvar, eModes mode)> Dvar_GetSessionModeSpecificDvar{
|
||||
0x1422BF500, 0x140575D90
|
||||
};
|
||||
|
||||
// UI
|
||||
WEAK symbol<void(int localClientNumber, int errorcode, const char* errorMessage)> UI_OpenErrorPopupWithMessage{0x14228DEE0};
|
||||
WEAK symbol<void(bool frontend)> UI_CoD_Init{0x141F29010, 0x1404A0A50};
|
||||
WEAK symbol<void()> UI_CoD_LobbyUI_Init{0x141F2BD80, 0x1404A1F50};
|
||||
WEAK symbol<void()> UI_CoD_Shutdown{0x141F32E10, 0x0};
|
||||
WEAK symbol<void(const char*, const char*, int, game::hks::lua_State*)> UI_AddMenu{0x1427018F0, 0x0};
|
||||
WEAK symbol<const char*(int)> UI_CoD_GetRootNameForController{0x141F28940, 0x0};
|
||||
WEAK symbol<void(hks::lua_State*, const char*)> Lua_CoD_LoadLuaFile{0x141F11A20, 0x0};
|
||||
WEAK symbol<void(int localClientNum)> CG_LUIHUDRestart{0x140F7E970};
|
||||
WEAK symbol<void(int localClientNum)> CL_CheckKeepDrawingConnectScreen{0x1413CCAE0};
|
||||
WEAK symbol<void(const char* key, int value, hks::lua_State* luaVM)> Lua_SetTableInt{ 0x141F066E0 };
|
||||
|
||||
// Scr
|
||||
WEAK symbol<void(scriptInstance_t inst, int value)> Scr_AddInt{0x1412E9870, 0x14016F160};
|
||||
WEAK symbol<void(scriptInstance_t inst, const char* value)> Scr_AddString{0x0, 0x14016F320};
|
||||
WEAK symbol<const char*(scriptInstance_t inst, unsigned int index)> Scr_GetString{0x0, 0x140171490};
|
||||
WEAK symbol<void(gentity_s* ent, ScrVarCanonicalName_t stringValue, unsigned int paramcount)> Scr_Notify_Canon{
|
||||
0x0, 0x1402F5FF0
|
||||
};
|
||||
WEAK symbol<unsigned int(scriptInstance_t inst)> Scr_GetNumParam{0x0, 0x140171320};
|
||||
|
||||
WEAK symbol<void(const char* name, const char* key, unsigned int playbackFlags, float volume, void* callbackInfo,
|
||||
int id)> Cinematic_StartPlayback{0x1412BE3A0};
|
||||
WEAK symbol<void(uint64_t id, bool cancelAll)> Cinematic_StopPlayback{0x1412BEA70};
|
||||
|
||||
// Rendering
|
||||
WEAK symbol<void(const char*, int, const void*, float, float, float, float, float, const float*, int)>
|
||||
R_AddCmdDrawText{
|
||||
0x141CD98D0
|
||||
};
|
||||
|
||||
// PCache
|
||||
WEAK symbol<void(ControllerIndex_t controllerIndex)> PCache_DeleteEntries{0x141E8D710};
|
||||
|
||||
// SV
|
||||
WEAK symbol<bool()> SV_Loaded{0x142252250, 0x140535460};
|
||||
WEAK symbol<void*()> SV_AddTestClient{0x142248F40, 0x14052E3E0};
|
||||
WEAK symbol<void (netadr_t from)> SV_DirectConnect{0x142249880, 0x14052EC60};
|
||||
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{
|
||||
0x14224F580, 0x140532CA0
|
||||
};
|
||||
WEAK symbol<void(client_s* cl_0, svscmd_type type, const char* fmt, ...)> SV_SendServerCommand{0x0, 0x140537F10};
|
||||
WEAK symbol<bool(int clientNum)> SV_IsTestClient{0x14224AB60, 0x14052FF40};
|
||||
WEAK symbol<void(int controllerIndex, const char* server, MapPreload preload, bool savegame)> SV_SpawnServer{
|
||||
0x1422528C0, 0x140535B20
|
||||
};
|
||||
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x1420EF130, 0x1404FA6C0};
|
||||
WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x1420EF0E0, 0x1404FA670};
|
||||
|
||||
// FS
|
||||
WEAK symbol<char*(int bytes)> FS_AllocMem{0x1422AC9F0, 0x14056C340};
|
||||
|
||||
// Utils
|
||||
WEAK symbol<const char*(char* str)> I_CleanStr{0x1422E9050, 0x140580E80};
|
||||
|
||||
// Variables
|
||||
WEAK symbol<cmd_function_s> cmd_functions{0x15689DF58, 0x14946F860};
|
||||
WEAK symbol<CmdArgs> sv_cmd_args{0x15689AE30, 0x14944C740};
|
||||
|
||||
WEAK symbol<gentity_s> g_entities{0x0, 0x1471031B0};
|
||||
|
||||
WEAK symbol<int> level_time{0x0, 0x1474FDC94};
|
||||
|
||||
WEAK symbol<SOCKET> ip_socket{0x157E75818, 0x14A640988};
|
||||
|
||||
WEAK symbol<Join> s_join{0x15574A640};
|
||||
|
||||
WEAK symbol<char> s_dvarPool{0x157AC6220, 0x14A3CB620};
|
||||
WEAK symbol<int> g_dvarCount{0x157AC61CC, 0x14A3CB5FC};
|
||||
|
||||
WEAK symbol<int> fs_loadStack{0x157A65310, 0x14A39C650};
|
||||
|
||||
// Client and dedi struct size differs :(
|
||||
WEAK symbol<client_s_cl*> svs_clients_cl{0x1576F9318, 0};
|
||||
WEAK symbol<client_s*> svs_clients{0x0, 0x14A178E98};
|
||||
|
||||
// Dvar variables
|
||||
WEAK symbol<dvar_t*> com_maxclients{0x0, 0x14948EE70};
|
||||
|
||||
namespace s_wcd
|
||||
{
|
||||
WEAK symbol<HWND> codLogo{0x157E75A50, 0x14A640BC0};
|
||||
WEAK symbol<HFONT> hfBufferFont{0x157E75A58, 0x14A640BC8};
|
||||
WEAK symbol<HWND> hWnd{0x157E75A40, 0x14A640BB0};
|
||||
WEAK symbol<HWND> hwndBuffer{0x157E75A48, 0x14A640BB8};
|
||||
WEAK symbol<HWND> hwndInputLine{0x157E75A60, 0x14A640BD0};
|
||||
WEAK symbol<int> windowHeight{0x157E7606C, 0x14A6411DC};
|
||||
WEAK symbol<int> windowWidth{0x157E76068, 0x14A6411D8};
|
||||
WEAK symbol<WNDPROC> SysInputLineWndProc{0x157E76070, 0x14A6411E0};
|
||||
}
|
||||
|
||||
// Global game definitions
|
||||
constexpr auto CMD_MAX_NESTING = 8;
|
||||
|
||||
// Re-implementations
|
||||
eModes Com_SessionMode_GetMode();
|
||||
|
||||
bool I_islower(int c);
|
||||
bool I_isupper(int c);
|
||||
|
||||
unsigned int Scr_CanonHash(const char* str);
|
||||
|
||||
namespace hks
|
||||
{
|
||||
WEAK symbol<lua_State*> lua_state{0x159C76D88, 0x14858C408};
|
||||
WEAK symbol<void(lua_State* s, const char* str, unsigned int l)> hksi_lua_pushlstring{0x140A18430, 0x1401DE6F0};
|
||||
|
||||
WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)>
|
||||
hks_obj_settable{0x141D4B660, 0x1403F41B0};
|
||||
WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)>
|
||||
hks_obj_gettable{0x141D4ABF0, 0x1403F3750};
|
||||
WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{
|
||||
0x141D70FE0, 0x140418E40
|
||||
};
|
||||
WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{
|
||||
0x141D3B5F0, 0x1403E46D0
|
||||
};
|
||||
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues, int internal_,
|
||||
int profilerTreatClosureAsFunc)> cclosure_Create{0x141D3B7E0, 0x1403E48C0};
|
||||
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x141D4D1A0, 0x1403F5CF0};
|
||||
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x141D4D320, 0x1403F5E70};
|
||||
|
||||
WEAK symbol<int(lua_State* s, const HksCompilerSettings* options, const char* buff, unsigned __int64 sz,
|
||||
const char* name)> hksi_hksL_loadbuffer{0x141D4BD80, 0x1403F48D0};
|
||||
WEAK symbol<int(lua_State* s, const char* what, lua_Debug* ar)> hksi_lua_getinfo{0x141D4D8D0, 0x1403F64B0};
|
||||
WEAK symbol<int(lua_State* s, int level, lua_Debug* ar)> hksi_lua_getstack{0x141D4DB90, 0x1403F6770};
|
||||
WEAK symbol<void(lua_State* s, const char* fmt, ...)> hksi_luaL_error{0x141D4D050, 0x1403F5BA0};
|
||||
WEAK symbol<const char*> s_compilerTypeName{0x140A18430};
|
||||
}
|
||||
}
|
||||
WEAK symbol<void(const char* key, int value, hks::lua_State* luaVM)> Lua_SetTableInt{0x141F066E0};
|
||||
|
||||
// Scr
|
||||
WEAK symbol<void(scriptInstance_t inst, int value)> Scr_AddInt{0x1412E9870, 0x14016F160};
|
||||
WEAK symbol<void(scriptInstance_t inst, const char* value)> Scr_AddString{0x0, 0x14016F320};
|
||||
WEAK symbol<const char*(scriptInstance_t inst, unsigned int index)> Scr_GetString{0x0, 0x140171490};
|
||||
WEAK symbol<void(gentity_s* ent, ScrVarCanonicalName_t stringValue, unsigned int paramcount)> Scr_Notify_Canon{
|
||||
0x0, 0x1402F5FF0
|
||||
};
|
||||
WEAK symbol<unsigned int(scriptInstance_t inst)> Scr_GetNumParam{0x0, 0x140171320};
|
||||
|
||||
WEAK symbol<void(const char* name, const char* key, unsigned int playbackFlags, float volume, void* callbackInfo,
|
||||
int id)> Cinematic_StartPlayback{0x1412BE3A0};
|
||||
WEAK symbol<void(uint64_t id, bool cancelAll)> Cinematic_StopPlayback{0x1412BEA70};
|
||||
|
||||
// Rendering
|
||||
WEAK symbol<void(const char*, int, const void*, float, float, float, float, float, const float*, int)>
|
||||
R_AddCmdDrawText{
|
||||
0x141CD98D0
|
||||
};
|
||||
|
||||
// PCache
|
||||
WEAK symbol<void(ControllerIndex_t controllerIndex)> PCache_DeleteEntries{0x141E8D710};
|
||||
|
||||
// SV
|
||||
WEAK symbol<bool()> SV_Loaded{0x142252250, 0x140535460};
|
||||
WEAK symbol<void*()> SV_AddTestClient{0x142248F40, 0x14052E3E0};
|
||||
WEAK symbol<void (netadr_t from)> SV_DirectConnect{0x142249880, 0x14052EC60};
|
||||
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{
|
||||
0x14224F580, 0x140532CA0
|
||||
};
|
||||
WEAK symbol<void(client_s* cl_0, svscmd_type type, const char* fmt, ...)> SV_SendServerCommand{0x0, 0x140537F10};
|
||||
WEAK symbol<bool(int clientNum)> SV_IsTestClient{0x14224AB60, 0x14052FF40};
|
||||
WEAK symbol<void(int controllerIndex, const char* server, MapPreload preload, bool savegame)> SV_SpawnServer{
|
||||
0x1422528C0, 0x140535B20
|
||||
};
|
||||
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x1420EF130, 0x1404FA6C0};
|
||||
WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x1420EF0E0, 0x1404FA670};
|
||||
|
||||
// FS
|
||||
WEAK symbol<char*(int bytes)> FS_AllocMem{0x1422AC9F0, 0x14056C340};
|
||||
|
||||
// Utils
|
||||
WEAK symbol<const char*(char* str)> I_CleanStr{0x1422E9050, 0x140580E80};
|
||||
|
||||
// Variables
|
||||
WEAK symbol<cmd_function_s> cmd_functions{0x15689DF58, 0x14946F860};
|
||||
WEAK symbol<CmdArgs> sv_cmd_args{0x15689AE30, 0x14944C740};
|
||||
|
||||
WEAK symbol<gentity_s> g_entities{0x0, 0x1471031B0};
|
||||
|
||||
WEAK symbol<int> level_time{0x0, 0x1474FDC94};
|
||||
|
||||
WEAK symbol<SOCKET> ip_socket{0x157E75818, 0x14A640988};
|
||||
|
||||
WEAK symbol<Join> s_join{0x15574A640};
|
||||
|
||||
WEAK symbol<char> s_dvarPool{0x157AC6220, 0x14A3CB620};
|
||||
WEAK symbol<int> g_dvarCount{0x157AC61CC, 0x14A3CB5FC};
|
||||
|
||||
WEAK symbol<int> fs_loadStack{0x157A65310, 0x14A39C650};
|
||||
|
||||
// Client and dedi struct size differs :(
|
||||
WEAK symbol<client_s_cl*> svs_clients_cl{0x1576F9318, 0};
|
||||
WEAK symbol<client_s*> svs_clients{0x0, 0x14A178E98};
|
||||
|
||||
// Dvar variables
|
||||
WEAK symbol<dvar_t*> com_maxclients{0x0, 0x14948EE70};
|
||||
|
||||
namespace s_wcd
|
||||
{
|
||||
WEAK symbol<HWND> codLogo{0x157E75A50, 0x14A640BC0};
|
||||
WEAK symbol<HFONT> hfBufferFont{0x157E75A58, 0x14A640BC8};
|
||||
WEAK symbol<HWND> hWnd{0x157E75A40, 0x14A640BB0};
|
||||
WEAK symbol<HWND> hwndBuffer{0x157E75A48, 0x14A640BB8};
|
||||
WEAK symbol<HWND> hwndInputLine{0x157E75A60, 0x14A640BD0};
|
||||
WEAK symbol<int> windowHeight{0x157E7606C, 0x14A6411DC};
|
||||
WEAK symbol<int> windowWidth{0x157E76068, 0x14A6411D8};
|
||||
WEAK symbol<WNDPROC> SysInputLineWndProc{0x157E76070, 0x14A6411E0};
|
||||
}
|
||||
|
||||
// Global game definitions
|
||||
constexpr auto CMD_MAX_NESTING = 8;
|
||||
|
||||
// Re-implementations
|
||||
eModes Com_SessionMode_GetMode();
|
||||
|
||||
bool I_islower(int c);
|
||||
bool I_isupper(int c);
|
||||
|
||||
unsigned int Scr_CanonHash(const char* str);
|
||||
|
||||
namespace hks
|
||||
{
|
||||
WEAK symbol<lua_State*> lua_state{0x159C76D88, 0x14858C408};
|
||||
WEAK symbol<void(lua_State* s, const char* str, unsigned int l)> hksi_lua_pushlstring{0x140A18430, 0x1401DE6F0};
|
||||
|
||||
WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)>
|
||||
hks_obj_settable{0x141D4B660, 0x1403F41B0};
|
||||
WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)>
|
||||
hks_obj_gettable{0x141D4ABF0, 0x1403F3750};
|
||||
WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{
|
||||
0x141D70FE0, 0x140418E40
|
||||
};
|
||||
WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{
|
||||
0x141D3B5F0, 0x1403E46D0
|
||||
};
|
||||
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues, int internal_,
|
||||
int profilerTreatClosureAsFunc)> cclosure_Create{0x141D3B7E0, 0x1403E48C0};
|
||||
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x141D4D1A0, 0x1403F5CF0};
|
||||
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x141D4D320, 0x1403F5E70};
|
||||
|
||||
WEAK symbol<int(lua_State* s, const HksCompilerSettings* options, const char* buff, unsigned __int64 sz,
|
||||
const char* name)> hksi_hksL_loadbuffer{0x141D4BD80, 0x1403F48D0};
|
||||
WEAK symbol<int(lua_State* s, const char* what, lua_Debug* ar)> hksi_lua_getinfo{0x141D4D8D0, 0x1403F64B0};
|
||||
WEAK symbol<int(lua_State* s, int level, lua_Debug* ar)> hksi_lua_getstack{0x141D4DB90, 0x1403F6770};
|
||||
WEAK symbol<void(lua_State* s, const char* fmt, ...)> hksi_luaL_error{0x141D4D050, 0x1403F5BA0};
|
||||
WEAK symbol<const char*> s_compilerTypeName{0x140A18430};
|
||||
}
|
||||
}
|
||||
|
@ -176,6 +176,30 @@ namespace game
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static bool access_client(T* client_states, const size_t index, const std::function<void(client_s&)>& callback)
|
||||
{
|
||||
if (!client_states || !callback)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index >= get_max_client_count())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& client = client_states[index];
|
||||
if (client.client_state <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
callback(client);
|
||||
return true;
|
||||
}
|
||||
|
||||
void foreach_client(const std::function<void(client_s&, size_t index)>& callback)
|
||||
{
|
||||
if (is_server())
|
||||
@ -214,4 +238,14 @@ namespace game
|
||||
callback(client);
|
||||
});
|
||||
}
|
||||
|
||||
bool access_connected_client(const size_t index, const std::function<void(client_s&)>& callback)
|
||||
{
|
||||
if (is_server())
|
||||
{
|
||||
return access_client(*svs_clients, index, callback);
|
||||
}
|
||||
|
||||
return access_client(*svs_clients_cl, index, callback);
|
||||
}
|
||||
}
|
||||
|
@ -24,4 +24,6 @@ namespace game
|
||||
|
||||
void foreach_connected_client(const std::function<void(client_s&, size_t index)>& callback);
|
||||
void foreach_connected_client(const std::function<void(client_s&)>& callback);
|
||||
|
||||
bool access_connected_client(size_t index, const std::function<void(client_s&)>& callback);
|
||||
}
|
||||
|
@ -65,6 +65,7 @@
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
@ -55,12 +55,14 @@ namespace steam
|
||||
const auto mode = game::eModes(std::atoi(playmode.data()));
|
||||
|
||||
const auto* tags = ::utils::string::va(
|
||||
R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\%s\zombies\%s\modName\\playerCount\%d\bots\%d\)",
|
||||
R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\%s\zombies\%s\playerCount\%d\bots\%d\modName\%s\)",
|
||||
info.get("gametype").data(),
|
||||
info.get("dedicated") == "1" ? "true" : "false",
|
||||
info.get("hc") == "1" ? "true" : "false",
|
||||
mode == game::MODE_ZOMBIES ? "true" : "false",
|
||||
server.m_nPlayers, atoi(info.get("bots").data()));
|
||||
server.m_nPlayers,
|
||||
atoi(info.get("bots").data()),
|
||||
info.get("modname").data());
|
||||
|
||||
::utils::string::copy(server.m_szGameTags, tags);
|
||||
server.m_steamID.bits = strtoull(info.get("xuid").data(), nullptr, 16);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "file_updater.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/flags.hpp>
|
||||
#include <utils/http.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/compression.hpp>
|
||||
@ -199,7 +200,11 @@ namespace updater
|
||||
throw;
|
||||
}
|
||||
|
||||
utils::nt::relaunch_self();
|
||||
if (!utils::flags::has_flag("norelaunch"))
|
||||
{
|
||||
utils::nt::relaunch_self();
|
||||
}
|
||||
|
||||
throw update_cancelled();
|
||||
}
|
||||
|
||||
@ -271,7 +276,7 @@ namespace updater
|
||||
bool file_updater::is_outdated_file(const file_info& file) const
|
||||
{
|
||||
#if !defined(NDEBUG) || !defined(CI)
|
||||
if (file.name == UPDATE_HOST_BINARY)
|
||||
if (file.name == UPDATE_HOST_BINARY && !utils::flags::has_flag("update"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -41,9 +41,9 @@ namespace utils
|
||||
this->offset_ += length;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> byte_buffer::read_data(const size_t length)
|
||||
std::string byte_buffer::read_data(const size_t length)
|
||||
{
|
||||
std::vector<uint8_t> result{};
|
||||
std::string result{};
|
||||
result.resize(length);
|
||||
|
||||
this->read(result.data(), result.size());
|
||||
|
@ -20,6 +20,11 @@ namespace utils
|
||||
|
||||
void write(const void* buffer, size_t length);
|
||||
|
||||
void write(const char* text)
|
||||
{
|
||||
this->write(text, strlen(text));
|
||||
}
|
||||
|
||||
void write_string(const char* str, const size_t length)
|
||||
{
|
||||
this->write<uint32_t>(static_cast<uint32_t>(length));
|
||||
@ -42,6 +47,13 @@ namespace utils
|
||||
this->write(&object, sizeof(object));
|
||||
}
|
||||
|
||||
template<>
|
||||
void write<byte_buffer>(const byte_buffer& object)
|
||||
{
|
||||
const auto& buffer = object.get_buffer();
|
||||
this->write(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write(const std::vector<T>& vec)
|
||||
{
|
||||
@ -109,7 +121,17 @@ namespace utils
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read_data(size_t length);
|
||||
size_t get_remaining_size() const
|
||||
{
|
||||
return this->buffer_.size() - offset_;
|
||||
}
|
||||
|
||||
std::string get_remaining_data()
|
||||
{
|
||||
return this->read_data(this->get_remaining_size());
|
||||
}
|
||||
|
||||
std::string read_data(size_t length);
|
||||
|
||||
private:
|
||||
bool writing_{false};
|
||||
|
@ -194,18 +194,19 @@ namespace utils::io
|
||||
|
||||
std::vector<std::filesystem::path> list_files(const std::filesystem::path& directory, const bool recursive)
|
||||
{
|
||||
std::error_code code{};
|
||||
std::vector<std::filesystem::path> files;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
for (auto& file : std::filesystem::recursive_directory_iterator(directory))
|
||||
for (auto& file : std::filesystem::recursive_directory_iterator(directory, code))
|
||||
{
|
||||
files.push_back(file.path());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& file : std::filesystem::directory_iterator(directory))
|
||||
for (auto& file : std::filesystem::directory_iterator(directory, code))
|
||||
{
|
||||
files.push_back(file.path());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user