mirror of
https://github.com/XLabsProject/s1x-client.git
synced 2023-08-02 15:02:12 +02:00
Prepare networking
This commit is contained in:
parent
2247b68b4a
commit
832b6ac581
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace dvars
|
||||
{
|
||||
namespace override
|
||||
|
@ -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,19 +18,25 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
void reallocate_asset_pool(const game::XAssetType type, const unsigned int new_size)
|
||||
{
|
||||
const size_t element_size = game::DB_GetXAssetTypeSize(type);
|
||||
const char* get_current_fastfile()
|
||||
{
|
||||
return current_fastfile.data();
|
||||
}
|
||||
|
||||
auto* new_pool = utils::memory::get_allocator()->allocate(new_size * element_size);
|
||||
std::memmove(new_pool, game::DB_XAssetPool[type], game::g_poolSize[type] * element_size);
|
||||
void reallocate_asset_pool(const game::XAssetType type, const unsigned int new_size)
|
||||
{
|
||||
const size_t element_size = game::DB_GetXAssetTypeSize(type);
|
||||
|
||||
game::DB_XAssetPool[type] = new_pool;
|
||||
game::g_poolSize[type] = new_size;
|
||||
}
|
||||
auto* new_pool = utils::memory::get_allocator()->allocate(new_size * element_size);
|
||||
std::memmove(new_pool, game::DB_XAssetPool[type], game::g_poolSize[type] * element_size);
|
||||
|
||||
game::DB_XAssetPool[type] = new_pool;
|
||||
game::g_poolSize[type] = new_size;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
|
9
src/client/component/fastfiles.hpp
Normal file
9
src/client/component/fastfiles.hpp
Normal 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);
|
||||
}
|
294
src/client/component/network.cpp
Normal file
294
src/client/component/network.cpp
Normal 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)
|
48
src/client/component/network.hpp
Normal file
48
src/client/component/network.hpp
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 };
|
||||
|
||||
/***************************************************************
|
||||
|
@ -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>
|
||||
|
||||
|
10
src/client/proto/auth.proto
Normal file
10
src/client/proto/auth.proto
Normal file
@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package proto.network;
|
||||
|
||||
message connect_info
|
||||
{
|
||||
bytes infostring = 1;
|
||||
bytes publickey = 2;
|
||||
bytes signature = 3;
|
||||
}
|
@ -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;
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user