Prepare networking

This commit is contained in:
Joelrau 2021-01-05 19:07:19 +02:00
parent 2247b68b4a
commit 832b6ac581
17 changed files with 608 additions and 69 deletions

View File

@ -3,6 +3,7 @@
#include "auth.hpp"
#include "command.hpp"
#include "network.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
@ -31,6 +32,107 @@ namespace auth
static auto key = utils::cryptography::ecc::generate_key(512, get_key_entropy());
return key;
}
int send_connect_data_stub(game::netsrc_t sock, game::netadr_s* adr, const char* format, const int len)
{
std::string connect_string(format, len);
game::SV_Cmd_TokenizeString(connect_string.data());
const auto _ = gsl::finally([]()
{
game::SV_Cmd_EndTokenizedString();
});
const command::params_sv params;
if (params.size() < 3)
{
return false;
}
const utils::info_string info_string{ std::string{params[2]} };
const auto challenge = info_string.get("challenge");
connect_string.clear();
connect_string.append(params[0]);
connect_string.append(" ");
connect_string.append(params[1]);
connect_string.append(" ");
connect_string.append("\"" + info_string.build() + "\"");
proto::network::connect_info info;
info.set_publickey(get_key().get_public_key());
info.set_signature(sign_message(get_key(), challenge));
info.set_infostring(connect_string);
network::send(*adr, "connect", info.SerializeAsString());
return true;
}
void direct_connect(game::netadr_s* from, game::msg_t* msg)
{
const auto offset = sizeof("connect") + 4;
proto::network::connect_info info;
if (!info.ParseFromArray(msg->data + offset, msg->cursize - offset))
{
network::send(*from, "error", "Invalid connect data!", '\n');
return;
}
game::SV_Cmd_EndTokenizedString();
game::SV_Cmd_TokenizeString(info.infostring().data());
const command::params_sv params;
if (params.size() < 3)
{
network::send(*from, "error", "Invalid connect string!", '\n');
return;
}
const utils::info_string info_string{ std::string{params[2]} };
const auto steam_id = info_string.get("xuid");
const auto challenge = info_string.get("challenge");
if (steam_id.empty() || challenge.empty())
{
network::send(*from, "error", "Invalid connect data!", '\n');
return;
}
utils::cryptography::ecc::key key;
key.set(info.publickey());
const auto xuid = strtoull(steam_id.data(), nullptr, 16);
if (xuid != key.get_hash())
{
network::send(*from, "error", "XUID doesn't match the certificate!", '\n');
return;
}
if (!key.is_valid() || !verify_message(key, challenge, info.signature()))
{
network::send(*from, "error", "Challenge signature was invalid!", '\n');
return;
}
game::SV_DirectConnect(from);
}
void* get_direct_connect_stub()
{
return utils::hook::assemble([](utils::hook::assembler& a)
{
a.lea(rcx, qword_ptr(rsp, 0x20));
a.movaps(xmmword_ptr(rsp, 0x20), xmm0);
a.pushad64();
a.mov(rdx, rsi);
a.call_aligned(direct_connect);
a.popad64();
a.mov(eax, 0x140442317);
a.jmp(eax);
});
}
}
uint64_t get_guid()
@ -62,6 +164,9 @@ namespace auth
utils::hook::jump(0x140009AEB, 0x140009B48);
utils::hook::jump(0x14053995F, 0x1405399A0);
utils::hook::jump(0x140539E70, 0x140539EB6);
//utils::hook::jump(0x1404421F6, get_direct_connect_stub(), true);
//utils::hook::call(0x140208C54, send_connect_data_stub);
}
}
};

View File

@ -29,17 +29,17 @@ namespace command
}
}
void client_command(const int clientNum, void* a2)
void client_command(const int client_num, void* a2)
{
params_sv params = {};
const auto command = utils::string::to_lower(params[0]);
if (handlers_sv.find(command) != handlers_sv.end())
{
handlers_sv[command](clientNum, params);
handlers_sv[command](client_num, params);
}
client_command_hook.invoke<void>(clientNum, a2);
client_command_hook.invoke<void>(client_num, a2);
}
// Shamelessly stolen from Quake3
@ -53,7 +53,7 @@ namespace command
}
static std::string comand_line_buffer = GetCommandLineA();
char* command_line = comand_line_buffer.data();
auto* command_line = comand_line_buffer.data();
auto& com_num_console_lines = *reinterpret_cast<int*>(0x141AE732C);
auto* com_console_lines = reinterpret_cast<char**>(0x141AE7330);
@ -254,18 +254,6 @@ namespace command
*reinterpret_cast<int*>(1) = 0;
});
add("print", [](const params& params)
{
auto msg = params.join(1);
printf("%s\n", msg.data());
});
add("printError", [](const params& params)
{
auto msg = params.join(1);
game::Com_Error(game::ERR_DROP, "%s\n", msg.data());
});
add("dvarDump", []()
{
game_console::print(game_console::con_type_info,

View File

@ -386,9 +386,7 @@ namespace demonware
auto lsg_server = register_server("aw-pc-lobby.prod.demonware.net");
auto auth_server = register_server("aw-pc-auth3.prod.demonware.net");
// TODO:
/*auth_server->register_service<bdDediAuth>();
auth_server->register_service<bdDediAuth>();
auth_server->register_service<bdSteamAuth>();
auth_server->register_service<bdDediRSAAuth>();
@ -400,7 +398,7 @@ namespace demonware
lsg_server->register_service<bdBandwidthTest>();
lsg_server->register_service<bdGroup>();
lsg_server->register_service<bdAnticheat>();
lsg_server->register_service<bdRelayService>();*/
lsg_server->register_service<bdRelayService>();
}
void post_load() override

View File

@ -4,6 +4,8 @@
#include "game/game.hpp"
#include <utils/hook.hpp>
namespace dvars
{
namespace override

View File

@ -1,7 +1,6 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "fastfiles.hpp"
#include "command.hpp"
#include "game_console.hpp"
@ -11,6 +10,7 @@
namespace fastfiles
{
static std::string current_fastfile;
namespace
{
utils::hook::detour db_try_load_x_file_internal_hook;
@ -18,8 +18,15 @@ namespace fastfiles
void db_try_load_x_file_internal(const char* zoneName, const int flags)
{
game_console::print(game_console::con_type_info, "Loading fastfile %s\n", zoneName);
current_fastfile = zoneName;
return db_try_load_x_file_internal_hook.invoke<void>(zoneName, flags);
}
}
const char* get_current_fastfile()
{
return current_fastfile.data();
}
void reallocate_asset_pool(const game::XAssetType type, const unsigned int new_size)
{
@ -31,7 +38,6 @@ namespace fastfiles
game::DB_XAssetPool[type] = new_pool;
game::g_poolSize[type] = new_size;
}
}
class component final : public component_interface
{

View File

@ -0,0 +1,9 @@
#pragma once
#include "game/game.hpp"
namespace fastfiles
{
const char* get_current_fastfile();
void reallocate_asset_pool(const game::XAssetType type, const unsigned int new_size);
}

View File

@ -0,0 +1,294 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "command.hpp"
#include "network.hpp"
#include "game_console.hpp"
#include "dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace network
{
namespace
{
std::unordered_map<std::string, callback>& get_callbacks()
{
static std::unordered_map<std::string, callback> callbacks{};
return callbacks;
}
bool handle_command(game::netadr_s* address, const char* command, game::msg_t* message)
{
const auto cmd_string = utils::string::to_lower(command);
auto& callbacks = get_callbacks();
const auto handler = callbacks.find(cmd_string);
if (handler == callbacks.end())
{
return false;
}
const auto offset = cmd_string.size() + 5;
const std::string_view data(message->data + offset, message->cursize - offset);
handler->second(*address, data);
return true;
}
/*void handle_command_stub(utils::hook::assembler& a)
{
const auto return_unhandled = a.newLabel();
a.pushad64();
a.mov(r8, rsi); // message
a.mov(rdx, rdi); // command
a.mov(rcx, r14); // netaddr
a.call_aligned(handle_command);
a.test(al, al);
a.jz(return_unhandled);
// Command handled
a.popad64();
a.mov(eax, 0x14020AA0E);
a.jmp(eax);
a.bind(return_unhandled);
a.popad64();
a.mov(eax, 0x14020A19A);
a.jmp(eax);
}*/
int net_compare_base_address(const game::netadr_s* a1, const game::netadr_s* a2)
{
if (a1->type == a2->type)
{
switch (a1->type)
{
case game::netadrtype_t::NA_BOT:
case game::netadrtype_t::NA_LOOPBACK:
return a1->port == a2->port;
case game::netadrtype_t::NA_IP:
return !memcmp(a1->ip, a2->ip, 4);
case game::netadrtype_t::NA_BROADCAST:
return true;
default:
break;
}
}
return false;
}
int net_compare_address(const game::netadr_s* a1, const game::netadr_s* a2)
{
return net_compare_base_address(a1, a2) && a1->port == a2->port;
}
void reconnect_migratated_client(void*, game::netadr_s* from, const int, const int, const char*,
const char*, bool)
{
// This happens when a client tries to rejoin after being recently disconnected, OR by a duplicated guid
// We don't want this to do anything. It decides to crash seemingly randomly
// Rather than try and let the player in, just tell them they are a duplicate player and reject connection
game::NET_OutOfBandPrint(game::NS_SERVER, from, "error\nYou are already connected to the server.");
}
}
void on(const std::string& command, const callback& callback)
{
get_callbacks()[utils::string::to_lower(command)] = callback;
}
void send(const game::netadr_s& address, const std::string& command, const std::string& data, const char separator)
{
std::string packet = "\xFF\xFF\xFF\xFF";
packet.append(command);
packet.push_back(separator);
packet.append(data);
send(address, packet);
}
void send(const game::netadr_s& address, const std::string& data)
{
if (address.type == game::NA_LOOPBACK)
{
game::NET_SendLoopPacket(game::NS_CLIENT1, static_cast<int>(data.size()), data.data(), &address);
}
else
{
game::Sys_SendPacket(static_cast<int>(data.size()), data.data(), &address);
}
}
bool are_addresses_equal(const game::netadr_s& a, const game::netadr_s& b)
{
return net_compare_address(&a, &b);
}
const char* net_adr_to_string(const game::netadr_s& a)
{
if (a.type == game::netadrtype_t::NA_LOOPBACK)
{
return "loopback";
}
if (a.type == game::netadrtype_t::NA_BOT)
{
return "bot";
}
if (a.type == game::netadrtype_t::NA_IP || a.type == game::netadrtype_t::NA_BROADCAST)
{
if (a.port)
{
return utils::string::va("%u.%u.%u.%u:%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3], htons(a.port));
}
return utils::string::va("%u.%u.%u.%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
}
return "bad";
}
/*void set_xuid_config_string_stub(utils::hook::assembler& a)
{
const auto return_regular = a.newLabel();
a.mov(rax, ptr(rsp));
a.mov(r9, 0x); // This is the evil one :(
a.cmp(rax, r9);
a.jne(return_regular);
// Do the original work
a.call_aligned(return_regular);
// Jump to success branch
a.mov(rax, 0x);
a.mov(ptr(rsp), rax);
a.ret();
a.bind(return_regular);
a.sub(rsp, 0x38);
a.mov(eax, ptr(rcx));
a.mov(r9d, ptr(rcx, 4));
a.mov(r10, rdx);
a.jmp(0x1404B725D);
}*/
game::dvar_t* register_netport_stub(const char* dvarName, int value, int min, int max, unsigned int flags,
const char* description)
{
auto dvar = game::Dvar_RegisterInt("net_port", 27016, 0, 0xFFFFu, game::DVAR_FLAG_LATCHED, "Network port");
// read net_port from command line
command::read_startup_variable("net_port");
return dvar;
}
class component final : public component_interface
{
public:
void post_unpack() override
{
{
if (game::environment::is_sp())
{
return;
}
// redirect dw_sendto to raw socket
utils::hook::jump(0x1404D850A, reinterpret_cast<void*>(0x1404D849A));
// intercept command handling
//utils::hook::jump(0x14020A175, utils::hook::assemble(handle_command_stub), true);
// handle xuid without secure connection
//utils::hook::jump(0x1404B7250, utils::hook::assemble(set_xuid_config_string_stub), true);
utils::hook::jump(0x1403DA700, net_compare_address);
utils::hook::jump(0x1403DA750, net_compare_base_address);
// don't establish secure conenction
utils::hook::set<uint8_t>(0x140232BBD, 0xEB);
utils::hook::set<uint8_t>(0x140232C9A, 0xEB);
utils::hook::set<uint8_t>(0x140232F8D, 0xEB);
utils::hook::set<uint8_t>(0x14020862F, 0xEB);
// ignore unregistered connection
utils::hook::jump(0x140439EA9, reinterpret_cast<void*>(0x140439E28));
utils::hook::set<uint8_t>(0x140439E9E, 0xEB);
// disable xuid verification
utils::hook::set<uint8_t>(0x140022319, 0xEB);
utils::hook::set<uint8_t>(0x140022334, 0xEB);
// disable xuid verification
utils::hook::nop(0x14043CC4C, 2);
utils::hook::set<uint8_t>(0x14043CCA8, 0xEB);
// ignore configstring mismatch
utils::hook::set<uint8_t>(0x140211610, 0xEB);
// ignore dw handle in SV_PacketEvent
utils::hook::set<uint8_t>(0x140442F6D, 0xEB);
utils::hook::call(0x140442F61, &net_compare_address);
// ignore dw handle in SV_FindClientByAddress
utils::hook::set<uint8_t>(0x14044256D, 0xEB);
utils::hook::call(0x140442561, &net_compare_address);
// ignore dw handle in SV_DirectConnect
utils::hook::set<uint8_t>(0x140439BA8, 0xEB);
utils::hook::set<uint8_t>(0x140439DA5, 0xEB);
utils::hook::call(0x140439B9B, &net_compare_address);
utils::hook::call(0x140439D98, &net_compare_address);
// increase cl_maxpackets
dvars::override::Dvar_RegisterInt("cl_maxpackets", 1000, 1, 1000, 0x1);
// ignore impure client
utils::hook::jump(0x14043AC0D, reinterpret_cast<void*>(0x14043ACA3));
// don't send checksum
utils::hook::set<uint8_t>(0x1404D84C0, 0);
// don't read checksum
utils::hook::jump(0x1404D842B, 0x1404D8453);
// don't try to reconnect client
utils::hook::call(0x140439D4D, reconnect_migratated_client);
// allow server owner to modify net_port before the socket bind
utils::hook::call(0x1404D7A7F, register_netport_stub);
// ignore built in "print" oob command and add in our own
utils::hook::set<uint8_t>(0x14020A723, 0xEB);
on("print", [](const game::netadr_s& addr, const std::string_view& data)
{
const std::string message{data};
if (game::environment::is_dedi())
{
printf("%s\n", message.data());
}
else
{
game_console::print(game_console::con_type_info, "%s\n", message.data());
}
});
}
}
};
}
REGISTER_COMPONENT(network::component)

View File

@ -0,0 +1,48 @@
#pragma once
#include "game/game.hpp"
namespace network
{
using callback = std::function<void(const game::netadr_s&, const std::string_view&)>;
void on(const std::string& command, const callback& callback);
void send(const game::netadr_s& address, const std::string& command, const std::string& data, char separator = ' ');
void send(const game::netadr_s& address, const std::string& data);
bool are_addresses_equal(const game::netadr_s& a, const game::netadr_s& b);
const char* net_adr_to_string(const game::netadr_s& a);
}
inline bool operator==(const game::netadr_s& a, const game::netadr_s& b)
{
return network::are_addresses_equal(a, b); //
}
inline bool operator!=(const game::netadr_s& a, const game::netadr_s& b)
{
return !(a == b); //
}
namespace std
{
template <>
struct equal_to<game::netadr_s>
{
using result_type = bool;
bool operator()(const game::netadr_s& lhs, const game::netadr_s& rhs) const
{
return network::are_addresses_equal(lhs, rhs);
}
};
template <>
struct hash<game::netadr_s>
{
size_t operator()(const game::netadr_s& x) const noexcept
{
return hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(&x.ip[0])) ^ hash<uint16_t>()(x.port);
}
};
}

View File

@ -5,9 +5,10 @@
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "scheduler.hpp"
#include "dvars.hpp"
#include "fastfiles.hpp"
#include <utils/string.hpp>
#include <utils/hook.hpp>
namespace patches
@ -21,6 +22,22 @@ namespace patches
return game::Dvar_FindVar("name")->current.string;
}
utils::hook::detour com_register_dvars_hook;
void com_register_dvars()
{
if (game::environment::is_mp())
{
// Make name save
game::Dvar_RegisterString("name", "Unknown Soldier", 0x1, "Player name.");
// Disable data validation error popup
game::Dvar_RegisterInt("data_validation_allow_drop", 0, 0, 0, 0, "");
}
return com_register_dvars_hook.invoke<void>();
}
game::dvar_t* register_com_maxfps_stub(const char* name, int /*value*/, int /*min*/, int /*max*/,
const unsigned int /*flags*/,
const char* description)
@ -74,6 +91,11 @@ namespace patches
return 0;
}
void missing_content_error_stub(int /*mode*/, const char* /*message*/)
{
game::Com_Error(game::ERR_DROP, utils::string::va("MISSING FILE\n%s.ff", fastfiles::get_current_fastfile()));
}
}
class component final : public component_interface
@ -85,7 +107,8 @@ namespace patches
LoadLibraryA("PhysXDevice64.dll");
LoadLibraryA("PhysXUpdateLoader64.dll");
dvars::override::Dvar_RegisterString("name", "Unknown Soldier", 1);
// Register dvars
com_register_dvars_hook.create(SELECT_VALUE(0x1402F86F0, 0x1403CF7F0), &com_register_dvars);
// Unlock fps in main menu
utils::hook::set<BYTE>(SELECT_VALUE(0x140144F5B, 0x140213C3B), 0xEB);
@ -102,6 +125,9 @@ namespace patches
// Patch Dvar_Command to print out values how CoD4 does it
utils::hook::jump(SELECT_VALUE(0x1402FB4C0, 0x1403D31C0), dvar_command_patch);
// Show missing fastfiles
utils::hook::call(SELECT_VALUE(0x1401817AF, 0x1402742A8), missing_content_error_stub);
// Fix mouse lag
utils::hook::nop(SELECT_VALUE(0x14038FAFF, 0x1404DB1AF), 6);
scheduler::loop([]()
@ -123,9 +149,6 @@ namespace patches
{
// Use name dvar
live_get_local_client_name_hook.create(0x1404D47F0, &live_get_local_client_name);
utils::hook::set<uint8_t>(0x1400058C0, 0xC3); // ValidateMetaData
utils::hook::set<uint8_t>(0x140005B10, 0xC3); // ^
}
static void patch_sp()

View File

@ -1,25 +1,37 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "utils/hook.hpp"
#include "utils/string.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace renderer
{
namespace
{
static auto technique = game::TECHNIQUE_UNLIT;
utils::hook::detour r_init_draw_method_hook;
utils::hook::detour r_update_front_end_dvar_options_hook;
int get_fullbright_technique()
{
switch (dvars::r_fullbright->current.integer)
{
case 3:
return 13;
case 2:
return 25;
default:
return game::TECHNIQUE_UNLIT;
}
}
void r_init_draw_method_stub()
{
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? technique : game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? technique : game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? technique : 182;
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : 182;
}
bool r_update_front_end_dvar_options_stub()
@ -30,9 +42,9 @@ namespace renderer
game::R_SyncRenderThread();
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? technique : game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? technique : game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? technique : 182;
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : 182;
}
return r_update_front_end_dvar_options_hook.invoke<bool>();
@ -49,7 +61,7 @@ namespace renderer
return;
}
dvars::r_fullbright = game::Dvar_RegisterBool("r_fullbright", false, 1, "Toggles rendering without lighting");
dvars::r_fullbright = game::Dvar_RegisterInt("r_fullbright", 0, 0, 3, 0x1, "Toggles rendering without lighting");
r_init_draw_method_hook.create(SELECT_VALUE(0x14046C150, 0x140588B00), &r_init_draw_method_stub);
r_update_front_end_dvar_options_hook.create(SELECT_VALUE(0x1404A5330, 0x1405C3AE0), &r_update_front_end_dvar_options_stub);

View File

@ -139,11 +139,6 @@ namespace demonware
int size;
buffer.read_int32(&size);
if (buffer.size() == 96)
{
size = 0;
}
if (size <= 0)
{
const std::string zero("\x00\x00\x00\x00", 4);

View File

@ -583,6 +583,49 @@ namespace game
vec2_t subScreenLeft;
};
enum netadrtype_t
{
NA_BOT = 0x0,
NA_BAD = 0x1,
NA_LOOPBACK = 0x2,
NA_BROADCAST = 0x3,
NA_IP = 0x4,
};
enum netsrc_t
{
NS_CLIENT1 = 0x0,
NS_MAXCLIENTS = 0x1,
NS_SERVER = 0x2,
NS_PACKET = 0x3,
NS_INVALID_NETSRC = 0x4,
};
struct netadr_s
{
netadrtype_t type;
unsigned char ip[4];
unsigned __int16 port;
netsrc_t localNetID;
unsigned int addrHandleIndex;
};
struct msg_t
{
int overflowed;
int readOnly;
char* data;
char* splitData;
int maxsize;
int cursize;
int splitSize;
int readcount;
int bit;
int lastEntityRef;
netsrc_t targetLocalNetID;
int useZlib;
};
enum errorParm
{
ERR_FATAL = 0,
@ -855,7 +898,7 @@ namespace game
struct gentity_s
{
int number;
};
struct playerState_s

View File

@ -25,7 +25,7 @@ namespace game
WEAK symbol<bool()> CL_IsCgameInitialized{ 0x140136560, 0x1401FD510 };
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{ 0x1401A3050, 0x1400EE500 };
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{ 0x1400EE500, 0x1401A3050 };
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), void* inData, bool includeOverride)> DB_EnumXAssets_FastFile{ 0x14017D7C0, 0x14026EC10 };
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{ 0x140151C20, 0x140240DF0 };
@ -57,6 +57,10 @@ namespace game
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{ 0x1404919D0, 0x1405AFBE0 };
WEAK symbol<void(netsrc_t, netadr_s*, const char*)> NET_OutOfBandPrint{ 0, 0x1403DADC0 };
WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{ 0, 0x1403DAF80 };
WEAK symbol<bool(const char* s, game::netadr_s* a)> NET_StringToAdr{ 0, 0x1403DB070 };
WEAK symbol<void(float x, float y, float width, float height, float s0, float t0, float s1, float t1,
float* color, Material* material)> R_AddCmdDrawStretchPic{ 0x1404A2580, 0x1405C0CB0 };
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{ 0x1404A2BF0, 0x1405C1320 };
@ -69,8 +73,12 @@ namespace game
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x14014FA70, 0x14023CB50 };
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{ 0, 0x1403B0640 };
WEAK symbol<void()> SV_Cmd_EndTokenizedString{ 0, 0x1403B0600 };
WEAK symbol<void(netadr_s* from)> SV_DirectConnect{ 0, 0x1404397A0 };
WEAK symbol<void(int localClientNum)> SV_FastRestart{ 0, 0x1404374E0 };
WEAK symbol<void(int, int, const char*)> SV_GameSendServerCommand{ 0, 0x14043E120 };
WEAK symbol<void(int, int, const char*)> SV_GameSendServerCommand{ 0x1403F3A70, 0x14043E120 };
WEAK symbol<const char* (int clientNum)> SV_GetGuid{ 0, 0x14043E1E0 };
WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{ 0, 0x1404377A0 };
WEAK symbol<bool()> SV_Loaded{ 0x1403F42C0, 0x14043FA50 };
@ -78,7 +86,9 @@ namespace game
WEAK symbol<void(int localClientNum, const char* map)> SV_StartMap{ 0, 0x140438320 };
WEAK symbol<void(int localClientNum, const char* map, bool migrate)> SV_StartMapForParty{ 0, 0x140438490 };
WEAK symbol<HANDLE(int folder, const char* baseFileName)> Sys_CreateFile{ 0x14037BCA0, 0x1404CC8A0 };
WEAK symbol<bool()> Sys_IsDatabaseReady2{ 0x1402FF980, 0x1403E1840 };
WEAK symbol<bool(int, void const*, const netadr_s*)> Sys_SendPacket{ 0x14038E720, 0x1404D8460 };
WEAK symbol<void()> Sys_ShowConsole{ 0x14038FA90, 0x1404D98B0 };
/***************************************************************

View File

@ -4,6 +4,7 @@
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include <utils/string.hpp>
#include <utils/flags.hpp>
#include <utils/io.hpp>

View File

@ -0,0 +1,10 @@
syntax = "proto3";
package proto.network;
message connect_info
{
bytes infostring = 1;
bytes publickey = 2;
bytes signature = 3;
}

View File

@ -45,7 +45,7 @@
#include <VersionHelpers.h>
#include <Psapi.h>
#include <urlmon.h>
//#include <atlbase.h>
#include <atlbase.h>
#include <iphlpapi.h>
// min and max is required by gdi, therefore NOMINMAX won't work
@ -86,6 +86,8 @@
#include <asmjit/core/jitruntime.h>
#include <asmjit/x86/x86assembler.h>
#include <proto/auth.pb.h>
#pragma warning(pop)
#pragma warning(disable: 4100)
@ -96,11 +98,4 @@
#include "resource.hpp"
#include <game/game.hpp>
#include <game/structs.hpp>
#include <utils/string.hpp>
#include <utils/flags.hpp>
#include <utils/hook.hpp>
using namespace std::literals;

View File

@ -87,13 +87,13 @@ namespace utils::hook
asmjit::Error assembler::call(void* target)
{
return Assembler::call(size_t(target));
return Assembler::call(target);
}
//asmjit::Error assembler::jmp(void* target)
//{
// return Assembler::jmp(size_t(target));
//}
asmjit::Error assembler::jmp(void* target)
{
return Assembler::jmp(target);
}
detour::detour(const size_t place, void* target) : detour(reinterpret_cast<void*>(place), target)
{