[Theatre]: Cleanup (#624)

This commit is contained in:
Edo 2022-12-05 18:45:14 +00:00 committed by GitHub
parent c6cbd7d5c8
commit 210873499c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 216 additions and 111 deletions

View File

@ -58,6 +58,7 @@ namespace Components
Loader::Register(new MapDump()); Loader::Register(new MapDump());
Loader::Register(new ModList()); Loader::Register(new ModList());
Loader::Register(new Network()); Loader::Register(new Network());
Loader::Register(new NetworkDebug());
Loader::Register(new Session()); Loader::Register(new Session());
Loader::Register(new Theatre()); Loader::Register(new Theatre());
Loader::Register(new ClanTags()); Loader::Register(new ClanTags());

View File

@ -81,6 +81,7 @@ namespace Components
#include "Modules/UIScript.hpp" #include "Modules/UIScript.hpp"
#include "Modules/ModList.hpp" #include "Modules/ModList.hpp"
#include "Modules/Network.hpp" #include "Modules/Network.hpp"
#include "Modules/NetworkDebug.hpp"
#include "Modules/Theatre.hpp" #include "Modules/Theatre.hpp"
#include "Modules/QuickPatch.hpp" #include "Modules/QuickPatch.hpp"
#include "Modules/Security.hpp" #include "Modules/Security.hpp"

View File

@ -94,7 +94,7 @@ namespace Components
++(*Game::com_errorPrintsCount); ++(*Game::com_errorPrintsCount);
MessagePrint(channel, msg); MessagePrint(channel, msg);
if (*Game::cls_uiStarted != 0 && (*Game::com_fixedConsolePosition == 0)) if (Game::cls->uiStarted != 0 && (*Game::com_fixedConsolePosition == 0))
{ {
Game::CL_ConsoleFixPosition(); Game::CL_ConsoleFixPosition();
} }

View File

@ -263,7 +263,7 @@ namespace Components
{ {
if (client->reliableAcknowledge < 0) if (client->reliableAcknowledge < 0)
{ {
Logger::Print(Game::conChannel_t::CON_CHANNEL_NETWORK, "Negative reliableAcknowledge from {} - cl->reliableSequence is {}, reliableAcknowledge is {}\n", Logger::Print(Game::CON_CHANNEL_NETWORK, "Negative reliableAcknowledge from {} - cl->reliableSequence is {}, reliableAcknowledge is {}\n",
client->name, client->reliableSequence, client->reliableAcknowledge); client->name, client->reliableSequence, client->reliableAcknowledge);
client->reliableAcknowledge = client->reliableSequence; client->reliableAcknowledge = client->reliableSequence;
SendCommand(Game::NS_SERVER, client->header.netchan.remoteAddress, "error", "EXE_LOSTRELIABLECOMMANDS"); SendCommand(Game::NS_SERVER, client->header.netchan.remoteAddress, "error", "EXE_LOSTRELIABLECOMMANDS");

View File

@ -0,0 +1,47 @@
#include <STDInclude.hpp>
namespace Components
{
void NetworkDebug::CL_ParseServerMessage_Hk(Game::msg_t* msg)
{
auto file = Game::FS_FOpenFileWrite("badpacket.dat");
if (file)
{
Game::FS_Write(msg->data, msg->cursize, file);
Game::FS_FCloseFile(file);
}
Game::MSG_Discard(msg);
}
void NetworkDebug::CL_ParseBadPacket_f()
{
Game::msg_t msg;
unsigned char* file;
auto fileSize = Game::FS_ReadFile("badpacket.dat", reinterpret_cast<char**>(&file));
if (fileSize < 0)
{
return;
}
ZeroMemory(&msg, sizeof(msg));
msg.cursize = fileSize;
msg.data = file;
Game::MSG_ReadLong(&msg);
Game::MSG_ReadLong(&msg);
assert(0 && "Time to debug this packet, baby!");
Game::CL_ParseServerMessage(0, &msg);
Game::FS_FreeFile(file);
}
NetworkDebug::NetworkDebug()
{
#ifdef _DEBUG
Utils::Hook(0x4AA06A, CL_ParseServerMessage_Hk, HOOK_CALL).install()->quick();
Command::Add("parseBadPacket", CL_ParseBadPacket_f);
#endif
// Backport updates from IW5
Utils::Hook::Set<const char*>(0x45D112, "CL_PacketEvent - ignoring illegible message\n");
}
}

View File

@ -0,0 +1,15 @@
#pragma once
namespace Components
{
class NetworkDebug : public Component
{
public:
NetworkDebug();
private:
static void CL_ParseServerMessage_Hk(Game::msg_t* msg);
static void CL_ParseBadPacket_f();
};
}

View File

@ -2,9 +2,9 @@
namespace Components namespace Components
{ {
int Security::MsgReadBitsCompressCheckSV(const char* from, char* to, int size) int Security::MsgReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size)
{ {
static char buffer[0x8000]; static unsigned char buffer[0x8000];
if (size > 0x800) return 0; if (size > 0x800) return 0;
size = Game::MSG_ReadBitsCompress(from, buffer, size); size = Game::MSG_ReadBitsCompress(from, buffer, size);
@ -15,9 +15,9 @@ namespace Components
return size; return size;
} }
int Security::MsgReadBitsCompressCheckCL(const char* from, char* to, int size) int Security::MsgReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size)
{ {
static char buffer[0x100000]; static unsigned char buffer[0x100000];
if (size > 0x20000) return 0; if (size > 0x20000) return 0;
size = Game::MSG_ReadBitsCompress(from, buffer, size); size = Game::MSG_ReadBitsCompress(from, buffer, size);

View File

@ -7,10 +7,10 @@ namespace Components
public: public:
Security(); Security();
private: static int MsgReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size);
static int MsgReadBitsCompressCheckSV(const char* from, char* to, int size); static int MsgReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size);
static int MsgReadBitsCompressCheckCL(const char* from, char* to, int size);
private:
static int SVCanReplaceServerCommand(Game::client_t* client, const char* cmd); static int SVCanReplaceServerCommand(Game::client_t* client, const char* cmd);
static long AtolAdjustPlayerLimit(const char* string); static long AtolAdjustPlayerLimit(const char* string);

View File

@ -25,11 +25,11 @@ namespace Components
void Theatre::StoreBaseline(PBYTE snapshotMsg) void Theatre::StoreBaseline(PBYTE snapshotMsg)
{ {
// Store offset and length // Store offset and length
Theatre::BaselineSnapshotMsgLen = *reinterpret_cast<int*>(snapshotMsg + 20); BaselineSnapshotMsgLen = *reinterpret_cast<int*>(snapshotMsg + 20);
Theatre::BaselineSnapshotMsgOff = *reinterpret_cast<int*>(snapshotMsg + 28) - 7; BaselineSnapshotMsgOff = *reinterpret_cast<int*>(snapshotMsg + 28) - 7;
// Copy to our snapshot buffer // Copy to our snapshot buffer
std::memcpy(Theatre::BaselineSnapshot, *reinterpret_cast<DWORD**>(snapshotMsg + 8), *reinterpret_cast<DWORD*>(snapshotMsg + 20)); std::memcpy(BaselineSnapshot, *reinterpret_cast<DWORD**>(snapshotMsg + 8), *reinterpret_cast<DWORD*>(snapshotMsg + 20));
} }
__declspec(naked) void Theatre::BaselineStoreStub() __declspec(naked) void Theatre::BaselineStoreStub()
@ -37,7 +37,7 @@ namespace Components
_asm _asm
{ {
push edi push edi
call Theatre::StoreBaseline call StoreBaseline
pop edi pop edi
mov edx, 5ABEF5h mov edx, 5ABEF5h
@ -48,15 +48,15 @@ namespace Components
void Theatre::WriteBaseline() void Theatre::WriteBaseline()
{ {
static unsigned char bufData[131072]; static unsigned char bufData[131072];
static char cmpData[131072]; static unsigned char cmpData[131072];
Game::msg_t buf; Game::msg_t buf;
Game::MSG_Init(&buf, bufData, 131072); Game::MSG_Init(&buf, bufData, 131072);
Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff); Game::MSG_WriteData(&buf, &BaselineSnapshot[BaselineSnapshotMsgOff], BaselineSnapshotMsgLen - BaselineSnapshotMsgOff);
Game::MSG_WriteByte(&buf, 6); Game::MSG_WriteByte(&buf, 6);
const auto compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast<char*>(buf.data), cmpData, buf.cursize); const auto compressedSize = Game::MSG_WriteBitsCompress(false, buf.data, cmpData, buf.cursize);
const auto fileCompressedSize = compressedSize + 4; const auto fileCompressedSize = compressedSize + 4;
int byte8 = 8; int byte8 = 8;
@ -86,7 +86,7 @@ namespace Components
__asm __asm
{ {
pushad pushad
call Theatre::WriteBaseline call WriteBaseline
popad popad
// Restore overwritten operation // Restore overwritten operation
@ -161,12 +161,12 @@ namespace Components
{ {
Game::Com_Printf(channel, message, file); Game::Com_Printf(channel, message, file);
Theatre::CurrentInfo.name = file; CurrentInfo.name = file;
Theatre::CurrentInfo.mapname = (*Game::sv_mapname)->current.string; CurrentInfo.mapname = (*Game::sv_mapname)->current.string;
Theatre::CurrentInfo.gametype = (*Game::sv_gametype)->current.string; CurrentInfo.gametype = (*Game::sv_gametype)->current.string;
Theatre::CurrentInfo.author = Steam::SteamFriends()->GetPersonaName(); CurrentInfo.author = Steam::SteamFriends()->GetPersonaName();
Theatre::CurrentInfo.length = Game::Sys_Milliseconds(); CurrentInfo.length = Game::Sys_Milliseconds();
std::time(&Theatre::CurrentInfo.timeStamp); std::time(&CurrentInfo.timeStamp);
} }
void Theatre::StopRecordStub(int channel, char* message) void Theatre::StopRecordStub(int channel, char* message)
@ -174,17 +174,17 @@ namespace Components
Game::Com_Printf(channel, message); Game::Com_Printf(channel, message);
// Store correct length // Store correct length
Theatre::CurrentInfo.length = Game::Sys_Milliseconds() - Theatre::CurrentInfo.length; CurrentInfo.length = Game::Sys_Milliseconds() - CurrentInfo.length;
// Write metadata // Write metadata
FileSystem::FileWriter meta(Utils::String::VA("%s.json", Theatre::CurrentInfo.name.data())); FileSystem::FileWriter meta(std::format("{}.json", CurrentInfo.name));
meta.write(nlohmann::json(Theatre::CurrentInfo.to_json()).dump()); meta.write(nlohmann::json(CurrentInfo.to_json()).dump());
} }
void Theatre::LoadDemos([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) void Theatre::LoadDemos([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
Theatre::CurrentSelection = 0; CurrentSelection = 0;
Theatre::Demos.clear(); Demos.clear();
const auto demos = FileSystem::GetFileList("demos/", "dm_13"); const auto demos = FileSystem::GetFileList("demos/", "dm_13");
@ -198,35 +198,34 @@ namespace Components
try try
{ {
metaObject = nlohmann::json::parse(meta.getBuffer()); metaObject = nlohmann::json::parse(meta.getBuffer());
DemoInfo demoInfo;
demoInfo.name = demo.substr(0, demo.find_last_of("."));
demoInfo.author = metaObject["author"].get<std::string>();
demoInfo.gametype = metaObject["gametype"].get<std::string>();
demoInfo.mapname = metaObject["mapname"].get<std::string>();
demoInfo.length = metaObject["length"].get<int>();
auto timestamp = metaObject["timestamp"].get<std::string>();
demoInfo.timeStamp = _atoi64(timestamp.data());
Demos.push_back(demoInfo);
} }
catch (const nlohmann::json::parse_error& ex) catch (const nlohmann::json::parse_error& ex)
{ {
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what()); Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
continue;
} }
Theatre::DemoInfo demoInfo;
demoInfo.name = demo.substr(0, demo.find_last_of("."));
demoInfo.author = metaObject["author"].get<std::string>();
demoInfo.gametype = metaObject["gametype"].get<std::string>();
demoInfo.mapname = metaObject["mapname"].get<std::string>();
demoInfo.length = metaObject["length"].get<int>();
auto timestamp = metaObject["timestamp"].get<std::string>();
demoInfo.timeStamp = _atoi64(timestamp.data());
Theatre::Demos.push_back(demoInfo);
} }
} }
// Reverse, latest demo first! // Reverse, latest demo first!
std::ranges::reverse(Theatre::Demos); std::ranges::reverse(Demos);
} }
void Theatre::DeleteDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) void Theatre::DeleteDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
if (Theatre::CurrentSelection < Theatre::Demos.size()) if (CurrentSelection < Demos.size())
{ {
Theatre::DemoInfo demoInfo = Theatre::Demos[Theatre::CurrentSelection]; auto demoInfo = Demos.at(CurrentSelection);
Logger::Print("Deleting demo {}...\n", demoInfo.name); Logger::Print("Deleting demo {}...\n", demoInfo.name);
@ -242,31 +241,30 @@ namespace Components
Dvar::Var("ui_demo_date").set(""); Dvar::Var("ui_demo_date").set("");
// Reload demos // Reload demos
Theatre::LoadDemos(UIScript::Token(), info); LoadDemos(UIScript::Token(), info);
} }
} }
void Theatre::PlayDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) void Theatre::PlayDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
if (Theatre::CurrentSelection < Theatre::Demos.size()) if (CurrentSelection < Demos.size())
{ {
Command::Execute(Utils::String::VA("demo %s", Theatre::Demos[Theatre::CurrentSelection].name.data()), true); Command::Execute(std::format("demo {}", Demos[CurrentSelection].name), true);
Command::Execute("demoback", false); Command::Execute("demoback", false);
} }
} }
unsigned int Theatre::GetDemoCount() unsigned int Theatre::GetDemoCount()
{ {
return Theatre::Demos.size(); return Demos.size();
} }
// Omit column here // Omit column here
const char* Theatre::GetDemoText(unsigned int item, int /*column*/) const char* Theatre::GetDemoText(unsigned int item, int /*column*/)
{ {
if (item < Theatre::Demos.size()) if (item < Demos.size())
{ {
Theatre::DemoInfo info = Theatre::Demos[item]; auto info = Demos.at(item);
return Utils::String::VA("%s on %s", Game::UI_LocalizeGameType(info.gametype.data()), Game::UI_LocalizeMapName(info.mapname.data())); return Utils::String::VA("%s on %s", Game::UI_LocalizeGameType(info.gametype.data()), Game::UI_LocalizeMapName(info.mapname.data()));
} }
@ -275,13 +273,13 @@ namespace Components
void Theatre::SelectDemo(unsigned int index) void Theatre::SelectDemo(unsigned int index)
{ {
if (index < Theatre::Demos.size()) if (index < Demos.size())
{ {
Theatre::CurrentSelection = index; CurrentSelection = index;
Theatre::DemoInfo info = Theatre::Demos[index]; auto info = Demos.at(index);
tm time; tm time;
char buffer[1000] = { 0 }; char buffer[1000] = {0};
localtime_s(&time, &info.timeStamp); localtime_s(&time, &info.timeStamp);
asctime_s(buffer, sizeof buffer, &time); asctime_s(buffer, sizeof buffer, &time);
@ -299,7 +297,7 @@ namespace Components
if (Dvar::Var("cl_autoRecord").get<bool>() && !*Game::demoPlaying) if (Dvar::Var("cl_autoRecord").get<bool>() && !*Game::demoPlaying)
{ {
std::vector<std::string> files; std::vector<std::string> files;
std::vector<std::string> demos = FileSystem::GetFileList("demos/", "dm_13"); auto demos = FileSystem::GetFileList("demos/", "dm_13");
for (auto demo : demos) for (auto demo : demos)
{ {
@ -309,9 +307,9 @@ namespace Components
} }
} }
int numDel = files.size() - Dvar::Var("cl_demosKeep").get<int>(); auto numDel = static_cast<int>(files.size()) - Dvar::Var("cl_demosKeep").get<int>();
for (int i = 0; i < numDel; ++i) for (auto i = 0; i < numDel; ++i)
{ {
Logger::Print("Deleting old demo {}\n", files[i]); Logger::Print("Deleting old demo {}\n", files[i]);
FileSystem::_DeleteFile("demos", files[i].data()); FileSystem::_DeleteFile("demos", files[i].data());
@ -326,17 +324,10 @@ namespace Components
void Theatre::MapChangeStub() void Theatre::MapChangeStub()
{ {
Theatre::StopRecording(); StopRecording();
Utils::Hook::Call<void()>(0x464A60)(); Utils::Hook::Call<void()>(0x464A60)();
} }
// DANGEROUS, DON'T USE THIS ONE!
void Theatre::MapChangeSVStub(char* a1, char* a2)
{
Theatre::StopRecording();
Utils::Hook::Call<void(char*, char*)>(0x487C50)(a1, a2);
}
void Theatre::StopRecording() void Theatre::StopRecording()
{ {
if (*Game::demoRecording) if (*Game::demoRecording)
@ -350,30 +341,29 @@ namespace Components
Dvar::Register<bool>("cl_autoRecord", true, Game::DVAR_ARCHIVE, "Automatically record games."); Dvar::Register<bool>("cl_autoRecord", true, Game::DVAR_ARCHIVE, "Automatically record games.");
Dvar::Register<int>("cl_demosKeep", 30, 1, 999, Game::DVAR_ARCHIVE, "How many demos to keep with autorecord."); Dvar::Register<int>("cl_demosKeep", 30, 1, 999, Game::DVAR_ARCHIVE, "How many demos to keep with autorecord.");
Utils::Hook(0x5A8370, Theatre::GamestateWriteStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5A8370, GamestateWriteStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5A85D2, Theatre::RecordGamestateStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5A85D2, RecordGamestateStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5ABE36, Theatre::BaselineStoreStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x5ABE36, BaselineStoreStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x5A8630, Theatre::BaselineToFileStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x5A8630, BaselineToFileStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x4CB3EF, Theatre::UISetActiveMenuStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x4CB3EF, UISetActiveMenuStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x50320E, Theatre::AdjustTimeDeltaStub, HOOK_CALL).install()->quick(); Utils::Hook(0x50320E, AdjustTimeDeltaStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5A8E03, Theatre::ServerTimedOutStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x5A8E03, ServerTimedOutStub, HOOK_JUMP).install()->quick();
// Hook commands to enforce metadata generation // Hook commands to enforce metadata generation
Utils::Hook(0x5A82AE, Theatre::RecordStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5A82AE, RecordStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5A8156, Theatre::StopRecordStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5A8156, StopRecordStub, HOOK_CALL).install()->quick();
// Autorecording // Autorecording
Utils::Hook(0x5A1D6A, Theatre::InitCGameStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5A1D6A, InitCGameStub, HOOK_CALL).install()->quick();
Utils::Hook(0x4A712A, Theatre::MapChangeStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4A712A, MapChangeStub, HOOK_CALL).install()->quick();
//Utils::Hook(0x5AA91C, Theatre::MapChangeSVStub, HOOK_CALL).install()->quick();
// UIScripts // UIScripts
UIScript::Add("loadDemos", Theatre::LoadDemos); UIScript::Add("loadDemos", LoadDemos);
UIScript::Add("launchDemo", Theatre::PlayDemo); UIScript::Add("launchDemo", PlayDemo);
UIScript::Add("deleteDemo", Theatre::DeleteDemo); UIScript::Add("deleteDemo", DeleteDemo);
// Feeder // Feeder
UIFeeder::Add(10.0f, Theatre::GetDemoCount, Theatre::GetDemoText, Theatre::SelectDemo); UIFeeder::Add(10.0f, GetDemoCount, GetDemoText, SelectDemo);
// set the configstrings stuff to load the default (empty) string table; this should allow demo recording on all gametypes/maps // set the configstrings stuff to load the default (empty) string table; this should allow demo recording on all gametypes/maps
if (!Dedicated::IsEnabled()) Utils::Hook::Set<const char*>(0x47440B, "mp/defaultStringTable.csv"); if (!Dedicated::IsEnabled()) Utils::Hook::Set<const char*>(0x47440B, "mp/defaultStringTable.csv");
@ -381,11 +371,5 @@ namespace Components
// Change font size // Change font size
Utils::Hook::Set<BYTE>(0x5AC854, 2); Utils::Hook::Set<BYTE>(0x5AC854, 2);
Utils::Hook::Set<BYTE>(0x5AC85A, 2); Utils::Hook::Set<BYTE>(0x5AC85A, 2);
// Command::Add("democycle", [] (Command::Params params)
// {
// // Cmd_FollowCycle_f
// Utils::Hook::Call<void(Game::gentity_t*, int)>(0x458ED0)(Game::g_entities, -1);
// });
} }
} }

View File

@ -62,7 +62,6 @@ namespace Components
static uint32_t InitCGameStub(); static uint32_t InitCGameStub();
static void MapChangeStub(); static void MapChangeStub();
static void MapChangeSVStub(char* a1, char* a2);
static void RecordStub(int channel, char* message, char* file); static void RecordStub(int channel, char* message, char* file);
static void StopRecordStub(int channel, char* message); static void StopRecordStub(int channel, char* message);

View File

@ -8,6 +8,10 @@ namespace Game
CL_DownloadsComplete_t CL_DownloadsComplete = CL_DownloadsComplete_t(0x42CE90); CL_DownloadsComplete_t CL_DownloadsComplete = CL_DownloadsComplete_t(0x42CE90);
CL_DrawStretchPicPhysical_t CL_DrawStretchPicPhysical = CL_DrawStretchPicPhysical_t(0x4FC120); CL_DrawStretchPicPhysical_t CL_DrawStretchPicPhysical = CL_DrawStretchPicPhysical_t(0x4FC120);
CL_GetConfigString_t CL_GetConfigString = CL_GetConfigString_t(0x44ADB0); CL_GetConfigString_t CL_GetConfigString = CL_GetConfigString_t(0x44ADB0);
CL_AddReliableCommand_t CL_AddReliableCommand = CL_AddReliableCommand_t(0x454F40);
CL_ParseGamestate_t CL_ParseGamestate = CL_ParseGamestate_t(0x5AC250);
CL_ParseSnapshot_t CL_ParseSnapshot = CL_ParseSnapshot_t(0x5ABD40);
CL_ParseServerMessage_t CL_ParseServerMessage = CL_ParseServerMessage_t(0x4A9E90);
CL_GetMaxRank_t CL_GetMaxRank = CL_GetMaxRank_t(0x44BA30); CL_GetMaxRank_t CL_GetMaxRank = CL_GetMaxRank_t(0x44BA30);
CL_GetRankForXP_t CL_GetRankForXP = CL_GetRankForXP_t(0x4FF8A0); CL_GetRankForXP_t CL_GetRankForXP = CL_GetRankForXP_t(0x4FF8A0);
CL_GetRankIcon_t CL_GetRankIcon = CL_GetRankIcon_t(0x4A7B30); CL_GetRankIcon_t CL_GetRankIcon = CL_GetRankIcon_t(0x4A7B30);
@ -19,6 +23,8 @@ namespace Game
CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount = CL_GetLocalClientActiveCount_t(0x5BAD90); CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount = CL_GetLocalClientActiveCount_t(0x5BAD90);
CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30); CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30);
CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50); CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50);
CL_WriteDemoClientArchive_t CL_WriteDemoClientArchive = CL_WriteDemoClientArchive_t(0x5A8020);
CL_WriteDemoMessage_t CL_WriteDemoMessage = CL_WriteDemoMessage_t(0x4707C0);
float* cl_angles = reinterpret_cast<float*>(0xB2F8D0); float* cl_angles = reinterpret_cast<float*>(0xB2F8D0);
@ -28,13 +34,15 @@ namespace Game
clientUIActive_t* clientUIActives = reinterpret_cast<clientUIActive_t*>(0xB2BB88); clientUIActive_t* clientUIActives = reinterpret_cast<clientUIActive_t*>(0xB2BB88);
clientActive_t* clients = reinterpret_cast<clientActive_t*>(0xB2C698);
voiceCommunication_t* cl_voiceCommunication = reinterpret_cast<voiceCommunication_t*>(0x1079DA0); voiceCommunication_t* cl_voiceCommunication = reinterpret_cast<voiceCommunication_t*>(0x1079DA0);
int CL_GetMaxXP() int CL_GetMaxXP()
{ {
StringTable* rankTable = DB_FindXAssetHeader(ASSET_TYPE_STRINGTABLE, "mp/rankTable.csv").stringTable; StringTable* rankTable = DB_FindXAssetHeader(ASSET_TYPE_STRINGTABLE, "mp/rankTable.csv").stringTable;
const char* maxrank = StringTable_Lookup(rankTable, 0, "maxrank", 1); const char* maxrank = StringTable_Lookup(rankTable, 0, "maxrank", 1);
return atoi(StringTable_Lookup(rankTable, 0, maxrank, 7)); return std::atoi(StringTable_Lookup(rankTable, 0, maxrank, 7));
} }
clientConnection_t* CL_GetLocalClientConnection(const int localClientNum) clientConnection_t* CL_GetLocalClientConnection(const int localClientNum)
@ -64,4 +72,11 @@ namespace Game
AssertIn(localClientNum, MAX_LOCAL_CLIENTS); AssertIn(localClientNum, MAX_LOCAL_CLIENTS);
return &clientUIActives[localClientNum]; return &clientUIActives[localClientNum];
} }
clientActive_t* CL_GetLocalClientGlobals(const int localClientNum)
{
AssertIn(localClientNum, MAX_LOCAL_CLIENTS);
assert(clients[localClientNum].alwaysFalse == false);
return &clients[localClientNum];
}
} }

View File

@ -20,6 +20,18 @@ namespace Game
typedef const char* (*CL_GetConfigString_t)(int index); typedef const char* (*CL_GetConfigString_t)(int index);
extern CL_GetConfigString_t CL_GetConfigString; extern CL_GetConfigString_t CL_GetConfigString;
typedef void(*CL_AddReliableCommand_t)(int localClientNum, const char* cmd);
extern CL_AddReliableCommand_t CL_AddReliableCommand;
typedef void(*CL_ParseGamestate_t)(int localClientNum, msg_t* msg);
extern CL_ParseGamestate_t CL_ParseGamestate;
typedef void(*CL_ParseSnapshot_t)(int localClientNum, msg_t* msg);
extern CL_ParseSnapshot_t CL_ParseSnapshot;
typedef void(*CL_ParseServerMessage_t)(int localClientNum, msg_t* msg);
extern CL_ParseServerMessage_t CL_ParseServerMessage;
typedef int(*CL_GetMaxRank_t)(); typedef int(*CL_GetMaxRank_t)();
extern CL_GetMaxRank_t CL_GetMaxRank; extern CL_GetMaxRank_t CL_GetMaxRank;
@ -53,6 +65,12 @@ namespace Game
typedef int(*CL_MouseEvent_t)(int x, int y, int dx, int dy); typedef int(*CL_MouseEvent_t)(int x, int y, int dx, int dy);
extern CL_MouseEvent_t CL_MouseEvent; extern CL_MouseEvent_t CL_MouseEvent;
typedef void(*CL_WriteDemoClientArchive_t)(void (*write)(const void*, int, int), const playerState_s* ps, const float* viewangles, const float* selectedLocation, float selectedLocationAngle, int localClientNum, int index);
extern CL_WriteDemoClientArchive_t CL_WriteDemoClientArchive;
typedef void(*CL_WriteDemoMessage_t)(void (*write)(const void*, int, int), int serverMessageSequence, unsigned char* data, int len, int localClientNum);
extern CL_WriteDemoMessage_t CL_WriteDemoMessage;
extern float* cl_angles; extern float* cl_angles;
extern clientConnection_t* clientConnections; extern clientConnection_t* clientConnections;
@ -61,6 +79,8 @@ namespace Game
extern clientUIActive_t* clientUIActives; extern clientUIActive_t* clientUIActives;
extern clientActive_t* clients;
extern voiceCommunication_t* cl_voiceCommunication; extern voiceCommunication_t* cl_voiceCommunication;
extern int CL_GetMaxXP(); extern int CL_GetMaxXP();
@ -68,4 +88,5 @@ namespace Game
extern connstate_t CL_GetLocalClientConnectionState(int localClientNum); extern connstate_t CL_GetLocalClientConnectionState(int localClientNum);
extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum); extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum);
extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum); extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum);
extern clientActive_t* CL_GetLocalClientGlobals(int localClientNum);
} }

View File

@ -45,6 +45,7 @@ namespace Game
const dvar_t** cl_showSend = reinterpret_cast<const dvar_t**>(0xA1E870); const dvar_t** cl_showSend = reinterpret_cast<const dvar_t**>(0xA1E870);
const dvar_t** cl_voice = reinterpret_cast<const dvar_t**>(0xB2BB44); const dvar_t** cl_voice = reinterpret_cast<const dvar_t**>(0xB2BB44);
const dvar_t** cl_ingame = reinterpret_cast<const dvar_t**>(0xB2BB80); const dvar_t** cl_ingame = reinterpret_cast<const dvar_t**>(0xB2BB80);
const dvar_t** cl_shownet = reinterpret_cast<const dvar_t**>(0x1059008);
const dvar_t** g_cheats = reinterpret_cast<const dvar_t**>(0x1A45D54); const dvar_t** g_cheats = reinterpret_cast<const dvar_t**>(0x1A45D54);
const dvar_t** g_deadChat = reinterpret_cast<const dvar_t**>(0x19BD5DC); const dvar_t** g_deadChat = reinterpret_cast<const dvar_t**>(0x19BD5DC);

View File

@ -101,6 +101,7 @@ namespace Game
extern const dvar_t** cl_showSend; extern const dvar_t** cl_showSend;
extern const dvar_t** cl_voice; extern const dvar_t** cl_voice;
extern const dvar_t** cl_ingame; extern const dvar_t** cl_ingame;
extern const dvar_t** cl_shownet;
extern const dvar_t** g_cheats; extern const dvar_t** g_cheats;
extern const dvar_t** g_deadChat; extern const dvar_t** g_deadChat;

View File

@ -99,10 +99,11 @@ namespace Game
MSG_WriteLong_t MSG_WriteLong = MSG_WriteLong_t(0x41CA20); MSG_WriteLong_t MSG_WriteLong = MSG_WriteLong_t(0x41CA20);
MSG_WriteShort_t MSG_WriteShort = MSG_WriteShort_t(0x503B90); MSG_WriteShort_t MSG_WriteShort = MSG_WriteShort_t(0x503B90);
MSG_WriteString_t MSG_WriteString = MSG_WriteString_t(0x463820); MSG_WriteString_t MSG_WriteString = MSG_WriteString_t(0x463820);
MSG_ReadDeltaUsercmdKey_t MSG_ReadDeltaUsercmdKey = MSG_ReadDeltaUsercmdKey_t(0x491F00); MSG_Discard_t MSG_Discard = MSG_Discard_t(0x4F56D0);
MSG_WriteBitsCompress_t MSG_WriteBitsCompress = MSG_WriteBitsCompress_t(0x4319D0);
MSG_ReadByte_t MSG_ReadByte = MSG_ReadByte_t(0x4C1C20); MSG_ReadByte_t MSG_ReadByte = MSG_ReadByte_t(0x4C1C20);
MSG_ReadDeltaUsercmdKey_t MSG_ReadDeltaUsercmdKey = MSG_ReadDeltaUsercmdKey_t(0x491F00);
MSG_ReadBitsCompress_t MSG_ReadBitsCompress = MSG_ReadBitsCompress_t(0x4DCC30); MSG_ReadBitsCompress_t MSG_ReadBitsCompress = MSG_ReadBitsCompress_t(0x4DCC30);
MSG_WriteBitsCompress_t MSG_WriteBitsCompress = MSG_WriteBitsCompress_t(0x4319D0);
NetadrToSockadr_t NetadrToSockadr = NetadrToSockadr_t(0x4B4B40); NetadrToSockadr_t NetadrToSockadr = NetadrToSockadr_t(0x4B4B40);
@ -262,6 +263,7 @@ namespace Game
LargeLocalBegin_t LargeLocalBegin = LargeLocalBegin_t(0x4127A0); LargeLocalBegin_t LargeLocalBegin = LargeLocalBegin_t(0x4127A0);
LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140); LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140);
LargeLocalReset_t LargeLocalReset = LargeLocalReset_t(0x430630);
CmdArgs* cmd_args = reinterpret_cast<CmdArgs*>(0x1AAC5D0); CmdArgs* cmd_args = reinterpret_cast<CmdArgs*>(0x1AAC5D0);
CmdArgs* sv_cmd_args = reinterpret_cast<CmdArgs*>(0x1ACF8A0); CmdArgs* sv_cmd_args = reinterpret_cast<CmdArgs*>(0x1ACF8A0);
@ -344,8 +346,6 @@ namespace Game
ScreenPlacement* scrPlaceFullUnsafe = reinterpret_cast<ScreenPlacement*>(0x1084460); ScreenPlacement* scrPlaceFullUnsafe = reinterpret_cast<ScreenPlacement*>(0x1084460);
ScreenPlacement* scrPlaceView = reinterpret_cast<ScreenPlacement*>(0x1084378); ScreenPlacement* scrPlaceView = reinterpret_cast<ScreenPlacement*>(0x1084378);
clientActive_t* clients = reinterpret_cast<clientActive_t*>(0xB2C698);
cg_s* cgArray = reinterpret_cast<cg_s*>(0x7F0F78); cg_s* cgArray = reinterpret_cast<cg_s*>(0x7F0F78);
cgs_t* cgsArray = reinterpret_cast<cgs_t*>(0x7ED3B8); cgs_t* cgsArray = reinterpret_cast<cgs_t*>(0x7ED3B8);
@ -381,8 +381,6 @@ namespace Game
unsigned long* _tls_index = reinterpret_cast<unsigned long*>(0x66D94A8); unsigned long* _tls_index = reinterpret_cast<unsigned long*>(0x66D94A8);
int* cls_uiStarted = reinterpret_cast<int*>(0xA7FFA0);
unsigned int* playerCardUIStringIndex = reinterpret_cast<unsigned int*>(0x62CD7A8); unsigned int* playerCardUIStringIndex = reinterpret_cast<unsigned int*>(0x62CD7A8);
char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38] = reinterpret_cast<char(*)[PLAYER_CARD_UI_STRING_COUNT][38]>(0x62CB4F8); char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38] = reinterpret_cast<char(*)[PLAYER_CARD_UI_STRING_COUNT][38]>(0x62CB4F8);

View File

@ -224,18 +224,12 @@ namespace Game
typedef __int64(*MSG_ReadInt64_t)(msg_t* msg); typedef __int64(*MSG_ReadInt64_t)(msg_t* msg);
extern MSG_ReadInt64_t MSG_ReadInt64; extern MSG_ReadInt64_t MSG_ReadInt64;
typedef char* (*MSG_ReadString_t)(msg_t* msg); typedef char*(*MSG_ReadString_t)(msg_t* msg, char* string, unsigned int maxChars);
extern MSG_ReadString_t MSG_ReadString; extern MSG_ReadString_t MSG_ReadString;
typedef char* (*MSG_ReadStringLine_t)(msg_t *msg, char *string, unsigned int maxChars); typedef char*(*MSG_ReadStringLine_t)(msg_t *msg, char *string, unsigned int maxChars);
extern MSG_ReadStringLine_t MSG_ReadStringLine; extern MSG_ReadStringLine_t MSG_ReadStringLine;
typedef int(*MSG_ReadByte_t)(msg_t* msg);
extern MSG_ReadByte_t MSG_ReadByte;
typedef int(*MSG_ReadBitsCompress_t)(const char *from, char *to, int size);
extern MSG_ReadBitsCompress_t MSG_ReadBitsCompress;
typedef void(*MSG_WriteByte_t)(msg_t* msg, int c); typedef void(*MSG_WriteByte_t)(msg_t* msg, int c);
extern MSG_WriteByte_t MSG_WriteByte; extern MSG_WriteByte_t MSG_WriteByte;
@ -251,10 +245,19 @@ namespace Game
typedef void(*MSG_WriteString_t)(msg_t* msg, const char *str); typedef void(*MSG_WriteString_t)(msg_t* msg, const char *str);
extern MSG_WriteString_t MSG_WriteString; extern MSG_WriteString_t MSG_WriteString;
typedef void(*MSG_Discard_t)(msg_t* msg);
extern MSG_Discard_t MSG_Discard;
typedef int(*MSG_ReadByte_t)(msg_t* msg);
extern MSG_ReadByte_t MSG_ReadByte;
typedef bool(*MSG_ReadDeltaUsercmdKey_t)(msg_t* msg, int key, const usercmd_s* from, usercmd_s* to); typedef bool(*MSG_ReadDeltaUsercmdKey_t)(msg_t* msg, int key, const usercmd_s* from, usercmd_s* to);
extern MSG_ReadDeltaUsercmdKey_t MSG_ReadDeltaUsercmdKey; extern MSG_ReadDeltaUsercmdKey_t MSG_ReadDeltaUsercmdKey;
typedef int(*MSG_WriteBitsCompress_t)(bool trainHuffman, const char *from, char *to, int size); typedef int(*MSG_ReadBitsCompress_t)(const unsigned char* from, unsigned char* to, int size);
extern MSG_ReadBitsCompress_t MSG_ReadBitsCompress;
typedef int(*MSG_WriteBitsCompress_t)(bool trainHuffman, const unsigned char* from, unsigned char* to, int size);
extern MSG_WriteBitsCompress_t MSG_WriteBitsCompress; extern MSG_WriteBitsCompress_t MSG_WriteBitsCompress;
typedef void(*NetadrToSockadr_t)(netadr_t *a, sockaddr *s); typedef void(*NetadrToSockadr_t)(netadr_t *a, sockaddr *s);
@ -578,6 +581,9 @@ namespace Game
typedef int(*LargeLocalBeginRight_t)(int size); typedef int(*LargeLocalBeginRight_t)(int size);
extern LargeLocalBeginRight_t LargeLocalBeginRight; extern LargeLocalBeginRight_t LargeLocalBeginRight;
typedef void(*LargeLocalReset_t)();
extern LargeLocalReset_t LargeLocalReset;
constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1; constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1;
constexpr std::size_t MAX_LOCAL_CLIENTS = 1; constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
constexpr std::size_t MAX_CLIENTS = 18; constexpr std::size_t MAX_CLIENTS = 18;
@ -663,8 +669,6 @@ namespace Game
extern ScreenPlacement* scrPlaceFullUnsafe; extern ScreenPlacement* scrPlaceFullUnsafe;
extern ScreenPlacement* scrPlaceView; extern ScreenPlacement* scrPlaceView;
extern clientActive_t* clients;
extern cg_s* cgArray; extern cg_s* cgArray;
extern cgs_t* cgsArray; extern cgs_t* cgsArray;
@ -704,8 +708,6 @@ namespace Game
extern unsigned long* _tls_index; extern unsigned long* _tls_index;
extern int* cls_uiStarted;
constexpr std::size_t PLAYER_CARD_UI_STRING_COUNT = 18; constexpr std::size_t PLAYER_CARD_UI_STRING_COUNT = 18;
extern unsigned int* playerCardUIStringIndex; extern unsigned int* playerCardUIStringIndex;
extern char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38]; extern char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38];
@ -724,6 +726,8 @@ namespace Game
extern int* ui_numArenas; extern int* ui_numArenas;
extern int* ui_arenaBufPos; extern int* ui_arenaBufPos;
constexpr auto MAX_MSGLEN = 0x20000;
ScreenPlacement* ScrPlace_GetFullPlacement(); ScreenPlacement* ScrPlace_GetFullPlacement();
ScreenPlacement* ScrPlace_GetUnsafeFullPlacement(); ScreenPlacement* ScrPlace_GetUnsafeFullPlacement();

View File

@ -19,6 +19,7 @@ namespace Game
SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0); SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0);
SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390); SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390);
SV_FindClientByAddress_t SV_FindClientByAddress = SV_FindClientByAddress_t(0x44F450); SV_FindClientByAddress_t SV_FindClientByAddress = SV_FindClientByAddress_t(0x44F450);
SV_WaitServer_t SV_WaitServer = SV_WaitServer_t(0x4256F0);
int* svs_time = reinterpret_cast<int*>(0x31D9384); int* svs_time = reinterpret_cast<int*>(0x31D9384);
int* sv_timeResidual = reinterpret_cast<int*>(0x2089E14); int* sv_timeResidual = reinterpret_cast<int*>(0x2089E14);

View File

@ -44,15 +44,18 @@ namespace Game
typedef void(*SV_DropClient_t)(client_t* drop, const char* reason, bool tellThem); typedef void(*SV_DropClient_t)(client_t* drop, const char* reason, bool tellThem);
extern SV_DropClient_t SV_DropClient; extern SV_DropClient_t SV_DropClient;
typedef client_t* (*SV_GetPlayerByName_t)(); typedef client_t*(*SV_GetPlayerByName_t)();
extern SV_GetPlayerByName_t SV_GetPlayerByName; extern SV_GetPlayerByName_t SV_GetPlayerByName;
typedef client_t* (*SV_GetPlayerByNum_t)(); typedef client_t*(*SV_GetPlayerByNum_t)();
extern SV_GetPlayerByNum_t SV_GetPlayerByNum; extern SV_GetPlayerByNum_t SV_GetPlayerByNum;
typedef client_t* (*SV_FindClientByAddress_t)(netadr_t from, int qport, int remoteClientIndex); typedef client_t*(*SV_FindClientByAddress_t)(netadr_t from, int qport, int remoteClientIndex);
extern SV_FindClientByAddress_t SV_FindClientByAddress; extern SV_FindClientByAddress_t SV_FindClientByAddress;
typedef void(*SV_WaitServer_t)();
extern SV_WaitServer_t SV_WaitServer;
constexpr auto MAX_STATPACKETS = 7; constexpr auto MAX_STATPACKETS = 7;
extern int* svs_time; extern int* svs_time;

View File

@ -1603,6 +1603,8 @@ namespace Game
int serverCommandNum; int serverCommandNum;
}; };
static_assert(sizeof(clSnapshot_t) == 0x314C);
enum StanceState enum StanceState
{ {
CL_STANCE_STAND = 0x0, CL_STANCE_STAND = 0x0,
@ -5962,6 +5964,17 @@ namespace Game
FS_LIST_ALL = 0x1, FS_LIST_ALL = 0x1,
}; };
enum svc_ops_e
{
svc_nop = 0x0,
svc_gamestate = 0x1,
svc_configstring = 0x2,
svc_serverCommand = 0x3,
svc_matchdata = 0x4,
svc_snapshot = 0x5,
svc_EOF = 0x6,
};
enum netsrc_t enum netsrc_t
{ {
NS_CLIENT1 = 0x0, NS_CLIENT1 = 0x0,

View File

@ -45,6 +45,7 @@
#include <source_location> #include <source_location>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include <type_traits>
#include <unordered_map> #include <unordered_map>
#pragma warning(pop) #pragma warning(pop)