Merge remote-tracking branch 'upstream/main' into mods
This commit is contained in:
commit
2c27b4fd6e
Binary file not shown.
@ -3,11 +3,9 @@
|
|||||||
#using scripts\shared\callbacks_shared;
|
#using scripts\shared\callbacks_shared;
|
||||||
#using scripts\shared\system_shared;
|
#using scripts\shared\system_shared;
|
||||||
|
|
||||||
#insert scripts\shared\shared.gsh;
|
|
||||||
|
|
||||||
#namespace serversettings;
|
#namespace serversettings;
|
||||||
|
|
||||||
REGISTER_SYSTEM( "serversettings", &__init__, undefined )
|
function autoexec __init__sytem__() { system::register("serversettings",&__init__,undefined,undefined); }
|
||||||
|
|
||||||
function __init__()
|
function __init__()
|
||||||
{
|
{
|
||||||
@ -21,26 +19,29 @@ function init()
|
|||||||
level.hostname = "CoDHost";
|
level.hostname = "CoDHost";
|
||||||
SetDvar("sv_hostname", level.hostname);
|
SetDvar("sv_hostname", level.hostname);
|
||||||
SetDvar("ui_hostname", level.hostname);
|
SetDvar("ui_hostname", level.hostname);
|
||||||
|
//makeDvarServerInfo("ui_hostname", "CoDHost");
|
||||||
|
|
||||||
level.motd = GetDvarString( "scr_motd" );
|
level.motd = GetDvarString( "scr_motd" );
|
||||||
if(level.motd == "")
|
if(level.motd == "")
|
||||||
level.motd = "";
|
level.motd = "";
|
||||||
SetDvar("scr_motd", level.motd);
|
SetDvar("scr_motd", level.motd);
|
||||||
SetDvar("ui_motd", level.motd);
|
SetDvar("ui_motd", level.motd);
|
||||||
|
//makeDvarServerInfo("ui_motd", "");
|
||||||
|
|
||||||
level.allowvote = GetDvarString( "g_allowvote");
|
level.allowvote = GetDvarString( "g_allowvote" );
|
||||||
if(level.allowvote == "")
|
if(level.allowvote == "")
|
||||||
level.allowvote = "1";
|
level.allowvote = "1";
|
||||||
SetDvar("g_allowvote", level.allowvote);
|
SetDvar("g_allowvote", level.allowvote);
|
||||||
SetDvar("ui_allowvote", level.allowvote);
|
SetDvar("ui_allowvote", level.allowvote);
|
||||||
|
//makeDvarServerInfo("ui_allowvote", "1");
|
||||||
|
|
||||||
level.allow_teamchange = "1";
|
level.allow_teamchange = "1";
|
||||||
SetDvar("ui_allow_teamchange", level.allow_teamchange);
|
SetDvar("ui_allow_teamchange", level.allow_teamchange);
|
||||||
|
|
||||||
|
|
||||||
level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
|
level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
|
||||||
|
|
||||||
SetDvar("ui_friendlyfire", level.friendlyfire);
|
SetDvar("ui_friendlyfire", level.friendlyfire);
|
||||||
|
//makeDvarServerInfo("ui_friendlyfire", "0");
|
||||||
|
|
||||||
if(GetDvarString( "scr_mapsize") == "")
|
if(GetDvarString( "scr_mapsize") == "")
|
||||||
SetDvar("scr_mapsize", "64");
|
SetDvar("scr_mapsize", "64");
|
||||||
@ -57,6 +58,8 @@ function init()
|
|||||||
constrain_gametype(GetDvarString( "g_gametype"));
|
constrain_gametype(GetDvarString( "g_gametype"));
|
||||||
constrain_map_size(level.mapsize);
|
constrain_map_size(level.mapsize);
|
||||||
|
|
||||||
|
thread setup_callbacks();
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
@ -80,7 +83,7 @@ function update()
|
|||||||
SetDvar("ui_motd", level.motd);
|
SetDvar("ui_motd", level.motd);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_allowvote = GetDvarString( "g_allowvote");
|
g_allowvote = GetDvarString( "g_allowvote" );
|
||||||
if(level.allowvote != g_allowvote)
|
if(level.allowvote != g_allowvote)
|
||||||
{
|
{
|
||||||
level.allowvote = g_allowvote;
|
level.allowvote = g_allowvote;
|
||||||
@ -194,3 +197,13 @@ function constrain_map_size(mapsize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setup_callbacks()
|
||||||
|
{
|
||||||
|
level.onForfeit = &default_onForfeit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function default_onForfeit()
|
||||||
|
{
|
||||||
|
level.gameForfeited = false;
|
||||||
|
}
|
@ -20,7 +20,7 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
|||||||
|
|
||||||
table.insert(optionsTable,
|
table.insert(optionsTable,
|
||||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Loot",
|
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", {
|
"cg_unlockall_loot", {
|
||||||
{
|
{
|
||||||
option = "MENU_DISABLED",
|
option = "MENU_DISABLED",
|
||||||
@ -47,6 +47,20 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
|||||||
value = 1
|
value = 1
|
||||||
},
|
},
|
||||||
}, nil, updateDvar))
|
}, 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
|
end
|
||||||
table.insert(optionsTable,
|
table.insert(optionsTable,
|
||||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
|
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
|
||||||
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit dc18b40b406e9946a2198d66b6edb62575660faf
|
Subproject commit 1c5ed24ee0e929a6f410fcc3729becfd2ee71211
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
|||||||
Subproject commit eb0e038b297f2c9877ed8b3515c6718a4b65d485
|
Subproject commit 66588683b36042154ad35140bf9fcbb60c5d573c
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "auth.hpp"
|
#include "auth.hpp"
|
||||||
|
#include "party.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
@ -24,6 +25,8 @@ namespace auth
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
std::array<uint64_t, 18> client_xuids{};
|
||||||
|
|
||||||
std::string get_hdd_serial()
|
std::string get_hdd_serial()
|
||||||
{
|
{
|
||||||
DWORD serial{};
|
DWORD serial{};
|
||||||
@ -107,8 +110,6 @@ namespace auth
|
|||||||
|
|
||||||
buffer.write_string(data, static_cast<size_t>(length));
|
buffer.write_string(data, static_cast<size_t>(length));
|
||||||
|
|
||||||
printf("Serialized with size: %llX\n", buffer.get_buffer().size());
|
|
||||||
|
|
||||||
return buffer.move_buffer();
|
return buffer.move_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +154,59 @@ namespace auth
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void distribute_player_xuid(const game::netadr_t& target, const size_t player_index, const uint64_t xuid)
|
||||||
|
{
|
||||||
|
if (player_index >= 18)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::byte_buffer buffer{};
|
||||||
|
buffer.write(static_cast<uint32_t>(player_index));
|
||||||
|
buffer.write(xuid);
|
||||||
|
|
||||||
|
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)
|
void dispatch_connect_packet(const game::netadr_t& target, const std::string& data)
|
||||||
{
|
{
|
||||||
utils::byte_buffer buffer(data);
|
utils::byte_buffer buffer(data);
|
||||||
@ -174,14 +228,7 @@ namespace auth
|
|||||||
profile_infos::add_and_distribute_profile_info(target, xuid, info);
|
profile_infos::add_and_distribute_profile_info(target, xuid, info);
|
||||||
|
|
||||||
game::SV_DirectConnect(target);
|
game::SV_DirectConnect(target);
|
||||||
|
handle_new_player(target);
|
||||||
game::foreach_connected_client([&](game::client_s& client)
|
|
||||||
{
|
|
||||||
if (client.address == target)
|
|
||||||
{
|
|
||||||
client.xuid = xuid;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_connect_packet_fragment(const game::netadr_t& target, const network::data_view& data)
|
void handle_connect_packet_fragment(const game::netadr_t& target, const network::data_view& data)
|
||||||
@ -196,9 +243,36 @@ namespace auth
|
|||||||
std::string final_packet{};
|
std::string final_packet{};
|
||||||
if (game::fragment_handler::handle(target, buffer, final_packet))
|
if (game::fragment_handler::handle(target, buffer, final_packet))
|
||||||
{
|
{
|
||||||
dispatch_connect_packet(target, final_packet);
|
scheduler::once([t = target, p = std::move(final_packet)]
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t get_guid()
|
uint64_t get_guid()
|
||||||
@ -216,6 +290,40 @@ namespace auth
|
|||||||
return guid;
|
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
|
struct component final : generic_component
|
||||||
{
|
{
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
@ -223,6 +331,10 @@ namespace auth
|
|||||||
// Skip connect handler
|
// Skip connect handler
|
||||||
utils::hook::set<uint8_t>(game::select(0x142253EFA, 0x14053714A), 0xEB);
|
utils::hook::set<uint8_t>(game::select(0x142253EFA, 0x14053714A), 0xEB);
|
||||||
network::on("connect", handle_connect_packet_fragment);
|
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
|
// Patch steam id bit check
|
||||||
std::vector<std::pair<size_t, size_t>> patches{};
|
std::vector<std::pair<size_t, size_t>> patches{};
|
||||||
|
@ -3,4 +3,6 @@
|
|||||||
namespace auth
|
namespace auth
|
||||||
{
|
{
|
||||||
uint64_t get_guid();
|
uint64_t get_guid();
|
||||||
|
uint64_t get_guid(size_t client_num);
|
||||||
|
void clear_stored_guids();
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,9 @@ namespace client_patches
|
|||||||
{
|
{
|
||||||
fix_amd_cpu_stuttering();
|
fix_amd_cpu_stuttering();
|
||||||
|
|
||||||
|
// Don't modify process priority
|
||||||
|
utils::hook::nop(0x142334C98_g, 6);
|
||||||
|
|
||||||
// Kill microphones for now
|
// Kill microphones for now
|
||||||
utils::hook::set(0x15AAE9254_g, mixer_open_stub);
|
utils::hook::set(0x15AAE9254_g, mixer_open_stub);
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "auth.hpp"
|
||||||
|
|
||||||
|
#include "steam/steam.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
@ -10,8 +14,25 @@ namespace colors
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::hook::detour get_player_name_hook;
|
utils::hook::detour cl_get_client_name_hook;
|
||||||
utils::hook::detour get_gamer_tag_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>
|
template <size_t index>
|
||||||
void patch_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a = 255)
|
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));
|
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,
|
bool cl_get_client_name_stub(const int local_client_num, const int index, char* buf, const int size,
|
||||||
const bool has_clan_tag)
|
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);
|
return res;
|
||||||
strncpy_s(buffer, size, val, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
const auto color = get_color_for_client(index);
|
||||||
}*/
|
if (!color)
|
||||||
|
|
||||||
/*const char* get_gamer_tag_stub(const uint64_t num)
|
|
||||||
{
|
{
|
||||||
return utils::string::va("^3%s", get_gamer_tag_hook.invoke<const char*>(num));
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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
|
patch_color<6>(151, 80, 221); // 6 - Pink
|
||||||
|
|
||||||
// Old addresses
|
// Old addresses
|
||||||
//get_player_name_hook.create(0x1413E3140_g, get_player_name_stub);
|
cl_get_client_name_hook.create(game::CL_GetClientName, cl_get_client_name_stub);
|
||||||
//get_gamer_tag_hook.create(0x141EC7370_g, get_gamer_tag_stub);
|
//utils::hook::jump(0x141EC72E0_g, get_gamer_tag_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace loot
|
|||||||
const game::dvar_t* dvar_cg_unlockall_camos_and_reticles;
|
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_calling_cards;
|
||||||
const game::dvar_t* dvar_cg_unlockall_specialists_outfits;
|
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 loot_getitemquantity_hook;
|
||||||
utils::hook::detour liveinventory_getitemquantity_hook;
|
utils::hook::detour liveinventory_getitemquantity_hook;
|
||||||
@ -30,6 +31,7 @@ namespace loot
|
|||||||
utils::hook::detour bg_unlockablescharactercustomizationitemlocked_hook;
|
utils::hook::detour bg_unlockablescharactercustomizationitemlocked_hook;
|
||||||
utils::hook::detour bg_emblemisentitlementbackgroundgranted_hook;
|
utils::hook::detour bg_emblemisentitlementbackgroundgranted_hook;
|
||||||
utils::hook::detour liveentitlements_isentitlementactiveforcontroller_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)
|
int loot_getitemquantity_stub(const game::ControllerIndex_t controller_index, const game::eModes mode, const int item_id)
|
||||||
{
|
{
|
||||||
@ -48,19 +50,25 @@ namespace loot
|
|||||||
|
|
||||||
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
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 ||
|
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))
|
item_id >= 90047 && item_id <= 90064))
|
||||||
{
|
{
|
||||||
return 1;
|
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);
|
return liveinventory_getitemquantity_hook.invoke<int>(controller_index, item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool liveinventory_areextraslotspurchased_stub(const game::ControllerIndex_t controller_index)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,9 +168,19 @@ namespace loot
|
|||||||
|
|
||||||
return liveentitlements_isentitlementactiveforcontroller_hook.invoke<bool>(controllerIndex, incentiveId);
|
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
|
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_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_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_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);
|
loot_getitemquantity_hook.create(0x141E82C00_g, loot_getitemquantity_stub);
|
||||||
liveinventory_getitemquantity_hook.create(0x141E09030_g, liveinventory_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_unlockablescharactercustomizationitemlocked_hook.create(0x1426A2030_g, bg_unlockablescharactercustomizationitemlocked_stub);
|
||||||
bg_emblemisentitlementbackgroundgranted_hook.create(0x142667520_g, bg_emblemisentitlementbackgroundgranted_stub);
|
bg_emblemisentitlementbackgroundgranted_hook.create(0x142667520_g, bg_emblemisentitlementbackgroundgranted_stub);
|
||||||
liveentitlements_isentitlementactiveforcontroller_hook.create(0x141E124E0_g, liveentitlements_isentitlementactiveforcontroller_stub);
|
liveentitlements_isentitlementactiveforcontroller_hook.create(0x141E124E0_g, liveentitlements_isentitlementactiveforcontroller_stub);
|
||||||
|
bg_unlockablesgetcustomclasscount_hook.create(0x1426A5900_g, bg_unlockablesgetcustomclasscount_stub);
|
||||||
|
|
||||||
scheduler::once([]() {
|
scheduler::once([]() {
|
||||||
if (dvar_cg_unlockall_loot->current.value.enabled)
|
if (dvar_cg_unlockall_loot->current.value.enabled)
|
||||||
|
@ -163,7 +163,6 @@ namespace network
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t ret2()
|
uint64_t ret2()
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
@ -173,6 +172,15 @@ namespace network
|
|||||||
{
|
{
|
||||||
return 0;
|
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)
|
void on(const std::string& command, const callback& callback)
|
||||||
@ -321,10 +329,21 @@ namespace network
|
|||||||
// NA_IP -> NA_RAWIP in NetAdr_ToString
|
// NA_IP -> NA_RAWIP in NetAdr_ToString
|
||||||
utils::hook::set<uint8_t>(game::select(0x142172ED4, 0x140515864), game::NA_RAWIP);
|
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())
|
if (game::is_server())
|
||||||
{
|
{
|
||||||
// Remove restrictions for rcon commands
|
// 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
|
// TODO: Fix that
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include "party.hpp"
|
#include "party.hpp"
|
||||||
|
#include "auth.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
#include "workshop.hpp"
|
#include "workshop.hpp"
|
||||||
@ -39,6 +40,8 @@ namespace party
|
|||||||
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
||||||
const std::string& usermap_id, const std::string& mod_id)
|
const std::string& usermap_id, const std::string& mod_id)
|
||||||
{
|
{
|
||||||
|
auth::clear_stored_guids();
|
||||||
|
|
||||||
workshop::load_mod_if_needed(usermap_id, mod_id);
|
workshop::load_mod_if_needed(usermap_id, mod_id);
|
||||||
|
|
||||||
game::XSESSION_INFO info{};
|
game::XSESSION_INFO info{};
|
||||||
@ -56,7 +59,8 @@ namespace party
|
|||||||
}
|
}
|
||||||
|
|
||||||
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
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& usermap_id, const std::string& mod_id,
|
const std::string& gametype, const std::string& usermap_id,
|
||||||
|
const std::string& mod_id,
|
||||||
const bool was_retried = false)
|
const bool was_retried = false)
|
||||||
{
|
{
|
||||||
if (game::Com_SessionMode_IsMode(mode))
|
if (game::Com_SessionMode_IsMode(mode))
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <utils/info_string.hpp>
|
#include <utils/info_string.hpp>
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
namespace party
|
namespace party
|
||||||
{
|
{
|
||||||
using query_callback_func = void(bool success, const game::netadr_t& host, const ::utils::info_string& info, uint32_t ping);
|
using query_callback_func = void(bool success, const game::netadr_t& host, const ::utils::info_string& info, uint32_t ping);
|
||||||
|
@ -2,12 +2,31 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include <game/game.hpp>
|
#include <game/game.hpp>
|
||||||
|
#include <game/utils.hpp>
|
||||||
|
|
||||||
|
#include "network.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
namespace patches
|
namespace patches
|
||||||
{
|
{
|
||||||
namespace
|
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->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, ...)
|
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
char buffer[0x1000];
|
char buffer[0x1000];
|
||||||
@ -34,6 +53,14 @@ namespace patches
|
|||||||
utils::hook::set<uint8_t>(game::select(0x14224DA53, 0x140531143), 3);
|
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(0x14224DBB4, 0x1405312A8), 3);
|
||||||
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,6 @@ namespace scheduler
|
|||||||
task_pipeline pipelines[pipeline::count];
|
task_pipeline pipelines[pipeline::count];
|
||||||
|
|
||||||
utils::hook::detour r_end_frame_hook;
|
utils::hook::detour r_end_frame_hook;
|
||||||
utils::hook::detour g_run_frame_hook;
|
|
||||||
utils::hook::detour main_frame_hook;
|
utils::hook::detour main_frame_hook;
|
||||||
|
|
||||||
|
|
||||||
@ -98,9 +97,9 @@ namespace scheduler
|
|||||||
r_end_frame_hook.invoke<void>();
|
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);
|
execute(pipeline::server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,12 +167,14 @@ namespace scheduler
|
|||||||
{
|
{
|
||||||
if (!game::is_server())
|
if (!game::is_server())
|
||||||
{
|
{
|
||||||
r_end_frame_hook.create(0x142272B00_g, r_end_frame_stub);
|
|
||||||
// some func called before R_EndFrame, maybe SND_EndFrame?
|
// 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
|
// 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
|
void pre_destroy() override
|
||||||
|
@ -1583,15 +1583,23 @@ namespace game
|
|||||||
int client_state;
|
int client_state;
|
||||||
char __pad0[0x28];
|
char __pad0[0x28];
|
||||||
netadr_t address;
|
netadr_t address;
|
||||||
char __pad1[0x5588];
|
char __pad1[20468];
|
||||||
|
int reliableSequence;
|
||||||
|
int reliableAcknowledge;
|
||||||
|
char __pad2[4];
|
||||||
|
int messageAcknowledge;
|
||||||
|
char gap_5040[1416];
|
||||||
uint64_t xuid;
|
uint64_t xuid;
|
||||||
char __pad2[0xB5D84];
|
char __pad3[0xB5D84];
|
||||||
int guid;
|
int guid;
|
||||||
char __pad3[0x8];
|
char __pad4[0x8];
|
||||||
bool bIsTestClient;
|
bool bIsTestClient;
|
||||||
char __pad4[0x29DAC];
|
char __pad5[3];
|
||||||
|
int serverId;
|
||||||
|
char __pad6[171432];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
static_assert(sizeof(client_s) == 0xE5110);
|
static_assert(sizeof(client_s) == 0xE5110);
|
||||||
|
|
||||||
|
@ -75,6 +75,11 @@ namespace game
|
|||||||
WEAK symbol<bool(const char* zoneName, int source)> DB_FileExists{0x141420B40};
|
WEAK symbol<bool(const char* zoneName, int source)> DB_FileExists{0x141420B40};
|
||||||
WEAK symbol<void()> DB_ReleaseXAssets{0x1414247C0};
|
WEAK symbol<void()> DB_ReleaseXAssets{0x1414247C0};
|
||||||
|
|
||||||
|
// G
|
||||||
|
WEAK symbol<void()> G_ClearVehicleInputs{0x1423812E0, 0x1405C1200};
|
||||||
|
|
||||||
|
WEAK symbol<qboolean(void* ent)> StuckInClient{0x1415A8360, 0x14023BFE0};
|
||||||
|
|
||||||
// Live
|
// Live
|
||||||
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
||||||
|
|
||||||
|
@ -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)
|
void foreach_client(const std::function<void(client_s&, size_t index)>& callback)
|
||||||
{
|
{
|
||||||
if (is_server())
|
if (is_server())
|
||||||
@ -214,4 +238,14 @@ namespace game
|
|||||||
callback(client);
|
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&, size_t index)>& callback);
|
||||||
void foreach_connected_client(const std::function<void(client_s&)>& 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
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -200,7 +200,11 @@ namespace updater
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!utils::flags::has_flag("norelaunch"))
|
||||||
|
{
|
||||||
utils::nt::relaunch_self();
|
utils::nt::relaunch_self();
|
||||||
|
}
|
||||||
|
|
||||||
throw update_cancelled();
|
throw update_cancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,18 +194,19 @@ namespace utils::io
|
|||||||
|
|
||||||
std::vector<std::filesystem::path> list_files(const std::filesystem::path& directory, const bool recursive)
|
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;
|
std::vector<std::filesystem::path> files;
|
||||||
|
|
||||||
if (recursive)
|
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());
|
files.push_back(file.path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (auto& file : std::filesystem::directory_iterator(directory))
|
for (auto& file : std::filesystem::directory_iterator(directory, code))
|
||||||
{
|
{
|
||||||
files.push_back(file.path());
|
files.push_back(file.path());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user