assets(weapons): cache weapons from code (Code quaK/H1-Mod probably took from Pluto xD)

Co-authored-by: H1-Mod Team <info@auroramod.dev>
Co-authored-by: HighTechRedNeck <HTRNModding@outlook.com>
This commit is contained in:
diamante0018 2025-01-24 13:59:57 +01:00
parent 199206ee5a
commit 3d77a21f3d
No known key found for this signature in database
GPG Key ID: F2000F181A4F7C85
10 changed files with 331 additions and 61 deletions

View File

@ -0,0 +1,61 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "component/console.hpp"
#include <utils/hook.hpp>
namespace weapons
{
namespace
{
void g_setup_level_weapon_def_stub()
{
game::G_SetupLevelWeaponDef();
// The count on most maps is well below 200
std::array<game::WeaponCompleteDef*, 256> weapons{};
const auto count = game::DB_GetAllXAssetOfType_FastFile(game::ASSET_TYPE_WEAPON, (void**)weapons.data(), static_cast<int>(weapons.max_size()));
std::sort(weapons.begin(), weapons.begin() + count, [](game::WeaponCompleteDef* weapon1, game::WeaponCompleteDef* weapon2)
{
assert(weapon1->szInternalName);
assert(weapon2->szInternalName);
return std::strcmp(weapon1->szInternalName, weapon2->szInternalName) < 0;
});
#ifdef _DEBUG
console::info("Found %i weapons to precache\n", count);
#endif
for (auto i = 0; i < count; ++i)
{
#ifdef _DEBUG
console::info("Precaching weapon \"%s\"\n", weapons[i]->szInternalName);
#endif
(void)game::G_GetWeaponForName(weapons[i]->szInternalName);
}
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
if (game::environment::is_sp()) return;
// Kill Scr_PrecacheItem (We are going to do this from code)
utils::hook::nop(0x1403BDB10, 4);
utils::hook::set<std::uint8_t>(0x1403BDB10, 0xC3);
// Load weapons from the DB
utils::hook::call(0x14039F382, g_setup_level_weapon_def_stub);
utils::hook::call(0x1403AE31A, g_setup_level_weapon_def_stub);
}
};
}
REGISTER_COMPONENT(weapons::component)

View File

@ -2,6 +2,7 @@
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "game/engine/sv_game.hpp"
#include "command.hpp"
#include "console.hpp"
@ -459,10 +460,7 @@ namespace command
}
game::sp::g_entities[0].flags ^= game::FL_GODMODE;
game::CG_GameMessage(0, utils::string::va("godmode %s",
game::sp::g_entities[0].flags & game::FL_GODMODE
? "^2on"
: "^1off"));
game::CG_GameMessage(0, utils::string::va("godmode %s", game::sp::g_entities[0].flags & game::FL_GODMODE ? "^2on" : "^1off"));
});
add("notarget", []
@ -473,10 +471,7 @@ namespace command
}
game::sp::g_entities[0].flags ^= game::FL_NOTARGET;
game::CG_GameMessage(0, utils::string::va("notarget %s",
game::sp::g_entities[0].flags & game::FL_NOTARGET
? "^2on"
: "^1off"));
game::CG_GameMessage(0, utils::string::va("notarget %s", game::sp::g_entities[0].flags & game::FL_NOTARGET ? "^2on" : "^1off"));
});
add("noclip", []
@ -487,10 +482,7 @@ namespace command
}
game::sp::g_entities[0].client->flags ^= 1;
game::CG_GameMessage(0, utils::string::va("noclip %s",
game::sp::g_entities[0].client->flags & 1
? "^2on"
: "^1off"));
game::CG_GameMessage(0, utils::string::va("noclip %s", game::sp::g_entities[0].client->flags & 1 ? "^2on" : "^1off"));
});
add("ufo", []
@ -501,10 +493,7 @@ namespace command
}
game::sp::g_entities[0].client->flags ^= 2;
game::CG_GameMessage(0, utils::string::va("ufo %s",
game::sp::g_entities[0].client->flags & 2
? "^2on"
: "^1off"));
game::CG_GameMessage(0, utils::string::va("ufo %s", game::sp::g_entities[0].client->flags & 2 ? "^2on" : "^1off"));
});
add("give", [](const params& params)
@ -556,78 +545,65 @@ namespace command
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
game::mp::g_entities[client_num].flags ^= game::FL_GODMODE;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"godmode %s\"",
game::mp::g_entities[client_num].flags & game::FL_GODMODE
? "^2on"
: "^1off"));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, utils::string::va("f \"godmode %s\"", game::mp::g_entities[client_num].flags & game::FL_GODMODE ? "^2on" : "^1off"));
});
add_sv("notarget", [](const int client_num, const params_sv&)
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
game::mp::g_entities[client_num].flags ^= game::FL_NOTARGET;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"notarget %s\"",
game::mp::g_entities[client_num].flags & game::FL_NOTARGET
? "^2on"
: "^1off"));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"notarget %s\"", game::mp::g_entities[client_num].flags & game::FL_NOTARGET ? "^2on" : "^1off"));
});
add_sv("noclip", [](const int client_num, const params_sv&)
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
game::mp::g_entities[client_num].client->flags ^= 1;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"noclip %s\"",
game::mp::g_entities[client_num].client->flags & 1
? "^2on"
: "^1off"));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"noclip %s\"", game::mp::g_entities[client_num].client->flags & 1 ? "^2on" : "^1off"));
});
add_sv("ufo", [](const int client_num, const params_sv&)
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
game::mp::g_entities[client_num].client->flags ^= 2;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"ufo %s\"",
game::mp::g_entities[client_num].client->flags & 2
? "^2on"
: "^1off"));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"ufo %s\"", game::mp::g_entities[client_num].client->flags & 2 ? "^2on" : "^1off"));
});
add_sv("setviewpos", [](const int client_num, const params_sv& params)
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
if (params.size() < 4)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"You did not specify the correct number of coordinates\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"You did not specify the correct number of coordinates\"");
return;
}
@ -640,14 +616,14 @@ namespace command
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
if (params.size() < 4)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"You did not specify the correct number of coordinates\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"You did not specify the correct number of coordinates\"");
return;
}
@ -660,13 +636,13 @@ namespace command
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
if (params.size() < 2)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
return;
}
@ -683,13 +659,13 @@ namespace command
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
return;
}
if (params.size() < 2)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
return;
}

View File

@ -1,8 +1,8 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "game/engine/sv_game.hpp"
#include "console.hpp"
@ -136,7 +136,7 @@ namespace dvar_cheats
const auto* dvar = game::Scr_GetString(0); // grab the original dvar again since it's never stored on stack
const auto* command = utils::string::va("q %s \"%s\"", dvar, value);
game::SV_GameSendServerCommand(entity_num, game::SV_CMD_RELIABLE, command);
game::engine::SV_GameSendServerCommand(entity_num, game::SV_CMD_RELIABLE, command);
}
const auto player_cmd_set_client_dvar = utils::hook::assemble([](utils::hook::assembler& a)

View File

@ -2,6 +2,7 @@
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "game/engine/sv_game.hpp"
#include "command.hpp"
#include "console.hpp"
@ -380,7 +381,7 @@ namespace party
const auto message = params.join(2);
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
console::info("%s -> %i: %s\n", name, client_num, message.data());
});
@ -394,7 +395,7 @@ namespace party
const auto client_num = atoi(params.get(1));
const auto message = params.join(2);
game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
console::info("%i: %s\n", client_num, message.data());
});
@ -408,7 +409,7 @@ namespace party
const auto message = params.join(1);
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
game::engine::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
console::info("%s: %s\n", name, message.data());
});
@ -421,7 +422,7 @@ namespace party
const auto message = params.join(1);
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
game::engine::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
console::info("%s\n", message.data());
});

View File

@ -2,6 +2,7 @@
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "game/engine/sv_game.hpp"
#include "command.hpp"
#include "console.hpp"
@ -290,6 +291,10 @@ namespace patches
static void patch_mp()
{
// Bypass Arxan function
utils::hook::nop(0x1404758C0, 16);
utils::hook::jump(0x1404758C0, game::engine::SV_GameSendServerCommand, true);
// Register dvars
com_register_dvars_hook.create(0x140413A90, &com_register_dvars_stub);

View File

@ -0,0 +1,181 @@
#include <std_include.hpp>
#include <game/game.hpp>
#include "sv_game.hpp"
#include <component/console.hpp>
#include <utils/string.hpp>
namespace game::engine
{
char* SV_ExpandNewlines(char* in)
{
static char string[1024];
unsigned int l = 0;
while (*in && l < sizeof(string) - 3)
{
if (*in == '\n')
{
string[l++] = '\\';
string[l++] = 'n';
}
else
{
if (*in != '\x14' && *in != '\x15')
{
string[l++] = *in;
}
}
++in;
}
string[l] = '\0';
return string;
}
void SV_CullIgnorableServerCommands(mp::client_t* client)
{
int to = client->reliableSent + 1;
for (int from = to; from <= client->reliableSequence; ++from)
{
int from_index = from & 0x7F;
assert(client->netBuf.reliableCommandInfo[from_index].time >= 0);
if (client->netBuf.reliableCommandInfo[from_index].type)
{
int to_index = to & 0x7F;
if (to_index != from_index)
{
client->netBuf.reliableCommandInfo[to_index] = client->netBuf.reliableCommandInfo[from_index];
}
++to;
}
}
client->reliableSequence = to - 1;
}
void SV_DelayDropClient(mp::client_t* drop, const char* reason)
{
assert(drop);
assert(reason);
assert(drop->header.state != CS_FREE);
if (drop->header.state == CS_ZOMBIE)
{
#ifdef _DEBUG
console::info("(drop->dropReason) = %s", drop->dropReason);
#endif
}
else if (!drop->dropReason)
{
drop->dropReason = reason;
}
}
void SV_AddServerCommand(mp::client_t* client, svscmd_type type, const char* cmd)
{
static_assert(offsetof(mp::client_t, netBuf.reliableCommandInfo[0].cmd) == 0xC44);
if (client->testClient == TC_BOT)
{
return;
}
if (client->reliableSequence - client->reliableAcknowledge < 64 && client->header.state == CS_ACTIVE || (SV_CullIgnorableServerCommands(client), type))
{
int len = static_cast<int>(std::strlen(cmd)) + 1;
int to = SV_CanReplaceServerCommand(client, reinterpret_cast<const unsigned char*>(cmd), len);
if (to < 0)
{
++client->reliableSequence;
}
else
{
int from = to + 1;
while (from <= client->reliableSequence)
{
client->netBuf.reliableCommandInfo[to & 0x7F] = client->netBuf.reliableCommandInfo[from & 0x7F];
++from;
++to;
}
}
if (client->reliableSequence - client->reliableAcknowledge == 129)
{
#ifdef _DEBUG
console::info("===== pending server commands =====\n");
int i = 0;
for (i = client->reliableAcknowledge + 1; i <= client->reliableSequence; ++i)
{
console::info("cmd %5d: %8d: %s\n", i, client->netBuf.reliableCommandInfo[i & 0x7F].time, client->netBuf.reliableCommandInfo[i & 0x7F].cmd);
}
console::info("cmd %5d: %8d: %s\n", i, *game::mp::serverTime, cmd);
#endif
NET_OutOfBandPrint(NS_SERVER, &client->header.netchan.remoteAddress, "disconnect");
SV_DelayDropClient(client, "EXE_SERVERCOMMANDOVERFLOW");
type = SV_CMD_RELIABLE;
cmd = utils::string::va("%c \"EXE_SERVERCOMMANDOVERFLOW\"", 'r');
}
int index = client->reliableSequence & 0x7F;
MSG_WriteReliableCommandToBuffer(cmd, client->netBuf.reliableCommandInfo[index].cmd, sizeof(client->netBuf.reliableCommandInfo[index].cmd));
client->netBuf.reliableCommandInfo[index].time = *game::mp::serverTime;
client->netBuf.reliableCommandInfo[index].type = type;
}
}
void SV_SendServerCommand(mp::client_t* cl, svscmd_type type, const char* fmt, ...)
{
mp::client_t* client;
int j, len;
va_list va;
const auto server_command_buf_large = std::make_unique<char[]>(0x20000);
va_start(va, fmt);
len = vsnprintf_s(server_command_buf_large.get(), 0x20000, _TRUNCATE, fmt, va);
va_end(va);
assert(len >= 0);
if (cl)
{
SV_AddServerCommand(cl, type, server_command_buf_large.get());
return;
}
if (environment::is_dedi() && !std::strncmp(server_command_buf_large.get(), "print", 5))
{
console::info("broadcast: %s\n", SV_ExpandNewlines(server_command_buf_large.get()));
}
const auto* sv_maxclients = Dvar_FindVar("sv_maxclients");
for (j = 0, client = mp::svs_clients; j < sv_maxclients->current.integer; j++, client++)
{
if (client->header.state < CS_CLIENTLOADING)
{
continue;
}
SV_AddServerCommand(client, type, server_command_buf_large.get());
}
}
void SV_GameSendServerCommand(int clientNum, svscmd_type type, const char* text)
{
[[maybe_unused]] const auto* sv_maxclients = Dvar_FindVar("sv_maxclients");
if (clientNum == -1)
{
SV_SendServerCommand(nullptr, type, "%s", text);
return;
}
assert(sv_maxclients->current.integer >= 1 && sv_maxclients->current.integer <= 18);
assert(static_cast<unsigned>(clientNum) < sv_maxclients->current.unsignedInt);
SV_SendServerCommand(&mp::svs_clients[clientNum], type, "%s", text);
}
}

View File

@ -0,0 +1,6 @@
#pragma once
namespace game::engine
{
void SV_GameSendServerCommand(int clientNum, svscmd_type type, const char* text);
}

View File

@ -1963,6 +1963,12 @@ namespace game
const char* buffer;
};
struct WeaponCompleteDef
{
const char* szInternalName;
WeaponDef* weapDef;
}; // Incomplete
union XAssetHeader
{
void* data;
@ -1998,9 +2004,9 @@ namespace game
menuDef_t *menu;
AnimationClass *animClass;
LocalizeEntry *localize;
WeaponAttachment *attachment;
WeaponCompleteDef *weapon;
SndDriverGlobals *sndDriverGlobals;
WeaponAttachment *attachment;*/
WeaponCompleteDef* weapon;
/*SndDriverGlobals *sndDriverGlobals;
FxEffectDef *fx;
FxImpactTable *impactFx;
SurfaceFxTable *surfaceFx;*/
@ -2434,6 +2440,24 @@ namespace game
int isInKillcam;
};
struct svscmd_info_t
{
int time;
int type;
char cmd[1024];
};
static_assert(sizeof(svscmd_info_t) == 0x408);
struct client_net_buffers_t
{
svscmd_info_t reliableCommandInfo[128];
char netchanOutgoingBuffer[131072];
char netchanIncomingBuffer[2048];
};
static_assert(sizeof(client_net_buffers_t) == 0x40C00);
struct client_t
{
clientHeader_t header;
@ -2443,7 +2467,17 @@ namespace game
int reliableAcknowledge;
int reliableSent;
int messageAcknowledge;
char _0xC30[0x41238];
int largeCommandSequence;
int gamestateMessageNum;
int challenge;
client_net_buffers_t netBuf;
int cumulThinkTime;
int beginCmdIndex;
int currCmdIndex;
usercmd_s lastUsercmd;
usercmd_s cmds[8];
int lastClientCommand;
char lastClientCommandString[1024];
gentity_s* gentity;
char name[16];
int lastPacketTime;

View File

@ -19,6 +19,7 @@ namespace game
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0, 0x140139D80};
WEAK symbol<void(unsigned int weapon, bool isAlternate, char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0, 0x140239370};
WEAK symbol<void()> BG_ClearWeaponDef{0x0, 0x140238D20};
WEAK symbol<void()> Com_Frame_Try_Block_Function{0x1403BC980, 0x1404131A0};
WEAK symbol<const char*(char const**)> Com_Parse{0x1404313E0, 0x1404F50E0};
@ -57,6 +58,7 @@ namespace game
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x140272E80, 0x14031FF80};
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x140272D50, 0x14031FE50};
WEAK symbol<int(const char* zoneName)> DB_IsLocalized{0x140273210, 0x140320360};
WEAK symbol<int(XAssetType type, void** assets, int maxCount)> DB_GetAllXAssetOfType_FastFile{0x0, 0x14031FC00};
WEAK symbol<void*(unsigned int size, unsigned int alignment, unsigned int type, PMem_Source source)> PMem_AllocFromSource_NoDebug{0x140430B80, 0x1404F46C0};
WEAK symbol<void(const char* name, PMem_Direction allocDir)> PMem_Free{0x140430EC0 , 0x1404F4A30};
@ -96,6 +98,7 @@ namespace game
WEAK symbol<Weapon(const char* pickupName, int model)> G_FindItem{0x140462490, 0x14021B7E0};
WEAK symbol<int(playerState_s* ps, Weapon weapon, int dualWield, int startInAltMode, int usedBefore)> G_GivePlayerWeapon{0x140359E20, 0x1403DA5E0};
WEAK symbol<Weapon(const char* name)> G_GetWeaponForName{0x140359890, 0x1403DA060};
WEAK symbol<void()> G_SetupLevelWeaponDef{0x0, 0x1403DA910};
WEAK symbol<void()> G_Glass_Update{0x14030E680, 0x140397450};
WEAK symbol<void (playerState_s* ps, Weapon weapon, int hadWeapon)> G_InitializeAmmo{0x140311F00, 0x14039AEA0};
WEAK symbol<void(int clientNum, Weapon weapon)> G_SelectWeapon{0x14035A200, 0x1403DA880};
@ -227,7 +230,7 @@ namespace game
WEAK symbol<const char*(int clientNum)> SV_GetGuid{0, 0x140475990};
WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{0, 0x14046F730};
WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0, 0x140477450};
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{0x140490F40, 0x1404758C0};
WEAK symbol<int(mp::client_t* client, const unsigned char* cmd, int cmdSize)> SV_CanReplaceServerCommand{0x0, 0x140478F00};
WEAK symbol<void(const char* error, ...)> Sys_Error{0x14043AC20, 0x1404FF510};
WEAK symbol<bool()> Sys_IsDatabaseReady2{0x1403C2D40, 0x140423920};
@ -255,6 +258,8 @@ namespace game
WEAK symbol<void(void* ps)> Jump_ClearState{0x0, 0x140213120};
WEAK symbol<void(const char* pszCommand, char* pszBuffer, int iBufferSize)> MSG_WriteReliableCommandToBuffer{0x0, 0x1404232B0};
WEAK symbol<void(unsigned __int64 markPos)> LargeLocalResetToMark{0x140423B50, 0x1404E4D00};
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x14062E030, 0x140738060};

View File

@ -55,6 +55,7 @@
#include <fstream>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <queue>