diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index baceb617..bf5e3a7d 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -58,6 +58,7 @@ namespace Components Loader::Register(new MapDump()); Loader::Register(new ModList()); Loader::Register(new Network()); + Loader::Register(new NetworkDebug()); Loader::Register(new Session()); Loader::Register(new Theatre()); Loader::Register(new ClanTags()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 141e6b63..833168d0 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -81,6 +81,7 @@ namespace Components #include "Modules/UIScript.hpp" #include "Modules/ModList.hpp" #include "Modules/Network.hpp" +#include "Modules/NetworkDebug.hpp" #include "Modules/Theatre.hpp" #include "Modules/QuickPatch.hpp" #include "Modules/Security.hpp" diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 9b9e8257..48ec826b 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -94,7 +94,7 @@ namespace Components ++(*Game::com_errorPrintsCount); MessagePrint(channel, msg); - if (*Game::cls_uiStarted != 0 && (*Game::com_fixedConsolePosition == 0)) + if (Game::cls->uiStarted != 0 && (*Game::com_fixedConsolePosition == 0)) { Game::CL_ConsoleFixPosition(); } diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 9b198743..9e415552 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -263,7 +263,7 @@ namespace Components { 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->reliableAcknowledge = client->reliableSequence; SendCommand(Game::NS_SERVER, client->header.netchan.remoteAddress, "error", "EXE_LOSTRELIABLECOMMANDS"); diff --git a/src/Components/Modules/NetworkDebug.cpp b/src/Components/Modules/NetworkDebug.cpp new file mode 100644 index 00000000..45ceb182 --- /dev/null +++ b/src/Components/Modules/NetworkDebug.cpp @@ -0,0 +1,47 @@ +#include + +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(&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(0x45D112, "CL_PacketEvent - ignoring illegible message\n"); + } +} diff --git a/src/Components/Modules/NetworkDebug.hpp b/src/Components/Modules/NetworkDebug.hpp new file mode 100644 index 00000000..34ec8344 --- /dev/null +++ b/src/Components/Modules/NetworkDebug.hpp @@ -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(); + }; +} diff --git a/src/Components/Modules/Security.cpp b/src/Components/Modules/Security.cpp index 07193220..fbab96e3 100644 --- a/src/Components/Modules/Security.cpp +++ b/src/Components/Modules/Security.cpp @@ -2,9 +2,9 @@ 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; size = Game::MSG_ReadBitsCompress(from, buffer, size); @@ -15,9 +15,9 @@ namespace Components 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; size = Game::MSG_ReadBitsCompress(from, buffer, size); diff --git a/src/Components/Modules/Security.hpp b/src/Components/Modules/Security.hpp index 23ceb4d6..081cbd90 100644 --- a/src/Components/Modules/Security.hpp +++ b/src/Components/Modules/Security.hpp @@ -7,10 +7,10 @@ namespace Components public: Security(); - private: - static int MsgReadBitsCompressCheckSV(const char* from, char* to, int size); - static int MsgReadBitsCompressCheckCL(const char* from, char* to, int size); + static int MsgReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size); + static int MsgReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size); + private: static int SVCanReplaceServerCommand(Game::client_t* client, const char* cmd); static long AtolAdjustPlayerLimit(const char* string); diff --git a/src/Components/Modules/Theatre.cpp b/src/Components/Modules/Theatre.cpp index a62826d2..0c917386 100644 --- a/src/Components/Modules/Theatre.cpp +++ b/src/Components/Modules/Theatre.cpp @@ -25,11 +25,11 @@ namespace Components void Theatre::StoreBaseline(PBYTE snapshotMsg) { // Store offset and length - Theatre::BaselineSnapshotMsgLen = *reinterpret_cast(snapshotMsg + 20); - Theatre::BaselineSnapshotMsgOff = *reinterpret_cast(snapshotMsg + 28) - 7; + BaselineSnapshotMsgLen = *reinterpret_cast(snapshotMsg + 20); + BaselineSnapshotMsgOff = *reinterpret_cast(snapshotMsg + 28) - 7; // Copy to our snapshot buffer - std::memcpy(Theatre::BaselineSnapshot, *reinterpret_cast(snapshotMsg + 8), *reinterpret_cast(snapshotMsg + 20)); + std::memcpy(BaselineSnapshot, *reinterpret_cast(snapshotMsg + 8), *reinterpret_cast(snapshotMsg + 20)); } __declspec(naked) void Theatre::BaselineStoreStub() @@ -37,7 +37,7 @@ namespace Components _asm { push edi - call Theatre::StoreBaseline + call StoreBaseline pop edi mov edx, 5ABEF5h @@ -48,15 +48,15 @@ namespace Components void Theatre::WriteBaseline() { static unsigned char bufData[131072]; - static char cmpData[131072]; + static unsigned char cmpData[131072]; Game::msg_t buf; 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); - const auto compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast(buf.data), cmpData, buf.cursize); + const auto compressedSize = Game::MSG_WriteBitsCompress(false, buf.data, cmpData, buf.cursize); const auto fileCompressedSize = compressedSize + 4; int byte8 = 8; @@ -86,7 +86,7 @@ namespace Components __asm { pushad - call Theatre::WriteBaseline + call WriteBaseline popad // Restore overwritten operation @@ -161,12 +161,12 @@ namespace Components { Game::Com_Printf(channel, message, file); - Theatre::CurrentInfo.name = file; - Theatre::CurrentInfo.mapname = (*Game::sv_mapname)->current.string; - Theatre::CurrentInfo.gametype = (*Game::sv_gametype)->current.string; - Theatre::CurrentInfo.author = Steam::SteamFriends()->GetPersonaName(); - Theatre::CurrentInfo.length = Game::Sys_Milliseconds(); - std::time(&Theatre::CurrentInfo.timeStamp); + CurrentInfo.name = file; + CurrentInfo.mapname = (*Game::sv_mapname)->current.string; + CurrentInfo.gametype = (*Game::sv_gametype)->current.string; + CurrentInfo.author = Steam::SteamFriends()->GetPersonaName(); + CurrentInfo.length = Game::Sys_Milliseconds(); + std::time(&CurrentInfo.timeStamp); } void Theatre::StopRecordStub(int channel, char* message) @@ -174,17 +174,17 @@ namespace Components Game::Com_Printf(channel, message); // Store correct length - Theatre::CurrentInfo.length = Game::Sys_Milliseconds() - Theatre::CurrentInfo.length; + CurrentInfo.length = Game::Sys_Milliseconds() - CurrentInfo.length; // Write metadata - FileSystem::FileWriter meta(Utils::String::VA("%s.json", Theatre::CurrentInfo.name.data())); - meta.write(nlohmann::json(Theatre::CurrentInfo.to_json()).dump()); + FileSystem::FileWriter meta(std::format("{}.json", CurrentInfo.name)); + meta.write(nlohmann::json(CurrentInfo.to_json()).dump()); } void Theatre::LoadDemos([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - Theatre::CurrentSelection = 0; - Theatre::Demos.clear(); + CurrentSelection = 0; + Demos.clear(); const auto demos = FileSystem::GetFileList("demos/", "dm_13"); @@ -198,35 +198,34 @@ namespace Components try { metaObject = nlohmann::json::parse(meta.getBuffer()); + + DemoInfo demoInfo; + demoInfo.name = demo.substr(0, demo.find_last_of(".")); + demoInfo.author = metaObject["author"].get(); + demoInfo.gametype = metaObject["gametype"].get(); + demoInfo.mapname = metaObject["mapname"].get(); + demoInfo.length = metaObject["length"].get(); + auto timestamp = metaObject["timestamp"].get(); + demoInfo.timeStamp = _atoi64(timestamp.data()); + + Demos.push_back(demoInfo); } catch (const nlohmann::json::parse_error& ex) { 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(); - demoInfo.gametype = metaObject["gametype"].get(); - demoInfo.mapname = metaObject["mapname"].get(); - demoInfo.length = metaObject["length"].get(); - auto timestamp = metaObject["timestamp"].get(); - demoInfo.timeStamp = _atoi64(timestamp.data()); - - Theatre::Demos.push_back(demoInfo); } } // 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) { - 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); @@ -242,31 +241,30 @@ namespace Components Dvar::Var("ui_demo_date").set(""); // 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) { - 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); } } unsigned int Theatre::GetDemoCount() { - return Theatre::Demos.size(); + return Demos.size(); } // Omit column here 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())); } @@ -275,13 +273,13 @@ namespace Components void Theatre::SelectDemo(unsigned int index) { - if (index < Theatre::Demos.size()) + if (index < Demos.size()) { - Theatre::CurrentSelection = index; - Theatre::DemoInfo info = Theatre::Demos[index]; + CurrentSelection = index; + auto info = Demos.at(index); tm time; - char buffer[1000] = { 0 }; + char buffer[1000] = {0}; localtime_s(&time, &info.timeStamp); asctime_s(buffer, sizeof buffer, &time); @@ -299,7 +297,7 @@ namespace Components if (Dvar::Var("cl_autoRecord").get() && !*Game::demoPlaying) { std::vector files; - std::vector demos = FileSystem::GetFileList("demos/", "dm_13"); + auto demos = FileSystem::GetFileList("demos/", "dm_13"); for (auto demo : demos) { @@ -309,9 +307,9 @@ namespace Components } } - int numDel = files.size() - Dvar::Var("cl_demosKeep").get(); + auto numDel = static_cast(files.size()) - Dvar::Var("cl_demosKeep").get(); - for (int i = 0; i < numDel; ++i) + for (auto i = 0; i < numDel; ++i) { Logger::Print("Deleting old demo {}\n", files[i]); FileSystem::_DeleteFile("demos", files[i].data()); @@ -326,17 +324,10 @@ namespace Components void Theatre::MapChangeStub() { - Theatre::StopRecording(); + StopRecording(); Utils::Hook::Call(0x464A60)(); } - // DANGEROUS, DON'T USE THIS ONE! - void Theatre::MapChangeSVStub(char* a1, char* a2) - { - Theatre::StopRecording(); - Utils::Hook::Call(0x487C50)(a1, a2); - } - void Theatre::StopRecording() { if (*Game::demoRecording) @@ -350,30 +341,29 @@ namespace Components Dvar::Register("cl_autoRecord", true, Game::DVAR_ARCHIVE, "Automatically record games."); Dvar::Register("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(0x5A85D2, Theatre::RecordGamestateStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x5ABE36, Theatre::BaselineStoreStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x5A8630, Theatre::BaselineToFileStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x4CB3EF, Theatre::UISetActiveMenuStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x50320E, Theatre::AdjustTimeDeltaStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x5A8E03, Theatre::ServerTimedOutStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5A8370, GamestateWriteStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A85D2, RecordGamestateStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5ABE36, BaselineStoreStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5A8630, BaselineToFileStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x4CB3EF, UISetActiveMenuStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x50320E, AdjustTimeDeltaStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A8E03, ServerTimedOutStub, HOOK_JUMP).install()->quick(); // Hook commands to enforce metadata generation - Utils::Hook(0x5A82AE, Theatre::RecordStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x5A8156, Theatre::StopRecordStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A82AE, RecordStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A8156, StopRecordStub, HOOK_CALL).install()->quick(); // Autorecording - Utils::Hook(0x5A1D6A, Theatre::InitCGameStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x4A712A, Theatre::MapChangeStub, HOOK_CALL).install()->quick(); - //Utils::Hook(0x5AA91C, Theatre::MapChangeSVStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A1D6A, InitCGameStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x4A712A, MapChangeStub, HOOK_CALL).install()->quick(); // UIScripts - UIScript::Add("loadDemos", Theatre::LoadDemos); - UIScript::Add("launchDemo", Theatre::PlayDemo); - UIScript::Add("deleteDemo", Theatre::DeleteDemo); + UIScript::Add("loadDemos", LoadDemos); + UIScript::Add("launchDemo", PlayDemo); + UIScript::Add("deleteDemo", DeleteDemo); // 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 if (!Dedicated::IsEnabled()) Utils::Hook::Set(0x47440B, "mp/defaultStringTable.csv"); @@ -381,11 +371,5 @@ namespace Components // Change font size Utils::Hook::Set(0x5AC854, 2); Utils::Hook::Set(0x5AC85A, 2); - -// Command::Add("democycle", [] (Command::Params params) -// { -// // Cmd_FollowCycle_f -// Utils::Hook::Call(0x458ED0)(Game::g_entities, -1); -// }); } } diff --git a/src/Components/Modules/Theatre.hpp b/src/Components/Modules/Theatre.hpp index 34c4e76b..0a880c68 100644 --- a/src/Components/Modules/Theatre.hpp +++ b/src/Components/Modules/Theatre.hpp @@ -62,7 +62,6 @@ namespace Components static uint32_t InitCGameStub(); static void MapChangeStub(); - static void MapChangeSVStub(char* a1, char* a2); static void RecordStub(int channel, char* message, char* file); static void StopRecordStub(int channel, char* message); diff --git a/src/Game/Client.cpp b/src/Game/Client.cpp index 4f440e79..2eef16be 100644 --- a/src/Game/Client.cpp +++ b/src/Game/Client.cpp @@ -8,6 +8,10 @@ namespace Game CL_DownloadsComplete_t CL_DownloadsComplete = CL_DownloadsComplete_t(0x42CE90); CL_DrawStretchPicPhysical_t CL_DrawStretchPicPhysical = CL_DrawStretchPicPhysical_t(0x4FC120); 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_GetRankForXP_t CL_GetRankForXP = CL_GetRankForXP_t(0x4FF8A0); 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_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30); 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(0xB2F8D0); @@ -28,13 +34,15 @@ namespace Game clientUIActive_t* clientUIActives = reinterpret_cast(0xB2BB88); + clientActive_t* clients = reinterpret_cast(0xB2C698); + voiceCommunication_t* cl_voiceCommunication = reinterpret_cast(0x1079DA0); int CL_GetMaxXP() { StringTable* rankTable = DB_FindXAssetHeader(ASSET_TYPE_STRINGTABLE, "mp/rankTable.csv").stringTable; 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) @@ -64,4 +72,11 @@ namespace Game AssertIn(localClientNum, MAX_LOCAL_CLIENTS); return &clientUIActives[localClientNum]; } + + clientActive_t* CL_GetLocalClientGlobals(const int localClientNum) + { + AssertIn(localClientNum, MAX_LOCAL_CLIENTS); + assert(clients[localClientNum].alwaysFalse == false); + return &clients[localClientNum]; + } } diff --git a/src/Game/Client.hpp b/src/Game/Client.hpp index cb3606b9..2f722c7a 100644 --- a/src/Game/Client.hpp +++ b/src/Game/Client.hpp @@ -20,6 +20,18 @@ namespace Game typedef const char* (*CL_GetConfigString_t)(int index); 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)(); 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); 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 clientConnection_t* clientConnections; @@ -61,6 +79,8 @@ namespace Game extern clientUIActive_t* clientUIActives; + extern clientActive_t* clients; + extern voiceCommunication_t* cl_voiceCommunication; extern int CL_GetMaxXP(); @@ -68,4 +88,5 @@ namespace Game extern connstate_t CL_GetLocalClientConnectionState(int localClientNum); extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum); extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum); + extern clientActive_t* CL_GetLocalClientGlobals(int localClientNum); } diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp index 3e3fde5b..8f63be0f 100644 --- a/src/Game/Dvars.cpp +++ b/src/Game/Dvars.cpp @@ -45,6 +45,7 @@ namespace Game const dvar_t** cl_showSend = reinterpret_cast(0xA1E870); const dvar_t** cl_voice = reinterpret_cast(0xB2BB44); const dvar_t** cl_ingame = reinterpret_cast(0xB2BB80); + const dvar_t** cl_shownet = reinterpret_cast(0x1059008); const dvar_t** g_cheats = reinterpret_cast(0x1A45D54); const dvar_t** g_deadChat = reinterpret_cast(0x19BD5DC); diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp index 61697af7..e8532b86 100644 --- a/src/Game/Dvars.hpp +++ b/src/Game/Dvars.hpp @@ -101,6 +101,7 @@ namespace Game extern const dvar_t** cl_showSend; extern const dvar_t** cl_voice; extern const dvar_t** cl_ingame; + extern const dvar_t** cl_shownet; extern const dvar_t** g_cheats; extern const dvar_t** g_deadChat; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 9162125c..d82acd5a 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -99,10 +99,11 @@ namespace Game MSG_WriteLong_t MSG_WriteLong = MSG_WriteLong_t(0x41CA20); MSG_WriteShort_t MSG_WriteShort = MSG_WriteShort_t(0x503B90); MSG_WriteString_t MSG_WriteString = MSG_WriteString_t(0x463820); - MSG_ReadDeltaUsercmdKey_t MSG_ReadDeltaUsercmdKey = MSG_ReadDeltaUsercmdKey_t(0x491F00); - MSG_WriteBitsCompress_t MSG_WriteBitsCompress = MSG_WriteBitsCompress_t(0x4319D0); + MSG_Discard_t MSG_Discard = MSG_Discard_t(0x4F56D0); 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_WriteBitsCompress_t MSG_WriteBitsCompress = MSG_WriteBitsCompress_t(0x4319D0); NetadrToSockadr_t NetadrToSockadr = NetadrToSockadr_t(0x4B4B40); @@ -262,6 +263,7 @@ namespace Game LargeLocalBegin_t LargeLocalBegin = LargeLocalBegin_t(0x4127A0); LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140); + LargeLocalReset_t LargeLocalReset = LargeLocalReset_t(0x430630); CmdArgs* cmd_args = reinterpret_cast(0x1AAC5D0); CmdArgs* sv_cmd_args = reinterpret_cast(0x1ACF8A0); @@ -343,8 +345,6 @@ namespace Game ScreenPlacement* scrPlaceFull = reinterpret_cast(0x10843F0); ScreenPlacement* scrPlaceFullUnsafe = reinterpret_cast(0x1084460); ScreenPlacement* scrPlaceView = reinterpret_cast(0x1084378); - - clientActive_t* clients = reinterpret_cast(0xB2C698); cg_s* cgArray = reinterpret_cast(0x7F0F78); cgs_t* cgsArray = reinterpret_cast(0x7ED3B8); @@ -381,8 +381,6 @@ namespace Game unsigned long* _tls_index = reinterpret_cast(0x66D94A8); - int* cls_uiStarted = reinterpret_cast(0xA7FFA0); - unsigned int* playerCardUIStringIndex = reinterpret_cast(0x62CD7A8); char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38] = reinterpret_cast(0x62CB4F8); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2998bae5..a477a018 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -224,18 +224,12 @@ namespace Game typedef __int64(*MSG_ReadInt64_t)(msg_t* msg); 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; - 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; - 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); extern MSG_WriteByte_t MSG_WriteByte; @@ -251,10 +245,19 @@ namespace Game typedef void(*MSG_WriteString_t)(msg_t* msg, const char *str); 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); 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; typedef void(*NetadrToSockadr_t)(netadr_t *a, sockaddr *s); @@ -578,6 +581,9 @@ namespace Game typedef int(*LargeLocalBeginRight_t)(int size); 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 MAX_LOCAL_CLIENTS = 1; constexpr std::size_t MAX_CLIENTS = 18; @@ -662,8 +668,6 @@ namespace Game extern ScreenPlacement* scrPlaceFull; extern ScreenPlacement* scrPlaceFullUnsafe; extern ScreenPlacement* scrPlaceView; - - extern clientActive_t* clients; extern cg_s* cgArray; extern cgs_t* cgsArray; @@ -704,8 +708,6 @@ namespace Game extern unsigned long* _tls_index; - extern int* cls_uiStarted; - constexpr std::size_t PLAYER_CARD_UI_STRING_COUNT = 18; extern unsigned int* playerCardUIStringIndex; extern char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38]; @@ -724,6 +726,8 @@ namespace Game extern int* ui_numArenas; extern int* ui_arenaBufPos; + constexpr auto MAX_MSGLEN = 0x20000; + ScreenPlacement* ScrPlace_GetFullPlacement(); ScreenPlacement* ScrPlace_GetUnsafeFullPlacement(); diff --git a/src/Game/Server.cpp b/src/Game/Server.cpp index 1f9370d8..c64f5811 100644 --- a/src/Game/Server.cpp +++ b/src/Game/Server.cpp @@ -19,6 +19,7 @@ namespace Game SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0); SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390); SV_FindClientByAddress_t SV_FindClientByAddress = SV_FindClientByAddress_t(0x44F450); + SV_WaitServer_t SV_WaitServer = SV_WaitServer_t(0x4256F0); int* svs_time = reinterpret_cast(0x31D9384); int* sv_timeResidual = reinterpret_cast(0x2089E14); diff --git a/src/Game/Server.hpp b/src/Game/Server.hpp index c1ce9cd0..8fd62bba 100644 --- a/src/Game/Server.hpp +++ b/src/Game/Server.hpp @@ -44,15 +44,18 @@ namespace Game typedef void(*SV_DropClient_t)(client_t* drop, const char* reason, bool tellThem); extern SV_DropClient_t SV_DropClient; - typedef client_t* (*SV_GetPlayerByName_t)(); + typedef client_t*(*SV_GetPlayerByName_t)(); extern SV_GetPlayerByName_t SV_GetPlayerByName; - typedef client_t* (*SV_GetPlayerByNum_t)(); + typedef client_t*(*SV_GetPlayerByNum_t)(); 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; + typedef void(*SV_WaitServer_t)(); + extern SV_WaitServer_t SV_WaitServer; + constexpr auto MAX_STATPACKETS = 7; extern int* svs_time; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 949e4f9f..c804fb48 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1603,6 +1603,8 @@ namespace Game int serverCommandNum; }; + static_assert(sizeof(clSnapshot_t) == 0x314C); + enum StanceState { CL_STANCE_STAND = 0x0, @@ -5962,6 +5964,17 @@ namespace Game 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 { NS_CLIENT1 = 0x0, diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 71999f73..af82cd69 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #pragma warning(pop)