From 9b903f64e4826244b4edbe5d1a872ae2d5c11d45 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Wed, 23 Nov 2022 15:31:48 +0000 Subject: [PATCH 01/96] [Changelog]: Re-order urls --- src/Components/Modules/Changelog.cpp | 30 ++++++++++++++-------------- src/Utils/Cache.cpp | 22 ++++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/Components/Modules/Changelog.cpp b/src/Components/Modules/Changelog.cpp index 93b5974d..cafb5ebc 100644 --- a/src/Components/Modules/Changelog.cpp +++ b/src/Components/Modules/Changelog.cpp @@ -7,44 +7,44 @@ namespace Components void Changelog::LoadChangelog() { - //if (!Changelog::Lines.empty()) - // return; + std::lock_guard _(Mutex); + Lines.clear(); - std::lock_guard _(Changelog::Mutex); - Changelog::Lines.clear(); - std::string data = Utils::Cache::GetFile("/develop/CHANGELOG.md"); + const auto data = Utils::Cache::GetFile("/develop/CHANGELOG.md"); if (data.empty()) { - data = "^1Unable to get changelog."; + Lines.emplace_back("^1Unable to get changelog."); + return; } - Changelog::Lines = Utils::String::Split(data, '\n'); - - for (auto& line : Changelog::Lines) + auto buffer = Utils::String::Split(data, '\n'); + for (auto& line : buffer) { Utils::String::Replace(line, "\r", ""); } + + Lines = buffer; } unsigned int Changelog::GetChangelogCount() { - return Changelog::Lines.size(); + return Lines.size(); } // Omit column here - const char* Changelog::GetChangelogText(unsigned int item, int /*column*/) + const char* Changelog::GetChangelogText(unsigned int item, [[maybe_unused]] int column) { - std::lock_guard _(Changelog::Mutex); - if (item < Changelog::Lines.size()) + std::lock_guard _(Mutex); + if (item < Lines.size()) { - return Utils::String::VA("%s", Changelog::Lines[item].data()); + return Utils::String::VA("%s", Lines[item].data()); } return ""; } - void Changelog::SelectChangelog(unsigned int /*index*/) + void Changelog::SelectChangelog([[maybe_unused]] unsigned int index) { // Don't do anything in here } diff --git a/src/Utils/Cache.cpp b/src/Utils/Cache.cpp index 17390b83..4a654cab 100644 --- a/src/Utils/Cache.cpp +++ b/src/Utils/Cache.cpp @@ -4,8 +4,8 @@ namespace Utils { const char* Cache::Urls[] = { + "https://raw.githubusercontent.com/XLabsProject/iw4x-client", "https://xlabs.dev", - "https://raw.githubusercontent.com/XLabsProject/iw4x-client" }; std::string Cache::ValidUrl; @@ -13,7 +13,7 @@ namespace Utils std::string Cache::GetStaticUrl(const std::string& path) { - return Cache::Urls[0] + path; + return Urls[0] + path; } std::string Cache::GetUrl(const std::string& url, const std::string& path) @@ -23,29 +23,27 @@ namespace Utils std::string Cache::GetFile(const std::string& path, int timeout, const std::string& useragent) { - std::lock_guard _(Cache::CacheMutex); + std::lock_guard _(CacheMutex); - if (Cache::ValidUrl.empty()) + if (ValidUrl.empty()) { InternetSetCookieA("https://onion.casa", "disclaimer_accepted", "1"); InternetSetCookieA("https://hiddenservice.net", "disclaimer_accepted", "1"); - for (int i = 0; i < ARRAYSIZE(Cache::Urls); ++i) + for (std::size_t i = 0; i < ARRAYSIZE(Urls); ++i) { - std::string result = Utils::WebIO(useragent, Cache::GetUrl(Cache::Urls[i], path)).setTimeout(timeout)->get(); + std::string result = WebIO(useragent, GetUrl(Urls[i], path)).setTimeout(timeout)->get(); if (!result.empty()) { - Cache::ValidUrl = Cache::Urls[i]; + ValidUrl = Urls[i]; return result; } } - return ""; - } - else - { - return Utils::WebIO(useragent, Cache::GetUrl(Cache::ValidUrl, path)).setTimeout(timeout)->get(); + return {}; } + + return WebIO(useragent, GetUrl(ValidUrl, path)).setTimeout(timeout)->get(); } } From d60910c5d19e3c1a8c2efd4a24ddac9f463ff046 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Wed, 23 Nov 2022 16:36:07 +0000 Subject: [PATCH 02/96] [Cache]: Remove unused code --- src/Utils/Cache.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Utils/Cache.cpp b/src/Utils/Cache.cpp index 4a654cab..67479089 100644 --- a/src/Utils/Cache.cpp +++ b/src/Utils/Cache.cpp @@ -27,9 +27,6 @@ namespace Utils if (ValidUrl.empty()) { - InternetSetCookieA("https://onion.casa", "disclaimer_accepted", "1"); - InternetSetCookieA("https://hiddenservice.net", "disclaimer_accepted", "1"); - for (std::size_t i = 0; i < ARRAYSIZE(Urls); ++i) { std::string result = WebIO(useragent, GetUrl(Urls[i], path)).setTimeout(timeout)->get(); From dc7f6a9f6a57346607ef748cd33a9f89560d6314 Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 23 Nov 2022 21:19:47 +0000 Subject: [PATCH 03/96] [PlayerMovement]: Re-write stubs (#586) --- src/Components/Loader.cpp | 2 +- src/Components/Loader.hpp | 2 +- src/Components/Modules/Movement.cpp | 302 ------------------ src/Components/Modules/PlayerMovement.cpp | 278 ++++++++++++++++ .../{Movement.hpp => PlayerMovement.hpp} | 27 +- src/Game/Structs.hpp | 26 +- 6 files changed, 307 insertions(+), 330 deletions(-) delete mode 100644 src/Components/Modules/Movement.cpp create mode 100644 src/Components/Modules/PlayerMovement.cpp rename src/Components/Modules/{Movement.hpp => PlayerMovement.hpp} (59%) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index b4ad3c7d..783e289c 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -96,7 +96,7 @@ namespace Components Loader::Register(new Gamepad()); Loader::Register(new Chat()); Loader::Register(new TextRenderer()); - Loader::Register(new Movement()); + Loader::Register(new PlayerMovement()); Loader::Register(new Elevators()); Loader::Register(new ClientCommand()); Loader::Register(new VisionFile()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 5017eff3..981b55c2 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -126,7 +126,7 @@ namespace Components #include "Modules/SoundMutexFix.hpp" #include "Modules/Chat.hpp" #include "Modules/TextRenderer.hpp" -#include "Modules/Movement.hpp" +#include "Modules/PlayerMovement.hpp" #include "Modules/Elevators.hpp" #include "Modules/ClientCommand.hpp" #include "Modules/VisionFile.hpp" diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp deleted file mode 100644 index 6197387f..00000000 --- a/src/Components/Modules/Movement.cpp +++ /dev/null @@ -1,302 +0,0 @@ -#include - -namespace Components -{ - Dvar::Var Movement::PlayerSpectateSpeedScale; - Dvar::Var Movement::CGUfoScaler; - Dvar::Var Movement::CGNoclipScaler; - Dvar::Var Movement::BGBouncesAllAngles; - Dvar::Var Movement::BGRocketJump; - Dvar::Var Movement::BGRocketJumpScale; - Dvar::Var Movement::BGPlayerEjection; - Dvar::Var Movement::BGPlayerCollision; - Game::dvar_t* Movement::BGBounces; - Game::dvar_t* Movement::PlayerDuckedSpeedScale; - Game::dvar_t* Movement::PlayerProneSpeedScale; - - __declspec(naked) void Movement::PM_PlayerDuckedSpeedScaleStub() - { - __asm - { - push eax - mov eax, Movement::PlayerDuckedSpeedScale - fld dword ptr [eax + 0x10] // dvar_t.current.value - pop eax - - // Game's code - pop ecx - ret - } - } - - __declspec(naked) void Movement::PM_PlayerProneSpeedScaleStub() - { - __asm - { - push eax - mov eax, Movement::PlayerProneSpeedScale - fld dword ptr [eax + 0x10] // dvar_t.current.value - pop eax - - // Game's code - pop ecx - ret - } - } - - float Movement::PM_MoveScale(Game::playerState_s* ps, float fmove, - float rmove, float umove) - { - assert(ps != nullptr); - - auto max = std::fabsf(fmove) < std::fabsf(rmove) - ? std::fabsf(rmove) : std::fabsf(fmove); - - if (std::fabsf(umove) > max) - { - max = std::fabsf(umove); - } - - if (max == 0.0f) - { - return 0.0f; - } - - auto total = std::sqrtf(fmove * fmove - + rmove * rmove + umove * umove); - auto scale = (static_cast(ps->speed) * max) / (127.0f * total); - - if (ps->pm_flags & Game::PMF_WALKING || ps->leanf != 0.0f) - { - scale *= 0.4f; - } - - switch (ps->pm_type) - { - case Game::pmtype_t::PM_NOCLIP: - scale *= Movement::CGNoclipScaler.get(); - break; - case Game::pmtype_t::PM_UFO: - scale *= Movement::CGUfoScaler.get(); - break; - case Game::pmtype_t::PM_SPECTATOR: - scale *= Movement::PlayerSpectateSpeedScale.get(); - break; - default: - break; - } - - return scale; - } - - __declspec(naked) void Movement::PM_MoveScaleStub() - { - __asm - { - pushad - - push [esp + 0xC + 0x20] // umove - push [esp + 0xC + 0x20] // rmove - push [esp + 0xC + 0x20] // fmove - push esi // ps - call Movement::PM_MoveScale - add esp, 0x10 - - popad - ret - } - } - - __declspec(naked) void Movement::PM_StepSlideMoveStub() - { - __asm - { - // Check the value of BGBounces - push ecx - push eax - - mov eax, Movement::BGBounces - mov ecx, dword ptr [eax + 0x10] - test ecx, ecx - - pop eax - pop ecx - - // Do not bounce if BGBounces is 0 - jle noBounce - - // Bounce - push 0x4B1B34 - retn - - noBounce: - // Original game code - cmp dword ptr [esp + 0x24], 0 - push 0x4B1B48 - retn - } - } - - void Movement::PM_ProjectVelocityStub(const float* velIn, const float* normal, float* velOut) - { - const auto lengthSquared2D = velIn[0] * velIn[0] + velIn[1] * velIn[1]; - - if (std::fabsf(normal[2]) < 0.001f || lengthSquared2D == 0.0) - { - velOut[0] = velIn[0]; - velOut[1] = velIn[1]; - velOut[2] = velIn[2]; - return; - } - - auto newZ = velIn[0] * normal[0] + velIn[1] * normal[1]; - newZ = -newZ / normal[2]; - const auto lengthScale = std::sqrtf((velIn[2] * velIn[2] + lengthSquared2D) - / (newZ * newZ + lengthSquared2D)); - - if (Movement::BGBouncesAllAngles.get() - || (lengthScale < 1.f || newZ < 0.f || velIn[2] > 0.f)) - { - velOut[0] = velIn[0] * lengthScale; - velOut[1] = velIn[1] * lengthScale; - velOut[2] = newZ * lengthScale; - } - } - - // Double bounces - void Movement::Jump_ClearState_Hk(Game::playerState_s* ps) - { - if (Movement::BGBounces->current.integer != Movement::DOUBLE) - { - Game::Jump_ClearState(ps); - } - } - - Game::gentity_s* Movement::Weapon_RocketLauncher_Fire_Hk(Game::gentity_s* ent, unsigned int weaponIndex, - float spread, Game::weaponParms* wp, const float* gunVel, Game::lockonFireParms* lockParms, bool magicBullet) - { - auto* result = Game::Weapon_RocketLauncher_Fire(ent, weaponIndex, spread, wp, gunVel, lockParms, magicBullet); - - if (ent->client != nullptr && BGRocketJump.get() && - wp->weapDef->inventoryType != Game::WEAPINVENTORY_EXCLUSIVE) - { - const auto scale = Movement::BGRocketJumpScale.get(); - ent->client->ps.velocity[0] += (0.0f - wp->forward[0]) * scale; - ent->client->ps.velocity[1] += (0.0f - wp->forward[1]) * scale; - ent->client->ps.velocity[2] += (0.0f - wp->forward[2]) * scale; - } - - return result; - } - - int Movement::StuckInClient_Hk(Game::gentity_s* self) - { - if (Movement::BGPlayerEjection.get()) - { - return Utils::Hook::Call(0x402D30)(self); // StuckInClient - } - - return 0; - } - - void Movement::CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, - const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles) - { - if (Movement::BGPlayerCollision.get()) - { - Utils::Hook::Call - (0x478300) - (results, start, end, bounds, capsule, contents, origin, angles); // CM_TransformedCapsuleTrace - } - } - - Game::dvar_t* Movement::Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, - float min, float max, unsigned __int16 /*flags*/, const char* description) - { - Movement::PlayerSpectateSpeedScale = Dvar::Register(dvarName, value, - min, max, Game::DVAR_CHEAT | Game::DVAR_CODINFO, description); - - return Movement::PlayerSpectateSpeedScale.get(); - } - - void Movement::RegisterMovementDvars() - { - Movement::PlayerDuckedSpeedScale = Game::Dvar_RegisterFloat("player_duckedSpeedScale", - 0.65f, 0.0f, 5.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, - "The scale applied to the player speed when ducking"); - - Movement::PlayerProneSpeedScale = Game::Dvar_RegisterFloat("player_proneSpeedScale", - 0.15f, 0.0f, 5.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, - "The scale applied to the player speed when crawling"); - - // 3arc naming convention - Movement::CGUfoScaler = Dvar::Register("cg_ufo_scaler", - 6.0f, 0.001f, 1000.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, - "The speed at which ufo camera moves"); - - Movement::CGNoclipScaler = Dvar::Register("cg_noclip_scaler", - 3.0f, 0.001f, 1000.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, - "The speed at which noclip camera moves"); - - Movement::BGBouncesAllAngles = Dvar::Register("bg_bouncesAllAngles", - false, Game::DVAR_CODINFO, "Force bounce from all angles"); - - Movement::BGRocketJump = Dvar::Register("bg_rocketJump", - false, Game::DVAR_CODINFO, "Enable CoD4 rocket jumps"); - - Movement::BGRocketJumpScale = Dvar::Register("bg_rocketJumpScale", - 64.0f, 1.0f, std::numeric_limits::max(), Game::DVAR_CODINFO, - "The scale applied to the pushback force of a rocket"); - - Movement::BGPlayerEjection = Dvar::Register("bg_playerEjection", - true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); - - Movement::BGPlayerCollision = Dvar::Register("bg_playerCollision", - true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); - } - - Movement::Movement() - { - Scheduler::Once([] - { - static const char* bg_bouncesValues[] = - { - "disabled", - "enabled", - "double", - nullptr - }; - - Movement::BGBounces = Game::Dvar_RegisterEnum("bg_bounces", - bg_bouncesValues, Movement::DISABLED, Game::DVAR_CODINFO, "Bounce glitch settings"); - }, Scheduler::Pipeline::MAIN); - - // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. - Utils::Hook(0x448990, Movement::Dvar_RegisterSpectateSpeedScale, HOOK_CALL).install()->quick(); - - // PM_CmdScaleForStance - Utils::Hook(0x572D9B, Movement::PM_PlayerDuckedSpeedScaleStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x572DA5, Movement::PM_PlayerProneSpeedScaleStub, HOOK_JUMP).install()->quick(); - - // Hook PM_MoveScale so we can add custom speed scale for Ufo and Noclip - Utils::Hook(0x56F845, Movement::PM_MoveScaleStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x56FABD, Movement::PM_MoveScaleStub, HOOK_CALL).install()->quick(); - - // Bounce logic - Utils::Hook(0x4B1B2D, Movement::PM_StepSlideMoveStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x57383E, Movement::Jump_ClearState_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x4B1B97, Movement::PM_ProjectVelocityStub, HOOK_CALL).install()->quick(); - - // Rocket jump - Utils::Hook(0x4A4F9B, Movement::Weapon_RocketLauncher_Fire_Hk, HOOK_CALL).install()->quick(); // FireWeapon - - // Hook StuckInClient & CM_TransformedCapsuleTrace - // so we can prevent intersecting players from being pushed away from each other - Utils::Hook(0x5D8153, Movement::StuckInClient_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x45A5BF, Movement::CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity - Utils::Hook(0x5A0CAD, Movement::CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity - - Movement::RegisterMovementDvars(); - } -} diff --git a/src/Components/Modules/PlayerMovement.cpp b/src/Components/Modules/PlayerMovement.cpp new file mode 100644 index 00000000..9bf88dd7 --- /dev/null +++ b/src/Components/Modules/PlayerMovement.cpp @@ -0,0 +1,278 @@ +#include + +namespace Components +{ + Dvar::Var PlayerMovement::BGRocketJump; + Dvar::Var PlayerMovement::BGRocketJumpScale; + Dvar::Var PlayerMovement::BGPlayerEjection; + Dvar::Var PlayerMovement::BGPlayerCollision; + const Game::dvar_t* PlayerMovement::CGNoclipScaler; + const Game::dvar_t* PlayerMovement::CGUfoScaler; + const Game::dvar_t* PlayerMovement::PlayerSpectateSpeedScale; + const Game::dvar_t* PlayerMovement::BGBounces; + const Game::dvar_t* PlayerMovement::BGBouncesAllAngles; + const Game::dvar_t* PlayerMovement::PlayerDuckedSpeedScale; + const Game::dvar_t* PlayerMovement::PlayerProneSpeedScale; + + __declspec(naked) void PlayerMovement::PM_PlayerDuckedSpeedScaleStub() + { + __asm + { + push eax + mov eax, PlayerDuckedSpeedScale + fld dword ptr [eax + 0x10] // dvar_t.current.value + pop eax + + // Game's code + pop ecx + ret + } + } + + __declspec(naked) void PlayerMovement::PM_PlayerProneSpeedScaleStub() + { + __asm + { + push eax + mov eax, PlayerProneSpeedScale + fld dword ptr [eax + 0x10] // dvar_t.current.value + pop eax + + // Game's code + pop ecx + ret + } + } + + __declspec(naked) void PlayerMovement::PM_MoveScale_Noclip() + { + __asm + { + mov eax, CGNoclipScaler + fld dword ptr [eax + 0x10] // dvar_t.current.value + fmul dword ptr [esp + 0xC] + fstp dword ptr [esp + 0xC] + + push 0x56F43A + ret + } + } + + __declspec(naked) void PlayerMovement::PM_MoveScale_Ufo() + { + __asm + { + mov eax, CGUfoScaler + fld dword ptr [eax + 0x10] // dvar_t.current.value + fmul dword ptr [esp + 0xC] + fstp dword ptr [esp + 0xC] + + push 0x56F44D + ret + } + } + + __declspec(naked) void PlayerMovement::PM_MoveScale_Spectate() + { + __asm + { + mov eax, PlayerSpectateSpeedScale + fld dword ptr [eax + 0x10] // dvar_t.current.value + fmul dword ptr [esp + 0xC] + fstp dword ptr [esp + 0xC] + + push 0x56F462 + ret + } + } + + __declspec(naked) void PlayerMovement::PM_StepSlideMoveStub() + { + __asm + { + // Check the value of BGBounces + push ecx + push eax + + mov eax, BGBounces + mov ecx, dword ptr [eax + 0x10] + test ecx, ecx + + pop eax + pop ecx + + // Do not bounce if BGBounces is 0 + jle noBounce + + // Bounce + push 0x4B1B34 + retn + + noBounce: + // Original game code + cmp dword ptr [esp + 0x24], 0 + push 0x4B1B48 + retn + } + } + + // Double bounces + void PlayerMovement::Jump_ClearState_Hk(Game::playerState_s* ps) + { + if (BGBounces->current.integer != DOUBLE) + { + Game::Jump_ClearState(ps); + } + } + + __declspec(naked) void PlayerMovement::PM_ProjectVelocityStub() + { + __asm + { + push eax + mov eax, BGBouncesAllAngles + cmp byte ptr [eax + 0x10], 1 + pop eax + + je bounce + + fstp ST(0) + pop esi + add esp, 0x10 + ret + + bounce: + push 0x417B6F + ret + } + } + + Game::gentity_s* PlayerMovement::Weapon_RocketLauncher_Fire_Hk(Game::gentity_s* ent, unsigned int weaponIndex, + float spread, Game::weaponParms* wp, const float* gunVel, Game::lockonFireParms* lockParms, bool magicBullet) + { + auto* result = Game::Weapon_RocketLauncher_Fire(ent, weaponIndex, spread, wp, gunVel, lockParms, magicBullet); + + if (ent->client != nullptr && BGRocketJump.get() && + wp->weapDef->inventoryType != Game::WEAPINVENTORY_EXCLUSIVE) + { + const auto scale = BGRocketJumpScale.get(); + ent->client->ps.velocity[0] += (0.0f - wp->forward[0]) * scale; + ent->client->ps.velocity[1] += (0.0f - wp->forward[1]) * scale; + ent->client->ps.velocity[2] += (0.0f - wp->forward[2]) * scale; + } + + return result; + } + + int PlayerMovement::StuckInClient_Hk(Game::gentity_s* self) + { + if (BGPlayerEjection.get()) + { + return Utils::Hook::Call(0x402D30)(self); // StuckInClient + } + + return 0; + } + + void PlayerMovement::CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, + const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles) + { + if (BGPlayerCollision.get()) + { + Utils::Hook::Call + (0x478300) + (results, start, end, bounds, capsule, contents, origin, angles); // CM_TransformedCapsuleTrace + } + } + + const Game::dvar_t* PlayerMovement::Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, + float min, float max, unsigned __int16 /*flags*/, const char* description) + { + PlayerSpectateSpeedScale = Game::Dvar_RegisterFloat(dvarName, value, + min, max, Game::DVAR_CHEAT | Game::DVAR_CODINFO, description); + + return PlayerSpectateSpeedScale; + } + + void PlayerMovement::RegisterMovementDvars() + { + PlayerDuckedSpeedScale = Game::Dvar_RegisterFloat("player_duckedSpeedScale", + 0.65f, 0.0f, 5.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, + "The scale applied to the player speed when ducking"); + + PlayerProneSpeedScale = Game::Dvar_RegisterFloat("player_proneSpeedScale", + 0.15f, 0.0f, 5.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, + "The scale applied to the player speed when crawling"); + + // 3arc naming convention + CGUfoScaler = Game::Dvar_RegisterFloat("cg_ufo_scaler", + 6.0f, 0.001f, 1000.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, + "The speed at which ufo camera moves"); + + CGNoclipScaler = Game::Dvar_RegisterFloat("cg_noclip_scaler", + 3.0f, 0.001f, 1000.0f, Game::DVAR_CHEAT | Game::DVAR_CODINFO, + "The speed at which noclip camera moves"); + + BGBouncesAllAngles = Game::Dvar_RegisterBool("bg_bouncesAllAngles", + false, Game::DVAR_CODINFO, "Force bounce from all angles"); + + BGRocketJump = Dvar::Register("bg_rocketJump", + false, Game::DVAR_CODINFO, "Enable CoD4 rocket jumps"); + + BGRocketJumpScale = Dvar::Register("bg_rocketJumpScale", + 64.0f, 1.0f, std::numeric_limits::max(), Game::DVAR_CODINFO, + "The scale applied to the pushback force of a rocket"); + + BGPlayerEjection = Dvar::Register("bg_playerEjection", + true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); + + BGPlayerCollision = Dvar::Register("bg_playerCollision", + true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); + } + + PlayerMovement::PlayerMovement() + { + Scheduler::Once([] + { + static const char* bg_bouncesValues[] = + { + "disabled", + "enabled", + "double", + nullptr + }; + + BGBounces = Game::Dvar_RegisterEnum("bg_bounces", + bg_bouncesValues, DISABLED, Game::DVAR_CODINFO, "Bounce glitch settings"); + }, Scheduler::Pipeline::MAIN); + + // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. + Utils::Hook(0x448990, Dvar_RegisterSpectateSpeedScale, HOOK_CALL).install()->quick(); + + // PM_CmdScaleForStance + Utils::Hook(0x572D9B, PM_PlayerDuckedSpeedScaleStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x572DA5, PM_PlayerProneSpeedScaleStub, HOOK_JUMP).install()->quick(); + + // Hook PM_MoveScale so we can add custom speed scale for Ufo and Noclip + Utils::Hook(0x56F42C, PM_MoveScale_Noclip, HOOK_JUMP).install()->quick(); + Utils::Hook(0x56F43F, PM_MoveScale_Ufo, HOOK_JUMP).install()->quick(); + Utils::Hook(0x56F452, PM_MoveScale_Spectate, HOOK_JUMP).install()->quick(); + + // Bounce logic + Utils::Hook(0x4B1B2D, PM_StepSlideMoveStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x57383E, Jump_ClearState_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x417B66, PM_ProjectVelocityStub, HOOK_JUMP).install()->quick(); + + // Rocket jump + Utils::Hook(0x4A4F9B, Weapon_RocketLauncher_Fire_Hk, HOOK_CALL).install()->quick(); // FireWeapon + + // Hook StuckInClient & CM_TransformedCapsuleTrace + // so we can prevent intersecting players from being pushed away from each other + Utils::Hook(0x5D8153, StuckInClient_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x45A5BF, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity + Utils::Hook(0x5A0CAD, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity + + RegisterMovementDvars(); + } +} diff --git a/src/Components/Modules/Movement.hpp b/src/Components/Modules/PlayerMovement.hpp similarity index 59% rename from src/Components/Modules/Movement.hpp rename to src/Components/Modules/PlayerMovement.hpp index ddcd7bf2..c99ee59f 100644 --- a/src/Components/Modules/Movement.hpp +++ b/src/Components/Modules/PlayerMovement.hpp @@ -2,36 +2,37 @@ namespace Components { - class Movement : public Component + class PlayerMovement : public Component { public: - Movement(); + PlayerMovement(); private: enum BouncesSettings { DISABLED, ENABLED, DOUBLE }; - static Dvar::Var PlayerSpectateSpeedScale; - static Dvar::Var CGUfoScaler; - static Dvar::Var CGNoclipScaler; - static Dvar::Var BGBouncesAllAngles; static Dvar::Var BGRocketJump; static Dvar::Var BGRocketJumpScale; static Dvar::Var BGPlayerEjection; static Dvar::Var BGPlayerCollision; // Can't use Var class inside assembly stubs - static Game::dvar_t* BGBounces; - static Game::dvar_t* PlayerDuckedSpeedScale; - static Game::dvar_t* PlayerProneSpeedScale; + static const Game::dvar_t* CGNoclipScaler; + static const Game::dvar_t* CGUfoScaler; + static const Game::dvar_t* PlayerSpectateSpeedScale; + static const Game::dvar_t* BGBounces; + static const Game::dvar_t* BGBouncesAllAngles; + static const Game::dvar_t* PlayerDuckedSpeedScale; + static const Game::dvar_t* PlayerProneSpeedScale; static void PM_PlayerDuckedSpeedScaleStub(); static void PM_PlayerProneSpeedScaleStub(); - static float PM_MoveScale(Game::playerState_s* ps, float fmove, float rmove, float umove); - static void PM_MoveScaleStub(); + static void PM_MoveScale_Noclip(); + static void PM_MoveScale_Ufo(); + static void PM_MoveScale_Spectate(); // Bounce logic static void PM_StepSlideMoveStub(); - static void PM_ProjectVelocityStub(const float* velIn, const float* normal, float* velOut); + static void PM_ProjectVelocityStub(); static void Jump_ClearState_Hk(Game::playerState_s* ps); static Game::gentity_s* Weapon_RocketLauncher_Fire_Hk(Game::gentity_s* ent, unsigned int weaponIndex, float spread, Game::weaponParms* wp, const float* gunVel, Game::lockonFireParms* lockParms, bool a7); @@ -40,7 +41,7 @@ namespace Components static int StuckInClient_Hk(Game::gentity_s* self); static void CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles); - static Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description); + static const Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description); static void RegisterMovementDvars(); }; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 826fc6a8..df84c4f9 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -6681,9 +6681,9 @@ namespace Game typedef struct punctuation_s { - char *p; //punctuation character(s) - int n; //punctuation indication - struct punctuation_s *next; //next punctuation + char* p; //punctuation character(s) + int n; //punctuation indication + punctuation_s* next; //next punctuation } punctuation_t; #define MAX_TOKEN 1024 @@ -6691,16 +6691,16 @@ namespace Game typedef struct token_s { - char string[MAX_TOKEN]; //available token - int type; //last read token type - int subtype; //last read token sub type - unsigned long int intvalue; //integer value - long double floatvalue; //floating point value - char *whitespace_p; //start of white space before token - char *endwhitespace_p; //start of white space before token - int line; //line the token was on - int linescrossed; //lines crossed in white space - struct token_s *next; //next token in chain + char string[MAX_TOKEN]; //available token + int type; //last read token type + int subtype; //last read token sub type + unsigned long int intvalue; //integer value + long double floatvalue; //floating point value + char* whitespace_p; //start of white space before token + char* endwhitespace_p; //start of white space before token + int line; //line the token was on + int linescrossed; //lines crossed in white space + token_s* next; //next token in chain } token_t; typedef struct script_s From af6958bba12e0c4e8f81a0f48e7a60a5fbc1547b Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 24 Nov 2022 15:30:06 +0000 Subject: [PATCH 04/96] [Script]: Add IsSprinting & more --- src/Components/Modules/Bots.cpp | 10 +- src/Components/Modules/GSC/Script.cpp | 163 +++++++++++----------- src/Components/Modules/GSC/Script.hpp | 25 +++- src/Components/Modules/PlayerMovement.cpp | 22 ++- src/Components/Modules/PlayerMovement.hpp | 2 + src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 3 + src/Game/Structs.hpp | 34 ++--- 8 files changed, 157 insertions(+), 103 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 2b7132f8..2dfe290e 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -111,9 +111,15 @@ namespace Components } } - void Bots::GScr_isTestClient(Game::scr_entref_t entref) + void Bots::GScr_isTestClient(const Game::scr_entref_t entref) { - const auto* ent = Game::GetPlayerEntity(entref); + const auto* ent = Game::GetEntity(entref); + if (!ent->client) + { + Game::Scr_Error("isTestClient: entity must be a player entity"); + return; + } + Game::Scr_AddBool(Game::SV_IsTestClient(ent->s.number) != 0); } diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 9de55849..ae4e6723 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -15,8 +15,8 @@ namespace Components std::unordered_map Script::ReplacedFunctions; const char* Script::ReplacedPos = nullptr; - std::vector Script::ScriptMainHandles; - std::vector Script::ScriptInitHandles; + std::unordered_map Script::ScriptMainHandles; + std::unordered_map Script::ScriptInitHandles; void Script::ShowDeprecationWarning() { @@ -28,16 +28,16 @@ namespace Components void Script::FunctionError() { - const auto* funcName = Game::SL_ConvertToString(Script::FunctionName); + const auto* funcName = Game::SL_ConvertToString(FunctionName); Game::Scr_ShutdownAllocNode(); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n"); - Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: unknown function {} in {}\n", funcName, Script::ScriptName); + Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: unknown function {} in {}\n", funcName, ScriptName); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n"); - Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function {}\n{}\n\n", funcName, Script::ScriptName); + Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function {}\n{}\n\n", funcName, ScriptName); } __declspec(naked) void Script::StoreFunctionNameStub() @@ -45,7 +45,7 @@ namespace Components __asm { mov eax, [esp - 8h] - mov Script::FunctionName, ax + mov FunctionName, ax sub esp, 0Ch push 0 @@ -87,12 +87,12 @@ namespace Components void Script::StoreScriptName(const char* name) { - Script::ScriptNameStack.push_back(Script::ScriptName); - Script::ScriptName = name; + ScriptNameStack.push_back(ScriptName); + ScriptName = name; - if (!Utils::String::EndsWith(Script::ScriptName, ".gsc")) + if (!Utils::String::EndsWith(ScriptName, ".gsc")) { - Script::ScriptName.append(".gsc"); + ScriptName.append(".gsc"); } } @@ -105,7 +105,7 @@ namespace Components lea ecx, [esp + 30h] push ecx - call Script::StoreScriptName + call StoreScriptName add esp, 4h popad @@ -120,8 +120,8 @@ namespace Components void Script::RestoreScriptName() { - Script::ScriptName = Script::ScriptNameStack.back(); - Script::ScriptNameStack.pop_back(); + ScriptName = ScriptNameStack.back(); + ScriptNameStack.pop_back(); } __declspec(naked) void Script::RestoreScriptNameStub() @@ -129,7 +129,7 @@ namespace Components __asm { pushad - call Script::RestoreScriptName + call RestoreScriptName popad mov ds:1CDEAA8h, ebp @@ -205,17 +205,19 @@ namespace Components Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: {} ", msgbuf); - Script::PrintSourcePos(Script::ScriptName.data(), offset); + PrintSourcePos(ScriptName.data(), offset); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n\n"); - Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n{}\n{}\n(see console for actual details)\n", msgbuf, Script::ScriptName); + Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n{}\n{}\n(see console for actual details)\n", msgbuf, ScriptName); } void Script::Scr_LoadGameType_Stub() { - for (const auto& handle : Script::ScriptMainHandles) + for (const auto& handle : ScriptMainHandles) { - const auto id = Game::Scr_ExecThread(handle, 0); + Logger::Print("Executing '{}::main'\n", handle.first.data()); + + const auto id = Game::Scr_ExecThread(handle.second, 0); Game::Scr_FreeThread(static_cast(id)); } @@ -224,9 +226,11 @@ namespace Components void Script::Scr_StartupGameType_Stub() { - for (const auto& handle : Script::ScriptInitHandles) + for (const auto& handle : ScriptInitHandles) { - const auto id = Game::Scr_ExecThread(handle, 0); + Logger::Print("Executing '{}::init'\n", handle.first.data()); + + const auto id = Game::Scr_ExecThread(handle.second, 0); Game::Scr_FreeThread(static_cast(id)); } @@ -237,8 +241,8 @@ namespace Components void Script::GScr_LoadGameTypeScript_Stub() { // Clear handles (from previous GSC loading session) - Script::ScriptMainHandles.clear(); - Script::ScriptInitHandles.clear(); + ScriptMainHandles.clear(); + ScriptInitHandles.clear(); char path[MAX_PATH]{}; @@ -262,18 +266,17 @@ namespace Components } Logger::Print("Script {}.gsc loaded successfully.\n", path); - Logger::Debug("Finding script handle main or init..."); const auto initHandle = Game::Scr_GetFunctionHandle(path, "init"); if (initHandle != 0) { - Script::ScriptInitHandles.push_back(initHandle); + ScriptInitHandles.insert_or_assign(path, initHandle); } const auto mainHandle = Game::Scr_GetFunctionHandle(path, "main"); if (mainHandle != 0) { - Script::ScriptMainHandles.push_back(mainHandle); + ScriptMainHandles.insert_or_assign(path, mainHandle); } // Allow scripts with no handles @@ -285,7 +288,7 @@ namespace Components void Script::AddFunction(const std::string& name, Game::BuiltinFunction func, bool type) { - Script::ScriptFunction toAdd; + ScriptFunction toAdd; toAdd.actionFunc = func; toAdd.type = type; @@ -294,7 +297,7 @@ namespace Components void Script::AddMethod(const std::string& name, Game::BuiltinMethod func, bool type) { - Script::ScriptMethod toAdd; + ScriptMethod toAdd; toAdd.actionFunc = func; toAdd.type = type; @@ -306,7 +309,7 @@ namespace Components if (pName != nullptr) { // If no function was found let's call game's function - if (const auto itr = Script::CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != Script::CustomScrFunctions.end()) + if (const auto itr = CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != CustomScrFunctions.end()) { *type = itr->second.type; return itr->second.actionFunc; @@ -314,7 +317,7 @@ namespace Components } else { - for (const auto& [name, builtin] : Script::CustomScrFunctions) + for (const auto& [name, builtin] : CustomScrFunctions) { Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); } @@ -328,7 +331,7 @@ namespace Components if (pName != nullptr) { // If no method was found let's call game's function - if (const auto itr = Script::CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != Script::CustomScrMethods.end()) + if (const auto itr = CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != CustomScrMethods.end()) { *type = itr->second.type; return itr->second.actionFunc; @@ -336,7 +339,7 @@ namespace Components } else { - for (const auto& [name, builtin] : Script::CustomScrMethods) + for (const auto& [name, builtin] : CustomScrMethods) { Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); } @@ -347,7 +350,7 @@ namespace Components void Script::StoreScriptBaseProgramNum() { - Script::ScriptBaseProgramNum.insert_or_assign(Utils::Hook::Get(0x1CFEEF8), Script::ScriptName); + ScriptBaseProgramNum.insert_or_assign(Utils::Hook::Get(0x1CFEEF8), ScriptName); } void Script::Scr_PrintPrevCodePos(int scriptPos) @@ -355,7 +358,7 @@ namespace Components auto bestCodePos = -1, nextCodePos = -1, offset = -1; std::string file; - for (const auto& [key, value] : Script::ScriptBaseProgramNum) + for (const auto& [key, value] : ScriptBaseProgramNum) { const auto codePos = key; @@ -388,7 +391,7 @@ namespace Components __asm { push esi - call Script::Scr_PrintPrevCodePos + call Scr_PrintPrevCodePos add esp, 4h pop esi @@ -402,7 +405,7 @@ namespace Components { // execute our hook pushad - call Script::StoreScriptBaseProgramNum + call StoreScriptBaseProgramNum popad // execute overwritten code caused by the jump hook @@ -452,9 +455,9 @@ namespace Components void Script::GetReplacedPos(const char* pos) { - if (Script::ReplacedFunctions.contains(pos)) + if (ReplacedFunctions.contains(pos)) { - Script::ReplacedPos = Script::ReplacedFunctions[pos]; + ReplacedPos = ReplacedFunctions[pos]; } } @@ -466,12 +469,12 @@ namespace Components return; } - if (Script::ReplacedFunctions.contains(what)) + if (ReplacedFunctions.contains(what)) { Logger::Warning(Game::CON_CHANNEL_SCRIPT, "ReplacedFunctions already contains codePosValue for a function\n"); } - Script::ReplacedFunctions[what] = with; + ReplacedFunctions[what] = with; } __declspec(naked) void Script::VMExecuteInternalStub() @@ -481,12 +484,12 @@ namespace Components pushad push edx - call Script::GetReplacedPos + call GetReplacedPos pop edx popad - cmp Script::ReplacedPos, 0 + cmp ReplacedPos, 0 jne SetPos movzx eax, byte ptr [edx] @@ -509,8 +512,8 @@ namespace Components retn SetPos: - mov edx, Script::ReplacedPos - mov Script::ReplacedPos, 0 + mov edx, ReplacedPos + mov ReplacedPos, 0 movzx eax, byte ptr [edx] inc edx @@ -521,7 +524,7 @@ namespace Components Game::client_t* Script::GetClient(const Game::gentity_t* ent) { - assert(ent != nullptr); + assert(ent); if (ent->client == nullptr) { @@ -529,7 +532,7 @@ namespace Components return nullptr; } - if (ent->s.number >= *Game::svs_clientCount) + if (static_cast(ent->s.number) >= Game::MAX_CLIENTS) { Game::Scr_ObjectError(Utils::String::VA("Entity %i is out of bounds", ent->s.number)); return nullptr; @@ -540,7 +543,7 @@ namespace Components void Script::AddFunctions() { - Script::AddFunction("ReplaceFunc", [] // gsc: ReplaceFunc(, ) + AddFunction("ReplaceFunc", [] // gsc: ReplaceFunc(, ) { if (Game::Scr_GetNumParam() != 2) { @@ -548,14 +551,14 @@ namespace Components return; } - const auto what = Script::GetCodePosForParam(0); - const auto with = Script::GetCodePosForParam(1); + const auto what = GetCodePosForParam(0); + const auto with = GetCodePosForParam(1); - Script::SetReplacedPos(what, with); + SetReplacedPos(what, with); }); // System time - Script::AddFunction("GetSystemMilliseconds", [] // gsc: GetSystemMilliseconds() + AddFunction("GetSystemMilliseconds", [] // gsc: GetSystemMilliseconds() { SYSTEMTIME time; GetSystemTime(&time); @@ -564,7 +567,7 @@ namespace Components }); // Executes command to the console - Script::AddFunction("Exec", [] // gsc: Exec() + AddFunction("Exec", [] // gsc: Exec() { const auto str = Game::Scr_GetString(0); @@ -578,7 +581,7 @@ namespace Components }); // Allow printing to the console even when developer is 0 - Script::AddFunction("PrintConsole", [] // gsc: PrintConsole() + AddFunction("PrintConsole", [] // gsc: PrintConsole() { for (std::size_t i = 0; i < Game::Scr_GetNumParam(); ++i) { @@ -595,9 +598,9 @@ namespace Components }); // PlayerCmd_AreControlsFrozen GSC function from Black Ops 2 - Script::AddMethod("AreControlsFrozen", [](Game::scr_entref_t entref) // Usage: self AreControlsFrozen(); + AddMethod("AreControlsFrozen", [](Game::scr_entref_t entref) // Usage: self AreControlsFrozen(); { - const auto* ent = Game::GetPlayerEntity(entref); + const auto* ent = Scr_GetPlayerEntity(entref); Game::Scr_AddBool((ent->client->flags & Game::PLAYER_FLAG_FROZEN) != 0); }); @@ -605,34 +608,34 @@ namespace Components Script::Script() { - Utils::Hook(0x612DB0, Script::StoreFunctionNameStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x427E71, Script::RestoreScriptNameStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x427DBC, Script::StoreScriptNameStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x426C2D, Script::StoreScriptBaseProgramNumStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x42281B, Script::Scr_PrintPrevCodePosStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x612DB0, StoreFunctionNameStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x427E71, RestoreScriptNameStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x427DBC, StoreScriptNameStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x426C2D, StoreScriptBaseProgramNumStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x42281B, Scr_PrintPrevCodePosStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x61E3AD, Script::RuntimeError, HOOK_CALL).install()->quick(); - Utils::Hook(0x621976, Script::RuntimeError, HOOK_CALL).install()->quick(); - Utils::Hook(0x62246E, Script::RuntimeError, HOOK_CALL).install()->quick(); + Utils::Hook(0x61E3AD, RuntimeError, HOOK_CALL).install()->quick(); + Utils::Hook(0x621976, RuntimeError, HOOK_CALL).install()->quick(); + Utils::Hook(0x62246E, RuntimeError, HOOK_CALL).install()->quick(); // Skip check in GScr_CheckAllowedToSetPersistentData to prevent log spam in RuntimeError. // On IW5 the function is entirely nullsubbed - Utils::Hook::Set(0x5F8DBF, 0xEB); + Utils::Hook::Set(0x5F8DBF, 0xEB); - Utils::Hook(0x612E8D, Script::FunctionError, HOOK_CALL).install()->quick(); - Utils::Hook(0x612EA2, Script::FunctionError, HOOK_CALL).install()->quick(); - Utils::Hook(0x434260, Script::CompileError, HOOK_JUMP).install()->quick(); + Utils::Hook(0x612E8D, FunctionError, HOOK_CALL).install()->quick(); + Utils::Hook(0x612EA2, FunctionError, HOOK_CALL).install()->quick(); + Utils::Hook(0x434260, CompileError, HOOK_JUMP).install()->quick(); - Utils::Hook(0x48EFFE, Script::Scr_LoadGameType_Stub, HOOK_CALL).install()->quick(); - Utils::Hook(0x48F008, Script::Scr_StartupGameType_Stub, HOOK_CALL).install()->quick(); - Utils::Hook(0x45D44A, Script::GScr_LoadGameTypeScript_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x48EFFE, Scr_LoadGameType_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x48F008, Scr_StartupGameType_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x45D44A, GScr_LoadGameTypeScript_Stub, HOOK_CALL).install()->quick(); // Fetch custom functions - Utils::Hook(0x44E72E, Script::BuiltIn_GetFunctionStub, HOOK_CALL).install()->quick(); // Scr_GetFunction - Utils::Hook(0x4EC8DD, Script::BuiltIn_GetMethodStub, HOOK_CALL).install()->quick(); // Scr_GetMethod + Utils::Hook(0x44E72E, BuiltIn_GetFunctionStub, HOOK_CALL).install()->quick(); // Scr_GetFunction + Utils::Hook(0x4EC8DD, BuiltIn_GetMethodStub, HOOK_CALL).install()->quick(); // Scr_GetMethod - Utils::Hook(0x5F41A3, Script::SetExpFogStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5F41A3, SetExpFogStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x61E92E, VMExecuteInternalStub, HOOK_JUMP).install()->quick(); Utils::Hook::Nop(0x61E933, 1); Scheduler::Loop([] @@ -642,9 +645,9 @@ namespace Components const auto nowMs = Game::Sys_Milliseconds(); - if (Script::LastFrameTime != -1) + if (LastFrameTime != -1) { - const auto timeTaken = (nowMs - Script::LastFrameTime) * static_cast((*Game::com_timescale)->current.value); + const auto timeTaken = (nowMs - LastFrameTime) * static_cast((*Game::com_timescale)->current.value); if (timeTaken >= 500) { @@ -652,11 +655,11 @@ namespace Components } } - Script::LastFrameTime = nowMs; + LastFrameTime = nowMs; }, Scheduler::Pipeline::SERVER); #ifdef _DEBUG - Script::AddFunction("DebugBox", [] + AddFunction("DebugBox", [] { const auto* message = Game::Scr_GetString(0); @@ -666,14 +669,14 @@ namespace Components } MessageBoxA(nullptr, message, "DEBUG", MB_OK); - }, 1); + }, true); #endif - Script::AddFunctions(); + AddFunctions(); Events::OnVMShutdown([] { - Script::ReplacedFunctions.clear(); + ReplacedFunctions.clear(); }); } } diff --git a/src/Components/Modules/GSC/Script.hpp b/src/Components/Modules/GSC/Script.hpp index d80f952e..bf850257 100644 --- a/src/Components/Modules/GSC/Script.hpp +++ b/src/Components/Modules/GSC/Script.hpp @@ -16,6 +16,27 @@ namespace Components static void ShowDeprecationWarning(); + // Probably a macro 'originally' but this is fine + static Game::gentity_s* Scr_GetPlayerEntity(Game::scr_entref_t entref) + { + if (entref.classnum != 0) + { + Game::Scr_ObjectError("not an entity"); + return nullptr; + } + + assert(entref.entnum < Game::MAX_GENTITIES); + + auto* ent = &Game::g_entities[entref.entnum]; + if (ent->client == nullptr) + { + Game::Scr_ObjectError(Utils::String::VA("entity %i is not a player", entref.entnum)); + return nullptr; + } + + return ent; + } + private: struct ScriptFunction { @@ -38,8 +59,8 @@ namespace Components static std::unordered_map ScriptBaseProgramNum; static int LastFrameTime; - static std::vector ScriptMainHandles; - static std::vector ScriptInitHandles; + static std::unordered_map ScriptMainHandles; + static std::unordered_map ScriptInitHandles; static std::unordered_map ReplacedFunctions; static const char* ReplacedPos; diff --git a/src/Components/Modules/PlayerMovement.cpp b/src/Components/Modules/PlayerMovement.cpp index 9bf88dd7..05aeb8b5 100644 --- a/src/Components/Modules/PlayerMovement.cpp +++ b/src/Components/Modules/PlayerMovement.cpp @@ -1,4 +1,5 @@ #include +#include "GSC/Script.hpp" namespace Components { @@ -106,13 +107,13 @@ namespace Components // Bounce push 0x4B1B34 - retn + ret noBounce: // Original game code cmp dword ptr [esp + 0x24], 0 push 0x4B1B48 - retn + ret } } @@ -186,6 +187,18 @@ namespace Components } } + void PlayerMovement::GScr_IsSprinting(const Game::scr_entref_t entref) + { + const auto* client = Game::GetEntity(entref)->client; + if (!client) + { + Game::Scr_Error("IsSprinting can only be called on a player"); + return; + } + + Game::Scr_AddBool(Game::PM_IsSprinting(&client->ps)); + } + const Game::dvar_t* PlayerMovement::Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 /*flags*/, const char* description) { @@ -233,6 +246,9 @@ namespace Components PlayerMovement::PlayerMovement() { + AssertOffset(Game::playerState_s, eFlags, 0xB0); + AssertOffset(Game::playerState_s, pm_flags, 0xC); + Scheduler::Once([] { static const char* bg_bouncesValues[] = @@ -273,6 +289,8 @@ namespace Components Utils::Hook(0x45A5BF, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity Utils::Hook(0x5A0CAD, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity + Script::AddMethod("IsSprinting", GScr_IsSprinting); + RegisterMovementDvars(); } } diff --git a/src/Components/Modules/PlayerMovement.hpp b/src/Components/Modules/PlayerMovement.hpp index c99ee59f..5977ef44 100644 --- a/src/Components/Modules/PlayerMovement.hpp +++ b/src/Components/Modules/PlayerMovement.hpp @@ -41,6 +41,8 @@ namespace Components static int StuckInClient_Hk(Game::gentity_s* self); static void CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles); + static void GScr_IsSprinting(Game::scr_entref_t entref); + static const Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description); static void RegisterMovementDvars(); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 8a6e33c4..6f9c2c1d 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -233,6 +233,7 @@ namespace Game PM_Trace_t PM_Trace = PM_Trace_t(0x441F60); PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540); PM_UpdateLean_t PM_UpdateLean = PM_UpdateLean_t(0x43DED0); + PM_IsSprinting_t PM_IsSprinting = PM_IsSprinting_t(0x4B3830); IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6c52b815..1c12835c 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -524,6 +524,9 @@ namespace Game typedef void(*PM_UpdateLean_t)(playerState_s* ps, float msec, usercmd_s* cmd, void(*capsuleTrace)(trace_t*, const float*, const float*, const Bounds*, int, int)); extern PM_UpdateLean_t PM_UpdateLean; + typedef bool(*PM_IsSprinting_t)(const playerState_s* ps); + extern PM_IsSprinting_t PM_IsSprinting; + typedef void(*IN_RecenterMouse_t)(); extern IN_RecenterMouse_t IN_RecenterMouse; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index df84c4f9..c87612a2 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1679,23 +1679,23 @@ namespace Game enum usercmdButtonBits { - CMD_BUTTON_ATTACK = 0x1, - CMD_BUTTON_SPRINT = 0x2, - CMD_BUTTON_MELEE = 0x4, - CMD_BUTTON_ACTIVATE = 0x8, - CMD_BUTTON_RELOAD = 0x10, - CMD_BUTTON_USE_RELOAD = 0x20, - CMD_BUTTON_LEAN_LEFT = 0x40, - CMD_BUTTON_LEAN_RIGHT = 0x80, - CMD_BUTTON_PRONE = 0x100, - CMD_BUTTON_CROUCH = 0x200, - CMD_BUTTON_UP = 0x400, - CMD_BUTTON_ADS = 0x800, - CMD_BUTTON_DOWN = 0x1000, - CMD_BUTTON_BREATH = 0x2000, - CMD_BUTTON_FRAG = 0x4000, - CMD_BUTTON_OFFHAND_SECONDARY = 0x8000, - CMD_BUTTON_THROW = 0x80000 + CMD_BUTTON_ATTACK = 1 << 0, + CMD_BUTTON_SPRINT = 1 << 1, + CMD_BUTTON_MELEE = 1 << 2, + CMD_BUTTON_ACTIVATE = 1 << 3, + CMD_BUTTON_RELOAD = 1 << 4, + CMD_BUTTON_USE_RELOAD = 1 << 5, + CMD_BUTTON_LEAN_LEFT = 1 << 6, + CMD_BUTTON_LEAN_RIGHT = 1 << 7, + CMD_BUTTON_PRONE = 1 << 8, + CMD_BUTTON_CROUCH = 1 << 9, + CMD_BUTTON_UP = 1 << 10, + CMD_BUTTON_ADS = 1 << 11, + CMD_BUTTON_DOWN = 1 << 12, + CMD_BUTTON_BREATH = 1 << 13, + CMD_BUTTON_FRAG = 1 << 14, + CMD_BUTTON_OFFHAND_SECONDARY = 1 << 15, + CMD_BUTTON_THROW = 1 << 19, }; #pragma pack(push, 4) From 3d6e92768e040229543e2c0c332b55fc237553cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Nov 2022 17:03:08 +0000 Subject: [PATCH 05/96] Bump deps/mongoose from `db81c30` to `a4a5778` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `db81c30` to `a4a5778`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/db81c30d24df98031e41e33423a5eef0e89ba8c6...a4a577800132e70a2470a2aed01d6ff1d90d33ac) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index db81c30d..a4a57780 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit db81c30d24df98031e41e33423a5eef0e89ba8c6 +Subproject commit a4a577800132e70a2470a2aed01d6ff1d90d33ac From 3a48855698070ff1f86de8f2f1478b78c30042ae Mon Sep 17 00:00:00 2001 From: FutureRave Date: Fri, 25 Nov 2022 13:22:42 +0000 Subject: [PATCH 06/96] [LargeLocal]: CanUseServerLargeLocal --- src/Game/Engine/LargeLocal.cpp | 7 +++++-- src/Game/Engine/LargeLocal.hpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Game/Engine/LargeLocal.cpp b/src/Game/Engine/LargeLocal.cpp index 638584c5..24445074 100644 --- a/src/Game/Engine/LargeLocal.cpp +++ b/src/Game/Engine/LargeLocal.cpp @@ -3,8 +3,6 @@ namespace Game::Engine { - #define CanUseServerLargeLocal() (SV_GetServerThreadOwnsGame() ? Sys_IsServerThread() : Sys_IsRenderThread()) - LargeLocal::LargeLocal(int sizeParam) { assert(sizeParam); @@ -89,4 +87,9 @@ namespace Game::Engine return &g_largeLocalBuf[startIndex]; } + + int CanUseServerLargeLocal() + { + return SV_GetServerThreadOwnsGame() ? Sys_IsServerThread() : Sys_IsRenderThread(); + } } diff --git a/src/Game/Engine/LargeLocal.hpp b/src/Game/Engine/LargeLocal.hpp index 12fbfe9d..b1db09e6 100644 --- a/src/Game/Engine/LargeLocal.hpp +++ b/src/Game/Engine/LargeLocal.hpp @@ -26,4 +26,6 @@ namespace Game::Engine extern void LargeLocalEndRight(int startPos); extern void* LargeLocalGetBuf(int startPos, int size); + + extern int CanUseServerLargeLocal(); } From a4946981a1f60af11e475ce6aeb20fedb4e09721 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Fri, 25 Nov 2022 13:45:23 +0000 Subject: [PATCH 07/96] [LargeLocal]: Tabs vs Spaces --- src/Game/Engine/LargeLocal.hpp | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Game/Engine/LargeLocal.hpp b/src/Game/Engine/LargeLocal.hpp index b1db09e6..11e8af23 100644 --- a/src/Game/Engine/LargeLocal.hpp +++ b/src/Game/Engine/LargeLocal.hpp @@ -2,30 +2,30 @@ namespace Game::Engine { - class LargeLocal - { - public: - explicit LargeLocal(int sizeParam); - ~LargeLocal(); + class LargeLocal + { + public: + explicit LargeLocal(int sizeParam); + ~LargeLocal(); - LargeLocal(LargeLocal&&) = delete; - LargeLocal(const LargeLocal&) = delete; - LargeLocal& operator=(LargeLocal&&) = delete; - LargeLocal& operator=(const LargeLocal&) = delete; + LargeLocal(LargeLocal&&) = delete; + LargeLocal(const LargeLocal&) = delete; + LargeLocal& operator=(LargeLocal&&) = delete; + LargeLocal& operator=(const LargeLocal&) = delete; - [[nodiscard]] void* GetBuf() const; + [[nodiscard]] void* GetBuf() const; - private: - void PopBuf(); + private: + void PopBuf(); - int startPos; - int size; - }; + int startPos; + int size; + }; - extern void LargeLocalEnd(int startPos); - extern void LargeLocalEndRight(int startPos); + extern void LargeLocalEnd(int startPos); + extern void LargeLocalEndRight(int startPos); - extern void* LargeLocalGetBuf(int startPos, int size); + extern void* LargeLocalGetBuf(int startPos, int size); - extern int CanUseServerLargeLocal(); + extern int CanUseServerLargeLocal(); } From a0389ad39f4fc5c17c1af89aaa641e47c8569339 Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 25 Nov 2022 15:21:11 +0000 Subject: [PATCH 08/96] [General]: Use concurrency for build (#592) --- .github/workflows/build.yml | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 310c2aff..5cc63eee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,10 @@ on: - "*" types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Build binaries @@ -18,15 +22,7 @@ jobs: configuration: - Debug - Release - steps: - - name: Wait for previous workflows - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: softprops/turnstyle@v1 - with: - poll-interval-seconds: 10 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + steps: - name: Check out files uses: actions/checkout@v3 with: @@ -83,13 +79,6 @@ jobs: - name: Add known hosts run: ssh-keyscan -H ${{ secrets.XLABS_MASTER_SSH_ADDRESS }} >> ~/.ssh/known_hosts - - - name: Wait for previous workflows - uses: softprops/turnstyle@v1 - with: - poll-interval-seconds: 10 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # - name: Remove old data files # run: ssh ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }} rm -rf ${{ env.XLABS_MASTER_PATH }}/iw4x/data/* From d26e134579154ead6312bc60ac0fee2af7739bea Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 25 Nov 2022 15:33:51 +0000 Subject: [PATCH 09/96] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5cc63eee..a8f23722 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ on: - "*" types: [opened, synchronize, reopened] -concurrency: +concurrency: group: ${{ github.ref }} cancel-in-progress: true From 9f944c8ab153bee5338919da7bc2a92cac3239cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:02:41 +0000 Subject: [PATCH 10/96] Bump deps/mongoose from `a4a5778` to `a74d373` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `a4a5778` to `a74d373`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/a4a577800132e70a2470a2aed01d6ff1d90d33ac...a74d3737dc4ff18441fa092c9d13ec59f0701c11) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index a4a57780..a74d3737 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit a4a577800132e70a2470a2aed01d6ff1d90d33ac +Subproject commit a74d3737dc4ff18441fa092c9d13ec59f0701c11 From 4a677c5d08bad5d9c9dc8650d7923563b57e361e Mon Sep 17 00:00:00 2001 From: FutureRave Date: Fri, 25 Nov 2022 18:33:53 +0000 Subject: [PATCH 11/96] [ScriptStorage]: Allow users to load the storage file --- .../Modules/AssetInterfaces/IFont_s.cpp | 4 ++-- src/Components/Modules/ClientCommand.cpp | 18 +++++++------- src/Components/Modules/GSC/ScriptStorage.cpp | 21 ++++++++++++++++ src/Components/Modules/Logger.hpp | 6 +++++ src/Components/Modules/MapRotation.cpp | 2 +- src/Utils/String.cpp | 16 +++++++------ src/Utils/String.hpp | 24 +++++++++++++++---- 7 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IFont_s.cpp b/src/Components/Modules/AssetInterfaces/IFont_s.cpp index 0840b809..59c072a9 100644 --- a/src/Components/Modules/AssetInterfaces/IFont_s.cpp +++ b/src/Components/Modules/AssetInterfaces/IFont_s.cpp @@ -103,14 +103,14 @@ namespace Assets return; } - nlohmann::json fontDef = nlohmann::json::parse(fontDefFile.getBuffer()); + nlohmann::json fontDef; try { fontDef = nlohmann::json::parse(fontDefFile.getBuffer()); } catch (const nlohmann::json::parse_error& ex) { - Components::Logger::Error(Game::ERR_FATAL, "Json Parse Error: {}. Font {} is invalid", ex.what(), name); + Components::Logger::Error(Game::ERR_FATAL, "Json Parse Error: {}. Font {} is invalid\n", ex.what(), name); return; } diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index fd6c3cc6..8eaf76e2 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -37,9 +37,9 @@ namespace Components { const auto ent = &Game::g_entities[clientNum]; - if (ent->client == nullptr) + if (!ent->client) { - Logger::Debug("ClientCommand: client {} is not fully in game yet", clientNum); + Logger::Debug("ClientCommand: client {} is not fully connected", clientNum); return; } @@ -129,7 +129,7 @@ namespace Components Add("setviewpos", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) { - assert(ent != nullptr); + assert(ent); if (!CheatsOk(ent)) return; @@ -245,7 +245,7 @@ namespace Components Add("kill", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) { - assert(ent->client != nullptr); + assert(ent->client); assert(ent->client->sess.connected != Game::CON_DISCONNECTED); if (ent->client->sess.sessionState != Game::SESS_STATE_PLAYING || !CheatsOk(ent)) @@ -299,7 +299,7 @@ namespace Components duration = static_cast(std::floorf(input * 1000.0f + 0.5f)); } - assert(ent->client != nullptr); + assert(ent->client); constexpr auto visMode = Game::visionSetMode_t::VISIONSET_NORMAL; const auto* name = params->get(1); @@ -327,7 +327,7 @@ namespace Components duration = static_cast(std::floorf(input * 1000.0f + 0.5f)); } - assert(ent->client != nullptr); + assert(ent->client); constexpr auto visMode = Game::visionSetMode_t::VISIONSET_NIGHT; const auto* name = params->get(1); @@ -342,7 +342,7 @@ namespace Components Add("g_testCmd", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) { - assert(ent != nullptr); + assert(ent); ent->client->ps.stunTime = 1000 + Game::level->time; // 1000 is the default test stun time Logger::Debug("playerState_s.stunTime is {}", ent->client->ps.stunTime); @@ -464,9 +464,11 @@ namespace Components const auto* line = EntInfoLine(i); const auto lineLen = std::strlen(line); + assert(line); assert(lineLen); - Game::FS_Write(line, lineLen, h); + + Game::FS_Write(line, static_cast(lineLen), h); } Game::FS_FCloseFile(h); diff --git a/src/Components/Modules/GSC/ScriptStorage.cpp b/src/Components/Modules/GSC/ScriptStorage.cpp index 95879747..e89425d7 100644 --- a/src/Components/Modules/GSC/ScriptStorage.cpp +++ b/src/Components/Modules/GSC/ScriptStorage.cpp @@ -86,6 +86,27 @@ namespace Components FileSystem::FileWriter("scriptdata/scriptstorage.json").write(json.dump()); }); + Script::AddFunction("StorageLoad", [] // gsc: StorageLoad(); + { + FileSystem::File storageFile("scriptdata/scriptstorage.json"); + if (!storageFile.exists()) + { + return; + } + + const auto& buffer = storageFile.getBuffer(); + try + { + const nlohmann::json storageDef = nlohmann::json::parse(buffer); + const auto& newData = storageDef.get>(); + Data.insert(newData.begin(), newData.end()); + } + catch (const std::exception& ex) + { + Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}. File {} is invalid\n", ex.what(), storageFile.getName()); + } + }); + Script::AddFunction("StorageClear", [] // gsc: StorageClear(); { Data.clear(); diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index c794ecbd..359e473e 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -33,12 +33,14 @@ namespace Components template static void Print(std::string_view fmt, Args&&... args) { + (Utils::String::SanitizeFormatArgs(args), ...); PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(args...)); } template static void Print(int channel, std::string_view fmt, Args&&... args) { + (Utils::String::SanitizeFormatArgs(args), ...); PrintInternal(channel, fmt, std::make_format_args(args...)); } @@ -50,6 +52,7 @@ namespace Components template static void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args) { + (Utils::String::SanitizeFormatArgs(args), ...); ErrorInternal(error, fmt, std::make_format_args(args...)); } @@ -61,6 +64,7 @@ namespace Components template static void Warning(int channel, std::string_view fmt, Args&&... args) { + (Utils::String::SanitizeFormatArgs(args), ...); WarningInternal(channel, fmt, std::make_format_args(args...)); } @@ -72,6 +76,7 @@ namespace Components template static void PrintError(int channel, std::string_view fmt, Args&&... args) { + (Utils::String::SanitizeFormatArgs(args), ...); PrintErrorInternal(channel, fmt, std::make_format_args(args...)); } @@ -82,6 +87,7 @@ namespace Components Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] const Args&... args, [[maybe_unused]] const std::source_location& loc = std::source_location::current()) { #ifdef _DEBUG + (Utils::String::SanitizeFormatArgs(args), ...); DebugInternal(fmt, std::make_format_args(args...), loc); #endif } diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index 2c3da9cf..a9f01a8a 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -339,7 +339,7 @@ namespace Components } catch (const std::exception& ex) { - Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: parsing of 'normal' failed", ex.what()); + Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: parsing of 'normal' failed\n", ex.what()); return false; } diff --git a/src/Utils/String.cpp b/src/Utils/String.cpp index 502fe000..13e18025 100644 --- a/src/Utils/String.cpp +++ b/src/Utils/String.cpp @@ -5,7 +5,7 @@ namespace Utils::String { - const char *VA(const char *fmt, ...) + const char* VA(const char* fmt, ...) { static VAProvider<4, 100> globalProvider; static thread_local VAProvider<8, 256> provider; @@ -21,24 +21,26 @@ namespace Utils::String return result; } - std::string ToLower(std::string text) + std::string ToLower(const std::string& text) { - std::transform(text.begin(), text.end(), text.begin(), [](const unsigned char input) + std::string result; + std::ranges::transform(text, std::back_inserter(result), [](const unsigned char input) { return static_cast(std::tolower(input)); }); - return text; + return result; } - std::string ToUpper(std::string text) + std::string ToUpper(const std::string& text) { - std::transform(text.begin(), text.end(), text.begin(), [](const unsigned char input) + std::string result; + std::ranges::transform(text, std::back_inserter(result), [](const unsigned char input) { return static_cast(std::toupper(input)); }); - return text; + return result; } bool Compare(const std::string& lhs, const std::string& rhs) diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index 7ff19f5c..84c900fb 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -70,15 +70,31 @@ namespace Utils::String Entry stringPool[Buffers]; }; - const char *VA(const char *fmt, ...); + template // This should display a nice "null" instead of a number + static void SanitizeFormatArgs(Arg& arg) + { + if constexpr (std::is_same_v || std::is_same_v) + { + if (arg == nullptr) + { + arg = const_cast("nullptr"); + } + } + } + + const char* VA(const char* fmt, ...); + + std::string ToLower(const std::string& text); + std::string ToUpper(const std::string& text); - std::string ToLower(std::string text); - std::string ToUpper(std::string text); bool Compare(const std::string& lhs, const std::string& rhs); + std::vector Split(const std::string& str, char delim); void Replace(std::string& str, const std::string& from, const std::string& to); + bool StartsWith(const std::string& haystack, const std::string& needle); bool EndsWith(const std::string& haystack, const std::string& needle); + bool IsNumber(const std::string& str); std::string& LTrim(std::string& str); @@ -95,7 +111,7 @@ namespace Utils::String std::string XOR(std::string str, char value); - std::string EncodeBase64(const char* input, const unsigned long inputSize); + std::string EncodeBase64(const char* input, unsigned long inputSize); std::string EncodeBase64(const std::string& input); std::string EncodeBase128(const std::string& input); From e1e67a3ea9ecc3ffbacb4b8c5aebb79b083272dd Mon Sep 17 00:00:00 2001 From: FutureRave Date: Fri, 25 Nov 2022 22:37:49 +0000 Subject: [PATCH 12/96] [Memory]: Remove nullptr check before std::free --- src/Utils/Memory.cpp | 15 ++++++--------- src/Utils/Memory.hpp | 12 ++++++------ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Utils/Memory.cpp b/src/Utils/Memory.cpp index 9b3a0910..ceab4894 100644 --- a/src/Utils/Memory.cpp +++ b/src/Utils/Memory.cpp @@ -4,7 +4,7 @@ namespace Utils { Utils::Memory::Allocator Memory::MemAllocator; - void* Memory::AllocateAlign(size_t length, size_t alignment) + void* Memory::AllocateAlign(std::size_t length, std::size_t alignment) { auto* data = _aligned_malloc(length, alignment); assert(data); @@ -12,9 +12,9 @@ namespace Utils return data; } - void* Memory::Allocate(size_t length) + void* Memory::Allocate(std::size_t length) { - auto* data = calloc(length, 1); + auto* data = std::calloc(length, 1); assert(data); return data; } @@ -28,10 +28,7 @@ namespace Utils void Memory::Free(void* data) { - if (data) - { - ::free(data); - } + std::free(data); } void Memory::Free(const void* data) @@ -53,11 +50,11 @@ namespace Utils } // Complementary function for memset, which checks if memory is filled with a char - bool Memory::IsSet(void* mem, char chr, size_t length) + bool Memory::IsSet(void* mem, char chr, std::size_t length) { auto* memArr = static_cast(mem); - for (size_t i = 0; i < length; ++i) + for (std::size_t i = 0; i < length; ++i) { if (memArr[i] != chr) { diff --git a/src/Utils/Memory.hpp b/src/Utils/Memory.hpp index 7d3fc150..3e85c756 100644 --- a/src/Utils/Memory.hpp +++ b/src/Utils/Memory.hpp @@ -73,7 +73,7 @@ namespace Utils this->refMemory[memory] = callback; } - void* allocate(size_t length) + void* allocate(std::size_t length) { std::lock_guard _(this->mutex); @@ -87,7 +87,7 @@ namespace Utils return this->allocateArray(1); } - template T* allocateArray(size_t count = 1) + template T* allocateArray(std::size_t count = 1) { return static_cast(this->allocate(count * sizeof(T))); } @@ -133,13 +133,13 @@ namespace Utils std::unordered_map refMemory; }; - static void* AllocateAlign(size_t length, size_t alignment); - static void* Allocate(size_t length); + static void* AllocateAlign(std::size_t length, std::size_t alignment); + static void* Allocate(std::size_t length); template static T* Allocate() { return AllocateArray(1); } - template static T* AllocateArray(size_t count = 1) + template static T* AllocateArray(std::size_t count = 1) { return static_cast(Allocate(count * sizeof(T))); } @@ -159,7 +159,7 @@ namespace Utils static void FreeAlign(void* data); static void FreeAlign(const void* data); - static bool IsSet(void* mem, char chr, size_t length); + static bool IsSet(void* mem, char chr, std::size_t length); static bool IsBadReadPtr(const void* ptr); static bool IsBadCodePtr(const void* ptr); From 720ee9730cd6f28fe8d11b3edc52cb4f25bdde87 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Fri, 25 Nov 2022 23:28:20 +0000 Subject: [PATCH 13/96] [Script]: Fix asm --- src/Game/Script.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Game/Script.cpp b/src/Game/Script.cpp index b7bb7457..0966d6a3 100644 --- a/src/Game/Script.cpp +++ b/src/Game/Script.cpp @@ -107,18 +107,20 @@ namespace Game } } - void Scr_NotifyId(unsigned int id, unsigned __int16 stringValue, unsigned int paramcount) + __declspec(naked) void Scr_NotifyId(unsigned int /*id*/, unsigned __int16 /*stringValue*/, unsigned int /*paramcount*/) { static DWORD Scr_NotifyId_t = 0x61E670; __asm { pushad - mov eax, paramcount - push stringValue - push id + + mov eax, [esp + 0x20 + 0xC] // paramcount + push [esp + 0x20 + 0x8] // stringValue + push [esp + 0x20 + 0x8] // id call Scr_NotifyId_t - add esp, 8h + add esp, 0x8 + popad } } From 2d71174ed4f529d7aeb2d61e35db2554b0cf1578 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 26 Nov 2022 15:50:33 +0000 Subject: [PATCH 14/96] [Threading]: Removing this was not a good idea --- src/Components/Loader.cpp | 1 + src/Components/Loader.hpp | 1 + src/Components/Modules/QuickPatch.cpp | 3 - src/Components/Modules/Threading.cpp | 173 ++++++++++++++++++++++++++ src/Components/Modules/Threading.hpp | 14 +++ src/Game/Server.cpp | 1 + src/Game/Server.hpp | 1 + 7 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 src/Components/Modules/Threading.cpp create mode 100644 src/Components/Modules/Threading.hpp diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 783e289c..baceb617 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -74,6 +74,7 @@ namespace Components Loader::Register(new Gametypes()); Loader::Register(new Materials()); Loader::Register(new Scheduler()); + Loader::Register(new Threading()); Loader::Register(new CardTitles()); Loader::Register(new FileSystem()); Loader::Register(new ModelSurfs()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 981b55c2..141e6b63 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -106,6 +106,7 @@ namespace Components #include "Modules/Gametypes.hpp" #include "Modules/Materials.hpp" #include "Modules/Singleton.hpp" +#include "Modules/Threading.hpp" #include "Modules/CardTitles.hpp" #include "Modules/FileSystem.hpp" #include "Modules/ModelSurfs.hpp" diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 22076555..fc8889e4 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -332,9 +332,6 @@ namespace Components // Fix crash as nullptr goes unchecked Utils::Hook(0x437CAD, QuickPatch::SND_GetAliasOffset_Stub, HOOK_JUMP).install()->quick(); - // Make VA thread safe - Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick(); - // protocol version (workaround for hacks) Utils::Hook::Set(0x4FB501, PROTOCOL); diff --git a/src/Components/Modules/Threading.cpp b/src/Components/Modules/Threading.cpp new file mode 100644 index 00000000..eb481c71 --- /dev/null +++ b/src/Components/Modules/Threading.cpp @@ -0,0 +1,173 @@ +#include + +namespace Components +{ + namespace FrameTime + { + void NetSleep(int mSec) + { + if (mSec < 0) mSec = 0; + + fd_set fdr; + FD_ZERO(&fdr); + + auto highestFd = INVALID_SOCKET; + if (*Game::ip_socket != INVALID_SOCKET) + { + FD_SET(*Game::ip_socket, &fdr); + highestFd = *Game::ip_socket; + } + + if (highestFd == INVALID_SOCKET) + { + // windows ain't happy when select is called without valid FDs + std::this_thread::sleep_for(std::chrono::milliseconds(mSec)); + return; + } + + timeval timeout; + timeout.tv_sec = mSec / 1000; + timeout.tv_usec = (mSec % 1000) * 1000; + + const auto retVal = ::select(highestFd + 1, &fdr, nullptr, nullptr, &timeout); + + if (retVal == SOCKET_ERROR) + { + Logger::Warning(Game::CON_CHANNEL_SYSTEM, "WinAPI: select failed: {}\n", Game::NET_ErrorString()); + } + else if (retVal > 0) + { + if (Dedicated::IsRunning()) + { + Game::Com_ServerPacketEvent(); + } + else + { + Game::Com_ClientPacketEvent(); + } + } + } + + void SVFrameWaitFunc() + { + if (*Game::sv_timeResidual < 50) + { + NetSleep(50 - *Game::sv_timeResidual); + } + } + + void __declspec(naked) SVFrameWaitStub() + { + __asm + { + pushad + call SVFrameWaitFunc + popad + + push 4CD420h + ret + } + } + + int ComTimeVal(int minMsec) + { + const auto timeVal = Game::Sys_Milliseconds() - *Game::com_frameTime; + return (timeVal >= minMsec ? 0 : minMsec - timeVal); + } + + int ComFrameWait(int minMsec) + { + do + { + const auto timeVal = ComTimeVal(minMsec); + NetSleep(timeVal < 1 ? 0 : timeVal - 1); + } while (ComTimeVal(minMsec)); + + const auto lastTime = *Game::com_frameTime; + Game::Com_EventLoop(); + *Game::com_frameTime = Game::Sys_Milliseconds(); + + return *Game::com_frameTime - lastTime; + } + + void __declspec(naked) ComFrameWaitStub() + { + __asm + { + push ecx + pushad + + push edi + call ComFrameWait + add esp, 4 + + mov [esp + 20h], eax + popad + pop eax + mov ecx, eax + + mov edx, 1AD7934h // com_sv_running + cmp byte ptr [edx + 10h], 0 + + push 47DDC1h + ret + } + } + } + + __declspec(naked) void Threading::FrameEpilogueStub() + { + __asm + { + pop edi + pop esi + pop ebx + mov esp, ebp + pop ebp + retn + } + } + + __declspec(naked) void Threading::PacketEventStub() + { + __asm + { + mov eax, 49F0B0h + call eax + + mov eax, 458160h + jmp eax + } + } + + Threading::Threading() + { + // remove starting of server thread from Com_Init_Try_Block_Function + Utils::Hook::Nop(0x60BEC0, 5); + + // make server thread function jump to per-frame stuff + Utils::Hook(0x627049, 0x6271CE, HOOK_JUMP).install()->quick(); + + // make SV_WaitServer insta-return + Utils::Hook::Set(0x4256F0, 0xC3); + + // dvar setting function, unknown stuff related to server thread sync + Utils::Hook::Set(0x647781, 0xEB); + + Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick(); + Utils::Hook(0x43D1C7, PacketEventStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x6272E3, FrameEpilogueStub, HOOK_JUMP).install()->quick(); + + // make VA thread safe + Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick(); + + if (Dedicated::IsEnabled()) + { + Utils::Hook(0x4BAAAD, FrameTime::SVFrameWaitStub, HOOK_CALL).install()->quick(); + } + else + { + Utils::Hook(0x47DD80, FrameTime::ComFrameWaitStub, HOOK_JUMP).install()->quick(); + } + } +} diff --git a/src/Components/Modules/Threading.hpp b/src/Components/Modules/Threading.hpp new file mode 100644 index 00000000..2e4354d3 --- /dev/null +++ b/src/Components/Modules/Threading.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace Components +{ + class Threading : public Component + { + public: + Threading(); + + private: + static void FrameEpilogueStub(); + static void PacketEventStub(); + }; +} diff --git a/src/Game/Server.cpp b/src/Game/Server.cpp index 9789f273..46bb18d8 100644 --- a/src/Game/Server.cpp +++ b/src/Game/Server.cpp @@ -20,6 +20,7 @@ namespace Game SV_FindClientByAddress_t SV_FindClientByAddress = SV_FindClientByAddress_t(0x44F450); int* svs_time = reinterpret_cast(0x31D9384); + int* sv_timeResidual = reinterpret_cast(0x2089E14); int* sv_serverId_value = reinterpret_cast(0x2089DC0); int* svs_clientCount = reinterpret_cast(0x31D938C); client_t* svs_clients = reinterpret_cast(0x31D9390); diff --git a/src/Game/Server.hpp b/src/Game/Server.hpp index dbd9d659..52ecd6df 100644 --- a/src/Game/Server.hpp +++ b/src/Game/Server.hpp @@ -53,6 +53,7 @@ namespace Game constexpr auto MAX_STATPACKETS = 7; extern int* svs_time; + extern int* sv_timeResidual; extern int* sv_serverId_value; extern int* svs_clientCount; extern client_t* svs_clients; From 44098c51cd003fd2396177723b89a8dbeb754009 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 26 Nov 2022 17:38:34 +0000 Subject: [PATCH 15/96] [General]: Remove unnecessary global header (#600) * [General]: Remove unnecessary global header * [ServerList]: Fix comp --- src/Components/Modules/Branding.cpp | 16 +++++++++++++ src/Components/Modules/Console.cpp | 8 ++++++- src/Components/Modules/Exception.cpp | 2 ++ src/Components/Modules/News.cpp | 2 ++ src/Components/Modules/Party.cpp | 32 +++++++++++++++----------- src/Components/Modules/QuickPatch.cpp | 14 ----------- src/Components/Modules/ServerInfo.cpp | 9 +++++--- src/Components/Modules/ServerList.cpp | 5 ++-- src/Components/Modules/Singleton.cpp | 10 ++++---- src/Components/Modules/ZoneBuilder.cpp | 3 +++ src/Resource.rc | 5 ++-- src/STDInclude.hpp | 3 --- 12 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index 6f1c3fbf..63d766e2 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -1,5 +1,7 @@ #include +#include + namespace Components { Dvar::Var Branding::CGDrawVersion; @@ -125,5 +127,19 @@ namespace Components // Hook CG_DrawFullScreenDebugOverlays so we may render the version when it's appropriate Utils::Hook(0x5AC975, Branding::CG_DrawVersion_Hk, HOOK_CALL).install()->quick(); + + // Console title + if (ZoneBuilder::IsEnabled()) + { + Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): ZoneBuilder"); + } + else if (Dedicated::IsEnabled()) + { + Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Dedicated"); + } + else + { + Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Console"); + } } } diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index 7f501d0b..1a4e105a 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -1,5 +1,11 @@ #include -#undef MOUSE_MOVED + +#include + +#ifdef MOUSE_MOVED + #undef MOUSE_MOVED +#endif + #include #define REMOVE_HEADERBAR 1 diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index 4234b081..f1d84b3d 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -1,5 +1,7 @@ #include +#include + namespace Components { Utils::Hook Exception::SetFilterHook; diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 6816d8e2..9d70ef35 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -1,5 +1,7 @@ #include +#include + #define NEWS_MOTD_DEFAULT "Welcome to IW4x Multiplayer!" namespace Components diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index fbf30e6c..a43d1d2e 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -1,5 +1,7 @@ #include +#include + namespace Components { Party::JoinContainer Party::Container; @@ -313,13 +315,15 @@ namespace Components // Basic info handler Network::OnClientPacket("getInfo", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { - int botCount = 0; - int clientCount = 0; - int maxclientCount = *Game::svs_clientCount; + auto botCount = 0; + auto clientCount = 0; + auto maxClientCount = *Game::svs_clientCount; + const auto securityLevel = Dvar::Var("sv_securityLevel").get(); + const auto password = Dvar::Var("g_password").get(); - if (maxclientCount) + if (maxClientCount) { - for (int i = 0; i < maxclientCount; ++i) + for (int i = 0; i < maxClientCount; ++i) { if (Game::svs_clients[i].header.state >= Game::CS_CONNECTED) { @@ -330,7 +334,7 @@ namespace Components } else { - maxclientCount = Dvar::Var("party_maxplayers").get(); + maxClientCount = Dvar::Var("party_maxplayers").get(); clientCount = Game::PartyHost_CountMembers(reinterpret_cast(0x1081C00)); } @@ -341,16 +345,16 @@ namespace Components info.set("gametype", (*Game::sv_gametype)->current.string); info.set("fs_game", (*Game::fs_gameDirVar)->current.string); info.set("xuid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().bits)); - info.set("clients", Utils::String::VA("%i", clientCount)); - info.set("bots", Utils::String::VA("%i", botCount)); - info.set("sv_maxclients", Utils::String::VA("%i", maxclientCount)); - info.set("protocol", Utils::String::VA("%i", PROTOCOL)); + info.set("clients", std::to_string(clientCount)); + info.set("bots", std::to_string(botCount)); + info.set("sv_maxclients", std::to_string(maxClientCount)); + info.set("protocol", std::to_string(PROTOCOL)); info.set("shortversion", SHORTVERSION); - info.set("checksum", Utils::String::VA("%d", Game::Sys_Milliseconds())); - info.set("mapname", Dvar::Var("mapname").get()); - info.set("isPrivate", (Dvar::Var("g_password").get().size() ? "1" : "0")); + info.set("checksum", std::to_string(Game::Sys_Milliseconds())); + info.set("mapname", Dvar::Var("mapname").get()); + info.set("isPrivate", password.empty() ? "1" : "0"); info.set("hc", (Dvar::Var("g_hardcore").get() ? "1" : "0")); - info.set("securityLevel", Utils::String::VA("%i", Dvar::Var("sv_securityLevel").get())); + info.set("securityLevel", std::to_string(securityLevel)); info.set("sv_running", (Dedicated::IsRunning() ? "1" : "0")); info.set("aimAssist", (Gamepad::sv_allowAimAssist.get() ? "1" : "0")); info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0")); diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index fc8889e4..b68e267e 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -367,20 +367,6 @@ namespace Components // fs_basegame Utils::Hook::Set(0x6431D1, BASEGAME); - // console title - if (ZoneBuilder::IsEnabled()) - { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): ZoneBuilder"); - } - else if (Dedicated::IsEnabled()) - { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Dedicated"); - } - else - { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Console"); - } - // window title Utils::Hook::Set(0x5076A0, "IW4x: Multiplayer"); diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index ff90f9b4..e161ab5c 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -1,5 +1,7 @@ #include +#include + namespace Components { ServerInfo::Container ServerInfo::PlayerContainer; @@ -129,6 +131,7 @@ namespace Components Utils::InfoString ServerInfo::GetInfo() { auto maxClientCount = *Game::svs_clientCount; + const auto password = Dvar::Var("g_password").get(); if (!maxClientCount) { @@ -137,12 +140,12 @@ namespace Components Utils::InfoString info(Game::Dvar_InfoString_Big(Game::DVAR_SERVERINFO)); info.set("gamename", "IW4"); - info.set("sv_maxclients", Utils::String::VA("%i", maxClientCount)); - info.set("protocol", Utils::String::VA("%i", PROTOCOL)); + info.set("sv_maxclients", std::to_string(maxClientCount)); + info.set("protocol", std::to_string(PROTOCOL)); info.set("shortversion", SHORTVERSION); info.set("version", (*Game::version)->current.string); info.set("mapname", (*Game::sv_mapname)->current.string); - info.set("isPrivate", (Dvar::Var("g_password").get().empty() ? "0" : "1")); + info.set("isPrivate", password.empty() ? "0" : "1"); info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds())))); info.set("aimAssist", (Gamepad::sv_allowAimAssist.get() ? "1" : "0")); info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0")); diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 18ef579f..6f06ef46 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -1,5 +1,7 @@ #include +#include + namespace Components { bool ServerList::SortAsc = true; @@ -574,8 +576,7 @@ namespace Components } } - if (info.get("gamename") == "IW4" - && server.matchType + if (info.get("gamename") == "IW4"s && server.matchType #if !defined(DEBUG) && defined(VERSION_FILTER) && ServerList::CompareVersion(server.shortversion, SHORTVERSION) #endif diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index 148bc825..d0b0cefd 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -1,19 +1,21 @@ #include +#include + namespace Components { bool Singleton::FirstInstance = true; bool Singleton::IsFirstInstance() { - return Singleton::FirstInstance; + return FirstInstance; } Singleton::Singleton() { if (Flags::HasFlag("version")) { - printf("IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); + printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); printf("%d\n", REVISION); ExitProcess(0); } @@ -22,9 +24,9 @@ namespace Components if (Loader::IsPerformingUnitTests() || Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; - Singleton::FirstInstance = (CreateMutexA(nullptr, FALSE, "iw4x_mutex") && GetLastError() != ERROR_ALREADY_EXISTS); + FirstInstance = (CreateMutexA(nullptr, FALSE, "iw4x_mutex") && GetLastError() != ERROR_ALREADY_EXISTS); - if (!Singleton::FirstInstance && !ConnectProtocol::Used() && MessageBoxA(nullptr, "Do you want to start another instance?\nNot all features will be available!", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) + if (!FirstInstance && !ConnectProtocol::Used() && MessageBoxA(nullptr, "Do you want to start another instance?\nNot all features will be available!", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) { ExitProcess(0); } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 8b55e5f8..2b64618d 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -1,4 +1,7 @@ #include + +#include + #include "AssetInterfaces/ILocalizeEntry.hpp" namespace Components diff --git a/src/Resource.rc b/src/Resource.rc index b04f455f..cda9e955 100644 --- a/src/Resource.rc +++ b/src/Resource.rc @@ -2,7 +2,8 @@ // #pragma code_page(65001) -#include "STDInclude.hpp" +#include +#include #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// @@ -70,7 +71,7 @@ BEGIN #endif VALUE "FileVersion", SHORTVERSION VALUE "InternalName", "iw4x" - VALUE "LegalCopyright", "Copyright 2017 The IW4x Team. All rights reserved." + VALUE "LegalCopyright", "Copyright 2022 The IW4x Team. All rights reserved." VALUE "OriginalFilename", "iw4x.dll" VALUE "ProductName", "IW4x" VALUE "ProductVersion", SHORTVERSION diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index e1f4d8cc..2e994240 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -1,8 +1,5 @@ #pragma once -// Version number -#include "version.h" - #ifndef RC_INVOKED #define VC_EXTRALEAN From 365b287013a3ce011f255eb74e4e53a59891a925 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 26 Nov 2022 18:07:49 +0000 Subject: [PATCH 16/96] [Script]: Fix asm stub again --- src/Game/Script.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Game/Script.cpp b/src/Game/Script.cpp index 0966d6a3..7b68bb61 100644 --- a/src/Game/Script.cpp +++ b/src/Game/Script.cpp @@ -122,6 +122,7 @@ namespace Game add esp, 0x8 popad + ret } } } From 5f14a7396883ec63c4f9e00629b1231882ded064 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 26 Nov 2022 19:18:41 +0000 Subject: [PATCH 17/96] [Party]: Fix bug --- src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/Voice.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index a43d1d2e..34128c5d 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -352,7 +352,7 @@ namespace Components info.set("shortversion", SHORTVERSION); info.set("checksum", std::to_string(Game::Sys_Milliseconds())); info.set("mapname", Dvar::Var("mapname").get()); - info.set("isPrivate", password.empty() ? "1" : "0"); + info.set("isPrivate", password.empty() ? "0" : "1"); info.set("hc", (Dvar::Var("g_hardcore").get() ? "1" : "0")); info.set("securityLevel", std::to_string(securityLevel)); info.set("sv_running", (Dedicated::IsRunning() ? "1" : "0")); diff --git a/src/Components/Modules/Voice.cpp b/src/Components/Modules/Voice.cpp index edc84cca..5308ebba 100644 --- a/src/Components/Modules/Voice.cpp +++ b/src/Components/Modules/Voice.cpp @@ -40,8 +40,8 @@ namespace Components Game::msg_t msg{}; const auto clientNum = client - Game::svs_clients; - const Game::Engine::LargeLocal msg_buf_large_local(0x10000); - auto* msg_buf = static_cast(msg_buf_large_local.GetBuf()); + const auto msg_buf_large = std::make_unique(0x10000); + auto* msg_buf = msg_buf_large.get(); assert(VoicePacketCount[clientNum] >= 0); From 0b2cca4cb64bb17d10845b6fb233b29c262c9252 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 26 Nov 2022 19:28:49 +0000 Subject: [PATCH 18/96] [Download]: Update Download.cpp --- src/Components/Modules/Download.cpp | 4 ---- src/Components/Modules/GSC/Script.cpp | 8 -------- src/Components/Modules/GSC/Script.hpp | 2 -- src/Components/Modules/Voice.cpp | 1 - 4 files changed, 15 deletions(-) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 9283045e..9e3d0bc9 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -1,5 +1,4 @@ #include -#include "GSC/Script.hpp" #include @@ -715,9 +714,6 @@ namespace Components Dvar::Register("sv_wwwDownload", false, Game::DVAR_NONE, "Set to true to enable downloading maps/mods from an external server."); Dvar::Register("sv_wwwBaseUrl", "", Game::DVAR_NONE, "Set to the base url for the external map download."); }, Scheduler::Pipeline::MAIN); - - Script::AddFunction("HttpGet", Script::ShowDeprecationWarning); - Script::AddFunction("HttpCancel", Script::ShowDeprecationWarning); } Download::~Download() diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index ae4e6723..45bbc432 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -18,14 +18,6 @@ namespace Components std::unordered_map Script::ScriptMainHandles; std::unordered_map Script::ScriptInitHandles; - void Script::ShowDeprecationWarning() - { - Toast::Show("cardicon_gumby", "WARNING!", "You are using deprecated HttpGet/HttpCancel GSC function.", 2048); - Logger::Print(Game::CON_CHANNEL_SCRIPT, "*** DEPRECATION WARNING ***\n"); - Logger::PrintError(Game::CON_CHANNEL_ERROR, "Attempted to execute deprecated built-in HttpGet/HttpCancel! These functions have been deemed unsafe and are scheduled for removal. Please update your mod!\n"); - Logger::Print(Game::CON_CHANNEL_SCRIPT, "***************************\n"); - } - void Script::FunctionError() { const auto* funcName = Game::SL_ConvertToString(FunctionName); diff --git a/src/Components/Modules/GSC/Script.hpp b/src/Components/Modules/GSC/Script.hpp index bf850257..8c4742ba 100644 --- a/src/Components/Modules/GSC/Script.hpp +++ b/src/Components/Modules/GSC/Script.hpp @@ -14,8 +14,6 @@ namespace Components static const char* GetCodePosForParam(int index); - static void ShowDeprecationWarning(); - // Probably a macro 'originally' but this is fine static Game::gentity_s* Scr_GetPlayerEntity(Game::scr_entref_t entref) { diff --git a/src/Components/Modules/Voice.cpp b/src/Components/Modules/Voice.cpp index 5308ebba..1629656f 100644 --- a/src/Components/Modules/Voice.cpp +++ b/src/Components/Modules/Voice.cpp @@ -1,5 +1,4 @@ #include -#include "Game/Engine/LargeLocal.hpp" namespace Components { From 49d5e8437226408d44e53364514ac4b3051fb0ed Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 27 Nov 2022 19:20:07 +0000 Subject: [PATCH 19/96] [Script]: Add method to clear text in HudElems (#604) --- .../Modules/AssetInterfaces/IXAnimParts.cpp | 4 +-- .../Modules/AssetInterfaces/IXModel.cpp | 2 +- src/Components/Modules/Bots.cpp | 4 +-- src/Components/Modules/Chat.cpp | 2 +- src/Components/Modules/FileSystem.cpp | 6 ++-- src/Components/Modules/GSC/GSC.cpp | 2 ++ src/Components/Modules/GSC/IO.cpp | 2 +- src/Components/Modules/GSC/ScriptPatches.cpp | 36 +++++++++++++++++++ src/Components/Modules/GSC/ScriptPatches.hpp | 13 +++++++ src/Components/Modules/ZoneBuilder.cpp | 2 +- src/Game/Functions.cpp | 5 --- src/Game/Functions.hpp | 12 ------- src/Game/Game.cpp | 4 +++ src/Game/Game.hpp | 5 +++ src/Game/Script.cpp | 14 ++++++++ src/Game/Script.hpp | 33 +++++++++++++++-- src/Game/Server.cpp | 4 +++ src/Game/Server.hpp | 6 ++++ src/Game/Structs.hpp | 9 +++++ 19 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 src/Components/Modules/GSC/ScriptPatches.cpp create mode 100644 src/Components/Modules/GSC/ScriptPatches.hpp diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp index 736b0a40..e3e67e6b 100644 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp +++ b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp @@ -39,7 +39,7 @@ namespace Assets xanim->names = builder->getAllocator()->allocateArray(xanim->boneCount[Game::PART_TYPE_ALL]); for (int i = 0; i < xanim->boneCount[Game::PART_TYPE_ALL]; ++i) { - xanim->names[i] = Game::SL_GetString(reader.readCString(), 0); + xanim->names[i] = static_cast(Game::SL_GetString(reader.readCString(), 0)); } } @@ -49,7 +49,7 @@ namespace Assets for (int i = 0; i < xanim->notifyCount; ++i) { - xanim->notify[i].name = Game::SL_GetString(reader.readCString(), 0); + xanim->notify[i].name = static_cast(Game::SL_GetString(reader.readCString(), 0)); } } diff --git a/src/Components/Modules/AssetInterfaces/IXModel.cpp b/src/Components/Modules/AssetInterfaces/IXModel.cpp index c10751fd..60dea742 100644 --- a/src/Components/Modules/AssetInterfaces/IXModel.cpp +++ b/src/Components/Modules/AssetInterfaces/IXModel.cpp @@ -128,7 +128,7 @@ namespace Assets for (char i = 0; i < asset->numBones; ++i) { - asset->boneNames[i] = Game::SL_GetString(reader.readCString(), 0); + asset->boneNames[i] = static_cast(Game::SL_GetString(reader.readCString(), 0)); } } diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 2dfe290e..9f9c08bb 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -96,13 +96,13 @@ namespace Components { Game::Scr_AddString("autoassign"); Game::Scr_AddString("team_marinesopfor"); - Game::Scr_Notify(ent, Game::SL_GetString("menuresponse", 0), 2); + Game::Scr_Notify(ent, static_cast(Game::SL_GetString("menuresponse", 0)), 2); Scheduler::Once([ent] { Game::Scr_AddString(Utils::String::VA("class%u", Utils::Cryptography::Rand::GenerateInt() % 5u)); Game::Scr_AddString("changeclass"); - Game::Scr_Notify(ent, Game::SL_GetString("menuresponse", 0), 2); + Game::Scr_Notify(ent, static_cast(Game::SL_GetString("menuresponse", 0)), 2); }, Scheduler::Pipeline::SERVER, 1s); }, Scheduler::Pipeline::SERVER, 1s); diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 924cb498..a3ada816 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -73,7 +73,7 @@ namespace Components Game::Scr_AddEntity(player); Game::Scr_AddString(text + msgIndex); - Game::Scr_NotifyLevel(Game::SL_GetString("say", 0), 2); + Game::Scr_NotifyLevel(static_cast(Game::SL_GetString("say", 0)), 2); return text; } diff --git a/src/Components/Modules/FileSystem.cpp b/src/Components/Modules/FileSystem.cpp index 473a38ac..46ae0ca3 100644 --- a/src/Components/Modules/FileSystem.cpp +++ b/src/Components/Modules/FileSystem.cpp @@ -78,19 +78,19 @@ namespace Components Utils::Memory::Allocator allocator; if (!this->exists()) return std::string(); - int position = Game::FS_FTell(this->handle); + const auto position = Game::FS_FTell(this->handle); this->seek(0, Game::FS_SEEK_SET); char* buffer = allocator.allocateArray(this->size); if (!this->read(buffer, this->size)) { this->seek(position, Game::FS_SEEK_SET); - return std::string(); + return {}; } this->seek(position, Game::FS_SEEK_SET); - return std::string(buffer, this->size); + return {buffer, static_cast(this->size)}; } bool FileSystem::FileReader::read(void* buffer, size_t _size) diff --git a/src/Components/Modules/GSC/GSC.cpp b/src/Components/Modules/GSC/GSC.cpp index 3970b014..0cf74f21 100644 --- a/src/Components/Modules/GSC/GSC.cpp +++ b/src/Components/Modules/GSC/GSC.cpp @@ -4,6 +4,7 @@ #include "IO.hpp" #include "Script.hpp" #include "ScriptExtension.hpp" +#include "ScriptPatches.hpp" #include "ScriptStorage.hpp" namespace Components @@ -14,6 +15,7 @@ namespace Components Loader::Register(new IO()); Loader::Register(new Script()); Loader::Register(new ScriptExtension()); + Loader::Register(new ScriptPatches()); Loader::Register(new ScriptStorage()); } } diff --git a/src/Components/Modules/GSC/IO.cpp b/src/Components/Modules/GSC/IO.cpp index e3a420db..5116d32c 100644 --- a/src/Components/Modules/GSC/IO.cpp +++ b/src/Components/Modules/GSC/IO.cpp @@ -126,7 +126,7 @@ namespace Components } } - const auto p = "scriptdata" / std::filesystem::path(path); + const auto p = "scriptdata"s / std::filesystem::path(path); const auto folder = p.parent_path().string(); const auto file = p.filename().string(); Game::Scr_AddInt(FileSystem::_DeleteFile(folder, file)); diff --git a/src/Components/Modules/GSC/ScriptPatches.cpp b/src/Components/Modules/GSC/ScriptPatches.cpp new file mode 100644 index 00000000..4e7843d8 --- /dev/null +++ b/src/Components/Modules/GSC/ScriptPatches.cpp @@ -0,0 +1,36 @@ +#include +#include "ScriptPatches.hpp" +#include "Script.hpp" + +using namespace Utils::String; + +namespace Components +{ + constexpr auto offset = 511; + + Game::game_hudelem_s* ScriptPatches::HECmd_GetHudElem(Game::scr_entref_t entref) + { + if (entref.classnum != 1) + { + Game::Scr_ObjectError("not a hud element"); + return nullptr; + } + + assert(entref.entnum < 1024); + return &Game::g_hudelems[entref.entnum]; + } + + ScriptPatches::ScriptPatches() + { + Script::AddMethod("ClearHudText", [](Game::scr_entref_t entref) -> void + { + auto* hud = HECmd_GetHudElem(entref); + + // Frees config string up + if ((hud->elem).text) + { + Game::SV_SetConfigstring((hud->elem).text + offset, nullptr); + } + }); + } +} diff --git a/src/Components/Modules/GSC/ScriptPatches.hpp b/src/Components/Modules/GSC/ScriptPatches.hpp new file mode 100644 index 00000000..cf4787d0 --- /dev/null +++ b/src/Components/Modules/GSC/ScriptPatches.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace Components +{ + class ScriptPatches : public Component + { + public: + ScriptPatches(); + + private: + static Game::game_hudelem_s* HECmd_GetHudElem(Game::scr_entref_t entref); + }; +} diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 2b64618d..0a35ee71 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -576,7 +576,7 @@ namespace Components int ZoneBuilder::Zone::addScriptString(const std::string& str) { - return this->addScriptString(Game::SL_GetString(str.data(), 0)); + return this->addScriptString(static_cast(Game::SL_GetString(str.data(), 0))); } // Mark a scriptString for writing and map it. diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 6f9c2c1d..236719c8 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -168,11 +168,6 @@ namespace Game Dvar_SetFloat_t Dvar_SetFloat = Dvar_SetFloat_t(0x40BB20); Dvar_SetInt_t Dvar_SetInt = Dvar_SetInt_t(0x421DA0); - SL_ConvertToString_t SL_ConvertToString = SL_ConvertToString_t(0x4EC1D0); - SL_GetString_t SL_GetString = SL_GetString_t(0x4CDC10); - SL_AddRefToString_t SL_AddRefToString = SL_AddRefToString_t(0x4D9B00); - SL_RemoveRefToString_t SL_RemoveRefToString = SL_RemoveRefToString_t(0x47CD70); - SND_Init_t SND_Init = SND_Init_t(0x46A630); SND_InitDriver_t SND_InitDriver = SND_InitDriver_t(0x4F5090); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 1c12835c..e642bd77 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -389,18 +389,6 @@ namespace Game typedef int(*SEH_GetCurrentLanguage_t)(); extern SEH_GetCurrentLanguage_t SEH_GetCurrentLanguage; - typedef const char*(*SL_ConvertToString_t)(scr_string_t stringValue); - extern SL_ConvertToString_t SL_ConvertToString; - - typedef short(*SL_GetString_t)(const char *str, unsigned int user); - extern SL_GetString_t SL_GetString; - - typedef void(*SL_AddRefToString_t)(unsigned int stringValue); - extern SL_AddRefToString_t SL_AddRefToString; - - typedef void(*SL_RemoveRefToString_t)(unsigned int stringValue); - extern SL_RemoveRefToString_t SL_RemoveRefToString; - typedef void(*SND_Init_t)(int a1, int a2, int a3); extern SND_Init_t SND_Init; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 876da5fa..a4fd994d 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -12,8 +12,12 @@ namespace Game G_PrintEntities_t G_PrintEntities = G_PrintEntities_t(0x4E6A50); G_GetEntityTypeName_t G_GetEntityTypeName = G_GetEntityTypeName_t(0x4EB810); + G_LocalizedStringIndex_t G_LocalizedStringIndex = G_LocalizedStringIndex_t(0x4582F0); + gentity_t* g_entities = reinterpret_cast(0x18835D8); + const char* origErrorMsg = reinterpret_cast(0x79B124); + XModel* G_GetModel(const int index) { assert(index > 0); diff --git a/src/Game/Game.hpp b/src/Game/Game.hpp index b4d7d3b7..d094afb9 100644 --- a/src/Game/Game.hpp +++ b/src/Game/Game.hpp @@ -40,9 +40,14 @@ namespace Game typedef const char*(*G_GetEntityTypeName_t)(const gentity_s* ent); extern G_GetEntityTypeName_t G_GetEntityTypeName; + typedef int(*G_LocalizedStringIndex_t)(const char* string); + extern G_LocalizedStringIndex_t G_LocalizedStringIndex; + constexpr std::size_t MAX_GENTITIES = 2048; constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1; extern gentity_t* g_entities; + extern const char* origErrorMsg; + extern XModel* G_GetModel(int index); } diff --git a/src/Game/Script.cpp b/src/Game/Script.cpp index 7b68bb61..4766e89b 100644 --- a/src/Game/Script.cpp +++ b/src/Game/Script.cpp @@ -56,6 +56,10 @@ namespace Game Scr_SetClientField_t Scr_SetClientField = Scr_SetClientField_t(0x4A6DF0); Scr_AddClassField_t Scr_AddClassField = Scr_AddClassField_t(0x4C0E70); + Scr_ConstructMessageString_t Scr_ConstructMessageString = Scr_ConstructMessageString_t(0x45F940); + + Scr_FreeHudElemConstStrings_t Scr_FreeHudElemConstStrings = Scr_FreeHudElemConstStrings_t(0x5E1120); + GetEntity_t GetEntity = GetEntity_t(0x4BC270); GetPlayerEntity_t GetPlayerEntity = GetPlayerEntity_t(0x49C4A0); @@ -63,11 +67,21 @@ namespace Game Scr_ShutdownAllocNode_t Scr_ShutdownAllocNode = Scr_ShutdownAllocNode_t(0x441650); Scr_IsSystemActive_t Scr_IsSystemActive = Scr_IsSystemActive_t(0x4B24E0); + SL_ConvertToString_t SL_ConvertToString = SL_ConvertToString_t(0x4EC1D0); + SL_GetString_t SL_GetString = SL_GetString_t(0x4CDC10); + SL_GetString__t SL_GetString_ = SL_GetString__t(0x47E310); + SL_FindString_t SL_FindString = SL_FindString_t(0x434EE0); + SL_FindLowercaseString_t SL_FindLowercaseString = SL_FindLowercaseString_t(0x4C63E0); + SL_AddRefToString_t SL_AddRefToString = SL_AddRefToString_t(0x4D9B00); + SL_RemoveRefToString_t SL_RemoveRefToString = SL_RemoveRefToString_t(0x47CD70); + scr_const_t* scr_const = reinterpret_cast(0x1AA2E00); scrVmPub_t* scrVmPub = reinterpret_cast(0x2040CF0); scrVarPub_t* scrVarPub = reinterpret_cast(0x201A408); + game_hudelem_s* g_hudelems = reinterpret_cast(0x18565A8); + void IncInParam() { Scr_ClearOutParams(); diff --git a/src/Game/Script.hpp b/src/Game/Script.hpp index 145dccf6..7c998c50 100644 --- a/src/Game/Script.hpp +++ b/src/Game/Script.hpp @@ -119,10 +119,10 @@ namespace Game typedef int(*Scr_GetPointerType_t)(unsigned int index); extern Scr_GetPointerType_t Scr_GetPointerType; - typedef void(*Scr_Error_t)(const char*); + typedef void(*Scr_Error_t)(const char* error); extern Scr_Error_t Scr_Error; - typedef void(*Scr_ObjectError_t)(const char*); + typedef void(*Scr_ObjectError_t)(const char* error); extern Scr_ObjectError_t Scr_ObjectError; typedef void(*Scr_ParamError_t)(unsigned int paramIndex, const char*); @@ -143,12 +143,39 @@ namespace Game typedef void(*Scr_AddClassField_t)(unsigned int classnum, const char* name, unsigned int offset); extern Scr_AddClassField_t Scr_AddClassField; + typedef void(*Scr_ConstructMessageString_t)(int firstParmIndex, int lastParmIndex, const char* errorContext, char* string, unsigned int stringLimit); + extern Scr_ConstructMessageString_t Scr_ConstructMessageString; + + typedef void(*Scr_FreeHudElemConstStrings_t)(game_hudelem_s* hud); + extern Scr_FreeHudElemConstStrings_t Scr_FreeHudElemConstStrings; + typedef gentity_s*(*GetPlayerEntity_t)(scr_entref_t entref); extern GetPlayerEntity_t GetPlayerEntity; typedef gentity_s*(*GetEntity_t)(scr_entref_t entref); extern GetEntity_t GetEntity; + typedef const char*(*SL_ConvertToString_t)(scr_string_t stringValue); + extern SL_ConvertToString_t SL_ConvertToString; + + typedef unsigned int(*SL_GetString_t)(const char* str, unsigned int user); + extern SL_GetString_t SL_GetString; + + typedef unsigned int(*SL_GetString__t)(const char* str, unsigned int user, int type); + extern SL_GetString__t SL_GetString_; + + typedef unsigned int(*SL_FindString_t)(const char* name); + extern SL_FindString_t SL_FindString; + + typedef unsigned int(*SL_FindLowercaseString_t)(const char* str); + extern SL_FindLowercaseString_t SL_FindLowercaseString; + + typedef void(*SL_AddRefToString_t)(unsigned int stringValue); + extern SL_AddRefToString_t SL_AddRefToString; + + typedef void(*SL_RemoveRefToString_t)(unsigned int stringValue); + extern SL_RemoveRefToString_t SL_RemoveRefToString; + extern void IncInParam(); extern void Scr_AddBool(int value); @@ -161,4 +188,6 @@ namespace Game extern scrVmPub_t* scrVmPub; extern scrVarPub_t* scrVarPub; + + extern game_hudelem_s* g_hudelems; } diff --git a/src/Game/Server.cpp b/src/Game/Server.cpp index 46bb18d8..1f9370d8 100644 --- a/src/Game/Server.cpp +++ b/src/Game/Server.cpp @@ -12,6 +12,7 @@ namespace Game SV_Cmd_ArgvBuffer_t SV_Cmd_ArgvBuffer = SV_Cmd_ArgvBuffer_t(0x40BB60); SV_DirectConnect_t SV_DirectConnect = SV_DirectConnect_t(0x460480); SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0); + SV_GetConfigstringConst_t SV_GetConfigstringConst = SV_GetConfigstringConst_t(0x468500); SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0); SV_ClientThink_t SV_ClientThink = SV_ClientThink_t(0x44ADD0); SV_DropClient_t SV_DropClient = SV_DropClient_t(0x4D1600); @@ -25,6 +26,9 @@ namespace Game int* svs_clientCount = reinterpret_cast(0x31D938C); client_t* svs_clients = reinterpret_cast(0x31D9390); + unsigned short* sv_sconfigstrings = reinterpret_cast(0x208A632); + unsigned short* sv_emptyConfigString = reinterpret_cast(0x208A630); + volatile long* sv_thread_owns_game = reinterpret_cast(0x2089DB8); int SV_GetServerThreadOwnsGame() diff --git a/src/Game/Server.hpp b/src/Game/Server.hpp index 52ecd6df..c1ce9cd0 100644 --- a/src/Game/Server.hpp +++ b/src/Game/Server.hpp @@ -29,6 +29,9 @@ namespace Game typedef void(*SV_SetConfigstring_t)(int index, const char* string); extern SV_SetConfigstring_t SV_SetConfigstring; + typedef unsigned int(*SV_GetConfigstringConst_t)(int index); + extern SV_GetConfigstringConst_t SV_GetConfigstringConst; + typedef void(*SV_DirectConnect_t)(netadr_t adr); extern SV_DirectConnect_t SV_DirectConnect; @@ -58,6 +61,9 @@ namespace Game extern int* svs_clientCount; extern client_t* svs_clients; + extern unsigned short* sv_sconfigstrings; + extern unsigned short* sv_emptyConfigString; + extern volatile long* sv_thread_owns_game; extern int SV_GetServerThreadOwnsGame(); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index c87612a2..79b398fd 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -272,6 +272,7 @@ namespace Game CS_VOTE_NO = 0x14, CS_VOTE_MAPNAME = 0x15, CS_VOTE_GAMETYPE = 0x16, + CS_SHELLSHOCKS = 0x985, CS_ITEMS = 0x102A, }; // Incomplete @@ -1290,6 +1291,14 @@ namespace Game int flags; }; + struct game_hudelem_s + { + hudelem_s elem; + int clientNum; + int team; + int archived; + }; + enum { PMF_PRONE = 1 << 0, From 70ff8d3aa349d9bd5878c8b18c8d636a5c1157e8 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 28 Nov 2022 17:30:17 +0000 Subject: [PATCH 20/96] [Zone:b:uilder]: Fix typos --- .../Modules/AssetInterfaces/ImenuDef_t.cpp | 74 ++++++++----------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp index c9b6fc8e..b3ea1162 100644 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp +++ b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp @@ -20,7 +20,7 @@ namespace Assets void ImenuDef_t::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { - Game::menuDef_t *asset = header.menu; + auto* asset = header.menu; if (asset->window.background) { @@ -59,14 +59,14 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); - Game::ExpressionSupportingData *dest = buffer->dest(); + auto* dest = buffer->dest(); buffer->save(asset); if (asset->uifunctions.functions) { buffer->align(Utils::Stream::ALIGN_4); - Game::Statement_s **destStatement = buffer->dest(); + auto** destStatement = buffer->dest(); buffer->saveArray(asset->uifunctions.functions, asset->uifunctions.totalFunctions); for (int i = 0; i < asset->uifunctions.totalFunctions; ++i) @@ -87,17 +87,17 @@ namespace Assets { buffer->align(Utils::Stream::ALIGN_4); - Game::StaticDvar **destStaticDvars = buffer->dest(); + auto** destStaticDvars = buffer->dest(); buffer->saveArray(asset->staticDvarList.staticDvars, asset->staticDvarList.numStaticDvars); - for (int i = 0; i < asset->staticDvarList.numStaticDvars; ++i) + for (auto i = 0; i < asset->staticDvarList.numStaticDvars; ++i) { if (asset->staticDvarList.staticDvars[i]) { Utils::Stream::ClearPointer(&destStaticDvars[i]); buffer->align(Utils::Stream::ALIGN_4); - Game::StaticDvar *destStaticDvar = buffer->dest(); + auto* destStaticDvar = buffer->dest(); buffer->save(asset->staticDvarList.staticDvars[i]); if (asset->staticDvarList.staticDvars[i]->dvarName) @@ -115,7 +115,7 @@ namespace Assets { buffer->align(Utils::Stream::ALIGN_4); - const char **destuiStrings = buffer->dest(); + const auto** destUIStrings = buffer->dest(); buffer->saveArray(asset->uiStrings.strings, asset->uiStrings.totalStrings); for (int i = 0; i < asset->uiStrings.totalStrings; ++i) @@ -123,7 +123,7 @@ namespace Assets if (asset->uiStrings.strings[i]) { buffer->saveString(asset->uiStrings.strings[i]); - Utils::Stream::ClearPointer(&destuiStrings[i]); + Utils::Stream::ClearPointer(&destUIStrings[i]); } } } @@ -143,7 +143,7 @@ namespace Assets #endif // Write header data - Game::Statement_s *dest = buffer->dest(); + auto* dest = buffer->dest(); buffer->save(asset); // Write statement entries @@ -155,7 +155,7 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); // Write entries - Game::expressionEntry *destEntries = buffer->dest(); + auto* destEntries = buffer->dest(); buffer->save(asset->entries, sizeof(Game::expressionEntry), asset->numEntries); // Loop through entries @@ -222,7 +222,7 @@ namespace Assets #endif // Write header data - Game::MenuEventHandlerSet *destset = buffer->dest(); + auto* destset = buffer->dest(); buffer->save(asset); // Event handlers @@ -234,7 +234,7 @@ namespace Assets buffer->save(asset->eventHandlers, sizeof(Game::MenuEventHandler*), asset->eventHandlerCount); // Loop through eventHandlers - for (int i = 0; i < asset->eventHandlerCount; ++i) + for (auto i = 0; i < asset->eventHandlerCount; ++i) { if (asset->eventHandlers[i]) { @@ -244,7 +244,7 @@ namespace Assets #endif // Write menu event handler - Game::MenuEventHandler *dest = buffer->dest(); + auto* dest = buffer->dest(); buffer->save(asset->eventHandlers[i]); // Write additional data based on type @@ -264,7 +264,7 @@ namespace Assets if (asset->eventHandlers[i]->eventData.conditionalScript) { buffer->align(Utils::Stream::ALIGN_4); - Game::ConditionalScript *destConditionalScript = buffer->dest(); + auto* destConditionalScript = buffer->dest(); buffer->save(asset->eventHandlers[i]->eventData.conditionalScript); // eventExpression @@ -307,7 +307,7 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); // header data - Game::SetLocalVarData *destLocalVarData = buffer->dest(); + auto* destLocalVarData = buffer->dest(); buffer->save(asset->eventHandlers[i]->eventData.setLocalVarData); // localVarName @@ -354,7 +354,7 @@ namespace Assets while (asset) { // Write header - Game::ItemKeyHandler* dest = buffer->dest(); + auto* dest = buffer->dest(); buffer->save(asset); // MenuEventHandlerSet @@ -367,7 +367,7 @@ namespace Assets if (asset->next) { - // align every indice, besides the first one? + // align every index, besides the first one? buffer->align(Utils::Stream::ALIGN_4); } @@ -379,20 +379,20 @@ namespace Assets #endif } -#define EVENTHANDLERSET(__indice) \ - if (asset->__indice) \ +#define EVENTHANDLERSET(__index) \ + if (asset->__index) \ { \ buffer->align(Utils::Stream::ALIGN_4); \ - this->save_MenuEventHandlerSet(asset->__indice, builder); \ - Utils::Stream::ClearPointer(&dest->__indice); \ + this->save_MenuEventHandlerSet(asset->__index, builder); \ + Utils::Stream::ClearPointer(&dest->__index); \ } -#define STATEMENT(__indice) \ - if (asset->__indice) \ +#define STATEMENT(__index) \ + if (asset->__index) \ { \ buffer->align(Utils::Stream::ALIGN_4); \ - this->save_Statement_s(asset->__indice, builder); \ - Utils::Stream::ClearPointer(&dest->__indice); \ + this->save_Statement_s(asset->__index, builder); \ + Utils::Stream::ClearPointer(&dest->__index); \ } void ImenuDef_t::save_itemDefData_t(Game::itemDefData_t* asset, int type, Game::itemDef_s* dest, Components::ZoneBuilder::Zone* builder) @@ -412,7 +412,7 @@ namespace Assets if (type == 6) { buffer->align(Utils::Stream::ALIGN_4); - Game::listBoxDef_s* destlb = buffer->dest(); + auto* destlb = buffer->dest(); buffer->save(asset->listBox); if (asset->listBox->onDoubleClick) @@ -427,17 +427,7 @@ namespace Assets } } // HexRays spaghetti - else if (type != 4 - && type != 9 - && type != 16 - && type != 18 - && type != 11 - && type != 14 - && type != 10 - && type != 17 - && type != 22 - && type != 23 - && type != 0) + else if (type != 4 && type != 9 && type != 16 && type != 18 && type != 11 && type != 14 && type != 10 && type != 17 && type != 22 && type != 23 && type != 0) { switch (type) { @@ -457,7 +447,7 @@ namespace Assets break; case 12: buffer->align(Utils::Stream::ALIGN_4); - Game::multiDef_s* destdef = buffer->dest(); + auto* destdef = buffer->dest(); buffer->save(asset->multi); for (int i = 0; i < 32; ++i) @@ -500,7 +490,7 @@ namespace Assets AssertSize(Game::itemDef_s, 380); Utils::Stream* buffer = builder->getBuffer(); - Game::itemDef_s* dest = buffer->dest(); + auto* dest = buffer->dest(); #ifdef WRITE_LOGS if (asset->window.name) @@ -587,7 +577,7 @@ namespace Assets buffer->enterStruct("floatExpressions"); #endif - Game::ItemFloatExpression* destExp = buffer->dest(); + auto* destExp = buffer->dest(); buffer->saveArray(asset->floatExpressions, asset->floatExpressionCount); for (int i = 0; i < asset->floatExpressionCount; ++i) @@ -624,8 +614,8 @@ namespace Assets #endif Utils::Stream* buffer = builder->getBuffer(); - Game::menuDef_t* asset = header.menu; - Game::menuDef_t* dest = buffer->dest(); + auto* asset = header.menu; + auto* dest = buffer->dest(); buffer->save(asset); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); From a447a2945aae2c7534e730e969453abc323e3647 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 28 Nov 2022 18:06:42 +0000 Subject: [PATCH 21/96] [Menus]: Fix crashes while parsing (#607) --- src/Components/Modules/AssetInterfaces/IMenuList.cpp | 8 ++++---- src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp | 2 +- src/Components/Modules/Menus.cpp | 7 +++++++ src/Components/Modules/ZoneBuilder.cpp | 6 ++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IMenuList.cpp b/src/Components/Modules/AssetInterfaces/IMenuList.cpp index dd9fd1fe..4cfc63d0 100644 --- a/src/Components/Modules/AssetInterfaces/IMenuList.cpp +++ b/src/Components/Modules/AssetInterfaces/IMenuList.cpp @@ -12,7 +12,7 @@ namespace Assets if (menus.empty()) return; // Allocate new menu list - Game::MenuList* newList = allocator->allocate(); + auto* newList = allocator->allocate(); if (!newList) return; newList->menus = allocator->allocateArray(menus.size()); @@ -35,7 +35,7 @@ namespace Assets } void IMenuList::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { - Game::MenuList *asset = header.menuList; + auto* asset = header.menuList; for (int i = 0; i < asset->menuCount; ++i) { @@ -51,7 +51,7 @@ namespace Assets Utils::Stream* buffer = builder->getBuffer(); Game::MenuList* asset = header.menuList; - Game::MenuList* dest = buffer->dest(); + auto* dest = buffer->dest(); buffer->save(asset); @@ -67,7 +67,7 @@ namespace Assets { buffer->align(Utils::Stream::ALIGN_4); - Game::menuDef_t **destMenus = buffer->dest(); + auto** destMenus = buffer->dest(); buffer->saveArray(asset->menus, asset->menuCount); for (int i = 0; i < asset->menuCount; ++i) diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp index b3ea1162..ec3c18be 100644 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp +++ b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp @@ -11,7 +11,7 @@ namespace Assets // load from disk auto menus = Components::Menus::LoadMenu(Utils::String::VA("ui_mp/%s.menu", name.data())); - if (menus.size() == 0) return; + if (menus.empty()) return; if (menus.size() > 1) Components::Logger::Print("Menu '{}' on disk has more than one menudef in it. Only saving the first one\n", name); header->menu = menus[0].second; diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index ef726aed..ae04d35c 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -166,6 +166,13 @@ namespace Components } } + if (!menu->window.name) + { + allocator->free(menu->items); + allocator->free(menu); + return nullptr; + } + Menus::OverrideMenu(menu); Menus::RemoveMenu(menu->window.name); Menus::MenuList[menu->window.name] = menu; diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 0a35ee71..38b73487 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -265,8 +265,10 @@ namespace Components if (asset->type != type) continue; - const char* assetName = Game::DB_GetXAssetName(asset); - if (assetName[0] == ',') ++assetName; + const auto* assetName = Game::DB_GetXAssetName(asset); + if (!assetName) return -1; + if (assetName[0] == ',' && assetName[1] != '\0') ++assetName; + else return -1; if (this->getAssetName(type, assetName) == name) { From 0642eed7bc80d25bb72fc46c9d0d639314f0f99c Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 28 Nov 2022 22:04:57 +0000 Subject: [PATCH 22/96] [General]: Correct function definition --- src/Components/Modules/ClanTags.cpp | 4 +--- src/Components/Modules/Gamepad.cpp | 12 +++++----- src/Components/Modules/UIScript.cpp | 35 +++++++++++++++++------------ src/Components/Modules/UIScript.hpp | 2 ++ src/Game/Client.cpp | 6 +++++ src/Game/Client.hpp | 1 + src/Game/Functions.cpp | 2 +- src/Game/Functions.hpp | 6 ++--- 8 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index 7394e55d..2aa3d29d 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -70,9 +70,7 @@ namespace Components void ClanTags::CL_SanitizeClanName() { - char saneNameBuf[5]; - std::memset(saneNameBuf, 0, sizeof(saneNameBuf)); - + char saneNameBuf[5]{}; auto* saneName = saneNameBuf; assert(ClanName); diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 4942ff58..e749053e 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -788,7 +788,7 @@ namespace Components bool Gamepad::CG_ShouldUpdateViewAngles(const int localClientNum) { - return !Game::Key_IsKeyCatcherActive(localClientNum, Game::KEYCATCH_MASK_ANY) || Game::UI_GetActiveMenu(localClientNum) == Game::UIMENU_SCOREBOARD; + return !Game::Key_IsCatcherActive(localClientNum, Game::KEYCATCH_MASK_ANY) || Game::UI_GetActiveMenu(localClientNum) == Game::UIMENU_SCOREBOARD; } float Gamepad::CL_GamepadAxisValue(const int gamePadIndex, const Game::GamepadVirtualAxis virtualAxis) @@ -1096,7 +1096,7 @@ namespace Components auto& gamePadGlobal = gamePadGlobals[gamePadIndex]; - if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) + if (Game::Key_IsCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) { const int scrollDelayFirst = gpad_menu_scroll_delay_first.get(); const int scrollDelayRest = gpad_menu_scroll_delay_rest.get(); @@ -1149,7 +1149,7 @@ namespace Components if (pressedOrUpdated && CL_CheckForIgnoreDueToRepeat(gamePadIndex, key, keyState.keys[key].repeats, time)) return; - if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_LOCATION_SELECTION) && pressedOrUpdated) + if (Game::Key_IsCatcherActive(gamePadIndex, Game::KEYCATCH_LOCATION_SELECTION) && pressedOrUpdated) { if (key == Game::K_BUTTON_B || keyState.keys[key].binding && strcmp(keyState.keys[key].binding, "+actionslot 4") == 0) { @@ -1176,7 +1176,7 @@ namespace Components char cmd[1024]; if (pressedOrUpdated) { - if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) + if (Game::Key_IsCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) { UI_GamepadKeyEvent(gamePadIndex, key, pressedOrUpdated); return; @@ -1203,7 +1203,7 @@ namespace Components Game::Cbuf_AddText(gamePadIndex, cmd); } - if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) + if (Game::Key_IsCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) { UI_GamepadKeyEvent(gamePadIndex, key, pressedOrUpdated); } @@ -1218,7 +1218,7 @@ namespace Components gamePad.inUse = true; gpad_in_use.setRaw(true); - if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) + if (Game::Key_IsCatcherActive(gamePadIndex, Game::KEYCATCH_UI)) CL_GamepadResetMenuScrollTime(gamePadIndex, key, buttonEvent == Game::GPAD_BUTTON_PRESSED, time); diff --git a/src/Components/Modules/UIScript.cpp b/src/Components/Modules/UIScript.cpp index 835d4682..08534954 100644 --- a/src/Components/Modules/UIScript.cpp +++ b/src/Components/Modules/UIScript.cpp @@ -9,7 +9,7 @@ namespace Components { if (this->isValid()) { - return std::atoi(this->token); + return std::strtol(this->token, nullptr, 0); } return 0; @@ -49,22 +49,22 @@ namespace Components return &Game::uiInfoArray[localClientNum]; } - void UIScript::Add(const std::string& name, const UIScript::UIScriptHandler& callback) + void UIScript::Add(const std::string& name, const UIScriptHandler& callback) { - UIScript::UIScripts[name] = callback; + UIScripts[name] = callback; } void UIScript::AddOwnerDraw(int ownerdraw, const std::function& callback) { - UIScript::UIOwnerDraws[ownerdraw] = callback; + UIOwnerDraws[ownerdraw] = callback; } bool UIScript::RunMenuScript(const char* name, const char** args) { - if (const auto itr = UIScript::UIScripts.find(name); itr != UIScript::UIScripts.end()) + if (const auto itr = UIScripts.find(name); itr != UIScripts.end()) { - const auto* info = UIScript::UI_GetClientInfo(0); - itr->second(UIScript::Token(args), info); + const auto* info = UI_GetClientInfo(0); + itr->second(Token(args), info); return true; } @@ -75,7 +75,7 @@ namespace Components { if (key == 200 || key == 201) // mouse buttons { - for (auto i = UIScript::UIOwnerDraws.begin(); i != UIScript::UIOwnerDraws.end(); ++i) + for (auto i = UIOwnerDraws.begin(); i != UIOwnerDraws.end(); ++i) { if (i->first == ownerDraw) { @@ -93,12 +93,12 @@ namespace Components { mov eax, esp add eax, 8h - mov edx, eax // UIScript name + mov edx, eax // UIScript name mov eax, [esp + 0C10h] // UIScript args push eax push edx - call UIScript::RunMenuScript + call RunMenuScript add esp, 8h test al, al @@ -116,6 +116,11 @@ namespace Components } } + bool UIScript::CL_IsUIActive_Hk(const int localClientNum) + { + return Game::Key_IsCatcherActive(localClientNum, Game::KEYCATCH_UI) || Game::cgsArray->hardcore; + } + UIScript::UIScript() { AssertSize(Game::uiInfo_s, 0x22FC); @@ -123,15 +128,17 @@ namespace Components if (Dedicated::IsEnabled()) return; // Install handler - Utils::Hook::RedirectJump(0x45EC59, UIScript::RunMenuScriptStub); + Utils::Hook::RedirectJump(0x45EC59, RunMenuScriptStub); // Install ownerdraw handler - Utils::Hook(0x63D233, UIScript::OwnerDrawHandleKeyStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x63D233, OwnerDrawHandleKeyStub, HOOK_CALL).install()->quick(); + + Utils::Hook(0x62B397, CL_IsUIActive_Hk, HOOK_CALL).install()->quick(); } UIScript::~UIScript() { - UIScript::UIScripts.clear(); - UIScript::UIOwnerDraws.clear(); + UIScripts.clear(); + UIOwnerDraws.clear(); } } diff --git a/src/Components/Modules/UIScript.hpp b/src/Components/Modules/UIScript.hpp index 553e15ab..dfbe2cee 100644 --- a/src/Components/Modules/UIScript.hpp +++ b/src/Components/Modules/UIScript.hpp @@ -36,6 +36,8 @@ namespace Components static bool RunMenuScript(const char* name, const char** args); static void RunMenuScriptStub(); + static bool CL_IsUIActive_Hk(int localClientNum); + static std::unordered_map UIScripts; static std::unordered_map> UIOwnerDraws; }; diff --git a/src/Game/Client.cpp b/src/Game/Client.cpp index 4798a21c..4f440e79 100644 --- a/src/Game/Client.cpp +++ b/src/Game/Client.cpp @@ -58,4 +58,10 @@ namespace Game return cl_voiceCommunication; } + + clientUIActive_t* CL_GetLocalClientUIGlobals(const int localClientNum) + { + AssertIn(localClientNum, MAX_LOCAL_CLIENTS); + return &clientUIActives[localClientNum]; + } } diff --git a/src/Game/Client.hpp b/src/Game/Client.hpp index 834d73fa..cb3606b9 100644 --- a/src/Game/Client.hpp +++ b/src/Game/Client.hpp @@ -67,4 +67,5 @@ namespace Game extern clientConnection_t* CL_GetLocalClientConnection(int localClientNum); extern connstate_t CL_GetLocalClientConnectionState(int localClientNum); extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum); + extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum); } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 236719c8..f776c2a6 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -52,7 +52,7 @@ namespace Game Key_SetCatcher_t Key_SetCatcher = Key_SetCatcher_t(0x43BD00); Key_RemoveCatcher_t Key_RemoveCatcher = Key_RemoveCatcher_t(0x408260); - Key_IsKeyCatcherActive_t Key_IsKeyCatcherActive = Key_IsKeyCatcherActive_t(0x4DA010); + Key_IsCatcherActive_t Key_IsCatcherActive = Key_IsCatcherActive_t(0x4DA010); Key_SetBinding_t Key_SetBinding = Key_SetBinding_t(0x494C90); LargeLocalInit_t LargeLocalInit = LargeLocalInit_t(0x4A62A0); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index e642bd77..e307ef42 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -104,10 +104,10 @@ namespace Game typedef void(*Key_RemoveCatcher_t)(int localClientNum, int andMask); extern Key_RemoveCatcher_t Key_RemoveCatcher; - typedef bool(*Key_IsKeyCatcherActive_t)(int localClientNum, int catcher); - extern Key_IsKeyCatcherActive_t Key_IsKeyCatcherActive; + typedef bool(*Key_IsCatcherActive_t)(int localClientNum, int mask); + extern Key_IsCatcherActive_t Key_IsCatcherActive; - typedef void(*Key_SetBinding_t)(int localClientNum, int keyNum, const char* binding); + typedef void(*Key_SetBinding_t)(int localClientNum, int keynum, const char* binding); extern Key_SetBinding_t Key_SetBinding; typedef void(*LargeLocalInit_t)(); From c3d6b206440d2092ceb900524dbd289acb7d6419 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 28 Nov 2022 23:15:21 +0000 Subject: [PATCH 23/96] [Command]: Fix definition of Cmd_AddCommand (#609) --- src/Components/Modules/Debug.cpp | 22 ++++++++++++++++++++++ src/Components/Modules/Debug.hpp | 1 + src/Game/Functions.hpp | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index 0d968983..c0fb92ae 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -308,6 +308,27 @@ namespace Components } } + void Debug::Com_BugNameInc_f() + { + char buf[260]{}; + + if (std::strlen(BugName->current.string) < 4) + { + Game::Dvar_SetString(BugName, "bug0"); + return; + } + + if (strncmp(BugName->current.string, "bug", 3) != 0) + { + Game::Dvar_SetString(BugName, "bug0"); + return; + } + + const auto n = std::strtol(BugName->current.string + 3, nullptr, 10); + sprintf_s(buf, "bug%d", n + 1); + Game::Dvar_SetString(BugName, buf); + } + void Debug::CL_InitDebugDvars() { static const char* debugOverlayNames_0[] = @@ -338,6 +359,7 @@ namespace Components #ifdef _DEBUG Command::Add("bug", Com_Bug_f); + Command::Add("bug_name_inc", Com_BugNameInc_f); #endif } } diff --git a/src/Components/Modules/Debug.hpp b/src/Components/Modules/Debug.hpp index 3eaf8a78..893eb25b 100644 --- a/src/Components/Modules/Debug.hpp +++ b/src/Components/Modules/Debug.hpp @@ -43,6 +43,7 @@ namespace Components static void Com_Assert_f(); static void Com_Bug_f(Command::Params* params); + static void Com_BugNameInc_f(); static void CL_InitDebugDvars(); }; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index e307ef42..cd1c7c30 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -48,7 +48,7 @@ namespace Game typedef void(*CG_SetupWeaponDef_t)(int localClientNum, unsigned int weapIndex); extern CG_SetupWeaponDef_t CG_SetupWeaponDef; - typedef void(*Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_t* allocedCmd, bool isKey); + typedef void(*Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_t* allocedCmd, int isKey); extern Cmd_AddCommand_t Cmd_AddCommand; typedef void(*Cmd_AddServerCommand_t)(const char* name, void(*callback), cmd_function_t* data); From b195d96abbb5f7b3e16b33ef13839953cb19d42f Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 29 Nov 2022 14:18:10 +0000 Subject: [PATCH 24/96] [GSC]: Script aliases (#610) --- src/Components/Modules/Bots.cpp | 44 +++--- src/Components/Modules/Debug.cpp | 2 +- src/Components/Modules/Dvar.cpp | 3 +- src/Components/Modules/GSC/Script.cpp | 74 +++++++--- src/Components/Modules/GSC/Script.hpp | 10 +- .../Modules/GSC/ScriptExtension.cpp | 30 ----- .../Modules/GSC/ScriptExtension.hpp | 1 - src/Components/Modules/GSC/ScriptPatches.cpp | 30 +++++ src/Components/Modules/GSC/ScriptPatches.hpp | 2 + src/Components/Modules/Logger.cpp | 126 +++++++++--------- src/Components/Modules/Node.cpp | 2 +- src/Components/Modules/PlayerName.cpp | 2 +- src/Components/Modules/RCon.cpp | 2 +- src/STDInclude.hpp | 25 ++-- src/Utils/String.cpp | 4 +- src/Utils/String.hpp | 62 ++++++--- 16 files changed, 243 insertions(+), 176 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 9f9c08bb..75d30db1 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -7,10 +7,10 @@ namespace Components struct BotMovementInfo { - int buttons; // Actions - int8_t forward; - int8_t right; - uint16_t weapon; + std::int32_t buttons; // Actions + std::int8_t forward; + std::int8_t right; + std::uint16_t weapon; bool active; }; @@ -19,7 +19,7 @@ namespace Components struct BotAction { std::string action; - int key; + std::int32_t key; }; static const BotAction BotActions[] = @@ -47,7 +47,7 @@ namespace Components static bool loadedNames = false; // Load file only once const char* botName; - if (Bots::BotNames.empty() && !loadedNames) + if (BotNames.empty() && !loadedNames) { FileSystem::File bots("bots.txt"); loadedNames = true; @@ -59,20 +59,20 @@ namespace Components for (auto& name : names) { Utils::String::Replace(name, "\r", ""); - name = Utils::String::Trim(name); + Utils::String::Trim(name); if (!name.empty()) { - Bots::BotNames.push_back(name); + BotNames.push_back(name); } } } } - if (!Bots::BotNames.empty()) + if (!BotNames.empty()) { - botId %= Bots::BotNames.size(); - botName = Bots::BotNames[botId++].data(); + botId %= BotNames.size(); + botName = BotNames[botId++].data(); } else { @@ -125,8 +125,7 @@ namespace Components void Bots::AddMethods() { - Script::AddMethod("IsBot", Bots::GScr_isTestClient); // Usage: self IsBot(); - Script::AddMethod("IsTestClient", Bots::GScr_isTestClient); // Usage: self IsTestClient(); + Script::AddMethMultiple(GScr_isTestClient, false, {"IsTestClient", "IsBot"}); // Usage: self IsTestClient(); Script::AddMethod("BotStop", [](Game::scr_entref_t entref) // Usage: BotStop(); { @@ -240,7 +239,8 @@ namespace Components return; } - Game::usercmd_s userCmd = {0}; + Game::usercmd_s userCmd; + ZeroMemory(&userCmd, sizeof(Game::usercmd_s)); userCmd.serverTime = *Game::svs_time; @@ -260,7 +260,7 @@ namespace Components pushad push edi - call Bots::BotAiAction + call BotAiAction add esp, 4 popad @@ -284,7 +284,7 @@ namespace Components push [esp + 0x20 + 0x8] push [esp + 0x20 + 0x8] - call Bots::G_SelectWeaponIndex + call G_SelectWeaponIndex add esp, 0x8 popad @@ -307,12 +307,12 @@ namespace Components Utils::Hook::Set(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\""); // Intercept sprintf for the connect string - Utils::Hook(0x48ADAB, Bots::BuildConnectString, HOOK_CALL).install()->quick(); + Utils::Hook(0x48ADAB, BuildConnectString, HOOK_CALL).install()->quick(); - Utils::Hook(0x627021, Bots::SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x627241, Bots::SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x627021, SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x627241, SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x441B80, Bots::G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); // Reset BotMovementInfo.active when client is dropped Events::OnClientDisconnect([](const int clientNum) @@ -365,10 +365,10 @@ namespace Components Toast::Show("cardicon_headshot", "^2Success", Utils::String::VA("Spawning %d %s...", count, (count == 1 ? "bot" : "bots")), 3000); Logger::Debug("Spawning {} {}", count, (count == 1 ? "bot" : "bots")); - Bots::Spawn(count); + Spawn(count); }); - Bots::AddMethods(); + AddMethods(); // In case a loaded mod didn't call "BotStop" before the VM shutdown Events::OnVMShutdown([] diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index c0fb92ae..1347d95f 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -318,7 +318,7 @@ namespace Components return; } - if (strncmp(BugName->current.string, "bug", 3) != 0) + if (std::strncmp(BugName->current.string, "bug", 3) != 0) { Game::Dvar_SetString(BugName, "bug0"); return; diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index a01a6314..aaa34ca9 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -229,7 +229,8 @@ namespace Components // Don't perform any checks if name didn't change if (name == lastValidName) return; - std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(Utils::String::Trim(name))); + Utils::String::Trim(name); + std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(name)); if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{')) { Logger::PrintError(Game::CON_CHANNEL_ERROR, "Username '{}' is invalid. It must at least be 3 characters long and not appear empty!\n", name); diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 45bbc432..30126f84 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -3,8 +3,8 @@ namespace Components { - std::unordered_map Script::CustomScrFunctions; - std::unordered_map Script::CustomScrMethods; + std::vector Script::CustomScrFunctions; + std::vector Script::CustomScrMethods; std::string Script::ScriptName; std::vector Script::ScriptNameStack; @@ -278,43 +278,74 @@ namespace Components Game::GScr_LoadGameTypeScript(); } - void Script::AddFunction(const std::string& name, Game::BuiltinFunction func, bool type) + void Script::AddFunction(const std::string& name, const Game::BuiltinFunction func, const bool type) { ScriptFunction toAdd; toAdd.actionFunc = func; toAdd.type = type; + toAdd.aliases.push_back({Utils::String::ToLower(name)}); - CustomScrFunctions.insert_or_assign(Utils::String::ToLower(name), toAdd); + CustomScrFunctions.emplace_back(toAdd); } - void Script::AddMethod(const std::string& name, Game::BuiltinMethod func, bool type) + void Script::AddMethod(const std::string& name, const Game::BuiltinMethod func, const bool type) { ScriptMethod toAdd; toAdd.actionFunc = func; toAdd.type = type; + toAdd.aliases.push_back({Utils::String::ToLower(name)}); - CustomScrMethods.insert_or_assign(Utils::String::ToLower(name), toAdd); + CustomScrMethods.emplace_back(toAdd); + } + + void Script::AddFuncMultiple(Game::BuiltinFunction func, bool type, scriptNames aliases) + { + ScriptFunction toAdd; + auto aliasesToAdd = Utils::String::ApplyToLower(aliases); + + toAdd.actionFunc = func; + toAdd.type = type; + toAdd.aliases = std::move(aliasesToAdd); + + CustomScrFunctions.emplace_back(toAdd); + } + + void Script::AddMethMultiple(Game::BuiltinMethod func, bool type, scriptNames aliases) + { + ScriptMethod toAdd; + auto aliasesToAdd = Utils::String::ApplyToLower(aliases); + + toAdd.actionFunc = func; + toAdd.type = type; + toAdd.aliases = std::move(aliasesToAdd); + + CustomScrMethods.emplace_back(toAdd); } Game::BuiltinFunction Script::BuiltIn_GetFunctionStub(const char** pName, int* type) { if (pName != nullptr) { - // If no function was found let's call game's function - if (const auto itr = CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != CustomScrFunctions.end()) + const auto name = Utils::String::ToLower(*pName); + for (const auto& func : CustomScrFunctions) { - *type = itr->second.type; - return itr->second.actionFunc; - } + if (std::ranges::find(func.aliases, name) != func.aliases.end()) + { + *type = func.type; + return func.actionFunc; + } + } } else { - for (const auto& [name, builtin] : CustomScrFunctions) + for (const auto& func : CustomScrFunctions) { - Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); + const auto& name = func.aliases[0]; + Game::Scr_RegisterFunction(reinterpret_cast(func.actionFunc), name.data()); } } + // If no function was found let's call game's function return Utils::Hook::Call(0x5FA2B0)(pName, type); // BuiltIn_GetFunction } @@ -322,21 +353,26 @@ namespace Components { if (pName != nullptr) { - // If no method was found let's call game's function - if (const auto itr = CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != CustomScrMethods.end()) + const auto name = Utils::String::ToLower(*pName); + for (const auto& meth : CustomScrMethods) { - *type = itr->second.type; - return itr->second.actionFunc; + if (std::ranges::find(meth.aliases, name) != meth.aliases.end()) + { + *type = meth.type; + return meth.actionFunc; + } } } else { - for (const auto& [name, builtin] : CustomScrMethods) + for (const auto& meth : CustomScrMethods) { - Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); + const auto& name = meth.aliases[0]; + Game::Scr_RegisterFunction(reinterpret_cast(meth.actionFunc), name.data()); } } + // If no method was found let's call game's function return Utils::Hook::Call(0x5FA360)(pName, type); // Player_GetMethod } diff --git a/src/Components/Modules/GSC/Script.hpp b/src/Components/Modules/GSC/Script.hpp index 8c4742ba..c3a27a00 100644 --- a/src/Components/Modules/GSC/Script.hpp +++ b/src/Components/Modules/GSC/Script.hpp @@ -7,9 +7,13 @@ namespace Components public: Script(); + using scriptNames = std::vector; static void AddFunction(const std::string& name, Game::BuiltinFunction func, bool type = false); static void AddMethod(const std::string& name, Game::BuiltinMethod func, bool type = false); + static void AddFuncMultiple(Game::BuiltinFunction func, bool type, scriptNames); + static void AddMethMultiple(Game::BuiltinMethod func, bool type, scriptNames); + static Game::client_t* GetClient(const Game::gentity_t* gentity); static const char* GetCodePosForParam(int index); @@ -40,16 +44,18 @@ namespace Components { Game::BuiltinFunction actionFunc; bool type; + scriptNames aliases; }; struct ScriptMethod { Game::BuiltinMethod actionFunc; bool type; + scriptNames aliases; }; - static std::unordered_map CustomScrFunctions; - static std::unordered_map CustomScrMethods; + static std::vector CustomScrFunctions; + static std::vector CustomScrMethods; static std::string ScriptName; static std::vector ScriptNameStack; diff --git a/src/Components/Modules/GSC/ScriptExtension.cpp b/src/Components/Modules/GSC/ScriptExtension.cpp index 94e08aa3..0b30a4f0 100644 --- a/src/Components/Modules/GSC/ScriptExtension.cpp +++ b/src/Components/Modules/GSC/ScriptExtension.cpp @@ -273,30 +273,6 @@ namespace Components }); } - void ScriptExtension::Scr_TableLookupIStringByRow() - { - if (Game::Scr_GetNumParam() < 3) - { - Game::Scr_Error("USAGE: tableLookupIStringByRow( filename, rowNum, returnValueColumnNum )\n"); - return; - } - - const auto* fileName = Game::Scr_GetString(0); - const auto rowNum = Game::Scr_GetInt(1); - const auto returnValueColumnNum = Game::Scr_GetInt(2); - - const auto* table = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, fileName).stringTable; - - if (table == nullptr) - { - Game::Scr_ParamError(0, Utils::String::VA("%s does not exist\n", fileName)); - return; - } - - const auto* value = Game::StringTable_GetColumnValueForRow(table, rowNum, returnValueColumnNum); - Game::Scr_AddIString(value); - } - void ScriptExtension::AddEntityFields() { AddEntityField("entityflags", Game::F_INT, @@ -330,16 +306,10 @@ namespace Components AddEntityFields(); AddClientFields(); - // Correct builtin function pointer - Utils::Hook::Set(0x79A90C, Scr_TableLookupIStringByRow); - Utils::Hook(0x4EC721, GScr_AddFieldsForEntityStub, HOOK_CALL).install()->quick(); // GScr_AddFieldsForEntity Utils::Hook(0x41BED2, Scr_SetObjectFieldStub, HOOK_CALL).install()->quick(); // SetEntityFieldValue Utils::Hook(0x5FBF01, Scr_SetClientFieldStub, HOOK_CALL).install()->quick(); // Scr_SetObjectField Utils::Hook(0x4FF413, Scr_GetEntityFieldStub, HOOK_CALL).install()->quick(); // Scr_GetObjectField - - // Fix format string in Scr_RandomFloatRange - Utils::Hook::Set(0x5F10C6, "Scr_RandomFloatRange parms: %f %f "); } } diff --git a/src/Components/Modules/GSC/ScriptExtension.hpp b/src/Components/Modules/GSC/ScriptExtension.hpp index cc6cb694..c153f24c 100644 --- a/src/Components/Modules/GSC/ScriptExtension.hpp +++ b/src/Components/Modules/GSC/ScriptExtension.hpp @@ -27,6 +27,5 @@ namespace Components static void AddMethods(); static void AddEntityFields(); static void AddClientFields(); - static void Scr_TableLookupIStringByRow(); }; } diff --git a/src/Components/Modules/GSC/ScriptPatches.cpp b/src/Components/Modules/GSC/ScriptPatches.cpp index 4e7843d8..3c2b6197 100644 --- a/src/Components/Modules/GSC/ScriptPatches.cpp +++ b/src/Components/Modules/GSC/ScriptPatches.cpp @@ -20,8 +20,38 @@ namespace Components return &Game::g_hudelems[entref.entnum]; } + void ScriptPatches::Scr_TableLookupIStringByRow_Hk() + { + if (Game::Scr_GetNumParam() < 3) + { + Game::Scr_Error("USAGE: tableLookupIStringByRow( filename, rowNum, returnValueColumnNum )\n"); + return; + } + + const auto* fileName = Game::Scr_GetString(0); + const auto rowNum = Game::Scr_GetInt(1); + const auto returnValueColumnNum = Game::Scr_GetInt(2); + + const auto* table = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, fileName).stringTable; + + if (table == nullptr) + { + Game::Scr_ParamError(0, Utils::String::VA("%s does not exist\n", fileName)); + return; + } + + const auto* value = Game::StringTable_GetColumnValueForRow(table, rowNum, returnValueColumnNum); + Game::Scr_AddIString(value); + } + ScriptPatches::ScriptPatches() { + // Fix format string in Scr_RandomFloatRange + Utils::Hook::Set(0x5F10C6, "Scr_RandomFloatRange parms: %f %f "); + + // Correct builtin function pointer + Utils::Hook::Set(0x79A90C, Scr_TableLookupIStringByRow_Hk); + Script::AddMethod("ClearHudText", [](Game::scr_entref_t entref) -> void { auto* hud = HECmd_GetHudElem(entref); diff --git a/src/Components/Modules/GSC/ScriptPatches.hpp b/src/Components/Modules/GSC/ScriptPatches.hpp index cf4787d0..6d69a2fd 100644 --- a/src/Components/Modules/GSC/ScriptPatches.hpp +++ b/src/Components/Modules/GSC/ScriptPatches.hpp @@ -9,5 +9,7 @@ namespace Components private: static Game::game_hudelem_s* HECmd_GetHudElem(Game::scr_entref_t entref); + + static void Scr_TableLookupIStringByRow_Hk(); }; } diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 7d24c198..9b9e8257 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -22,7 +22,7 @@ namespace Components _vsnprintf_s(buf, _TRUNCATE, message, va); va_end(va); - Logger::MessagePrint(channel, {buf}); + MessagePrint(channel, {buf}); } void Logger::MessagePrint(const int channel, const std::string& msg) @@ -42,14 +42,14 @@ namespace Components return; } - if (!Logger::IsConsoleReady()) + if (!IsConsoleReady()) { OutputDebugStringA(out.data()); } if (!Game::Sys_IsMainThread()) { - Logger::EnqueueMessage(msg); + EnqueueMessage(msg); } else { @@ -67,14 +67,14 @@ namespace Components const auto out = std::format("^2{}\n", msg); #endif - Logger::MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); + MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); } void Logger::PrintInternal(int channel, std::string_view fmt, std::format_args&& args) { const auto msg = std::vformat(fmt, args); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); } void Logger::ErrorInternal(const Game::errorParm_t error, const std::string_view fmt, std::format_args&& args) @@ -92,7 +92,7 @@ namespace Components const auto msg = "^1Error: " + std::vformat(fmt, args); ++(*Game::com_errorPrintsCount); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); if (*Game::cls_uiStarted != 0 && (*Game::com_fixedConsolePosition == 0)) { @@ -104,36 +104,36 @@ namespace Components { const auto msg = "^3" + std::vformat(fmt, args); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); } void Logger::Frame() { - std::unique_lock _(Logger::MessageMutex); + std::unique_lock _(MessageMutex); - for (auto i = Logger::MessageQueue.begin(); i != Logger::MessageQueue.end();) + for (auto i = MessageQueue.begin(); i != MessageQueue.end();) { Game::Com_PrintMessage(Game::CON_CHANNEL_DONT_FILTER, i->data(), 0); - if (!Logger::IsConsoleReady()) + if (!IsConsoleReady()) { OutputDebugStringA(i->data()); } - i = Logger::MessageQueue.erase(i); + i = MessageQueue.erase(i); } } void Logger::PipeOutput(const std::function& callback) { - Logger::PipeCallback = callback; + PipeCallback = callback; } void Logger::PrintMessagePipe(const char* data) { - if (Logger::PipeCallback) + if (PipeCallback) { - Logger::PipeCallback(data); + PipeCallback(data); } } @@ -144,7 +144,7 @@ namespace Components return; } - for (const auto& addr : Logger::LoggingAddresses[gLog & 1]) + for (const auto& addr : LoggingAddresses[gLog & 1]) { Network::SendCommand(addr, "print", data); } @@ -169,20 +169,20 @@ namespace Components } // Allow the network log to run even if logFile was not opened - Logger::NetworkLog(string, true); + NetworkLog(string, true); } __declspec(naked) void Logger::PrintMessage_Stub() { __asm { - mov eax, Logger::PipeCallback + mov eax, PipeCallback test eax, eax jz returnPrint pushad push [esp + 28h] - call Logger::PrintMessagePipe + call PrintMessagePipe add esp, 4h popad retn @@ -191,7 +191,7 @@ namespace Components pushad push 0 push [esp + 2Ch] - call Logger::NetworkLog + call NetworkLog add esp, 8h popad @@ -205,8 +205,8 @@ namespace Components void Logger::EnqueueMessage(const std::string& message) { - std::unique_lock _(Logger::MessageMutex); - Logger::MessageQueue.push_back(message); + std::unique_lock _(MessageMutex); + MessageQueue.push_back(message); } void Logger::RedirectOSPath(const char* file, char* folder) @@ -232,7 +232,7 @@ namespace Components push [esp + 28h] push [esp + 30h] - call Logger::RedirectOSPath + call RedirectOSPath add esp, 8h @@ -256,9 +256,9 @@ namespace Components Network::Address addr(params->get(1)); - if (std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr) == Logger::LoggingAddresses[0].end()) + if (std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr) == LoggingAddresses[0].end()) { - Logger::LoggingAddresses[0].push_back(addr); + LoggingAddresses[0].push_back(addr); } }); @@ -267,37 +267,37 @@ namespace Components if (params->size() < 2) return; const auto num = atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[0].size()) + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[0].size()) { auto addr = Logger::LoggingAddresses[0].begin() + num; - Logger::Print("Address {} removed\n", addr->getString()); - Logger::LoggingAddresses[0].erase(addr); + Print("Address {} removed\n", addr->getString()); + LoggingAddresses[0].erase(addr); } else { Network::Address addr(params->get(1)); - const auto i = std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr); - if (i != Logger::LoggingAddresses[0].end()) + const auto i = std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr); + if (i != LoggingAddresses[0].end()) { - Logger::LoggingAddresses[0].erase(i); - Logger::Print("Address {} removed\n", addr.getString()); + LoggingAddresses[0].erase(i); + Print("Address {} removed\n", addr.getString()); } else { - Logger::Print("Address {} not found!\n", addr.getString()); + Print("Address {} not found!\n", addr.getString()); } } }); - Command::AddSV("log_list", [](Command::Params*) + Command::AddSV("log_list", []([[maybe_unused]] Command::Params* params) { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); + Print("# ID: Address\n"); + Print("-------------\n"); - for (unsigned int i = 0; i < Logger::LoggingAddresses[0].size(); ++i) + for (unsigned int i = 0; i < LoggingAddresses[0].size(); ++i) { - Logger::Print("#{:03d}: {}\n", i, Logger::LoggingAddresses[0][i].getString()); + Print("#{:03d}: {}\n", i, LoggingAddresses[0][i].getString()); } }); @@ -307,9 +307,9 @@ namespace Components const Network::Address addr(params->get(1)); - if (std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr) == Logger::LoggingAddresses[1].end()) + if (std::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr) == LoggingAddresses[1].end()) { - Logger::LoggingAddresses[1].push_back(addr); + LoggingAddresses[1].push_back(addr); } }); @@ -318,37 +318,37 @@ namespace Components if (params->size() < 2) return; const auto num = std::atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[1].size()) + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[1].size()) { - const auto addr = Logger::LoggingAddresses[1].begin() + num; - Logger::Print("Address {} removed\n", addr->getString()); - Logger::LoggingAddresses[1].erase(addr); + const auto addr = LoggingAddresses[1].begin() + num; + Print("Address {} removed\n", addr->getString()); + LoggingAddresses[1].erase(addr); } else { const Network::Address addr(params->get(1)); - const auto i = std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr); - if (i != Logger::LoggingAddresses[1].end()) + const auto i = std::ranges::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr); + if (i != LoggingAddresses[1].end()) { - Logger::LoggingAddresses[1].erase(i); - Logger::Print("Address {} removed\n", addr.getString()); + LoggingAddresses[1].erase(i); + Print("Address {} removed\n", addr.getString()); } else { - Logger::Print("Address {} not found!\n", addr.getString()); + Print("Address {} not found!\n", addr.getString()); } } }); Command::AddSV("g_log_list", [](Command::Params*) { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); + Print("# ID: Address\n"); + Print("-------------\n"); - for (std::size_t i = 0; i < Logger::LoggingAddresses[1].size(); ++i) + for (std::size_t i = 0; i < LoggingAddresses[1].size(); ++i) { - Logger::Print("#{:03d}: {}\n", i, Logger::LoggingAddresses[1][i].getString()); + Print("#{:03d}: {}\n", i, LoggingAddresses[1][i].getString()); } }); } @@ -356,30 +356,28 @@ namespace Components Logger::Logger() { Dvar::Register("iw4x_onelog", false, Game::DVAR_LATCH | Game::DVAR_ARCHIVE, "Only write the game log to the 'userraw' OS folder"); - Utils::Hook(0x642139, Logger::BuildOSPath_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x642139, BuildOSPath_Stub, HOOK_JUMP).install()->quick(); - Logger::PipeOutput(nullptr); + Scheduler::Loop(Frame, Scheduler::Pipeline::SERVER); - Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::SERVER); - - Utils::Hook(Game::G_LogPrintf, Logger::G_LogPrintf_Hk, HOOK_JUMP).install()->quick(); - Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessage_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::G_LogPrintf, G_LogPrintf_Hk, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::Com_PrintMessage, PrintMessage_Stub, HOOK_JUMP).install()->quick(); if (Loader::IsPerformingUnitTests()) { - Utils::Hook(Game::Com_Printf, Logger::Print_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::Com_Printf, Print_Stub, HOOK_JUMP).install()->quick(); } - Events::OnSVInit(Logger::AddServerCommands); + Events::OnSVInit(AddServerCommands); } Logger::~Logger() { - Logger::LoggingAddresses[0].clear(); - Logger::LoggingAddresses[1].clear(); + LoggingAddresses[0].clear(); + LoggingAddresses[1].clear(); - std::unique_lock lock(Logger::MessageMutex); - Logger::MessageQueue.clear(); + std::unique_lock lock(MessageMutex); + MessageQueue.clear(); lock.unlock(); // Flush the console log diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 6ebe6811..19ce000c 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -59,7 +59,7 @@ namespace Components for (auto& node : nodeList) { Utils::String::Replace(node, "\r", ""); - node = Utils::String::Trim(node); + Utils::String::Trim(node); Node::Add(node); } } diff --git a/src/Components/Modules/PlayerName.cpp b/src/Components/Modules/PlayerName.cpp index 11ca774d..5d69c66a 100644 --- a/src/Components/Modules/PlayerName.cpp +++ b/src/Components/Modules/PlayerName.cpp @@ -18,7 +18,7 @@ namespace Components } std::string readablePlayerName(buffer); - readablePlayerName = Utils::String::Trim(readablePlayerName); + Utils::String::Trim(readablePlayerName); if (readablePlayerName.size() < 3) { diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 57fa3324..b7c0ab20 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -127,8 +127,8 @@ namespace Components Network::OnClientPacket("rcon", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { std::string data_ = data; - Utils::String::Trim(data_); + const auto pos = data.find_first_of(' '); if (pos == std::string::npos) { diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 2e994240..71999f73 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -28,23 +28,24 @@ #pragma warning(disable: 4244) #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #pragma warning(pop) diff --git a/src/Utils/String.cpp b/src/Utils/String.cpp index 13e18025..f14ecd31 100644 --- a/src/Utils/String.cpp +++ b/src/Utils/String.cpp @@ -145,9 +145,9 @@ namespace Utils::String } // Trim from both ends - std::string& Trim(std::string& str) + void Trim(std::string& str) { - return LTrim(RTrim(str)); + LTrim(RTrim(str)); } std::string Convert(const std::wstring& wstr) diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index 84c900fb..cf2417f3 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -11,7 +11,7 @@ namespace Utils::String VAProvider() : currentBuffer(0) {} ~VAProvider() = default; - const char* get(const char* format, va_list ap) + [[nodiscard]] const char* get(const char* format, va_list ap) { ++this->currentBuffer %= ARRAYSIZE(this->stringPool); auto entry = &this->stringPool[this->currentBuffer]; @@ -82,37 +82,61 @@ namespace Utils::String } } - const char* VA(const char* fmt, ...); + [[nodiscard]] const char* VA(const char* fmt, ...); - std::string ToLower(const std::string& text); - std::string ToUpper(const std::string& text); + [[nodiscard]] std::string ToLower(const std::string& text); + [[nodiscard]] std::string ToUpper(const std::string& text); - bool Compare(const std::string& lhs, const std::string& rhs); + template + [[nodiscard]] OutputIter ApplyToLower(OutputIter container) + { + OutputIter result; + std::ranges::transform(container, std::back_inserter(result), [](const std::string& s) -> std::string + { + return ToLower(s); + }); - std::vector Split(const std::string& str, char delim); + return result; + } + + template + [[nodiscard]] OutputIter ApplyToUpper(OutputIter container) + { + OutputIter result; + std::ranges::transform(container, std::back_inserter(result), [](const std::string& s) -> std::string + { + return ToUpper(s); + }); + + return result; + } + + [[nodiscard]] bool Compare(const std::string& lhs, const std::string& rhs); + + [[nodiscard]] std::vector Split(const std::string& str, char delim); void Replace(std::string& str, const std::string& from, const std::string& to); - bool StartsWith(const std::string& haystack, const std::string& needle); - bool EndsWith(const std::string& haystack, const std::string& needle); + [[nodiscard]] bool StartsWith(const std::string& haystack, const std::string& needle); + [[nodiscard]] bool EndsWith(const std::string& haystack, const std::string& needle); - bool IsNumber(const std::string& str); + [[nodiscard]] bool IsNumber(const std::string& str); std::string& LTrim(std::string& str); std::string& RTrim(std::string& str); - std::string& Trim(std::string& str); + void Trim(std::string& str); - std::string Convert(const std::wstring& wstr); - std::wstring Convert(const std::string& str); + [[nodiscard]] std::string Convert(const std::wstring& wstr); + [[nodiscard]] std::wstring Convert(const std::string& str); - std::string FormatTimeSpan(int milliseconds); - std::string FormatBandwidth(std::size_t bytes, int milliseconds); + [[nodiscard]] std::string FormatTimeSpan(int milliseconds); + [[nodiscard]] std::string FormatBandwidth(std::size_t bytes, int milliseconds); - std::string DumpHex(const std::string& data, const std::string& separator = " "); + [[nodiscard]] std::string DumpHex(const std::string& data, const std::string& separator = " "); - std::string XOR(std::string str, char value); + [[nodiscard]] std::string XOR(std::string str, char value); - std::string EncodeBase64(const char* input, unsigned long inputSize); - std::string EncodeBase64(const std::string& input); + [[nodiscard]] std::string EncodeBase64(const char* input, unsigned long inputSize); + [[nodiscard]] std::string EncodeBase64(const std::string& input); - std::string EncodeBase128(const std::string& input); + [[nodiscard]] std::string EncodeBase128(const std::string& input); } From 845b9e0341c48b549054f0b728ec32b8815e0aed Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 29 Nov 2022 16:01:20 +0000 Subject: [PATCH 25/96] [Script]: Use .at instead of [] (#611) * [Script]: Use .at instead of [] * [Script]: Fix typo --- src/Components/Modules/GSC/Script.cpp | 4 ++-- src/STDInclude.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 30126f84..19693cb5 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -340,7 +340,7 @@ namespace Components { for (const auto& func : CustomScrFunctions) { - const auto& name = func.aliases[0]; + const auto& name = func.aliases.at(0); Game::Scr_RegisterFunction(reinterpret_cast(func.actionFunc), name.data()); } } @@ -367,7 +367,7 @@ namespace Components { for (const auto& meth : CustomScrMethods) { - const auto& name = meth.aliases[0]; + const auto& name = meth.aliases.at(0); Game::Scr_RegisterFunction(reinterpret_cast(meth.actionFunc), name.data()); } } diff --git a/src/STDInclude.cpp b/src/STDInclude.cpp index 534f0160..81dd2b0a 100644 --- a/src/STDInclude.cpp +++ b/src/STDInclude.cpp @@ -78,37 +78,37 @@ static_assert(sizeof(intptr_t) == 4 && sizeof(void*) == 4 && sizeof(size_t) == 4 // ReSharper restore CppRedundantBooleanExpressionArgument #if !defined(_M_IX86) -#error "Invalid processor achritecture!" +#error "Invalid processor architecture!" #endif extern "C" { - // Disable telemetry data logging + // Disable telemetry data logging void __cdecl __vcrt_initialize_telemetry_provider() {} void __cdecl __telemetry_main_invoke_trigger() {} void __cdecl __telemetry_main_return_trigger() {} void __cdecl __vcrt_uninitialize_telemetry_provider() {} // Enable 'High Performance Graphics' - __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; // Tommath fixes - int s_read_arc4random(void*, size_t) + int s_read_arc4random(void*, std::size_t) { return -1; } - int s_read_getrandom(void*, size_t) + int s_read_getrandom(void*, std::size_t) { return -1; } - int s_read_urandom(void*, size_t) + int s_read_urandom(void*, std::size_t) { return -1; } - int s_read_ltm_rng(void*, size_t) + int s_read_ltm_rng(void*, std::size_t) { return -1; } From 0ece6c4f8cbed062a195dfedd82c1479625061dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 17:03:05 +0000 Subject: [PATCH 26/96] Bump deps/mongoose from `a74d373` to `2553392` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `a74d373` to `2553392`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/a74d3737dc4ff18441fa092c9d13ec59f0701c11...2553392e421fde36d1af81978af9d4cadffd90d5) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index a74d3737..2553392e 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit a74d3737dc4ff18441fa092c9d13ec59f0701c11 +Subproject commit 2553392e421fde36d1af81978af9d4cadffd90d5 From 874a8027afccf918ffa372a3f7c1f6f73841292d Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 1 Dec 2022 00:00:18 +0000 Subject: [PATCH 27/96] [Vote]: Add menus (#613) --- src/Components/Modules/Menus.cpp | 6 ++++++ src/Components/Modules/Vote.cpp | 7 ++++++- src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 9 ++++++--- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index ae04d35c..122a35d6 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -768,6 +768,11 @@ namespace Components Menus::Menus() { + if (ZoneBuilder::IsEnabled()) + { + Game::Menu_Setup(Game::uiContext); + } + if (Dedicated::IsEnabled()) return; // Ensure everything is zero'ed @@ -870,6 +875,7 @@ namespace Components Menus::~Menus() { + // In your dreams! Menus::FreeEverything(); } } diff --git a/src/Components/Modules/Vote.cpp b/src/Components/Modules/Vote.cpp index 3a74336b..ccf01c45 100644 --- a/src/Components/Modules/Vote.cpp +++ b/src/Components/Modules/Vote.cpp @@ -316,11 +316,16 @@ namespace Components Vote::Vote() { // Replicate g_allowVote - Utils::Hook::Set(0x5E3A4F, Game::DVAR_INTERNAL | Game::DVAR_CODINFO); + Utils::Hook::Set(0x5E3A4F, Game::DVAR_INTERNAL | Game::DVAR_CODINFO); ClientCommand::Add("callvote", Cmd_CallVote_f); ClientCommand::Add("vote", Cmd_Vote_f); + Menus::Add("ui_mp/scriptmenus/callvote.menu"); + Menus::Add("ui_mp/scriptmenus/kickplayer.menu"); + Menus::Add("ui_mp/scriptmenus/changegametype.menu"); + Menus::Add("ui_mp/scriptmenus/changemap.menu"); + UIScript::Add("voteKick", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { if (info->playerIndex >= 0 && info->playerIndex < Game::sharedUiInfo->playerCount) diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index f776c2a6..9162125c 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -83,6 +83,7 @@ namespace Game Menus_MenuIsInStack_t Menus_MenuIsInStack = Menus_MenuIsInStack_t(0x47ACB0); Menu_HandleKey_t Menu_HandleKey = Menu_HandleKey_t(0x4C4A00); Menu_GetFocused_t Menu_GetFocused = Menu_GetFocused_t(0x4AFF10); + Menu_Setup_t Menu_Setup = Menu_Setup_t(0x415AD0); MSG_Init_t MSG_Init = MSG_Init_t(0x45FCA0); MSG_ReadBit_t MSG_ReadBit = MSG_ReadBit_t(0x476D20); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index cd1c7c30..2998bae5 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -173,7 +173,7 @@ namespace Game typedef int(*Menus_OpenByName_t)(UiContext* dc, const char* p); extern Menus_OpenByName_t Menus_OpenByName; - typedef menuDef_t *(*Menus_FindByName_t)(UiContext* dc, const char* name); + typedef menuDef_t*(*Menus_FindByName_t)(UiContext* dc, const char* name); extern Menus_FindByName_t Menus_FindByName; typedef bool(*Menu_IsVisible_t)(UiContext* dc, menuDef_t* menu); @@ -182,11 +182,14 @@ namespace Game typedef bool(*Menus_MenuIsInStack_t)(UiContext* dc, menuDef_t* menu); extern Menus_MenuIsInStack_t Menus_MenuIsInStack; + typedef void(*Menu_HandleKey_t)(UiContext* ctx, menuDef_t* menu, Game::keyNum_t key, int down); + extern Menu_HandleKey_t Menu_HandleKey; + typedef menuDef_t*(*Menu_GetFocused_t)(UiContext* ctx); extern Menu_GetFocused_t Menu_GetFocused; - typedef void(*Menu_HandleKey_t)(UiContext* ctx, menuDef_t* menu, Game::keyNum_t key, int down); - extern Menu_HandleKey_t Menu_HandleKey; + typedef void(*Menu_Setup_t)(UiContext* dc); + extern Menu_Setup_t Menu_Setup; typedef bool(*UI_KeyEvent_t)(int clientNum, int key, int down); extern UI_KeyEvent_t UI_KeyEvent; From 7778798f17e284e54a07cad8b9f293263959549a Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 1 Dec 2022 14:04:30 +0000 Subject: [PATCH 28/96] [Zone:b:uilder]: Fix rawfiles (#614) --- .../Modules/AssetInterfaces/IRawFile.cpp | 13 +- src/Components/Modules/ZoneBuilder.cpp | 6 +- src/Game/Structs.hpp | 1274 ++++++++--------- 3 files changed, 649 insertions(+), 644 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.cpp b/src/Components/Modules/AssetInterfaces/IRawFile.cpp index 1b531f62..603a4d7c 100644 --- a/src/Components/Modules/AssetInterfaces/IRawFile.cpp +++ b/src/Components/Modules/AssetInterfaces/IRawFile.cpp @@ -18,18 +18,21 @@ namespace Assets return; } - const auto data = Utils::Compression::ZLib::Compress(rawFile.getBuffer()); + auto compressed_size = compressBound(rawFile.getBuffer().size()); asset->name = builder->getAllocator()->duplicateString(name); + asset->len = static_cast(rawFile.getBuffer().size()); - if (data.size() < rawFile.getBuffer().size()) + if (asset->len < static_cast(compressed_size)) { - asset->buffer = builder->getAllocator()->duplicateString(data); - asset->compressedLen = static_cast(data.size()); + asset->buffer = builder->getAllocator()->allocateArray(compressed_size); + compress2((Bytef*)(asset->buffer), &compressed_size, (const Bytef*)(rawFile.getBuffer().data()), rawFile.getBuffer().size(), Z_BEST_COMPRESSION); + asset->compressedLen = static_cast(compressed_size); } else { - asset->buffer = builder->getAllocator()->duplicateString(rawFile.getBuffer()); + asset->buffer = builder->getAllocator()->allocateArray(rawFile.getBuffer().size() + 1); + std::memcpy(const_cast(asset->buffer), rawFile.getBuffer().data(), rawFile.getBuffer().size()); asset->compressedLen = 0; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 38b73487..33ac55a4 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -518,8 +518,10 @@ namespace Components // Add branding asset void ZoneBuilder::Zone::addBranding() { - const char* data = "FastFile built using the IW4x ZoneBuilder!"; - this->branding = { this->zoneName.data(), static_cast(strlen(data)), 0, data }; + constexpr auto* data = "Built using the IW4x Zone:B:uilder Version 4"; + auto dataLen = std::strlen(data) + 1; + + this->branding = { this->zoneName.data(), 0, static_cast(dataLen), data }; if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1) { diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 79b398fd..9450e942 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -28,8 +28,8 @@ namespace Game unsigned __int16 classnum; }; - typedef void(__cdecl * BuiltinFunction)(); - typedef void(__cdecl * BuiltinMethod)(scr_entref_t); + typedef void(__cdecl* BuiltinFunction)(); + typedef void(__cdecl* BuiltinMethod)(scr_entref_t); struct BuiltinFunctionDef { @@ -149,7 +149,7 @@ namespace Game DVAR_NONE = 0, // No flags DVAR_ARCHIVE = 1 << 0, // Set to cause it to be saved to config_mp.cfg of the client DVAR_LATCH = 1 << 1, // Will only change when C code next does a Dvar_Get(), so it can't be changed - // without proper initialization. Modified will be set, even though the value hasn't changed yet + // without proper initialization. Modified will be set, even though the value hasn't changed yet DVAR_CHEAT = 1 << 2, // Can not be changed if cheats are disabled DVAR_CODINFO = 1 << 3, // On change, this is sent to all clients (if you are host) DVAR_SCRIPTINFO = 1 << 4, @@ -414,11 +414,11 @@ namespace Game typedef struct cmd_function_s { - cmd_function_s *next; - const char *name; - const char *autoCompleteDir; - const char *autoCompleteExt; - void(__cdecl *function)(); + cmd_function_s* next; + const char* name; + const char* autoCompleteDir; + const char* autoCompleteExt; + void(__cdecl* function)(); int flags; } cmd_function_t; @@ -603,14 +603,14 @@ namespace Game struct __declspec(align(4)) PhysPreset { - const char *name; + const char* name; int type; float mass; float bounce; float friction; float bulletForceScale; float explosiveForceScale; - const char *sndAliasPrefix; + const char* sndAliasPrefix; float piecesSpreadFraction; float piecesUpwardVelocity; bool tempDefaultToCylinder; @@ -633,7 +633,7 @@ namespace Game struct cbrushside_t { - cplane_s *plane; + cplane_s* plane; unsigned __int16 materialNum; char firstAdjacentSideOffset; char edgeCount; @@ -643,8 +643,8 @@ namespace Game { unsigned __int16 numsides; unsigned __int16 glassPieceIndex; - cbrushside_t *sides; - char *baseAdjacentSide; + cbrushside_t* sides; + char* baseAdjacentSide; __int16 axialMaterialNum[2][3]; char firstAdjacentSideOffsets[2][3]; char edgeCount[2][3]; @@ -655,12 +655,12 @@ namespace Game Bounds bounds; cbrush_t brush; int totalEdgeCount; - cplane_s *planes; + cplane_s* planes; }; struct PhysGeomInfo { - BrushWrapper *brushWrapper; + BrushWrapper* brushWrapper; int type; float orientation[3][3]; Bounds bounds; @@ -675,18 +675,18 @@ namespace Game struct PhysCollmap { - const char *name; + const char* name; unsigned int count; - PhysGeomInfo *geoms; + PhysGeomInfo* geoms; PhysMass mass; Bounds bounds; }; union XAnimIndices { - char *_1; - unsigned __int16 *_2; - void *data; + char* _1; + unsigned __int16* _2; + void* data; }; struct XAnimNotifyInfo @@ -766,14 +766,14 @@ namespace Game struct XAnimDeltaPart { - XAnimPartTrans *trans; - XAnimDeltaPartQuat2 *quat2; - XAnimDeltaPartQuat *quat; + XAnimPartTrans* trans; + XAnimDeltaPartQuat2* quat2; + XAnimDeltaPartQuat* quat; }; struct XAnimParts { - const char *name; + const char* name; unsigned __int16 dataByteCount; unsigned __int16 dataShortCount; unsigned __int16 dataIntCount; @@ -789,22 +789,22 @@ namespace Game unsigned int indexCount; float framerate; float frequency; - unsigned __int16 *names; - char *dataByte; - __int16 *dataShort; - int *dataInt; - __int16 *randomDataShort; - char *randomDataByte; - int *randomDataInt; + unsigned __int16* names; + char* dataByte; + __int16* dataShort; + int* dataInt; + __int16* randomDataShort; + char* randomDataByte; + int* randomDataInt; XAnimIndices indices; - XAnimNotifyInfo *notify; - XAnimDeltaPart *deltaPart; + XAnimNotifyInfo* notify; + XAnimDeltaPart* deltaPart; }; struct XSurfaceVertexInfo { __int16 vertCount[4]; - unsigned __int16 *vertsBlend; + unsigned __int16* vertsBlend; }; union GfxColor @@ -857,9 +857,9 @@ namespace Game float trans[3]; float scale[3]; unsigned int nodeCount; - XSurfaceCollisionNode *nodes; + XSurfaceCollisionNode* nodes; unsigned int leafCount; - XSurfaceCollisionLeaf *leafs; + XSurfaceCollisionLeaf* leafs; }; struct XRigidVertList @@ -868,7 +868,7 @@ namespace Game unsigned __int16 vertCount; unsigned __int16 triOffset; unsigned __int16 triCount; - XSurfaceCollisionTree *collisionTree; + XSurfaceCollisionTree* collisionTree; }; struct XSurface @@ -880,18 +880,18 @@ namespace Game char zoneHandle; unsigned __int16 baseTriIndex; unsigned __int16 baseVertIndex; - unsigned __int16 *triIndices; + unsigned __int16* triIndices; XSurfaceVertexInfo vertInfo; - GfxPackedVertex *verts0; + GfxPackedVertex* verts0; unsigned int vertListCount; - XRigidVertList *vertList; + XRigidVertList* vertList; int partBits[6]; }; struct XModelSurfs { - const char *name; - XSurface *surfs; + const char* name; + XSurface* surfs; unsigned __int16 numsurfs; int partBits[6]; }; @@ -926,7 +926,7 @@ namespace Game struct /*__declspec(align(4))*/ MaterialInfo { - const char *name; + const char* name; char gameFlags; char sortKey; unsigned char textureAtlasRowCount; @@ -945,12 +945,12 @@ namespace Game struct MaterialVertexStreamRouting { MaterialStreamRouting data[13]; - IDirect3DVertexDeclaration9 *decl[16]; + IDirect3DVertexDeclaration9* decl[16]; }; struct MaterialVertexDeclaration { - const char *name; + const char* name; char streamCount; bool hasOptionalSource; MaterialVertexStreamRouting routing; @@ -958,39 +958,39 @@ namespace Game struct GfxVertexShaderLoadDef { - unsigned int *program; + unsigned int* program; unsigned __int16 programSize; unsigned __int16 loadForRenderer; }; struct MaterialVertexShaderProgram { - IDirect3DVertexShader9 *vs; + IDirect3DVertexShader9* vs; GfxVertexShaderLoadDef loadDef; }; struct MaterialVertexShader { - const char *name; + const char* name; MaterialVertexShaderProgram prog; }; struct GfxPixelShaderLoadDef { - unsigned int *program; + unsigned int* program; unsigned __int16 programSize; unsigned __int16 loadForRenderer; }; struct MaterialPixelShaderProgram { - IDirect3DPixelShader9 *ps; + IDirect3DPixelShader9* ps; GfxPixelShaderLoadDef loadDef; }; struct MaterialPixelShader { - const char *name; + const char* name; MaterialPixelShaderProgram prog; }; @@ -1003,7 +1003,7 @@ namespace Game union MaterialArgumentDef { - const float *literalConst; + const float* literalConst; MaterialArgumentCodeConst codeConst; unsigned int codeSampler; unsigned int nameHash; @@ -1018,14 +1018,14 @@ namespace Game struct MaterialPass { - MaterialVertexDeclaration *vertexDecl; - MaterialVertexShader *vertexShader; - MaterialPixelShader *pixelShader; + MaterialVertexDeclaration* vertexDecl; + MaterialVertexShader* vertexShader; + MaterialPixelShader* pixelShader; char perPrimArgCount; char perObjArgCount; char stableArgCount; char customSamplerFlags; - MaterialShaderArgument *args; + MaterialShaderArgument* args; }; struct visionSetVars_t @@ -1880,7 +1880,7 @@ namespace Game struct MaterialTechnique { - const char *name; + const char* name; unsigned __int16 flags; unsigned __int16 passCount; MaterialPass passArray[1]; @@ -1888,12 +1888,12 @@ namespace Game struct MaterialTechniqueSet { - const char *name; + const char* name; char worldVertFormat; bool hasBeenUploaded; char unused[1]; - MaterialTechniqueSet *remappedTechniqueSet; - MaterialTechnique *techniques[48]; + MaterialTechniqueSet* remappedTechniqueSet; + MaterialTechnique* techniques[48]; }; struct GfxImageLoadDefIW3 @@ -1918,11 +1918,11 @@ namespace Game union GfxTexture { - IDirect3DBaseTexture9 *basemap; - IDirect3DTexture9 *map; - IDirect3DVolumeTexture9 *volmap; - IDirect3DCubeTexture9 *cubemap; - GfxImageLoadDef *loadDef; + IDirect3DBaseTexture9* basemap; + IDirect3DTexture9* map; + IDirect3DVolumeTexture9* volmap; + IDirect3DCubeTexture9* cubemap; + GfxImageLoadDef* loadDef; }; struct Picmip @@ -1950,7 +1950,7 @@ namespace Game unsigned __int16 height; unsigned __int16 depth; bool delayLoadPixels; - const char *name; + const char* name; }; struct WaterWritable @@ -1967,8 +1967,8 @@ namespace Game struct water_t { WaterWritable writable; - complex_s *H0; - float *wTerm; + complex_s* H0; + float* wTerm; int M; int N; float Lx; @@ -1978,13 +1978,13 @@ namespace Game float winddir[2]; float amplitude; float codeConstant[4]; - GfxImage *image; + GfxImage* image; }; union MaterialTextureDefInfo { - GfxImage *image; - water_t *water; + GfxImage* image; + water_t* water; }; struct MaterialTextureDef @@ -2018,10 +2018,10 @@ namespace Game unsigned char stateBitsCount; char stateFlags; char cameraRegion; - MaterialTechniqueSet *techniqueSet; - MaterialTextureDef *textureTable; - MaterialConstantDef *constantTable; - GfxStateBits *stateBitsTable; + MaterialTechniqueSet* techniqueSet; + MaterialTextureDef* textureTable; + MaterialConstantDef* constantTable; + GfxStateBits* stateBitsTable; }; struct XModelLodInfo @@ -2029,9 +2029,9 @@ namespace Game float dist; unsigned __int16 numsurfs; unsigned __int16 surfIndex; - XModelSurfs *modelSurfs; + XModelSurfs* modelSurfs; int partBits[6]; - XSurface *surfs; + XSurface* surfs; char lod; char smcBaseIndexPlusOne; char smcSubIndexMask; @@ -2047,7 +2047,7 @@ namespace Game struct XModelCollSurf_s { - XModelCollTri_s *collTris; + XModelCollTri_s* collTris; int numCollTris; Bounds bounds; int boneIdx; @@ -2063,66 +2063,66 @@ namespace Game struct XModel { - const char *name; + const char* name; char numBones; char numRootBones; unsigned char numsurfs; char lodRampType; float scale; unsigned int noScalePartBits[6]; - unsigned __int16 *boneNames; - char *parentList; - __int16 *quats; - float *trans; - char *partClassification; - DObjAnimMat *baseMat; - Material **materialHandles; + unsigned __int16* boneNames; + char* parentList; + __int16* quats; + float* trans; + char* partClassification; + DObjAnimMat* baseMat; + Material** materialHandles; XModelLodInfo lodInfo[4]; char maxLoadedLod; char numLods; char collLod; char flags; - XModelCollSurf_s *collSurfs; + XModelCollSurf_s* collSurfs; int numCollSurfs; int contents; - XBoneInfo *boneInfo; + XBoneInfo* boneInfo; float radius; Bounds bounds; int memUsage; bool bad; - PhysPreset *physPreset; - PhysCollmap *physCollmap; + PhysPreset* physPreset; + PhysCollmap* physCollmap; }; struct _AILSOUNDINFO { int format; - const void *data_ptr; + const void* data_ptr; unsigned int data_len; unsigned int rate; int bits; int channels; unsigned int samples; unsigned int block_size; - const void *initial_ptr; + const void* initial_ptr; }; struct MssSound { _AILSOUNDINFO info; - char *data; + char* data; }; struct LoadedSound { - const char *name; + const char* name; MssSound sound; }; struct StreamFileNameRaw { - const char *dir; - const char *name; + const char* dir; + const char* name; }; union StreamFileInfo @@ -2142,7 +2142,7 @@ namespace Game union SoundFileRef { - LoadedSound *loadSnd; + LoadedSound* loadSnd; StreamedSound streamSnd; }; @@ -2170,7 +2170,7 @@ namespace Game struct SndCurve { - const char *filename; + const char* filename; unsigned __int16 knotCount; float knots[16][2]; }; @@ -2191,18 +2191,18 @@ namespace Game struct SpeakerMap { bool isDefault; - const char *name; + const char* name; MSSChannelMap channelMaps[2][2]; }; const struct snd_alias_t { - const char *aliasName; - const char *subtitle; - const char *secondaryAliasName; - const char *chainAliasName; - const char *mixerGroup; - SoundFile *soundFile; + const char* aliasName; + const char* subtitle; + const char* secondaryAliasName; + const char* chainAliasName; + const char* mixerGroup; + SoundFile* soundFile; int sequence; float volMin; float volMax; @@ -2217,23 +2217,23 @@ namespace Game float lfePercentage; float centerPercentage; int startDelay; - SndCurve *volumeFalloffCurve; + SndCurve* volumeFalloffCurve; float envelopMin; float envelopMax; float envelopPercentage; - SpeakerMap *speakerMap; + SpeakerMap* speakerMap; }; struct snd_alias_list_t { - const char *aliasName; - snd_alias_t *head; + const char* aliasName; + snd_alias_t* head; unsigned int count; }; struct cStaticModel_s { - XModel *xmodel; + XModel* xmodel; float origin[3]; float invScaledAxis[3][3]; Bounds absBounds; @@ -2241,14 +2241,14 @@ namespace Game struct ClipMaterial { - const char *name; + const char* name; int surfaceFlags; int contents; }; struct cNode_t { - cplane_s *plane; + cplane_s* plane; __int16 children[2]; }; @@ -2264,7 +2264,7 @@ namespace Game struct cLeafBrushNodeLeaf_t { - unsigned __int16 *brushes; + unsigned __int16* brushes; }; struct cLeafBrushNodeChildren_t @@ -2303,7 +2303,7 @@ namespace Game char borderCount; char firstVertSegment; int firstTri; - CollisionBorder *borders; + CollisionBorder* borders; }; union CollisionAabbTreeIndex @@ -2355,16 +2355,16 @@ namespace Game struct MapTriggers { unsigned int count; - TriggerModel *models; + TriggerModel* models; unsigned int hullCount; - TriggerHull *hulls; + TriggerHull* hulls; unsigned int slabCount; - TriggerSlab *slabs; + TriggerSlab* slabs; }; struct /*__declspec(align(2))*/ Stage { - const char *name; + const char* name; float origin[3]; unsigned __int16 triggerIndex; char sunPrimaryLightIndex; @@ -2372,11 +2372,11 @@ namespace Game struct __declspec(align(4)) MapEnts { - const char *name; - const char *entityString; + const char* name; + const char* entityString; int numEntityChars; MapTriggers trigger; - Stage *stages; + Stage* stages; char stageCount; }; @@ -2476,28 +2476,28 @@ namespace Game struct FxElemMarkVisuals { - Material *materials[2]; + Material* materials[2]; }; union FxEffectDefRef { - FxEffectDef *handle; - const char *name; + FxEffectDef* handle; + const char* name; }; union FxElemVisuals { - const void *anonymous; - Material *material; - XModel *model; + const void* anonymous; + Material* material; + XModel* model; FxEffectDefRef effectDef; - const char *soundName; + const char* soundName; }; union FxElemDefVisuals { - FxElemMarkVisuals *markArray; - FxElemVisuals *array; + FxElemMarkVisuals* markArray; + FxElemVisuals* array; FxElemVisuals instance; }; @@ -2516,9 +2516,9 @@ namespace Game float invSplitArcDist; float invSplitTime; int vertCount; - FxTrailVertex *verts; + FxTrailVertex* verts; int indCount; - unsigned __int16 *inds; + unsigned __int16* inds; }; struct FxSparkFountainDef @@ -2540,9 +2540,9 @@ namespace Game union FxElemExtendedDefPtr { - FxTrailDef *trailDef; - FxSparkFountainDef *sparkFountainDef; - void *unknownDef; + FxTrailDef* trailDef; + FxSparkFountainDef* sparkFountainDef; + void* unknownDef; }; const struct FxElemDef @@ -2568,8 +2568,8 @@ namespace Game char visualCount; char velIntervalCount; char visStateIntervalCount; - FxElemVelStateSample *velSamples; - FxElemVisStateSample *visSamples; + FxElemVelStateSample* velSamples; + FxElemVisStateSample* visSamples; FxElemDefVisuals visuals; Bounds collBounds; FxEffectDefRef effectOnImpact; @@ -2586,25 +2586,25 @@ namespace Game struct FxEffectDef { - const char *name; + const char* name; int flags; int totalSize; int msecLoopingLife; int elemDefCountLooping; int elemDefCountOneShot; int elemDefCountEmission; - FxElemDef *elemDefs; + FxElemDef* elemDefs; }; struct DynEntityDef { DynEntityType type; GfxPlacement pose; - XModel *xModel; + XModel* xModel; unsigned __int16 brushModel; unsigned __int16 physicsBrushModel; - FxEffectDef *destroyFx; - PhysPreset *physPreset; + FxEffectDef* destroyFx; + PhysPreset* physPreset; int health; PhysMass mass; int contents; @@ -2636,53 +2636,53 @@ namespace Game #pragma warning(disable: 4324) struct __declspec(align(64)) clipMap_t { - const char *name; + const char* name; int isInUse; int planeCount; - cplane_s *planes; + cplane_s* planes; unsigned int numStaticModels; - cStaticModel_s *staticModelList; + cStaticModel_s* staticModelList; unsigned int numMaterials; - ClipMaterial *materials; + ClipMaterial* materials; unsigned int numBrushSides; - cbrushside_t *brushsides; + cbrushside_t* brushsides; unsigned int numBrushEdges; - char *brushEdges; + char* brushEdges; unsigned int numNodes; - cNode_t *nodes; + cNode_t* nodes; unsigned int numLeafs; - cLeaf_t *leafs; + cLeaf_t* leafs; unsigned int leafbrushNodesCount; - cLeafBrushNode_s *leafbrushNodes; + cLeafBrushNode_s* leafbrushNodes; unsigned int numLeafBrushes; - unsigned __int16 *leafbrushes; + unsigned __int16* leafbrushes; unsigned int numLeafSurfaces; - unsigned int *leafsurfaces; + unsigned int* leafsurfaces; unsigned int vertCount; float(*verts)[3]; int triCount; - unsigned __int16 *triIndices; - char *triEdgeIsWalkable; + unsigned __int16* triIndices; + char* triEdgeIsWalkable; int borderCount; - CollisionBorder *borders; + CollisionBorder* borders; int partitionCount; - CollisionPartition *partitions; + CollisionPartition* partitions; int aabbTreeCount; - CollisionAabbTree *aabbTrees; + CollisionAabbTree* aabbTrees; unsigned int numSubModels; - cmodel_t *cmodels; + cmodel_t* cmodels; unsigned __int16 numBrushes; - cbrush_t *brushes; - Bounds *brushBounds; - int *brushContents; - MapEnts *mapEnts; + cbrush_t* brushes; + Bounds* brushBounds; + int* brushContents; + MapEnts* mapEnts; unsigned __int16 smodelNodeCount; - SModelAabbNode *smodelNodes; + SModelAabbNode* smodelNodes; unsigned __int16 dynEntCount[2]; - DynEntityDef *dynEntDefList[2]; - DynEntityPose *dynEntPoseList[2]; - DynEntityClient *dynEntClientList[2]; - DynEntityColl *dynEntCollList[2]; + DynEntityDef* dynEntDefList[2]; + DynEntityPose* dynEntPoseList[2]; + DynEntityClient* dynEntClientList[2]; + DynEntityColl* dynEntCollList[2]; unsigned int checksum; }; #pragma warning(pop) @@ -2702,15 +2702,15 @@ namespace Game float cosHalfFovExpanded; float rotationLimit; float translationLimit; - const char *defName; + const char* defName; }; struct ComWorld { - const char *name; + const char* name; int isInUse; unsigned int primaryLightCount; - ComPrimaryLight *primaryLights; + ComPrimaryLight* primaryLights; }; enum nodeType @@ -2786,12 +2786,12 @@ namespace Game $23305223CFD097B6F79557BDD2047E6C ___u12; __int16 wOverlapNode[2]; unsigned __int16 totalLinkCount; - pathlink_s *Links; + pathlink_s* Links; }; struct pathnode_dynamic_t { - void *pOwner; + void* pOwner; int iFreeTime; int iValidTime[3]; int dangerousNodeTime[3]; @@ -2812,9 +2812,9 @@ namespace Game struct pathnode_transient_t { int iSearchFrame; - pathnode_t *pNextOpen; - pathnode_t *pPrevOpen; - pathnode_t *pParent; + pathnode_t* pNextOpen; + pathnode_t* pPrevOpen; + pathnode_t* pParent; float fCost; float fHeuristic; $73F238679C0419BE2C31C6559E8604FC ___u6; @@ -2836,12 +2836,12 @@ namespace Game struct pathnode_tree_nodes_t { int nodeCount; - unsigned __int16 *nodes; + unsigned __int16* nodes; }; union pathnode_tree_info_t { - pathnode_tree_t *child[2]; + pathnode_tree_t* child[2]; pathnode_tree_nodes_t s; }; @@ -2855,15 +2855,15 @@ namespace Game struct PathData { unsigned int nodeCount; - pathnode_t *nodes; - pathbasenode_t *basenodes; + pathnode_t* nodes; + pathbasenode_t* basenodes; unsigned int chainNodeCount; - unsigned __int16 *chainNodeForNode; - unsigned __int16 *nodeForChainNode; + unsigned __int16* chainNodeForNode; + unsigned __int16* nodeForChainNode; int visBytes; - char *pathVis; + char* pathVis; int nodeTreeCount; - pathnode_tree_t *nodeTree; + pathnode_tree_t* nodeTree; }; struct VehicleTrackObstacle @@ -2884,18 +2884,18 @@ namespace Game float sectorWidth; float totalPriorLength; float totalFollowingLength; - VehicleTrackObstacle *obstacles; + VehicleTrackObstacle* obstacles; unsigned int obstacleCount; }; struct VehicleTrackSegment { - const char *targetName; - VehicleTrackSector *sectors; + const char* targetName; + VehicleTrackSector* sectors; unsigned int sectorCount; - VehicleTrackSegment **nextBranches; + VehicleTrackSegment** nextBranches; unsigned int nextBranchesCount; - VehicleTrackSegment **prevBranches; + VehicleTrackSegment** prevBranches; unsigned int prevBranchesCount; float endEdgeDir[2]; float endEdgeDist; @@ -2904,7 +2904,7 @@ namespace Game struct VehicleTrack { - VehicleTrackSegment *segments; + VehicleTrackSegment* segments; unsigned int segmentCount; }; @@ -2919,35 +2919,35 @@ namespace Game struct G_GlassName { - char *nameStr; + char* nameStr; unsigned __int16 name; unsigned __int16 pieceCount; - unsigned __int16 *pieceIndices; + unsigned __int16* pieceIndices; }; struct G_GlassData { - G_GlassPiece *glassPieces; + G_GlassPiece* glassPieces; unsigned int pieceCount; unsigned __int16 damageToWeaken; unsigned __int16 damageToDestroy; unsigned int glassNameCount; - G_GlassName *glassNames; + G_GlassName* glassNames; char pad[108]; }; struct GameWorldSp { - const char *name; + const char* name; PathData path; VehicleTrack vehicleTrack; - G_GlassData *g_glassData; + G_GlassData* g_glassData; }; struct GameWorldMp { - const char *name; - G_GlassData *g_glassData; + const char* name; + G_GlassData* g_glassData; }; struct FxGlassDef @@ -2955,9 +2955,9 @@ namespace Game float halfThickness; float texVecs[2][2]; GfxColor color; - Material *material; - Material *materialShattered; - PhysPreset *physPreset; + Material* material; + Material* materialShattered; + PhysPreset* physPreset; }; struct FxSpatialFrame @@ -3059,19 +3059,19 @@ namespace Game unsigned int geoDataLimit; unsigned int geoDataCount; unsigned int initGeoDataCount; - FxGlassDef *defs; - FxGlassPiecePlace *piecePlaces; - FxGlassPieceState *pieceStates; - FxGlassPieceDynamics *pieceDynamics; - FxGlassGeometryData *geoData; - unsigned int *isInUse; - unsigned int *cellBits; - char *visData; + FxGlassDef* defs; + FxGlassPiecePlace* piecePlaces; + FxGlassPieceState* pieceStates; + FxGlassPieceDynamics* pieceDynamics; + FxGlassGeometryData* geoData; + unsigned int* isInUse; + unsigned int* cellBits; + char* visData; float(*linkOrg)[3]; - float *halfThickness; - unsigned __int16 *lightingHandles; - FxGlassInitPieceState *initPieceStates; - FxGlassGeometryData *initGeoData; + float* halfThickness; + unsigned __int16* lightingHandles; + FxGlassInitPieceState* initPieceStates; + FxGlassGeometryData* initGeoData; bool needToCompactData; char initCount; float effectChanceAccum; @@ -3080,24 +3080,24 @@ namespace Game struct FxWorld { - const char *name; + const char* name; FxGlassSystem glassSys; }; struct __declspec(align(4)) GfxSky { int skySurfCount; - int *skyStartSurfs; - GfxImage *skyImage; + int* skyStartSurfs; + GfxImage* skyImage; char skySamplerState; }; struct GfxWorldDpvsPlanes { int cellCount; - cplane_s *planes; - unsigned __int16 *nodes; - unsigned int *sceneEntCellBits; + cplane_s* planes; + unsigned __int16* nodes; + unsigned int* sceneEntCellBits; }; struct GfxCellTreeCount @@ -3114,13 +3114,13 @@ namespace Game unsigned __int16 surfaceCountNoDecal; unsigned __int16 startSurfIndexNoDecal; unsigned __int16 smodelIndexCount; - unsigned __int16 *smodelIndexes; + unsigned __int16* smodelIndexes; int childrenOffset; }; struct GfxCellTree { - GfxAabbTree *aabbTree; + GfxAabbTree* aabbTree; }; struct GfxPortalWritable @@ -3130,7 +3130,7 @@ namespace Game char recursionDepth; char hullPointCount; float(*hullPoints)[2]; - GfxPortal *queuedParent; + GfxPortal* queuedParent; }; struct DpvsPlane @@ -3152,9 +3152,9 @@ namespace Game { Bounds bounds; int portalCount; - GfxPortal *portals; + GfxPortal* portals; char reflectionProbeCount; - char *reflectionProbes; + char* reflectionProbes; }; struct GfxReflectionProbe @@ -3164,8 +3164,8 @@ namespace Game struct GfxLightmapArray { - GfxImage *primary; - GfxImage *secondary; + GfxImage* primary; + GfxImage* secondary; }; struct GfxWorldVertex @@ -3181,34 +3181,34 @@ namespace Game struct GfxWorldVertexData { - GfxWorldVertex *vertices; - IDirect3DVertexBuffer9 *worldVb; + GfxWorldVertex* vertices; + IDirect3DVertexBuffer9* worldVb; }; struct GfxWorldVertexLayerData { - char *data; - IDirect3DVertexBuffer9 *layerVb; + char* data; + IDirect3DVertexBuffer9* layerVb; }; struct GfxWorldDraw { unsigned int reflectionProbeCount; - GfxImage **reflectionProbes; - GfxReflectionProbe *reflectionProbeOrigins; - GfxTexture *reflectionProbeTextures; + GfxImage** reflectionProbes; + GfxReflectionProbe* reflectionProbeOrigins; + GfxTexture* reflectionProbeTextures; int lightmapCount; - GfxLightmapArray *lightmaps; - GfxTexture *lightmapPrimaryTextures; - GfxTexture *lightmapSecondaryTextures; - GfxImage *lightmapOverridePrimary; - GfxImage *lightmapOverrideSecondary; + GfxLightmapArray* lightmaps; + GfxTexture* lightmapPrimaryTextures; + GfxTexture* lightmapSecondaryTextures; + GfxImage* lightmapOverridePrimary; + GfxImage* lightmapOverrideSecondary; unsigned int vertexCount; GfxWorldVertexData vd; unsigned int vertexLayerDataSize; GfxWorldVertexLayerData vld; unsigned int indexCount; - unsigned __int16 *indices; + unsigned __int16* indices; }; struct GfxLightGridEntry @@ -3231,13 +3231,13 @@ namespace Game unsigned __int16 maxs[3]; unsigned int rowAxis; unsigned int colAxis; - unsigned __int16 *rowDataStart; + unsigned __int16* rowDataStart; unsigned int rawRowDataSize; - char *rawRowData; + char* rawRowData; unsigned int entryCount; - GfxLightGridEntry *entries; + GfxLightGridEntry* entries; unsigned int colorCount; - GfxLightGridColors *colors; + GfxLightGridColors* colors; }; struct GfxBrushModelWritable @@ -3257,15 +3257,15 @@ namespace Game struct MaterialMemory { - Material *material; + Material* material; int memory; }; struct sunflare_t { bool hasValidData; - Material *spriteMaterial; - Material *flareMaterial; + Material* spriteMaterial; + Material* flareMaterial; float spriteSize; float flareMinSize; float flareMinDot; @@ -3315,8 +3315,8 @@ namespace Game { unsigned __int16 surfaceCount; unsigned __int16 smodelCount; - unsigned __int16 *sortedSurfIndex; - unsigned __int16 *smodelIndex; + unsigned __int16* sortedSurfIndex; + unsigned __int16* smodelIndex; }; struct GfxLightRegionAxis @@ -3331,13 +3331,13 @@ namespace Game float kdopMidPoint[9]; float kdopHalfSize[9]; unsigned int axisCount; - GfxLightRegionAxis *axis; + GfxLightRegionAxis* axis; }; struct GfxLightRegion { unsigned int hullCount; - GfxLightRegionHull *hulls; + GfxLightRegionHull* hulls; }; struct GfxStaticModelInst @@ -3372,7 +3372,7 @@ namespace Game struct GfxSurface { srfTriangles_t tris; - Material *material; + Material* material; GfxSurfaceLightingAndFlags laf; }; @@ -3391,7 +3391,7 @@ namespace Game struct GfxStaticModelDrawInst { GfxPackedPlacement placement; - XModel *model; + XModel* model; unsigned __int16 cullDist; unsigned __int16 lightingHandle; char reflectionProbeIndex; @@ -3417,15 +3417,15 @@ namespace Game unsigned int emissiveSurfsEnd; unsigned int smodelVisDataCount; unsigned int surfaceVisDataCount; - char *smodelVisData[3]; - char *surfaceVisData[3]; - unsigned __int16 *sortedSurfIndex; - GfxStaticModelInst *smodelInsts; - GfxSurface *surfaces; - GfxSurfaceBounds *surfacesBounds; - GfxStaticModelDrawInst *smodelDrawInsts; - GfxDrawSurf *surfaceMaterials; - unsigned int *surfaceCastsSunShadow; + char* smodelVisData[3]; + char* surfaceVisData[3]; + unsigned __int16* sortedSurfIndex; + GfxStaticModelInst* smodelInsts; + GfxSurface* surfaces; + GfxSurfaceBounds* surfacesBounds; + GfxStaticModelDrawInst* smodelDrawInsts; + GfxDrawSurf* surfaceMaterials; + unsigned int* surfaceCastsSunShadow; volatile int usageCount; }; @@ -3433,8 +3433,8 @@ namespace Game { unsigned int dynEntClientWordCount[2]; unsigned int dynEntClientCount[2]; - unsigned int *dynEntCellBits[2]; - char *dynEntVisData[2][3]; + unsigned int* dynEntCellBits[2]; + char* dynEntVisData[2][3]; }; struct GfxHeroOnlyLight @@ -3452,13 +3452,13 @@ namespace Game struct __declspec(align(4)) GfxWorld { - const char *name; - const char *baseName; + const char* name; + const char* baseName; int planeCount; int nodeCount; unsigned int surfaceCount; int skyCount; - GfxSky *skies; + GfxSky* skies; unsigned int lastSunPrimaryLightIndex; unsigned int primaryLightCount; unsigned int sortKeyLitDecal; @@ -3466,46 +3466,46 @@ namespace Game unsigned int sortKeyEffectAuto; unsigned int sortKeyDistortion; GfxWorldDpvsPlanes dpvsPlanes; - GfxCellTreeCount *aabbTreeCounts; - GfxCellTree *aabbTrees; - GfxCell *cells; + GfxCellTreeCount* aabbTreeCounts; + GfxCellTree* aabbTrees; + GfxCell* cells; GfxWorldDraw draw; GfxLightGrid lightGrid; int modelCount; - GfxBrushModel *models; + GfxBrushModel* models; Bounds bounds; unsigned int checksum; int materialMemoryCount; - MaterialMemory *materialMemory; + MaterialMemory* materialMemory; sunflare_t sun; float outdoorLookupMatrix[4][4]; - GfxImage *outdoorImage; - unsigned int *cellCasterBits; - unsigned int *cellHasSunLitSurfsBits; - GfxSceneDynModel *sceneDynModel; - GfxSceneDynBrush *sceneDynBrush; - unsigned int *primaryLightEntityShadowVis; - unsigned int *primaryLightDynEntShadowVis[2]; - char *nonSunPrimaryLightForModelDynEnt; - GfxShadowGeometry *shadowGeom; - GfxLightRegion *lightRegion; + GfxImage* outdoorImage; + unsigned int* cellCasterBits; + unsigned int* cellHasSunLitSurfsBits; + GfxSceneDynModel* sceneDynModel; + GfxSceneDynBrush* sceneDynBrush; + unsigned int* primaryLightEntityShadowVis; + unsigned int* primaryLightDynEntShadowVis[2]; + char* nonSunPrimaryLightForModelDynEnt; + GfxShadowGeometry* shadowGeom; + GfxLightRegion* lightRegion; GfxWorldDpvsStatic dpvs; GfxWorldDpvsDynamic dpvsDyn; unsigned int mapVtxChecksum; unsigned int heroOnlyLightCount; - GfxHeroOnlyLight *heroOnlyLights; + GfxHeroOnlyLight* heroOnlyLights; char fogTypesAllowed; }; struct __declspec(align(4)) GfxLightImage { - GfxImage *image; + GfxImage* image; char samplerState; }; struct GfxLightDef { - const char *name; + const char* name; GfxLightImage attenuation; int lmapLookupStart; }; @@ -3526,12 +3526,12 @@ namespace Game struct Font_s { - const char *fontName; + const char* fontName; int pixelHeight; int glyphCount; - Material *material; - Material *glowMaterial; - Glyph *glyphs; + Material* material; + Material* glowMaterial; + Glyph* glyphs; }; struct __declspec(align(4)) rectDef_s @@ -3546,10 +3546,10 @@ namespace Game struct windowDef_t { - const char *name; + const char* name; rectDef_s rect; rectDef_s rectClient; - const char *group; + const char* group; int style; int border; int ownerDraw; @@ -3563,7 +3563,7 @@ namespace Game float borderColor[4]; float outlineColor[4]; float disableColor[4]; - Material *background; + Material* background; }; enum expDataType @@ -3578,7 +3578,7 @@ namespace Game struct ExpressionString { - const char *string; + const char* string; }; union operandInternalDataUnion @@ -3586,7 +3586,7 @@ namespace Game int intVal; float floatVal; ExpressionString stringVal; - Statement_s *function; + Statement_s* function; }; struct Operand @@ -3794,7 +3794,7 @@ namespace Game struct UIFunctionList { int totalFunctions; - Statement_s **functions; + Statement_s** functions; }; union DvarValue @@ -3849,7 +3849,7 @@ namespace Game DvarValue latched; DvarValue reset; DvarLimits domain; - bool(__cdecl * domainFunc)(dvar_t*, DvarValue); + bool(__cdecl* domainFunc)(dvar_t*, DvarValue); dvar_t* hashNext; }; @@ -3883,30 +3883,30 @@ namespace Game struct Statement_s { int numEntries; - expressionEntry *entries; - ExpressionSupportingData *supportingData; + expressionEntry* entries; + ExpressionSupportingData* supportingData; int lastExecuteTime; Operand lastResult; }; struct ConditionalScript { - MenuEventHandlerSet *eventHandlerSet; - Statement_s *eventExpression; + MenuEventHandlerSet* eventHandlerSet; + Statement_s* eventExpression; }; struct SetLocalVarData { - const char *localVarName; - Statement_s *expression; + const char* localVarName; + Statement_s* expression; }; union EventData { - const char *unconditionalScript; - ConditionalScript *conditionalScript; - MenuEventHandlerSet *elseScript; - SetLocalVarData *setLocalVarData; + const char* unconditionalScript; + ConditionalScript* conditionalScript; + MenuEventHandlerSet* elseScript; + SetLocalVarData* setLocalVarData; }; struct __declspec(align(4)) MenuEventHandler @@ -3918,14 +3918,14 @@ namespace Game struct MenuEventHandlerSet { int eventHandlerCount; - MenuEventHandler **eventHandlers; + MenuEventHandler** eventHandlers; }; struct ItemKeyHandler { int key; - MenuEventHandlerSet *action; - ItemKeyHandler *next; + MenuEventHandlerSet* action; + ItemKeyHandler* next; }; struct columnInfo_s @@ -3947,12 +3947,12 @@ namespace Game int elementStyle; int numColumns; columnInfo_s columnInfo[16]; - MenuEventHandlerSet *onDoubleClick; + MenuEventHandlerSet* onDoubleClick; int notselectable; int noScrollBars; int usePaging; float selectBorder[4]; - Material *selectIcon; + Material* selectIcon; }; struct editFieldDef_s @@ -3969,8 +3969,8 @@ namespace Game struct multiDef_s { - const char *dvarList[32]; - const char *dvarStr[32]; + const char* dvarList[32]; + const char* dvarStr[32]; float dvarValue[32]; int count; int strDef; @@ -3994,19 +3994,19 @@ namespace Game union itemDefData_t { - listBoxDef_s *listBox; - editFieldDef_s *editField; - multiDef_s *multi; - const char *enumDvarName; - newsTickerDef_s *ticker; - textScrollDef_s *scroll; - void *data; + listBoxDef_s* listBox; + editFieldDef_s* editField; + multiDef_s* multi; + const char* enumDvarName; + newsTickerDef_s* ticker; + textScrollDef_s* scroll; + void* data; }; struct ItemFloatExpression { int target; - Statement_s *expression; + Statement_s* expression; }; struct itemDef_s @@ -4024,34 +4024,34 @@ namespace Game int textStyle; int gameMsgWindowIndex; int gameMsgWindowMode; - const char *text; + const char* text; int itemFlags; - menuDef_t *parent; - MenuEventHandlerSet *mouseEnterText; - MenuEventHandlerSet *mouseExitText; - MenuEventHandlerSet *mouseEnter; - MenuEventHandlerSet *mouseExit; - MenuEventHandlerSet *action; - MenuEventHandlerSet *accept; - MenuEventHandlerSet *onFocus; - MenuEventHandlerSet *leaveFocus; - const char *dvar; - const char *dvarTest; - ItemKeyHandler *onKey; - const char *enableDvar; - const char *localVar; + menuDef_t* parent; + MenuEventHandlerSet* mouseEnterText; + MenuEventHandlerSet* mouseExitText; + MenuEventHandlerSet* mouseEnter; + MenuEventHandlerSet* mouseExit; + MenuEventHandlerSet* action; + MenuEventHandlerSet* accept; + MenuEventHandlerSet* onFocus; + MenuEventHandlerSet* leaveFocus; + const char* dvar; + const char* dvarTest; + ItemKeyHandler* onKey; + const char* enableDvar; + const char* localVar; int dvarFlags; - snd_alias_list_t *focusSound; + snd_alias_list_t* focusSound; float special; int cursorPos[1]; itemDefData_t typeData; int imageTrack; int floatExpressionCount; - ItemFloatExpression *floatExpressions; - Statement_s *visibleExp; - Statement_s *disabledExp; - Statement_s *textExp; - Statement_s *materialExp; + ItemFloatExpression* floatExpressions; + Statement_s* visibleExp; + Statement_s* disabledExp; + Statement_s* textExp; + Statement_s* materialExp; float glowColor[4]; bool decayActive; int fxBirthTime; @@ -4265,8 +4265,8 @@ namespace Game struct TracerDef { - const char *name; - Material *material; + const char* name; + Material* material; unsigned int drawInterval; float speed; float beamLength; @@ -4278,16 +4278,16 @@ namespace Game struct __declspec(align(4)) WeaponDef { - const char *szOverlayName; - XModel **gunXModel; - XModel *handXModel; - const char **szXAnimsRightHanded; - const char **szXAnimsLeftHanded; - const char *szModeName; - unsigned __int16 *notetrackSoundMapKeys; - unsigned __int16 *notetrackSoundMapValues; - unsigned __int16 *notetrackRumbleMapKeys; - unsigned __int16 *notetrackRumbleMapValues; + const char* szOverlayName; + XModel** gunXModel; + XModel* handXModel; + const char** szXAnimsRightHanded; + const char** szXAnimsLeftHanded; + const char* szModeName; + unsigned __int16* notetrackSoundMapKeys; + unsigned __int16* notetrackSoundMapValues; + unsigned __int16* notetrackRumbleMapKeys; + unsigned __int16* notetrackRumbleMapValues; int playerAnimType; weapType_t weapType; weapClass_t weapClass; @@ -4296,62 +4296,62 @@ namespace Game weapFireType_t fireType; OffhandClass offhandClass; weapStance_t stance; - FxEffectDef *viewFlashEffect; - FxEffectDef *worldFlashEffect; - snd_alias_list_t *pickupSound; - snd_alias_list_t *pickupSoundPlayer; - snd_alias_list_t *ammoPickupSound; - snd_alias_list_t *ammoPickupSoundPlayer; - snd_alias_list_t *projectileSound; - snd_alias_list_t *pullbackSound; - snd_alias_list_t *pullbackSoundPlayer; - snd_alias_list_t *fireSound; - snd_alias_list_t *fireSoundPlayer; - snd_alias_list_t *fireSoundPlayerAkimbo; - snd_alias_list_t *fireLoopSound; - snd_alias_list_t *fireLoopSoundPlayer; - snd_alias_list_t *fireStopSound; - snd_alias_list_t *fireStopSoundPlayer; - snd_alias_list_t *fireLastSound; - snd_alias_list_t *fireLastSoundPlayer; - snd_alias_list_t *emptyFireSound; - snd_alias_list_t *emptyFireSoundPlayer; - snd_alias_list_t *meleeSwipeSound; - snd_alias_list_t *meleeSwipeSoundPlayer; - snd_alias_list_t *meleeHitSound; - snd_alias_list_t *meleeMissSound; - snd_alias_list_t *rechamberSound; - snd_alias_list_t *rechamberSoundPlayer; - snd_alias_list_t *reloadSound; - snd_alias_list_t *reloadSoundPlayer; - snd_alias_list_t *reloadEmptySound; - snd_alias_list_t *reloadEmptySoundPlayer; - snd_alias_list_t *reloadStartSound; - snd_alias_list_t *reloadStartSoundPlayer; - snd_alias_list_t *reloadEndSound; - snd_alias_list_t *reloadEndSoundPlayer; - snd_alias_list_t *detonateSound; - snd_alias_list_t *detonateSoundPlayer; - snd_alias_list_t *nightVisionWearSound; - snd_alias_list_t *nightVisionWearSoundPlayer; - snd_alias_list_t *nightVisionRemoveSound; - snd_alias_list_t *nightVisionRemoveSoundPlayer; - snd_alias_list_t *altSwitchSound; - snd_alias_list_t *altSwitchSoundPlayer; - snd_alias_list_t *raiseSound; - snd_alias_list_t *raiseSoundPlayer; - snd_alias_list_t *firstRaiseSound; - snd_alias_list_t *firstRaiseSoundPlayer; - snd_alias_list_t *putawaySound; - snd_alias_list_t *putawaySoundPlayer; - snd_alias_list_t *scanSound; - snd_alias_list_t **bounceSound; - FxEffectDef *viewShellEjectEffect; - FxEffectDef *worldShellEjectEffect; - FxEffectDef *viewLastShotEjectEffect; - FxEffectDef *worldLastShotEjectEffect; - Material *reticleCenter; - Material *reticleSide; + FxEffectDef* viewFlashEffect; + FxEffectDef* worldFlashEffect; + snd_alias_list_t* pickupSound; + snd_alias_list_t* pickupSoundPlayer; + snd_alias_list_t* ammoPickupSound; + snd_alias_list_t* ammoPickupSoundPlayer; + snd_alias_list_t* projectileSound; + snd_alias_list_t* pullbackSound; + snd_alias_list_t* pullbackSoundPlayer; + snd_alias_list_t* fireSound; + snd_alias_list_t* fireSoundPlayer; + snd_alias_list_t* fireSoundPlayerAkimbo; + snd_alias_list_t* fireLoopSound; + snd_alias_list_t* fireLoopSoundPlayer; + snd_alias_list_t* fireStopSound; + snd_alias_list_t* fireStopSoundPlayer; + snd_alias_list_t* fireLastSound; + snd_alias_list_t* fireLastSoundPlayer; + snd_alias_list_t* emptyFireSound; + snd_alias_list_t* emptyFireSoundPlayer; + snd_alias_list_t* meleeSwipeSound; + snd_alias_list_t* meleeSwipeSoundPlayer; + snd_alias_list_t* meleeHitSound; + snd_alias_list_t* meleeMissSound; + snd_alias_list_t* rechamberSound; + snd_alias_list_t* rechamberSoundPlayer; + snd_alias_list_t* reloadSound; + snd_alias_list_t* reloadSoundPlayer; + snd_alias_list_t* reloadEmptySound; + snd_alias_list_t* reloadEmptySoundPlayer; + snd_alias_list_t* reloadStartSound; + snd_alias_list_t* reloadStartSoundPlayer; + snd_alias_list_t* reloadEndSound; + snd_alias_list_t* reloadEndSoundPlayer; + snd_alias_list_t* detonateSound; + snd_alias_list_t* detonateSoundPlayer; + snd_alias_list_t* nightVisionWearSound; + snd_alias_list_t* nightVisionWearSoundPlayer; + snd_alias_list_t* nightVisionRemoveSound; + snd_alias_list_t* nightVisionRemoveSoundPlayer; + snd_alias_list_t* altSwitchSound; + snd_alias_list_t* altSwitchSoundPlayer; + snd_alias_list_t* raiseSound; + snd_alias_list_t* raiseSoundPlayer; + snd_alias_list_t* firstRaiseSound; + snd_alias_list_t* firstRaiseSoundPlayer; + snd_alias_list_t* putawaySound; + snd_alias_list_t* putawaySoundPlayer; + snd_alias_list_t* scanSound; + snd_alias_list_t** bounceSound; + FxEffectDef* viewShellEjectEffect; + FxEffectDef* worldShellEjectEffect; + FxEffectDef* viewLastShotEjectEffect; + FxEffectDef* worldLastShotEjectEffect; + Material* reticleCenter; + Material* reticleSide; int iReticleCenterSize; int iReticleSideSize; int iReticleMinOfs; @@ -4376,26 +4376,26 @@ namespace Game float fStandRotMinSpeed; float fDuckedRotMinSpeed; float fProneRotMinSpeed; - XModel **worldModel; - XModel *worldClipModel; - XModel *rocketModel; - XModel *knifeModel; - XModel *worldKnifeModel; - Material *hudIcon; + XModel** worldModel; + XModel* worldClipModel; + XModel* rocketModel; + XModel* knifeModel; + XModel* worldKnifeModel; + Material* hudIcon; weaponIconRatioType_t hudIconRatio; - Material *pickupIcon; + Material* pickupIcon; weaponIconRatioType_t pickupIconRatio; - Material *ammoCounterIcon; + Material* ammoCounterIcon; weaponIconRatioType_t ammoCounterIconRatio; ammoCounterClipType_t ammoCounterClip; int iStartAmmo; - const char *szAmmoName; + const char* szAmmoName; int iAmmoIndex; - const char *szClipName; + const char* szClipName; int iClipIndex; int iMaxAmmo; int shotCount; - const char *szSharedAmmoCapName; + const char* szSharedAmmoCapName; int iSharedAmmoCapIndex; int iSharedAmmoCap; int damage; @@ -4452,10 +4452,10 @@ namespace Game float sprintDurationScale; float fAdsZoomInFrac; float fAdsZoomOutFrac; - Material *overlayMaterial; - Material *overlayMaterialLowRes; - Material *overlayMaterialEMP; - Material *overlayMaterialEMPLowRes; + Material* overlayMaterial; + Material* overlayMaterialLowRes; + Material* overlayMaterialEMP; + Material* overlayMaterialEMPLowRes; weapOverlayReticle_t overlayReticle; WeapOverlayInteface_t overlayInterface; float overlayWidth; @@ -4500,7 +4500,7 @@ namespace Game float adsSwayVertScale; float adsViewErrorMin; float adsViewErrorMax; - PhysCollmap *physCollmap; + PhysCollmap* physCollmap; float dualWieldViewModelOffset; weaponIconRatioType_t killIconRatio; int iReloadAmmoAdd; @@ -4522,25 +4522,25 @@ namespace Game float projLifetime; float timeToAccelerate; float projectileCurvature; - XModel *projectileModel; + XModel* projectileModel; weapProjExposion_t projExplosion; - FxEffectDef *projExplosionEffect; - FxEffectDef *projDudEffect; - snd_alias_list_t *projExplosionSound; - snd_alias_list_t *projDudSound; + FxEffectDef* projExplosionEffect; + FxEffectDef* projDudEffect; + snd_alias_list_t* projExplosionSound; + snd_alias_list_t* projDudSound; WeapStickinessType stickiness; float lowAmmoWarningThreshold; float ricochetChance; - float *parallelBounce; - float *perpendicularBounce; - FxEffectDef *projTrailEffect; - FxEffectDef *projBeaconEffect; + float* parallelBounce; + float* perpendicularBounce; + FxEffectDef* projTrailEffect; + FxEffectDef* projBeaconEffect; float vProjectileColor[3]; guidedMissileType_t guidedMissileType; float maxSteeringAccel; int projIgnitionDelay; - FxEffectDef *projIgnitionEffect; - snd_alias_list_t *projIgnitionSound; + FxEffectDef* projIgnitionEffect; + snd_alias_list_t* projIgnitionSound; float fAdsAimPitch; float fAdsCrosshairInFrac; float fAdsCrosshairOutFrac; @@ -4579,7 +4579,7 @@ namespace Game float fHipViewScatterMax; float fightDist; float maxDist; - const char *accuracyGraphName[2]; + const char* accuracyGraphName[2]; float(*originalAccuracyGraphKnots[2])[2]; unsigned __int16 originalAccuracyGraphKnotCount[2]; int iPositionReloadTransTime; @@ -4598,8 +4598,8 @@ namespace Game float maxRange; float fAnimHorRotateInc; float fPlayerPositionDist; - const char *szUseHintString; - const char *dropHintString; + const char* szUseHintString; + const char* dropHintString; int iUseHintStringIndex; int dropHintStringIndex; float horizViewJitter; @@ -4607,7 +4607,7 @@ namespace Game float scanSpeed; float scanAccel; int scanPauseTime; - const char *szScript; + const char* szScript; float fOOPosAnimLength[2]; int minDamage; int minPlayerDamage; @@ -4616,27 +4616,27 @@ namespace Game float destabilizationRateTime; float destabilizationCurvatureMax; int destabilizeDistance; - float *locationDamageMultipliers; - const char *fireRumble; - const char *meleeImpactRumble; - TracerDef *tracerType; + float* locationDamageMultipliers; + const char* fireRumble; + const char* meleeImpactRumble; + TracerDef* tracerType; float turretScopeZoomRate; float turretScopeZoomMin; float turretScopeZoomMax; float turretOverheatUpRate; float turretOverheatDownRate; float turretOverheatPenalty; - snd_alias_list_t *turretOverheatSound; - FxEffectDef *turretOverheatEffect; - const char *turretBarrelSpinRumble; + snd_alias_list_t* turretOverheatSound; + FxEffectDef* turretOverheatEffect; + const char* turretBarrelSpinRumble; float turretBarrelSpinSpeed; float turretBarrelSpinUpTime; float turretBarrelSpinDownTime; - snd_alias_list_t *turretBarrelSpinMaxSnd; - snd_alias_list_t *turretBarrelSpinUpSnd[4]; - snd_alias_list_t *turretBarrelSpinDownSnd[4]; - snd_alias_list_t *missileConeSoundAlias; - snd_alias_list_t *missileConeSoundAliasAtBase; + snd_alias_list_t* turretBarrelSpinMaxSnd; + snd_alias_list_t* turretBarrelSpinUpSnd[4]; + snd_alias_list_t* turretBarrelSpinDownSnd[4]; + snd_alias_list_t* missileConeSoundAlias; + snd_alias_list_t* missileConeSoundAliasAtBase; float missileConeSoundRadiusAtTop; float missileConeSoundRadiusAtBase; float missileConeSoundHeight; @@ -4716,11 +4716,11 @@ namespace Game struct WeaponCompleteDef { - const char *szInternalName; - WeaponDef *weapDef; - const char *szDisplayName; - unsigned __int16 *hideTags; - const char **szXAnims; + const char* szInternalName; + WeaponDef* weapDef; + const char* szDisplayName; + unsigned __int16* hideTags; + const char** szXAnims; float fAdsZoomFov; int iAdsTransInTime; int iAdsTransOutTime; @@ -4731,11 +4731,11 @@ namespace Game float penetrateMultiplier; float fAdsViewKickCenterSpeed; float fHipViewKickCenterSpeed; - const char *szAltWeaponName; + const char* szAltWeaponName; unsigned int altWeaponIndex; int iAltRaiseTime; - Material *killIcon; - Material *dpadIcon; + Material* killIcon; + Material* dpadIcon; int fireAnimLength; int iFirstRaiseTime; int ammoDropStockMax; @@ -4750,41 +4750,41 @@ namespace Game struct SndDriverGlobals { - const char *name; + const char* name; }; struct FxImpactEntry { - FxEffectDef *nonflesh[31]; - FxEffectDef *flesh[4]; + FxEffectDef* nonflesh[31]; + FxEffectDef* flesh[4]; }; struct FxImpactTable { - const char *name; - FxImpactEntry *table; + const char* name; + FxImpactEntry* table; }; struct RawFile { - const char *name; + const char* name; int compressedLen; int len; - const char *buffer; + const char* buffer; }; struct StringTableCell { - const char *string; + const char* string; int hash; }; struct StringTable { - const char *name; + const char* name; int columnCount; int rowCount; - StringTableCell *values; + StringTableCell* values; }; enum LbColType @@ -4809,11 +4809,11 @@ namespace Game struct LbColumnDef { - const char *name; + const char* name; int id; int propertyId; bool hidden; - const char *statName; + const char* statName; LbColType type; int precision; LbAggType agg; @@ -4821,17 +4821,17 @@ namespace Game struct LeaderboardDef { - const char *name; + const char* name; int id; int columnCount; int xpColId; int prestigeColId; - LbColumnDef *columns; + LbColumnDef* columns; }; struct __declspec(align(4)) StructuredDataEnumEntry { - const char *string; + const char* string; unsigned __int16 index; }; @@ -4839,7 +4839,7 @@ namespace Game { int entryCount; int reservedEntryCount; - StructuredDataEnumEntry *entries; + StructuredDataEnumEntry* entries; }; enum StructuredDataTypeCategory @@ -4874,7 +4874,7 @@ namespace Game struct StructuredDataStructProperty { - const char *name; + const char* name; StructuredDataType type; unsigned int offset; }; @@ -4882,7 +4882,7 @@ namespace Game struct StructuredDataStruct { int propertyCount; - StructuredDataStructProperty *properties; + StructuredDataStructProperty* properties; int size; unsigned int bitOffset; }; @@ -4906,27 +4906,27 @@ namespace Game int version; unsigned int formatChecksum; int enumCount; - StructuredDataEnum *enums; + StructuredDataEnum* enums; int structCount; - StructuredDataStruct *structs; + StructuredDataStruct* structs; int indexedArrayCount; - StructuredDataIndexedArray *indexedArrays; + StructuredDataIndexedArray* indexedArrays; int enumedArrayCount; - StructuredDataEnumedArray *enumedArrays; + StructuredDataEnumedArray* enumedArrays; StructuredDataType rootType; unsigned int size; }; struct StructuredDataDefSet { - const char *name; + const char* name; unsigned int defCount; - StructuredDataDef *defs; + StructuredDataDef* defs; }; struct StructuredDataBuffer { - char *data; + char* data; unsigned int size; }; @@ -4953,9 +4953,9 @@ namespace Game struct VehiclePhysDef { int physicsEnabled; - const char *physPresetName; - PhysPreset *physPreset; - const char *accelGraphName; + const char* physPresetName; + PhysPreset* physPreset; + const char* accelGraphName; VehicleAxleType steeringAxle; VehicleAxleType powerAxle; VehicleAxleType brakingAxle; @@ -5001,9 +5001,9 @@ namespace Game struct VehicleDef { - const char *name; + const char* name; VehicleType type; - const char *useHintString; + const char* useHintString; int health; int quadBarrel; float texScrollScale; @@ -5057,49 +5057,49 @@ namespace Game float camFovIncrease; float camFovOffset; float camFovSpeed; - const char *turretWeaponName; - WeaponCompleteDef *turretWeapon; + const char* turretWeaponName; + WeaponCompleteDef* turretWeapon; float turretHorizSpanLeft; float turretHorizSpanRight; float turretVertSpanUp; float turretVertSpanDown; float turretRotRate; - snd_alias_list_t *turretSpinSnd; - snd_alias_list_t *turretStopSnd; + snd_alias_list_t* turretSpinSnd; + snd_alias_list_t* turretStopSnd; int trophyEnabled; float trophyRadius; float trophyInactiveRadius; int trophyAmmoCount; float trophyReloadTime; unsigned __int16 trophyTags[4]; - Material *compassFriendlyIcon; - Material *compassEnemyIcon; + Material* compassFriendlyIcon; + Material* compassEnemyIcon; int compassIconWidth; int compassIconHeight; - snd_alias_list_t *idleLowSnd; - snd_alias_list_t *idleHighSnd; - snd_alias_list_t *engineLowSnd; - snd_alias_list_t *engineHighSnd; + snd_alias_list_t* idleLowSnd; + snd_alias_list_t* idleHighSnd; + snd_alias_list_t* engineLowSnd; + snd_alias_list_t* engineHighSnd; float engineSndSpeed; - snd_alias_list_t *engineStartUpSnd; + snd_alias_list_t* engineStartUpSnd; int engineStartUpLength; - snd_alias_list_t *engineShutdownSnd; - snd_alias_list_t *engineIdleSnd; - snd_alias_list_t *engineSustainSnd; - snd_alias_list_t *engineRampUpSnd; + snd_alias_list_t* engineShutdownSnd; + snd_alias_list_t* engineIdleSnd; + snd_alias_list_t* engineSustainSnd; + snd_alias_list_t* engineRampUpSnd; int engineRampUpLength; - snd_alias_list_t *engineRampDownSnd; + snd_alias_list_t* engineRampDownSnd; int engineRampDownLength; - snd_alias_list_t *suspensionSoftSnd; + snd_alias_list_t* suspensionSoftSnd; float suspensionSoftCompression; - snd_alias_list_t *suspensionHardSnd; + snd_alias_list_t* suspensionHardSnd; float suspensionHardCompression; - snd_alias_list_t *collisionSnd; + snd_alias_list_t* collisionSnd; float collisionBlendSpeed; - snd_alias_list_t *speedSnd; + snd_alias_list_t* speedSnd; float speedSndBlendSpeed; - const char *surfaceSndPrefix; - snd_alias_list_t *surfaceSnds[31]; + const char* surfaceSndPrefix; + snd_alias_list_t* surfaceSnds[31]; float surfaceSndBlendSpeed; float slideVolume; float slideBlendSpeed; @@ -5108,52 +5108,52 @@ namespace Game struct AddonMapEnts { - const char *name; - char *entityString; + const char* name; + char* entityString; int numEntityChars; MapTriggers trigger; }; union XAssetHeader { - void *data; - PhysPreset *physPreset; - PhysCollmap *physCollmap; - XAnimParts *parts; - XModelSurfs *modelSurfs; - XModel *model; - Material *material; - MaterialPixelShader *pixelShader; - MaterialVertexShader *vertexShader; - MaterialVertexDeclaration *vertexDecl; - MaterialTechniqueSet *techniqueSet; - GfxImage *image; - snd_alias_list_t *sound; - SndCurve *sndCurve; - LoadedSound *loadSnd; - clipMap_t *clipMap; - ComWorld *comWorld; - GameWorldSp *gameWorldSp; - GameWorldMp *gameWorldMp; - MapEnts *mapEnts; - FxWorld *fxWorld; - GfxWorld *gfxWorld; - GfxLightDef *lightDef; - Font_s *font; - MenuList *menuList; - menuDef_t *menu; - LocalizeEntry *localize; - WeaponCompleteDef *weapon; - SndDriverGlobals *sndDriverGlobals; - FxEffectDef *fx; - FxImpactTable *impactFx; - RawFile *rawfile; - StringTable *stringTable; - LeaderboardDef *leaderboardDef; - StructuredDataDefSet *structuredDataDefSet; - TracerDef *tracerDef; - VehicleDef *vehDef; - AddonMapEnts *addonMapEnts; + void* data; + PhysPreset* physPreset; + PhysCollmap* physCollmap; + XAnimParts* parts; + XModelSurfs* modelSurfs; + XModel* model; + Material* material; + MaterialPixelShader* pixelShader; + MaterialVertexShader* vertexShader; + MaterialVertexDeclaration* vertexDecl; + MaterialTechniqueSet* techniqueSet; + GfxImage* image; + snd_alias_list_t* sound; + SndCurve* sndCurve; + LoadedSound* loadSnd; + clipMap_t* clipMap; + ComWorld* comWorld; + GameWorldSp* gameWorldSp; + GameWorldMp* gameWorldMp; + MapEnts* mapEnts; + FxWorld* fxWorld; + GfxWorld* gfxWorld; + GfxLightDef* lightDef; + Font_s* font; + MenuList* menuList; + menuDef_t* menu; + LocalizeEntry* localize; + WeaponCompleteDef* weapon; + SndDriverGlobals* sndDriverGlobals; + FxEffectDef* fx; + FxImpactTable* impactFx; + RawFile* rawfile; + StringTable* stringTable; + LeaderboardDef* leaderboardDef; + StructuredDataDefSet* structuredDataDefSet; + TracerDef* tracerDef; + VehicleDef* vehDef; + AddonMapEnts* addonMapEnts; }; /* 9210 */ @@ -5177,7 +5177,7 @@ namespace Game struct XBlock { - char *data; + char* data; unsigned int size; }; @@ -5250,14 +5250,14 @@ namespace Game struct ScriptStringList { int count; - const char **strings; + const char** strings; }; struct XAssetList { ScriptStringList stringList; int assetCount; - XAsset *assets; + XAsset* assets; }; struct ZoneHeader @@ -5269,10 +5269,10 @@ namespace Game struct XZoneMemory { XBlock blocks[MAX_XFILE_COUNT]; - char *lockedVertexData; - char *lockedIndexData; - void *vertexBuffer; - void *indexBuffer; + char* lockedVertexData; + char* lockedIndexData; + void* vertexBuffer; + void* indexBuffer; }; struct XZone @@ -5352,8 +5352,8 @@ namespace Game struct fileInIwd_s { unsigned int pos; - char *name; - fileInIwd_s *next; + char* name; + fileInIwd_s* next; }; struct iwd_t @@ -5361,15 +5361,15 @@ namespace Game char iwdFilename[256]; char iwdBasename[256]; char iwdGamename[256]; - char *handle; + char* handle; int checksum; int pure_checksum; volatile int hasOpenFile; int numfiles; char referenced; unsigned int hashSize; - fileInIwd_s **hashTable; - fileInIwd_s *buildBuffer; + fileInIwd_s** hashTable; + fileInIwd_s* buildBuffer; }; #ifdef IDA @@ -5378,8 +5378,8 @@ namespace Game union qfile_gus { - _iobuf *o; - char *z; + _iobuf* o; + char* z; }; struct qfile_us @@ -5394,7 +5394,7 @@ namespace Game int handleSync; int fileSize; int zipFilePos; - iwd_t *zipFile; + iwd_t* zipFile; int streamed; char name[256]; }; @@ -5407,7 +5407,7 @@ namespace Game typedef struct searchpath_s { searchpath_s* next; - iwd_t *iwd; + iwd_t* iwd; directory_t* dir; int bLocalized; int ignore; @@ -5431,7 +5431,7 @@ namespace Game { bool spawnVarsValid; int numSpawnVars; - char *spawnVars[64][2]; + char* spawnVars[64][2]; int numSpawnVarChars; char spawnVarChars[2048]; }; @@ -5457,7 +5457,7 @@ namespace Game float radiusOffset[3]; float boundingRadius; /*TraceThreadInfo*/ int threadInfo; - /*CM_WorldTraceCallbacks*/ void *callbacks; + /*CM_WorldTraceCallbacks*/ void* callbacks; }; struct gameState_t @@ -5484,7 +5484,7 @@ namespace Game struct VariableStackBuffer { - const char *pos; + const char* pos; unsigned __int16 size; unsigned __int16 bufLen; unsigned __int16 localId; @@ -5542,10 +5542,10 @@ namespace Game unsigned int uintValue; float floatValue; unsigned int stringValue; - const float *vectorValue; - const char *codePosValue; + const float* vectorValue; + const char* codePosValue; unsigned int pointerValue; - VariableStackBuffer *stackValue; + VariableStackBuffer* stackValue; unsigned int entityOffset; }; @@ -5935,8 +5935,8 @@ namespace Game { int overflowed; int readOnly; - unsigned char *data; - unsigned char *splitData; + unsigned char* data; + unsigned char* splitData; int maxsize; int cursize; int splitSize; @@ -5947,7 +5947,7 @@ namespace Game struct XZoneInfo { - const char *name; + const char* name; int allocFlags; int freeFlags; }; @@ -6071,23 +6071,23 @@ namespace Game FxFloatRange elasticity; FxEditorElemAtlas atlas; float velScale[2][3]; - FxCurve *velShape[2][3][2]; + FxCurve* velShape[2][3][2]; float rotationScale; - FxCurve *rotationShape[2]; + FxCurve* rotationShape[2]; float sizeScale[2]; - FxCurve *sizeShape[2][2]; + FxCurve* sizeShape[2][2]; float scaleScale; - FxCurve *scaleShape[2]; - FxCurve *color[2]; - FxCurve *alpha[2]; + FxCurve* scaleShape[2]; + FxCurve* color[2]; + FxCurve* alpha[2]; float lightingFrac; float decalFadeInTime; float collOffset[3]; float collRadius; - FxEffectDef *effectOnImpact; - FxEffectDef *effectOnDeath; + FxEffectDef* effectOnImpact; + FxEffectDef* effectOnDeath; int sortOrder; - FxEffectDef *emission; + FxEffectDef* emission; FxFloatRange emitDist; FxFloatRange emitDistVariance; char elemType; @@ -6127,8 +6127,8 @@ namespace Game struct FxElemField { - const char *keyName; - bool(__cdecl *handler)(const char **, FxEditorElemDef *); + const char* keyName; + bool(__cdecl* handler)(const char**, FxEditorElemDef*); }; enum $18B36A54AD92993D0728595D3504B7CB @@ -6153,7 +6153,7 @@ namespace Game struct infoParm_t { - char *name; + char* name; int clearSolid; int surfaceFlags; int contents; @@ -6496,8 +6496,8 @@ namespace Game const char* name; int ofs; fieldtype_t type; - void(__cdecl * setter)(gentity_s*, int); - void(__cdecl * getter)(gentity_s*, int); + void(__cdecl* setter)(gentity_s*, int); + void(__cdecl* getter)(gentity_s*, int); }; struct client_fields_s @@ -6505,12 +6505,12 @@ namespace Game const char* name; int ofs; fieldtype_t type; - void(__cdecl * setter)(gclient_s*, const client_fields_s*); - void(__cdecl * getter)(gclient_s*, const client_fields_s*); + void(__cdecl* setter)(gclient_s*, const client_fields_s*); + void(__cdecl* getter)(gclient_s*, const client_fields_s*); }; - typedef void(__cdecl * ScriptCallbackEnt)(gentity_s*, int); - typedef void(__cdecl * ScriptCallbackClient)(gclient_s*, const client_fields_s*); + typedef void(__cdecl* ScriptCallbackEnt)(gentity_s*, int); + typedef void(__cdecl* ScriptCallbackClient)(gclient_s*, const client_fields_s*); struct lockonFireParms { @@ -6715,53 +6715,53 @@ namespace Game typedef struct script_s { char filename[64]; //file name of the script - char *buffer; //buffer containing the script - char *script_p; //current pointer in the script - char *end_p; //pointer to the end of the script - char *lastscript_p; //script pointer before reading token - char *whitespace_p; //begin of the white space - char *endwhitespace_p; //end of the white space + char* buffer; //buffer containing the script + char* script_p; //current pointer in the script + char* end_p; //pointer to the end of the script + char* lastscript_p; //script pointer before reading token + char* whitespace_p; //begin of the white space + char* endwhitespace_p; //end of the white space int length; //length of the script in bytes int line; //current line in script int lastline; //line before reading token int tokenavailable; //set by UnreadLastToken int flags; //several script flags - punctuation_t *punctuations; //the punctuations used in the script - punctuation_t **punctuationtable; + punctuation_t* punctuations; //the punctuations used in the script + punctuation_t** punctuationtable; token_t token; //available token - struct script_s *next; //next script in a chain + struct script_s* next; //next script in a chain } script_t; typedef struct define_s { - char *name; //define name + char* name; //define name int flags; //define flags int builtin; // > 0 if builtin define int numparms; //number of define parameters - token_t *parms; //define parameters - token_t *tokens; //macro tokens (possibly containing parm tokens) - struct define_s *next; //next defined macro in a list - struct define_s *hashnext; //next define in the hash chain + token_t* parms; //define parameters + token_t* tokens; //macro tokens (possibly containing parm tokens) + struct define_s* next; //next defined macro in a list + struct define_s* hashnext; //next define in the hash chain } define_t; typedef struct indent_s { int type; //indent type int skip; //true if skipping current indent - script_t *script; //script the indent was in - struct indent_s *next; //next indent on the indent stack + script_t* script; //script the indent was in + struct indent_s* next; //next indent on the indent stack } indent_t; typedef struct source_s { char filename[64]; //file name of the script char includepath[64]; //path to include files - punctuation_t *punctuations; //punctuations to use - script_t *scriptstack; //stack with scripts of the source - token_t *tokens; //tokens to read first - define_t *defines; //list with macro definitions - define_t **definehash; //hash chain with defines - indent_t *indentstack; //stack with indents + punctuation_t* punctuations; //punctuations to use + script_t* scriptstack; //stack with scripts of the source + token_t* tokens; //tokens to read first + define_t* defines; //list with macro definitions + define_t** definehash; //hash chain with defines + indent_t* indentstack; //stack with indents int skip; // > 0 if skipping conditional code token_t token; //last read token } source_t; @@ -6777,8 +6777,8 @@ namespace Game typedef struct keywordHash_s { - char *keyword; - bool(*func)(menuDef_t *item, int handle); + char* keyword; + bool(*func)(menuDef_t* item, int handle); //struct keywordHash_s *next; } keywordHash_t; @@ -6863,17 +6863,17 @@ namespace Game struct $A6DFE8F2BEFD3E7315B44D22E582538B { unsigned int stride; - IDirect3DVertexBuffer9 *vb; + IDirect3DVertexBuffer9* vb; unsigned int offset; }; struct GfxCmdBufPrimState { - IDirect3DDevice9 *device; - IDirect3DIndexBuffer9 *indexBuffer; + IDirect3DDevice9* device; + IDirect3DIndexBuffer9* indexBuffer; MaterialVertexDeclType vertDeclType; $A6DFE8F2BEFD3E7315B44D22E582538B streams[2]; - IDirect3DVertexDeclaration9 *vertexDecl; + IDirect3DVertexDeclaration9* vertexDecl; }; enum GfxDepthRangeType @@ -6913,12 +6913,12 @@ namespace Game { char refSamplerState[16]; unsigned int samplerState[16]; - GfxTexture *samplerTexture[16]; + GfxTexture* samplerTexture[16]; GfxCmdBufPrimState prim; - Material *material; + Material* material; MaterialTechniqueType techType; - MaterialTechnique *technique; - MaterialPass *pass; + MaterialTechnique* technique; + MaterialPass* pass; unsigned int passIndex; GfxDepthRangeType depthRangeType; float depthRangeNear; @@ -6928,27 +6928,27 @@ namespace Game char alphaRef; unsigned int refStateBits[2]; unsigned int activeStateBits[2]; - MaterialPixelShader *pixelShader; - MaterialVertexShader *vertexShader; + MaterialPixelShader* pixelShader; + MaterialVertexShader* vertexShader; unsigned int scissorX; unsigned int scissorY; unsigned int scissorW; unsigned int scissorH; unsigned int pixPrimarySortKey; unsigned int pixSceneLightIndex; - Material *pixMaterial; - MaterialTechnique *pixTechnique; + Material* pixMaterial; + MaterialTechnique* pixTechnique; int pixCombine; GfxViewport viewport; GfxRenderTargetId renderTargetId; - Material *origMaterial; + Material* origMaterial; MaterialTechniqueType origTechType; }; struct GfxCmdBufContext { - /*GfxCmdBufSourceState*/ void *source; - GfxCmdBufState *state; + /*GfxCmdBufSourceState*/ void* source; + GfxCmdBufState* state; }; struct GfxDrawGroupSetupFields @@ -7254,7 +7254,7 @@ namespace Game int updateSound; int allowAddDObj; }; - + enum TextRenderFlags { TEXT_RENDERFLAG_FORCEMONOSPACE = 0x1, @@ -7270,7 +7270,7 @@ namespace Game TEXT_RENDERFLAG_OUTLINE = 0x400, TEXT_RENDERFLAG_OUTLINE_EXTRA = 0x800, }; - + enum FontPassType { FONTPASS_NORMAL = 0x0, @@ -8097,7 +8097,7 @@ namespace Game int flashShotFadeTime; ShockViewTypes type; } screenBlend; - + struct { int fadeTime; From 1283abc4e709787dd4f5e5272cafd0f9baca1064 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 1 Dec 2022 14:46:18 +0000 Subject: [PATCH 29/96] [RawFiles]: Actually fix parse code --- .../Modules/AssetInterfaces/IRawFile.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.cpp b/src/Components/Modules/AssetInterfaces/IRawFile.cpp index 603a4d7c..f9e7e69c 100644 --- a/src/Components/Modules/AssetInterfaces/IRawFile.cpp +++ b/src/Components/Modules/AssetInterfaces/IRawFile.cpp @@ -18,16 +18,16 @@ namespace Assets return; } - auto compressed_size = compressBound(rawFile.getBuffer().size()); - asset->name = builder->getAllocator()->duplicateString(name); asset->len = static_cast(rawFile.getBuffer().size()); - if (asset->len < static_cast(compressed_size)) + const auto compressedData = Utils::Compression::ZLib::Compress(rawFile.getBuffer()); + // Only save the compressed buffer if we gained space + if (compressedData.size() < rawFile.getBuffer().size()) { - asset->buffer = builder->getAllocator()->allocateArray(compressed_size); - compress2((Bytef*)(asset->buffer), &compressed_size, (const Bytef*)(rawFile.getBuffer().data()), rawFile.getBuffer().size(), Z_BEST_COMPRESSION); - asset->compressedLen = static_cast(compressed_size); + asset->buffer = builder->getAllocator()->duplicateString(compressedData); + std::memcpy(const_cast(asset->buffer), compressedData.data(), compressedData.size()); + asset->compressedLen = static_cast(compressedData.size()); } else { @@ -36,8 +36,6 @@ namespace Assets asset->compressedLen = 0; } - asset->len = static_cast(rawFile.getBuffer().size()); - header->rawfile = asset; } From ee2d12e4049333da677c7495e7072ad60a49d445 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 1 Dec 2022 14:55:25 +0000 Subject: [PATCH 30/96] [RawFile]: Remove copy & pasted code --- src/Components/Modules/AssetInterfaces/IRawFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.cpp b/src/Components/Modules/AssetInterfaces/IRawFile.cpp index f9e7e69c..5a254acd 100644 --- a/src/Components/Modules/AssetInterfaces/IRawFile.cpp +++ b/src/Components/Modules/AssetInterfaces/IRawFile.cpp @@ -25,7 +25,7 @@ namespace Assets // Only save the compressed buffer if we gained space if (compressedData.size() < rawFile.getBuffer().size()) { - asset->buffer = builder->getAllocator()->duplicateString(compressedData); + asset->buffer = builder->getAllocator()->allocateArray(compressedData.size()); std::memcpy(const_cast(asset->buffer), compressedData.data(), compressedData.size()); asset->compressedLen = static_cast(compressedData.size()); } From 0156f106b9a522dfdd1daa66748a4ccffc7419e3 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 1 Dec 2022 15:01:30 +0000 Subject: [PATCH 31/96] [Zone:b:uilder]: Remove + 1 --- src/Components/Modules/ZoneBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 33ac55a4..2fe44b5a 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -519,7 +519,7 @@ namespace Components void ZoneBuilder::Zone::addBranding() { constexpr auto* data = "Built using the IW4x Zone:B:uilder Version 4"; - auto dataLen = std::strlen(data) + 1; + auto dataLen = std::strlen(data); // + 1 is added by the save code this->branding = { this->zoneName.data(), 0, static_cast(dataLen), data }; From becfbe42fa4785680f0553756434649f9bdd45c7 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 1 Dec 2022 18:24:44 +0000 Subject: [PATCH 32/96] [Download]: Use filesystem library for paths --- src/Components/Modules/Download.cpp | 119 ++++++++++++++-------------- src/Components/Modules/Download.hpp | 2 +- 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 9e3d0bc9..f127033c 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -9,19 +9,19 @@ namespace Components Download::ClientDownload Download::CLDownload; std::thread Download::ServerThread; - bool Download::Terminate; + volatile bool Download::Terminate; bool Download::ServerRunning; #pragma region Client void Download::InitiateMapDownload(const std::string& map, bool needPassword) { - Download::InitiateClientDownload(map, needPassword, true); + InitiateClientDownload(map, needPassword, true); } void Download::InitiateClientDownload(const std::string& mod, bool needPassword, bool map) { - if (Download::CLDownload.running) return; + if (CLDownload.running) return; Scheduler::Once([] { @@ -42,20 +42,20 @@ namespace Components return; } - Download::CLDownload.hashedPassword = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(password), ""); + CLDownload.hashedPassword = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(password), ""); } - Download::CLDownload.running = true; - Download::CLDownload.isMap = map; - Download::CLDownload.mod = mod; - Download::CLDownload.terminateThread = false; - Download::CLDownload.totalBytes = 0; - Download::CLDownload.lastTimeStamp = 0; - Download::CLDownload.downBytes = 0; - Download::CLDownload.timeStampBytes = 0; - Download::CLDownload.isPrivate = needPassword; - Download::CLDownload.target = Party::Target(); - Download::CLDownload.thread = std::thread(Download::ModDownloader, &Download::CLDownload); + CLDownload.running = true; + CLDownload.isMap = map; + CLDownload.mod = mod; + CLDownload.terminateThread = false; + CLDownload.totalBytes = 0; + CLDownload.lastTimeStamp = 0; + CLDownload.downBytes = 0; + CLDownload.timeStampBytes = 0; + CLDownload.isPrivate = needPassword; + CLDownload.target = Party::Target(); + CLDownload.thread = std::thread(ModDownloader, &CLDownload); } bool Download::ParseModList(ClientDownload* download, const std::string& list) @@ -92,7 +92,7 @@ namespace Components const auto name = file.at("name").get(); const auto size = file.at("size").get(); - Download::ClientDownload::File fileEntry; + ClientDownload::File fileEntry; fileEntry.name = name; fileEntry.hash = hash; fileEntry.size = size; @@ -185,7 +185,7 @@ namespace Components Logger::Print("Downloading from url {}\n", url); - Download::FileDownload fDownload; + FileDownload fDownload; fDownload.file = file; fDownload.index = index; fDownload.download = download; @@ -199,7 +199,7 @@ namespace Components fDownload.downloading = true; Utils::WebIO webIO; - webIO.setProgressCallback([&fDownload, &webIO](size_t bytes, size_t) + webIO.setProgressCallback([&fDownload, &webIO](std::size_t bytes, std::size_t) { if(!fDownload.downloading || fDownload.download->terminateThread) { @@ -207,7 +207,7 @@ namespace Components return; } - Download::DownloadProgress(&fDownload, bytes - fDownload.receivedBytes); + DownloadProgress(&fDownload, bytes - fDownload.receivedBytes); }); bool result = false; @@ -231,7 +231,7 @@ namespace Components void Download::ModDownloader(ClientDownload* download) { - if (!download) download = &Download::CLDownload; + if (!download) download = &CLDownload; std::string host = "http://" + download->target.getString(); @@ -256,7 +256,7 @@ namespace Components if (download->terminateThread) return; - if (!Download::ParseModList(download, list)) + if (!ParseModList(download, list)) { if (download->terminateThread) return; @@ -281,7 +281,7 @@ namespace Components { if (download->terminateThread) return; - if (!Download::DownloadFile(download, i)) + if (!DownloadFile(download, i)) { if (download->terminateThread) return; @@ -369,7 +369,7 @@ namespace Components }, Scheduler::Pipeline::CLIENT); } - int delta = Game::Sys_Milliseconds() - fDownload->download->lastTimeStamp; + auto delta = Game::Sys_Milliseconds() - fDownload->download->lastTimeStamp; if (delta > 300) { bool doFormat = fDownload->download->lastTimeStamp != 0; @@ -386,7 +386,7 @@ namespace Components if (doFormat) { - static size_t dlTsBytes; + static std::size_t dlTsBytes; static int dlDelta, dlTimeLeft; dlTimeLeft = timeLeft; dlDelta = delta; @@ -434,7 +434,7 @@ namespace Components { // Score and ping are irrelevant const auto* name = Game::PartyHost_GetMemberName(Game::g_lobbyData, i); - if (!name || *name == '\0') continue; + if (name == nullptr || *name == '\0') continue; playerInfo["name"] = name; } @@ -451,7 +451,7 @@ namespace Components static nlohmann::json jsonList; static auto handled = false; - const std::string fs_gameDirVar = (*Game::fs_gameDirVar)->current.string; + const std::filesystem::path fs_gameDirVar((*Game::fs_gameDirVar)->current.string); if (!fs_gameDirVar.empty() && !handled) { @@ -459,28 +459,30 @@ namespace Components std::vector fileList; - const auto path = Dvar::Var("fs_basepath").get() + "\\" + fs_gameDirVar; - auto list = FileSystem::GetSysFileList(path, "iwd", false); + const auto path = Dvar::Var("fs_basepath").get() / fs_gameDirVar; + auto list = FileSystem::GetSysFileList(path.generic_string(), "iwd", false); list.emplace_back("mod.ff"); for (const auto& file : list) { - std::string filename = path + "\\" + file; - if (file.find("_svr_") == std::string::npos) + auto filename = path / file; + if (file.find("_svr_") != std::string::npos) { - std::unordered_map jsonFileList; - std::string fileBuffer = Utils::IO::ReadFile(filename); - if (fileBuffer.empty()) - { - continue; - } - - jsonFileList["name"] = file; - jsonFileList["size"] = fileBuffer.size(); - jsonFileList["hash"] = Utils::Cryptography::SHA256::Compute(fileBuffer, true); - - fileList.emplace_back(jsonFileList); + continue; } + + std::unordered_map jsonFileList; + std::string fileBuffer = Utils::IO::ReadFile(filename.generic_string()); + if (fileBuffer.empty()) + { + continue; + } + + jsonFileList["name"] = file; + jsonFileList["size"] = fileBuffer.size(); + jsonFileList["hash"] = Utils::Cryptography::SHA256::Compute(fileBuffer, true); + + fileList.emplace_back(jsonFileList); } jsonList = fileList; @@ -506,13 +508,14 @@ namespace Components mapNamePre = mapName; - const auto path = Dvar::Var("fs_basepath").get() + "\\usermaps\\" + mapName; + const std::filesystem::path basePath(Dvar::Var("fs_basepath").get()); + const auto path = basePath / "usermaps" / mapName; - for (auto i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) + for (std::size_t i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) { - const auto filename = path + "\\" + mapName + Maps::UserMapFiles[i]; - - std::map file; + const auto filename = std::format("{}\\{}{}", path.generic_string(), mapName, Maps::UserMapFiles[i]); + + std::unordered_map file; std::string fileBuffer = Utils::IO::ReadFile(filename); if (fileBuffer.empty()) { @@ -550,7 +553,7 @@ namespace Components auto mapName = (Party::IsInUserMapLobby() ? Dvar::Var("ui_mapname").get() : Maps::GetUserMap()->getName()); auto isValidFile = false; - for (auto i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) + for (std::size_t i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) { if (url == (mapName + Maps::UserMapFiles[i])) { @@ -684,11 +687,11 @@ namespace Components } }); - Download::ServerRunning = true; - Download::Terminate = false; - Download::ServerThread = std::thread([] + ServerRunning = true; + Terminate = false; + ServerThread = std::thread([] { - while (!Download::Terminate) + while (!Terminate) { mg_mgr_poll(&Mgr, 100); } @@ -705,7 +708,7 @@ namespace Components UIScript::Add("mod_download_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - Download::CLDownload.clear(); + CLDownload.clear(); }); } @@ -718,7 +721,7 @@ namespace Components Download::~Download() { - if (Download::ServerRunning) + if (ServerRunning) { mg_mgr_free(&Mgr); } @@ -726,15 +729,15 @@ namespace Components void Download::preDestroy() { - Download::Terminate = true; - if (Download::ServerThread.joinable()) + Terminate = true; + if (ServerThread.joinable()) { - Download::ServerThread.join(); + ServerThread.join(); } if (!Dedicated::IsEnabled()) { - Download::CLDownload.clear(); + CLDownload.clear(); } } } diff --git a/src/Components/Modules/Download.hpp b/src/Components/Modules/Download.hpp index ac896e2a..84ccfd93 100644 --- a/src/Components/Modules/Download.hpp +++ b/src/Components/Modules/Download.hpp @@ -81,7 +81,7 @@ namespace Components static ClientDownload CLDownload; static std::thread ServerThread; - static bool Terminate; + static volatile bool Terminate; static bool ServerRunning; static void DownloadProgress(FileDownload* fDownload, std::size_t bytes); From 2ef78d50426fd6be3ead74c5ac706f32e841fd91 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 1 Dec 2022 18:33:32 +0000 Subject: [PATCH 33/96] [Download]: Use auto keyword --- src/Components/Modules/Download.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index f127033c..fbe7b83b 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -119,7 +119,7 @@ namespace Components auto file = download->files[index]; - std::string path = download->mod + "/" + file.name; + auto path = download->mod + "/" + file.name; if (download->isMap) { path = "usermaps/" + path; @@ -127,8 +127,7 @@ namespace Components if (Utils::IO::FileExists(path)) { - std::string data = Utils::IO::ReadFile(path); - + auto data = Utils::IO::ReadFile(path); if (data.size() == file.size && Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(data), "") == file.hash) { download->totalBytes += file.size; @@ -233,11 +232,11 @@ namespace Components { if (!download) download = &CLDownload; - std::string host = "http://" + download->target.getString(); + auto host = "http://" + download->target.getString(); - std::string listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); + auto listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); - std::string list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get(); + auto list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get(); if (list.empty()) { if (download->terminateThread) return; @@ -472,7 +471,7 @@ namespace Components } std::unordered_map jsonFileList; - std::string fileBuffer = Utils::IO::ReadFile(filename.generic_string()); + auto fileBuffer = Utils::IO::ReadFile(filename.generic_string()); if (fileBuffer.empty()) { continue; @@ -516,7 +515,7 @@ namespace Components const auto filename = std::format("{}\\{}{}", path.generic_string(), mapName, Maps::UserMapFiles[i]); std::unordered_map file; - std::string fileBuffer = Utils::IO::ReadFile(filename); + auto fileBuffer = Utils::IO::ReadFile(filename); if (fileBuffer.empty()) { continue; From cb067ff24ba63a78d2dede0b7ec7dd2d734e631c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 17:03:03 +0000 Subject: [PATCH 34/96] Bump deps/mongoose from `2553392` to `751413f` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `2553392` to `751413f`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/2553392e421fde36d1af81978af9d4cadffd90d5...751413f0503fc4fb97e9032c3ee25e30a8d53dae) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 2553392e..751413f0 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 2553392e421fde36d1af81978af9d4cadffd90d5 +Subproject commit 751413f0503fc4fb97e9032c3ee25e30a8d53dae From 5eec7687be53a82de552d8c50b999a7d1e532189 Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 2 Dec 2022 19:18:04 +0000 Subject: [PATCH 35/96] [Zone:b:uilder]: Delete 'uncompressed' file (#620) --- src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp | 6 +++--- src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp | 3 ++- src/Components/Modules/Menus.cpp | 3 ++- src/Components/Modules/ZoneBuilder.cpp | 4 ++++ src/Game/Structs.hpp | 6 +++++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp b/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp index 56205bce..64904c86 100644 --- a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp +++ b/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp @@ -151,11 +151,11 @@ namespace Assets void IGameWorldSp::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { - AssertSize(Game::GameWorldMp, 8); + AssertSize(Game::GameWorldSp, 0x38); Utils::Stream* buffer = builder->getBuffer(); - Game::GameWorldSp* asset = header.gameWorldSp; - Game::GameWorldSp* dest = buffer->dest(); + auto* asset = header.gameWorldSp; + auto* dest = buffer->dest(); buffer->save(asset); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp index ec3c18be..ada64262 100644 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp +++ b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp @@ -487,7 +487,7 @@ namespace Assets void ImenuDef_t::save_itemDef_s(Game::itemDef_s *asset, Components::ZoneBuilder::Zone* builder) { - AssertSize(Game::itemDef_s, 380); + AssertSize(Game::itemDef_s, 0x17C); Utils::Stream* buffer = builder->getBuffer(); auto* dest = buffer->dest(); @@ -608,6 +608,7 @@ namespace Assets void ImenuDef_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { AssertSize(Game::menuDef_t, 400); + AssertSize(Game::windowDef_t, 0xA4); #ifdef WRITE_LOGS buffer->enterStruct("ImenuDef_t"); diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 122a35d6..c601b8a7 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -205,7 +205,8 @@ namespace Components { Game::PC_ReadTokenHandle(handle, &token); - Utils::Merge(&menus, Menus::LoadMenu(Utils::String::VA("ui_mp\\%s.menu", token.string))); + auto* filename = Utils::String::VA("ui_mp\\%s.menu", token.string); + Utils::Merge(&menus, Menus::LoadMenu(filename)); } if (!_stricmp(token.string, "menudef")) diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 2fe44b5a..2ac3d780 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -419,6 +419,10 @@ namespace Components #endif Utils::IO::WriteFile("uncompressed", zoneBuffer); + const auto _0 = gsl::finally([] + { + Utils::IO::RemoveFile("uncompressed"); + }); zoneBuffer = Utils::Compression::ZLib::Compress(zoneBuffer); outBuffer.append(zoneBuffer); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 9450e942..949e4f9f 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -3534,7 +3534,7 @@ namespace Game Glyph* glyphs; }; - struct __declspec(align(4)) rectDef_s + struct rectDef_s { float x; float y; @@ -3544,6 +3544,8 @@ namespace Game char vertAlign; }; + static_assert(sizeof(rectDef_s) == 0x14); + struct windowDef_t { const char* name; @@ -3566,6 +3568,8 @@ namespace Game Material* background; }; + static_assert(sizeof(windowDef_t) == 0xA4); + enum expDataType { VAL_INT = 0x0, From 72460032aeb34cee479c6c0118ae49c63abdf438 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 4 Dec 2022 00:15:46 +0000 Subject: [PATCH 36/96] [Zone:b:uilder]: Port over json parsing of loc strings (#621) --- .../AssetInterfaces/ILocalizeEntry.cpp | 47 +++++++++++++++++++ .../AssetInterfaces/ILocalizeEntry.hpp | 1 + src/Components/Modules/FileSystem.hpp | 5 ++ src/Components/Modules/ZoneBuilder.cpp | 9 +++- src/Utils/Memory.cpp | 2 +- 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp index 5b5eb82a..243c0958 100644 --- a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp +++ b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp @@ -81,4 +81,51 @@ namespace Assets builder->addRawAsset(type, entry); } } + + void ILocalizeEntry::ParseLocalizedStringsJson(Components::ZoneBuilder::Zone* builder, Components::FileSystem::File& file) + { + nlohmann::json localize; + try + { + Components::Logger::Debug("Parsing localized string \"{}\"...", file.getName()); + localize = nlohmann::json::parse(file.getBuffer()); + } + catch (const std::exception& ex) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}\n", ex.what()); + return; + } + + if (!localize.is_object()) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Localized strings json file '{}' should be an object!", file.getName()); + return; + } + + std::vector assets; + + try + { + for (const auto& [key, value] : localize.items()) + { + const auto valueStr = value.get(); + + auto* entry = builder->getAllocator()->allocate(); + entry->name = builder->getAllocator()->duplicateString(key); + entry->value = builder->getAllocator()->duplicateString(valueStr); + + assets.emplace_back(entry); + } + } + catch (const std::exception& ex) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: Localized strings json file '{}' contains invalid data!", ex.what(), file.getName()); + } + + auto type = Game::DB_GetXAssetNameType("localize"); + for (const auto& entry : assets) + { + builder->addRawAsset(type, entry); + } + } } diff --git a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp index b01b9c81..3818e1d4 100644 --- a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp +++ b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp @@ -11,5 +11,6 @@ namespace Assets void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; static void ParseLocalizedStringsFile(Components::ZoneBuilder::Zone* builder, const std::string& name, const std::string& filename); + static void ParseLocalizedStringsJson(Components::ZoneBuilder::Zone* builder, Components::FileSystem::File& file); }; } diff --git a/src/Components/Modules/FileSystem.hpp b/src/Components/Modules/FileSystem.hpp index 50573b40..bcdbd0e1 100644 --- a/src/Components/Modules/FileSystem.hpp +++ b/src/Components/Modules/FileSystem.hpp @@ -13,6 +13,11 @@ namespace Components virtual bool exists() = 0; virtual std::string getName() = 0; virtual std::string& getBuffer() = 0; + + virtual explicit operator bool() + { + return this->exists(); + } }; class File : public AbstractFile diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 2ac3d780..00aa122a 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -158,12 +158,17 @@ namespace Components if (this->dataMap.getElementAt(i, 0) == "localize"s) { const auto filename = this->dataMap.getElementAt(i, 1); - FileSystem::File file(std::format("localizedstrings/{}.str", filename)); - if (file.exists()) + if (FileSystem::File file = std::format("localizedstrings/{}.str", filename)) { Assets::ILocalizeEntry::ParseLocalizedStringsFile(this, filename, file.getName()); continue; } + + if (FileSystem::File file = std::format("localizedstrings/{}.json", filename)) + { + Assets::ILocalizeEntry::ParseLocalizedStringsJson(this, file); + continue; + } } if (this->dataMap.getColumns(i) > 2) diff --git a/src/Utils/Memory.cpp b/src/Utils/Memory.cpp index ceab4894..cf26b3ca 100644 --- a/src/Utils/Memory.cpp +++ b/src/Utils/Memory.cpp @@ -21,7 +21,7 @@ namespace Utils char* Memory::DuplicateString(const std::string& string) { - auto* newString = Memory::AllocateArray(string.size() + 1); + auto* newString = AllocateArray(string.size() + 1); std::memcpy(newString, string.data(), string.size()); return newString; } From ac986e3ded2f0a981f8b67312bbbc88c0f1a8c09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 17:06:11 +0000 Subject: [PATCH 37/96] Bump deps/mongoose from `751413f` to `ad05126` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `751413f` to `ad05126`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/751413f0503fc4fb97e9032c3ee25e30a8d53dae...ad051269ed61689071f4be0f9b3207d66890c25f) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 751413f0..ad051269 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 751413f0503fc4fb97e9032c3ee25e30a8d53dae +Subproject commit ad051269ed61689071f4be0f9b3207d66890c25f From 210873499c3de71e3ed161b9c664cd49f72a9c66 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 5 Dec 2022 18:45:14 +0000 Subject: [PATCH 38/96] [Theatre]: Cleanup (#624) --- src/Components/Loader.cpp | 1 + src/Components/Loader.hpp | 1 + src/Components/Modules/Logger.cpp | 2 +- src/Components/Modules/Network.cpp | 2 +- src/Components/Modules/NetworkDebug.cpp | 47 ++++++++ src/Components/Modules/NetworkDebug.hpp | 15 +++ src/Components/Modules/Security.cpp | 8 +- src/Components/Modules/Security.hpp | 6 +- src/Components/Modules/Theatre.cpp | 140 +++++++++++------------- src/Components/Modules/Theatre.hpp | 1 - src/Game/Client.cpp | 17 ++- src/Game/Client.hpp | 21 ++++ src/Game/Dvars.cpp | 1 + src/Game/Dvars.hpp | 1 + src/Game/Functions.cpp | 10 +- src/Game/Functions.hpp | 30 ++--- src/Game/Server.cpp | 1 + src/Game/Server.hpp | 9 +- src/Game/Structs.hpp | 13 +++ src/STDInclude.hpp | 1 + 20 files changed, 216 insertions(+), 111 deletions(-) create mode 100644 src/Components/Modules/NetworkDebug.cpp create mode 100644 src/Components/Modules/NetworkDebug.hpp 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) From b8b939133292315f769756b73ac7b11781d3d99c Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 5 Dec 2022 19:34:24 +0000 Subject: [PATCH 39/96] [UI]: Fix bug (#625) --- src/Components/Modules/Dvar.cpp | 5 +++++ src/Components/Modules/Flags.cpp | 10 +++++----- src/Components/Modules/UIScript.cpp | 7 ------- src/Components/Modules/UIScript.hpp | 2 -- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index aaa34ca9..e9126362 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -402,6 +402,11 @@ namespace Components // remove write protection from fs_game Utils::Hook::Xor(0x6431EA, Game::DVAR_INIT); + // cheat protect g_hardcore + Utils::Hook::Xor(0x5E374F, Game::DVAR_CHEAT); + Utils::Hook::Xor(0x4D3689, Game::DVAR_CHEAT); + Utils::Hook::Xor(0x4197C3, Game::DVAR_CHEAT); + // set cg_fov max to 160.0 // because that's the max on SP static float cg_Fov = 160.0f; diff --git a/src/Components/Modules/Flags.cpp b/src/Components/Modules/Flags.cpp index 87400340..a41a942f 100644 --- a/src/Components/Modules/Flags.cpp +++ b/src/Components/Modules/Flags.cpp @@ -6,9 +6,9 @@ namespace Components bool Flags::HasFlag(const std::string& flag) { - Flags::ParseFlags(); + ParseFlags(); - for (const auto& entry : Flags::EnabledFlags) + for (const auto& entry : EnabledFlags) { if (Utils::String::ToLower(entry) == Utils::String::ToLower(flag)) { @@ -40,7 +40,7 @@ namespace Components if (wFlag[0] == L'-') { wFlag.erase(wFlag.begin()); - Flags::EnabledFlags.emplace_back(Utils::String::Convert(wFlag)); + EnabledFlags.emplace_back(Utils::String::Convert(wFlag)); } } @@ -48,9 +48,9 @@ namespace Components } // Workaround for wine - if (Utils::IsWineEnvironment() && Dedicated::IsEnabled() && !Flags::HasFlag("console") && !Flags::HasFlag("stdout")) + if (Utils::IsWineEnvironment() && Dedicated::IsEnabled() && !HasFlag("console") && !HasFlag("stdout")) { - Flags::EnabledFlags.emplace_back("stdout"); + EnabledFlags.emplace_back("stdout"); } } } diff --git a/src/Components/Modules/UIScript.cpp b/src/Components/Modules/UIScript.cpp index 08534954..36abb50f 100644 --- a/src/Components/Modules/UIScript.cpp +++ b/src/Components/Modules/UIScript.cpp @@ -116,11 +116,6 @@ namespace Components } } - bool UIScript::CL_IsUIActive_Hk(const int localClientNum) - { - return Game::Key_IsCatcherActive(localClientNum, Game::KEYCATCH_UI) || Game::cgsArray->hardcore; - } - UIScript::UIScript() { AssertSize(Game::uiInfo_s, 0x22FC); @@ -132,8 +127,6 @@ namespace Components // Install ownerdraw handler Utils::Hook(0x63D233, OwnerDrawHandleKeyStub, HOOK_CALL).install()->quick(); - - Utils::Hook(0x62B397, CL_IsUIActive_Hk, HOOK_CALL).install()->quick(); } UIScript::~UIScript() diff --git a/src/Components/Modules/UIScript.hpp b/src/Components/Modules/UIScript.hpp index dfbe2cee..553e15ab 100644 --- a/src/Components/Modules/UIScript.hpp +++ b/src/Components/Modules/UIScript.hpp @@ -36,8 +36,6 @@ namespace Components static bool RunMenuScript(const char* name, const char** args); static void RunMenuScriptStub(); - static bool CL_IsUIActive_Hk(int localClientNum); - static std::unordered_map UIScripts; static std::unordered_map> UIOwnerDraws; }; From c6b3e88938aab93f97b2a498af85a723f26ab865 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Tue, 6 Dec 2022 13:05:03 +0000 Subject: [PATCH 40/96] [Main]: Improve error message --- src/Components/Modules/News.cpp | 2 +- src/Components/Modules/Node.cpp | 22 ---------------------- src/Components/Modules/Node.hpp | 2 -- src/DllMain.cpp | 23 +++++++++++++---------- src/STDInclude.hpp | 1 + src/Utils/Cache.cpp | 5 ----- src/Utils/Cache.hpp | 6 +++--- src/Utils/Cryptography.cpp | 2 +- 8 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 9d70ef35..1ec06436 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -56,7 +56,7 @@ namespace Components UIScript::Add("visitWebsite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - Utils::OpenUrl(Utils::Cache::GetStaticUrl("")); + Utils::OpenUrl(Utils::Cache::GetUrl(Utils::Cache::Urls[1], {})); }); Localization::Set("MPUI_CHANGELOG_TEXT", "Loading..."); diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 19ce000c..b5084bab 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -50,20 +50,6 @@ namespace Components this->lastRequest.reset(); } - void Node::LoadNodeRemotePreset() - { - std::string nodes = Utils::Cache::GetFile("/iw4/nodes.txt"); - if (nodes.empty()) return; - - auto nodeList = Utils::String::Split(nodes, '\n'); - for (auto& node : nodeList) - { - Utils::String::Replace(node, "\r", ""); - Utils::String::Trim(node); - Node::Add(node); - } - } - void Node::LoadNodePreset() { Proto::Node::List list; @@ -350,14 +336,6 @@ namespace Components Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN); - Network::OnStart([] - { - std::thread([] - { - Node::LoadNodeRemotePreset(); - }).detach(); - }); - Command::Add("listnodes", [](Command::Params*) { Logger::Print("Nodes: {}\n", Node::Nodes.size()); diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index 389a8945..e6e992ad 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -41,8 +41,6 @@ namespace Components static void RunFrame(); static void Synchronize(); - static void LoadNodeRemotePreset(); - private: static std::recursive_mutex Mutex; static std::vector Nodes; diff --git a/src/DllMain.cpp b/src/DllMain.cpp index 7c904bfe..2a0cbec0 100644 --- a/src/DllMain.cpp +++ b/src/DllMain.cpp @@ -55,24 +55,27 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser #ifndef DISABLE_BINARY_CHECK // Ensure we're working with our desired binary - auto* _module = reinterpret_cast(0x400000); - auto hash1 = Utils::Cryptography::JenkinsOneAtATime::Compute(_module + 0x1000, 0x2D531F); // .text - auto hash2 = Utils::Cryptography::JenkinsOneAtATime::Compute(_module + 0x2D75FC, 0xBDA04); // .rdata - if ((hash1 != 0x54684DBE -#ifdef DEBUG - && hash1 != 0x8AADE716 + +#ifndef DEBUG_BINARY_CHECK + const auto* binary = reinterpret_cast(0x6F9358); + if (binary == nullptr || std::strcmp(binary, BASEGAME_NAME) != 0) #endif - ) || hash2 != 0x8030ec53) { + MessageBoxA(nullptr, + "Failed to load game binary.\n" + "You did not install the iw4x-rawfiles!\n" + "Please use the XLabs launcher to run the game. For support please visit https://xlabs.dev/support_iw4x_client", + "ERROR", + MB_ICONERROR + ); return FALSE; } - - DWORD oldProtect; - VirtualProtect(_module + 0x1000, 0x2D6000, PAGE_EXECUTE_READ, &oldProtect); // Protect the .text segment #endif +#ifndef DEBUG_BINARY_CHECK // Install entry point hook Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick(); +#endif } else if (fdwReason == DLL_PROCESS_DETACH) { diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index af82cd69..e957a9ad 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -173,6 +173,7 @@ using namespace std::literals; #endif #define BASEGAME "iw4x" +#define BASEGAME_NAME "iw4mp_ceg.exe" #define CLIENT_CONFIG "iw4x_config.cfg" // Resource stuff diff --git a/src/Utils/Cache.cpp b/src/Utils/Cache.cpp index 67479089..99c79d0d 100644 --- a/src/Utils/Cache.cpp +++ b/src/Utils/Cache.cpp @@ -11,11 +11,6 @@ namespace Utils std::string Cache::ValidUrl; std::mutex Cache::CacheMutex; - std::string Cache::GetStaticUrl(const std::string& path) - { - return Urls[0] + path; - } - std::string Cache::GetUrl(const std::string& url, const std::string& path) { return url + path; diff --git a/src/Utils/Cache.hpp b/src/Utils/Cache.hpp index 73b772fa..4c2b280f 100644 --- a/src/Utils/Cache.hpp +++ b/src/Utils/Cache.hpp @@ -5,13 +5,13 @@ namespace Utils class Cache { public: - static std::string GetStaticUrl(const std::string& path); + static const char* Urls[]; + + static std::string GetUrl(const std::string& url, const std::string& path); static std::string GetFile(const std::string& path, int timeout = 5000, const std::string& useragent = "IW4x"); private: static std::mutex CacheMutex; - static const char* Urls[]; static std::string ValidUrl; - static std::string GetUrl(const std::string& url, const std::string& path); }; } diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 26eb3813..c2e515cc 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -270,7 +270,7 @@ namespace Utils return Compute(data.data(), data.size()); } - unsigned int JenkinsOneAtATime::Compute(const char *key, size_t len) + unsigned int JenkinsOneAtATime::Compute(const char *key, std::size_t len) { unsigned int hash, i; for (hash = i = 0; i < len; ++i) From 3f06eb8eb93510ff438c0e1bc5312166991c0fd0 Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 6 Dec 2022 14:42:09 +0000 Subject: [PATCH 41/96] [Weapon]: Move fix here (#627) --- src/Components/Modules/QuickPatch.cpp | 17 ----------- src/Components/Modules/QuickPatch.hpp | 2 -- src/Components/Modules/Weapon.cpp | 42 +++++++++++++++++++++++---- src/Components/Modules/Weapon.hpp | 4 +++ 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index b68e267e..3110347a 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -47,20 +47,6 @@ namespace Components } } - __declspec(naked) void QuickPatch::JavelinResetHook_Stub() - { - __asm - { - mov eax, 577A10h; - call eax; - pop edi; - mov dword ptr [esi+34h], 0; - pop esi; - pop ebx; - retn; - } - } - Game::dvar_t* QuickPatch::g_antilag; __declspec(naked) void QuickPatch::ClientEventsFireWeapon_Stub() { @@ -315,9 +301,6 @@ namespace Components Utils::Hook(0x5D6D56, QuickPatch::ClientEventsFireWeapon_Stub, HOOK_JUMP).install()->quick(); Utils::Hook(0x5D6D6A, QuickPatch::ClientEventsFireWeaponMelee_Stub, HOOK_JUMP).install()->quick(); - // Javelin fix - Utils::Hook(0x578F52, QuickPatch::JavelinResetHook_Stub, HOOK_JUMP).install()->quick(); - // Add ultrawide support Utils::Hook(0x51B13B, QuickPatch::Dvar_RegisterAspectRatioDvar, HOOK_CALL).install()->quick(); Utils::Hook(0x5063F3, QuickPatch::SetAspectRatio_Stub, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/QuickPatch.hpp b/src/Components/Modules/QuickPatch.hpp index 64fa0793..58679706 100644 --- a/src/Components/Modules/QuickPatch.hpp +++ b/src/Components/Modules/QuickPatch.hpp @@ -12,8 +12,6 @@ namespace Components static void UnlockStats(); private: - static void JavelinResetHook_Stub(); - static Dvar::Var r_customAspectRatio; static Game::dvar_t* Dvar_RegisterAspectRatioDvar(const char* dvarName, const char** valueList, int defaultIndex, unsigned __int16 flags, const char* description); static void SetAspectRatio_Stub(); diff --git a/src/Components/Modules/Weapon.cpp b/src/Components/Modules/Weapon.cpp index ae82ada9..bdc0a646 100644 --- a/src/Components/Modules/Weapon.cpp +++ b/src/Components/Modules/Weapon.cpp @@ -3,6 +3,8 @@ namespace Components { + const Game::dvar_t* Weapon::BGWeaponOffHandFix; + Game::WeaponCompleteDef* Weapon::LoadWeaponCompleteDef(const char* name) { if (auto* rawWeaponFile = Game::BG_LoadWeaponCompleteDefInternal("mp", name)) @@ -481,7 +483,7 @@ namespace Components // Game code push 0x48BB2D - retn + ret null: push 0x48BB1F // Exit function @@ -499,7 +501,7 @@ namespace Components jz touched push 0x56E82C - retn + ret touched: test dword ptr [edi + 0x2BC], PWF_DISABLE_WEAPON_PICKUP @@ -515,7 +517,32 @@ namespace Components continue_func: push 0x56E84C - retn + ret + } + } + + __declspec(naked) void Weapon::JavelinResetHook_Stub() + { + static DWORD PM_Weapon_OffHandEnd_t = 0x577A10; + + __asm + { + call PM_Weapon_OffHandEnd_t + + push eax + mov eax, BGWeaponOffHandFix + cmp byte ptr [eax + 0x10], 1 + pop eax + + jne safeReturn + + mov dword ptr [esi + 0x34], 0 // playerState_s.grenadeTimeLeft + + safeReturn: + pop edi + pop esi + pop ebx + ret } } @@ -565,9 +592,14 @@ namespace Components Utils::Hook(0x59E341, CG_UpdatePrimaryForAltModeWeapon_Stub, HOOK_JUMP).install()->quick(); Utils::Hook(0x48BB25, CG_SelectWeaponIndex_Stub, HOOK_JUMP).install()->quick(); - AddScriptMethods(); - AssertOffset(Game::playerState_s, Game::playerState_s::weapCommon.weapFlags, 0x2BC); Utils::Hook(0x56E825, WeaponEntCanBeGrabbed_Stub, HOOK_JUMP).install()->quick(); + + // Javelin fix (PM_Weapon_OffHandEnd) + AssertOffset(Game::playerState_s, grenadeTimeLeft, 0x34); + BGWeaponOffHandFix = Game::Dvar_RegisterBool("bg_weaponOffHandFix", true, Game::DVAR_CODINFO, "Reset grenadeTimeLeft after using off hand weapon"); + Utils::Hook(0x578F52, JavelinResetHook_Stub, HOOK_JUMP).install()->quick(); + + AddScriptMethods(); } } diff --git a/src/Components/Modules/Weapon.hpp b/src/Components/Modules/Weapon.hpp index 3b6d14d5..7e5a235a 100644 --- a/src/Components/Modules/Weapon.hpp +++ b/src/Components/Modules/Weapon.hpp @@ -13,6 +13,8 @@ namespace Components Weapon(); private: + static const Game::dvar_t* BGWeaponOffHandFix; + static Game::WeaponCompleteDef* LoadWeaponCompleteDef(const char* name); static void PatchLimit(); static void* LoadNoneWeaponHook(); @@ -29,6 +31,8 @@ namespace Components static void CG_UpdatePrimaryForAltModeWeapon_Stub(); static void CG_SelectWeaponIndex_Stub(); + static void JavelinResetHook_Stub(); + static void WeaponEntCanBeGrabbed_Stub(); static void AddScriptMethods(); }; From b80ee8cc7acd69d06e93321cf2a13d97cd48cb79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Dec 2022 17:03:01 +0000 Subject: [PATCH 42/96] Bump deps/mongoose from `ad05126` to `f14798d` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `ad05126` to `f14798d`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/ad051269ed61689071f4be0f9b3207d66890c25f...f14798dec9da41cfc390e8ddf14545aeeb8af2fb) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index ad051269..f14798de 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit ad051269ed61689071f4be0f9b3207d66890c25f +Subproject commit f14798dec9da41cfc390e8ddf14545aeeb8af2fb From fc97944a12922ef706d510bf62ed79b1f5b58004 Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 6 Dec 2022 21:18:29 +0000 Subject: [PATCH 43/96] [MapRotation]: Port changes from S1x (#629) --- src/Components/Modules/MapRotation.cpp | 38 ++++++++++++++------------ src/Components/Modules/MapRotation.hpp | 3 +- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index a9f01a8a..b349fa80 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -26,7 +26,7 @@ namespace Components this->rotationEntries_.emplace_back(std::make_pair(key, value)); } - std::size_t MapRotation::RotationData::getEntriesSize() const + std::size_t MapRotation::RotationData::getEntriesSize() const noexcept { return this->rotationEntries_.size(); } @@ -47,7 +47,7 @@ namespace Components const auto& key = tokens[i]; const auto& value = tokens[i + 1]; - if (key == "map" || key == "gametype") + if (key == "map"s || key == "gametype"s) { this->addEntry(key, value); } @@ -58,13 +58,17 @@ namespace Components } } + bool MapRotation::RotationData::empty() const noexcept + { + return this->rotationEntries_.empty(); + } + bool MapRotation::RotationData::contains(const std::string& key, const std::string& value) const { - return std::ranges::any_of(this->rotationEntries_, - [&](const auto& entry) - { - return entry.first == key && entry.second == value; - }); + return std::ranges::any_of(this->rotationEntries_, [&](const auto& entry) + { + return entry.first == key && entry.second == value; + }); } nlohmann::json MapRotation::RotationData::to_json() const @@ -74,18 +78,18 @@ namespace Components for (const auto& [key, val] : this->rotationEntries_) { - if (key == "map") + if (key == "map"s) { mapVector.emplace_back(val); } - else if (key == "gametype") + else if (key == "gametype"s) { gametypeVector.emplace_back(val); } } - nlohmann::json mapRotationJson = nlohmann::json + auto mapRotationJson = nlohmann::json { {"maps", mapVector}, {"gametypes", gametypeVector}, @@ -194,7 +198,7 @@ namespace Components void MapRotation::ApplyGametype(const std::string& gametype) { assert(!gametype.empty()); - Dvar::Var("g_gametype").set(gametype.data()); + Dvar::Var("g_gametype").set(gametype); } void MapRotation::RestartCurrentMap() @@ -204,7 +208,7 @@ namespace Components if (svMapname.empty()) { Logger::Print(Game::CON_CHANNEL_SERVER, "mapname dvar is empty! Defaulting to mp_afghan\n"); - svMapname = "mp_afghan"; + svMapname = "mp_afghan"s; } ApplyMap(svMapname); @@ -212,7 +216,7 @@ namespace Components void MapRotation::ApplyRotation(RotationData& rotation) { - assert(rotation.getEntriesSize() != 0); + assert(!rotation.empty()); // Continue to apply gametype until a map is found auto foundMap = false; @@ -222,7 +226,7 @@ namespace Components { const auto& entry = rotation.getNextEntry(); - if (entry.first == "map") + if (entry.first == "map"s) { Logger::Debug("Loading new map: '{}'", entry.second); ApplyMap(entry.second); @@ -230,7 +234,7 @@ namespace Components // Map was found so we exit the loop foundMap = true; } - else if (entry.first == "gametype") + else if (entry.first == "gametype"s) { Logger::Debug("Applying new gametype: '{}'", entry.second); ApplyGametype(entry.second); @@ -260,7 +264,7 @@ namespace Components Game::Dvar_SetString(*Game::sv_mapRotationCurrent, ""); - if (rotationCurrent.getEntriesSize() == 0) + if (rotationCurrent.empty()) { Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*Game::sv_mapRotationCurrent)->name); RestartCurrentMap(); @@ -302,7 +306,7 @@ namespace Components } LoadMapRotation(); - if (DedicatedRotation.getEntriesSize() == 0) + if (DedicatedRotation.empty()) { Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*Game::sv_mapRotation)->name); RestartCurrentMap(); diff --git a/src/Components/Modules/MapRotation.hpp b/src/Components/Modules/MapRotation.hpp index 4a57d1a0..09da7517 100644 --- a/src/Components/Modules/MapRotation.hpp +++ b/src/Components/Modules/MapRotation.hpp @@ -30,11 +30,12 @@ namespace Components // this method should be called to add a new entry (gamemode/map & value) void addEntry(const std::string& key, const std::string& value); - [[nodiscard]] std::size_t getEntriesSize() const; + [[nodiscard]] std::size_t getEntriesSize() const noexcept; rotationEntry& getNextEntry(); void parse(const std::string& data); + [[nodiscard]] bool empty() const noexcept; [[nodiscard]] bool contains(const std::string& key, const std::string& value) const; [[nodiscard]] nlohmann::json to_json() const; From 5df8aba871113e45bd01be469c36fb19376f9bac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:04:18 +0000 Subject: [PATCH 44/96] Bump deps/mongoose from `f14798d` to `615d324` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `f14798d` to `615d324`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/f14798dec9da41cfc390e8ddf14545aeeb8af2fb...615d324b11f9e6b813d51094669448773ccd9705) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index f14798de..615d324b 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit f14798dec9da41cfc390e8ddf14545aeeb8af2fb +Subproject commit 615d324b11f9e6b813d51094669448773ccd9705 From f3efbd781af303e5a1648a02abf2b67471d7c6ab Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 8 Dec 2022 20:40:59 +0100 Subject: [PATCH 45/96] [Deps]: Cleanup libtomcrypt (#632) --- deps/premake/libtomcrypt.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deps/premake/libtomcrypt.lua b/deps/premake/libtomcrypt.lua index 51860cfa..6e8cf0f3 100644 --- a/deps/premake/libtomcrypt.lua +++ b/deps/premake/libtomcrypt.lua @@ -17,6 +17,8 @@ function libtomcrypt.includes() "LTC_NO_FAST", "LTC_NO_PROTOTYPES", "LTC_NO_RSA_BLINDING", + "LTC_NO_FILE", + "ARGTYPE=4", } end @@ -32,6 +34,7 @@ function libtomcrypt.project() } removefiles { + path.join(libtomcrypt.source, "src/**/*_test.c"), path.join(libtomcrypt.source, "src/**/*tab.c"), path.join(libtomcrypt.source, "src/encauth/ocb3/**.c"), } From 9fcf4a77c3a8448a5b93c8331bf324f9138e1cf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 17:02:48 +0000 Subject: [PATCH 46/96] Bump deps/nlohmannjson from `a3e6e26` to `349e4b3` Bumps [deps/nlohmannjson](https://github.com/nlohmann/json) from `a3e6e26` to `349e4b3`. - [Release notes](https://github.com/nlohmann/json/releases) - [Commits](https://github.com/nlohmann/json/compare/a3e6e26dc83a726b292f5be0492fcc408663ce55...349e4b310e173e187823c77bf32dbe72b5494bae) --- updated-dependencies: - dependency-name: deps/nlohmannjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/nlohmannjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/nlohmannjson b/deps/nlohmannjson index a3e6e26d..349e4b31 160000 --- a/deps/nlohmannjson +++ b/deps/nlohmannjson @@ -1 +1 @@ -Subproject commit a3e6e26dc83a726b292f5be0492fcc408663ce55 +Subproject commit 349e4b310e173e187823c77bf32dbe72b5494bae From cb8a21c3b1891a980dd9a79d6eb06e0f133da7bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 17:02:51 +0000 Subject: [PATCH 47/96] Bump deps/mongoose from `615d324` to `0b2712f` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `615d324` to `0b2712f`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/615d324b11f9e6b813d51094669448773ccd9705...0b2712f52f8747d557509d170c6b42ecbfe552fc) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 615d324b..0b2712f5 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 615d324b11f9e6b813d51094669448773ccd9705 +Subproject commit 0b2712f52f8747d557509d170c6b42ecbfe552fc From ac90714811ac96e5853234a373f41c15af59f478 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 11 Dec 2022 18:54:24 +0100 Subject: [PATCH 48/96] [General]: Use std::format more often (#635) --- .../Modules/AssetInterfaces/IComWorld.cpp | 2 +- .../Modules/AssetInterfaces/IFont_s.cpp | 6 +-- .../Modules/AssetInterfaces/IFxEffectDef.cpp | 2 +- .../Modules/AssetInterfaces/IGfxImage.cpp | 2 +- .../Modules/AssetInterfaces/IGfxLightDef.cpp | 2 +- .../Modules/AssetInterfaces/IGfxWorld.cpp | 2 +- .../Modules/AssetInterfaces/ILoadedSound.cpp | 2 +- .../Modules/AssetInterfaces/IMapEnts.cpp | 4 +- .../Modules/AssetInterfaces/IMaterial.cpp | 4 +- .../AssetInterfaces/IMaterialPixelShader.cpp | 2 +- .../AssetInterfaces/IMaterialTechniqueSet.cpp | 4 +- .../IMaterialVertexDeclaration.cpp | 2 +- .../AssetInterfaces/IMaterialVertexShader.cpp | 2 +- .../Modules/AssetInterfaces/IWeapon.cpp | 2 +- .../Modules/AssetInterfaces/IXAnimParts.cpp | 2 +- .../Modules/AssetInterfaces/IXModel.cpp | 2 +- .../Modules/AssetInterfaces/IclipMap_t.cpp | 4 +- .../Modules/AssetInterfaces/ImenuDef_t.cpp | 2 +- .../AssetInterfaces/Isnd_alias_list_t.cpp | 2 +- src/Components/Modules/CardTitles.cpp | 4 +- src/Components/Modules/Changelog.cpp | 2 +- src/Components/Modules/Chat.cpp | 18 ++++---- src/Components/Modules/ClanTags.cpp | 6 +-- src/Components/Modules/ClientCommand.cpp | 37 +++++++--------- src/Components/Modules/ConnectProtocol.cpp | 43 ++++++++++--------- src/Components/Modules/Dedicated.cpp | 2 +- src/Components/Modules/Download.cpp | 2 +- src/Components/Modules/Dvar.cpp | 4 +- src/Components/Modules/FastFiles.cpp | 17 ++++---- src/Components/Modules/GSC/Script.cpp | 4 +- src/Components/Modules/Gametypes.cpp | 2 +- src/Components/Modules/Logger.cpp | 6 +-- src/Components/Modules/Maps.cpp | 20 ++++----- src/Components/Modules/ModList.cpp | 4 +- src/Components/Modules/ModelSurfs.cpp | 2 +- src/Components/Modules/QuickPatch.cpp | 5 ++- src/Components/Modules/StructuredData.cpp | 2 +- src/Components/Modules/Theatre.cpp | 12 +++--- src/Components/Modules/ZoneBuilder.cpp | 17 ++++---- src/Components/Modules/Zones.cpp | 14 +++--- src/Utils/Stream.cpp | 16 +++---- src/Utils/Stream.hpp | 19 ++++---- src/Utils/String.hpp | 11 +++++ src/Utils/Utils.hpp | 22 +++++++--- 44 files changed, 178 insertions(+), 163 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IComWorld.cpp b/src/Components/Modules/AssetInterfaces/IComWorld.cpp index bb01b757..ae7aff94 100644 --- a/src/Components/Modules/AssetInterfaces/IComWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IComWorld.cpp @@ -11,7 +11,7 @@ namespace Assets Utils::String::Replace(name, "maps/mp/", ""); Utils::String::Replace(name, ".d3dbsp", ""); - Components::FileSystem::File mapFile(Utils::String::VA("comworld/%s.iw4xComWorld", name.data())); + Components::FileSystem::File mapFile(std::format("comworld/{}.iw4xComWorld", name)); if (mapFile.exists()) { diff --git a/src/Components/Modules/AssetInterfaces/IFont_s.cpp b/src/Components/Modules/AssetInterfaces/IFont_s.cpp index 59c072a9..b2988164 100644 --- a/src/Components/Modules/AssetInterfaces/IFont_s.cpp +++ b/src/Components/Modules/AssetInterfaces/IFont_s.cpp @@ -95,8 +95,8 @@ namespace Assets void IFont_s::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File fontDefFile(Utils::String::VA("%s.json", name.data())); - Components::FileSystem::File fontFile(Utils::String::VA("%s.ttf", name.data())); + Components::FileSystem::File fontDefFile(std::format("{}.json", name)); + Components::FileSystem::File fontFile(std::format("{}.ttf", name)); if (!fontDefFile.exists() || !fontFile.exists()) { @@ -254,7 +254,7 @@ namespace Assets rgbaPixels[i + 3] = static_cast(pixels[i / 4]); } - Utils::IO::WriteFile(Utils::String::VA("userraw\\images\\%s.iwi", texName), outIwi); + Utils::IO::WriteFile(std::format("userraw\\images\\{}.iwi", texName), outIwi); } void IFont_s::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) diff --git a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp index 80778bb6..37e2c8db 100644 --- a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp +++ b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp @@ -64,7 +64,7 @@ namespace Assets void IFxEffectDef::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File fxFile(Utils::String::VA("fx/%s.iw4xFx", name.data())); + Components::FileSystem::File fxFile(std::format("fx/{}.iw4xFx", name)); if (fxFile.exists()) { diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp index e7be7614..823876eb 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -23,7 +23,7 @@ namespace Assets const char* tempName = image->name; if (tempName[0] == '*') tempName++; - Components::FileSystem::File imageFile(Utils::String::VA("images/%s.iw4xImage", tempName)); + Components::FileSystem::File imageFile(std::format("images/{}.iw4xImage", tempName)); if (imageFile.exists()) { Utils::Stream::Reader reader(builder->getAllocator(), imageFile.getBuffer()); diff --git a/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp b/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp index 6347f993..c2e58c70 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp @@ -7,7 +7,7 @@ namespace Assets { void IGfxLightDef::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File mapFile(Utils::String::VA("lights/%s.iw4xLight", name.data())); + Components::FileSystem::File mapFile(std::format("lights/{}.iw4xLight", name)); if (mapFile.exists()) { diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 556303be..3a84a800 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -129,7 +129,7 @@ namespace Assets Utils::String::Replace(name, "maps/mp/", ""); Utils::String::Replace(name, ".d3dbsp", ""); - Components::FileSystem::File mapFile(Utils::String::VA("gfxworld/%s.iw4xGfxWorld", name.data())); + Components::FileSystem::File mapFile(std::format("gfxworld/{}.iw4xGfxWorld", name)); if (mapFile.exists()) { diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp index 6e282c15..45b291a4 100644 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp +++ b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp @@ -5,7 +5,7 @@ namespace Assets { void ILoadedSound::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File soundFile(Utils::String::VA("loaded_sound/%s", name.data())); + Components::FileSystem::File soundFile(std::format("loaded_sound/{}", name)); if (!soundFile.exists()) { header->loadSnd = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).loadSnd; diff --git a/src/Components/Modules/AssetInterfaces/IMapEnts.cpp b/src/Components/Modules/AssetInterfaces/IMapEnts.cpp index 9cd343a0..11f4ac0a 100644 --- a/src/Components/Modules/AssetInterfaces/IMapEnts.cpp +++ b/src/Components/Modules/AssetInterfaces/IMapEnts.cpp @@ -10,7 +10,7 @@ namespace Assets Utils::String::Replace(name, "mp/", ""); Utils::String::Replace(name, ".d3dbsp", ""); - Components::FileSystem::File ents(Utils::String::VA("mapents/%s.ents", name.data())); + Components::FileSystem::File ents(std::format("mapents/{}.ents", name)); if (ents.exists()) { Game::MapEnts* entites = builder->getAllocator()->allocate(); @@ -48,7 +48,7 @@ namespace Assets std::string entityString = ents.getBuffer(); - entites->name = builder->getAllocator()->duplicateString(Utils::String::VA("maps/mp/%s.d3dbsp", name.data())); + entites->name = builder->getAllocator()->duplicateString(std::format("maps/mp/{}.d3dbsp", name)); entites->entityString = builder->getAllocator()->duplicateString(entityString); entites->numEntityChars = entityString.size() + 1; diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp index 499acf36..e6635b0e 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -53,7 +53,7 @@ namespace Assets {"mc_unlit_alphatest", "mc_unlit_blend_lin"} }; - Components::FileSystem::File materialFile(Utils::String::VA("materials/%s.iw4xMaterial", name.data())); + Components::FileSystem::File materialFile(std::format("materials/{}.iw4xMaterial", name)); if (!materialFile.exists()) return; Utils::Stream::Reader reader(builder->getAllocator(), materialFile.getBuffer()); @@ -329,7 +329,7 @@ namespace Assets void IMaterial::loadJson(Game::XAssetHeader* header, const std::string& name, [[maybe_unused]] Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File materialInfo(Utils::String::VA("materials/%s.json", name.data())); + Components::FileSystem::File materialInfo(std::format("materials/{}.json", name)); if (!materialInfo.exists()) return; diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp index fd91bae6..47c24cdd 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp @@ -19,7 +19,7 @@ namespace Assets void IMaterialPixelShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File psFile(Utils::String::VA("ps/%s.iw4xPS", name.data())); + Components::FileSystem::File psFile(std::format("ps/{}.iw4xPS", name)); if (!psFile.exists()) return; Utils::Stream::Reader reader(builder->getAllocator(), psFile.getBuffer()); diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp index 30364266..cf713cea 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp @@ -20,7 +20,7 @@ namespace Assets { AssertSize(Game::MaterialPass, 20); - Components::FileSystem::File techFile(Utils::String::VA("techniques/%s.iw4xTech", name.data())); + Components::FileSystem::File techFile(std::format("techniques/{}.iw4xTech", name)); if (!techFile.exists()) { *tech = nullptr; Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Missing technique '{}'\n", name); @@ -101,7 +101,7 @@ namespace Assets void IMaterialTechniqueSet::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File tsFile(Utils::String::VA("techsets/%s.iw4xTS", name.data())); + Components::FileSystem::File tsFile(std::format("techsets/{}.iw4xTS", name)); if (!tsFile.exists()) return; Utils::Stream::Reader reader(builder->getAllocator(), tsFile.getBuffer()); diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp index 2b506f05..e1225f7e 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp @@ -18,7 +18,7 @@ namespace Assets void IMaterialVertexDeclaration::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File declFile(Utils::String::VA("decl/%s.iw4xDECL", name.data())); + Components::FileSystem::File declFile(std::format("decl/{}.iw4xDECL", name)); if (!declFile.exists()) return; Utils::Stream::Reader reader(builder->getAllocator(), declFile.getBuffer()); diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp index bf786e52..3acd7be2 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp @@ -18,7 +18,7 @@ namespace Assets void IMaterialVertexShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File vsFile(Utils::String::VA("vs/%s.iw4xVS", name.data())); + Components::FileSystem::File vsFile(std::format("vs/{}.iw4xVS", name)); if (!vsFile.exists()) return; Utils::Stream::Reader reader(builder->getAllocator(), vsFile.getBuffer()); diff --git a/src/Components/Modules/AssetInterfaces/IWeapon.cpp b/src/Components/Modules/AssetInterfaces/IWeapon.cpp index be6f6946..d98b310f 100644 --- a/src/Components/Modules/AssetInterfaces/IWeapon.cpp +++ b/src/Components/Modules/AssetInterfaces/IWeapon.cpp @@ -6,7 +6,7 @@ namespace Assets void IWeapon::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) { // Try loading raw weapon - if (Components::FileSystem::File(Utils::String::VA("weapons/mp/%s", name.data())).exists()) + if (Components::FileSystem::File(std::format("weapons/mp/{}", name))) { // let the function see temporary assets when calling DB_FindXAssetHeader during the loading function // otherwise it fails to link things properly diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp index e3e67e6b..f9527de5 100644 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp +++ b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp @@ -7,7 +7,7 @@ namespace Assets { void IXAnimParts::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File animFile(Utils::String::VA("xanim/%s.iw4xAnim", name.data())); + Components::FileSystem::File animFile(std::format("xanim/{}.iw4xAnim", name)); if (animFile.exists()) { diff --git a/src/Components/Modules/AssetInterfaces/IXModel.cpp b/src/Components/Modules/AssetInterfaces/IXModel.cpp index 60dea742..386bc472 100644 --- a/src/Components/Modules/AssetInterfaces/IXModel.cpp +++ b/src/Components/Modules/AssetInterfaces/IXModel.cpp @@ -85,7 +85,7 @@ namespace Assets void IXModel::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File modelFile(Utils::String::VA("xmodel/%s.iw4xModel", name.data())); + Components::FileSystem::File modelFile(std::format("xmodel/{}.iw4xModel", name)); if (!builder->isPrimaryAsset() && (!Components::ZoneBuilder::PreferDiskAssetsDvar.get() || !modelFile.exists())) { diff --git a/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp b/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp index ae28d788..f0524227 100644 --- a/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp +++ b/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp @@ -573,7 +573,7 @@ namespace Assets Utils::String::Replace(name, "maps/mp/", ""); Utils::String::Replace(name, ".d3dbsp", ""); - Components::FileSystem::File clipFile(Utils::String::VA("clipmap/%s.iw4xClipMap", name.data())); + Components::FileSystem::File clipFile(std::format("clipmap/{}.iw4xClipMap", name)); if (!clipFile.exists()) { return; @@ -882,7 +882,7 @@ namespace Assets clipMap->smodelNodeCount = reader.read(); clipMap->smodelNodes = reader.readArray(clipMap->smodelNodeCount); - clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, Utils::String::VA("maps/mp/%s.d3dbsp", name.data()), builder).mapEnts; + clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, std::format("maps/mp/{}.d3dbsp", name), builder).mapEnts; // add triggers to mapEnts if (version >= 2) { diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp index ada64262..65a10757 100644 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp +++ b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp @@ -9,7 +9,7 @@ namespace Assets void ImenuDef_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) { // load from disk - auto menus = Components::Menus::LoadMenu(Utils::String::VA("ui_mp/%s.menu", name.data())); + auto menus = Components::Menus::LoadMenu(std::format("ui_mp/{}.menu", name)); if (menus.empty()) return; if (menus.size() > 1) Components::Logger::Print("Menu '{}' on disk has more than one menudef in it. Only saving the first one\n", name); diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp index 021781b3..21a88b27 100644 --- a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp +++ b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp @@ -5,7 +5,7 @@ namespace Assets { void Isnd_alias_list_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File aliasFile(Utils::String::VA("sounds/%s.json", name.data())); + Components::FileSystem::File aliasFile(std::format("sounds/{}.json", name)); if (!aliasFile.exists()) { header->sound = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).sound; diff --git a/src/Components/Modules/CardTitles.cpp b/src/Components/Modules/CardTitles.cpp index da34aa24..d4dcb8b0 100644 --- a/src/Components/Modules/CardTitles.cpp +++ b/src/Components/Modules/CardTitles.cpp @@ -169,10 +169,10 @@ namespace Components playerTitle[0] = '\0'; } - list.append(Utils::String::VA("\\%s\\%s", std::to_string(i).data(), playerTitle)); + list.append(std::format("\\{}\\{}", std::to_string(i), playerTitle)); } - const auto* command = Utils::String::VA("%c customTitles \"%s\"", 21, list.data()); + const auto* command = Utils::String::Format("{:c} customTitles \"{}\"", 21, list); Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, command); } diff --git a/src/Components/Modules/Changelog.cpp b/src/Components/Modules/Changelog.cpp index cafb5ebc..fd82a21c 100644 --- a/src/Components/Modules/Changelog.cpp +++ b/src/Components/Modules/Changelog.cpp @@ -38,7 +38,7 @@ namespace Components std::lock_guard _(Mutex); if (item < Lines.size()) { - return Utils::String::VA("%s", Lines[item].data()); + return Utils::String::Format("{}", Lines[item]); } return ""; diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index a3ada816..4cb1b3e9 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -268,8 +268,7 @@ namespace Components }); Logger::Print("{} was muted\n", client->name); - Game::SV_GameSendServerCommand(client - Game::svs_clients, Game::SV_CMD_CAN_IGNORE, - Utils::String::VA("%c \"You were muted\"", 0x65)); + Game::SV_GameSendServerCommand(client - Game::svs_clients, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"You were muted\"", 0x65)); } void Chat::UnmuteClient(const Game::client_t* client) @@ -277,8 +276,7 @@ namespace Components UnmuteInternal(client->steamID); Logger::Print("{} was unmuted\n", client->name); - Game::SV_GameSendServerCommand(client - Game::svs_clients, Game::SV_CMD_CAN_IGNORE, - Utils::String::VA("%c \"You were unmuted\"", 0x65)); + Game::SV_GameSendServerCommand(client - Game::svs_clients, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"You were unmuted\"", 0x65)); } void Chat::UnmuteInternal(const std::uint64_t id, bool everyone) @@ -369,12 +367,12 @@ namespace Components if (!name.empty()) { - Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s: %s\"", 0x68, name.data(), message.data())); + Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"{}: {}\"", 0x68, name, message)); Logger::Print(Game::CON_CHANNEL_SERVER, "{}: {}\n", name, message); } else { - Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"Console: %s\"", 0x68, message.data())); + Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"Console: {}\"", 0x68, message)); Logger::Print(Game::CON_CHANNEL_SERVER, "Console: {}\n", message); } }); @@ -395,12 +393,12 @@ namespace Components if (!name.empty()) { - Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s: %s\"", 0x68, name.data(), message.data())); + Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"{}: {}\"", 0x68, name.data(), message)); Logger::Print(Game::CON_CHANNEL_SERVER, "{} -> {}: {}\n", name, client, message); } else { - Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"Console: %s\"", 104, message.data())); + Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"Console: {}\"", 0x68, message)); Logger::Print(Game::CON_CHANNEL_SERVER, "Console -> {}: {}\n", client, message); } }); @@ -416,7 +414,7 @@ namespace Components if (params->size() < 2) return; auto message = params->join(1); - Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x68, message.data())); + Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"{}\"", 0x68, message)); Logger::Print(Game::CON_CHANNEL_SERVER, "Raw: {}\n", message); }); @@ -432,7 +430,7 @@ namespace Components const auto client = atoi(params->get(1)); std::string message = params->join(2); - Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x68, message.data())); + Game::SV_GameSendServerCommand(client, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} \"{}\"", 0x68, message)); Logger::Print(Game::CON_CHANNEL_SERVER, "Raw -> {}: {}\n", client, message); }); diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index 2aa3d29d..eda87643 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -28,15 +28,15 @@ namespace Components list.append(std::format("\\{}\\{}", std::to_string(i), ClientState[i])); } - const auto* command = Utils::String::VA("%c clanNames \"%s\"", 22, list.data()); - Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, command); + Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, Utils::String::Format("{:c} clanNames \"{}\"", 22, list)); } void ClanTags::ParseClanTags(const char* infoString) { for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i) { - const auto* clanTag = Game::Info_ValueForKey(infoString, std::to_string(i).data()); + const auto index = std::to_string(i); + const auto* clanTag = Game::Info_ValueForKey(infoString, index.data()); if (clanTag[0] == '\0') { diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index 8eaf76e2..0cddc918 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -1,6 +1,8 @@ #include #include "GSC/Script.hpp" +using namespace Utils::String; + namespace Components { std::unordered_map> ClientCommand::HandlersSV; @@ -12,14 +14,14 @@ namespace Components if (!(*Game::g_cheats)->current.enabled) { Logger::Debug("Cheats are disabled!"); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"GAME_CHEATSNOTENABLED\"", 0x65)); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"GAME_CHEATSNOTENABLED\"", 0x65)); return false; } if (ent->health < 1) { Logger::Debug("Entity {} must be alive to use this command!", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"GAME_MUSTBEALIVECOMMAND\"", 0x65)); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"GAME_MUSTBEALIVECOMMAND\"", 0x65)); return false; } @@ -67,8 +69,7 @@ namespace Components const auto entNum = ent->s.number; Logger::Debug("Noclip toggled for entity {}", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x65, - (ent->client->flags & Game::PLAYER_FLAG_NOCLIP) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF")); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"%s\"", 0x65, (ent->client->flags & Game::PLAYER_FLAG_NOCLIP) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF")); }); Add("ufo", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -81,8 +82,7 @@ namespace Components const auto entNum = ent->s.number; Logger::Debug("UFO toggled for entity {}", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x65, - (ent->client->flags & Game::PLAYER_FLAG_UFO) ? "GAME_UFOON" : "GAME_UFOOFF")); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"%s\"", 0x65, (ent->client->flags & Game::PLAYER_FLAG_UFO) ? "GAME_UFOON" : "GAME_UFOOFF")); }); Add("god", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -95,8 +95,7 @@ namespace Components const auto entNum = ent->s.number; Logger::Debug("God toggled for entity {}", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x65, - (ent->flags & Game::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF")); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"%s\"", 0x65, (ent->flags & Game::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF")); }); Add("demigod", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -109,8 +108,7 @@ namespace Components const auto entNum = ent->s.number; Logger::Debug("Demigod toggled for entity {}", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x65, - (ent->flags & Game::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF")); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"%s\"", 0x65, (ent->flags & Game::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF")); }); Add("notarget", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -123,8 +121,7 @@ namespace Components const auto entNum = ent->s.number; Logger::Debug("Notarget toggled for entity {}", entNum); - Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"%s\"", 0x65, - (ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF")); + Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, VA("%c \"%s\"", 0x65, (ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF")); }); Add("setviewpos", [](Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -138,8 +135,7 @@ namespace Components if (params->size() < 4 || params->size() > 6) { - Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_CAN_IGNORE, - Utils::String::VA("%c \"GAME_USAGE\x15: setviewpos x y z [yaw] [pitch]\n\"", 0x65)); + Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_CAN_IGNORE, VA("%c \"GAME_USAGE\x15: setviewpos x y z [yaw] [pitch]\n\"", 0x65)); return; } @@ -170,8 +166,7 @@ namespace Components if (params->size() < 2) { - Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_CAN_IGNORE, - Utils::String::VA("%c \"GAME_USAGE\x15: give \"", 0x65)); + Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_CAN_IGNORE, VA("%c \"GAME_USAGE\x15: give \"", 0x65)); return; } @@ -308,8 +303,7 @@ namespace Components strncpy_s(ent->client->visionName[visMode], sizeof(Game::gclient_t::visionName[0]) / sizeof(char), name, _TRUNCATE); - Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_RELIABLE, - Utils::String::VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration)); + Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_RELIABLE, VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration)); }); Add("visionsetnight", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -336,8 +330,7 @@ namespace Components strncpy_s(ent->client->visionName[visMode], sizeof(Game::gclient_t::visionName[0]) / sizeof(char), name, _TRUNCATE); - Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_RELIABLE, - Utils::String::VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration)); + Game::SV_GameSendServerCommand(ent->s.number, Game::SV_CMD_RELIABLE, VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration)); }); Add("g_testCmd", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] const Command::ServerParams* params) @@ -406,7 +399,7 @@ namespace Components // See description of the format string in the function G_DumpEntityDebugInfoToCSV // If empty it means the item does not exist in the current version of the game or it was not possible to reverse it - return Utils::String::VA("%i,%s,%.0f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%.0f %.0f %.0f,%.0f %.0f %.0f,%i\n", + return VA("%i,%s,%.0f,%s,%s,%s,%s,%s,%s,%s,%s,%s,%.0f %.0f %.0f,%.0f %.0f %.0f,%i\n", entNum, eventType, distance, classname, codeClassname, (model) ? model->name : "", targetName, target, "", scriptLinkName, team, "", point[0], point[1], point[2], angles[0], angles[1], angles[2], 0); @@ -442,7 +435,7 @@ namespace Components { assert(filenameSuffix); - const auto* fileName = Utils::String::VA("%s%s%s%s", "EntInfo", (*filenameSuffix) ? "_" : "", filenameSuffix, ".csv"); + const auto* fileName = VA("%s%s%s%s", "EntInfo", (*filenameSuffix) ? "_" : "", filenameSuffix, ".csv"); Logger::Print(Game::CON_CHANNEL_SERVER, "Opening file \"{}\" for writing.\n", fileName); auto h = Game::FS_FOpenTextFileWrite(fileName); diff --git a/src/Components/Modules/ConnectProtocol.cpp b/src/Components/Modules/ConnectProtocol.cpp index a3323a9b..fd3c9a77 100644 --- a/src/Components/Modules/ConnectProtocol.cpp +++ b/src/Components/Modules/ConnectProtocol.cpp @@ -7,17 +7,17 @@ namespace Components bool ConnectProtocol::IsEvaluated() { - return ConnectProtocol::Evaluated; + return Evaluated; } bool ConnectProtocol::Used() { - if (!ConnectProtocol::IsEvaluated()) + if (!IsEvaluated()) { - ConnectProtocol::EvaluateProtocol(); + EvaluateProtocol(); } - return (!ConnectProtocol::ConnectString.empty()); + return (!ConnectString.empty()); } bool ConnectProtocol::InstallProtocol() @@ -25,8 +25,8 @@ namespace Components HKEY hKey = nullptr; std::string data; - char ownPth[MAX_PATH] = {0}; - char workdir[MAX_PATH] = {0}; + char ownPth[MAX_PATH]{}; + char workdir[MAX_PATH]{}; DWORD dwsize = MAX_PATH; HMODULE hModule = GetModuleHandleA(nullptr); @@ -65,13 +65,13 @@ namespace Components LONG openRes = RegOpenKeyExA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x\\shell\\open\\command", 0, KEY_ALL_ACCESS, &hKey); if (openRes == ERROR_SUCCESS) { - char regred[MAX_PATH] = { 0 }; + char regred[MAX_PATH]{}; // Check if the game has been moved. openRes = RegQueryValueExA(hKey, nullptr, nullptr, nullptr, reinterpret_cast(regred), &dwsize); if (openRes == ERROR_SUCCESS) { - char* endPtr = strstr(regred, "\" \"%1\""); + auto* endPtr = std::strstr(regred, "\" \"%1\""); if (endPtr != nullptr) { *endPtr = 0; @@ -82,7 +82,8 @@ namespace Components } RegCloseKey(hKey); - if (strcmp(regred + 1, ownPth)) + + if (std::strcmp(regred + 1, ownPth) != 0) { RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x"); } @@ -173,8 +174,8 @@ namespace Components void ConnectProtocol::EvaluateProtocol() { - if (ConnectProtocol::Evaluated) return; - ConnectProtocol::Evaluated = true; + if (Evaluated) return; + Evaluated = true; std::string cmdLine = GetCommandLineA(); @@ -190,15 +191,15 @@ namespace Components cmdLine = cmdLine.substr(0, pos); } - ConnectProtocol::ConnectString = cmdLine; + ConnectString = cmdLine; } } void ConnectProtocol::Invocation() { - if (ConnectProtocol::Used()) + if (Used()) { - Command::Execute(Utils::String::VA("connect %s", ConnectProtocol::ConnectString.data()), false); + Command::Execute(std::format("connect {}", ConnectString), false); } } @@ -209,28 +210,28 @@ namespace Components // IPC handler IPCPipe::On("connect", [](const std::string& data) { - Command::Execute(Utils::String::VA("connect %s", data.data()), false); + Command::Execute(std::format("connect {}", data), false); }); // Invocation handler - Scheduler::OnGameInitialized(ConnectProtocol::Invocation, Scheduler::Pipeline::MAIN); + Scheduler::OnGameInitialized(Invocation, Scheduler::Pipeline::MAIN); - ConnectProtocol::InstallProtocol(); - ConnectProtocol::EvaluateProtocol(); + InstallProtocol(); + EvaluateProtocol(); // Fire protocol handlers // Make sure this happens after the pipe-initialization! - if (ConnectProtocol::Used()) + if (Used()) { if (!Singleton::IsFirstInstance()) { - IPCPipe::Write("connect", ConnectProtocol::ConnectString); + IPCPipe::Write("connect", ConnectString); ExitProcess(0); } else { // Only skip intro here, invocation will be done later. - Utils::Hook::Set(0x60BECF, 0xEB); + Utils::Hook::Set(0x60BECF, 0xEB); Scheduler::Once([] { diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 547ac20b..493275ba 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -114,7 +114,7 @@ namespace Components if (!partyEnable) // Time wrapping should not occur in party servers, but yeah... { if (mapname.empty()) mapname = "mp_rust"; - Command::Execute(Utils::String::VA("map %s", mapname.data()), true); + Command::Execute(std::format("map {}", mapname), true); } }, Scheduler::Pipeline::SERVER); diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index fbe7b83b..16c324d4 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -284,7 +284,7 @@ namespace Components { if (download->terminateThread) return; - mod = Utils::String::VA("Failed to download file: %s!", download->files[i].name.data()); + mod = std::format("Failed to download file: {}!", download->files[i].name); download->thread.detach(); download->clear(); diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index e9126362..ebffebd1 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -307,10 +307,10 @@ namespace Components { if (!Utils::IO::FileExists(ArchiveDvarPath)) { - Utils::IO::WriteFile(ArchiveDvarPath, "// generated by IW4x, do not modify\n"); + Utils::IO::WriteFile(ArchiveDvarPath, "// generated by IW4x, do not modify\n", false); } - Utils::IO::WriteFile(ArchiveDvarPath, Utils::String::VA("seta %s \"%s\"\n", var->name, Game::Dvar_DisplayableValue(var)), true); + Utils::IO::WriteFile(ArchiveDvarPath, std::format("set {} \"{}\"\n", var->name, Game::Dvar_DisplayableValue(var)), true); } void Dvar::DvarSetFromStringByName_Stub(const char* dvarName, const char* value) diff --git a/src/Components/Modules/FastFiles.cpp b/src/Components/Modules/FastFiles.cpp index fedb64d3..c3b3cb01 100644 --- a/src/Components/Modules/FastFiles.cpp +++ b/src/Components/Modules/FastFiles.cpp @@ -235,10 +235,11 @@ namespace Components const char* dir = Dvar::Var("fs_basepath").get(); std::vector paths; - std::string modDir = Dvar::Var("fs_game").get(); + auto modDir = Dvar::Var("fs_game").get(); + if ((file == "mod"s || file == "mod.ff"s) && !modDir.empty()) { - paths.push_back(Utils::String::VA("%s\\", modDir.data())); + paths.push_back(std::format("{}\\", modDir)); } if (Utils::String::StartsWith(file, "mp_")) @@ -256,17 +257,17 @@ namespace Components Utils::String::Replace(zone, "_load", ""); } - if (Utils::IO::FileExists(Utils::String::VA("usermaps\\%s\\%s.ff", zone.data(), filename.data()))) + if (Utils::IO::FileExists(std::format("usermaps\\{}\\{}.ff", zone, filename))) { - return Utils::String::VA("usermaps\\%s\\", zone.data()); + return Utils::String::Format("usermaps\\{}\\", zone); } } Utils::Merge(&paths, FastFiles::ZonePaths); - for (auto &path : paths) + for (auto& path : paths) { - std::string absoluteFile = Utils::String::VA("%s\\%s%s", dir, path.data(), file); + auto absoluteFile = std::format("{}\\{}{}", dir, path, file); // No ".ff" appended, append it manually if (!Utils::String::EndsWith(absoluteFile, ".ff")) @@ -277,11 +278,11 @@ namespace Components // Check if FastFile exists if (Utils::IO::FileExists(absoluteFile)) { - return Utils::String::VA("%s", path.data()); + return Utils::String::Format("{}", path); } } - return Utils::String::VA("zone\\%s\\", Game::Win_GetLanguage()); + return Utils::String::Format("zone\\{}\\", Game::Win_GetLanguage()); } void FastFiles::AddZonePath(const std::string& path) diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 19693cb5..e662ccf6 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -329,7 +329,7 @@ namespace Components const auto name = Utils::String::ToLower(*pName); for (const auto& func : CustomScrFunctions) { - if (std::ranges::find(func.aliases, name) != func.aliases.end()) + if (Utils::Contains(&func.aliases, name)) { *type = func.type; return func.actionFunc; @@ -356,7 +356,7 @@ namespace Components const auto name = Utils::String::ToLower(*pName); for (const auto& meth : CustomScrMethods) { - if (std::ranges::find(meth.aliases, name) != meth.aliases.end()) + if (Utils::Contains(&meth.aliases, name)) { *type = meth.type; return meth.actionFunc; diff --git a/src/Components/Modules/Gametypes.cpp b/src/Components/Modules/Gametypes.cpp index 93c580ba..df8e6735 100644 --- a/src/Components/Modules/Gametypes.cpp +++ b/src/Components/Modules/Gametypes.cpp @@ -78,7 +78,7 @@ namespace Components std::string data; for (auto& gametype : gametypes) { - if (Game::Scr_AddSourceBuffer(nullptr, Utils::String::VA("maps/mp/gametypes/%s.txt", gametype.data()), nullptr, false)) + if (Game::Scr_AddSourceBuffer(nullptr, Utils::String::Format("maps/mp/gametypes/{}.txt", gametype), nullptr, false)) { data.append(gametype); data.append("\r\n"); diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 48ec826b..4037303c 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -266,8 +266,8 @@ namespace Components { if (params->size() < 2) return; - const auto num = atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[0].size()) + const auto num = std::atoi(params->get(1)); + if (!std::strcmp(Utils::String::VA("%i", num), params->get(1)) && static_cast(num) < LoggingAddresses[0].size()) { auto addr = Logger::LoggingAddresses[0].begin() + num; Print("Address {} removed\n", addr->getString()); @@ -318,7 +318,7 @@ namespace Components if (params->size() < 2) return; const auto num = std::atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[1].size()) + if (!std::strcmp(Utils::String::VA("%i", num), params->get(1)) && static_cast(num) < LoggingAddresses[1].size()) { const auto addr = LoggingAddresses[1].begin() + num; Print("Address {} removed\n", addr->getString()); diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 266e9a9f..fcb99cee 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -29,8 +29,8 @@ namespace Components { if (this->isValid() && !this->searchPath.iwd) { - std::string iwdName = Utils::String::VA("%s.iwd", this->mapname.data()); - std::string path = Utils::String::VA("%s\\usermaps\\%s\\%s", Dvar::Var("fs_basepath").get(), this->mapname.data(), iwdName.data()); + auto iwdName = std::format("{}.iwd", this->mapname); + auto path = std::format("{}\\usermaps\\{}\\{}", Dvar::Var("fs_basepath").get(), this->mapname, iwdName); if (Utils::IO::FileExists(path)) { @@ -146,10 +146,10 @@ namespace Components team.allocFlags = zoneInfo->allocFlags; team.freeFlags = zoneInfo->freeFlags; - team.name = allocator.duplicateString(Utils::String::VA("iw4x_team_%s", teams.first.data())); + team.name = allocator.duplicateString(std::format("iw4x_team_{}", teams.first)); data.push_back(team); - team.name = allocator.duplicateString(Utils::String::VA("iw4x_team_%s", teams.second.data())); + team.name = allocator.duplicateString(std::format("iw4x_team_{}", teams.second)); data.push_back(team); } @@ -166,7 +166,7 @@ namespace Components } // Load patch files - std::string patchZone = Utils::String::VA("patch_%s", zoneInfo->name); + auto patchZone = std::format("patch_{}", zoneInfo->name); if (FastFiles::Exists(patchZone)) { data.push_back({patchZone.data(), zoneInfo->allocFlags, zoneInfo->freeFlags}); @@ -301,7 +301,7 @@ namespace Components Game::GfxWorld* world = *reinterpret_cast(0x66DEE94); - if (FileSystem::File(Utils::String::VA("sun/%s.sun", Maps::CurrentMainZone.data())).exists()) + if (FileSystem::File(std::format("sun/{}.sun", Maps::CurrentMainZone))) { Game::R_LoadSunThroughDvars(Maps::CurrentMainZone.data(), &world->sun); } @@ -404,13 +404,13 @@ namespace Components unsigned int Maps::GetUsermapHash(const std::string& map) { - if (Utils::IO::DirectoryExists(Utils::String::VA("usermaps/%s", map.data()))) + if (Utils::IO::DirectoryExists(std::format("usermaps/{}", map))) { std::string hash; for (std::size_t i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) { - std::string filePath = Utils::String::VA("usermaps/%s/%s%s", map.data(), map.data(), Maps::UserMapFiles[i]); + auto filePath = std::format("usermaps/{}/{}{}", map, map, Maps::UserMapFiles[i]); if (Utils::IO::FileExists(filePath)) { hash.append(Utils::Cryptography::SHA256::Compute(Utils::IO::ReadFile(filePath))); @@ -570,7 +570,7 @@ namespace Components bool Maps::IsUserMap(const std::string& mapname) { - return Utils::IO::DirectoryExists(Utils::String::VA("usermaps/%s", mapname.data())) && Utils::IO::FileExists(Utils::String::VA("usermaps/%s/%s.ff", mapname.data(), mapname.data())); + return Utils::IO::DirectoryExists(std::format("usermaps/{}", mapname)) && Utils::IO::FileExists(std::format("usermaps/{}/{}.ff", mapname, mapname)); } Game::XAssetEntry* Maps::GetAssetEntryPool() @@ -916,7 +916,7 @@ namespace Components unsigned int i = 0; for (auto& model : models) { - Game::R_AddCmdDrawText(Utils::String::VA("%d %s", model.second, model.first.data()), 0x7FFFFFFF, font, 15.0f, (height * scale + 1) * (i++ + 1) + 15.0f, scale, scale, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL); + Game::R_AddCmdDrawText(Utils::String::VA("%d %s", model.second, model.first.data()), std::numeric_limits::max(), font, 15.0f, (height * scale + 1) * (i++ + 1) + 15.0f, scale, scale, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL); } }, Scheduler::Pipeline::RENDERER); } diff --git a/src/Components/Modules/ModList.cpp b/src/Components/Modules/ModList.cpp index 5dc9d38c..65d1e708 100644 --- a/src/Components/Modules/ModList.cpp +++ b/src/Components/Modules/ModList.cpp @@ -60,7 +60,6 @@ namespace Components { auto fsGame = Dvar::Var("fs_game"); fsGame.set(""); - fsGame.get()->modified = true; if (Dvar::Var("cl_modVidRestart").get()) { @@ -75,8 +74,7 @@ namespace Components void ModList::RunMod(const std::string& mod) { auto fsGame = Dvar::Var("fs_game"); - fsGame.set(Utils::String::VA("mods/%s", mod.data())); - fsGame.get()->modified = true; + fsGame.set(std::format("mods/{}", mod)); if (Dvar::Var("cl_modVidRestart").get()) { diff --git a/src/Components/Modules/ModelSurfs.cpp b/src/Components/Modules/ModelSurfs.cpp index 40c61812..4c5424a4 100644 --- a/src/Components/Modules/ModelSurfs.cpp +++ b/src/Components/Modules/ModelSurfs.cpp @@ -38,7 +38,7 @@ namespace Components Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(const std::string& name) { Utils::Memory::Allocator allocator; - FileSystem::FileReader model(Utils::String::VA("models/%s", name.data())); + FileSystem::FileReader model(std::format("models/{}", name)); if (!model.exists()) { diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 3110347a..4684d2de 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -576,7 +576,8 @@ namespace Components formatString = "userraw/shader_bin/%.vs"; } - if (Utils::IO::FileExists(Utils::String::VA(formatString, name.data()))) return; + const auto path = std::format("{}{}", formatString, name); + if (Utils::IO::FileExists(path)) return; Utils::Stream buffer(0x1000); auto* dest = buffer.dest(); @@ -588,7 +589,7 @@ namespace Components Utils::Stream::ClearPointer(&dest->prog.loadDef.program); } - Utils::IO::WriteFile(Utils::String::VA(formatString, name.data()), buffer.toBuffer()); + Utils::IO::WriteFile(path, buffer.toBuffer()); } if (type == Game::ASSET_TYPE_TECHNIQUE_SET) diff --git a/src/Components/Modules/StructuredData.cpp b/src/Components/Modules/StructuredData.cpp index 42ead9e1..5164a112 100644 --- a/src/Components/Modules/StructuredData.cpp +++ b/src/Components/Modules/StructuredData.cpp @@ -199,7 +199,7 @@ namespace Components for (int i = 156;; ++i) { // We're on DB thread (OnLoad) so use DB thread for FS - FileSystem::File definition(Utils::String::VA("%s/%d.json", filename.data(), i), Game::FsThread::FS_THREAD_DATABASE); + FileSystem::File definition(std::format("{}/{}.json", filename, i), Game::FsThread::FS_THREAD_DATABASE); if (!definition.exists()) break; std::vector> enumContainer; diff --git a/src/Components/Modules/Theatre.cpp b/src/Components/Modules/Theatre.cpp index 0c917386..eb01abc7 100644 --- a/src/Components/Modules/Theatre.cpp +++ b/src/Components/Modules/Theatre.cpp @@ -190,9 +190,7 @@ namespace Components for (auto demo : demos) { - FileSystem::File meta(Utils::String::VA("demos/%s.json", demo.data())); - - if (meta.exists()) + if (FileSystem::File meta = std::format("demos/{}.json", demo)) { nlohmann::json metaObject; try @@ -206,7 +204,7 @@ namespace Components demoInfo.mapname = metaObject["mapname"].get(); demoInfo.length = metaObject["length"].get(); auto timestamp = metaObject["timestamp"].get(); - demoInfo.timeStamp = _atoi64(timestamp.data()); + demoInfo.timeStamp = std::strtoll(timestamp.data(), nullptr, 10); Demos.push_back(demoInfo); } @@ -312,11 +310,11 @@ namespace Components for (auto i = 0; i < numDel; ++i) { Logger::Print("Deleting old demo {}\n", files[i]); - FileSystem::_DeleteFile("demos", files[i].data()); - FileSystem::_DeleteFile("demos", Utils::String::VA("%s.json", files[i].data())); + FileSystem::_DeleteFile("demos", files[i]); + FileSystem::_DeleteFile("demos", std::format("%s.json", files[i])); } - Command::Execute(Utils::String::VA("record auto_%lld", time(nullptr)), true); + Command::Execute(Utils::String::VA("record auto_%lld", std::time(nullptr)), true); } return Utils::Hook::Call(0x42BBB0)(); diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 00aa122a..2defb49b 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -23,7 +23,7 @@ namespace Components // Side note: if you need a fastfile larger than 100MB, you're doing it wrong- // Well, decompressed maps can get way larger than 100MB, so let's increase that. buffer(0xC800000), - zoneName(name), dataMap("zone_source/" + name + ".csv"), branding{ nullptr }, assetDepth(0) + zoneName(name), dataMap("zone_source/" + name + ".csv"), branding{nullptr}, assetDepth(0) { } @@ -1196,9 +1196,10 @@ namespace Components Zone(zoneName).build(); }); - Command::Add("buildall", [](Command::Params*) + Command::Add("buildall", []([[maybe_unused]] Command::Params* params) { - auto zoneSources = FileSystem::GetSysFileList(Dvar::Var("fs_basepath").get() + "\\zone_source", "csv", false); + auto path = std::format("{}\\zone_source", Dvar::Var("fs_basepath").get()); + auto zoneSources = FileSystem::GetSysFileList(path, "csv", false); for (auto source : zoneSources) { @@ -1207,7 +1208,7 @@ namespace Components source = source.substr(0, source.find(".csv")); } - Command::Execute(Utils::String::VA("buildzone %s", source.data()), true); + Command::Execute(std::format("buildzone {}", source), true); } }); @@ -1528,12 +1529,12 @@ namespace Components { if (params->size() < 2) return; - std::string path = Utils::String::VA("%s\\mods\\%s\\images", Dvar::Var("fs_basepath").get(), params->get(1)); - std::vector images = FileSystem::GetSysFileList(path, "iwi", false); + auto path = std::format("{}\\mods\\{}\\images", Dvar::Var("fs_basepath").get(), params->get(1)); + auto images = FileSystem::GetSysFileList(path, "iwi", false); - for(auto i = images.begin(); i != images.end();) + for (auto i = images.begin(); i != images.end();) { - *i = Utils::String::VA("images/%s", i->data()); + *i = std::format("images/{}", *i); if (FileSystem::File(*i).exists()) { diff --git a/src/Components/Modules/Zones.cpp b/src/Components/Modules/Zones.cpp index 590718f1..933a133a 100644 --- a/src/Components/Modules/Zones.cpp +++ b/src/Components/Modules/Zones.cpp @@ -3515,7 +3515,7 @@ namespace Components Logger::Print("decrypted {} images!\n", images.size()); }); - Command::Add("decryptSounds", [](Command::Params*) + Command::Add("decryptSounds", []([[maybe_unused]] Command::Params* params) { auto sounds = FileSystem::GetSysFileList("iw4x/sound", "iwi"); Logger::Print("decrypting {} sounds...\n", sounds.size()); @@ -3523,19 +3523,19 @@ namespace Components for (auto& sound : sounds) { char* buffer = nullptr; - auto fileLength = Game::FS_ReadFile(Utils::String::VA("sound/%s", sound.data()), &buffer); + auto len = Game::FS_ReadFile(Utils::String::Format("sound/{}", sound), &buffer); - if (fileLength && buffer) + if (len && buffer) { auto path = std::filesystem::path(sound.data()); std::filesystem::create_directories("raw/sound" / path.parent_path()); - if (!std::filesystem::exists(Utils::String::VA("raw/sound/%s", sound.data()))) + if (!std::filesystem::exists(std::format("raw/sound/{}", sound))) { - const auto fp = fopen(Utils::String::VA("raw/sound/%s", sound.data()), "wb"); - if (fp) + FILE* fp; + if (!fopen_s(&fp, Utils::String::Format("raw/sound/{}", sound), "wb") && fp) { - fwrite(buffer, fileLength, 1, fp); + fwrite(buffer, len, 1, fp); fclose(fp); } } diff --git a/src/Utils/Stream.cpp b/src/Utils/Stream.cpp index 95d83dfc..dc50f51c 100644 --- a/src/Utils/Stream.cpp +++ b/src/Utils/Stream.cpp @@ -108,7 +108,7 @@ namespace Utils if (this->criticalSectionState != 0) { - MessageBoxA(nullptr, Utils::String::VA("Invalid critical section state '%i' for stream destruction!", this->criticalSectionState), "WARNING", MB_ICONEXCLAMATION); + MessageBoxA(nullptr, String::VA("Invalid critical section state '%i' for stream destruction!", this->criticalSectionState), "WARNING", MB_ICONEXCLAMATION); } }; @@ -163,7 +163,7 @@ namespace Utils if (this->isCriticalSection() && this->length() + (size * count) > this->capacity()) { - MessageBoxA(nullptr, Utils::String::VA("Potential stream reallocation during critical operation detected! Writing data of the length 0x%X exceeds the allocated stream size of 0x%X\n", (size * count), this->capacity()), "ERROR", MB_ICONERROR); + MessageBoxA(nullptr, String::VA("Potential stream reallocation during critical operation detected! Writing data of the length 0x%X exceeds the allocated stream size of 0x%X\n", (size * count), this->capacity()), "ERROR", MB_ICONERROR); __debugbreak(); } @@ -291,9 +291,9 @@ namespace Utils } #ifdef WRITE_LOGS - std::string data = Utils::String::VA("%*s%d\n", this->structLevel, "", size); - if (stream == Game::XFILE_BLOCK_RUNTIME) data = Utils::String::VA("%*s(%d)\n", this->structLevel, "", size); - Utils::IO::WriteFile("userraw/logs/zb_writes.log", data, true); + const auto* data = String::VA("%*s%u\n", this->structLevel, "", size); + if (stream == Game::XFILE_BLOCK_RUNTIME) data = String::VA("%*s(%u)\n", this->structLevel, "", size); + IO::WriteFile("userraw/logs/zb_writes.log", data, true); #endif } @@ -365,7 +365,7 @@ namespace Utils --this->criticalSectionState; } - bool Stream::isCriticalSection() + bool Stream::isCriticalSection() const { if (this->criticalSectionState < 0) { @@ -381,7 +381,7 @@ namespace Utils { if (this->structLevel >= 0) { - Utils::IO::WriteFile("userraw/logs/zb_writes.log", Utils::String::VA("%*s%s\n", this->structLevel++, "", structName), true); + IO::WriteFile("userraw/logs/zb_writes.log", String::VA("%*s%s\n", this->structLevel++, "", structName), true); } } @@ -393,7 +393,7 @@ namespace Utils return; } - Utils::IO::WriteFile("userraw/logs/zb_writes.log", Utils::String::VA("%*s-----\n", this->structLevel, ""), true); + IO::WriteFile("userraw/logs/zb_writes.log", String::VA("%*s-----\n", this->structLevel, ""), true); } #endif } diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index b63fc978..e9f7ae96 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -1,7 +1,7 @@ #pragma once // write logs for ZoneBuilder -//#define WRITE_LOGS + #ifndef WRITE_LOGS // they take forever to run so only enable if needed #define SaveLogEnter(x) #define SaveLogExit() @@ -67,7 +67,7 @@ namespace Utils unsigned int position; std::string buffer; std::map pointerMap; - Utils::Memory::Allocator* allocator; + Memory::Allocator* allocator; }; enum Alignment @@ -89,17 +89,19 @@ namespace Utils Stream(size_t size); ~Stream(); - std::size_t length() const; - std::size_t capacity() const; + [[nodiscard]] std::size_t length() const; + [[nodiscard]] std::size_t capacity() const; char* save(const void * _str, std::size_t size, std::size_t count = 1); char* save(Game::XFILE_BLOCK_TYPES stream, const void * _str, std::size_t size, std::size_t count); char* save(Game::XFILE_BLOCK_TYPES stream, int value, std::size_t count); - template inline char* save(T* object) + + template char* save(T* object) { return saveArray(object, 1); } - template inline char* saveArray(T* array, std::size_t count) + + template char* saveArray(T* array, std::size_t count) { return save(array, sizeof(T), count); } @@ -131,7 +133,8 @@ namespace Utils { return reinterpret_cast(this->at()); } - template static inline void ClearPointer(T** object) + + template static void ClearPointer(T** object) { *object = reinterpret_cast(-1); } @@ -151,7 +154,7 @@ namespace Utils // by editing the code though. void enterCriticalSection(); void leaveCriticalSection(); - bool isCriticalSection(); + bool isCriticalSection() const; // for recording zb writes #ifdef WRITE_LOGS diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index cf2417f3..242ea0d9 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -84,6 +84,17 @@ namespace Utils::String [[nodiscard]] const char* VA(const char* fmt, ...); + template + [[nodiscard]] const char* Format(std::string_view fmt, Args&&... args) + { + static thread_local std::string vaBuffer; + vaBuffer.clear(); + + (SanitizeFormatArgs(args), ...); + std::vformat_to(std::back_inserter(vaBuffer), fmt, std::make_format_args(args...)); + return vaBuffer.data(); + } + [[nodiscard]] std::string ToLower(const std::string& text); [[nodiscard]] std::string ToUpper(const std::string& text); diff --git a/src/Utils/Utils.hpp b/src/Utils/Utils.hpp index 702efd38..252def02 100644 --- a/src/Utils/Utils.hpp +++ b/src/Utils/Utils.hpp @@ -25,7 +25,8 @@ namespace Utils bool HasIntersection(unsigned int base1, unsigned int len1, unsigned int base2, unsigned int len2); - template void RotLeft(T& object, size_t bits) + template + void RotLeft(T& object, std::size_t bits) { bits %= sizeof(T) * 8; @@ -38,31 +39,40 @@ namespace Utils object |= T(negative) << ((sizeof(T) * 8 - 1 + bits) % (sizeof(T) * 8)); } - template void RotRight(T& object, size_t bits) + template + void RotRight(T& object, std::size_t bits) { bits %= (sizeof(T) * 8); RotLeft(object, ((sizeof(T) * 8) - bits)); } - template void Merge(std::vector* target, T* source, size_t length) + template + void Merge(std::vector* target, T* source, std::size_t length) { if (source) { - for (size_t i = 0; i < length; ++i) + for (std::size_t i = 0; i < length; ++i) { target->push_back(source[i]); } } } - template void Merge(std::vector* target, std::vector source) + template + void Merge(std::vector* target, std::vector source) { - for (auto &entry : source) + for (auto& entry : source) { target->push_back(entry); } } + template + bool Contains(const std::vector* haystack, T needle) + { + return std::ranges::find(*haystack, needle) != haystack->end(); + } + template using Slot = std::function; template class Signal From 0af1eea7786c85be3b66a1cf53d9ec85687100fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 17:04:39 +0000 Subject: [PATCH 49/96] Bump deps/nlohmannjson from `349e4b3` to `7f72eed` Bumps [deps/nlohmannjson](https://github.com/nlohmann/json) from `349e4b3` to `7f72eed`. - [Release notes](https://github.com/nlohmann/json/releases) - [Commits](https://github.com/nlohmann/json/compare/349e4b310e173e187823c77bf32dbe72b5494bae...7f72eedc2d4fc196d389f5aa0b2659f70dabe278) --- updated-dependencies: - dependency-name: deps/nlohmannjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/nlohmannjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/nlohmannjson b/deps/nlohmannjson index 349e4b31..7f72eedc 160000 --- a/deps/nlohmannjson +++ b/deps/nlohmannjson @@ -1 +1 @@ -Subproject commit 349e4b310e173e187823c77bf32dbe72b5494bae +Subproject commit 7f72eedc2d4fc196d389f5aa0b2659f70dabe278 From 9073896afca0097efeed545eb8169c7654e7a348 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 17:04:49 +0000 Subject: [PATCH 50/96] Bump deps/protobuf from `57786d1` to `7ef0c27` Bumps [deps/protobuf](https://github.com/google/protobuf) from `57786d1` to `7ef0c27`. - [Release notes](https://github.com/google/protobuf/releases) - [Commits](https://github.com/google/protobuf/compare/57786d126249b5ed4f42b579047941805e742949...7ef0c27900b1c77e592c514677eefe2636691e3c) --- updated-dependencies: - dependency-name: deps/protobuf dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/protobuf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/protobuf b/deps/protobuf index 57786d12..7ef0c279 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 57786d126249b5ed4f42b579047941805e742949 +Subproject commit 7ef0c27900b1c77e592c514677eefe2636691e3c From a88b8adbcbdb6c3120043860aa540d684c98857d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 17:03:29 +0000 Subject: [PATCH 51/96] Bump deps/mongoose from `0b2712f` to `6921227` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `0b2712f` to `6921227`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/0b2712f52f8747d557509d170c6b42ecbfe552fc...6921227ec8a610abefb8698e66441e037438e442) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 0b2712f5..6921227e 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 0b2712f52f8747d557509d170c6b42ecbfe552fc +Subproject commit 6921227ec8a610abefb8698e66441e037438e442 From f91fa0d0b22417eccf0bd06ef66ae600cbc3ee3d Mon Sep 17 00:00:00 2001 From: Louve <33836535+Rackover@users.noreply.github.com> Date: Wed, 14 Dec 2022 09:40:15 +0100 Subject: [PATCH 52/96] Big zonebuilder update (#427) --- src/Components/Modules/AssetHandler.cpp | 2 +- .../Modules/AssetInterfaces/IFxEffectDef.cpp | 18 +- .../Modules/AssetInterfaces/IFxWorld.cpp | 13 +- .../Modules/AssetInterfaces/IGameWorldMp.cpp | 116 ++ .../Modules/AssetInterfaces/IGameWorldMp.hpp | 1 + .../Modules/AssetInterfaces/IGameWorldSp.cpp | 2 +- .../Modules/AssetInterfaces/IGfxImage.cpp | 4 +- .../Modules/AssetInterfaces/IGfxWorld.cpp | 27 +- .../Modules/AssetInterfaces/ILoadedSound.cpp | 13 +- .../Modules/AssetInterfaces/IMaterial.cpp | 580 ++++++-- .../Modules/AssetInterfaces/IMaterial.hpp | 3 + .../AssetInterfaces/IMaterialPixelShader.cpp | 39 +- .../AssetInterfaces/IMaterialTechniqueSet.cpp | 208 ++- .../AssetInterfaces/IMaterialTechniqueSet.hpp | 4 +- .../IMaterialVertexDeclaration.cpp | 11 +- .../AssetInterfaces/IMaterialVertexShader.cpp | 40 +- .../Modules/AssetInterfaces/IWeapon.cpp | 10 +- .../Modules/AssetInterfaces/IXAnimParts.cpp | 4 +- .../Modules/AssetInterfaces/IXModel.cpp | 178 +-- .../Modules/AssetInterfaces/IXModelSurfs.cpp | 77 +- src/Components/Modules/Maps.cpp | 94 +- src/Components/Modules/Menus.cpp | 15 - src/Components/Modules/Menus.hpp | 2 - src/Components/Modules/Renderer.cpp | 72 +- src/Components/Modules/Renderer.hpp | 4 + src/Components/Modules/ZoneBuilder.cpp | 104 +- src/Components/Modules/ZoneBuilder.hpp | 3 +- src/Components/Modules/Zones.cpp | 4 +- src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 1 + src/Game/Structs.hpp | 1230 ++++++++++++++++- src/Utils/Compression.cpp | 19 +- src/Utils/Entities.cpp | 4 +- src/Utils/Json.cpp | 29 + src/Utils/Json.hpp | 2 + src/Utils/Stream.hpp | 34 + 36 files changed, 2395 insertions(+), 573 deletions(-) diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index d450d50b..94220280 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -257,7 +257,7 @@ namespace Components for (int k = 0; k < (pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount); ++k) { - if (pass->args[k].type == D3DSHADER_PARAM_REGISTER_TYPE::D3DSPR_CONSTINT) + if (pass->args[k].type == Game::MaterialShaderArgumentType::MTL_ARG_LITERAL_PIXEL_CONST) { if (pass->args[k].u.codeConst.index == -28132) { diff --git a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp index 37e2c8db..994a6349 100644 --- a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp +++ b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp @@ -391,7 +391,7 @@ namespace Assets switch (elemType) { - case 7: + case Game::FX_ELEM_TYPE_MODEL: { if (visuals->model) { @@ -401,11 +401,11 @@ namespace Assets break; } - case 8: - case 9: + case Game::FX_ELEM_TYPE_OMNI_LIGHT: + case Game::FX_ELEM_TYPE_SPOT_LIGHT: break; - case 0xA: + case Game::FX_ELEM_TYPE_SOUND: { if (visuals->soundName) { @@ -416,7 +416,7 @@ namespace Assets break; } - case 0xC: + case Game::FX_ELEM_TYPE_RUNNER: { if (visuals->effectDef.handle) { @@ -491,7 +491,7 @@ namespace Assets // Save_FxElemDefVisuals { - if (elemDef->elemType == 11) + if (elemDef->elemType == Game::FX_ELEM_TYPE_DECAL) { if (elemDef->visuals.markArray) { @@ -501,7 +501,7 @@ namespace Assets Game::FxElemMarkVisuals* destMarkArray = buffer->dest(); buffer->saveArray(elemDef->visuals.markArray, elemDef->visualCount); - for (char j = 0; j < elemDef->visualCount; ++j) + for (auto j = 0; j < elemDef->visualCount; ++j) { if (elemDef->visuals.markArray[j].materials[0]) { @@ -563,7 +563,7 @@ namespace Assets { AssertSize(Game::FxElemExtendedDefPtr, 4); - if (elemDef->elemType == 3) + if (elemDef->elemType == Game::FX_ELEM_TYPE_TRAIL) { // Save_FxTrailDef { @@ -597,7 +597,7 @@ namespace Assets } } } - else if (elemDef->elemType == 6) + else if (elemDef->elemType == Game::FX_ELEM_TYPE_SPARK_FOUNTAIN) { if (elemDef->extended.sparkFountainDef) { diff --git a/src/Components/Modules/AssetInterfaces/IFxWorld.cpp b/src/Components/Modules/AssetInterfaces/IFxWorld.cpp index cec5b4dc..6988543f 100644 --- a/src/Components/Modules/AssetInterfaces/IFxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IFxWorld.cpp @@ -186,11 +186,20 @@ namespace Assets } } - void IFxWorld::load(Game::XAssetHeader* /*header*/, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) + void IFxWorld::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { Game::FxWorld* map = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FXWORLD, name.data()).fxWorld; if (map) return; - Components::Logger::Error(Game::ERR_FATAL, "Missing fx_map {}... you can't make them yet you idiot.", name); + // Generate + map = builder->getAllocator()->allocate(); + map->name = builder->getAllocator()->duplicateString(name); + + // No glass for you! + ZeroMemory(&map->glassSys, sizeof(map->glassSys)); + + map->glassSys.firstFreePiece = 0xFFFF; // That's how rust has it (no glass) + + header->fxWorld = map; } } diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp b/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp index 64c53039..1656d480 100644 --- a/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp +++ b/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp @@ -1,6 +1,8 @@ #include #include "IGameWorldMp.hpp" +#define IW4X_GAMEWORLD_VERSION 1 + namespace Assets { void IGameWorldMp::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) @@ -75,4 +77,118 @@ namespace Assets buffer->popBlock(); } + + void IGameWorldMp::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) + { + std::string name = _name; + Utils::String::Replace(name, "maps/mp/", ""); + Utils::String::Replace(name, ".d3dbsp", ""); + + Components::FileSystem::File gameWorld(std::format("gameworld/{}.iw4x.json", name)); + + if (gameWorld.exists()) + { + nlohmann::json gameWorldJson; + + try + { + + gameWorldJson = nlohmann::json::parse(gameWorld.getBuffer()); + } + catch (const std::exception& e) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid JSON for gameworld {}! {}", name, e.what()); + return; + } + + auto* asset = builder->getAllocator()->allocate(); + + if (!gameWorldJson.is_object()) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid GameWorldMp json for {}\n", name); + return; + } + + auto version = gameWorldJson["version"].is_number() ? gameWorldJson["version"].get() : 0; + if (version != IW4X_GAMEWORLD_VERSION) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid GameWorld json version for {}, expected {} and got {}\n", name, IW4X_GAMEWORLD_VERSION, version); + return; + } + + if (!gameWorldJson["name"].is_string()) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Missing gameworld name! on {}\n", name); + return; + } + + asset->name = builder->getAllocator()->duplicateString(gameWorldJson["name"].get()); + auto glassData = builder->getAllocator()->allocate(); + + if (gameWorldJson["glassData"].is_object()) + { + auto jsonGlassData = gameWorldJson["glassData"]; + + try + { + glassData->damageToDestroy = jsonGlassData["damageToDestroy"].get(); + glassData->damageToWeaken = jsonGlassData["damageToWeaken"].get(); + + if (jsonGlassData["glassNames"].is_array()) + { + nlohmann::json::array_t glassNames = jsonGlassData["glassNames"]; + glassData->glassNameCount = glassNames.size(); + glassData->glassNames = builder->getAllocator()->allocateArray(glassData->glassNameCount); + + for (size_t i = 0; i < glassData->glassNameCount; i++) + { + auto jsonGlassName = glassNames[i]; + glassData->glassNames[i].nameStr = builder->getAllocator()->duplicateString(jsonGlassName["nameStr"]); + + glassData->glassNames[i].name = jsonGlassName["name"].get(); + + if (jsonGlassName["piecesIndices"].is_array()) + { + nlohmann::json::array_t jsonPiecesIndices = jsonGlassName["piecesIndices"]; + glassData->glassNames[i].pieceCount = static_cast(jsonPiecesIndices.size()); + + for (size_t j = 0; j < glassData->glassNames[i].pieceCount; j++) + { + glassData->glassNames[i].pieceIndices[j] = jsonPiecesIndices[j].get(); + } + } + } + } + + if (gameWorldJson["glassPieces"].is_array()) + { + nlohmann::json::array_t glassPieces = gameWorldJson["glassPieces"]; + glassData->pieceCount = glassPieces.size(); + glassData->glassPieces = builder->getAllocator()->allocateArray(glassData->pieceCount); + + for (size_t i = 0; i < glassData->pieceCount; i++) + { + glassData->glassPieces[i].collapseTime = glassPieces[i]["collapseTime"].get(); + glassData->glassPieces[i].damageTaken = glassPieces[i]["damageTaken"].get(); + glassData->glassPieces[i].lastStateChangeTime = glassPieces[i]["lastStateChangeTime"].get(); + glassData->glassPieces[i].impactDir = glassPieces[i]["impactDir"].get(); + + nlohmann::json::array_t jsonPos = glassPieces[i]["impactPos"]; + glassData->glassPieces[i].impactPos[0] = jsonPos[0].get(); + glassData->glassPieces[i].impactPos[1] = jsonPos[1].get(); + } + } + } + catch (const nlohmann::json::exception& e) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Malformed GameWorldMp json for {} ({})\n", name, e.what()); + return; + } + } + + asset->g_glassData = glassData; + + header->gameWorldMp = asset; + } + } } diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp b/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp index 243378ef..f19b8d58 100644 --- a/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp +++ b/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp @@ -8,5 +8,6 @@ namespace Assets Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP; } void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; }; } diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp b/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp index 64904c86..0b06b0c2 100644 --- a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp +++ b/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp @@ -187,7 +187,7 @@ namespace Assets for (char j = 0; j < 5; ++j) { - builder->mapScriptString(&(&node->constant.targetname)[j]); + builder->mapScriptString((&node->constant.targetname)[j]); } if (node->constant.Links) diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp index 823876eb..3c7bfee4 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp @@ -18,7 +18,7 @@ namespace Assets } image->name = builder->getAllocator()->duplicateString(name); - image->semantic = 2; + image->semantic = Game::TextureSemantic::TS_COLOR_MAP; const char* tempName = image->name; if (tempName[0] == '*') tempName++; @@ -35,7 +35,7 @@ namespace Assets } image->mapType = reader.read(); - image->semantic = reader.read(); + image->semantic = reader.read(); image->category = reader.read(); int dataLength = reader.read(); diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp index 3a84a800..8548c309 100644 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp @@ -3,6 +3,27 @@ #define IW4X_GFXMAP_VERSION 1 +// The xmodel vehicle_small_hatch_green_destructible_mp causes EXTREME lag +// when placed in the world, for reasons unknown. +// +// Something happens with the SModelSurfIterator which makes it load garbage +// as an XSurface in the middle of otherwise valid surfaces. This bug is very +// easy to reproduce with an empty map and just this car in the middle +// +// As of know we do not know why the iterator corruption occurs or what causes +// it. It doesn't seem linked to the SModel, nor to the materials or techsets, +// nor to the sortkeys, nor to the tilemode, boneinfo, and so on. So for now +// and to make it work for majority of users, we just swap the car. (no, using +// the identical car from iw4's favela_escape doesn't work either!) +// +// Two other models have this problem: ch_apartment_9story_noentry_02 and +// ch_apartment_5story_noentry_01 +// But these exist in mp_vacant in slightly different versions, and can be +// swapped safely by deleting the two .iw4XModel files and requiring mp_vacant +// or a minimal zone containing just these two models. +// +#define SWAP_GREEN_VEHICLE_XMODEL 1 + namespace Assets { void IGfxWorld::loadGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Components::ZoneBuilder::Zone* builder, Utils::Stream::Reader* reader) @@ -47,7 +68,11 @@ namespace Assets if (model->model) { - model->model = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_XMODEL, reader->readString().data(), builder).model; + auto name = reader->readString(); + + model->model = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_XMODEL, name.data(), builder).model; + + assert(model->model); } } } diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp index 45b291a4..d651e99a 100644 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp +++ b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp @@ -120,17 +120,8 @@ namespace Assets if (asset->sound.data) { - if (builder->hasPointer(asset->sound.data)) - { - dest->sound.data = builder->getPointer(asset->sound.data); - } - else - { - builder->storePointer(asset->sound.data); - - buffer->saveArray(asset->sound.data, asset->sound.info.data_len); - Utils::Stream::ClearPointer(&dest->sound.data); - } + buffer->saveArray(asset->sound.data, asset->sound.info.data_len); + Utils::Stream::ClearPointer(&dest->sound.data); } buffer->popBlock(); diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp index e6635b0e..42b63a8e 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -1,15 +1,439 @@ #include #include "IMaterial.hpp" -#define IW4X_MAT_VERSION "1" +#define IW4X_MAT_BIN_VERSION "1" +#define IW4X_MAT_JSON_VERSION 1 namespace Assets { + const std::unordered_map techSetCorrespondance = + { + {"effect", "effect_blend"}, + {"effect", "effect_blend"}, + {"effect_nofog", "effect_blend_nofog"}, + {"effect_zfeather", "effect_zfeather_blend"}, + {"effect_zfeather_falloff", "effect_zfeather_falloff_add"}, + {"effect_zfeather_nofog", "effect_zfeather_add_nofog"}, + + {"wc_unlit_add", "wc_unlit_add_lin"}, + {"wc_unlit_distfalloff", "wc_unlit_distfalloff_replace"}, + {"wc_unlit_multiply", "wc_unlit_multiply_lin"}, + {"wc_unlit_falloff_add", "wc_unlit_falloff_add_lin"}, + {"wc_unlit", "wc_unlit_replace_lin"}, + {"wc_unlit_alphatest", "wc_unlit_blend_lin"}, + {"wc_unlit_blend", "wc_unlit_blend_lin"}, + {"wc_unlit_replace", "wc_unlit_replace_lin"}, + {"wc_unlit_nofog", "wc_unlit_replace_lin_nofog_nocast" }, + + {"mc_unlit_replace", "mc_unlit_replace_lin"}, + {"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"}, + {"mc_unlit", "mc_unlit_replace_lin_nocast"}, + {"mc_unlit_alphatest", "mc_unlit_blend_lin"}, + {"mc_effect_nofog", "mc_effect_blend_nofog"}, + {"mc_effect_falloff_add_nofog", "mc_effect_falloff_add_nofog_eyeoffset"}, + }; + void IMaterial::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - if (!header->data) this->loadJson(header, name, builder); // Check if we want to override materials + if (!header->data) this->loadJson(header, name, builder); // Check if we want to load a material from disk + if (!header->data) this->loadBinary(header, name, builder); // Check if we want to load a material from disk (binary format) if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game + } + + + void IMaterial::loadJson(Game::XAssetHeader* header, const std::string& name, [[maybe_unused]] Components::ZoneBuilder::Zone* builder) + { + Components::FileSystem::File materialInfo(std::format("materials/{}.iw4x.json", name)); + + if (!materialInfo.exists()) return; + + Game::Material* asset = builder->getAllocator()->allocate(); + + + nlohmann::json materialJson; + try + { + materialJson = nlohmann::json::parse(materialInfo.getBuffer()); + } + catch (const std::exception& e) + { + Components::Logger::Print("Invalid material json for {} (broken json {})\n", name, e.what()); + } + + if (!materialJson.is_object()) + { + Components::Logger::Print("Invalid material json for {} (Is it zonebuilder format?)\n", name); + return; + } + + if (materialJson["version"].get() != IW4X_MAT_JSON_VERSION) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid material json version for {}, expected {} and got {}\n", name, IW4X_MAT_JSON_VERSION, materialJson["version"].get()); + return; + } + + try + { + asset->info.name = builder->getAllocator()->duplicateString(materialJson["name"].get()); + asset->info.gameFlags = static_cast(Utils::Json::ReadFlags(materialJson["gameFlags"].get(), sizeof(char))); + + asset->info.sortKey = materialJson["sortKey"].get(); + // * We do techset later * // + asset->info.textureAtlasRowCount = materialJson["textureAtlasRowCount"].get(); + asset->info.textureAtlasColumnCount = materialJson["textureAtlasColumnCount"].get(); + asset->info.surfaceTypeBits = static_cast(Utils::Json::ReadFlags(materialJson["surfaceTypeBits"].get(), sizeof(int))); + asset->info.hashIndex = materialJson["hashIndex"].get(); + asset->cameraRegion = materialJson["cameraRegion"].get(); + } + catch (const nlohmann::json::exception& e) + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid material json for {} (broken json {})\n", name, e.what()); + return; + } + + if (materialJson["gfxDrawSurface"].is_object()) + { + asset->info.drawSurf.fields.customIndex = materialJson["gfxDrawSurface"]["customIndex"].get(); + asset->info.drawSurf.fields.hasGfxEntIndex = materialJson["gfxDrawSurface"]["hasGfxEntIndex"].get(); + asset->info.drawSurf.fields.materialSortedIndex = materialJson["gfxDrawSurface"]["materialSortedIndex"].get(); + asset->info.drawSurf.fields.objectId = materialJson["gfxDrawSurface"]["objectId"].get(); + asset->info.drawSurf.fields.prepass = materialJson["gfxDrawSurface"]["prepass"].get(); + asset->info.drawSurf.fields.primarySortKey = materialJson["gfxDrawSurface"]["primarySortKey"].get(); + asset->info.drawSurf.fields.reflectionProbeIndex = materialJson["gfxDrawSurface"]["reflectionProbeIndex"].get(); + asset->info.drawSurf.fields.sceneLightIndex = materialJson["gfxDrawSurface"]["sceneLightIndex"].get(); + asset->info.drawSurf.fields.surfType = materialJson["gfxDrawSurface"]["surfType"].get(); + asset->info.drawSurf.fields.unused = materialJson["gfxDrawSurface"]["unused"].get(); + asset->info.drawSurf.fields.useHeroLighting = materialJson["gfxDrawSurface"]["useHeroLighting"].get(); + } + + asset->stateFlags = static_cast(Utils::Json::ReadFlags(materialJson["stateFlags"].get(), sizeof(char))); + + if (materialJson["textureTable"].is_array()) + { + nlohmann::json::array_t textureTable = materialJson["textureTable"]; + asset->textureCount = static_cast(textureTable.size()); + asset->textureTable = builder->getAllocator()->allocateArray(asset->textureCount); + + for (size_t i = 0; i < textureTable.size(); i++) + { + auto& textureJson = textureTable[i]; + if (textureJson.is_object()) + { + Game::MaterialTextureDef* textureDef = &asset->textureTable[i]; + textureDef->semantic = textureJson["semantic"].get(); + textureDef->samplerState = textureJson["samplerState"].get(); + textureDef->nameStart = textureJson["nameStart"].get(); + textureDef->nameEnd = textureJson["nameEnd"].get(); + textureDef->nameHash = textureJson["nameHash"].get(); + + if (textureDef->semantic == Game::TextureSemantic::TS_WATER_MAP) + { + Game::water_t* water = builder->getAllocator()->allocate(); + + if (textureJson["water"].is_object()) + { + auto& waterJson = textureJson["water"]; + + if (waterJson["image"].is_string()) + { + auto imageName = waterJson["image"].get(); + + water->image = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_IMAGE, imageName.data(), builder).image; + } + + water->amplitude = waterJson["amplitude"].get(); + water->M = waterJson["M"].get(); + water->N = waterJson["N"].get(); + water->Lx = waterJson["Lx"].get(); + water->Lz = waterJson["Lz"].get(); + water->gravity = waterJson["gravity"].get(); + water->windvel = waterJson["windvel"].get(); + + auto winddir = waterJson["winddir"].get>(); + if (winddir.size() == 2) + { + std::copy(winddir.begin(), winddir.end(), water->winddir); + } + + auto codeConstant = waterJson["codeConstant"].get>(); + + if (codeConstant.size() == 4) + { + std::copy(codeConstant.begin(), codeConstant.end(), water->codeConstant); + } + + /// H0 + [[maybe_unused]] auto idealSize = water->M * water->N * sizeof(Game::complex_s); + auto h064 = waterJson["H0"].get(); + auto predictedSize = static_cast(std::ceilf((h064.size() / 4.f) * 3.f)); + assert(predictedSize >= idealSize); + + auto h0 = reinterpret_cast(builder->getAllocator()->allocate(predictedSize)); + + [[maybe_unused]] auto h0Result = base64_decode( + h064.data(), + h064.size(), + reinterpret_cast(h0), + &predictedSize + ); + + assert(h0Result == CRYPT_OK); + water->H0 = h0; + + /// WTerm + auto wTerm64 = waterJson["wTerm"].get(); + auto predictedWTermSize = static_cast(std::ceilf((wTerm64.size() / 4.f) * 3.f)); + + auto wTerm = reinterpret_cast(builder->getAllocator()->allocate(predictedWTermSize)); + + [[maybe_unused]] auto wTermResult = base64_decode( + wTerm64.data(), + wTerm64.size(), + reinterpret_cast(wTerm), + &predictedWTermSize + ); + + assert(wTermResult == CRYPT_OK); + water->wTerm = wTerm; + } + + textureDef->u.water = water; + } + else + { + textureDef->u.image = nullptr; + if (textureJson["image"].is_string()) + { + textureDef->u.image = Components::AssetHandler::FindAssetForZone + ( + Game::XAssetType::ASSET_TYPE_IMAGE, + textureJson["image"].get(), + builder + ).image; + } + } + } + } + } + + // Statebits + if (materialJson["stateBitsEntry"].is_array()) + { + nlohmann::json::array_t stateBitsEntry = materialJson["stateBitsEntry"]; + + for (size_t i = 0; i < std::min(stateBitsEntry.size(), 48u); i++) + { + asset->stateBitsEntry[i] = stateBitsEntry[i].get(); + } + } + + if (materialJson["stateBitsTable"].is_array()) + { + nlohmann::json::array_t array = materialJson["stateBitsTable"]; + asset->stateBitsCount = static_cast(array.size()); + + asset->stateBitsTable = builder->getAllocator()->allocateArray(array.size()); + + size_t statebitTableIndex = 0; + for (auto& jsonStateBitEntry : array) + { + auto stateBit = &asset->stateBitsTable[statebitTableIndex++]; + + unsigned int loadbits0 = 0; + unsigned int loadbits1 = 0; + +#define READ_INT_LB_FROM_JSON(x) unsigned int x = jsonStateBitEntry[#x].get() +#define READ_BOOL_LB_FROM_JSON(x) bool x = jsonStateBitEntry[#x].get() + + READ_INT_LB_FROM_JSON(srcBlendRgb); + READ_INT_LB_FROM_JSON(dstBlendRgb); + READ_INT_LB_FROM_JSON(blendOpRgb); + READ_INT_LB_FROM_JSON(srcBlendAlpha); + READ_INT_LB_FROM_JSON(dstBlendAlpha); + READ_INT_LB_FROM_JSON(blendOpAlpha); + READ_INT_LB_FROM_JSON(depthTest); + READ_INT_LB_FROM_JSON(polygonOffset); + + const auto alphaTest = jsonStateBitEntry["alphaTest"].get(); + const auto cullFace = jsonStateBitEntry["cullFace"].get(); + + READ_BOOL_LB_FROM_JSON(colorWriteRgb); + READ_BOOL_LB_FROM_JSON(colorWriteAlpha); + READ_BOOL_LB_FROM_JSON(polymodeLine); + + READ_BOOL_LB_FROM_JSON(gammaWrite); + READ_BOOL_LB_FROM_JSON(depthWrite); + READ_BOOL_LB_FROM_JSON(stencilFrontEnabled); + READ_BOOL_LB_FROM_JSON(stencilBackEnabled); + + READ_INT_LB_FROM_JSON(stencilFrontPass); + READ_INT_LB_FROM_JSON(stencilFrontFail); + READ_INT_LB_FROM_JSON(stencilFrontZFail); + READ_INT_LB_FROM_JSON(stencilFrontFunc); + READ_INT_LB_FROM_JSON(stencilBackPass); + READ_INT_LB_FROM_JSON(stencilBackFail); + READ_INT_LB_FROM_JSON(stencilBackZFail); + READ_INT_LB_FROM_JSON(stencilBackFunc); + + loadbits0 |= srcBlendRgb << Game::GFXS0_SRCBLEND_RGB_SHIFT; + loadbits0 |= dstBlendRgb << Game::GFXS0_DSTBLEND_RGB_SHIFT; + loadbits0 |= blendOpRgb << Game::GFXS0_BLENDOP_RGB_SHIFT; + loadbits0 |= srcBlendAlpha << Game::GFXS0_SRCBLEND_ALPHA_SHIFT; + loadbits0 |= dstBlendAlpha << Game::GFXS0_DSTBLEND_ALPHA_SHIFT; + loadbits0 |= blendOpAlpha << Game::GFXS0_BLENDOP_ALPHA_SHIFT; + + if (depthTest == -1) + { + loadbits1 |= Game::GFXS1_DEPTHTEST_DISABLE; + } + else + { + loadbits1 |= depthTest << Game::GFXS1_DEPTHTEST_SHIFT; + } + + loadbits1 |= polygonOffset << Game::GFXS1_POLYGON_OFFSET_SHIFT; + + if (alphaTest == "disable") + { + loadbits0 |= Game::GFXS0_ATEST_DISABLE; + } + else if (alphaTest == ">0") + { + loadbits0 |= Game::GFXS0_ATEST_GT_0; + } + else if (alphaTest == "<128") + { + loadbits0 |= Game::GFXS0_ATEST_LT_128; + } + else if (alphaTest == ">=128") + { + loadbits0 |= Game::GFXS0_ATEST_GE_128; + } + else + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid alphatest loadbit0 '{}' in material {}\n", alphaTest, name); + return; + } + + if (cullFace == "none") + { + loadbits0 |= Game::GFXS0_CULL_NONE; + } + else if (cullFace == "back") + { + loadbits0 |= Game::GFXS0_CULL_BACK; + } + else if (cullFace == "front") + { + loadbits0 |= Game::GFXS0_CULL_FRONT; + } + else + { + Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid cullFace loadbit0 '{}' in material {}\n", cullFace, name); + return; + } + + if (gammaWrite) + { + loadbits0 |= Game::GFXS0_GAMMAWRITE; + } + + if (colorWriteAlpha) + { + loadbits0 |= Game::GFXS0_COLORWRITE_ALPHA; + } + + if (colorWriteRgb) + { + loadbits0 |= Game::GFXS0_COLORWRITE_RGB; + } + + if (polymodeLine) + { + loadbits0 |= Game::GFXS0_POLYMODE_LINE; + } + + if (depthWrite) + { + loadbits1 |= Game::GFXS1_DEPTHWRITE; + } + if (stencilFrontEnabled) + { + loadbits1 |= Game::GFXS1_STENCIL_FRONT_ENABLE; + } + if (stencilBackEnabled) + { + loadbits1 |= Game::GFXS1_STENCIL_BACK_ENABLE; + } + + loadbits1 |= stencilFrontPass << Game::GFXS1_STENCIL_FRONT_PASS_SHIFT; + loadbits1 |= stencilFrontFail << Game::GFXS1_STENCIL_FRONT_FAIL_SHIFT; + loadbits1 |= stencilFrontZFail << Game::GFXS1_STENCIL_FRONT_ZFAIL_SHIFT; + loadbits1 |= stencilFrontFunc << Game::GFXS1_STENCIL_FRONT_FUNC_SHIFT; + loadbits1 |= stencilBackPass << Game::GFXS1_STENCIL_BACK_PASS_SHIFT; + loadbits1 |= stencilBackFail << Game::GFXS1_STENCIL_BACK_FAIL_SHIFT; + loadbits1 |= stencilBackZFail << Game::GFXS1_STENCIL_BACK_ZFAIL_SHIFT; + loadbits1 |= stencilBackFunc << Game::GFXS1_STENCIL_BACK_FUNC_SHIFT; + + stateBit->loadBits[0] = loadbits0; + stateBit->loadBits[1] = loadbits1; + } + + // Constant table + if (materialJson["constantTable"].is_array()) + { + + nlohmann::json::array_t constants = materialJson["constantTable"]; + asset->constantCount = static_cast(constants.size()); + auto table = builder->getAllocator()->allocateArray(asset->constantCount); + + for (size_t constantIndex = 0; constantIndex < asset->constantCount; constantIndex++) + { + auto& constant = constants[constantIndex]; + auto entry = &table[constantIndex]; + + auto litVec = constant["literal"].get>(); + std::copy(litVec.begin(), litVec.end(), entry->literal); + + auto constantName = constant["name"].get(); + std::copy(constantName.begin(), constantName.end(), entry->name); + + entry->nameHash = constant["nameHash"].get(); + } + + asset->constantTable = table; + } + + if (materialJson["techniqueSet"].is_string()) + { + const std::string techsetName = materialJson["techniqueSet"].get(); + asset->techniqueSet = findWorkingTechset(techsetName, asset, builder); + + if (asset->techniqueSet == nullptr) + { + assert(false); + } + } + + header->material = asset; + } + } + + Game::MaterialTechniqueSet* IMaterial::findWorkingTechset(std::string techsetName, [[maybe_unused]] Game::Material* material, Components::ZoneBuilder::Zone* builder) const + { + Game::MaterialTechniqueSet* techset; + + // Pass 1: Identical techset (1:1) + techset = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, techsetName.data(), builder).techniqueSet; + if (techset != nullptr) + { + return techset; + } + + // We do no more cause we use CoD4 techset and they should always be present + // If one day we want to go back to mw2 fallback we can add extra steps here! + + return nullptr; } void IMaterial::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) @@ -30,29 +454,6 @@ namespace Assets "_add_lin_nofog", }; - static std::unordered_map techSetCorrespondance = - { - {"effect", "effect_blend"}, - {"effect", "effect_blend"}, - {"effect_nofog", "effect_blend_nofog"}, - {"effect_zfeather", "effect_zfeather_blend"}, - - {"wc_unlit_add", "wc_unlit_add_lin"}, - {"wc_unlit_distfalloff", "wc_unlit_distfalloff_replace"}, - {"wc_unlit_multiply", "wc_unlit_multiply_lin"}, - {"wc_unlit_falloff_add", "wc_unlit_falloff_add_lin_ua"}, - {"wc_unlit", "wc_unlit_replace_lin"}, - {"wc_unlit_alphatest", "wc_unlit_blend_lin"}, - {"wc_unlit_blend", "wc_unlit_blend_lin_ua"}, - {"wc_unlit_replace", "wc_unlit_replace_lin"}, - {"wc_unlit_nofog", "wc_unlit_replace_lin_nofog_nocast" }, - - {"mc_unlit_replace", "mc_unlit_replace_lin"}, - {"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"}, - {"mc_unlit", "mc_unlit_replace_lin_nocast"}, - {"mc_unlit_alphatest", "mc_unlit_blend_lin"} - }; - Components::FileSystem::File materialFile(std::format("materials/{}.iw4xMaterial", name)); if (!materialFile.exists()) return; @@ -66,9 +467,9 @@ namespace Assets std::string version; version.push_back(reader.read()); - if (version != IW4X_MAT_VERSION) + if (version != IW4X_MAT_BIN_VERSION) { - Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, expected version is {}, but it was {}!", name, IW4X_MAT_VERSION, version); + Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, expected version is {}, but it was {}!", name, IW4X_MAT_BIN_VERSION, version); } auto* asset = reader.readObject(); @@ -127,7 +528,7 @@ namespace Assets { Game::MaterialTextureDef* textureDef = &asset->textureTable[i]; - if (textureDef->semantic == SEMANTIC_WATER_MAP) + if (textureDef->semantic == Game::TextureSemantic::TS_WATER_MAP) { if (textureDef->u.water) { @@ -175,29 +576,29 @@ namespace Assets // Find correct sortkey by comparing techsets Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset](Game::XAssetEntry* entry) - { - if (!replacementFound) { - Game::XAssetHeader header = entry->asset.header; - - const char* name = asset->techniqueSet->name; - if (name[0] == ',') ++name; - - if (std::string(name) == header.material->techniqueSet->name) + if (!replacementFound) { - asset->info.sortKey = header.material->info.sortKey; + Game::XAssetHeader header = entry->asset.header; - // This is temp, as nobody has time to fix materials - asset->stateBitsCount = header.material->stateBitsCount; - asset->stateBitsTable = header.material->stateBitsTable; - std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, 48); - asset->constantCount = header.material->constantCount; - asset->constantTable = header.material->constantTable; - Components::Logger::Print("For {}, copied constants & statebits from {}\n", asset->info.name, header.material->info.name); - replacementFound = true; + const char* name = asset->techniqueSet->name; + if (name[0] == ',') ++name; + + if (std::string(name) == header.material->techniqueSet->name) + { + asset->info.sortKey = header.material->info.sortKey; + + // This is temp, as nobody has time to fix materials + asset->stateBitsCount = header.material->stateBitsCount; + asset->stateBitsTable = header.material->stateBitsTable; + std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, ARRAYSIZE(asset->stateBitsEntry)); + asset->constantCount = header.material->constantCount; + asset->constantTable = header.material->constantTable; + Components::Logger::Print("For {}, copied constants & statebits from {}\n", asset->info.name, header.material->info.name); + replacementFound = true; + } } - } - }, false); + }, false); if (!replacementFound) { @@ -222,70 +623,72 @@ namespace Assets Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, techsetMatches](Game::XAssetEntry* entry) - { - if (!replacementFound) { - Game::XAssetHeader header = entry->asset.header; - - if (techsetMatches(header.material, asset)) + if (!replacementFound) { - Components::Logger::Print("Material {} with techset {} has been mapped to {}\n", asset->info.name, asset->techniqueSet->name, header.material->techniqueSet->name); - asset->info.sortKey = header.material->info.sortKey; - replacementFound = true; + Game::XAssetHeader header = entry->asset.header; + + if (techsetMatches(header.material, asset)) + { + Components::Logger::Print("Material {} with techset {} has been mapped to {}\n", asset->info.name, asset->techniqueSet->name, header.material->techniqueSet->name); + asset->info.sortKey = header.material->info.sortKey; + replacementFound = true; + } } - } - }, false); + }, false); } if (!replacementFound && asset->techniqueSet) { Components::Logger::Print("No replacement found for material {} with techset {}\n", asset->info.name, asset->techniqueSet->name); std::string techName = asset->techniqueSet->name; - if (techSetCorrespondance.contains(techName)) + if (const auto itr = techSetCorrespondance.find(techName); itr != techSetCorrespondance.end()) { - auto iw4TechSetName = techSetCorrespondance[techName]; - Game::XAssetEntry* iw4TechSet = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, iw4TechSetName.data()); + auto& iw4TechSetName = itr->second; + auto* iw4TechSet = Game::DB_FindXAssetEntry(Game::ASSET_TYPE_TECHNIQUE_SET, iw4TechSetName.data()); - if (iw4TechSet) + if (iw4TechSet) { Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, iw4TechSet](Game::XAssetEntry* entry) - { - if (!replacementFound) { - Game::XAssetHeader header = entry->asset.header; - - if (header.material->techniqueSet == iw4TechSet->asset.header.techniqueSet - && std::string(header.material->info.name).find("icon") == std::string::npos) // Yeah this has a tendency to fuck up a LOT of transparent materials + if (!replacementFound) { + Game::XAssetHeader header = entry->asset.header; Components::Logger::Print("Material {} with techset {} has been mapped to {} (last chance!), taking the sort key of material {}\n", asset->info.name, asset->techniqueSet->name, header.material->techniqueSet->name, header.material->info.name); - asset->info.sortKey = header.material->info.sortKey; - asset->techniqueSet = iw4TechSet->asset.header.techniqueSet; + // Yeah this has a tendency to fuck up a LOT of transparent materials + if (header.material->techniqueSet == iw4TechSet->asset.header.techniqueSet && std::string(header.material->info.name).find("icon") != std::string::npos) + { + Components::Logger::Print("Material {} with techset {} has been mapped to {} (last chance!), taking the sort key of material {}\n", + asset->info.name, asset->techniqueSet->name, header.material->techniqueSet->name, header.material->info.name); - // this is terrible! - asset->stateBitsCount = header.material->stateBitsCount; - asset->stateBitsTable = header.material->stateBitsTable; - std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, 48); - asset->constantCount = header.material->constantCount; - asset->constantTable = header.material->constantTable; + asset->info.sortKey = header.material->info.sortKey; + asset->techniqueSet = iw4TechSet->asset.header.techniqueSet; - replacementFound = true; + // this is terrible! + asset->stateBitsCount = header.material->stateBitsCount; + asset->stateBitsTable = header.material->stateBitsTable; + std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, 48); + asset->constantCount = header.material->constantCount; + asset->constantTable = header.material->constantTable; + + replacementFound = true; + } } - } - }, false); + }, false); - if (!replacementFound) + if (!replacementFound) { Components::Logger::Print("Could not find any loaded material with techset {} (in replacement of {}), so I cannot set the sortkey for material {}\n", iw4TechSetName, asset->techniqueSet->name, asset->info.name); } } - else + else { Components::Logger::Print("Could not find any loaded techset with iw4 name {} for iw3 techset {}\n", iw4TechSetName, asset->techniqueSet->name); } } - else + else { Components::Logger::Print("Could not match iw3 techset {} with any of the techsets I know! This is a critical error, there's a good chance the map will not be playable.\n", techName); } @@ -327,15 +730,6 @@ namespace Assets header->material = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).material; } - void IMaterial::loadJson(Game::XAssetHeader* header, const std::string& name, [[maybe_unused]] Components::ZoneBuilder::Zone* builder) - { - Components::FileSystem::File materialInfo(std::format("materials/{}.json", name)); - - if (!materialInfo.exists()) return; - - header->material = nullptr; - } - void IMaterial::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { Game::Material* asset = header.material; @@ -351,7 +745,7 @@ namespace Assets { if (asset->textureTable[i].u.image) { - if (asset->textureTable[i].semantic == SEMANTIC_WATER_MAP) + if (asset->textureTable[i].semantic == Game::TextureSemantic::TS_WATER_MAP) { if (asset->textureTable[i].u.water->image) { @@ -411,7 +805,7 @@ namespace Assets auto* destTextureDef = &destTextureTable[i]; auto* textureDef = &asset->textureTable[i]; - if (textureDef->semantic == SEMANTIC_WATER_MAP) + if (textureDef->semantic == Game::TextureSemantic::TS_WATER_MAP) { AssertSize(Game::water_t, 68); diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.hpp b/src/Components/Modules/AssetInterfaces/IMaterial.hpp index 54c10449..2aa645b7 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.hpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.hpp @@ -13,5 +13,8 @@ namespace Assets void loadJson(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); + + private: + Game::MaterialTechniqueSet* findWorkingTechset(const std::string techsetName, Game::Material* material, Components::ZoneBuilder::Zone* builder) const; }; } diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp index 47c24cdd..7c3737e4 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp @@ -1,15 +1,15 @@ #include #include "IMaterialPixelShader.hpp" -#define IW4X_TECHSET_VERSION "0" +#define GFX_RENDERER_SHADER_SM3 0 namespace Assets { void IMaterialPixelShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game + if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one } void IMaterialPixelShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) @@ -19,36 +19,19 @@ namespace Assets void IMaterialPixelShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File psFile(std::format("ps/{}.iw4xPS", name)); + Components::FileSystem::File psFile(std::format("ps/{}.cso", name)); if (!psFile.exists()) return; - Utils::Stream::Reader reader(builder->getAllocator(), psFile.getBuffer()); + auto buff = psFile.getBuffer(); + auto programSize = buff.size() / 4; + Game::MaterialPixelShader* asset = builder->getAllocator()->allocate(); - char* magic = reader.readArray(8); - if (std::memcmp(magic, "IW4xPIXL", 8)) - { - Components::Logger::Error(Game::ERR_FATAL, "Reading pixel shader '{}' failed, header is invalid!", name); - } + asset->name = builder->getAllocator()->duplicateString(name); + asset->prog.loadDef.loadForRenderer = GFX_RENDERER_SHADER_SM3; + asset->prog.loadDef.programSize = static_cast(programSize); + asset->prog.loadDef.program = builder->getAllocator()->allocateArray(programSize); + memcpy_s(asset->prog.loadDef.program, buff.size(), buff.data(), buff.size()); - std::string version; - version.push_back(reader.read()); - if (version != IW4X_TECHSET_VERSION) - { - Components::Logger::Error(Game::ERR_FATAL, - "Reading pixel shader '{}' failed, expected version is {}, but it was {}!", name, IW4X_TECHSET_VERSION, version); - } - - Game::MaterialPixelShader* asset = reader.readObject(); - - if (asset->name) - { - asset->name = reader.readCString(); - } - - if (asset->prog.loadDef.program) - { - asset->prog.loadDef.program = reader.readArray(asset->prog.loadDef.programSize); - } header->pixelShader = asset; } diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp index cf713cea..839c3fb0 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp @@ -1,14 +1,14 @@ #include #include "IMaterialTechniqueSet.hpp" -#define IW4X_TECHSET_VERSION "0" +#define IW4X_TECHSET_VERSION 1 namespace Assets { void IMaterialTechniqueSet::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { + if (!header->data) this->loadFromDisk(header, name, builder); // Check if we need to import a new one into the game if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game } void IMaterialTechniqueSet::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) @@ -16,132 +16,202 @@ namespace Assets header->techniqueSet = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).techniqueSet; } - void IMaterialTechniqueSet::loadBinaryTechnique(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder) + void IMaterialTechniqueSet::loadTechniqueFromDisk(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder) { AssertSize(Game::MaterialPass, 20); - Components::FileSystem::File techFile(std::format("techniques/{}.iw4xTech", name)); - if (!techFile.exists()) { + Components::FileSystem::File techFile(std::format("techniques/{}.iw4x.json", name)); + if (!techFile.exists()) + { *tech = nullptr; + Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Missing technique '{}'\n", name); return; } - Utils::Stream::Reader reader(builder->getAllocator(), techFile.getBuffer()); + nlohmann::json technique; - char* magic = reader.readArray(8); - if (std::memcmp(magic, "IW4xTECH", 8)) + try { - Components::Logger::Error(Game::ERR_FATAL, "Reading technique '{}' failed, header is invalid!", name); + technique = nlohmann::json::parse(techFile.getBuffer()); + } + catch (std::exception& e) + { + Components::Logger::Error(Game::ERR_FATAL, "Reading techset '{}' failed, file is messed up! {}", name, e.what()); } - std::string version; - version.push_back(reader.read()); + int version = technique["version"].get(); + if (version != IW4X_TECHSET_VERSION) { Components::Logger::Error(Game::ERR_FATAL, - "Reading technique '{}' failed, expected version is {}, but it was {}!", name, IW4X_TECHSET_VERSION, version.data()); + "Reading technique '{}' failed, expected version is {}, but it was {}!", name, IW4X_TECHSET_VERSION, version); } - unsigned short flags = reader.read(); - unsigned short passCount = reader.read(); + unsigned short flags = static_cast(Utils::Json::ReadFlags(technique["flags"].get(), sizeof(short))); - Game::MaterialTechnique* asset = (Game::MaterialTechnique*)builder->getAllocator()->allocateArray(sizeof(Game::MaterialTechnique) + (sizeof(Game::MaterialPass) * (passCount - 1))); + if (technique["passArray"].is_array()) + { + nlohmann::json::array_t passArray = technique["passArray"]; - asset->name = builder->getAllocator()->duplicateString(name); - asset->flags = flags; - asset->passCount = passCount; + Game::MaterialTechnique* asset = (Game::MaterialTechnique*)builder->getAllocator()->allocateArray(sizeof(Game::MaterialTechnique) + (sizeof(Game::MaterialPass) * (passArray.size() - 1))); - Game::MaterialPass* passes = reader.readArray(passCount); - std::memcpy(asset->passArray, passes, sizeof(Game::MaterialPass) * passCount); + asset->name = builder->getAllocator()->duplicateString(name); + asset->flags = flags; + asset->passCount = static_cast(passArray.size()); - for (unsigned short i = 0; i < asset->passCount; i++) - { - Game::MaterialPass* pass = &asset->passArray[i]; + Game::MaterialPass* passes = builder->getAllocator()->allocateArray(asset->passCount); + std::memcpy(asset->passArray, passes, sizeof(Game::MaterialPass) * asset->passCount); - if (pass->vertexDecl) + for (unsigned short i = 0; i < asset->passCount; i++) { - const char* declName = reader.readCString(); - pass->vertexDecl = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXDECL, declName, builder).vertexDecl; - } + Game::MaterialPass* pass = &asset->passArray[i]; + auto jsonPass = passArray[i]; - if (pass->vertexShader) - { - const char* vsName = reader.readCString(); - pass->vertexShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, vsName, builder).vertexShader; - - } - - if (pass->pixelShader) - { - const char* psName = reader.readCString(); - pass->pixelShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_PIXELSHADER, psName, builder).pixelShader; - } - - pass->args = reader.readArray(pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount); - - for (int j = 0; j < pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount; j++) - { - if (pass->args[j].type == 1 || pass->args[j].type == 7) + if (jsonPass["vertexDeclaration"].is_string()) { - pass->args[j].u.literalConst = reader.readArray(4); + auto declName = jsonPass["vertexDeclaration"].get(); + pass->vertexDecl = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXDECL, declName, builder).vertexDecl; } - if (pass->args[j].type == 3 || pass->args[j].type == 5) + if (jsonPass["vertexShader"].is_string()) { - pass->args[j].u.codeConst.index = *reader.readObject(); - pass->args[j].u.codeConst.firstRow = *reader.readObject(); - pass->args[j].u.codeConst.rowCount = *reader.readObject(); + auto vsName = jsonPass["vertexShader"].get(); + pass->vertexShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, vsName, builder).vertexShader; + } + + if (jsonPass["pixelShader"].is_string()) + { + auto psName = jsonPass["pixelShader"].get(); + pass->pixelShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_PIXELSHADER, psName, builder).pixelShader; + } + + pass->perPrimArgCount = jsonPass["perPrimArgCount"].get(); + pass->perObjArgCount = jsonPass["perObjArgCount"].get(); + pass->stableArgCount = jsonPass["stableArgCount"].get(); + pass->customSamplerFlags = jsonPass["customSamplerFlags"].get(); + + + if (jsonPass["arguments"].is_array()) + { + nlohmann::json::array_t jsonAguments = jsonPass["arguments"]; + + pass->args = builder->getAllocator()->allocateArray(jsonAguments.size()); + + for (size_t j = 0; j < jsonAguments.size(); j++) + { + auto jsonArgument = jsonAguments[j]; + Game::MaterialShaderArgument* argument = &pass->args[j]; + + argument->type = jsonArgument["type"].get(); + argument->dest = jsonArgument["dest"].get(); + + if (argument->type == Game::MaterialShaderArgumentType::MTL_ARG_LITERAL_VERTEX_CONST || + argument->type == Game::MaterialShaderArgumentType::MTL_ARG_LITERAL_PIXEL_CONST) + { + argument->u.literalConst = builder->getAllocator()->allocateArray(4); + + auto literals = jsonArgument["literals"].get>(); + std::copy(literals.begin(), literals.end(), argument->u.literalConst); + } + else if (argument->type == Game::MaterialShaderArgumentType::MTL_ARG_CODE_VERTEX_CONST || + argument->type == Game::MaterialShaderArgumentType::MTL_ARG_CODE_PIXEL_CONST) + { + if (jsonArgument["codeConst"].is_object()) + { + auto codeConst = jsonArgument["codeConst"]; + + argument->u.codeConst.index = codeConst["index"].get(); + argument->u.codeConst.firstRow = codeConst["firstRow"].get(); + argument->u.codeConst.rowCount = codeConst["rowCount"].get(); + } + } + else if (argument->type == Game::MaterialShaderArgumentType::MTL_ARG_MATERIAL_PIXEL_SAMPLER || + argument->type == Game::MaterialShaderArgumentType::MTL_ARG_MATERIAL_VERTEX_CONST || + argument->type == Game::MaterialShaderArgumentType::MTL_ARG_MATERIAL_PIXEL_CONST) + { + argument->u.nameHash = jsonArgument["nameHash"].get(); + } + else if (argument->type == Game::MaterialShaderArgumentType::MTL_ARG_CODE_PIXEL_SAMPLER) + { + argument->u.codeSampler = jsonArgument["codeSampler"].get(); + } + } } } + + *tech = asset; } - - *tech = asset; } - void IMaterialTechniqueSet::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) + void IMaterialTechniqueSet::loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File tsFile(std::format("techsets/{}.iw4xTS", name)); + Components::FileSystem::File tsFile(std::format("techsets/{}.iw4x.json", name)); if (!tsFile.exists()) return; - Utils::Stream::Reader reader(builder->getAllocator(), tsFile.getBuffer()); + nlohmann::json techset; - char* magic = reader.readArray(8); - if (std::memcmp(magic, "IW4xTSET", 8)) + try { - Components::Logger::Error(Game::ERR_FATAL, "Reading techset '{}' failed, header is invalid!", name); + techset = nlohmann::json::parse(tsFile.getBuffer()); + } + catch (std::exception& e) + { + Components::Logger::Error(Game::ERR_FATAL, "Reading techset '{}' failed, file is messed up! {}", name, e.what()); } - std::string version; - version.push_back(reader.read()); + auto version = techset["version"].get(); if (version != IW4X_TECHSET_VERSION) { Components::Logger::Error(Game::ERR_FATAL, "Reading techset '{}' failed, expected version is {}, but it was {}!", name, IW4X_TECHSET_VERSION, version); } - Game::MaterialTechniqueSet* asset = reader.readObject(); + Game::MaterialTechniqueSet* asset = builder->getAllocator()->allocate(); - if (asset->name) + if (asset == nullptr) { - asset->name = reader.readCString(); + Components::Logger::Error(Game::ERR_FATAL, "Reading techset '{}' failed, allocation failed!", name); + return; } - for (int i = 0; i < 48; i++) + if (techset["name"].is_string()) { - if (asset->techniques[i]) + asset->name = builder->getAllocator()->duplicateString(techset["name"].get()); + } + + asset->hasBeenUploaded = techset["hasBeenUploaded"].get(); + asset->worldVertFormat = techset["worldVertFormat"].get(); + + + if (techset["remappedTechniqueSet"].is_string()) + { + auto remapped = techset["remappedTechniqueSet"].get(); + + if (remapped != asset->name) { - const char* techName = reader.readCString(); - this->loadBinaryTechnique(&asset->techniques[i], techName, builder); + builder->loadAssetByName(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, remapped, false); } } + if (techset["techniques"].is_object()) + { + for (int i = 0; i < Game::TECHNIQUE_COUNT; i++) + { + auto technique = techset["techniques"].at(std::to_string(i)); + + if (technique.is_string()) + { + this->loadTechniqueFromDisk(&asset->techniques[i], technique.get(), builder); + } + } + } header->techniqueSet = asset; } void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { + { Game::MaterialTechniqueSet* asset = header.techniqueSet; for (int i = 0; i < ARRAYSIZE(Game::MaterialTechniqueSet::techniques); ++i) @@ -177,8 +247,10 @@ namespace Assets AssertSize(Game::MaterialTechniqueSet, 204); Utils::Stream* buffer = builder->getBuffer(); + Game::MaterialTechniqueSet* asset = header.techniqueSet; Game::MaterialTechniqueSet* dest = buffer->dest(); + buffer->save(asset); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp index 9978b6cd..60275dc4 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp @@ -12,8 +12,8 @@ namespace Assets void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); + void loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadBinaryTechnique(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder); + void loadTechniqueFromDisk(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder); }; } diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp index e1225f7e..26b16d11 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp @@ -1,14 +1,14 @@ #include #include "IMaterialVertexDeclaration.hpp" -#define IW4X_TECHSET_VERSION "0" +#define IW4X_TECHSET_VERSION 1 namespace Assets { void IMaterialVertexDeclaration::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game + if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one } void IMaterialVertexDeclaration::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) @@ -29,12 +29,11 @@ namespace Assets Components::Logger::Error(Game::ERR_FATAL, "Reading vertex declaration '{}' failed, header is invalid!", name); } - std::string version; - version.push_back(reader.read()); + auto version = reader.read(); if (version != IW4X_TECHSET_VERSION) { - Components::Logger::Error(Game::ERR_FATAL, "Reading vertex declaration '{}' failed, expected version is {}, but it was {}!", - name, IW4X_TECHSET_VERSION, version.data()); + Components::Logger::Error(Game::ERR_FATAL, "Reading vertex declaration '{}' failed, expected version is {}, but it was {:d}!", + name, IW4X_TECHSET_VERSION, version); } Game::MaterialVertexDeclaration* asset = reader.readObject(); diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp index 3acd7be2..e4d7c9b5 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp @@ -1,14 +1,14 @@ #include #include "IMaterialVertexShader.hpp" -#define IW4X_TECHSET_VERSION "0" +#define GFX_RENDERER_SHADER_SM3 0 namespace Assets { void IMaterialVertexShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game + if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one } void IMaterialVertexShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) @@ -18,36 +18,18 @@ namespace Assets void IMaterialVertexShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { - Components::FileSystem::File vsFile(std::format("vs/{}.iw4xVS", name)); + Components::FileSystem::File vsFile(std::format("vs/{}.cso", name)); if (!vsFile.exists()) return; - Utils::Stream::Reader reader(builder->getAllocator(), vsFile.getBuffer()); + auto buff = vsFile.getBuffer(); + auto programSize = buff.size() / 4; + Game::MaterialVertexShader* asset = builder->getAllocator()->allocate(); - char* magic = reader.readArray(8); - if (std::memcmp(magic, "IW4xVERT", 8)) - { - Components::Logger::Error(Game::ERR_FATAL, "Reading vertex shader '{}' failed, header is invalid!", name); - } - - std::string version; - version.push_back(reader.read()); - if (version != IW4X_TECHSET_VERSION) - { - Components::Logger::Error(Game::ERR_FATAL, "Reading vertex shader '{}' failed, expected version is {}, but it was {}!", - name, IW4X_TECHSET_VERSION, version); - } - - Game::MaterialVertexShader* asset = reader.readObject(); - - if (asset->name) - { - asset->name = reader.readCString(); - } - - if (asset->prog.loadDef.program) - { - asset->prog.loadDef.program = reader.readArray(asset->prog.loadDef.programSize); - } + asset->name = builder->getAllocator()->duplicateString(name); + asset->prog.loadDef.loadForRenderer = GFX_RENDERER_SHADER_SM3; + asset->prog.loadDef.programSize = static_cast(programSize); + asset->prog.loadDef.program = builder->getAllocator()->allocateArray(programSize); + memcpy_s(asset->prog.loadDef.program, buff.size(), buff.data(), buff.size()); header->vertexShader = asset; } diff --git a/src/Components/Modules/AssetInterfaces/IWeapon.cpp b/src/Components/Modules/AssetInterfaces/IWeapon.cpp index d98b310f..40e8fdd5 100644 --- a/src/Components/Modules/AssetInterfaces/IWeapon.cpp +++ b/src/Components/Modules/AssetInterfaces/IWeapon.cpp @@ -280,7 +280,7 @@ namespace Assets unsigned short* scriptStringTable = buffer->dest(); buffer->saveArray(def->notetrackSoundMapKeys, 16); for (int i = 0; i < 16; i++) { - builder->mapScriptString(&scriptStringTable[i]); + builder->mapScriptString(scriptStringTable[i]); } Utils::Stream::ClearPointer(&dest->notetrackSoundMapKeys); @@ -292,7 +292,7 @@ namespace Assets unsigned short* scriptStringTable = buffer->dest(); buffer->saveArray(def->notetrackSoundMapValues, 16); for (int i = 0; i < 16; i++) { - builder->mapScriptString(&scriptStringTable[i]); + builder->mapScriptString(scriptStringTable[i]); } Utils::Stream::ClearPointer(&dest->notetrackSoundMapValues); @@ -304,7 +304,7 @@ namespace Assets unsigned short* scriptStringTable = buffer->dest(); buffer->saveArray(def->notetrackRumbleMapKeys, 16); for (int i = 0; i < 16; i++) { - builder->mapScriptString(&scriptStringTable[i]); + builder->mapScriptString(scriptStringTable[i]); } Utils::Stream::ClearPointer(&dest->notetrackRumbleMapKeys); @@ -316,7 +316,7 @@ namespace Assets unsigned short* scriptStringTable = buffer->dest(); buffer->saveArray(def->notetrackRumbleMapValues, 16); for (int i = 0; i < 16; i++) { - builder->mapScriptString(&scriptStringTable[i]); + builder->mapScriptString(scriptStringTable[i]); } Utils::Stream::ClearPointer(&dest->notetrackRumbleMapValues); @@ -725,7 +725,7 @@ namespace Assets unsigned short* scriptStringTable = buffer->dest(); buffer->saveArray(asset->hideTags, 32); for (int i = 0; i < 32; i++) { - builder->mapScriptString(&scriptStringTable[i]); + builder->mapScriptString(scriptStringTable[i]); } Utils::Stream::ClearPointer(&dest->hideTags); diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp index f9527de5..0bd5e2ce 100644 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp +++ b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp @@ -264,7 +264,7 @@ namespace Assets for (char i = 0; i < asset->boneCount[Game::PART_TYPE_ALL]; ++i) { - builder->mapScriptString(&destTagnames[i]); + builder->mapScriptString(destTagnames[i]); } Utils::Stream::ClearPointer(&dest->names); @@ -280,7 +280,7 @@ namespace Assets for (char i = 0; i < asset->notifyCount; ++i) { - builder->mapScriptString(&destNotetracks[i].name); + builder->mapScriptString(destNotetracks[i].name); } Utils::Stream::ClearPointer(&dest->notify); diff --git a/src/Components/Modules/AssetInterfaces/IXModel.cpp b/src/Components/Modules/AssetInterfaces/IXModel.cpp index 386bc472..305a624c 100644 --- a/src/Components/Modules/AssetInterfaces/IXModel.cpp +++ b/src/Components/Modules/AssetInterfaces/IXModel.cpp @@ -1,7 +1,7 @@ #include #include "IXModel.hpp" -#define IW4X_MODEL_VERSION 5 +#define IW4X_MODEL_VERSION 8 namespace Assets { @@ -9,32 +9,32 @@ namespace Assets { if (entry->nodes) { - entry->nodes = reader->readArray(entry->nodeCount); + entry->nodes = reader->readArrayOnce(entry->nodeCount); } if (entry->leafs) { - entry->leafs = reader->readArray(entry->leafCount); + entry->leafs = reader->readArrayOnce(entry->leafCount); } } - void IXModel::loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader, Components::ZoneBuilder::Zone* builder) + void IXModel::loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader, [[maybe_unused]] Components::ZoneBuilder::Zone* builder) { if (surf->vertInfo.vertsBlend) { - surf->vertInfo.vertsBlend = reader->readArray(surf->vertInfo.vertCount[0] + (surf->vertInfo.vertCount[1] * 3) + (surf->vertInfo.vertCount[2] * 5) + (surf->vertInfo.vertCount[3] * 7)); + surf->vertInfo.vertsBlend = reader->readArrayOnce(surf->vertInfo.vertCount[0] + (surf->vertInfo.vertCount[1] * 3) + (surf->vertInfo.vertCount[2] * 5) + (surf->vertInfo.vertCount[3] * 7)); } // Access vertex block if (surf->verts0) { - surf->verts0 = reader->readArray(surf->vertCount); + surf->verts0 = reader->readArrayOnce(surf->vertCount); } // Save_XRigidVertListArray if (surf->vertList) { - surf->vertList = reader->readArray(surf->vertListCount); + surf->vertList = reader->readArrayOnce(surf->vertListCount); for (unsigned int i = 0; i < surf->vertListCount; ++i) { @@ -51,17 +51,7 @@ namespace Assets // Access index block if (surf->triIndices) { - void* oldPtr = surf->triIndices; - surf->triIndices = reader->readArray(surf->triCount * 3); - - if (builder->getAllocator()->isPointerMapped(oldPtr)) - { - surf->triIndices = builder->getAllocator()->getPointer(oldPtr); - } - else - { - builder->getAllocator()->mapPointer(oldPtr, surf->triIndices); - } + surf->triIndices = reader->readArrayOnce(surf->triCount * 3); } } @@ -74,7 +64,7 @@ namespace Assets if (asset->surfs) { - asset->surfs = reader->readArray(asset->numsurfs); + asset->surfs = reader->readArrayOnce(asset->numsurfs); for (int i = 0; i < asset->numsurfs; ++i) { @@ -110,11 +100,6 @@ namespace Assets Components::Logger::Error(Game::ERR_FATAL, "Reading model '{}' failed, expected version is {}, but it was {}!", name, IW4X_MODEL_VERSION, version); } - if (version == 4) - { - Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Model '{}' is in legacy format, please update it!\n", name); - } - Game::XModel* asset = reader.readObject(); if (asset->name) @@ -134,27 +119,27 @@ namespace Assets if (asset->parentList) { - asset->parentList = reader.readArray(asset->numBones - asset->numRootBones); + asset->parentList = reader.readArrayOnce(asset->numBones - asset->numRootBones); } if (asset->quats) { - asset->quats = reader.readArray((asset->numBones - asset->numRootBones) * 4); + asset->quats = reader.readArrayOnce((asset->numBones - asset->numRootBones) * 4); } if (asset->trans) { - asset->trans = reader.readArray((asset->numBones - asset->numRootBones) * 3); + asset->trans = reader.readArrayOnce((asset->numBones - asset->numRootBones) * 3); } if (asset->partClassification) { - asset->partClassification = reader.readArray(asset->numBones); + asset->partClassification = reader.readArrayOnce(asset->numBones); } if (asset->baseMat) { - asset->baseMat = reader.readArray(asset->numBones); + asset->baseMat = reader.readArrayOnce(asset->numBones); } if (asset->materialHandles) @@ -172,7 +157,7 @@ namespace Assets // Save_XModelLodInfoArray { - for (int i = 0; i < 4; ++i) + for (unsigned int i = 0; i < 4; ++i) { if (asset->lodInfo[i].modelSurfs) { @@ -247,60 +232,53 @@ namespace Assets if (asset->physCollmap) { - if (version == 4) + Game::PhysCollmap* collmap = reader.readObject(); + asset->physCollmap = collmap; + + if (collmap->name) { - asset->physCollmap = nullptr; + collmap->name = reader.readCString(); } - else + + if (collmap->geoms) { - Game::PhysCollmap* collmap = reader.readObject(); - asset->physCollmap = collmap; + collmap->geoms = reader.readArray(collmap->count); - if (collmap->name) + for (unsigned int i = 0; i < collmap->count; ++i) { - collmap->name = reader.readCString(); - } + Game::PhysGeomInfo* geom = &collmap->geoms[i]; - if (collmap->geoms) - { - collmap->geoms = reader.readArray(collmap->count); - - for (unsigned int i = 0; i < collmap->count; ++i) + if (geom->brushWrapper) { - Game::PhysGeomInfo* geom = &collmap->geoms[i]; - - if (geom->brushWrapper) + Game::BrushWrapper* brush = reader.readObject(); + geom->brushWrapper = brush; { - Game::BrushWrapper* brush = reader.readObject(); - geom->brushWrapper = brush; + if (brush->brush.sides) { - if (brush->brush.sides) + brush->brush.sides = reader.readArray(brush->brush.numsides); + for (unsigned short j = 0; j < brush->brush.numsides; ++j) { - brush->brush.sides = reader.readArray(brush->brush.numsides); - for (unsigned short j = 0; j < brush->brush.numsides; ++j) - { - Game::cbrushside_t* side = &brush->brush.sides[j]; + Game::cbrushside_t* side = &brush->brush.sides[j]; - // TODO: Add pointer support - if (side->plane) - { - side->plane = reader.readObject(); - } + // TODO: Add pointer support + if (side->plane) + { + side->plane = reader.readObject(); } } - - if (brush->brush.baseAdjacentSide) - { - brush->brush.baseAdjacentSide = reader.readArray(brush->totalEdgeCount); - } } - // TODO: Add pointer support - if (brush->planes) + if (brush->brush.baseAdjacentSide) { - brush->planes = reader.readArray(brush->brush.numsides); + brush->brush.baseAdjacentSide = reader.readArray(brush->totalEdgeCount); } } + + // TODO: Add pointer support + if (brush->planes) + { + brush->planes = reader.readArray(brush->brush.numsides); + } } } @@ -386,7 +364,7 @@ namespace Assets for (char i = 0; i < asset->numBones; ++i) { - builder->mapScriptString(&destBoneNames[i]); + builder->mapScriptString(destBoneNames[i]); } Utils::Stream::ClearPointer(&dest->boneNames); @@ -394,37 +372,77 @@ namespace Assets if (asset->parentList) { - buffer->save(asset->parentList, asset->numBones - asset->numRootBones); - Utils::Stream::ClearPointer(&dest->parentList); + if (builder->hasPointer(asset->parentList)) + { + dest->parentList = builder->getPointer(asset->parentList); + } + else + { + builder->storePointer(asset->parentList); + buffer->save(asset->parentList, asset->numBones - asset->numRootBones); + Utils::Stream::ClearPointer(&dest->parentList); + } } if (asset->quats) { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->quats, (asset->numBones - asset->numRootBones) * 4); - Utils::Stream::ClearPointer(&dest->quats); + if (builder->hasPointer(asset->quats)) + { + dest->quats = builder->getPointer(asset->quats); + } + else + { + buffer->align(Utils::Stream::ALIGN_2); + builder->storePointer(asset->quats); + buffer->saveArray(asset->quats, (asset->numBones - asset->numRootBones) * 4); + Utils::Stream::ClearPointer(&dest->quats); + } } if (asset->trans) { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->trans, (asset->numBones - asset->numRootBones) * 3); - Utils::Stream::ClearPointer(&dest->trans); + if (builder->hasPointer(asset->trans)) + { + dest->trans = builder->getPointer(asset->trans); + } + else + { + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(asset->trans); + buffer->saveArray(asset->trans, (asset->numBones - asset->numRootBones) * 3); + Utils::Stream::ClearPointer(&dest->trans); + } } if (asset->partClassification) { - buffer->save(asset->partClassification, asset->numBones); - Utils::Stream::ClearPointer(&dest->partClassification); + if (builder->hasPointer(asset->partClassification)) + { + dest->partClassification = builder->getPointer(asset->partClassification); + } + else + { + builder->storePointer(asset->partClassification); + buffer->save(asset->partClassification, asset->numBones); + Utils::Stream::ClearPointer(&dest->partClassification); + } } if (asset->baseMat) { AssertSize(Game::DObjAnimMat, 32); + if (builder->hasPointer(asset->baseMat)) + { + dest->baseMat = builder->getPointer(asset->baseMat); + } + else + { + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(asset->baseMat); + buffer->saveArray(asset->baseMat, asset->numBones); + Utils::Stream::ClearPointer(&dest->baseMat); + } - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->baseMat, asset->numBones); - Utils::Stream::ClearPointer(&dest->baseMat); } if (asset->materialHandles) diff --git a/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp b/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp index bbe4b96a..15c4333a 100644 --- a/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp +++ b/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp @@ -37,9 +37,18 @@ namespace Assets if (surf->vertInfo.vertsBlend) { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(surf->vertInfo.vertsBlend, surf->vertInfo.vertCount[0] + (surf->vertInfo.vertCount[1] * 3) + (surf->vertInfo.vertCount[2] * 5) + (surf->vertInfo.vertCount[3] * 7)); - Utils::Stream::ClearPointer(&destSurf->vertInfo.vertsBlend); + if (builder->hasPointer(surf->vertInfo.vertsBlend)) + { + destSurf->vertInfo.vertsBlend = builder->getPointer(surf->vertInfo.vertsBlend); + } + else + { + + buffer->align(Utils::Stream::ALIGN_2); + builder->storePointer(surf->vertInfo.vertsBlend); + buffer->saveArray(surf->vertInfo.vertsBlend, surf->vertInfo.vertCount[0] + (surf->vertInfo.vertCount[1] * 3) + (surf->vertInfo.vertCount[2] * 5) + (surf->vertInfo.vertCount[3] * 7)); + Utils::Stream::ClearPointer(&destSurf->vertInfo.vertsBlend); + } } // Access vertex block @@ -48,9 +57,17 @@ namespace Assets { AssertSize(Game::GfxPackedVertex, 32); - buffer->align(Utils::Stream::ALIGN_16); - buffer->saveArray(surf->verts0, surf->vertCount); - Utils::Stream::ClearPointer(&destSurf->verts0); + if (builder->hasPointer(surf->verts0)) + { + destSurf->verts0 = builder->getPointer(surf->verts0); + } + else + { + buffer->align(Utils::Stream::ALIGN_16); + builder->storePointer(surf->verts0); + buffer->saveArray(surf->verts0, surf->vertCount); + Utils::Stream::ClearPointer(&destSurf->verts0); + } } buffer->popBlock(); @@ -59,25 +76,40 @@ namespace Assets { AssertSize(Game::XRigidVertList, 12); - buffer->align(Utils::Stream::ALIGN_4); - - Game::XRigidVertList* destCt = buffer->dest(); - buffer->saveArray(surf->vertList, surf->vertListCount); - - for (unsigned int i = 0; i < surf->vertListCount; ++i) + if (builder->hasPointer(surf->vertList)) { - Game::XRigidVertList* destRigidVertList = &destCt[i]; - Game::XRigidVertList* rigidVertList = &surf->vertList[i]; - - if (rigidVertList->collisionTree) - { - buffer->align(Utils::Stream::ALIGN_4); - this->saveXSurfaceCollisionTree(rigidVertList->collisionTree, builder); - Utils::Stream::ClearPointer(&destRigidVertList->collisionTree); - } + destSurf->vertList = builder->getPointer(surf->vertList); } + else + { + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(surf->vertList); - Utils::Stream::ClearPointer(&destSurf->vertList); + Game::XRigidVertList* destCt = buffer->dest(); + buffer->saveArray(surf->vertList, surf->vertListCount); + + for (unsigned int i = 0; i < surf->vertListCount; ++i) + { + Game::XRigidVertList* destRigidVertList = &destCt[i]; + Game::XRigidVertList* rigidVertList = &surf->vertList[i]; + + if (rigidVertList->collisionTree) + { + if (builder->hasPointer(rigidVertList->collisionTree)) + { + destRigidVertList->collisionTree = builder->getPointer(rigidVertList->collisionTree); + } + else { + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(rigidVertList->collisionTree); + this->saveXSurfaceCollisionTree(rigidVertList->collisionTree, builder); + Utils::Stream::ClearPointer(&destRigidVertList->collisionTree); + } + } + } + + Utils::Stream::ClearPointer(&destSurf->vertList); + } } // Access index block @@ -89,6 +121,7 @@ namespace Assets else { buffer->align(Utils::Stream::ALIGN_16); + builder->storePointer(surf->triIndices); buffer->saveArray(surf->triIndices, surf->triCount * 3); Utils::Stream::ClearPointer(&destSurf->triIndices); } diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index fcb99cee..14183e85 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -564,7 +564,7 @@ namespace Components bool Maps::IsCustomMap() { Game::GfxWorld*& gameWorld = *reinterpret_cast(0x66DEE94); - if(gameWorld) return gameWorld->checksum == 0xDEADBEEF; + if (gameWorld) return (gameWorld->checksum & 0xFFFF0000) == 0xC0D40000; return false; } @@ -619,7 +619,7 @@ namespace Components for (unsigned int i = 0; i < gameWorld->dpvs.smodelCount; ++i) { - if (gameWorld->dpvs.smodelDrawInsts[i].model->name == model) + if (model == "all"s || gameWorld->dpvs.smodelDrawInsts[i].model->name == model) { gameWorld->dpvs.smodelVisData[0][i] = 0; gameWorld->dpvs.smodelVisData[1][i] = 0; @@ -641,86 +641,6 @@ namespace Components } } - Game::dvar_t* Maps::GetDistortionDvar() - { - Game::dvar_t*& r_distortion = *reinterpret_cast(0x69F0DCC); - - if(Maps::IsCustomMap()) - { - static Game::dvar_t noDistortion; - ZeroMemory(&noDistortion, sizeof noDistortion); - return &noDistortion; - } - - return r_distortion; - } - - __declspec(naked) void Maps::SetDistortionStub() - { - __asm - { - push eax - pushad - call Maps::GetDistortionDvar - - mov [esp + 20h], eax - popad - - pop eax - retn - } - } - - Game::dvar_t* Maps::GetSpecularDvar() - { - Game::dvar_t*& r_specular = *reinterpret_cast(0x69F0D94); - static Game::dvar_t* r_specularCustomMaps = Game::Dvar_RegisterBool("r_specularCustomMaps", false, Game::DVAR_ARCHIVE, "Allows shaders to use phong specular lighting on custom maps"); - - if (Maps::IsCustomMap()) - { - if (!r_specularCustomMaps->current.enabled) - { - static Game::dvar_t noSpecular; - ZeroMemory(&noSpecular, sizeof noSpecular); - return &noSpecular; - } - } - - return r_specular; - } - - __declspec(naked) void Maps::SetSpecularStub1() - { - __asm - { - push eax - pushad - call Maps::GetSpecularDvar - - mov [esp + 20h], eax - popad - - pop eax - retn - } - } - - __declspec(naked) void Maps::SetSpecularStub2() - { - __asm - { - push eax - pushad - call Maps::GetSpecularDvar - - mov [esp + 20h], eax - popad - - pop edx - retn - } - } - void Maps::G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2) { if (Maps::CurrentMainZone == "mp_backlot_sh"s || Maps::CurrentMainZone == "mp_con_spring"s || @@ -842,16 +762,6 @@ namespace Components // Allow loading raw suns Utils::Hook(0x51B46A, Maps::LoadRawSun, HOOK_CALL).install()->quick(); - // Disable distortion on custom maps - //Utils::Hook(0x50AA47, Maps::SetDistortionStub, HOOK_CALL).install()->quick(); - - // Disable speculars on custom maps - Utils::Hook(0x525EA6, Maps::SetSpecularStub1, HOOK_CALL).install()->quick(); - Utils::Hook(0x51FBC7, Maps::SetSpecularStub2, HOOK_CALL).install()->quick(); - Utils::Hook(0x522A2E, Maps::SetSpecularStub2, HOOK_CALL).install()->quick(); - Utils::Hook::Nop(0x51FBCC, 1); - Utils::Hook::Nop(0x522A33, 1); - // Intercept map loading for usermap initialization Utils::Hook(0x6245E3, Maps::SpawnServerStub, HOOK_CALL).install()->quick(); Utils::Hook(0x62493E, Maps::SpawnServerStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index c601b8a7..7a4e302b 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -755,18 +755,6 @@ namespace Components Menus::CustomMenus.push_back(menu); } - void Menus::RegisterCustomMenusHook() - { - Utils::Hook::Call(0x401700)(); // call original load functions - -#ifdef _DEBUG - for (int i = 0; i < Game::uiContext->menuCount; i++) - { - OutputDebugStringA(Utils::String::VA("%s\n", Game::uiContext->Menus[i]->window.name)); - } -#endif - } - Menus::Menus() { if (ZoneBuilder::IsEnabled()) @@ -786,9 +774,6 @@ namespace Components // Don't open connect menu //Utils::Hook::Nop(0x428E48, 5); - // register custom menufiles if they exist - Utils::Hook(0x4A58C3, Menus::RegisterCustomMenusHook, HOOK_CALL).install()->quick(); - // Use the connect menu open call to update server motds Utils::Hook(0x428E48, []() { diff --git a/src/Components/Modules/Menus.hpp b/src/Components/Modules/Menus.hpp index fd13fe13..7e53759f 100644 --- a/src/Components/Modules/Menus.hpp +++ b/src/Components/Modules/Menus.hpp @@ -56,8 +56,6 @@ namespace Components static void RemoveMenuFromContext(Game::UiContext* dc, Game::menuDef_t* menu); - static void RegisterCustomMenusHook(); - // Ugly! static int KeywordHash(char* key); }; diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 16bb5b66..71541cad 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -14,6 +14,7 @@ namespace Components Dvar::Var Renderer::r_drawModelNames; Dvar::Var Renderer::r_drawAABBTrees; Dvar::Var Renderer::r_playerDrawDebugDistance; + Dvar::Var Renderer::r_forceTechnique; float cyan[4] = { 0.0f, 0.5f, 0.5f, 1.0f }; float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; @@ -171,6 +172,32 @@ namespace Components return Utils::Hook::Call(0x005033E0)(a1, a2, a3, Utils::String::VA("%s (^3%s^7)", mat->info.name, mat->techniqueSet->name), color, a6); } + void ListSamplers() + { + static auto* source = reinterpret_cast(0x6CAF080); + + Game::Font_s* font = Game::R_RegisterFont("fonts/smallFont", 0); + auto height = Game::R_TextHeight(font); + auto scale = 1.0f; + float color[4] = {0.0f, 1.0f, 0.0f, 1.0f}; + + for (std::size_t i = 0; i < 27; ++i) + { + if (source->input.codeImages[i] == nullptr) + { + color[0] = 1.f; + } + else + { + color[0] = 0.f; + } + + std::stringstream str; + str << std::format("{}/{:#X} => ", i, i) << (source->input.codeImages[i] == nullptr ? "---" : source->input.codeImages[i]->name) << " " << std::to_string(source->input.codeImageSamplerStates[i]); + Game::R_AddCmdDrawText(str.str().data(), std::numeric_limits::max(), font, 15.0f, (height * scale + 1) * (i + 1) + 14.0f, scale, scale, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL); + } + } + void Renderer::DebugDrawTriggers() { if (!r_drawTriggers.get()) return; @@ -326,21 +353,15 @@ namespace Components // Static models for (size_t i = 0; i < world->dpvs.smodelCount; i++) { - auto staticModel = world->dpvs.smodelDrawInsts[i]; + auto staticModel = &world->dpvs.smodelDrawInsts[i]; + Game::Bounds* b = &world->dpvs.smodelInsts[i].bounds; - if (Utils::Maths::Vec3SqrDistance(playerPosition, staticModel.placement.origin) < sqrDist) + if (Utils::Maths::Vec3SqrDistance(playerPosition, staticModel->placement.origin) < sqrDist) { - if (staticModel.model) + if (staticModel->model) { - Game::Bounds b = staticModel.model->bounds; - b.midPoint[0] += staticModel.placement.origin[0]; - b.midPoint[1] += staticModel.placement.origin[1]; - b.midPoint[2] += staticModel.placement.origin[2]; - b.halfSize[0] *= staticModel.placement.scale; - b.halfSize[1] *= staticModel.placement.scale; - b.halfSize[2] *= staticModel.placement.scale; - Game::R_AddDebugBounds(staticModelsColor, &b); + Game::R_AddDebugBounds(staticModelsColor, b); } } } @@ -447,6 +468,29 @@ namespace Components } } + void Renderer::ForceTechnique() + { + auto forceTechnique = r_forceTechnique.get(); + + if (forceTechnique > 0) + { + Utils::Hook::Set(0x6FABDF4, forceTechnique); + } + } + + int Renderer::FixSunShadowPartitionSize(Game::GfxCamera* camera, Game::GfxSunShadowMapMetrics* mapMetrics, Game::GfxSunShadow* sunShadow, Game::GfxSunShadowClip* clip, float* partitionFraction) + { + auto result = Utils::Hook::Call(0x5463B0)(camera, mapMetrics, sunShadow, clip, partitionFraction); + + if (Maps::IsCustomMap()) + { + // Fixes shadowmap viewport which fixes pixel adjustment shadowmap bug - partly, because the real problem lies within the way CoD4 shaders are programmed + sunShadow->partition[Game::SunShadowPartition::R_SUNSHADOW_FAR].viewportParms.viewport = sunShadow->partition[Game::SunShadowPartition::R_SUNSHADOW_NEAR].viewportParms.viewport; + } + + return result; + } + Renderer::Renderer() { if (Dedicated::IsEnabled()) return; @@ -460,9 +504,14 @@ namespace Components DebugDrawModelBoundingBoxes(); DebugDrawSceneModelCollisions(); DebugDrawTriggers(); + ForceTechnique(); } }, Scheduler::Pipeline::RENDERER); + // COD4 Map Fixes + // The day map porting is perfect we should be able to remove these + Utils::Hook(0x546A09, FixSunShadowPartitionSize, HOOK_CALL).install()->quick(); + // Log broken materials Utils::Hook(0x0054CAAA, Renderer::StoreGfxBufContextPtrStub1, HOOK_JUMP).install()->quick(); Utils::Hook(0x0054CF8D, Renderer::StoreGfxBufContextPtrStub2, HOOK_JUMP).install()->quick(); @@ -510,6 +559,7 @@ namespace Components Renderer::r_drawModelNames = Game::Dvar_RegisterEnum("r_drawModelNames", values, 0, Game::DVAR_CHEAT, "Draw all model names"); Renderer::r_drawAABBTrees = Game::Dvar_RegisterBool("r_drawAabbTrees", false, Game::DVAR_CHEAT, "Draw aabb trees"); Renderer::r_playerDrawDebugDistance = Game::Dvar_RegisterInt("r_drawDebugDistance", 1000, 0, 50000, Game::DVAR_ARCHIVE, "r_draw debug functions draw distance, relative to the player"); + Renderer::r_forceTechnique = Game::Dvar_RegisterInt("r_forceTechnique", 0, 0, 14, Game::DVAR_NONE, "Force a base technique on the renderer"); }, Scheduler::Pipeline::MAIN); } diff --git a/src/Components/Modules/Renderer.hpp b/src/Components/Modules/Renderer.hpp index 11c799cd..c856376e 100644 --- a/src/Components/Modules/Renderer.hpp +++ b/src/Components/Modules/Renderer.hpp @@ -39,6 +39,9 @@ namespace Components static void DebugDrawModelBoundingBoxes(); static void DebugDrawModelNames(); static void DebugDrawAABBTrees(); + static void ForceTechnique(); + + static int FixSunShadowPartitionSize(Game::GfxCamera* camera, Game::GfxSunShadowMapMetrics* mapMetrics, Game::GfxSunShadow* sunShadow, Game::GfxSunShadowClip* clip, float* partitionFraction); static Utils::Signal EndRecoverDeviceSignal; static Utils::Signal BeginRecoverDeviceSignal; @@ -52,5 +55,6 @@ namespace Components static Dvar::Var r_drawModelNames; static Dvar::Var r_drawAABBTrees; static Dvar::Var r_playerDrawDebugDistance; + static Dvar::Var r_forceTechnique; }; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 2defb49b..88220c49 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -225,6 +225,9 @@ namespace Components // Sanitize name for empty assets if (name[0] == ',') name.erase(name.begin()); + // Fix forward slashes for FXEffectDef (and probably other assets) + std::replace(name.begin(), name.end(), '\\', '/'); + if (this->findAsset(type, name) != -1 || this->findSubAsset(type, name).data) return true; if (type == Game::XAssetType::ASSET_TYPE_INVALID || type >= Game::XAssetType::ASSET_TYPE_COUNT) @@ -245,6 +248,9 @@ namespace Components asset.type = type; asset.header = assetHeader; + // Handle script strings + AssetHandler::ZoneMark(asset, this); + if (isSubAsset) { this->loadedSubAssets.push_back(asset); @@ -254,8 +260,6 @@ namespace Components this->loadedAssets.push_back(asset); } - // Handle script strings - AssetHandler::ZoneMark(asset, this); return true; } @@ -447,38 +451,30 @@ namespace Components Utils::Stream::ClearPointer(&zoneHeader.assetList.assets); // Increment ScriptStrings count (for empty script string) if available - if (!this->scriptStrings.empty()) - { - zoneHeader.assetList.stringList.count = this->scriptStrings.size() + 1; - Utils::Stream::ClearPointer(&zoneHeader.assetList.stringList.strings); - } + zoneHeader.assetList.stringList.count = this->scriptStrings.size() + 1; + Utils::Stream::ClearPointer(&zoneHeader.assetList.stringList.strings); // Write header this->buffer.save(&zoneHeader, sizeof(Game::ZoneHeader)); this->buffer.pushBlock(Game::XFILE_BLOCK_VIRTUAL); // Push main stream onto the stream stack // Write ScriptStrings, if available - if (!this->scriptStrings.empty()) + this->buffer.saveNull(4); + // Empty script string? + // This actually represents a NULL string, but as scriptString. + // So scriptString loading for NULL scriptStrings from fastfile results in a NULL scriptString. + // That's the reason why the count is incremented by 1, if scriptStrings are available. + + // Write ScriptString pointer table + for (std::size_t i = 0; i < this->scriptStrings.size(); ++i) { - this->buffer.saveNull(4); - // Empty script string? - // This actually represents a NULL string, but as scriptString. - // So scriptString loading for NULL scriptStrings from fastfile results in a NULL scriptString. - // That's the reason why the count is incremented by 1, if scriptStrings are available. + this->buffer.saveMax(4); + } - // Write ScriptString pointer table - for (std::size_t i = 0; i < this->scriptStrings.size(); ++i) - { - this->buffer.saveMax(4); - } - - this->buffer.align(Utils::Stream::ALIGN_4); - - // Write ScriptStrings - for (auto ScriptString : this->scriptStrings) - { - this->buffer.saveString(ScriptString.data()); - } + // Write ScriptStrings + for (auto ScriptString : this->scriptStrings) + { + this->buffer.saveString(ScriptString.data()); } // Align buffer (4 bytes) to get correct offsets for pointers @@ -530,7 +526,7 @@ namespace Components constexpr auto* data = "Built using the IW4x Zone:B:uilder Version 4"; auto dataLen = std::strlen(data); // + 1 is added by the save code - this->branding = { this->zoneName.data(), 0, static_cast(dataLen), data }; + this->branding = {this->zoneName.data(), 0, static_cast(dataLen), data}; if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1) { @@ -641,9 +637,9 @@ namespace Components } // Remap a scriptString to it's corresponding value in the local scriptString table. - void ZoneBuilder::Zone::mapScriptString(unsigned short* gameIndex) + void ZoneBuilder::Zone::mapScriptString(unsigned short& gameIndex) { - *gameIndex = 0xFFFF & this->scriptStringMap[*gameIndex]; + gameIndex = 0xFFFF & this->scriptStringMap[gameIndex]; } // Store a new name for a given asset @@ -1006,6 +1002,19 @@ namespace Components return ""; } + void ZoneBuilder::ReallocateLoadedSounds(void*& data, [[maybe_unused]] void* a2) + { + assert(data); + auto* sound = Utils::Hook::Get(0x112AE04); + auto length = sound->info.data_len; + auto allocatedSpace = Utils::Memory::AllocateArray(length); + memcpy_s(allocatedSpace, length, data, length); + + data = allocatedSpace; + sound->data = allocatedSpace; + sound->info.data_ptr = allocatedSpace; + } + ZoneBuilder::ZoneBuilder() { // ReSharper disable CppStaticAssertFailure @@ -1048,7 +1057,7 @@ namespace Components //Utils::Hook::Nop(0x5BB632, 5); // Don't load sounds - //Utils::Hook::Set(0x413430, 0xC3); + Utils::Hook(0x492EFC, ReallocateLoadedSounds, HOOK_CALL).install()->quick(); // Don't display errors when assets are missing (we might manually build those) Utils::Hook::Nop(0x5BB3F2, 5); @@ -1228,6 +1237,41 @@ namespace Components } }); + + AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, [[maybe_unused]] const std::string& name, [[maybe_unused]] bool* restrict) + { + if (type != Game::ASSET_TYPE_SOUND) + { + return; + } + + auto sound = asset.sound; + + for (size_t i = 0; i < sound->count; i++) + { + auto thisSound = sound->head[i]; + + if (thisSound.soundFile->type == Game::SAT_LOADED) + { + if (thisSound.soundFile->u.loadSnd->sound.data == nullptr) + { + // ouch + // This should never happen and will cause a memory leak + // Let's change it to a streamed sound instead + thisSound.soundFile->type = Game::SAT_STREAMED; + + auto virtualPath = std::filesystem::path(thisSound.soundFile->u.loadSnd->name); + + thisSound.soundFile->u.streamSnd.filename.info.raw.name = Utils::Memory::DuplicateString(virtualPath.filename().string()); + + auto dir = virtualPath.remove_filename().string(); + dir = dir.substr(0, dir.size() - 1); // remove / + thisSound.soundFile->u.streamSnd.filename.info.raw.dir = Utils::Memory::DuplicateString(dir); + } + } + } + }); + Command::Add("buildtechsets", [](Command::Params*) { Utils::IO::CreateDir("zone_source/techsets"); diff --git a/src/Components/Modules/ZoneBuilder.hpp b/src/Components/Modules/ZoneBuilder.hpp index ea18ed1a..33e61cc6 100644 --- a/src/Components/Modules/ZoneBuilder.hpp +++ b/src/Components/Modules/ZoneBuilder.hpp @@ -60,7 +60,7 @@ namespace Components int findScriptString(const std::string& str); void addRawAsset(Game::XAssetType type, void* ptr); - void mapScriptString(unsigned short* gameIndex); + void mapScriptString(unsigned short& gameIndex); void renameAsset(Game::XAssetType type, const std::string& asset, const std::string& newName); std::string getAssetName(Game::XAssetType type, const std::string& asset); @@ -138,6 +138,7 @@ namespace Components static void ReleaseTexture(Game::XAssetHeader header); static std::string FindMaterialByTechnique(const std::string& name); + static void ReallocateLoadedSounds(void*& data, void* a2); static int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/); static void HandleError(Game::errorParm_t code, const char* fmt, ...); diff --git a/src/Components/Modules/Zones.cpp b/src/Components/Modules/Zones.cpp index 933a133a..6efd7be6 100644 --- a/src/Components/Modules/Zones.cpp +++ b/src/Components/Modules/Zones.cpp @@ -1456,7 +1456,7 @@ namespace Components { Game::MaterialShaderArgument* arg = &argument[i]; - if (arg->type != D3DSHADER_PARAM_REGISTER_TYPE::D3DSPR_TEXTURE && arg->type != D3DSHADER_PARAM_REGISTER_TYPE::D3DSPR_ATTROUT) + if (arg->type != Game::MaterialShaderArgumentType::MTL_ARG_CODE_VERTEX_CONST && arg->type != Game::MaterialShaderArgumentType::MTL_ARG_CODE_PIXEL_CONST) { continue; } @@ -1730,7 +1730,7 @@ namespace Components { Game::GfxImageLoadDef* texture; char mapType; - char semantic; + Game::TextureSemantic semantic; char category; char flags; int cardMemory; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index d82acd5a..8c27e020 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -323,6 +323,7 @@ namespace Game PhysPreset*** varPhysPresetPtr = reinterpret_cast(0x112B378); MaterialPass** varMaterialPass = reinterpret_cast(0x112A960); snd_alias_list_t*** varsnd_alias_list_name = reinterpret_cast(0x112AF38); + MaterialVertexShader** varMaterialVertexShader = reinterpret_cast(0x112B338); FxElemField* s_elemFields = reinterpret_cast(0x73B848); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index a477a018..5d045c06 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -646,6 +646,7 @@ namespace Game extern PhysPreset*** varPhysPresetPtr; extern MaterialPass** varMaterialPass; extern snd_alias_list_t*** varsnd_alias_list_name; + extern MaterialVertexShader** varMaterialVertexShader; extern FxElemField* s_elemFields; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index c804fb48..d477e789 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -2,7 +2,6 @@ #define PROTOCOL 0x96 #define NUM_CUSTOM_CLASSES 15 -#define SEMANTIC_WATER_MAP 11 #define FX_ELEM_FIELD_COUNT 90 // This allows us to compile our structures in IDA, for easier reversing :3 @@ -96,6 +95,164 @@ namespace Game ASSET_TYPE_INVALID = -1, }; + enum surfType_t + { + R_SMODEL_SURFTYPE_RIGID = 0x0, + R_SMODEL_SURFTYPE_SKINNED = 0x1, + R_SMODEL_SURFTYPE_CACHED = 0x2, + R_SMODEL_SURFTYPE_PRETESS = 0x3, + R_SMODEL_SURFTYPE_COUNT = 0x4, + }; + + enum ShaderCodeConstants + { + CONST_SRC_CODE_MAYBE_DIRTY_PS_BEGIN = 0x0, + CONST_SRC_CODE_LIGHT_POSITION = 0x0, + CONST_SRC_CODE_LIGHT_DIFFUSE = 0x1, + CONST_SRC_CODE_LIGHT_SPECULAR = 0x2, + CONST_SRC_CODE_LIGHT_SPOTDIR = 0x3, + CONST_SRC_CODE_LIGHT_SPOTFACTORS = 0x4, + CONST_SRC_CODE_LIGHT_FALLOFF_PLACEMENT = 0x5, + CONST_SRC_CODE_PARTICLE_CLOUD_COLOR = 0x6, + CONST_SRC_CODE_GAMETIME = 0x7, + CONST_SRC_CODE_MAYBE_DIRTY_PS_END = 0x8, + CONST_SRC_CODE_ALWAYS_DIRTY_PS_BEGIN = 0x8, + CONST_SRC_CODE_PIXEL_COST_FRACS = 0x8, + CONST_SRC_CODE_PIXEL_COST_DECODE = 0x9, + CONST_SRC_CODE_FILTER_TAP_0 = 0xA, + CONST_SRC_CODE_FILTER_TAP_1 = 0xB, + CONST_SRC_CODE_FILTER_TAP_2 = 0xC, + CONST_SRC_CODE_FILTER_TAP_3 = 0xD, + CONST_SRC_CODE_FILTER_TAP_4 = 0xE, + CONST_SRC_CODE_FILTER_TAP_5 = 0xF, + CONST_SRC_CODE_FILTER_TAP_6 = 0x10, + CONST_SRC_CODE_FILTER_TAP_7 = 0x11, + CONST_SRC_CODE_COLOR_MATRIX_R = 0x12, + CONST_SRC_CODE_COLOR_MATRIX_G = 0x13, + CONST_SRC_CODE_COLOR_MATRIX_B = 0x14, + CONST_SRC_CODE_SHADOWMAP_POLYGON_OFFSET = 0x15, + CONST_SRC_CODE_RENDER_TARGET_SIZE = 0x16, + CONST_SRC_CODE_ALWAYS_DIRTY_PS_END = 0x17, + CONST_SRC_CODE_FIXED_PS_BEGIN = 0x17, + CONST_SRC_CODE_DOF_EQUATION_VIEWMODEL_AND_FAR_BLUR = 0x17, + CONST_SRC_CODE_DOF_EQUATION_SCENE = 0x18, + CONST_SRC_CODE_DOF_LERP_SCALE = 0x19, + CONST_SRC_CODE_DOF_LERP_BIAS = 0x1A, + CONST_SRC_CODE_DOF_ROW_DELTA = 0x1B, + CONST_SRC_CODE_MOTION_MATRIX_X = 0x1C, + CONST_SRC_CODE_MOTION_MATRIX_Y = 0x1D, + CONST_SRC_CODE_MOTION_MATRIX_W = 0x1E, + CONST_SRC_CODE_SHADOWMAP_SWITCH_PARTITION = 0x1F, + CONST_SRC_CODE_SHADOWMAP_SCALE = 0x20, + CONST_SRC_CODE_ZNEAR = 0x21, + CONST_SRC_CODE_LIGHTING_LOOKUP_SCALE = 0x22, + CONST_SRC_CODE_DEBUG_BUMPMAP = 0x23, + CONST_SRC_CODE_MATERIAL_COLOR = 0x24, + CONST_SRC_CODE_FOG = 0x25, + CONST_SRC_CODE_FOG_COLOR_LINEAR = 0x26, + CONST_SRC_CODE_FOG_COLOR_GAMMA = 0x27, + CONST_SRC_CODE_FOG_SUN_CONSTS = 0x28, + CONST_SRC_CODE_FOG_SUN_COLOR_LINEAR = 0x29, + CONST_SRC_CODE_FOG_SUN_COLOR_GAMMA = 0x2A, + CONST_SRC_CODE_FOG_SUN_DIR = 0x2B, + CONST_SRC_CODE_GLOW_SETUP = 0x2C, + CONST_SRC_CODE_GLOW_APPLY = 0x2D, + CONST_SRC_CODE_COLOR_BIAS = 0x2E, + CONST_SRC_CODE_COLOR_TINT_BASE = 0x2F, + CONST_SRC_CODE_COLOR_TINT_DELTA = 0x30, + CONST_SRC_CODE_COLOR_TINT_QUADRATIC_DELTA = 0x31, + CONST_SRC_CODE_OUTDOOR_FEATHER_PARMS = 0x32, + CONST_SRC_CODE_ENVMAP_PARMS = 0x33, + CONST_SRC_CODE_SUN_SHADOWMAP_PIXEL_ADJUST = 0x34, + CONST_SRC_CODE_SPOT_SHADOWMAP_PIXEL_ADJUST = 0x35, + CONST_SRC_CODE_COMPOSITE_FX_DISTORTION = 0x36, + CONST_SRC_CODE_POSTFX_FADE_EFFECT = 0x37, + CONST_SRC_CODE_VIEWPORT_DIMENSIONS = 0x38, + CONST_SRC_CODE_FRAMEBUFFER_READ = 0x39, + CONST_SRC_CODE_FIXED_PS_END = 0x3A, + CONST_SRC_CODE_NON_PS_BEGIN = 0x3A, + CONST_SRC_CODE_BASE_LIGHTING_COORDS = 0x3A, + CONST_SRC_CODE_LIGHT_PROBE_AMBIENT = 0x3B, + CONST_SRC_CODE_NEARPLANE_ORG = 0x3C, + CONST_SRC_CODE_NEARPLANE_DX = 0x3D, + CONST_SRC_CODE_NEARPLANE_DY = 0x3E, + CONST_SRC_CODE_CLIP_SPACE_LOOKUP_SCALE = 0x3F, + CONST_SRC_CODE_CLIP_SPACE_LOOKUP_OFFSET = 0x40, + CONST_SRC_CODE_PARTICLE_CLOUD_MATRIX0 = 0x41, + CONST_SRC_CODE_PARTICLE_CLOUD_MATRIX1 = 0x42, + CONST_SRC_CODE_PARTICLE_CLOUD_MATRIX2 = 0x43, + CONST_SRC_CODE_PARTICLE_CLOUD_SPARK_COLOR0 = 0x44, + CONST_SRC_CODE_PARTICLE_CLOUD_SPARK_COLOR1 = 0x45, + CONST_SRC_CODE_PARTICLE_CLOUD_SPARK_COLOR2 = 0x46, + CONST_SRC_CODE_PARTICLE_FOUNTAIN_PARM0 = 0x47, + CONST_SRC_CODE_PARTICLE_FOUNTAIN_PARM1 = 0x48, + CONST_SRC_CODE_DEPTH_FROM_CLIP = 0x49, + CONST_SRC_CODE_CODE_MESH_ARG_0 = 0x4A, + CONST_SRC_CODE_CODE_MESH_ARG_1 = 0x4B, + CONST_SRC_CODE_CODE_MESH_ARG_LAST = 0x4B, + CONST_SRC_CODE_NON_PS_END = 0x4C, + CONST_SRC_CODE_COUNT_FLOAT4 = 0x4C, + CONST_SRC_FIRST_CODE_MATRIX = 0x4C, + CONST_SRC_CODE_VIEW_MATRIX = 0x4C, + CONST_SRC_CODE_INVERSE_VIEW_MATRIX = 0x4D, + CONST_SRC_CODE_TRANSPOSE_VIEW_MATRIX = 0x4E, + CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_MATRIX = 0x4F, + CONST_SRC_CODE_PROJECTION_MATRIX = 0x50, + CONST_SRC_CODE_INVERSE_PROJECTION_MATRIX = 0x51, + CONST_SRC_CODE_TRANSPOSE_PROJECTION_MATRIX = 0x52, + CONST_SRC_CODE_INVERSE_TRANSPOSE_PROJECTION_MATRIX = 0x53, + CONST_SRC_CODE_VIEW_PROJECTION_MATRIX = 0x54, + CONST_SRC_CODE_INVERSE_VIEW_PROJECTION_MATRIX = 0x55, + CONST_SRC_CODE_TRANSPOSE_VIEW_PROJECTION_MATRIX = 0x56, + CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_PROJECTION_MATRIX = 0x57, + CONST_SRC_CODE_SHADOW_LOOKUP_MATRIX = 0x58, + CONST_SRC_CODE_INVERSE_SHADOW_LOOKUP_MATRIX = 0x59, + CONST_SRC_CODE_TRANSPOSE_SHADOW_LOOKUP_MATRIX = 0x5A, + CONST_SRC_CODE_INVERSE_TRANSPOSE_SHADOW_LOOKUP_MATRIX = 0x5B, + CONST_SRC_CODE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0x5C, + CONST_SRC_CODE_INVERSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0x5D, + CONST_SRC_CODE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0x5E, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX = 0x5F, + CONST_SRC_CODE_WORLD_MATRIX0 = 0x60, + CONST_SRC_CODE_INVERSE_WORLD_MATRIX0 = 0x61, + CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX0 = 0x62, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX0 = 0x63, + CONST_SRC_CODE_WORLD_VIEW_MATRIX0 = 0x64, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX0 = 0x65, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX0 = 0x66, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX0 = 0x67, + CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX0 = 0x68, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX0 = 0x69, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX0 = 0x6A, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX0 = 0x6B, + CONST_SRC_CODE_WORLD_MATRIX1 = 0x6C, + CONST_SRC_CODE_INVERSE_WORLD_MATRIX1 = 0x6D, + CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX1 = 0x6E, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX1 = 0x6F, + CONST_SRC_CODE_WORLD_VIEW_MATRIX1 = 0x70, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX1 = 0x71, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX1 = 0x72, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX1 = 0x73, + CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX1 = 0x74, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX1 = 0x75, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX1 = 0x76, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX1 = 0x77, + CONST_SRC_CODE_WORLD_MATRIX2 = 0x78, + CONST_SRC_CODE_INVERSE_WORLD_MATRIX2 = 0x79, + CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX2 = 0x7A, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX2 = 0x7B, + CONST_SRC_CODE_WORLD_VIEW_MATRIX2 = 0x7C, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX2 = 0x7D, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX2 = 0x7E, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX2 = 0x7F, + CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX2 = 0x80, + CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX2 = 0x81, + CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX2 = 0x82, + CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX2 = 0x83, + CONST_SRC_TOTAL_COUNT = 0x84, + CONST_SRC_NONE = 0x85, + }; + enum FsThread { FS_THREAD_MAIN = 0x0, @@ -107,6 +264,23 @@ namespace Game FS_THREAD_INVALID = 0x6, }; + enum TextureSemantic : char + { + TS_2D = 0x0, + TS_FUNCTION = 0x1, + TS_COLOR_MAP = 0x2, + TS_DETAIL_MAP = 0x3, + TS_UNUSED_2 = 0x4, + TS_NORMAL_MAP = 0x5, + TS_UNUSED_3 = 0x6, + TS_UNUSED_4 = 0x7, + TS_SPECULAR_MAP = 0x8, + TS_UNUSED_5 = 0x9, + TS_UNUSED_6 = 0xA, + TS_WATER_MAP = 0xB, + }; + + enum materialSurfType_t { SURF_TYPE_DEFAULT, @@ -252,6 +426,19 @@ namespace Game SS_GAME = 0x2, }; + enum GfxLightType + { + GFX_LIGHT_TYPE_NONE = 0x0, + GFX_LIGHT_TYPE_DIR = 0x1, + GFX_LIGHT_TYPE_SPOT = 0x2, + GFX_LIGHT_TYPE_OMNI = 0x3, + GFX_LIGHT_TYPE_COUNT = 0x4, + GFX_LIGHT_TYPE_DIR_SHADOWMAP = 0x4, + GFX_LIGHT_TYPE_SPOT_SHADOWMAP = 0x5, + GFX_LIGHT_TYPE_OMNI_SHADOWMAP = 0x6, + GFX_LIGHT_TYPE_COUNT_WITH_SHADOWMAP_VERSIONS = 0x7, + }; + enum errorParm_t { ERR_FATAL = 0x0, @@ -924,11 +1111,11 @@ namespace Game unsigned __int64 packed; }; - struct /*__declspec(align(4))*/ MaterialInfo + struct MaterialInfo { const char* name; - char gameFlags; - char sortKey; + unsigned char gameFlags; + unsigned char sortKey; unsigned char textureAtlasRowCount; unsigned char textureAtlasColumnCount; GfxDrawSurf drawSurf; @@ -994,6 +1181,23 @@ namespace Game MaterialPixelShaderProgram prog; }; + + enum MaterialShaderArgumentType : unsigned __int16 + { + MTL_ARG_MATERIAL_VERTEX_CONST = 0x0, + MTL_ARG_LITERAL_VERTEX_CONST = 0x1, + MTL_ARG_MATERIAL_PIXEL_SAMPLER = 0x2, + MTL_ARG_CODE_PRIM_BEGIN = 0x3, + MTL_ARG_CODE_VERTEX_CONST = 0x3, + MTL_ARG_CODE_PIXEL_SAMPLER = 0x4, + MTL_ARG_CODE_PIXEL_CONST = 0x5, + MTL_ARG_CODE_PRIM_END = 0x6, + MTL_ARG_MATERIAL_PIXEL_CONST = 0x6, + MTL_ARG_LITERAL_PIXEL_CONST = 0x7, + MTL_ARG_COUNT = 0x8, + }; + + struct MaterialArgumentCodeConst { unsigned __int16 index; @@ -1003,7 +1207,7 @@ namespace Game union MaterialArgumentDef { - const float* literalConst; + float* literalConst; MaterialArgumentCodeConst codeConst; unsigned int codeSampler; unsigned int nameHash; @@ -1011,7 +1215,7 @@ namespace Game struct MaterialShaderArgument { - unsigned __int16 type; + MaterialShaderArgumentType type; unsigned __int16 dest; MaterialArgumentDef u; }; @@ -1089,8 +1293,6 @@ namespace Game int sprintStartMaxLength; }; - - /* 1018 */ struct MantleState { float yaw; @@ -1099,7 +1301,6 @@ namespace Game int flags; }; - /* 1019 */ struct PlayerActiveWeaponState { int weapAnim; @@ -1111,7 +1312,6 @@ namespace Game unsigned int weaponShotCount; }; - /* 1020 */ struct PlayerEquippedWeaponState { bool usedBefore; @@ -1120,14 +1320,12 @@ namespace Game bool needsRechamber[2]; }; - /* 1021 */ struct GlobalAmmo { int ammoType; int ammoCount; }; - /* 1022 */ struct ClipAmmo { int clipIndex; @@ -1142,7 +1340,6 @@ namespace Game WEAPON_HAND_DEFAULT = 0x0, }; - /* 1023 */ struct PlayerWeaponCommonState { int offHandIndex; @@ -1174,13 +1371,11 @@ namespace Game ACTIONSLOTTYPECOUNT = 0x4, }; - /* 1024 */ struct ActionSlotParam_SpecifyWeapon { unsigned int index; }; - /* 1025 */ struct ActionSlotParam { ActionSlotParam_SpecifyWeapon specifyWeapon; @@ -1197,7 +1392,6 @@ namespace Game OBJST_NUMSTATES = 0x6, }; - /* 1026 */ struct objective_t { objectiveState_t state; @@ -1207,8 +1401,6 @@ namespace Game int icon; }; - - /* 104 */ enum he_type_t { HE_TYPE_FREE = 0x0, @@ -1238,7 +1430,6 @@ namespace Game char a; }; - /* 1028 */ union hudelem_color_t { hud_color __s0; @@ -1941,7 +2132,7 @@ namespace Game { GfxTexture texture; char mapType; - char semantic; + TextureSemantic semantic; char category; bool useSrgbReads; Picmip picmip; @@ -1995,7 +2186,7 @@ namespace Game char nameStart; char nameEnd; char samplerState; - char semantic; + TextureSemantic semantic; MaterialTextureDefInfo u; }; @@ -2006,6 +2197,87 @@ namespace Game float literal[4]; }; + enum GfxSurfaceStatebitOp0 : unsigned int + { + GFXS0_SRCBLEND_RGB_SHIFT = 0x0, + GFXS0_SRCBLEND_RGB_MASK = 0xF, + GFXS0_DSTBLEND_RGB_SHIFT = 0x4, + GFXS0_DSTBLEND_RGB_MASK = 0xF0, + GFXS0_BLENDOP_RGB_SHIFT = 0x8, + GFXS0_BLENDOP_RGB_MASK = 0x700, + GFXS0_BLEND_RGB_MASK = 0x7FF, + GFXS0_ATEST_DISABLE = 0x800, + GFXS0_ATEST_GT_0 = 0x1000, + GFXS0_ATEST_LT_128 = 0x2000, + GFXS0_ATEST_GE_128 = 0x3000, + GFXS0_ATEST_MASK = 0x3000, + GFXS0_CULL_SHIFT = 0xE, + GFXS0_CULL_NONE = 0x4000, + GFXS0_CULL_BACK = 0x8000, + GFXS0_CULL_FRONT = 0xC000, + GFXS0_CULL_MASK = 0xC000, + GFXS0_SRCBLEND_ALPHA_SHIFT = 0x10, + GFXS0_SRCBLEND_ALPHA_MASK = 0xF0000, + GFXS0_DSTBLEND_ALPHA_SHIFT = 0x14, + GFXS0_DSTBLEND_ALPHA_MASK = 0xF00000, + GFXS0_BLENDOP_ALPHA_SHIFT = 0x18, + GFXS0_BLENDOP_ALPHA_MASK = 0x7000000, + GFXS0_BLEND_ALPHA_MASK = 0x7FF0000, + GFXS0_COLORWRITE_RGB = 0x8000000, + GFXS0_COLORWRITE_ALPHA = 0x10000000, + GFXS0_COLORWRITE_MASK = 0x18000000, + GFXS0_GAMMAWRITE = 0x40000000, + GFXS0_POLYMODE_LINE = 0x80000000 + }; + + enum GfxSurfaceStatebitOp1 : unsigned int + { + GFXS1_DEPTHWRITE = 0x1, + GFXS1_DEPTHTEST_DISABLE = 0x2, + GFXS1_DEPTHTEST_SHIFT = 0x2, + GFXS1_DEPTHTEST_ALWAYS = 0x0, + GFXS1_DEPTHTEST_LESS = 0x4, + GFXS1_DEPTHTEST_EQUAL = 0x8, + GFXS1_DEPTHTEST_LESSEQUAL = 0xC, + GFXS1_DEPTHTEST_MASK = 0xC, + GFXS1_POLYGON_OFFSET_SHIFT = 0x4, + GFXS1_POLYGON_OFFSET_0 = 0x0, + GFXS1_POLYGON_OFFSET_1 = 0x10, + GFXS1_POLYGON_OFFSET_2 = 0x20, + GFXS1_POLYGON_OFFSET_SHADOWMAP = 0x30, + GFXS1_POLYGON_OFFSET_MASK = 0x30, + GFXS1_STENCIL_FRONT_ENABLE = 0x40, + GFXS1_STENCIL_BACK_ENABLE = 0x80, + GFXS1_STENCIL_MASK = 0xC0, + GFXS1_STENCIL_FRONT_PASS_SHIFT = 0x8, + GFXS1_STENCIL_FRONT_FAIL_SHIFT = 0xB, + GFXS1_STENCIL_FRONT_ZFAIL_SHIFT = 0xE, + GFXS1_STENCIL_FRONT_FUNC_SHIFT = 0x11, + GFXS1_STENCIL_FRONT_MASK = 0xFFF00, + GFXS1_STENCIL_BACK_PASS_SHIFT = 0x14, + GFXS1_STENCIL_BACK_FAIL_SHIFT = 0x17, + GFXS1_STENCIL_BACK_ZFAIL_SHIFT = 0x1A, + GFXS1_STENCIL_BACK_FUNC_SHIFT = 0x1D, + GFXS1_STENCIL_BACK_MASK = 0xFFF00000, + GFXS1_STENCILFUNC_FRONTBACK_MASK = 0xE00E0000, + GFXS1_STENCILOP_FRONTBACK_MASK = 0x1FF1FF00, + }; + + enum GfxStencilOp + { + GFXS_STENCILOP_KEEP = 0x0, + GFXS_STENCILOP_ZERO = 0x1, + GFXS_STENCILOP_REPLACE = 0x2, + GFXS_STENCILOP_INCRSAT = 0x3, + GFXS_STENCILOP_DECRSAT = 0x4, + GFXS_STENCILOP_INVERT = 0x5, + GFXS_STENCILOP_INCR = 0x6, + GFXS_STENCILOP_DECR = 0x7, + + GFXS_STENCILOP_COUNT, + GFXS_STENCILOP_MASK = 0x7 + }; + struct GfxStateBits { unsigned int loadBits[2]; @@ -2066,24 +2338,24 @@ namespace Game struct XModel { const char* name; - char numBones; - char numRootBones; + unsigned char numBones; + unsigned char numRootBones; unsigned char numsurfs; - char lodRampType; + unsigned char lodRampType; float scale; unsigned int noScalePartBits[6]; unsigned __int16* boneNames; - char* parentList; - __int16* quats; + unsigned char *parentList; + short* quats; float* trans; - char* partClassification; + unsigned char* partClassification; DObjAnimMat* baseMat; Material** materialHandles; XModelLodInfo lodInfo[4]; - char maxLoadedLod; - char numLods; - char collLod; - char flags; + unsigned char maxLoadedLod; + unsigned char numLods; + unsigned char collLod; + unsigned char flags; XModelCollSurf_s* collSurfs; int numCollSurfs; int contents; @@ -2226,6 +2498,19 @@ namespace Game SpeakerMap* speakerMap; }; + struct Poly + { + float(*pts)[3]; + unsigned int ptCount; + }; + + enum SunShadowPartition + { + R_SUNSHADOW_NEAR = 0x0, + R_SUNSHADOW_FAR = 0x1, + R_SUNSHADOW_PARTITION_COUNT = 0x2, + }; + struct snd_alias_list_t { const char* aliasName; @@ -2364,7 +2649,7 @@ namespace Game TriggerSlab* slabs; }; - struct /*__declspec(align(2))*/ Stage + struct Stage { const char* name; float origin[3]; @@ -2910,7 +3195,7 @@ namespace Game unsigned int segmentCount; }; - struct /*__declspec(align(2))*/ G_GlassPiece + struct G_GlassPiece { unsigned __int16 damageTaken; unsigned __int16 collapseTime; @@ -3242,6 +3527,13 @@ namespace Game GfxLightGridColors* colors; }; + struct GfxSModelSurfVisDataHeader + { + XSurface* surfs; + unsigned __int16 smodelCount; + unsigned __int16 smodelIndexes[1]; + }; + struct GfxBrushModelWritable { Bounds bounds; @@ -3359,10 +3651,10 @@ namespace Game struct GfxSurfaceLightingAndFlagsFields { - char lightmapIndex; - char reflectionProbeIndex; - char primaryLightIndex; - char flags; + unsigned char lightmapIndex; + unsigned char reflectionProbeIndex; + unsigned char primaryLightIndex; + unsigned char flags; }; union GfxSurfaceLightingAndFlags @@ -3396,10 +3688,10 @@ namespace Game XModel* model; unsigned __int16 cullDist; unsigned __int16 lightingHandle; - char reflectionProbeIndex; - char primaryLightIndex; - char flags; - char firstMtlSkinIndex; + unsigned char reflectionProbeIndex; + unsigned char primaryLightIndex; + unsigned char flags; + unsigned char firstMtlSkinIndex; GfxColor groundLighting; unsigned __int16 cacheId[4]; }; @@ -3419,18 +3711,87 @@ namespace Game unsigned int emissiveSurfsEnd; unsigned int smodelVisDataCount; unsigned int surfaceVisDataCount; - char* smodelVisData[3]; - char* surfaceVisData[3]; + unsigned char* smodelVisData[3]; + unsigned char* surfaceVisData[3]; unsigned __int16* sortedSurfIndex; GfxStaticModelInst* smodelInsts; GfxSurface* surfaces; GfxSurfaceBounds* surfacesBounds; GfxStaticModelDrawInst* smodelDrawInsts; GfxDrawSurf* surfaceMaterials; - unsigned int* surfaceCastsSunShadow; + unsigned int* surfaceCastsSunShadow; volatile int usageCount; }; + struct GfxSModelSurfHeaderFields + { + char reflectionProbeIndex; + char sceneLightIndex; + unsigned __int16 materialSortedIndex : 12; + unsigned __int16 visDataRefCountLessOne : 4; + }; + + union GfxSModelSurfHeader + { + GfxSModelSurfHeaderFields fields; + unsigned int packed; + unsigned __int16 array[2]; + }; + + struct GfxSModelSurfVisDataRefFields + { + unsigned __int16 surfIndex : 4; + unsigned __int16 visDataIndexPacked : 12; + }; + + union GfxSModelSurfVisDataRef + { + GfxSModelSurfVisDataRefFields fields; + unsigned __int16 packed; + }; + + struct GfxSModelSurf + { + GfxSModelSurfHeader header; + GfxSModelSurfVisDataRef visDataRefs[1]; + }; + + struct GfxSModelSurfDelaySortFields + { + unsigned __int16 unused; + GfxSModelSurfVisDataRef visDataRef; + GfxSModelSurfHeader header; + }; + + union GfxSModelSurfDelaySort + { + GfxSModelSurfDelaySortFields fields; + unsigned __int64 packed; + }; + + struct GfxSModelSurfBuildList + { + GfxSModelSurfHeader lastSurfHeader; + GfxSModelSurf* lastSModelSurf; + unsigned int visDataRefCount; + char* surfDataBegin; + char* surfDataPos; + char* surfDataEnd; + GfxSModelSurfHeader minDelaySortKey; + GfxSModelSurfDelaySort* delaySurfList; + unsigned int delaySurfCount; + unsigned int delaySurfLimit; + }; + + struct GfxSModelSurfDrawData + { + unsigned int shadowCasterMaterialIndex; + char* visData; + unsigned int visDataUsed; + unsigned int visDataLimit; + GfxSModelSurfBuildList buildList[4][4]; + }; + struct GfxWorldDpvsDynamic { unsigned int dynEntClientWordCount[2]; @@ -5162,7 +5523,6 @@ namespace Game AddonMapEnts* addonMapEnts; }; - /* 9210 */ struct weaponParms { float forward[3]; @@ -5318,6 +5678,27 @@ namespace Game XNKEY keyExchangeKey; }; + struct GfxSunShadowMapMetrics + { + unsigned int pixelsPerTile; + unsigned int tilesPerTexture; + unsigned int usefulSize; + unsigned int minCoord; + float nearClip; + float farClip; + }; + + struct GfxSunShadowProjectionSetup + { + float sunAxis[3][3]; + float nearShadowMinDist; + float frustumRayDistToEdgeOfNearMap; + float shadowOrg[2]; + float shadowOrgPixelCenter[2]; + float snappedShadowOrg[2][2]; + float sampleSize[2]; + }; + struct mapArena_t { char uiName[32]; @@ -6926,7 +7307,7 @@ namespace Game R_RENDERTARGET_NONE = 0xD, }; - struct /*__declspec(align(16))*/ GfxCmdBufState + struct GfxCmdBufState { char refSamplerState[16]; unsigned int samplerState[16]; @@ -6962,10 +7343,44 @@ namespace Game MaterialTechniqueType origTechType; }; + enum MaterialTextureSource : unsigned int + { + TEXTURE_SRC_CODE_BLACK = 0x0, + TEXTURE_SRC_CODE_WHITE = 0x1, + TEXTURE_SRC_CODE_IDENTITY_NORMAL_MAP = 0x2, + TEXTURE_SRC_CODE_MODEL_LIGHTING = 0x3, + TEXTURE_SRC_CODE_LIGHTMAP_PRIMARY = 0x4, + TEXTURE_SRC_CODE_LIGHTMAP_SECONDARY = 0x5, + TEXTURE_SRC_CODE_SHADOWMAP_SUN = 0x6, + TEXTURE_SRC_CODE_SHADOWMAP_SPOT = 0x7, + TEXTURE_SRC_CODE_FEEDBACK = 0x8, + TEXTURE_SRC_CODE_RESOLVED_POST_SUN = 0x9, + TEXTURE_SRC_CODE_RESOLVED_SCENE = 0xA, + TEXTURE_SRC_CODE_POST_EFFECT_0 = 0xB, + TEXTURE_SRC_CODE_POST_EFFECT_1 = 0xC, + TEXTURE_SRC_CODE_LIGHT_ATTENUATION = 0xD, + TEXTURE_SRC_CODE_OUTDOOR = 0xE, + TEXTURE_SRC_CODE_FLOATZ = 0xF, + TEXTURE_SRC_CODE_PROCESSED_FLOATZ = 0x10, + TEXTURE_SRC_CODE_RAW_FLOATZ = 0x11, + TEXTURE_SRC_CODE_HALF_PARTICLES = 0x12, + TEXTURE_SRC_CODE_HALF_PARTICLES_Z = 0x13, + TEXTURE_SRC_CODE_CASE_TEXTURE = 0x14, + TEXTURE_SRC_CODE_CINEMATIC_Y = 0x15, + TEXTURE_SRC_CODE_CINEMATIC_CR = 0x16, + TEXTURE_SRC_CODE_CINEMATIC_CB = 0x17, + TEXTURE_SRC_CODE_CINEMATIC_A = 0x18, + TEXTURE_SRC_CODE_REFLECTION_PROBE = 0x19, + TEXTURE_SRC_CODE_ALTERNATE_SCENE = 0x1A, + TEXTURE_SRC_CODE_COUNT = 0x1B, + }; + + struct GfxCmdBufSourceState; + struct GfxCmdBufContext { - /*GfxCmdBufSourceState*/ void* source; - GfxCmdBufState* state; + GfxCmdBufSourceState *source; + GfxCmdBufState *state; }; struct GfxDrawGroupSetupFields @@ -7058,6 +7473,306 @@ namespace Game float sunShadowPixelAdjust[4]; }; + struct GfxMatrix + { + float m[4][4]; + }; + + struct GfxCodeMatrices + { + GfxMatrix matrix[56]; + }; + + struct GfxCamera + { + float origin[3]; + float axis[3][3]; + float subWindowMins[2]; + float subWindowMaxs[2]; + float tanHalfFovX; + float tanHalfFovY; + float zNear; + float depthHackNearClip; + }; + + struct GfxViewParms + { + GfxMatrix viewMatrix; + GfxMatrix projectionMatrix; + GfxMatrix viewProjectionMatrix; + GfxMatrix inverseViewProjectionMatrix; + GfxCamera camera; + }; + + struct GfxBackEndData; + struct GfxCmdBufInput + { + float consts[76][4]; + GfxImage* codeImages[27]; + char codeImageSamplerStates[27]; + GfxBackEndData* data; + }; + + + enum GfxViewMode + { + VIEW_MODE_NONE = 0x0, + VIEW_MODE_3D = 0x1, + VIEW_MODE_2D = 0x2, + VIEW_MODE_IDENTITY = 0x3, + }; + + enum GfxViewportBehavior + { + GFX_USE_VIEWPORT_FOR_VIEW = 0x0, + GFX_USE_VIEWPORT_FULL = 0x1, + }; + + enum ShadowType + { + SHADOW_NONE = 0x0, + SHADOW_MAP = 0x1, + }; + + struct GfxDepthOfField + { + float viewModelStart; + float viewModelEnd; + float nearStart; + float nearEnd; + float farStart; + float farEnd; + float nearBlur; + float farBlur; + }; + + struct GfxFilm + { + bool enabled; + float brightness; + float contrast; + float desaturation; + float desaturationDark; + bool invert; + float tintDark[3]; + float tintMedium[3]; + float tintLight[3]; + }; + + struct GfxGlow + { + bool enabled; + float bloomCutoff; + float bloomDesaturation; + float bloomIntensity; + float radius; + }; + + struct GfxLightScale + { + float diffuseScale; + float specularScale; + }; + + struct GfxStageInfo + { + Stage activeStage; + bool activeStageValid; + }; + + struct GfxCompositeFx + { + GfxFilm film; + float distortionScale[3]; + float blurRadius; + float distortionMagnitude; + float frameRate; + int lastUpdate; + int frame; + int startMSec; + int currentTime; + int duration; + bool enabled; + bool scriptEnabled; + }; + + struct GfxVertexBufferState + { + volatile int used; + int total; + IDirect3DVertexBuffer9* buffer; + char* verts; + }; + + struct GfxMeshData + { + unsigned int indexCount; + unsigned int totalIndexCount; + unsigned __int16* indices; + GfxVertexBufferState vb; + unsigned int vertSize; + }; + + struct GfxQuadMeshData + { + float x; + float y; + float width; + float height; + GfxMeshData meshData; + }; + + struct GfxSparkSurfList + { + GfxSparkSurf* surfs; + unsigned int count; + }; + + enum GfxCodeSurfListType + { + GFX_CODE_SURFLIST_INVALID = -1, + GFX_CODE_SURFLIST_TRANS = 0x0, + GFX_CODE_SURFLIST_EMISSIVE = 0x1, + GFX_CODE_SURFLIST_TYPE_COUNT = 0x2, + }; + + + struct GfxViewInfo; + + struct GfxDrawListInfo + { + MaterialTechniqueType baseTechType; + GfxViewInfo* viewInfo; + float eyeOffset[3]; + unsigned int sceneLightIndex; + int cameraView; + GfxCodeSurfListType codeSurfListType; + }; + + struct GfxBspSurfList + { + unsigned int count; + const unsigned __int16* stream; + }; + + struct GfxSModelSurfList + { + unsigned int surfDataBytes; + const char* surfData; + const char* visData; + }; + + struct GfxDrawSurfList + { + GfxDrawSurf* array; + unsigned int count; + }; + + struct GfxPreTessSurf + { + GfxDrawGroupSetup drawGroup; + char lightmapIndex; + char reflectionProbeIndex; + unsigned __int16 triCount; + unsigned int baseIndex; + unsigned int firstVertex; + IDirect3DVertexBuffer9* vb; + unsigned int vertexCount; + }; + + struct GfxPreTessSurfList + { + GfxPreTessSurf* surfs; + unsigned int count; + }; + + struct GfxCodeSurfList + { + GfxCodeSurf* surfs; + unsigned int count; + }; + + struct GfxMarkSurfList + { + GfxMarkSurf* surfs; + unsigned int count; + }; + + struct GfxGlassSurfList + { + GfxGlassSurf* surfs; + unsigned int count; + }; + + struct GfxScaledPlacement + { + GfxPlacement base; + float scale; + }; + + struct GfxParticleCloud + { + GfxScaledPlacement placement; + float endpos[3]; + GfxColor color; + float radius[2]; + unsigned int flags; + float timeOffset; + }; + + struct GfxCloudSurfList + { + GfxParticleCloud* particles; + GfxCloudSurf* surfs; + unsigned int count; + }; + + struct GfxDrawList + { + GfxBspSurfList bspSurfList; + GfxPreTessSurfList bspPreTessSurfList; + GfxSModelSurfList smodelSurfList[4]; + GfxDrawSurfList drawSurfList; + GfxCodeSurfList codeSurfList; + GfxMarkSurfList markSurfList; + GfxGlassSurfList glassSurfList; + GfxCloudSurfList cloudSurfList; + GfxSparkSurfList sparkSurfList; + GfxDrawListInfo info; + }; + + struct GfxViewInfo + { + GfxViewParms viewParms; + GfxViewport sceneViewport; + GfxViewport displayViewport; + GfxViewport scissorViewport; + GfxSceneDef sceneDef; + ShadowType dynamicShadowType; + char floatZUsage; + bool needsDistortionResolve; + bool viewModelHasDistortion; + char forceSunShadowsGenerate; + unsigned int sceneLightCount; + float blurRadius; + float frustumPlanes[4][4]; + GfxDepthOfField dof; + GfxFilm film; + GfxGlow glow; + GfxLightScale charPrimaryLightScale; + GfxStageInfo stageInfo; + GfxCompositeFx waterSheetingFx; + const void* displayCmds; + GfxQuadMeshData* fullSceneViewMesh; + GfxDrawList drawList[10]; + //__declspec(align(16)) GfxCmdBufInput input; + GfxRenderTargetId renderTargetId; + bool useShadows; + unsigned int sunShadowResolution; + GfxRenderTargetId sunShadowRenderTargetId; + unsigned int sunShadowTileCount; + }; + struct GfxLight { char type; @@ -7149,10 +7864,31 @@ namespace Game char reflectionProbeIndex; }; - struct GfxScaledPlacement + struct GfxCmdBufSourceState { - GfxPlacement base; - float scale; + GfxCodeMatrices matrices; + GfxCmdBufInput input; + GfxViewParms viewParms; + float eyeOffset[4]; + GfxMatrix shadowLookupMatrix; + unsigned __int16 constVersions[132]; + unsigned __int16 matrixVersions[14]; + unsigned int sceneLightForShadowLookupMatrix; + GfxPlacement* objectPlacement[3]; + GfxViewParms* viewParms3D; + unsigned int depthHackFlags; + GfxScaledPlacement skinnedPlacement; + int cameraView; + GfxViewMode viewMode; + GfxSceneDef sceneDef; + GfxViewport sceneViewport; + float materialTime; + GfxViewportBehavior viewportBehavior; + int renderTargetWidth; + int renderTargetHeight; + bool viewportIsDirty; + unsigned int sceneLightIndex; + bool useHeroLighting; }; struct GfxSceneModel @@ -9179,6 +9915,398 @@ namespace Game ET_EVENTS = 0x12, }; + struct GfxBackEndPrimitiveData + { + int hasSunDirChanged; + }; + + struct GfxFog + { + int startTime; + int finishTime; + GfxColor color; + float fogStart; + float density; + float fogMaxOpacity; + bool sunFogEnabled; + GfxColor sunColor; + float sunDir[3]; + float sunBeginFadeAngle; + float sunEndFadeAngle; + float sunFogScale; + }; + + struct GfxCmdHeader + { + unsigned __int16 id; + unsigned __int16 byteCount; + }; + + struct GfxCmdArray + { + char* cmds; + int usedTotal; + int usedCritical; + GfxCmdHeader* lastCmd; + }; + + struct GfxCmdBuf + { + IDirect3DDevice9* device; + }; + + struct GfxDrawCallOutput + { + GfxCmdBuf cmdBuf; + }; + + struct __declspec(align(4)) GfxDebugPoly + { + float color[4]; + int firstVert; + int vertCount; + bool outline; + }; + + struct GfxDebugPlume + { + float origin[3]; + float color[4]; + int score; + int startTime; + int duration; + }; + + struct DebugGlobals + { + float(*verts)[3]; + int vertCount; + int vertLimit; + GfxDebugPoly* polys; + int polyCount; + int polyLimit; + trDebugString_t* strings; + int stringCount; + int stringLimit; + trDebugString_t* externStrings; + int externStringCount; + int externMaxStringCount; + trDebugLine_t* lines; + int lineCount; + int lineLimit; + trDebugLine_t* externLines; + int externLineCount; + int externMaxLineCount; + GfxDebugPlume* plumes; + int plumeCount; + int plumeLimit; + }; + + struct GfxSunShadowProjection + { + float switchPartition[4]; + float shadowmapScale[4]; + }; + + struct GfxSunShadowOverlaySetup + { + float shadowOrg[2]; + float frustumShadowRays[4][2]; + unsigned int clipPlaneCount[2]; + float clipPlanes[2][8][3]; + }; + + struct GfxViewportParms + { + GfxViewport viewport; + GfxViewParms viewParms; + }; + + struct GfxSunShadowPartition + { + GfxViewportParms viewportParms; + }; + + struct GfxSunShadow + { + GfxMatrix lookupMatrix; + GfxSunShadowProjection sunProj; + GfxSunShadowPartition partition[2]; + GfxSunShadowOverlaySetup overlaySetup; + }; + + struct GfxSpotShadowSceneLight + { + GfxMatrix lookupMatrix; + float fade; + GfxImage* image; + }; + + struct GfxDrawSurfIter + { + GfxDrawSurf* current; + GfxDrawSurf* end; + GfxDrawSurf* mark; + }; + + struct GfxCodeSurfIter + { + GfxCodeSurf* current; + GfxCodeSurf* end; + GfxCodeSurf* mark; + }; + + struct GfxMarkSurfIter + { + GfxMarkSurf* current; + GfxMarkSurf* end; + GfxMarkSurf* mark; + }; + + struct GfxGlassSurfIter + { + GfxGlassSurf* current; + GfxGlassSurf* end; + GfxGlassSurf* mark; + }; + + struct GfxCloudSurfIter + { + GfxCloudSurf* current; + GfxCloudSurf* end; + GfxCloudSurf* mark; + }; + + struct GfxSparkSurfIter + { + GfxSparkSurf* current; + GfxSparkSurf* end; + GfxSparkSurf* mark; + }; + + struct GfxSModelSurfIter + { + const char* visData; + unsigned __int16* current; + const char* end; + const char* mark; + }; + + struct GfxBspSurfIter + { + const unsigned __int16* current; + const unsigned __int16* end; + const unsigned __int16* mark; + }; + + struct GfxBspLightMapSurfIter : GfxBspSurfIter + { + }; + + struct GfxPreTessSurfIter + { + GfxPreTessSurf* current; + GfxPreTessSurf* end; + GfxPreTessSurf* mark; + }; + + struct GfxSunShadowClip + { + unsigned int planeCount[2]; + unsigned int frustumPlaneCount[2]; + DpvsPlane planes[2][10]; + }; + + struct GfxSModelCachedSurfIter : GfxSModelSurfIter + { + }; + + struct GfxSModelRigidSurfIter : GfxSModelSurfIter + { + }; + + struct GfxSModelSkinnedSurfIter : GfxSModelSurfIter + { + }; + + struct GfxSModelPreTessSurfIter : GfxSModelSurfIter + { + }; + + struct GfxCmdRingBuf + { + struct GfxDrawListIter* drawListIter; + unsigned int memoryPos; + unsigned int maxMemoryPos; + char* memoryPool; + unsigned int fencePosIndex; + volatile unsigned int fenceIndex; + unsigned int availIndex; + unsigned int availMemoryPos; + unsigned int reserveMemoryPos0; + unsigned int reserveMemoryPos1; + unsigned int fencePos[64]; + unsigned int fence[64]; + unsigned int checkMemoryPos; + }; + + struct GfxDrawListIter + { + GfxBspSurfIter bspSurfIter; + GfxPreTessSurfIter bspPreTessSurfIter; + GfxSModelRigidSurfIter smodelRigidSurfIter; + GfxSModelSkinnedSurfIter smodelSkinnedSurfIter; + GfxSModelCachedSurfIter smodelCachedSurfIter; + GfxSModelPreTessSurfIter smodelPreTessSurfIter; + GfxDrawSurfIter drawSurfIter; + GfxCodeSurfIter codeSurfIter; + GfxMarkSurfIter markSurfIter; + GfxGlassSurfIter glassSurfIter; + GfxCloudSurfIter cloudSurfIter; + GfxSparkSurfIter sparkSurfIter; + }; + + union GfxSurfsIteratorSortKey + { + struct + { + unsigned int spliceIndex; + unsigned int sortKey; + } fields; + unsigned __int64 packed; + }; + + struct GfxSpotShadow + { + GfxSpotShadowSceneLight sceneLight; + GfxViewportParms viewportParms; + char sceneLightIndex; + char pad[3]; + GfxLight* light; + GfxRenderTargetId renderTargetId; + float pixelAdjust[4]; + int clearScreen; + GfxMeshData* clearMesh; + }; + + struct GfxDrawListArgs + { + GfxCmdBufContext context; + GfxDrawListInfo* listInfo; + }; + + struct GfxSurfsIterator + { + GfxSurfsIteratorSortKey key; + unsigned int(__cdecl* GetSortKeyCallback)(GfxDrawListIter*); + bool(__cdecl* RenderDrawGroupCallback)(GfxDrawListArgs*, GfxDrawListIter*); + }; + + struct GfxSurfsIterGroup + { + unsigned int iteratorBegin; + unsigned int iteratorCount; + GfxDrawListIter drawListIter; + GfxSurfsIterator iteratorPool[11]; + }; + + struct GfxSpliceSurfs + { + unsigned int iteratorBegin; + unsigned int iteratorCount; + unsigned int spliceCount; + GfxDrawListIter drawListIter[5]; + GfxViewport scissorViewport[5]; + int isSceneScissorViewport[5]; + GfxDrawListInfo* dynLightDrawListInfo[5]; + GfxSurfsIterator iteratorPool[55]; + }; + + struct GfxStaticModelDrawStream + { + GfxSModelSurfIter* smodelSurfIter; + GfxSModelSurfHeader smodelSurfHeader; + const char* smodelSurfVisData; + GfxTexture* reflectionProbeTexture; + unsigned int customSamplerFlags; + XSurface* localSurf; + unsigned int smodelCount; + const unsigned __int16* smodelList; + }; + + struct FxSparkMeshData + { + unsigned int triCount; + unsigned __int16* indices; + unsigned int baseVertex; + char pad[4]; + GfxParticleCloud cloud; + }; + + struct GfxBackEndData + { + char sceneLightTechType[13][256]; + GfxSparkSurf sparkSurfs[64]; + GfxViewParms viewParms[4]; + GfxMeshData mesh[5]; + int localClientNum; + GfxBackEndPrimitiveData prim; + volatile int bspSurfDataUsed; + volatile int smodelSurfDataUsed; + volatile int smodelSurfVisDataUsed; + unsigned int sceneLightHasShadowMap[8]; + int drawSurfCount; + volatile int surfPos; + volatile int gfxEntCount; + unsigned int codeSurfCount[2]; + unsigned int codeSurfArgsCount[2]; + volatile int cloudDataCount; + unsigned int glassSurfCount; + unsigned int markSurfCount; + volatile int sparkSurfCount; + GfxVertexBufferState* skinnedCacheVb; + unsigned int endFence; + unsigned int endFrameFence; + int viewParmCount; + GfxFog fogSettings; + GfxCmdArray* commands; + unsigned int viewInfoIndex; + unsigned int viewInfoCount; + GfxViewInfo* viewInfo; + const void* cmds; + float sunShadowLightDir[3]; + int hasApproxSunDirChanged; + int cmdBufValid[18]; + GfxDrawCallOutput drawOutput[18]; + DebugGlobals debugGlobals; + unsigned int imageRendered[112]; + unsigned int drawType; + GfxDrawList dynLightDrawList[4]; + unsigned int dynLightCount; + GfxDrawList* emissiveSpotShadowDrawList[1]; + unsigned int emissiveSpotLightCount; + GfxSunShadow sunShadow; + unsigned int spotShadowCount; + GfxSpotShadow spotShadows[4]; + GfxSurfsIterGroup prepassIterGroup[5]; + GfxSpliceSurfs litTransSpliceSurfs; + char surfsBuffer[131072]; + float codeSurfArgs[288][4]; + GfxCodeSurf codeEmissiveSurfs[2048]; + GfxCodeSurf codeTransSurfs[640]; + GfxMarkSurf markSurfs[1536]; + GfxGlassSurf glassSurfs[768]; + unsigned __int16 bspSurfData[35328]; + char smodelSurfData[35840]; + char smodelSurfVisData[45056]; + GfxCloudSurf cloudSurfs[256]; + GfxEntity gfxEnts[128]; + FxSparkMeshData sparkData[64]; + GfxParticleCloud cloudData[256]; + GfxDrawSurf drawSurfs[16384]; + GfxLight sceneLights[253]; + }; + #pragma endregion #ifndef IDA diff --git a/src/Utils/Compression.cpp b/src/Utils/Compression.cpp index a26fd668..adf5aefd 100644 --- a/src/Utils/Compression.cpp +++ b/src/Utils/Compression.cpp @@ -11,8 +11,15 @@ namespace Utils::Compression // Make sure the buffer is large enough if (length < 100) length *= 10; - char* buffer = allocator.allocateArray(length); - if (compress2(reinterpret_cast(buffer), &length, reinterpret_cast(const_cast(data.data())), data.size(), Z_BEST_COMPRESSION) != Z_OK) + auto* buffer = allocator.allocateArray(length); + +#ifdef _DEBUG + constexpr auto compression = Z_NO_COMPRESSION; +#else + constexpr auto compression = Z_BEST_COMPRESSION; +#endif + + if (compress2((Bytef*)(buffer), &length, (const Bytef*)(data.data()), data.size(), compression) != Z_OK) { return {}; } @@ -34,13 +41,13 @@ namespace Utils::Compression int ret; Memory::Allocator allocator; - std::uint8_t* dest = allocator.allocateArray(CHUNK); - const char* dataPtr = data.data(); + auto* dest = allocator.allocateArray(CHUNK); + const auto* dataPtr = data.data(); do { - stream.avail_in = std::min(static_cast(CHUNK), data.size() - (dataPtr - data.data())); - stream.next_in = reinterpret_cast(dataPtr); + stream.avail_in = std::min(static_cast(CHUNK), data.size() - (dataPtr - data.data())); + stream.next_in = reinterpret_cast(dataPtr); dataPtr += stream.avail_in; do diff --git a/src/Utils/Entities.cpp b/src/Utils/Entities.cpp index 5c31dfbe..baf3962e 100644 --- a/src/Utils/Entities.cpp +++ b/src/Utils/Entities.cpp @@ -35,7 +35,9 @@ namespace Utils { const auto& model = itr->second; - if (!model.empty() && model[0] != '*' && model[0] != '?') // Skip brushmodels + if (!model.empty() && model[0] != '*' && model[0] != '?' && // Skip brushmodels + model != "com_plasticcase_green_big_us_dirt"s // Team zones + ) { if (std::find(models.begin(), models.end(), model) == models.end()) { diff --git a/src/Utils/Json.cpp b/src/Utils/Json.cpp index cbf963e3..eb36fff6 100644 --- a/src/Utils/Json.cpp +++ b/src/Utils/Json.cpp @@ -1,4 +1,5 @@ #include +#include namespace Utils::Json { @@ -31,4 +32,32 @@ namespace Utils::Json return "null"; } } + + unsigned long ReadFlags(const std::string binaryFlags, size_t size) + { + std::bitset<64> input; + const auto binarySize = size * 8; + + if (binaryFlags.size() > binarySize) + { + Components::Logger::Print("Flag {} might not be properly translated, it seems to contain an error (invalid length)\n", binaryFlags); + return 0; + } + + auto i = binarySize - 1; + for (char bit : binaryFlags) + { + if (i < 0) + { + Components::Logger::Print("Flag {} might not be properly translated, it seems to contain an error (invalid length)\n", binaryFlags); + break; + } + + bool isOne = bit == '1'; + input.set(i--, isOne); + } + + return input.to_ulong(); + } + } diff --git a/src/Utils/Json.hpp b/src/Utils/Json.hpp index 854811e1..415309e7 100644 --- a/src/Utils/Json.hpp +++ b/src/Utils/Json.hpp @@ -3,4 +3,6 @@ namespace Utils::Json { std::string TypeToString(nlohmann::json::value_t type); + + unsigned long ReadFlags(const std::string binaryFlags, size_t size); } diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index e9f7ae96..3739cc3a 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -39,10 +39,44 @@ namespace Utils { return readArray(1); } + + template T* readArrayOnce(std::size_t count = 1) + { + constexpr auto POINTER = 255; + constexpr auto FOLLOWING = 254; + + auto b = static_cast(readByte()); + switch (b) + { + case POINTER: + { + auto ptr = read(); + auto* voidPtr = reinterpret_cast(ptr); + + if (allocator->isPointerMapped(voidPtr)) + { + return allocator->getPointer(voidPtr); + } + + throw std::runtime_error("Bad data: missing ptr"); + } + case FOLLOWING: + { + auto filePosition = position; + auto data = readArray(count); + allocator->mapPointer(reinterpret_cast(filePosition), data); + return data; + } + default: + throw std::runtime_error("Bad data"); + } + } + template T* readArray(std::size_t count = 1) { return static_cast(this->read(sizeof(T), count)); } + template T read() { T obj; From 873f54c7a3669ca2ca9f9d41d7815388979480ac Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 14 Dec 2022 11:26:04 +0100 Subject: [PATCH 53/96] [Main]: Remove bugged code. (#640) --- src/DllMain.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/DllMain.cpp b/src/DllMain.cpp index 2a0cbec0..16c2f485 100644 --- a/src/DllMain.cpp +++ b/src/DllMain.cpp @@ -64,7 +64,7 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser MessageBoxA(nullptr, "Failed to load game binary.\n" "You did not install the iw4x-rawfiles!\n" - "Please use the XLabs launcher to run the game. For support please visit https://xlabs.dev/support_iw4x_client", + "Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client", "ERROR", MB_ICONERROR ); @@ -72,10 +72,8 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser } #endif -#ifndef DEBUG_BINARY_CHECK // Install entry point hook Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick(); -#endif } else if (fdwReason == DLL_PROCESS_DETACH) { From e30bde84583bd0da645c2d9fd2e049f98585e74f Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 14 Dec 2022 12:31:03 +0100 Subject: [PATCH 54/96] [Menus]: Cleanup --- src/Components/Modules/Menus.cpp | 325 ++++++++++++++++--------------- src/Components/Modules/Menus.hpp | 4 +- src/Game/Common.cpp | 1 + src/Game/Common.hpp | 3 + src/Game/Functions.cpp | 25 +-- src/Game/Functions.hpp | 21 +- src/Game/Structs.hpp | 10 +- src/STDInclude.hpp | 2 +- 8 files changed, 202 insertions(+), 189 deletions(-) diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 7a4e302b..5301e3e6 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -6,6 +6,31 @@ namespace Components std::unordered_map Menus::MenuList; std::unordered_map Menus::MenuListList; + Game::KeywordHashEntry** menuParseKeywordHash; + + template + static int KeywordHashKey(const char* keyword) + { + auto hash = 0; + for (auto i = 0; keyword[i]; ++i) + { + hash += (i + HASH_SEED) * std::tolower(static_cast(keyword[i])); + } + return (hash + (hash >> 8)) & (128 - 1); + } + + template + static Game::KeywordHashEntry* KeywordHashFind(Game::KeywordHashEntry** table, const char* keyword) + { + auto hash = KeywordHashKey(keyword); + Game::KeywordHashEntry* key = table[hash]; + if (key && !_stricmp(key->keyword, keyword)) + { + return key; + } + return nullptr; + } + int Menus::ReserveSourceHandle() { // Check if a free slot is available @@ -27,7 +52,7 @@ namespace Components Game::script_t* Menus::LoadMenuScript(const std::string& name, const std::string& buffer) { - Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length()); + auto* script = static_cast(Game::GetClearedMemory(sizeof(Game::script_t) + 1 + buffer.length())); if (!script) return nullptr; strcpy_s(script->filename, sizeof(script->filename), name.data()); @@ -37,18 +62,18 @@ namespace Components script->script_p = script->buffer; script->lastscript_p = script->buffer; - script->length = buffer.length(); + script->length = static_cast(buffer.length()); script->end_p = &script->buffer[buffer.length()]; script->line = 1; script->lastline = 1; script->tokenavailable = 0; - Game::Script_SetupTokens(script, reinterpret_cast(0x797F80)); - script->punctuations = reinterpret_cast(0x797F80); + Game::PS_CreatePunctuationTable(script, Game::default_punctuations); + script->punctuations = Game::default_punctuations; std::memcpy(script->buffer, buffer.data(), script->length + 1); - script->length = Game::Script_CleanString(script->buffer); + script->length = Game::Com_Compress(script->buffer); return script; } @@ -57,10 +82,10 @@ namespace Components { Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator(); - int handle = Menus::ReserveSourceHandle(); - if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot! + const auto handle = ReserveSourceHandle(); + if (!IsValidSourceHandle(handle)) return 0; // No free source slot! - Game::script_t* script = Menus::LoadMenuScript(name, buffer); + auto* script = LoadMenuScript(name, buffer); if (!script) { @@ -68,8 +93,6 @@ namespace Components return 0; } - script->next = nullptr; - auto* source = allocator->allocate(); if (!source) { @@ -77,13 +100,17 @@ namespace Components return 0; } - strncpy_s(source->filename, 64, "string", 64); + std::memset(source, 0, sizeof(Game::source_s)); + + script->next = nullptr; + + strncpy_s(source->filename, "string", _TRUNCATE); source->scriptstack = script; source->tokens = nullptr; source->defines = nullptr; source->indentstack = nullptr; source->skip = 0; - source->definehash = static_cast(allocator->allocate(4096)); + source->definehash = static_cast(Game::GetClearedMemory(1024 * sizeof(Game::define_s*))); Game::sourceFiles[handle] = source; @@ -95,27 +122,9 @@ namespace Components return (handle > 0 && handle < MAX_SOURCEFILES && Game::sourceFiles[handle]); } - int Menus::KeywordHash(char* key) - { - int hash = 0; - - if (*key) - { - int sub = 3523 - reinterpret_cast(key); - do - { - char _chr = *key; - hash += reinterpret_cast(&(key++)[sub]) * tolower(_chr); - } while (*key); - } - - return (static_cast(hash) + static_cast(hash >> 8)) & 0x7F; - } - Game::menuDef_t* Menus::ParseMenu(int handle) { Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator(); - auto* menu = allocator->allocate(); if (!menu) return nullptr; @@ -149,10 +158,7 @@ namespace Components break; // Success } - int idx = Menus::KeywordHash(token.string); - - Game::keywordHash_t* key = Game::menuParseKeywordHash[idx]; - + auto* key = KeywordHashFind(menuParseKeywordHash, token.string); if (!key) { Game::PC_SourceError(handle, "unknown menu keyword %s", token.string); @@ -168,14 +174,15 @@ namespace Components if (!menu->window.name) { + Game::PC_SourceError(handle, "menu has no name"); allocator->free(menu->items); allocator->free(menu); return nullptr; } - Menus::OverrideMenu(menu); - Menus::RemoveMenu(menu->window.name); - Menus::MenuList[menu->window.name] = menu; + OverrideMenu(menu); + RemoveMenu(menu->window.name); + MenuList[menu->window.name] = menu; return menu; } @@ -188,9 +195,9 @@ namespace Components if (!menuFile.exists()) return nullptr; Game::pc_token_t token; - int handle = Menus::LoadMenuSource(menu, menuFile.getBuffer()); + int handle = LoadMenuSource(menu, menuFile.getBuffer()); - if (Menus::IsValidSourceHandle(handle)) + if (IsValidSourceHandle(handle)) { while (true) { @@ -206,23 +213,23 @@ namespace Components Game::PC_ReadTokenHandle(handle, &token); auto* filename = Utils::String::VA("ui_mp\\%s.menu", token.string); - Utils::Merge(&menus, Menus::LoadMenu(filename)); + Utils::Merge(&menus, LoadMenu(filename)); } if (!_stricmp(token.string, "menudef")) { - Game::menuDef_t* menudef = Menus::ParseMenu(handle); - if (menudef) menus.push_back({ true, menudef }); // Custom menu + auto* menudef = ParseMenu(handle); + if (menudef) menus.emplace_back(std::make_pair(true, menudef)); // Custom menu } } - Menus::FreeMenuSource(handle); + FreeMenuSource(handle); } if (menus.empty()) return nullptr; // Allocate new menu list - Game::MenuList* list = allocator->allocate(); + auto* list = allocator->allocate(); if (!list) return nullptr; list->menus = allocator->allocateArray(menus.size()); @@ -233,10 +240,10 @@ namespace Components } list->name = allocator->duplicateString(menu); - list->menuCount = menus.size(); + list->menuCount = static_cast(menus.size()); // Copy new menus - for (unsigned int i = 0; i < menus.size(); ++i) + for (std::size_t i = 0; i < menus.size(); ++i) { list->menus[i] = menus[i].second; } @@ -252,9 +259,9 @@ namespace Components if (menuFile.exists()) { Game::pc_token_t token; - int handle = Menus::LoadMenuSource(menu, menuFile.getBuffer()); + const auto handle = LoadMenuSource(menu, menuFile.getBuffer()); - if (Menus::IsValidSourceHandle(handle)) + if (IsValidSourceHandle(handle)) { while (true) { @@ -269,17 +276,17 @@ namespace Components { Game::PC_ReadTokenHandle(handle, &token); - Utils::Merge(&menus, Menus::LoadMenu(Utils::String::VA("ui_mp\\%s.menu", token.string))); + Utils::Merge(&menus, LoadMenu(Utils::String::VA("ui_mp\\%s.menu", token.string))); } if (!_stricmp(token.string, "menudef")) { - Game::menuDef_t* menudef = Menus::ParseMenu(handle); - if (menudef) menus.push_back({ true, menudef }); // Custom menu + auto* menudef = ParseMenu(handle); + if (menudef) menus.emplace_back(std::make_pair(true, menudef)); // Custom menu } } - Menus::FreeMenuSource(handle); + FreeMenuSource(handle); } } @@ -288,11 +295,13 @@ namespace Components std::vector> Menus::LoadMenu(Game::menuDef_t* menudef) { - std::vector> menus = Menus::LoadMenu(Utils::String::VA("ui_mp\\%s.menu", menudef->window.name)); + assert(menudef->window.name); + + std::vector> menus = LoadMenu(Utils::String::VA("ui_mp\\%s.menu", menudef->window.name)); if (menus.empty()) { - menus.push_back({ false, menudef }); // Native menu + menus.emplace_back(std::make_pair(false, menudef)); // Native menu } return menus; @@ -302,7 +311,7 @@ namespace Components { Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator(); - std::vector> menus = Menus::LoadMenu(menu); + auto menus = LoadMenu(menu); if (menus.empty()) return nullptr; // Allocate new menu list @@ -325,8 +334,8 @@ namespace Components newList->menus[i] = menus[i].second; } - Menus::RemoveMenuList(newList->name); - Menus::MenuListList[newList->name] = newList; + RemoveMenuList(newList->name); + MenuListList[newList->name] = newList; return newList; } @@ -366,7 +375,7 @@ namespace Components { if (i->second->window.name == std::string(newMenu.second->window.name)) { - Menus::RemoveMenu(i->second); + RemoveMenu(i->second); i = menus->erase(i); increment = false; @@ -389,13 +398,13 @@ namespace Components for (int i = 0; i < menuList->menuCount; ++i) { if (!menuList->menus[i]) continue; - Menus::SafeMergeMenus(&menus, Menus::LoadMenu(menuList->menus[i])); + SafeMergeMenus(&menus, LoadMenu(menuList->menus[i])); } // Load custom menus if (menuList->name == "ui_mp/code.txt"s) // Should be menus, but code is loaded ingame { - for (auto menu : Menus::CustomMenus) + for (auto menu : CustomMenus) { bool hasMenu = false; for (auto& loadedMenu : menus) @@ -407,15 +416,15 @@ namespace Components } } - if (!hasMenu) Menus::SafeMergeMenus(&menus, Menus::LoadMenu(menu)); + if (!hasMenu) SafeMergeMenus(&menus, LoadMenu(menu)); } } // Allocate new menu list - Game::MenuList* newList = allocator->allocate(); + auto* newList = allocator->allocate(); if (!newList) return menuList; - size_t size = menus.size(); + auto size = menus.size(); newList->menus = allocator->allocateArray(size); if (!newList->menus) { @@ -432,8 +441,8 @@ namespace Components newList->menus[i] = menus[i].second; } - Menus::RemoveMenuList(newList->name); - Menus::MenuListList[newList->name] = newList; + RemoveMenuList(newList->name); + MenuListList[newList->name] = newList; return newList; } @@ -442,7 +451,7 @@ namespace Components { Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator(); - if (!Menus::IsValidSourceHandle(handle)) return; + if (!IsValidSourceHandle(handle)) return; Game::source_t* source = Game::sourceFiles[handle]; @@ -481,28 +490,43 @@ namespace Components Game::sourceFiles[handle] = nullptr; } - void Menus::FreeMenu(Game::menuDef_t* menudef) + void Menus::Menu_FreeItemMemory(Game::itemDef_s* item) + { + AssertOffset(Game::itemDef_s, floatExpressionCount, 0x13C); + + for (auto i = 0; i < item->floatExpressionCount; ++i) + { + Game::free_expression(item->floatExpressions[i].expression); + } + + item->floatExpressionCount = 0; + } + + void Menus::FreeMenu(Game::menuDef_t* menu) { Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator(); - // Do i need to free expressions and strings? - // Or does the game take care of it? - // Seems like it does... - - if (menudef->items) + if (menu->items) { - // Seems like this is obsolete as well, - // as the game handles the memory + for (int i = 0; i < menu->itemCount; ++i) + { +#if 0 + Menu_FreeItemMemory(menu->items[i]); +#endif + } - //for (int i = 0; i < menudef->itemCount; ++i) - //{ - // Game::Menu_FreeItemMemory(menudef->items[i]); - //} - - allocator->free(menudef->items); + allocator->free(menu->items); } - allocator->free(menudef); + Game::free_expression(menu->visibleExp); + Game::free_expression(menu->rectXExp); + Game::free_expression(menu->rectYExp); + Game::free_expression(menu->rectWExp); + Game::free_expression(menu->rectHExp); + Game::free_expression(menu->openSoundExp); + Game::free_expression(menu->closeSoundExp); + + allocator->free(menu); } void Menus::FreeMenuList(Game::MenuList* menuList) @@ -513,37 +537,29 @@ namespace Components // Keep our compiler happy Game::MenuList list = { menuList->name, menuList->menuCount, menuList->menus }; - if (list.name) - { - allocator->free(list.name); - } - - if (list.menus) - { - allocator->free(list.menus); - } - + allocator->free(list.name); + allocator->free(list.menus); allocator->free(menuList); } void Menus::RemoveMenu(const std::string& menu) { - auto i = Menus::MenuList.find(menu); - if (i != Menus::MenuList.end()) + auto i = MenuList.find(menu); + if (i != MenuList.end()) { - if (i->second) Menus::FreeMenu(i->second); - i = Menus::MenuList.erase(i); + if (i->second) FreeMenu(i->second); + i = MenuList.erase(i); } } void Menus::RemoveMenu(Game::menuDef_t* menudef) { - for (auto i = Menus::MenuList.begin(); i != Menus::MenuList.end();) + for (auto i = MenuList.begin(); i != MenuList.end();) { if (i->second == menudef) { - Menus::FreeMenu(menudef); - i = Menus::MenuList.erase(i); + FreeMenu(menudef); + i = MenuList.erase(i); } else { @@ -554,20 +570,20 @@ namespace Components void Menus::RemoveMenuList(const std::string& menuList) { - auto i = Menus::MenuListList.find(menuList); - if (i != Menus::MenuListList.end()) + auto i = MenuListList.find(menuList); + if (i != MenuListList.end()) { if (i->second) { for (auto j = 0; j < i->second->menuCount; ++j) { - Menus::RemoveMenu(i->second->menus[j]); + RemoveMenu(i->second->menus[j]); } - Menus::FreeMenuList(i->second); + FreeMenuList(i->second); } - i = Menus::MenuListList.erase(i); + i = MenuListList.erase(i); } } @@ -584,8 +600,7 @@ namespace Components std::string name = menu->window.name; // Find the old menu - auto i = Menus::MenuList.find(name); - if (i != Menus::MenuList.end()) + if (auto i = MenuList.find(name); i != MenuList.end()) { // We have found it, *yay* Game::menuDef_t* oldMenu = i->second; @@ -600,7 +615,7 @@ namespace Components } // Replace every old instance with our new one in our menu lists - for (auto j = Menus::MenuListList.begin(); j != Menus::MenuListList.end(); ++j) + for (auto j = MenuListList.begin(); j != MenuListList.end(); ++j) { Game::MenuList* list = j->second; @@ -615,30 +630,33 @@ namespace Components } } } + + FreeMenu(oldMenu); } } void Menus::RemoveMenuList(Game::MenuList* menuList) { if (!menuList || !menuList->name) return; - Menus::RemoveMenuList(menuList->name); + RemoveMenuList(menuList->name); } + // In your dreams void Menus::FreeEverything() { - for (auto i = Menus::MenuListList.begin(); i != Menus::MenuListList.end(); ++i) + for (auto i = MenuListList.begin(); i != MenuListList.end(); ++i) { - Menus::FreeMenuList(i->second); + FreeMenuList(i->second); } - Menus::MenuListList.clear(); + MenuListList.clear(); - for (auto i = Menus::MenuList.begin(); i != Menus::MenuList.end(); ++i) + for (auto i = MenuList.begin(); i != MenuList.end(); ++i) { - Menus::FreeMenu(i->second); + FreeMenu(i->second); } - Menus::MenuList.clear(); + MenuList.clear(); } Game::XAssetHeader Menus::MenuFindHook(Game::XAssetType /*type*/, const std::string& filename) @@ -651,23 +669,23 @@ namespace Components Game::XAssetHeader header = { nullptr }; // Free the last menulist and ui context, as we have to rebuild it with the new menus - if (Menus::MenuListList.find(filename) != Menus::MenuListList.end()) + if (MenuListList.find(filename) != MenuListList.end()) { - Game::MenuList* list = Menus::MenuListList[filename]; + Game::MenuList* list = MenuListList[filename]; for (int i = 0; list && list->menus && i < list->menuCount; ++i) { - Menus::RemoveMenuFromContext(Game::uiContext, list->menus[i]); + RemoveMenuFromContext(Game::uiContext, list->menus[i]); } - Menus::RemoveMenuList(filename); + RemoveMenuList(filename); } if (Utils::String::EndsWith(filename, ".menu")) { if (FileSystem::File(filename).exists()) { - header.menuList = Menus::LoadScriptMenu(filename.data()); + header.menuList = LoadScriptMenu(filename.data()); if (header.menuList) return header; } } @@ -682,7 +700,7 @@ namespace Components { if (FileSystem::File(filename).exists()) { - header.menuList = Menus::LoadScriptMenu(filename.data()); + header.menuList = LoadScriptMenu(filename.data()); // Reset, if we didn't find scriptmenus if (!header.menuList) @@ -693,7 +711,7 @@ namespace Components } else { - header.menuList = Menus::LoadMenuList(menuList); + header.menuList = LoadMenuList(menuList); } } else @@ -714,7 +732,7 @@ namespace Components if (originalConnect == menu) // Check if we draw the original loadscreen { - if (Menus::MenuList.find("connect") != Menus::MenuList.end()) // Check if we have a custom loadscreen, to prevent drawing the original one on top + if (MenuList.find("connect") != Menus::MenuList.end()) // Check if we have a custom loadscreen, to prevent drawing the original one on top { return false; } @@ -748,15 +766,19 @@ namespace Components // Clear last menu dc->Menus[--dc->menuCount] = nullptr; } + + FreeMenu(menu); } void Menus::Add(const std::string& menu) { - Menus::CustomMenus.push_back(menu); + CustomMenus.push_back(menu); } Menus::Menus() { + menuParseKeywordHash = reinterpret_cast**>(0x63AE928); + if (ZoneBuilder::IsEnabled()) { Game::Menu_Setup(Game::uiContext); @@ -764,18 +786,15 @@ namespace Components if (Dedicated::IsEnabled()) return; - // Ensure everything is zero'ed - Menus::FreeEverything(); - // Intercept asset finding - AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENU, Menus::MenuFindHook); - AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENULIST, Menus::MenuListFindHook); + AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENU, MenuFindHook); + AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENULIST, MenuListFindHook); // Don't open connect menu - //Utils::Hook::Nop(0x428E48, 5); + // Utils::Hook::Nop(0x428E48, 5); // Use the connect menu open call to update server motds - Utils::Hook(0x428E48, []() + Utils::Hook(0x428E48, [] { if (!Party::GetMotd().empty() && Party::Target() == *Game::connectedHost) { @@ -784,10 +803,10 @@ namespace Components }, HOOK_CALL).install()->quick(); // Intercept menu painting - Utils::Hook(0x4FFBDF, Menus::IsMenuVisible, HOOK_CALL).install()->quick(); + Utils::Hook(0x4FFBDF, IsMenuVisible, HOOK_CALL).install()->quick(); - // disable the 2 new tokens in ItemParse_rect - Utils::Hook::Set(0x640693, 0xEB); + // disable the 2 new tokens in ItemParse_rect (Fix by NTA. Probably because he didn't want to update the menus) + Utils::Hook::Set(0x640693, 0xEB); // don't load ASSET_TYPE_MENU assets for every menu (might cause patch menus to fail) Utils::Hook::Nop(0x453406, 5); @@ -806,19 +825,19 @@ namespace Components // Not quite sure if we want to do this if we're not ingame, but it's only needed for ingame menus. if ((*Game::cl_ingame)->current.enabled) { - Game::Key_SetCatcher(0, 16); + Game::Key_SetCatcher(0, Game::KEYCATCH_UI); } Game::Menus_OpenByName(Game::uiContext, params->get(1)); }); - Command::Add("reloadmenus", [](Command::Params*) + Command::Add("reloadmenus", []([[maybe_unused]] Command::Params* params) { // Close all menus Game::Menus_CloseAll(Game::uiContext); - // Free custom menus - Menus::FreeEverything(); + // Free custom menus (Get pranked) + FreeEverything(); // Only disconnect if in-game, context is updated automatically! if (Game::CL_IsCgameInitialized()) @@ -841,27 +860,27 @@ namespace Components }); // Define custom menus here - Menus::Add("ui_mp/changelog.menu"); - Menus::Add("ui_mp/theater_menu.menu"); - Menus::Add("ui_mp/pc_options_multi.menu"); - Menus::Add("ui_mp/pc_options_game.menu"); - Menus::Add("ui_mp/pc_options_gamepad.menu"); - Menus::Add("ui_mp/stats_reset.menu"); - Menus::Add("ui_mp/stats_unlock.menu"); - Menus::Add("ui_mp/security_increase_popmenu.menu"); - Menus::Add("ui_mp/mod_download_popmenu.menu"); - Menus::Add("ui_mp/popup_friends.menu"); - Menus::Add("ui_mp/menu_first_launch.menu"); - Menus::Add("ui_mp/startup_messages.menu"); - Menus::Add("ui_mp/iw4x_credits.menu"); - Menus::Add("ui_mp/resetclass.menu"); - Menus::Add("ui_mp/popup_customtitle.menu"); - Menus::Add("ui_mp/popup_customclan.menu"); + Add("ui_mp/changelog.menu"); + Add("ui_mp/theater_menu.menu"); + Add("ui_mp/pc_options_multi.menu"); + Add("ui_mp/pc_options_game.menu"); + Add("ui_mp/pc_options_gamepad.menu"); + Add("ui_mp/stats_reset.menu"); + Add("ui_mp/stats_unlock.menu"); + Add("ui_mp/security_increase_popmenu.menu"); + Add("ui_mp/mod_download_popmenu.menu"); + Add("ui_mp/popup_friends.menu"); + Add("ui_mp/menu_first_launch.menu"); + Add("ui_mp/startup_messages.menu"); + Add("ui_mp/iw4x_credits.menu"); + Add("ui_mp/resetclass.menu"); + Add("ui_mp/popup_customtitle.menu"); + Add("ui_mp/popup_customclan.menu"); } Menus::~Menus() { - // In your dreams! + // Let Windows handle the memory leaks for you! Menus::FreeEverything(); } } diff --git a/src/Components/Modules/Menus.hpp b/src/Components/Modules/Menus.hpp index 7e53759f..45ff1639 100644 --- a/src/Components/Modules/Menus.hpp +++ b/src/Components/Modules/Menus.hpp @@ -43,6 +43,7 @@ namespace Components static void FreeMenuSource(int handle); static void FreeMenuList(Game::MenuList* menuList); + static void Menu_FreeItemMemory(Game::itemDef_s* item); static void FreeMenu(Game::menuDef_t* menudef); static void RemoveMenu(const std::string& menu); @@ -55,8 +56,5 @@ namespace Components static bool IsMenuVisible(Game::UiContext* dc, Game::menuDef_t* menu); static void RemoveMenuFromContext(Game::UiContext* dc, Game::menuDef_t* menu); - - // Ugly! - static int KeywordHash(char* key); }; } diff --git a/src/Game/Common.cpp b/src/Game/Common.cpp index b1c50c67..b9b626c2 100644 --- a/src/Game/Common.cpp +++ b/src/Game/Common.cpp @@ -23,6 +23,7 @@ namespace Game Com_Quitf_t Com_Quit_f = Com_Quitf_t(0x4D4000); Com_OpenLogFile_t Com_OpenLogFile = Com_OpenLogFile_t(0x60A8D0); Com_UpdateSlowMotion_t Com_UpdateSlowMotion = Com_UpdateSlowMotion_t(0x60B2D0); + Com_Compress_t Com_Compress = Com_Compress_t(0x498220); int* com_frameTime = reinterpret_cast(0x1AD8F3C); diff --git a/src/Game/Common.hpp b/src/Game/Common.hpp index 344bdfc6..58e18b0b 100644 --- a/src/Game/Common.hpp +++ b/src/Game/Common.hpp @@ -62,6 +62,9 @@ namespace Game typedef void(*Com_UpdateSlowMotion_t)(int msec); extern Com_UpdateSlowMotion_t Com_UpdateSlowMotion; + typedef int(*Com_Compress_t)(char* data_p); + extern Com_Compress_t Com_Compress; + extern int* com_frameTime; extern int* com_fixedConsolePosition; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 8c27e020..e8bf6e6a 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -152,9 +152,10 @@ namespace Game R_FlushSun_t R_FlushSun = R_FlushSun_t(0x53FB50); R_SortWorldSurfaces_t R_SortWorldSurfaces = R_SortWorldSurfaces_t(0x53DC10); - Script_Alloc_t Script_Alloc = Script_Alloc_t(0x422E70); - Script_SetupTokens_t Script_SetupTokens = Script_SetupTokens_t(0x4E6950); - Script_CleanString_t Script_CleanString = Script_CleanString_t(0x498220); + GetMemory_t GetMemory = GetMemory_t(0x4E67B0); + GetClearedMemory_t GetClearedMemory = GetClearedMemory_t(0x422E70); + PS_CreatePunctuationTable_t PS_CreatePunctuationTable = PS_CreatePunctuationTable_t(0x4E6950); + free_expression_t free_expression = free_expression_t(0x4ACC70); SE_Load_t SE_Load = SE_Load_t(0x502A30); @@ -270,8 +271,7 @@ namespace Game cmd_function_t** cmd_functions = reinterpret_cast(0x1AAC658); - source_t **sourceFiles = reinterpret_cast(0x7C4A98); - keywordHash_t **menuParseKeywordHash = reinterpret_cast(0x63AE928); + source_t** sourceFiles = reinterpret_cast(0x7C4A98); float* cgameFOVSensitivityScale = reinterpret_cast(0xB2F884); @@ -399,6 +399,8 @@ namespace Game int* ui_numArenas = reinterpret_cast(0x62D2788); int* ui_arenaBufPos = reinterpret_cast(0x62D278C); + punctuation_s* default_punctuations = reinterpret_cast(0x797F80); + const char* TableLookup(StringTable* stringtable, int row, int column) { if (!stringtable || !stringtable->values || row >= stringtable->rowCount || column >= stringtable->columnCount) return ""; @@ -926,19 +928,6 @@ namespace Game } } - __declspec(naked) void Menu_FreeItemMemory(itemDef_s* /*item*/) - { - __asm - { - pushad - mov edi, [esp + 24h] - mov eax, 63D880h - call eax - popad - retn - } - } - void Menu_SetNextCursorItem(UiContext* a1, menuDef_t* a2, int unk) { __asm diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 5d045c06..2834a2e0 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -374,14 +374,17 @@ namespace Game typedef GfxWorld*(*R_SortWorldSurfaces_t)(); extern R_SortWorldSurfaces_t R_SortWorldSurfaces; - typedef script_t*(*Script_Alloc_t)(int length); - extern Script_Alloc_t Script_Alloc; + typedef void* (*GetMemory_t)(unsigned int size); + extern GetMemory_t GetMemory; - typedef void(*Script_SetupTokens_t)(script_t* script, void* tokens); - extern Script_SetupTokens_t Script_SetupTokens; + typedef void*(*GetClearedMemory_t)(unsigned int size); + extern GetClearedMemory_t GetClearedMemory; - typedef int(*Script_CleanString_t)(char* buffer); - extern Script_CleanString_t Script_CleanString; + typedef void(*PS_CreatePunctuationTable_t)(script_s* script, punctuation_s* punctuations); + extern PS_CreatePunctuationTable_t PS_CreatePunctuationTable; + + typedef void(*free_expression_t)(Statement_s* statement); + extern free_expression_t free_expression; typedef char*(*SE_Load_t)(const char* psFileName, bool forceEnglish); extern SE_Load_t SE_Load; @@ -596,8 +599,7 @@ namespace Game extern float* cgameFOVSensitivityScale; - extern source_t **sourceFiles; - extern keywordHash_t **menuParseKeywordHash; + extern source_t** sourceFiles; extern UiContext* uiContext; @@ -727,6 +729,8 @@ namespace Game extern int* ui_numArenas; extern int* ui_arenaBufPos; + extern punctuation_s* default_punctuations; + constexpr auto MAX_MSGLEN = 0x20000; ScreenPlacement* ScrPlace_GetFullPlacement(); @@ -734,7 +738,6 @@ namespace Game void UI_FilterStringForButtonAnimation(char* str, unsigned int strMaxSize); - void Menu_FreeItemMemory(itemDef_s* item); void Menu_SetNextCursorItem(UiContext* ctx, menuDef_t* currentMenu, int unk = 1); void Menu_SetPrevCursorItem(UiContext* ctx, menuDef_t* currentMenu, int unk = 1); const char* TableLookup(StringTable* stringtable, int row, int column); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index d477e789..41b050e1 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -7173,12 +7173,12 @@ namespace Game char string[MAX_TOKENLENGTH]; } pc_token_t; - typedef struct keywordHash_s + template + struct KeywordHashEntry { - char* keyword; - bool(*func)(menuDef_t* item, int handle); - //struct keywordHash_s *next; - } keywordHash_t; + const char* keyword; + int (*func)(T*, int); + }; enum MaterialTechniqueType { diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index e957a9ad..62a39359 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include From 6f0438631f2705c5588301b6799d706a9c066ae2 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 14 Dec 2022 12:44:06 +0100 Subject: [PATCH 55/96] [Menus]: Disable this code too --- src/Components/Modules/Menus.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 5301e3e6..a931b553 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -517,7 +517,7 @@ namespace Components allocator->free(menu->items); } - +#if 0 Game::free_expression(menu->visibleExp); Game::free_expression(menu->rectXExp); Game::free_expression(menu->rectYExp); @@ -525,6 +525,7 @@ namespace Components Game::free_expression(menu->rectHExp); Game::free_expression(menu->openSoundExp); Game::free_expression(menu->closeSoundExp); +#endif allocator->free(menu); } From 34b92abd97bbc81320eb5149f70995b1129c5bc0 Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 14 Dec 2022 22:10:48 +0100 Subject: [PATCH 56/96] [Menus]: Remove calls to free menus (#642) It may cause a crash and does not even take a dent in the massive memory leak. --- src/Components/Modules/Menus.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index a931b553..e9adf249 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -631,8 +631,6 @@ namespace Components } } } - - FreeMenu(oldMenu); } } @@ -767,8 +765,6 @@ namespace Components // Clear last menu dc->Menus[--dc->menuCount] = nullptr; } - - FreeMenu(menu); } void Menus::Add(const std::string& menu) From 817ca6e688ba8998cebec3d3fa6c7710e00921ab Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 15 Dec 2022 15:59:52 +0100 Subject: [PATCH 57/96] [Deps]: Put json to a stable branch (#643) --- .gitmodules | 3 ++- deps/json | 1 + deps/nlohmannjson | 1 - deps/premake/json.lua | 19 +++++++++++++++++++ deps/premake/nlohmannjson.lua | 18 ------------------ 5 files changed, 22 insertions(+), 20 deletions(-) create mode 160000 deps/json delete mode 160000 deps/nlohmannjson create mode 100644 deps/premake/json.lua delete mode 100644 deps/premake/nlohmannjson.lua diff --git a/.gitmodules b/.gitmodules index 7839a17e..4387e293 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,5 +32,6 @@ path = deps/GSL url = https://github.com/microsoft/GSL.git [submodule "deps/nlohmannjson"] - path = deps/nlohmannjson + path = deps/json url = https://github.com/nlohmann/json.git + branch = v3.11.2 diff --git a/deps/json b/deps/json new file mode 160000 index 00000000..bc889afb --- /dev/null +++ b/deps/json @@ -0,0 +1 @@ +Subproject commit bc889afb4c5bf1c0d8ee29ef35eaaf4c8bef8a5d diff --git a/deps/nlohmannjson b/deps/nlohmannjson deleted file mode 160000 index 7f72eedc..00000000 --- a/deps/nlohmannjson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7f72eedc2d4fc196d389f5aa0b2659f70dabe278 diff --git a/deps/premake/json.lua b/deps/premake/json.lua new file mode 100644 index 00000000..c4731982 --- /dev/null +++ b/deps/premake/json.lua @@ -0,0 +1,19 @@ +json = { + source = path.join(dependencies.basePath, "json"), +} + +function json.import() + json.includes() +end + +function json.includes() + includedirs { + path.join(json.source, "single_include/nlohmann") + } +end + +function json.project() + +end + +table.insert(dependencies, json) diff --git a/deps/premake/nlohmannjson.lua b/deps/premake/nlohmannjson.lua deleted file mode 100644 index 8cdf6217..00000000 --- a/deps/premake/nlohmannjson.lua +++ /dev/null @@ -1,18 +0,0 @@ -nlohmannjson = { - source = path.join(dependencies.basePath, "nlohmannjson"), -} - -function nlohmannjson.import() - nlohmannjson.includes() -end - -function nlohmannjson.includes() - includedirs { - path.join(nlohmannjson.source, "single_include/nlohmann") - } -end - -function nlohmannjson.project() -end - -table.insert(dependencies, nlohmannjson) From d1efb1e219c91812e543dcefcb33889f2435874e Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 15 Dec 2022 16:06:28 +0100 Subject: [PATCH 58/96] [Threading]: VA is already thread safe (#644) --- src/Components/Modules/Threading.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Components/Modules/Threading.cpp b/src/Components/Modules/Threading.cpp index eb481c71..f22315a7 100644 --- a/src/Components/Modules/Threading.cpp +++ b/src/Components/Modules/Threading.cpp @@ -158,9 +158,6 @@ namespace Components Utils::Hook(0x43D1C7, PacketEventStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x6272E3, FrameEpilogueStub, HOOK_JUMP).install()->quick(); - // make VA thread safe - Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick(); - if (Dedicated::IsEnabled()) { Utils::Hook(0x4BAAAD, FrameTime::SVFrameWaitStub, HOOK_CALL).install()->quick(); From ab0da964eed3657382a6f7ffd1ce34602f59aacc Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 15 Dec 2022 16:13:49 +0100 Subject: [PATCH 59/96] [Bots]: Support clantags (#645) --- src/Components/Modules/Bots.cpp | 72 +++++++++++++++++++++------------ src/Components/Modules/Bots.hpp | 3 +- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 75d30db1..bd65eb50 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -3,7 +3,7 @@ namespace Components { - std::vector Bots::BotNames; + std::vector Bots::BotNames; struct BotMovementInfo { @@ -24,28 +24,29 @@ namespace Components static const BotAction BotActions[] = { - { "gostand", Game::usercmdButtonBits::CMD_BUTTON_UP }, - { "gocrouch", Game::usercmdButtonBits::CMD_BUTTON_CROUCH }, - { "goprone", Game::usercmdButtonBits::CMD_BUTTON_PRONE }, - { "fire", Game::usercmdButtonBits::CMD_BUTTON_ATTACK }, - { "melee", Game::usercmdButtonBits::CMD_BUTTON_MELEE }, - { "frag", Game::usercmdButtonBits::CMD_BUTTON_FRAG }, - { "smoke", Game::usercmdButtonBits::CMD_BUTTON_OFFHAND_SECONDARY }, - { "reload", Game::usercmdButtonBits::CMD_BUTTON_RELOAD }, - { "sprint", Game::usercmdButtonBits::CMD_BUTTON_SPRINT }, - { "leanleft", Game::usercmdButtonBits::CMD_BUTTON_LEAN_LEFT }, - { "leanright", Game::usercmdButtonBits::CMD_BUTTON_LEAN_RIGHT }, - { "ads", Game::usercmdButtonBits::CMD_BUTTON_ADS }, - { "holdbreath", Game::usercmdButtonBits::CMD_BUTTON_BREATH }, - { "usereload", Game::usercmdButtonBits::CMD_BUTTON_USE_RELOAD }, - { "activate", Game::usercmdButtonBits::CMD_BUTTON_ACTIVATE }, + { "gostand", Game::CMD_BUTTON_UP }, + { "gocrouch", Game::CMD_BUTTON_CROUCH }, + { "goprone", Game::CMD_BUTTON_PRONE }, + { "fire", Game::CMD_BUTTON_ATTACK }, + { "melee", Game::CMD_BUTTON_MELEE }, + { "frag", Game::CMD_BUTTON_FRAG }, + { "smoke", Game::CMD_BUTTON_OFFHAND_SECONDARY }, + { "reload", Game::CMD_BUTTON_RELOAD }, + { "sprint", Game::CMD_BUTTON_SPRINT }, + { "leanleft", Game::CMD_BUTTON_LEAN_LEFT }, + { "leanright", Game::CMD_BUTTON_LEAN_RIGHT }, + { "ads", Game::CMD_BUTTON_ADS }, + { "holdbreath", Game::CMD_BUTTON_BREATH }, + { "usereload", Game::CMD_BUTTON_USE_RELOAD }, + { "activate", Game::CMD_BUTTON_ACTIVATE }, }; int Bots::BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port) { - static size_t botId = 0; + static size_t botId = 0; // Loop over the BotNames vector static bool loadedNames = false; // Load file only once const char* botName; + const char* clanName; if (BotNames.empty() && !loadedNames) { @@ -54,16 +55,32 @@ namespace Components if (bots.exists()) { - auto names = Utils::String::Split(bots.getBuffer(), '\n'); + auto data = Utils::String::Split(bots.getBuffer(), '\n'); - for (auto& name : names) + for (auto& entry : data) { - Utils::String::Replace(name, "\r", ""); - Utils::String::Trim(name); + // Take into account for CR line endings + Utils::String::Replace(entry, "\r", ""); + // Remove whitespace + Utils::String::Trim(entry); - if (!name.empty()) + if (!entry.empty()) { - BotNames.push_back(name); + std::string clanAbbrev; + + // Check if there is a clan tag + if (const auto pos = entry.find(','); pos != std::string::npos) + { + // Only start copying over from non-null characters (otherwise it can be "<=") + if ((pos + 1) < entry.size()) + { + clanAbbrev = entry.substr(pos + 1); + } + + entry = entry.substr(0, pos); + } + + BotNames.emplace_back(std::make_pair(entry, clanAbbrev)); } } } @@ -72,14 +89,17 @@ namespace Components if (!BotNames.empty()) { botId %= BotNames.size(); - botName = BotNames[botId++].data(); + const auto index = botId++; + botName = BotNames[index].first.data(); + clanName = BotNames[index].second.data(); } else { botName = Utils::String::VA("bot%d", ++botId); + clanName = "BOT"; } - return _snprintf_s(buffer, 0x400, _TRUNCATE, connectString, num, botName, protocol, checksum, statVer, statStuff, port); + return _snprintf_s(buffer, 0x400, _TRUNCATE, connectString, num, botName, clanName, protocol, checksum, statVer, statStuff, port); } void Bots::Spawn(unsigned int count) @@ -304,7 +324,7 @@ namespace Components AssertOffset(Game::client_t, ping, 0x212C8); // Replace connect string - Utils::Hook::Set(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\""); + Utils::Hook::Set(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\clanAbbrev\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\""); // Intercept sprintf for the connect string Utils::Hook(0x48ADAB, BuildConnectString, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index bc295969..1182f92f 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -8,7 +8,8 @@ namespace Components Bots(); private: - static std::vector BotNames; + using botData = std::pair< std::string, std::string>; + static std::vector BotNames; static int BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port); From 3622946a104144b0ad996278fa2f250019da17c2 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 15 Dec 2022 16:38:50 +0100 Subject: [PATCH 60/96] [Refactor]: Use enum instead of int to catch mistakes (#646) --- src/Components/Modules/Debug.cpp | 2 +- src/Components/Modules/Logger.cpp | 6 +++--- src/Components/Modules/Logger.hpp | 18 +++++++++--------- src/Game/Structs.hpp | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index 1347d95f..14eec5a3 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -304,7 +304,7 @@ namespace Components if (!result) { - Logger::PrintError(1, "CopyFile failed({}) {} {}\n", GetLastError(), "console_mp.log", newFileName); + Logger::PrintError(Game::CON_CHANNEL_ERROR, "CopyFile failed({}) {} {}\n", GetLastError(), "console_mp.log", newFileName); } } diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 4037303c..832bac14 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -70,7 +70,7 @@ namespace Components MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); } - void Logger::PrintInternal(int channel, std::string_view fmt, std::format_args&& args) + void Logger::PrintInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) { const auto msg = std::vformat(fmt, args); @@ -87,7 +87,7 @@ namespace Components Game::Com_Error(error, "%s", msg.data()); } - void Logger::PrintErrorInternal(int channel, std::string_view fmt, std::format_args&& args) + void Logger::PrintErrorInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) { const auto msg = "^1Error: " + std::vformat(fmt, args); @@ -100,7 +100,7 @@ namespace Components } } - void Logger::WarningInternal(int channel, std::string_view fmt, std::format_args&& args) + void Logger::WarningInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) { const auto msg = "^3" + std::vformat(fmt, args); diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 359e473e..ff976a45 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -14,10 +14,10 @@ namespace Components static void PipeOutput(const std::function& callback); - static void PrintInternal(int channel, std::string_view fmt, std::format_args&& args); + static void PrintInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); static void ErrorInternal(Game::errorParm_t error, std::string_view fmt, std::format_args&& args); - static void PrintErrorInternal(int channel, std::string_view fmt, std::format_args&& args); - static void WarningInternal(int channel, std::string_view fmt, std::format_args&& args); + static void PrintErrorInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); + static void WarningInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); static void DebugInternal(std::string_view fmt, std::format_args&& args, const std::source_location& loc); static void Print(std::string_view fmt) @@ -25,7 +25,7 @@ namespace Components PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(0)); } - static void Print(int channel, std::string_view fmt) + static void Print(Game::conChannel_t channel, std::string_view fmt) { PrintInternal(channel, fmt, std::make_format_args(0)); } @@ -38,7 +38,7 @@ namespace Components } template - static void Print(int channel, std::string_view fmt, Args&&... args) + static void Print(Game::conChannel_t channel, std::string_view fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); PrintInternal(channel, fmt, std::make_format_args(args...)); @@ -56,25 +56,25 @@ namespace Components ErrorInternal(error, fmt, std::make_format_args(args...)); } - static void Warning(int channel, std::string_view fmt) + static void Warning(Game::conChannel_t channel, std::string_view fmt) { WarningInternal(channel, fmt, std::make_format_args(0)); } template - static void Warning(int channel, std::string_view fmt, Args&&... args) + static void Warning(Game::conChannel_t channel, std::string_view fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); WarningInternal(channel, fmt, std::make_format_args(args...)); } - static void PrintError(int channel, std::string_view fmt) + static void PrintError(Game::conChannel_t channel, std::string_view fmt) { PrintErrorInternal(channel, fmt, std::make_format_args(0)); } template - static void PrintError(int channel, std::string_view fmt, Args&&... args) + static void PrintError(Game::conChannel_t channel, std::string_view fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); PrintErrorInternal(channel, fmt, std::make_format_args(args...)); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 41b050e1..09ffb489 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -9239,7 +9239,7 @@ namespace Game char* openScriptIOFileBuffers[1]; com_parse_mark_t currentScriptIOLineMark[1]; cached_tag_mat_t cachedTagMat; - int scriptPrintChannel; + conChannel_t scriptPrintChannel; float compassMapUpperLeft[2]; float compassMapWorldSize[2]; float compassNorth[2]; From b4750b14b12460fa81e4f807374081313d5cae2a Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 15 Dec 2022 17:10:25 +0100 Subject: [PATCH 61/96] [Dvar]: Remove cheat protection from useful dvar (#647) --- src/Components/Modules/Dvar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index ebffebd1..dd96d737 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -396,6 +396,9 @@ namespace Components // un-cheat cg_debugInfoCornerOffset and add archive flags Utils::Hook::Xor(0x4F8FC2, Game::DVAR_CHEAT | Game::DVAR_ARCHIVE); + // un-cheat cg_drawGun + Utils::Hook::Set(0x4F8DC6, Game::DVAR_NONE); + // remove archive flags for cg_hudchatposition Utils::Hook::Xor(0x4F9992, Game::DVAR_ARCHIVE); From 64c759e2f3bb862174f10fa989b7b7e42a3c010c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:02:58 +0000 Subject: [PATCH 62/96] Bump deps/GSL from `517ed29` to `6c6111a` Bumps [deps/GSL](https://github.com/microsoft/GSL) from `517ed29` to `6c6111a`. - [Release notes](https://github.com/microsoft/GSL/releases) - [Commits](https://github.com/microsoft/GSL/compare/517ed29228d18cf2c5004d10826090108e06f049...6c6111acb7b5d687ac006969ac96e5b1f21374cd) --- updated-dependencies: - dependency-name: deps/GSL dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/GSL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/GSL b/deps/GSL index 517ed292..6c6111ac 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit 517ed29228d18cf2c5004d10826090108e06f049 +Subproject commit 6c6111acb7b5d687ac006969ac96e5b1f21374cd From 7a3a5ac671d7fb61d034e66e2930eaeca213ed04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:03:10 +0000 Subject: [PATCH 63/96] Bump deps/protobuf from `7ef0c27` to `fb257cd` Bumps [deps/protobuf](https://github.com/google/protobuf) from `7ef0c27` to `fb257cd`. - [Release notes](https://github.com/google/protobuf/releases) - [Commits](https://github.com/google/protobuf/compare/7ef0c27900b1c77e592c514677eefe2636691e3c...fb257cd23bab8455a26c91a0c8654e8c05d6c736) --- updated-dependencies: - dependency-name: deps/protobuf dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/protobuf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/protobuf b/deps/protobuf index 7ef0c279..fb257cd2 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 7ef0c27900b1c77e592c514677eefe2636691e3c +Subproject commit fb257cd23bab8455a26c91a0c8654e8c05d6c736 From 3cdd4d0636b3a99cac626c3ffbbced5d632152d8 Mon Sep 17 00:00:00 2001 From: Louve <33836535+Rackover@users.noreply.github.com> Date: Fri, 16 Dec 2022 15:55:50 +0100 Subject: [PATCH 64/96] Draw model name in its ground color if relevant (#651) Co-authored-by: Diavolo --- src/Components/Modules/Renderer.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 71541cad..853e1d78 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -440,7 +440,15 @@ namespace Components const auto dist = Utils::Maths::Vec3SqrDistance(playerPosition, staticModel.placement.origin); if (dist < static_cast(sqrDist)) { - Game::R_AddDebugString(staticModelsColor, staticModel.placement.origin, 1.0, staticModel.model->name); + float rgb01Color[] = + { + staticModel.groundLighting.array[0] / 255.f, + staticModel.groundLighting.array[1] / 255.f, + staticModel.groundLighting.array[2] / 255.f, + 1.f, + }; + + Game::R_AddDebugString(staticModel.flags & 0x20 ? rgb01Color : staticModelsColor, staticModel.placement.origin, 1.0f, staticModel.model->name); } } } From fc64f01602096911c438ff1dec370e28b93592b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Dec 2022 17:07:09 +0000 Subject: [PATCH 65/96] Bump deps/protobuf from `fb257cd` to `7ce9c41` Bumps [deps/protobuf](https://github.com/google/protobuf) from `fb257cd` to `7ce9c41`. - [Release notes](https://github.com/google/protobuf/releases) - [Commits](https://github.com/google/protobuf/compare/fb257cd23bab8455a26c91a0c8654e8c05d6c736...7ce9c415455c098409222702b3b4572b47232882) --- updated-dependencies: - dependency-name: deps/protobuf dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/protobuf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/protobuf b/deps/protobuf index fb257cd2..7ce9c415 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit fb257cd23bab8455a26c91a0c8654e8c05d6c736 +Subproject commit 7ce9c415455c098409222702b3b4572b47232882 From a89abf45b670159ead54d83e709890bd40474b5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Dec 2022 17:07:11 +0000 Subject: [PATCH 66/96] Bump deps/zlib from `04f42ce` to `e554695` Bumps [deps/zlib](https://github.com/madler/zlib) from `04f42ce` to `e554695`. - [Release notes](https://github.com/madler/zlib/releases) - [Commits](https://github.com/madler/zlib/compare/04f42ceca40f73e2978b50e93806c2a18c1281fc...e554695638228b846d49657f31eeff0ca4680e8a) --- updated-dependencies: - dependency-name: deps/zlib dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/zlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zlib b/deps/zlib index 04f42cec..e5546956 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit 04f42ceca40f73e2978b50e93806c2a18c1281fc +Subproject commit e554695638228b846d49657f31eeff0ca4680e8a From fdd02e2b8dc153010dca24157f8f5da1490afad1 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Fri, 16 Dec 2022 22:48:52 +0100 Subject: [PATCH 67/96] [RCon]: Tidy up code --- src/Components/Modules/RCon.cpp | 47 +++++++++++++++++++++++++++++++++ src/Components/Modules/RCon.hpp | 5 ++++ 2 files changed, 52 insertions(+) diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index b7c0ab20..6bcd6f8c 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -2,6 +2,8 @@ namespace Components { + std::unordered_map RCon::RateLimit; + RCon::Container RCon::RconContainer; Utils::Cryptography::ECC::Key RCon::RconKey; @@ -71,6 +73,43 @@ namespace Components }); } + bool RCon::RateLimitCheck(const Network::Address& address, const int time) + { + auto ip = address.getIP(); + + if (!RateLimit.contains(ip.full)) + { + RateLimit[ip.full] = 0; + } + + const auto lastTime = RateLimit[ip.full]; + + // Only one request every 500ms + if (lastTime && (time - lastTime) < 500) + { + return false; // Flooding + } + + RateLimit[ip.full] = time; + return true; + } + + void RCon::RateLimitCleanup(const int time) + { + for (auto i = RateLimit.begin(); i != RateLimit.end();) + { + // No longer at risk of flooding, remove + if ((time - i->second) > 500) + { + i = RateLimit.erase(i); + } + else + { + ++i; + } + } + } + RCon::RCon() { AddCommands(); @@ -126,6 +165,14 @@ namespace Components Network::OnClientPacket("rcon", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { + const auto time = Game::Sys_Milliseconds(); + if (!RateLimitCheck(address, time)) + { + return; + } + + RateLimitCleanup(time); + std::string data_ = data; Utils::String::Trim(data_); diff --git a/src/Components/Modules/RCon.hpp b/src/Components/Modules/RCon.hpp index 78b07dea..22c8cfc0 100644 --- a/src/Components/Modules/RCon.hpp +++ b/src/Components/Modules/RCon.hpp @@ -29,6 +29,8 @@ namespace Components static Utils::Cryptography::ECC::Key GetKeyInternal(); }; + static std::unordered_map RateLimit; + static Container RconContainer; static Utils::Cryptography::ECC::Key RconKey; @@ -38,5 +40,8 @@ namespace Components static Dvar::Var RconLogRequests; static void AddCommands(); + + static bool RateLimitCheck(const Network::Address& address, int time); + static void RateLimitCleanup(int time); }; } From 54aabee08d15e418f52f96de0ccebf9799f34330 Mon Sep 17 00:00:00 2001 From: Louve <33836535+Rackover@users.noreply.github.com> Date: Sat, 17 Dec 2022 16:52:00 +0100 Subject: [PATCH 68/96] =?UTF-8?q?Fix=20zonebuilder=20FindAsset=20always=20?= =?UTF-8?q?returning=20-1=20(not=20found)=20even=20when=20t=E2=80=A6=20(#6?= =?UTF-8?q?55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Louvenarde Co-authored-by: Edo --- src/Components/Modules/ZoneBuilder.cpp | 12 ++++++------ src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 88220c49..ed38193c 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -46,7 +46,7 @@ namespace Components if (!found) { - Logger::Print("Asset {} of type {} was loaded, but not written!", name, Game::DB_GetXAssetTypeName(subAsset.type)); + Logger::Print("Asset {} of type {} was loaded, but not written!\n", name, Game::DB_GetXAssetTypeName(subAsset.type)); } } @@ -66,17 +66,18 @@ namespace Components if (!found) { - Logger::Error(Game::ERR_FATAL, "Asset {} of type {} was written, but not loaded!", name, Game::DB_GetXAssetTypeName(alias.first.type)); + Logger::Error(Game::ERR_FATAL, "Asset {} of type {} was written, but not loaded!\n", name, Game::DB_GetXAssetTypeName(alias.first.type)); } } #endif // Unload our fastfiles - Game::XZoneInfo info; + Game::XZoneInfo info{}; info.name = nullptr; info.allocFlags = 0; info.freeFlags = 0x20; + Game::DB_LoadXAssets(&info, 1, true); AssetHandler::ClearTemporaryAssets(); @@ -277,7 +278,6 @@ namespace Components const auto* assetName = Game::DB_GetXAssetName(asset); if (!assetName) return -1; if (assetName[0] == ',' && assetName[1] != '\0') ++assetName; - else return -1; if (this->getAssetName(type, assetName) == name) { @@ -1007,11 +1007,11 @@ namespace Components assert(data); auto* sound = Utils::Hook::Get(0x112AE04); auto length = sound->info.data_len; - auto allocatedSpace = Utils::Memory::AllocateArray(length); + auto allocatedSpace = Game::Z_Malloc(length); memcpy_s(allocatedSpace, length, data, length); data = allocatedSpace; - sound->data = allocatedSpace; + sound->data = static_cast(allocatedSpace); sound->info.data_ptr = allocatedSpace; } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index e8bf6e6a..6444eff5 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -253,6 +253,7 @@ namespace Game Vec2NormalizeFast_t Vec2NormalizeFast = Vec2NormalizeFast_t(0x5FC830); Z_VirtualAlloc_t Z_VirtualAlloc = Z_VirtualAlloc_t(0x4CFBA0); + Z_Malloc_t Z_Malloc = Z_Malloc_t(0x4F3680); I_strncpyz_t I_strncpyz = I_strncpyz_t(0x4D6F80); I_CleanStr_t I_CleanStr = I_CleanStr_t(0x4AD470); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2834a2e0..29750448 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -563,6 +563,9 @@ namespace Game typedef void*(*Z_VirtualAlloc_t)(int size); extern Z_VirtualAlloc_t Z_VirtualAlloc; + typedef void*(*Z_Malloc_t)(int size); + extern Z_Malloc_t Z_Malloc; + typedef void(*I_strncpyz_t)(char* dest, const char* src, int destsize); extern I_strncpyz_t I_strncpyz; From 24ccd9af3b4b4d96988bdf0739badd28912f199a Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 17 Dec 2022 18:54:41 +0100 Subject: [PATCH 69/96] [String]: Use ARRAY_COUNT (#656) --- src/Components/Modules/Download.cpp | 2 +- src/Components/Modules/Scheduler.cpp | 2 +- src/Components/Modules/Threading.cpp | 3 +++ src/Game/Structs.hpp | 26 ++++++++++++++++++++++++++ src/Utils/String.hpp | 5 ++++- src/Utils/Thread.cpp | 28 ++++++++++++++-------------- src/Utils/Thread.hpp | 20 ++++++++++---------- 7 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 16c324d4..285503a3 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -688,7 +688,7 @@ namespace Components ServerRunning = true; Terminate = false; - ServerThread = std::thread([] + ServerThread = Utils::Thread::CreateNamedThread("Mongoose", [] { while (!Terminate) { diff --git a/src/Components/Modules/Scheduler.cpp b/src/Components/Modules/Scheduler.cpp index bc29402e..48246130 100644 --- a/src/Components/Modules/Scheduler.cpp +++ b/src/Components/Modules/Scheduler.cpp @@ -156,7 +156,7 @@ namespace Components Scheduler::Scheduler() { - Thread = Utils::Thread::createNamedThread("Async Scheduler", [] + Thread = Utils::Thread::CreateNamedThread("Async Scheduler", [] { while (!Kill) { diff --git a/src/Components/Modules/Threading.cpp b/src/Components/Modules/Threading.cpp index f22315a7..9382a1f9 100644 --- a/src/Components/Modules/Threading.cpp +++ b/src/Components/Modules/Threading.cpp @@ -154,6 +154,9 @@ namespace Components // dvar setting function, unknown stuff related to server thread sync Utils::Hook::Set(0x647781, 0xEB); + // make VA thread safe + Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick(); + Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick(); Utils::Hook(0x43D1C7, PacketEventStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x6272E3, FrameEpilogueStub, HOOK_JUMP).install()->quick(); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 09ffb489..a8be593b 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -10307,6 +10307,32 @@ namespace Game GfxLight sceneLights[253]; }; + enum + { + THREAD_VALUE_PROF_STACK = 0x0, + THREAD_VALUE_VA = 0x1, + THREAD_VALUE_COM_ERROR = 0x2, + THREAD_VALUE_TRACE = 0x3, + THREAD_VALUE_COUNT = 0x4, + }; + + struct va_info_t + { + char va_string[2][1024]; + int index; + }; + + struct TraceCheckCount + { + int global; + int* partitions; + }; + + struct TraceThreadInfo + { + TraceCheckCount checkcount; + }; + #pragma endregion #ifndef IDA diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index 242ea0d9..88856d75 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -1,5 +1,8 @@ #pragma once +template +constexpr auto ARRAY_COUNT(Type(&)[n]) { return n; } + namespace Utils::String { template @@ -13,7 +16,7 @@ namespace Utils::String [[nodiscard]] const char* get(const char* format, va_list ap) { - ++this->currentBuffer %= ARRAYSIZE(this->stringPool); + ++this->currentBuffer %= ARRAY_COUNT(this->stringPool); auto entry = &this->stringPool[this->currentBuffer]; if (!entry->size || !entry->buffer) diff --git a/src/Utils/Thread.cpp b/src/Utils/Thread.cpp index e328ff30..c6e5423c 100644 --- a/src/Utils/Thread.cpp +++ b/src/Utils/Thread.cpp @@ -2,7 +2,7 @@ namespace Utils::Thread { - bool setName(const HANDLE t, const std::string& name) + bool SetName(const HANDLE t, const std::string& name) { const Library kernel32("kernel32.dll"); if (!kernel32) @@ -19,7 +19,7 @@ namespace Utils::Thread return SUCCEEDED(setDescription(t, String::Convert(name).data())); } - bool setName(const DWORD id, const std::string& name) + bool SetName(const DWORD id, const std::string& name) { auto* const t = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, id); if (!t) return false; @@ -29,20 +29,20 @@ namespace Utils::Thread CloseHandle(t); }); - return setName(t, name); + return SetName(t, name); } - bool setName(std::thread& t, const std::string& name) + bool SetName(std::thread& t, const std::string& name) { - return setName(t.native_handle(), name); + return SetName(t.native_handle(), name); } - bool setName(const std::string& name) + bool SetName(const std::string& name) { - return setName(GetCurrentThread(), name); + return SetName(GetCurrentThread(), name); } - std::vector getThreadIds() + std::vector GetThreadIds() { auto* const h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId()); if (h == INVALID_HANDLE_VALUE) @@ -79,9 +79,9 @@ namespace Utils::Thread return ids; } - void forEachThread(const std::function& callback) + void ForEachThread(const std::function& callback) { - const auto ids = getThreadIds(); + const auto ids = GetThreadIds(); for (const auto& id : ids) { @@ -98,9 +98,9 @@ namespace Utils::Thread } } - void suspendOtherThreads() + void SuspendOtherThreads() { - forEachThread([](const HANDLE thread) + ForEachThread([](const HANDLE thread) { if (GetThreadId(thread) != GetCurrentThreadId()) { @@ -109,9 +109,9 @@ namespace Utils::Thread }); } - void resumeOtherThreads() + void ResumeOtherThreads() { - forEachThread([](const HANDLE thread) + ForEachThread([](const HANDLE thread) { if (GetThreadId(thread) != GetCurrentThreadId()) { diff --git a/src/Utils/Thread.hpp b/src/Utils/Thread.hpp index 807633f4..084eb2ce 100644 --- a/src/Utils/Thread.hpp +++ b/src/Utils/Thread.hpp @@ -2,22 +2,22 @@ namespace Utils::Thread { - bool setName(HANDLE t, const std::string& name); - bool setName(DWORD id, const std::string& name); - bool setName(std::thread& t, const std::string& name); - bool setName(const std::string& name); + bool SetName(HANDLE t, const std::string& name); + bool SetName(DWORD id, const std::string& name); + bool SetName(std::thread& t, const std::string& name); + bool SetName(const std::string& name); template - std::thread createNamedThread(const std::string& name, Args&&... args) + std::thread CreateNamedThread(const std::string& name, Args&&... args) { auto t = std::thread(std::forward(args)...); - setName(t, name); + SetName(t, name); return t; } - std::vector getThreadIds(); - void forEachThread(const std::function& callback); + std::vector GetThreadIds(); + void ForEachThread(const std::function& callback); - void suspendOtherThreads(); - void resumeOtherThreads(); + void SuspendOtherThreads(); + void ResumeOtherThreads(); } From d8166a4166b6ab4883407afd07e1e00bf787f780 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 18 Dec 2022 22:47:59 +0100 Subject: [PATCH 70/96] [Threading]: Initialize tls stuff, making va thread safe (#657) --- src/Components/Modules/ClientCommand.cpp | 21 ++-- src/Components/Modules/Discovery.cpp | 41 +++---- src/Components/Modules/Discovery.hpp | 3 + src/Components/Modules/Download.cpp | 15 ++- src/Components/Modules/News.cpp | 32 +++--- src/Components/Modules/Threading.cpp | 3 - src/Components/Modules/ZoneBuilder.cpp | 132 +++++++++++------------ src/Components/Modules/ZoneBuilder.hpp | 8 +- src/Game/Common.hpp | 16 +++ src/Game/Functions.cpp | 5 +- src/Game/Functions.hpp | 7 +- src/Game/Structs.hpp | 53 +++++++++ src/Game/System.cpp | 1 + src/Game/System.hpp | 22 +++- 14 files changed, 230 insertions(+), 129 deletions(-) diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index 0cddc918..07fdbba1 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -246,13 +246,20 @@ namespace Components if (ent->client->sess.sessionState != Game::SESS_STATE_PLAYING || !CheatsOk(ent)) return; - Scheduler::Once([ent] - { - ent->flags &= ~(Game::FL_GODMODE | Game::FL_DEMI_GODMODE); - ent->health = 0; - ent->client->ps.stats[0] = 0; - Game::player_die(ent, ent, ent, 100000, Game::MOD_SUICIDE, 0, nullptr, Game::HITLOC_NONE, 0); - }, Scheduler::Pipeline::SERVER); + auto** bgs = Game::Sys::GetTls(Game::Sys::ThreadOffset::LEVEL_BGS); + + assert(*bgs == nullptr); + + *bgs = Game::level_bgs; + + ent->flags &= ~(Game::FL_GODMODE | Game::FL_DEMI_GODMODE); + ent->health = 0; + ent->client->ps.stats[0] = 0; + Game::player_die(ent, ent, ent, 100000, Game::MOD_SUICIDE, 0, nullptr, Game::HITLOC_NONE, 0); + + assert(*bgs == Game::level_bgs); + + *bgs = nullptr; }); } diff --git a/src/Components/Modules/Discovery.cpp b/src/Components/Modules/Discovery.cpp index 3545ab07..14737a18 100644 --- a/src/Components/Modules/Discovery.cpp +++ b/src/Components/Modules/Discovery.cpp @@ -7,39 +7,42 @@ namespace Components std::thread Discovery::Thread; std::string Discovery::Challenge; + Dvar::Var Discovery::NetDiscoveryPortRangeMin; + Dvar::Var Discovery::NetDiscoveryPortRangeMax; + void Discovery::Perform() { - Discovery::IsPerforming = true; + IsPerforming = true; } Discovery::Discovery() { - Dvar::Register("net_discoveryPortRangeMin", 25000, 0, 65535, Game::DVAR_ARCHIVE, "Minimum scan range port for local server discovery"); - Dvar::Register("net_discoveryPortRangeMax", 35000, 1, 65536, Game::DVAR_ARCHIVE, "Maximum scan range port for local server discovery"); + NetDiscoveryPortRangeMin = Dvar::Register("net_discoveryPortRangeMin", 25000, 0, 65535, Game::DVAR_NONE, "Minimum scan range port for local server discovery"); + NetDiscoveryPortRangeMax = Dvar::Register("net_discoveryPortRangeMax", 35000, 1, 65536, Game::DVAR_NONE, "Maximum scan range port for local server discovery"); // An additional thread prevents lags // Not sure if that's the best way though - Discovery::IsPerforming = false; - Discovery::IsTerminating = false; - Discovery::Thread = std::thread([]() + IsPerforming = false; + IsTerminating = false; + Thread = std::thread([] { - while (!Discovery::IsTerminating) + while (!IsTerminating) { - if (Discovery::IsPerforming) + if (IsPerforming) { - int start = Game::Sys_Milliseconds(); + const auto start = Game::Sys_Milliseconds(); Logger::Print("Starting local server discovery...\n"); - Discovery::Challenge = Utils::Cryptography::Rand::GenerateChallenge(); + Challenge = Utils::Cryptography::Rand::GenerateChallenge(); - unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").get(); - unsigned int maxPort = Dvar::Var("net_discoveryPortRangeMax").get(); - Network::BroadcastRange(minPort, maxPort, Utils::String::VA("discovery %s", Discovery::Challenge.data())); + const auto minPort = NetDiscoveryPortRangeMin.get(); + const auto maxPort = NetDiscoveryPortRangeMax.get(); + Network::BroadcastRange(minPort, maxPort, std::format("discovery {}", Challenge)); Logger::Print("Discovery sent within {}ms, awaiting responses...\n", Game::Sys_Milliseconds() - start); - Discovery::IsPerforming = false; + IsPerforming = false; } std::this_thread::sleep_for(50ms); @@ -70,7 +73,7 @@ namespace Components return; } - if (Utils::ParseChallenge(data) != Discovery::Challenge) + if (Utils::ParseChallenge(data) != Challenge) { Logger::Print("Received discovery with invalid challenge from: {}\n", address.getString()); return; @@ -87,12 +90,12 @@ namespace Components void Discovery::preDestroy() { - Discovery::IsPerforming = false; - Discovery::IsTerminating = true; + IsPerforming = false; + IsTerminating = true; - if (Discovery::Thread.joinable()) + if (Thread.joinable()) { - Discovery::Thread.join(); + Thread.join(); } } } diff --git a/src/Components/Modules/Discovery.hpp b/src/Components/Modules/Discovery.hpp index 63f69b1b..2c00d284 100644 --- a/src/Components/Modules/Discovery.hpp +++ b/src/Components/Modules/Discovery.hpp @@ -16,5 +16,8 @@ namespace Components static bool IsPerforming; static std::thread Thread; static std::string Challenge; + + static Dvar::Var NetDiscoveryPortRangeMin; + static Dvar::Var NetDiscoveryPortRangeMax; }; } diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 285503a3..ecccc77d 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -232,11 +232,11 @@ namespace Components { if (!download) download = &CLDownload; - auto host = "http://" + download->target.getString(); + const auto host = "http://" + download->target.getString(); - auto listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); + const auto listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); - auto list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get(); + const auto list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get(); if (list.empty()) { if (download->terminateThread) return; @@ -276,7 +276,7 @@ namespace Components static std::string mod; mod = download->mod; - for (unsigned int i = 0; i < download->files.size(); ++i) + for (std::size_t i = 0; i < download->files.size(); ++i) { if (download->terminateThread) return; @@ -319,7 +319,6 @@ namespace Components Scheduler::Once([] { Game::Dvar_SetString(*Game::fs_gameDirVar, mod.data()); - const_cast(*Game::fs_gameDirVar)->modified = true; mod.clear(); @@ -673,6 +672,10 @@ namespace Components Download::Download() { + AssertSize(Game::va_info_t, 0x804); + AssertSize(jmp_buf, 0x40); + AssertSize(Game::TraceThreadInfo, 0x8); + if (Dedicated::IsEnabled()) { mg_mgr_init(&Mgr); @@ -690,6 +693,8 @@ namespace Components Terminate = false; ServerThread = Utils::Thread::CreateNamedThread("Mongoose", [] { + Com_InitThreadData(); + while (!Terminate) { mg_mgr_poll(&Mgr, 100); diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 1ec06436..3b839cc8 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -13,12 +13,12 @@ namespace Components { bool result = true; - if (News::Thread.joinable()) + if (Thread.joinable()) { Logger::Debug("Awaiting thread termination..."); - News::Thread.join(); + Thread.join(); - if (!strcmp(Localization::Get("MPUI_MOTD_TEXT"), NEWS_MOTD_DEFAULT)) + if (!std::strcmp(Localization::Get("MPUI_MOTD_TEXT"), NEWS_MOTD_DEFAULT)) { Logger::Print("Failed to fetch motd!\n"); result = false; @@ -43,14 +43,12 @@ namespace Components Dvar::Register("g_firstLaunch", true, Game::DVAR_ARCHIVE, ""); - Dvar::Register("cl_updateoldversion", REVISION, REVISION, REVISION, Game::DVAR_INIT, "Current version number."); - UIScript::Add("checkFirstLaunch", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { if (Dvar::Var("g_firstLaunch").get()) { Command::Execute("openmenu menu_first_launch", false); - //Dvar::Var("g_firstLaunch").set(false); + //Dvar::Var("g_firstLaunch").set(false); // The menus should set it } }); @@ -67,15 +65,15 @@ namespace Components // hook for getting the news ticker string Utils::Hook::Nop(0x6388BB, 2); // skip the "if (item->text[0] == '@')" localize check - Utils::Hook(0x6388C1, News::GetNewsText, HOOK_CALL).install()->quick(); + Utils::Hook(0x6388C1, GetNewsText, HOOK_CALL).install()->quick(); if (!Utils::IsWineEnvironment() && !Loader::IsPerformingUnitTests()) { - News::Terminate = false; - News::Thread = std::thread([]() + Terminate = false; + Thread = std::thread([]() { Changelog::LoadChangelog(); - if (News::Terminate) return; + if (Terminate) return; std::string data = Utils::Cache::GetFile("/iw4/motd.txt"); if (!data.empty()) @@ -83,12 +81,12 @@ namespace Components Localization::Set("MPUI_MOTD_TEXT", data); } - if (!Loader::IsPerformingUnitTests() && !News::Terminate) + if (!Loader::IsPerformingUnitTests() && !Terminate) { - while (!News::Terminate) + while (!Terminate) { // Sleep for 3 minutes - for (int i = 0; i < 180 && !News::Terminate; ++i) + for (int i = 0; i < 180 && !Terminate; ++i) { std::this_thread::sleep_for(1s); } @@ -100,13 +98,11 @@ namespace Components void News::preDestroy() { - News::Terminate = true; + Terminate = true; - if (News::Thread.joinable()) + if (Thread.joinable()) { - News::Thread.join(); + Thread.join(); } - - News::Thread = std::thread(); } } diff --git a/src/Components/Modules/Threading.cpp b/src/Components/Modules/Threading.cpp index 9382a1f9..f22315a7 100644 --- a/src/Components/Modules/Threading.cpp +++ b/src/Components/Modules/Threading.cpp @@ -154,9 +154,6 @@ namespace Components // dvar setting function, unknown stuff related to server thread sync Utils::Hook::Set(0x647781, 0xEB); - // make VA thread safe - Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick(); - Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick(); Utils::Hook(0x43D1C7, PacketEventStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x6272E3, FrameEpilogueStub, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index ed38193c..325495f3 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -11,7 +11,8 @@ namespace Components bool ZoneBuilder::MainThreadInterrupted; DWORD ZoneBuilder::InterruptingThreadId; - volatile bool ZoneBuilder::Terminate = false; + + volatile bool ZoneBuilder::CommandThreadTerminate = false; std::thread ZoneBuilder::CommandThread; Dvar::Var ZoneBuilder::PreferDiskAssetsDvar; @@ -120,7 +121,7 @@ namespace Components this->writeZone(); } - void ZoneBuilder::Zone::loadFastFiles() + void ZoneBuilder::Zone::loadFastFiles() const { Logger::Print("Loading required FastFiles...\n"); @@ -793,7 +794,8 @@ namespace Components return GetCurrentThreadId() == Utils::Hook::Get(0x1CDE7FC); } - static Game::XZoneInfo baseZones_old[] = { + static Game::XZoneInfo baseZones_old[] = + { { "code_pre_gfx_mp", Game::DB_ZONE_CODE, 0 }, { "localized_code_pre_gfx_mp", Game::DB_ZONE_CODE_LOC, 0 }, { "code_post_gfx_mp", Game::DB_ZONE_CODE, 0 }, @@ -805,7 +807,8 @@ namespace Components }; - static Game::XZoneInfo baseZones[] = { + static Game::XZoneInfo baseZones[] = + { { "defaults", Game::DB_ZONE_CODE, 0 }, { "techsets", Game::DB_ZONE_CODE, 0 }, { "common_mp", Game::DB_ZONE_COMMON, 0 }, @@ -819,50 +822,55 @@ namespace Components ExitProcess(0); } - int APIENTRY ZoneBuilder::EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/) + void ZoneBuilder::CommandThreadCallback() { - Utils::Hook::Call(0x42F0A0)(); // Com_InitCriticalSections - Utils::Hook::Call(0x4301B0)(); // Com_InitMainThread - Utils::Hook::Call(0x406D10)(0); // Win_InitLocalization - Utils::Hook::Call(0x4FF220)(); // Com_InitParse - Utils::Hook::Call(0x4D8220)(); // Dvar_Init - Utils::Hook::Call(0x4D2280)(); // SL_Init - Utils::Hook::Call(0x48F660)(); // Cmd_Init - Utils::Hook::Call(0x4D9210)(); // Cbuf_Init - Utils::Hook::Call(0x47F390)(); // Swap_Init - Utils::Hook::Call(0x60AD10)(); // Com_InitDvars - Utils::Hook::Call(0x420830)(); // Com_InitHunkMemory - Utils::Hook::Call(0x4A62A0)(); // LargeLocalInit - Utils::Hook::Call(0x4DCC10)(); // Sys_InitCmdEvents - Utils::Hook::Call(0x64A020)(); // PMem_Init + Com_InitThreadData(); + + while (!ZoneBuilder::CommandThreadTerminate) + { + ZoneBuilder::AssumeMainThreadRole(); + Utils::Hook::Call(0x4E2C80)(0, 0); // Cbuf_Execute + ZoneBuilder::ResetThreadRole(); + std::this_thread::sleep_for(1ms); + } + } + + BOOL APIENTRY ZoneBuilder::EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/) + { + Utils::Hook::Call(0x42F0A0)(); // Com_InitCriticalSections + Utils::Hook::Call(0x4301B0)(); // Com_InitMainThread + Utils::Hook::Call(0x406D10)(0); // Win_InitLocalization + Utils::Hook::Call(0x4FF220)(); // Com_InitParse + Utils::Hook::Call(0x4D8220)(); // Dvar_Init + Utils::Hook::Call(0x4D2280)(); // SL_Init + Utils::Hook::Call(0x48F660)(); // Cmd_Init + Utils::Hook::Call(0x4D9210)(); // Cbuf_Init + Utils::Hook::Call(0x47F390)(); // Swap_Init + Utils::Hook::Call(0x60AD10)(); // Com_InitDvars + Utils::Hook::Call(0x420830)(); // Com_InitHunkMemory + Utils::Hook::Call(0x4A62A0)(); // LargeLocalInit + Utils::Hook::Call(0x4DCC10)(); // Sys_InitCmdEvents + Utils::Hook::Call(0x64A020)(); // PMem_Init + if (!Flags::HasFlag("stdout")) { Console::ShowAsyncConsole(); Utils::Hook::Call(0x43D140)(); // Com_EventLoop } + + Utils::Hook::Call(0x502580)(static_cast(__rdtsc())); // Netchan_Init - Utils::Hook::Call(0x429080)(); // FS_InitFileSystem - Utils::Hook::Call(0x4BFBE0)(); // Con_InitChannels - Utils::Hook::Call(0x4E0FB0)(); // DB_InitThread - Utils::Hook::Call(0x5196C0)(); // R_RegisterDvars + Utils::Hook::Call(0x429080)(); // FS_InitFileSystem + Utils::Hook::Call(0x4BFBE0)(); // Con_InitChannels + Utils::Hook::Call(0x4E0FB0)(); // DB_InitThread + Utils::Hook::Call(0x5196C0)(); // R_RegisterDvars Game::NET_Init(); - Utils::Hook::Call(0x4F5090)(); // SND_InitDriver - Utils::Hook::Call(0x46A630)(); // SND_Init - //Utils::Hook::Call(0x4D3660)(); // SV_Init - //Utils::Hook::Call(0x4121E0)(); // SV_InitServerThread - //Utils::Hook::Call(0x464A90)(); // Com_ParseCommandLine + Utils::Hook::Call(0x4F5090)(); // SND_InitDriver + Utils::Hook::Call(0x46A630)(); // SND_Init Utils::Hook::Call(0x43D140)(); // Com_EventLoop - ZoneBuilder::CommandThread = std::thread([] - { - while (!ZoneBuilder::Terminate) - { - ZoneBuilder::AssumeMainThreadRole(); - Utils::Hook::Call(0x4E2C80)(0, 0); // Cbuf_Execute - ZoneBuilder::ResetThreadRole(); - std::this_thread::sleep_for(1ms); - } - }); + ZoneBuilder::CommandThread = Utils::Thread::CreateNamedThread("Command Thread", ZoneBuilder::CommandThreadCallback); + ZoneBuilder::CommandThread.detach(); Command::Add("quit", ZoneBuilder::Com_Quitf_t); @@ -873,8 +881,7 @@ namespace Components } else { - Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, - "Missing new init zones (defaults.ff & techsets.ff). You will need to load fastfiles to manually obtain techsets.\n"); + Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Missing new init zones (defaults.ff & techsets.ff). You will need to load fastfiles to manually obtain techsets.\n"); Game::DB_LoadXAssets(baseZones_old, ARRAYSIZE(baseZones_old), 0); } @@ -908,7 +915,7 @@ namespace Components } Logger::Print(" --------------------------------------------------------------------------------\n"); - Logger::Print(" IW4x ZoneBuilder (" VERSION ")\n"); + Logger::Print(" IW4x ZoneBuilder ({})\n", VERSION); Logger::Print(" Commands:\n"); Logger::Print("\t-buildzone [zone]: builds a zone from a csv located in zone_source\n"); Logger::Print("\t-buildall: builds all zones in zone_source\n"); @@ -1006,8 +1013,8 @@ namespace Components { assert(data); auto* sound = Utils::Hook::Get(0x112AE04); - auto length = sound->info.data_len; - auto allocatedSpace = Game::Z_Malloc(length); + const auto length = sound->info.data_len; + const auto allocatedSpace = Game::Z_Malloc(static_cast(length)); memcpy_s(allocatedSpace, length, data, length); data = allocatedSpace; @@ -1022,8 +1029,6 @@ namespace Components AssertSize(Game::XFile, 40); static_assert(Game::MAX_XFILE_COUNT == 8, "XFile block enum is invalid!"); - ZoneBuilder::EndAssetTrace(); - if (ZoneBuilder::IsEnabled()) { // Prevent loading textures (preserves loaddef) @@ -1035,10 +1040,10 @@ namespace Components // Release the loaddef Game::DB_ReleaseXAssetHandlers[Game::XAssetType::ASSET_TYPE_IMAGE] = ZoneBuilder::ReleaseTexture; - //r_loadForrenderer = 0 + // r_loadForrenderer = 0 Utils::Hook::Set(0x519DDF, 0); - //r_delayloadimage retn + // r_delayloadimage ret Utils::Hook::Set(0x51F450, 0xC3); // r_registerDvars hack @@ -1056,7 +1061,7 @@ namespace Components // Don't mark assets //Utils::Hook::Nop(0x5BB632, 5); - // Don't load sounds + // Load sounds Utils::Hook(0x492EFC, ReallocateLoadedSounds, HOOK_CALL).install()->quick(); // Don't display errors when assets are missing (we might manually build those) @@ -1092,14 +1097,14 @@ namespace Components Utils::Hook::Set(0x64A029, 0x38400000); // 900 MiB Utils::Hook::Set(0x64A057, 0x38400000); - // change fs_game domain func + // change FS_GameDirDomainFunc Utils::Hook::Set(0x643203, [](Game::dvar_t* dvar, Game::DvarValue value) { int result = Utils::Hook::Call(0x642FC0)(dvar, value); if (result) { - if (std::string(value.string) != dvar->current.string) + if (std::strcmp(value.string, dvar->current.string) != 0) { dvar->current.string = value.string; Game::FS_Restart(0, 0); @@ -1118,7 +1123,7 @@ namespace Components // handle Com_error Calls Utils::Hook(Game::Com_Error, ZoneBuilder::HandleError, HOOK_JUMP).install()->quick(); - // thread fuckery hooks + // Sys_IsMainThread hook Utils::Hook(0x4C37D0, ZoneBuilder::IsThreadMainThreadHook, HOOK_JUMP).install()->quick(); // Don't exec startup config in fs_restart @@ -1134,31 +1139,16 @@ namespace Components { if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current()) { - ZoneBuilder::TraceAssets.push_back({ type, name }); - OutputDebugStringA((name + "\n").data()); + ZoneBuilder::TraceAssets.emplace_back(std::make_pair(type, name)); +#ifdef _DEBUG + OutputDebugStringA(Utils::String::Format("%s\n", name)); +#endif } }); Command::Add("verifyzone", [](Command::Params* params) { if (params->size() < 2) return; - /* - Utils::Hook(0x4AE9C2, [] - { - Game::WeaponCompleteDef** varPtr = (Game::WeaponCompleteDef**)0x112A9F4; - Game::WeaponCompleteDef* var = *varPtr; - OutputDebugStringA(""); - Utils::Hook::Call(0x4D1D60)(); // DB_PopStreamPos - }, HOOK_JUMP).install()->quick(); - - Utils::Hook(0x4AE9B4, [] - { - Game::WeaponCompleteDef** varPtr = (Game::WeaponCompleteDef**)0x112A9F4; - Game::WeaponCompleteDef* var = *varPtr; - OutputDebugStringA(""); - Utils::Hook::Call(0x4D1D60)(); // DB_PopStreamPos - }, HOOK_JUMP).install()->quick(); - */ std::string zone = params->get(1); @@ -1601,7 +1591,7 @@ namespace Components ZoneBuilder::~ZoneBuilder() { - ZoneBuilder::Terminate = true; + ZoneBuilder::CommandThreadTerminate = true; if (ZoneBuilder::CommandThread.joinable()) { ZoneBuilder::CommandThread.join(); diff --git a/src/Components/Modules/ZoneBuilder.hpp b/src/Components/Modules/ZoneBuilder.hpp index 33e61cc6..11562b79 100644 --- a/src/Components/Modules/ZoneBuilder.hpp +++ b/src/Components/Modules/ZoneBuilder.hpp @@ -74,7 +74,7 @@ namespace Components bool isPrimaryAsset() { return this->assetDepth <= 1; } private: - void loadFastFiles(); + void loadFastFiles() const; bool loadAssets(); bool loadAssetByName(const std::string& type, std::string name, bool isSubAsset = true); @@ -140,7 +140,7 @@ namespace Components static std::string FindMaterialByTechnique(const std::string& name); static void ReallocateLoadedSounds(void*& data, void* a2); - static int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/); + static BOOL APIENTRY EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/); static void HandleError(Game::errorParm_t code, const char* fmt, ...); static void SoftErrorAssetOverflow(); @@ -151,10 +151,12 @@ namespace Components static void Com_Quitf_t(); + static void CommandThreadCallback(); + static bool MainThreadInterrupted; static DWORD InterruptingThreadId; - static volatile bool Terminate; + static volatile bool CommandThreadTerminate; static std::thread CommandThread; }; } diff --git a/src/Game/Common.hpp b/src/Game/Common.hpp index 58e18b0b..9eede34d 100644 --- a/src/Game/Common.hpp +++ b/src/Game/Common.hpp @@ -76,3 +76,19 @@ namespace Game extern const char* Com_LoadInfoString_FastFile(const char* fileName, const char* fileDesc, const char* ident, char* loadBuffer); } + +#define Com_InitThreadData() \ +{ \ + static Game::ProfileStack profile_stack{}; \ + static Game::va_info_t va_info{}; \ + static jmp_buf g_com_error{}; \ + static Game::TraceThreadInfo g_trace_thread_info{}; \ + static void* g_thread_values[Game::THREAD_VALUE_COUNT]{}; \ + auto** thread_data = \ + Game::Sys::GetTls(Game::Sys::ThreadOffset::THREAD_VALUES); \ + *thread_data = g_thread_values; \ + Game::Sys_SetValue(Game::THREAD_VALUE_PROF_STACK, &profile_stack); \ + Game::Sys_SetValue(Game::THREAD_VALUE_VA, &va_info); \ + Game::Sys_SetValue(Game::THREAD_VALUE_COM_ERROR, &g_com_error); \ + Game::Sys_SetValue(Game::THREAD_VALUE_TRACE, &g_trace_thread_info); \ +} diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 6444eff5..75b6cdd7 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -8,6 +8,7 @@ namespace Game Cbuf_AddServerText_f_t Cbuf_AddServerText_f = Cbuf_AddServerText_f_t(0x4BB9B0); Cbuf_AddText_t Cbuf_AddText = Cbuf_AddText_t(0x404B20); Cbuf_InsertText_t Cbuf_InsertText = Cbuf_InsertText_t(0x4940B0); + Cbuf_Execute_t Cbuf_Execute = Cbuf_Execute_t(0x4E2C80); CG_DrawDisconnect_t CG_DrawDisconnect = CG_DrawDisconnect_t(0x454A70); CG_NextWeapon_f_t CG_NextWeapon_f = CG_NextWeapon_f_t(0x449DE0); @@ -381,7 +382,9 @@ namespace Game Material** whiteMaterial = reinterpret_cast(0x8EE4B8); - unsigned long* _tls_index = reinterpret_cast(0x66D94A8); + unsigned long* g_dwTlsIndex = reinterpret_cast(0x66D94A8); + + bgs_t* level_bgs = reinterpret_cast(0x19BD680); 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 29750448..ae9d6323 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -15,6 +15,9 @@ namespace Game typedef void(*Cbuf_InsertText_t)(int localClientNum, const char* text); extern Cbuf_InsertText_t Cbuf_InsertText; + typedef void(*Cbuf_Execute_t)(int localClientNum, int controllerIndex); + extern Cbuf_Execute_t Cbuf_Execute; + typedef void(*CG_DrawDisconnect_t)(int localClientNum); extern CG_DrawDisconnect_t CG_DrawDisconnect; @@ -712,7 +715,9 @@ namespace Game extern Material** whiteMaterial; - extern unsigned long* _tls_index; + extern unsigned long* g_dwTlsIndex; + + extern bgs_t* level_bgs; constexpr std::size_t PLAYER_CARD_UI_STRING_COUNT = 18; extern unsigned int* playerCardUIStringIndex; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index a8be593b..ce0f3345 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -10333,6 +10333,59 @@ namespace Game TraceCheckCount checkcount; }; + struct ProfileAtom + { + unsigned int value[1]; + }; + + volatile struct ProfileReadable + { + unsigned int hits; + ProfileAtom total; + ProfileAtom self; + }; + + struct ProfileWritable + { + int nesting; + unsigned int hits; + ProfileAtom start[3]; + ProfileAtom total; + ProfileAtom child; + }; + + struct profile_t + { + ProfileWritable write; + ProfileReadable read; + }; + + struct profile_guard_t + { + int id; + profile_t** ppStack; + }; + + struct ProfileStack + { + profile_t prof_root; + profile_t* prof_pStack[16384]; + profile_t** prof_ppStack; + profile_t prof_array[443]; + ProfileAtom prof_overhead_internal; + ProfileAtom prof_overhead_external; + profile_guard_t prof_guardstack[32]; + int prof_guardpos; + float prof_timescale; + }; + + struct bgs_t + { + unsigned char __pad0[0x82950]; + }; + + static_assert(sizeof(bgs_t) == 0x82950); + #pragma endregion #ifndef IDA diff --git a/src/Game/System.cpp b/src/Game/System.cpp index 24cf1687..b4943c4c 100644 --- a/src/Game/System.cpp +++ b/src/Game/System.cpp @@ -21,6 +21,7 @@ namespace Game Sys_SendPacket_t Sys_SendPacket = Sys_SendPacket_t(0x60FDC0); Sys_ShowConsole_t Sys_ShowConsole = Sys_ShowConsole_t(0x4305E0); Sys_SuspendOtherThreads_t Sys_SuspendOtherThreads = Sys_SuspendOtherThreads_t(0x45A190); + Sys_SetValue_t Sys_SetValue = Sys_SetValue_t(0x4B2F50); char(*sys_exitCmdLine)[1024] = reinterpret_cast(0x649FB68); diff --git a/src/Game/System.hpp b/src/Game/System.hpp index 1232ba81..c6cbdbdd 100644 --- a/src/Game/System.hpp +++ b/src/Game/System.hpp @@ -2,7 +2,6 @@ namespace Game { - typedef void(*Sys_Error_t)(const char* error, ...); extern Sys_Error_t Sys_Error; @@ -60,6 +59,9 @@ namespace Game typedef void(*Sys_SuspendOtherThreads_t)(); extern Sys_SuspendOtherThreads_t Sys_SuspendOtherThreads; + typedef void(*Sys_SetValue_t)(int valueIndex, void* data); + extern Sys_SetValue_t Sys_SetValue; + extern char(*sys_exitCmdLine)[1024]; extern RTL_CRITICAL_SECTION* s_criticalSection; @@ -68,4 +70,22 @@ namespace Game extern void Sys_UnlockRead(FastCriticalSection* critSect); extern bool Sys_TryEnterCriticalSection(CriticalSection critSect); + + class Sys + { + public: + enum ThreadOffset : unsigned int + { + LEVEL_BGS = 0xC, + THREAD_VALUES = 0x14, + DVAR_MODIFIED_FLAGS = 0x18, + }; + + template + static T* GetTls(ThreadOffset offset) + { + const auto* tls = reinterpret_cast(__readfsdword(0x2C)); + return reinterpret_cast(tls[*g_dwTlsIndex] + offset); + } + }; } From 02db63cc3667f36d77f5570a659ee067d054cb3a Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 19 Dec 2022 15:01:37 +0100 Subject: [PATCH 71/96] [Sys]: Format code (#658) --- src/Game/Common.hpp | 4 +--- src/Game/Structs.hpp | 8 ++++++++ src/Game/System.hpp | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Game/Common.hpp b/src/Game/Common.hpp index 9eede34d..85f296bd 100644 --- a/src/Game/Common.hpp +++ b/src/Game/Common.hpp @@ -84,9 +84,7 @@ namespace Game static jmp_buf g_com_error{}; \ static Game::TraceThreadInfo g_trace_thread_info{}; \ static void* g_thread_values[Game::THREAD_VALUE_COUNT]{}; \ - auto** thread_data = \ - Game::Sys::GetTls(Game::Sys::ThreadOffset::THREAD_VALUES); \ - *thread_data = g_thread_values; \ + *(Game::Sys::GetTls(Game::Sys::THREAD_VALUES)) = g_thread_values; \ Game::Sys_SetValue(Game::THREAD_VALUE_PROF_STACK, &profile_stack); \ Game::Sys_SetValue(Game::THREAD_VALUE_VA, &va_info); \ Game::Sys_SetValue(Game::THREAD_VALUE_COM_ERROR, &g_com_error); \ diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index ce0f3345..ad90dd6b 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -10386,6 +10386,14 @@ namespace Game static_assert(sizeof(bgs_t) == 0x82950); + struct ZipInfo + { + int offsetCount; + int offsets[128]; + int size; + char* buffer; + }; + #pragma endregion #ifndef IDA diff --git a/src/Game/System.hpp b/src/Game/System.hpp index c6cbdbdd..db6ce89f 100644 --- a/src/Game/System.hpp +++ b/src/Game/System.hpp @@ -78,7 +78,10 @@ namespace Game { LEVEL_BGS = 0xC, THREAD_VALUES = 0x14, + HUFFMAN_BLOC = 0x10, + DVAR_ALLOWED_MODIFIED_FLAGS = 0x1C, DVAR_MODIFIED_FLAGS = 0x18, + ZIP_INFO = 0x20, }; template From f265d572e92c6be015f182ee9a34a020f78bef0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 17:06:46 +0000 Subject: [PATCH 72/96] Bump deps/mongoose from `6921227` to `6cedca5` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `6921227` to `6cedca5`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/6921227ec8a610abefb8698e66441e037438e442...6cedca5d76d9297a444d14f09ca0424fde7b1006) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 6921227e..6cedca5d 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 6921227ec8a610abefb8698e66441e037438e442 +Subproject commit 6cedca5d76d9297a444d14f09ca0424fde7b1006 From a4a622be52c40b03e237eac7173afcb651c79cf4 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 19 Dec 2022 18:57:13 +0100 Subject: [PATCH 73/96] [System]: Correct one function (#660) --- src/Components/Modules/ClientCommand.cpp | 2 +- src/Game/Common.hpp | 24 ++++++++++++------------ src/Game/System.cpp | 13 ++++++++++--- src/Game/System.hpp | 10 +++++++--- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index 07fdbba1..a005cdca 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -246,7 +246,7 @@ namespace Components if (ent->client->sess.sessionState != Game::SESS_STATE_PLAYING || !CheatsOk(ent)) return; - auto** bgs = Game::Sys::GetTls(Game::Sys::ThreadOffset::LEVEL_BGS); + auto** bgs = Game::Sys::GetTls(Game::Sys::TLS_OFFSET::LEVEL_BGS); assert(*bgs == nullptr); diff --git a/src/Game/Common.hpp b/src/Game/Common.hpp index 85f296bd..012e5f07 100644 --- a/src/Game/Common.hpp +++ b/src/Game/Common.hpp @@ -77,16 +77,16 @@ namespace Game extern const char* Com_LoadInfoString_FastFile(const char* fileName, const char* fileDesc, const char* ident, char* loadBuffer); } -#define Com_InitThreadData() \ -{ \ - static Game::ProfileStack profile_stack{}; \ - static Game::va_info_t va_info{}; \ - static jmp_buf g_com_error{}; \ - static Game::TraceThreadInfo g_trace_thread_info{}; \ - static void* g_thread_values[Game::THREAD_VALUE_COUNT]{}; \ - *(Game::Sys::GetTls(Game::Sys::THREAD_VALUES)) = g_thread_values; \ - Game::Sys_SetValue(Game::THREAD_VALUE_PROF_STACK, &profile_stack); \ - Game::Sys_SetValue(Game::THREAD_VALUE_VA, &va_info); \ - Game::Sys_SetValue(Game::THREAD_VALUE_COM_ERROR, &g_com_error); \ - Game::Sys_SetValue(Game::THREAD_VALUE_TRACE, &g_trace_thread_info); \ +#define Com_InitThreadData() \ +{ \ + static Game::ProfileStack profile_stack{}; \ + static Game::va_info_t va_info{}; \ + static jmp_buf g_com_error{}; \ + static Game::TraceThreadInfo g_trace_thread_info{}; \ + static void* g_thread_values[Game::THREAD_VALUE_COUNT]{}; \ + *(Game::Sys::GetTls(Game::Sys::TLS_OFFSET::THREAD_VALUES)) = g_thread_values; \ + Game::Sys_SetValue(Game::THREAD_VALUE_PROF_STACK, &profile_stack); \ + Game::Sys_SetValue(Game::THREAD_VALUE_VA, &va_info); \ + Game::Sys_SetValue(Game::THREAD_VALUE_COM_ERROR, &g_com_error); \ + Game::Sys_SetValue(Game::THREAD_VALUE_TRACE, &g_trace_thread_info); \ } diff --git a/src/Game/System.cpp b/src/Game/System.cpp index b4943c4c..21148722 100644 --- a/src/Game/System.cpp +++ b/src/Game/System.cpp @@ -12,6 +12,7 @@ namespace Game Sys_ListFiles_t Sys_ListFiles = Sys_ListFiles_t(0x45A660); Sys_Milliseconds_t Sys_Milliseconds = Sys_Milliseconds_t(0x42A660); Sys_Error_t Sys_Error = Sys_Error_t(0x43D570); + Sys_Sleep_t Sys_Sleep = Sys_Sleep_t(0x4169C0); Sys_LockWrite_t Sys_LockWrite = Sys_LockWrite_t(0x435880); Sys_TempPriorityAtLeastNormalBegin_t Sys_TempPriorityAtLeastNormalBegin = Sys_TempPriorityAtLeastNormalBegin_t(0x478680); Sys_TempPriorityEnd_t Sys_TempPriorityEnd = Sys_TempPriorityEnd_t(0x4DCF00); @@ -30,7 +31,7 @@ namespace Game void Sys_LockRead(FastCriticalSection* critSect) { InterlockedIncrement(&critSect->readCount); - while (critSect->writeCount) std::this_thread::sleep_for(1ms); + while (critSect->writeCount) Sys_Sleep(1); } void Sys_UnlockRead(FastCriticalSection* critSect) @@ -39,10 +40,16 @@ namespace Game InterlockedDecrement(&critSect->readCount); } + void Sys_UnlockWrite(FastCriticalSection* critSect) + { + assert(critSect->writeCount > 0); + InterlockedDecrement(&critSect->writeCount); + Sys_TempPriorityEnd(&critSect->tempPriority); + } + bool Sys_TryEnterCriticalSection(CriticalSection critSect) { - assert(static_cast(critSect) < - static_cast(CRITSECT_COUNT)); + AssertIn(critSect, CRITSECT_COUNT); return TryEnterCriticalSection(&s_criticalSection[critSect]) != FALSE; } diff --git a/src/Game/System.hpp b/src/Game/System.hpp index db6ce89f..5e3260f1 100644 --- a/src/Game/System.hpp +++ b/src/Game/System.hpp @@ -32,6 +32,9 @@ namespace Game typedef int(*Sys_Milliseconds_t)(); extern Sys_Milliseconds_t Sys_Milliseconds; + typedef void(*Sys_Sleep_t)(int msec); + extern Sys_Sleep_t Sys_Sleep; + typedef void(*Sys_LockWrite_t)(FastCriticalSection* critSect); extern Sys_LockWrite_t Sys_LockWrite; @@ -68,13 +71,14 @@ namespace Game extern void Sys_LockRead(FastCriticalSection* critSect); extern void Sys_UnlockRead(FastCriticalSection* critSect); + extern void Sys_UnlockWrite(FastCriticalSection* critSect); extern bool Sys_TryEnterCriticalSection(CriticalSection critSect); class Sys { public: - enum ThreadOffset : unsigned int + enum class TLS_OFFSET : unsigned int { LEVEL_BGS = 0xC, THREAD_VALUES = 0x14, @@ -85,10 +89,10 @@ namespace Game }; template - static T* GetTls(ThreadOffset offset) + static T* GetTls(TLS_OFFSET offset) { const auto* tls = reinterpret_cast(__readfsdword(0x2C)); - return reinterpret_cast(tls[*g_dwTlsIndex] + offset); + return reinterpret_cast(tls[*g_dwTlsIndex] + static_cast>(offset)); } }; } From 6692e99d86e4660680f7cce41463fec3432d2cab Mon Sep 17 00:00:00 2001 From: Louve <33836535+Rackover@users.noreply.github.com> Date: Sat, 24 Dec 2022 21:23:33 +0100 Subject: [PATCH 74/96] Add cod4 map to dlc list (and absolutely nothing else) (#663) Co-authored-by: louve Co-authored-by: Diavolo --- src/Components/Modules/Maps.cpp | 2 +- src/Components/Modules/PlayerMovement.cpp | 17 +++++++++++++++++ src/Components/Modules/PlayerMovement.hpp | 6 +++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 14183e85..b13f80c6 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -684,7 +684,7 @@ namespace Components Maps::AddDlc({ 6, "Freighter", {"mp_cargoship_sh"} }); Maps::AddDlc({ 7, "Resurrection Pack", {"mp_shipment_long", "mp_rust_long", "mp_firingrange"} }); Maps::AddDlc({ 8, "Recycled Pack", {"mp_bloc_sh", "mp_crash_tropical", "mp_estate_tropical", "mp_fav_tropical", "mp_storm_spring"} }); - Maps::AddDlc({ 9, "Classics Pack #3", {"mp_farm", "mp_backlot", "mp_pipeline", "mp_countdown", "mp_crash_snow", "mp_carentan"}}); + Maps::AddDlc({ 9, "Classics Pack #3", {"mp_farm", "mp_backlot", "mp_pipeline", "mp_countdown", "mp_crash_snow", "mp_carentan", "mp_broadcast", "mp_showdown", "mp_convoy"} }); Maps::UpdateDlcStatus(); diff --git a/src/Components/Modules/PlayerMovement.cpp b/src/Components/Modules/PlayerMovement.cpp index 05aeb8b5..a42600bc 100644 --- a/src/Components/Modules/PlayerMovement.cpp +++ b/src/Components/Modules/PlayerMovement.cpp @@ -7,6 +7,7 @@ namespace Components Dvar::Var PlayerMovement::BGRocketJumpScale; Dvar::Var PlayerMovement::BGPlayerEjection; Dvar::Var PlayerMovement::BGPlayerCollision; + Dvar::Var PlayerMovement::BGClimbAnything; const Game::dvar_t* PlayerMovement::CGNoclipScaler; const Game::dvar_t* PlayerMovement::CGUfoScaler; const Game::dvar_t* PlayerMovement::PlayerSpectateSpeedScale; @@ -15,6 +16,16 @@ namespace Components const Game::dvar_t* PlayerMovement::PlayerDuckedSpeedScale; const Game::dvar_t* PlayerMovement::PlayerProneSpeedScale; + void PlayerMovement::PM_PlayerTraceStub(Game::pmove_s* pm, Game::trace_t* results, const float* start, const float* end, Game::Bounds* bounds, int passEntityNum, int contentMask) + { + Game::PM_playerTrace(pm, results, start, end, bounds, passEntityNum, contentMask); + + if (results && BGClimbAnything.get()) + { + results[0].surfaceFlags |= SURF_LADDER; + } + } + __declspec(naked) void PlayerMovement::PM_PlayerDuckedSpeedScaleStub() { __asm @@ -242,6 +253,9 @@ namespace Components BGPlayerCollision = Dvar::Register("bg_playerCollision", true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); + + BGClimbAnything = Dvar::Register("bg_climbAnything", + false, Game::DVAR_CODINFO, "Allows to treat any surface as a ladder"); } PlayerMovement::PlayerMovement() @@ -289,6 +303,9 @@ namespace Components Utils::Hook(0x45A5BF, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity Utils::Hook(0x5A0CAD, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity + Utils::Hook(0x573F39, PM_PlayerTraceStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x573E93, PM_PlayerTraceStub, HOOK_CALL).install()->quick(); + Script::AddMethod("IsSprinting", GScr_IsSprinting); RegisterMovementDvars(); diff --git a/src/Components/Modules/PlayerMovement.hpp b/src/Components/Modules/PlayerMovement.hpp index 5977ef44..d86d8394 100644 --- a/src/Components/Modules/PlayerMovement.hpp +++ b/src/Components/Modules/PlayerMovement.hpp @@ -10,10 +10,13 @@ namespace Components private: enum BouncesSettings { DISABLED, ENABLED, DOUBLE }; + static constexpr auto SURF_LADDER = 0x8; + static Dvar::Var BGRocketJump; static Dvar::Var BGRocketJumpScale; static Dvar::Var BGPlayerEjection; static Dvar::Var BGPlayerCollision; + static Dvar::Var BGClimbAnything; // Can't use Var class inside assembly stubs static const Game::dvar_t* CGNoclipScaler; static const Game::dvar_t* CGUfoScaler; @@ -22,7 +25,8 @@ namespace Components static const Game::dvar_t* BGBouncesAllAngles; static const Game::dvar_t* PlayerDuckedSpeedScale; static const Game::dvar_t* PlayerProneSpeedScale; - + + static void PM_PlayerTraceStub(Game::pmove_s* pm, Game::trace_t* results, const float* start, const float* end, Game::Bounds* bounds, int passEntityNum, int contentMask); static void PM_PlayerDuckedSpeedScaleStub(); static void PM_PlayerProneSpeedScaleStub(); From 6958316fe49b705745f8dc3bf177addd0300f338 Mon Sep 17 00:00:00 2001 From: Louve <33836535+Rackover@users.noreply.github.com> Date: Sat, 24 Dec 2022 21:41:23 +0100 Subject: [PATCH 75/96] Zonebuilder directory for support zones (#662) Co-authored-by: Louvenarde Co-authored-by: Diavolo --- src/Components/Modules/Maps.hpp | 6 -- src/Components/Modules/PlayerMovement.cpp | 2 +- src/Components/Modules/ZoneBuilder.cpp | 14 +++++ src/Components/Modules/ZoneBuilder.hpp | 1 + src/Game/Structs.hpp | 70 +++++++++++++++++++++++ src/Game/System.cpp | 1 + src/Game/System.hpp | 3 + 7 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/Components/Modules/Maps.hpp b/src/Components/Modules/Maps.hpp index 5a9a26c8..ea47c28b 100644 --- a/src/Components/Modules/Maps.hpp +++ b/src/Components/Modules/Maps.hpp @@ -119,12 +119,6 @@ namespace Components static void HideModel(); static void HideModelStub(); - static Game::dvar_t* GetDistortionDvar(); - static void SetDistortionStub(); - - static Game::dvar_t* GetSpecularDvar(); - static void SetSpecularStub1(); - static void SetSpecularStub2(); static void G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2); static bool SV_SetTriggerModelHook(Game::gentity_s* ent); static int16 CM_TriggerModelBounds(int brushModelPointer, Game::Bounds* bounds); diff --git a/src/Components/Modules/PlayerMovement.cpp b/src/Components/Modules/PlayerMovement.cpp index a42600bc..bbbeb944 100644 --- a/src/Components/Modules/PlayerMovement.cpp +++ b/src/Components/Modules/PlayerMovement.cpp @@ -255,7 +255,7 @@ namespace Components true, Game::DVAR_CODINFO, "Push intersecting players away from each other"); BGClimbAnything = Dvar::Register("bg_climbAnything", - false, Game::DVAR_CODINFO, "Allows to treat any surface as a ladder"); + false, Game::DVAR_CODINFO, "Treat any surface as a ladder"); } PlayerMovement::PlayerMovement() diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 325495f3..97285687 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -1022,6 +1022,18 @@ namespace Components sound->info.data_ptr = allocatedSpace; } + Game::Sys_File ZoneBuilder::Sys_CreateFile_Stub(const char* dir, const char* filename) + { + auto file = Game::Sys_CreateFile(dir, filename); + + if (file.handle == INVALID_HANDLE_VALUE) + { + file = Game::Sys_CreateFile("zone\\zonebuilder\\", filename); + } + + return file; + } + ZoneBuilder::ZoneBuilder() { // ReSharper disable CppStaticAssertFailure @@ -1034,6 +1046,8 @@ namespace Components // Prevent loading textures (preserves loaddef) //Utils::Hook::Set(Game::Load_Texture, 0xC3); + Utils::Hook(0x5BC832, Sys_CreateFile_Stub, HOOK_CALL).install()->quick(); + // Store the loaddef Utils::Hook(Game::Load_Texture, StoreTexture, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/ZoneBuilder.hpp b/src/Components/Modules/ZoneBuilder.hpp index 11562b79..f61b140f 100644 --- a/src/Components/Modules/ZoneBuilder.hpp +++ b/src/Components/Modules/ZoneBuilder.hpp @@ -148,6 +148,7 @@ namespace Components static void ResetThreadRole(); static bool IsThreadMainThreadHook(); + static Game::Sys_File Sys_CreateFile_Stub(const char* dir, const char* filename); static void Com_Quitf_t(); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index ad90dd6b..669d474b 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -95,6 +95,71 @@ namespace Game ASSET_TYPE_INVALID = -1, }; + enum GfxWarningType + { + R_WARN_FRONTEND_ENT_LIMIT = 0x0, + R_WARN_KNOWN_MODELS = 0x1, + R_WARN_KNOWN_PER_CLIENT_MODELS = 0x2, + R_WARN_KNOWN_SPECIAL_MODELS = 0x3, + R_WARN_MODEL_LIGHT_CACHE = 0x4, + R_WARN_SCENE_ENTITIES = 0x5, + R_WARN_TEMP_SKIN_BUF_SIZE = 0x6, + R_WARN_MAX_SKINNED_CACHE_VERTICES = 0x7, + R_WARN_MAX_SCENE_SURFS_SIZE = 0x8, + R_WARN_MAX_SURF_BUF = 0x9, + R_WARN_PORTAL_PLANES = 0xA, + R_WARN_MAX_CLOUDS = 0xB, + R_WARN_MAX_DLIGHTS = 0xC, + R_WARN_SMODEL_LIGHTING = 0xD, + R_WARN_SMODEL_VIS_DATA_LIMIT = 0xE, + R_WARN_SMODEL_SURF_LIMIT = 0xF, + R_WARN_SMODEL_SURF_DELAY_LIMIT = 0x10, + R_WARN_BSPSURF_DATA_LIMIT = 0x11, + R_WARN_BSPSURF_PRETESS_LIMIT = 0x12, + R_WARN_MAX_DRAWSURFS = 0x13, + R_WARN_GFX_CODE_EMISSIVE_SURF_LIMIT = 0x14, + R_WARN_GFX_CODE_TRANS_SURF_LIMIT = 0x15, + R_WARN_GFX_GLASS_SURF_LIMIT = 0x16, + R_WARN_GFX_MARK_SURF_LIMIT = 0x17, + R_WARN_GFX_SPARK_SURF_LIMIT = 0x18, + R_WARN_MAX_SCENE_DRAWSURFS = 0x19, + R_WARN_MAX_FX_DRAWSURFS = 0x1A, + R_WARN_NONEMISSIVE_FX_MATERIAL = 0x1B, + R_WARN_NONLIT_MARK_MATERIAL = 0x1C, + R_WARN_CMDBUF_OVERFLOW = 0x1D, + R_WARN_MISSING_DECL_NONDEBUG = 0x1E, + R_WARN_MAX_DYNENT_REFS = 0x1F, + R_WARN_MAX_SCENE_DOBJ_REFS = 0x20, + R_WARN_MAX_SCENE_MODEL_REFS = 0x21, + R_WARN_MAX_SCENE_BRUSH_REFS = 0x22, + R_WARN_MAX_CODE_EMISSIVE_INDS = 0x23, + R_WARN_MAX_CODE_EMISSIVE_VERTS = 0x24, + R_WARN_MAX_CODE_EMISSIVE_ARGS = 0x25, + R_WARN_MAX_CODE_TRANS_INDS = 0x26, + R_WARN_MAX_CODE_TRANS_VERTS = 0x27, + R_WARN_MAX_CODE_TRANS_ARGS = 0x28, + R_WARN_MAX_GLASS_INDS = 0x29, + R_WARN_MAX_GLASS_VERTS = 0x2A, + R_WARN_MAX_MARK_INDS = 0x2B, + R_WARN_MAX_MARK_VERTS = 0x2C, + R_WARN_MAX_SPARK_INDS = 0x2D, + R_WARN_MAX_SPARK_VERTS = 0x2E, + R_WARN_DEBUG_ALLOC = 0x2F, + R_WARN_SPOT_LIGHT_LIMIT = 0x30, + R_WARN_FX_ELEM_LIMIT = 0x31, + R_WARN_FX_BOLT_LIMIT = 0x32, + R_WARN_WORKER_CMD_SIZE = 0x33, + R_WARN_UNKNOWN_STATICMODEL_SHADER = 0x34, + R_WARN_UNKNOWN_XMODEL_SHADER = 0x35, + R_WARN_DYNAMIC_INDEX_BUFFER_SIZE = 0x36, + R_WARN_TOO_MANY_LIGHT_GRID_POINTS = 0x37, + R_WARN_FOGABLE_2DTEXT = 0x38, + R_WARN_FOGABLE_2DGLYPH = 0x39, + R_WARN_SUN_QUERY = 0x3A, + R_WARN_ESTIMATED_BOUNDS_TOO_SMALL = 0x3B, + R_WARN_COUNT = 0x3C, + }; + enum surfType_t { R_SMODEL_SURFTYPE_RIGID = 0x0, @@ -10394,6 +10459,11 @@ namespace Game char* buffer; }; + struct Sys_File + { + HANDLE handle; + }; + #pragma endregion #ifndef IDA diff --git a/src/Game/System.cpp b/src/Game/System.cpp index 21148722..0068ff51 100644 --- a/src/Game/System.cpp +++ b/src/Game/System.cpp @@ -23,6 +23,7 @@ namespace Game Sys_ShowConsole_t Sys_ShowConsole = Sys_ShowConsole_t(0x4305E0); Sys_SuspendOtherThreads_t Sys_SuspendOtherThreads = Sys_SuspendOtherThreads_t(0x45A190); Sys_SetValue_t Sys_SetValue = Sys_SetValue_t(0x4B2F50); + Sys_CreateFile_t Sys_CreateFile = Sys_CreateFile_t(0x4B2EF0); char(*sys_exitCmdLine)[1024] = reinterpret_cast(0x649FB68); diff --git a/src/Game/System.hpp b/src/Game/System.hpp index 5e3260f1..68eb6ee5 100644 --- a/src/Game/System.hpp +++ b/src/Game/System.hpp @@ -65,6 +65,9 @@ namespace Game typedef void(*Sys_SetValue_t)(int valueIndex, void* data); extern Sys_SetValue_t Sys_SetValue; + typedef Sys_File(*Sys_CreateFile_t)(const char* dir, const char* filename); + extern Sys_CreateFile_t Sys_CreateFile; + extern char(*sys_exitCmdLine)[1024]; extern RTL_CRITICAL_SECTION* s_criticalSection; From 2698921382951ecfabbc928160acca6dd6d5f2e5 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 24 Dec 2022 22:16:01 +0100 Subject: [PATCH 76/96] [Entities]: Remove bruh code (#664) --- src/Utils/Entities.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Utils/Entities.cpp b/src/Utils/Entities.cpp index baf3962e..cbc8b494 100644 --- a/src/Utils/Entities.cpp +++ b/src/Utils/Entities.cpp @@ -6,13 +6,13 @@ namespace Utils { std::string entityString; - for (auto& entity : this->entities) + for (const auto& entity : this->entities) { entityString.append("{\n"); - for (auto& property : entity) + for (const auto& property : entity) { - entityString.push_back('"'); + entityString.append("\""); entityString.append(property.first); entityString.append("\" \""); entityString.append(property.second); From 9f67a4f62d0d3e213e5e17de8af6281708aa6763 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 24 Dec 2022 23:14:47 +0100 Subject: [PATCH 77/96] [Bots]: Add requested feature (#665) --- src/Components/Loader.cpp | 2 +- src/Components/Loader.hpp | 2 +- src/Components/Modules/Bots.cpp | 11 +++++++++++ src/Components/Modules/Bots.hpp | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index bf5e3a7d..74caf387 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -35,8 +35,8 @@ namespace Components Loader::Register(new Exception()); Loader::Register(new Auth()); Loader::Register(new Bans()); - Loader::Register(new Bots()); Loader::Register(new Dvar()); + Loader::Register(new Bots()); Loader::Register(new Lean()); Loader::Register(new Maps()); Loader::Register(new News()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 833168d0..b45931db 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -64,8 +64,8 @@ namespace Components #include "Modules/Scheduler.hpp" #include "Modules/Auth.hpp" #include "Modules/Bans.hpp" -#include "Modules/Bots.hpp" #include "Modules/Dvar.hpp" +#include "Modules/Bots.hpp" #include "Modules/Lean.hpp" #include "Modules/Maps.hpp" #include "Modules/News.hpp" diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index bd65eb50..ae85897b 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -5,6 +5,8 @@ namespace Components { std::vector Bots::BotNames; + Dvar::Var Bots::SVRandomBotNames; + struct BotMovementInfo { std::int32_t buttons; // Actions @@ -57,6 +59,13 @@ namespace Components { auto data = Utils::String::Split(bots.getBuffer(), '\n'); + if (SVRandomBotNames.get()) + { + std::random_device rd; + std::mt19937 gen(rd()); + std::ranges::shuffle(data, gen); + } + for (auto& entry : data) { // Take into account for CR line endings @@ -334,6 +343,8 @@ namespace Components Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + SVRandomBotNames = Dvar::Register("sv_RandomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); + // Reset BotMovementInfo.active when client is dropped Events::OnClientDisconnect([](const int clientNum) { diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index 1182f92f..f47f7a9a 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -11,6 +11,8 @@ namespace Components using botData = std::pair< std::string, std::string>; static std::vector BotNames; + static Dvar::Var SVRandomBotNames; + static int BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port); static void Spawn(unsigned int count); From 79758e1752371dc57c276d46a07d0222954b616d Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 24 Dec 2022 23:21:18 +0100 Subject: [PATCH 78/96] [Bots]: Fix code style mistake (#666) --- src/Components/Modules/Bots.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index ae85897b..5caf68fd 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -343,7 +343,7 @@ namespace Components Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); - SVRandomBotNames = Dvar::Register("sv_RandomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); + SVRandomBotNames = Dvar::Register("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); // Reset BotMovementInfo.active when client is dropped Events::OnClientDisconnect([](const int clientNum) From 01a629d02bb570f0e3803ec71514bdc74c442198 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 25 Dec 2022 18:23:53 +0100 Subject: [PATCH 79/96] [General]: Fix some things (#667) --- README.md | 1 - premake5.lua | 8 - src/Components/Loader.cpp | 220 +++++++++++++------------- src/Components/Loader.hpp | 128 +++++++-------- src/Components/Modules/CardTitles.cpp | 64 ++++---- src/Components/Modules/CardTitles.hpp | 43 ++--- src/Components/Modules/Dvar.cpp | 16 +- src/Components/Modules/Dvar.hpp | 13 +- src/Components/Modules/Exception.cpp | 84 ++++------ src/Components/Modules/Exception.hpp | 4 +- src/Components/Modules/Party.cpp | 4 +- src/Components/Modules/Playlist.cpp | 141 ++++++++--------- src/Components/Modules/Playlist.hpp | 8 +- src/Components/Modules/ServerInfo.cpp | 4 +- src/Components/Modules/Singleton.cpp | 4 +- src/DllMain.cpp | 2 +- src/Game/Common.cpp | 2 + src/Game/Common.hpp | 4 +- src/Game/Dvars.cpp | 1 + src/Game/Dvars.hpp | 1 + src/Game/Functions.cpp | 4 + src/Game/Functions.hpp | 5 + 22 files changed, 368 insertions(+), 393 deletions(-) diff --git a/README.md b/README.md index 448d11c9..fa6f3612 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ | `--copy-to=PATH` | Optional, copy the DLL to a custom folder after build, define the path here if wanted. | | `--copy-pdb` | Copy debug information for binaries as well to the path given via --copy-to. | | `--force-unit-tests` | Always compile unit tests. | -| `--force-exception-handler` | Install custom unhandled exception handler even for Debug builds. | | `--disable-binary-check` | Do not perform integrity checks on the exe. | ## Command line arguments diff --git a/premake5.lua b/premake5.lua index 3f36f4bd..a311c929 100644 --- a/premake5.lua +++ b/premake5.lua @@ -76,11 +76,6 @@ newoption { description = "Always compile unit tests." } -newoption { - trigger = "force-exception-handler", - description = "Install custom unhandled exception handler even for Debug builds." -} - newoption { trigger = "disable-binary-check", description = "Do not perform integrity checks on the exe." @@ -257,9 +252,6 @@ workspace "iw4x" if _OPTIONS["force-unit-tests"] then defines {"FORCE_UNIT_TESTS"} end - if _OPTIONS["force-exception-handler"] then - defines {"FORCE_EXCEPTION_HANDLER"} - end if _OPTIONS["disable-binary-check"] then defines {"DISABLE_BINARY_CHECK"} end diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 74caf387..ef452178 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -9,128 +9,128 @@ namespace Components bool Loader::IsPregame() { - return Loader::Pregame; + return Pregame; } bool Loader::IsPostgame() { - return Loader::Postgame; + return Postgame; } bool Loader::IsUninitializing() { - return Loader::Uninitializing; + return Uninitializing; } void Loader::Initialize() { - Loader::Pregame = true; - Loader::Postgame = false; - Loader::Uninitializing = false; + Pregame = true; + Postgame = false; + Uninitializing = false; Utils::Memory::GetAllocator()->clear(); - Loader::Register(new Flags()); - Loader::Register(new Singleton()); - // Install our exception handler as early as posssible to get better debug dumps from startup crashes - Loader::Register(new Exception()); - Loader::Register(new Auth()); - Loader::Register(new Bans()); - Loader::Register(new Dvar()); - Loader::Register(new Bots()); - Loader::Register(new Lean()); - Loader::Register(new Maps()); - Loader::Register(new News()); - Loader::Register(new Node()); - Loader::Register(new RCon()); - Loader::Register(new Stats()); - Loader::Register(new Menus()); - Loader::Register(new Toast()); - Loader::Register(new Party()); - Loader::Register(new Zones()); - Loader::Register(new D3D9Ex()); - Loader::Register(new Logger()); - Loader::Register(new Weapon()); - Loader::Register(new Window()); - Loader::Register(new Command()); - Loader::Register(new Console()); - Loader::Register(new Friends()); - Loader::Register(new IPCPipe()); - 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()); - Loader::Register(new Download()); - Loader::Register(new Playlist()); - Loader::Register(new RawFiles()); - Loader::Register(new Renderer()); - Loader::Register(new UIFeeder()); - Loader::Register(new UIScript()); - Loader::Register(new Changelog()); - Loader::Register(new Dedicated()); - Loader::Register(new Discovery()); - Loader::Register(new FastFiles()); - Loader::Register(new Gametypes()); - Loader::Register(new Materials()); - Loader::Register(new Scheduler()); - Loader::Register(new Threading()); - Loader::Register(new CardTitles()); - Loader::Register(new FileSystem()); - Loader::Register(new ModelSurfs()); - Loader::Register(new PlayerName()); - Loader::Register(new QuickPatch()); - Loader::Register(new Security()); - Loader::Register(new ServerInfo()); - Loader::Register(new ServerList()); - Loader::Register(new SlowMotion()); - Loader::Register(new ArenaLength()); - Loader::Register(new StringTable()); - Loader::Register(new ZoneBuilder()); - Loader::Register(new AssetHandler()); - Loader::Register(new Localization()); - Loader::Register(new ServerCommands()); - Loader::Register(new StructuredData()); - Loader::Register(new ConnectProtocol()); - Loader::Register(new StartupMessages()); - Loader::Register(new SoundMutexFix()); - Loader::Register(new Gamepad()); - Loader::Register(new Chat()); - Loader::Register(new TextRenderer()); - Loader::Register(new PlayerMovement()); - Loader::Register(new Elevators()); - Loader::Register(new ClientCommand()); - Loader::Register(new VisionFile()); - Loader::Register(new Branding()); - Loader::Register(new Debug()); - Loader::Register(new RawMouse()); - Loader::Register(new Bullet()); - Loader::Register(new MapRotation()); - Loader::Register(new Ceg()); - Loader::Register(new UserInfo()); - Loader::Register(new Events()); - Loader::Register(new Voice()); - Loader::Register(new Vote()); + Register(new Auth()); + Register(new Command()); + Register(new Dvar()); + Register(new Exception()); // Install our exception handler as early as posssible to get better debug dumps from startup crashes + Register(new Flags()); + Register(new Network()); + Register(new Logger()); + Register(new Singleton()); + Register(new UIScript()); + Register(new ZoneBuilder()); + + Register(new ArenaLength()); + Register(new AssetHandler()); + Register(new Bans()); + Register(new Bots()); + Register(new Branding()); + Register(new Bullet()); + Register(new CardTitles()); + Register(new Ceg()); + Register(new Changelog()); + Register(new Chat()); + Register(new ClanTags()); + Register(new ClientCommand()); + Register(new ConnectProtocol()); + Register(new Console()); + Register(new D3D9Ex()); + Register(new Debug()); + Register(new Dedicated()); + Register(new Discovery()); + Register(new Download()); + Register(new Elevators()); + Register(new Events()); + Register(new FastFiles()); + Register(new FileSystem()); + Register(new Friends()); + Register(new Gamepad()); + Register(new Gametypes()); + Register(new IPCPipe()); + Register(new Lean()); + Register(new Localization()); + Register(new MapDump()); + Register(new MapRotation()); + Register(new Maps()); + Register(new Materials()); + Register(new Menus()); + Register(new ModList()); + Register(new ModelSurfs()); + Register(new NetworkDebug()); + Register(new News()); + Register(new Node()); + Register(new Party()); + Register(new PlayerMovement()); + Register(new PlayerName()); + Register(new Playlist()); + Register(new QuickPatch()); + Register(new RCon()); + Register(new RawFiles()); + Register(new RawMouse()); + Register(new Renderer()); + Register(new Scheduler()); + Register(new Security()); + Register(new ServerCommands()); + Register(new ServerInfo()); + Register(new ServerList()); + Register(new Session()); + Register(new SlowMotion()); + Register(new SoundMutexFix()); + Register(new StartupMessages()); + Register(new Stats()); + Register(new StringTable()); + Register(new StructuredData()); + Register(new TextRenderer()); + Register(new Theatre()); + Register(new Threading()); + Register(new Toast()); + Register(new UIFeeder()); + Register(new UserInfo()); + Register(new VisionFile()); + Register(new Voice()); + Register(new Vote()); + Register(new Weapon()); + Register(new Window()); + Register(new Zones()); - Loader::Register(new GSC()); + Register(new GSC()); - Loader::Pregame = false; + Pregame = false; // Make sure preDestroy is called when the game shuts down - Scheduler::OnGameShutdown(Loader::PreDestroy); + Scheduler::OnGameShutdown(PreDestroy); } void Loader::Uninitialize() { - Loader::Uninitializing = true; - Loader::PreDestroyNoPostGame(); + Uninitializing = true; + PreDestroyNoPostGame(); - std::reverse(Loader::Components.begin(), Loader::Components.end()); - for (auto component : Loader::Components) + std::reverse(Components.begin(), Components.end()); + for (auto& component : Components) { #ifdef DEBUG - if (!Loader::IsPerformingUnitTests()) + if (!IsPerformingUnitTests()) { Logger::Print("Unregister component: {}\n", component->getName()); } @@ -138,21 +138,21 @@ namespace Components delete component; } - Loader::Components.clear(); + Components.clear(); Utils::Memory::GetAllocator()->clear(); - Loader::Uninitializing = false; + Uninitializing = false; } void Loader::PreDestroy() { - if (!Loader::Postgame) + if (!Postgame) { - Loader::Postgame = true; + Postgame = true; - auto components = Loader::Components; + auto components = Components; std::reverse(components.begin(), components.end()); - for (auto component : components) + for (auto& component : components) { component->preDestroy(); } @@ -161,17 +161,17 @@ namespace Components void Loader::PreDestroyNoPostGame() { - if (!Loader::Postgame) + if (!Postgame) { - auto components = Loader::Components; + auto components = Components; std::reverse(components.begin(), components.end()); - for (auto component : components) + for (auto& component : components) { component->preDestroy(); } - Loader::Postgame = true; + Postgame = true; } } @@ -181,7 +181,7 @@ namespace Components Logger::Print("Performing unit tests for components:\n"); - for (const auto component : Loader::Components) + for (const auto& component : Components) { #if defined(FORCE_UNIT_TESTS) Logger::Debug("Testing '{}'...\n", component->getName()); @@ -210,12 +210,12 @@ namespace Components if (component) { #if defined(DEBUG) || defined(FORCE_UNIT_TESTS) - if (!Loader::IsPerformingUnitTests()) + if (!IsPerformingUnitTests()) { Logger::Print("Component registered: {}\n", component->getName()); } #endif - Loader::Components.push_back(component); + Components.push_back(component); } } } diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index b45931db..33e84015 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -42,7 +42,7 @@ namespace Components template static T* GetInstance() { - for (auto& component : Loader::Components) + for (auto& component : Components) { if (typeid(*component) == typeid(T)) { @@ -61,87 +61,89 @@ namespace Components }; } -#include "Modules/Scheduler.hpp" +// Priority #include "Modules/Auth.hpp" -#include "Modules/Bans.hpp" -#include "Modules/Dvar.hpp" -#include "Modules/Bots.hpp" -#include "Modules/Lean.hpp" -#include "Modules/Maps.hpp" -#include "Modules/News.hpp" -#include "Modules/Flags.hpp" -#include "Modules/Menus.hpp" -#include "Modules/Toast.hpp" -#include "Modules/Zones.hpp" -#include "Modules/D3D9Ex.hpp" -#include "Modules/Weapon.hpp" -#include "Modules/Window.hpp" #include "Modules/Command.hpp" -#include "Modules/Console.hpp" -#include "Modules/UIScript.hpp" -#include "Modules/ModList.hpp" +#include "Modules/Dvar.hpp" +#include "Modules/Exception.hpp" +#include "Modules/Flags.hpp" #include "Modules/Network.hpp" -#include "Modules/NetworkDebug.hpp" -#include "Modules/Theatre.hpp" -#include "Modules/QuickPatch.hpp" -#include "Modules/Security.hpp" -#include "Modules/Node.hpp" -#include "Modules/RCon.hpp" -#include "Modules/Party.hpp" // Destroys the order, but requires network classes :D #include "Modules/Logger.hpp" -#include "Modules/Friends.hpp" -#include "Modules/IPCPipe.hpp" -#include "Modules/MapDump.hpp" -#include "Modules/Session.hpp" -#include "Modules/ClanTags.hpp" -#include "Modules/Download.hpp" -#include "Modules/Playlist.hpp" -#include "Modules/RawFiles.hpp" -#include "Modules/Renderer.hpp" -#include "Modules/UIFeeder.hpp" +#include "Modules/Singleton.hpp" +#include "Modules/UIScript.hpp" +#include "Modules/ZoneBuilder.hpp" + +#include "Modules/ArenaLength.hpp" +#include "Modules/AssetHandler.hpp" +#include "Modules/Bans.hpp" +#include "Modules/Bots.hpp" +#include "Modules/Branding.hpp" +#include "Modules/Bullet.hpp" +#include "Modules/CardTitles.hpp" +#include "Modules/Ceg.hpp" #include "Modules/Changelog.hpp" +#include "Modules/Chat.hpp" +#include "Modules/ClanTags.hpp" +#include "Modules/ClientCommand.hpp" +#include "Modules/ConnectProtocol.hpp" +#include "Modules/Console.hpp" +#include "Modules/D3D9Ex.hpp" +#include "Modules/Debug.hpp" #include "Modules/Dedicated.hpp" #include "Modules/Discovery.hpp" -#include "Modules/Exception.hpp" +#include "Modules/Download.hpp" +#include "Modules/Elevators.hpp" +#include "Modules/Events.hpp" #include "Modules/FastFiles.hpp" -#include "Modules/Gametypes.hpp" -#include "Modules/Materials.hpp" -#include "Modules/Singleton.hpp" -#include "Modules/Threading.hpp" -#include "Modules/CardTitles.hpp" #include "Modules/FileSystem.hpp" +#include "Modules/Friends.hpp" +#include "Modules/Gamepad.hpp" +#include "Modules/Gametypes.hpp" +#include "Modules/IPCPipe.hpp" +#include "Modules/Lean.hpp" +#include "Modules/Localization.hpp" +#include "Modules/MapDump.hpp" +#include "Modules/MapRotation.hpp" +#include "Modules/Maps.hpp" +#include "Modules/Materials.hpp" +#include "Modules/Menus.hpp" +#include "Modules/ModList.hpp" #include "Modules/ModelSurfs.hpp" +#include "Modules/NetworkDebug.hpp" +#include "Modules/News.hpp" +#include "Modules/Node.hpp" +#include "Modules/Party.hpp" +#include "Modules/PlayerMovement.hpp" #include "Modules/PlayerName.hpp" +#include "Modules/Playlist.hpp" +#include "Modules/QuickPatch.hpp" +#include "Modules/RCon.hpp" +#include "Modules/RawFiles.hpp" +#include "Modules/RawMouse.hpp" +#include "Modules/Renderer.hpp" +#include "Modules/Scheduler.hpp" +#include "Modules/Security.hpp" +#include "Modules/ServerCommands.hpp" #include "Modules/ServerInfo.hpp" #include "Modules/ServerList.hpp" +#include "Modules/Session.hpp" #include "Modules/SlowMotion.hpp" -#include "Modules/ArenaLength.hpp" -#include "Modules/StringTable.hpp" -#include "Modules/ZoneBuilder.hpp" -#include "Modules/AssetHandler.hpp" -#include "Modules/Localization.hpp" -#include "Modules/ServerCommands.hpp" -#include "Modules/StructuredData.hpp" -#include "Modules/ConnectProtocol.hpp" +#include "Modules/SoundMutexFix.hpp" #include "Modules/StartupMessages.hpp" #include "Modules/Stats.hpp" -#include "Modules/SoundMutexFix.hpp" -#include "Modules/Chat.hpp" +#include "Modules/StringTable.hpp" +#include "Modules/StructuredData.hpp" #include "Modules/TextRenderer.hpp" -#include "Modules/PlayerMovement.hpp" -#include "Modules/Elevators.hpp" -#include "Modules/ClientCommand.hpp" -#include "Modules/VisionFile.hpp" -#include "Modules/Gamepad.hpp" -#include "Modules/Branding.hpp" -#include "Modules/Debug.hpp" -#include "Modules/RawMouse.hpp" -#include "Modules/Bullet.hpp" -#include "Modules/MapRotation.hpp" -#include "Modules/Ceg.hpp" +#include "Modules/Theatre.hpp" +#include "Modules/Threading.hpp" +#include "Modules/Toast.hpp" +#include "Modules/UIFeeder.hpp" #include "Modules/UserInfo.hpp" -#include "Modules/Events.hpp" +#include "Modules/VisionFile.hpp" #include "Modules/Voice.hpp" #include "Modules/Vote.hpp" +#include "Modules/Weapon.hpp" +#include "Modules/Window.hpp" +#include "Modules/Zones.hpp" #include "Modules/GSC/GSC.hpp" diff --git a/src/Components/Modules/CardTitles.cpp b/src/Components/Modules/CardTitles.cpp index d4dcb8b0..5e00a4e4 100644 --- a/src/Components/Modules/CardTitles.cpp +++ b/src/Components/Modules/CardTitles.cpp @@ -2,7 +2,7 @@ namespace Components { - std::string CardTitles::CustomTitles[18]; + char CardTitles::CustomTitles[Game::MAX_CLIENTS][18]; Dvar::Var CardTitles::CustomTitle; CClient* CardTitles::GetClientByIndex(std::uint32_t index) @@ -10,35 +10,34 @@ namespace Components return &reinterpret_cast(0x8E77B0)[index]; } - std::int32_t CardTitles::GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data) + int CardTitles::GetPlayerCardClientInfo(int lookupResult, Game::PlayerCardData* data) { - std::int32_t returnResult = lookupResult; + auto result = lookupResult; - std::string username = Dvar::Var("name").get(); - - if (data->name == username) + const auto* username = Dvar::Var("name").get(); + if (std::strcmp(data->name, username) == 0) { - returnResult += 0xFE000000; + result += 0xFE000000; } else { - for (std::size_t clientNum = 0; clientNum < Game::MAX_CLIENTS; ++clientNum) + for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i) { - CClient* c = GetClientByIndex(clientNum); + CClient* c = GetClientByIndex(i); if (c != nullptr) { if (!std::strcmp(data->name, c->Name)) { // Since a 4 byte integer is overkill for a row num: We can use it to store the customprefix + clientNum and use a 2 byte integer for the row number - returnResult += 0xFF000000; - returnResult += clientNum * 0x10000; + result += 0xFF000000; + result += i * 0x10000; break; } } } } - return returnResult; + return result; } void __declspec(naked) CardTitles::GetPlayerCardClientInfoStub() @@ -71,7 +70,7 @@ namespace Components std::uint8_t prefix = (request->tableRow >> (8 * 3)) & 0xFF; std::uint8_t data = (request->tableRow >> (8 * 2)) & 0xFF; - if (data >= ARRAYSIZE(CardTitles::CustomTitles)) return nullptr; + if (data >= Game::MAX_CLIENTS) return nullptr; if (request->tablename == "mp/cardTitleTable.csv"s) { @@ -82,10 +81,10 @@ namespace Components { if (prefix == 0xFE) { - if (!CardTitles::CustomTitle.get().empty()) + if (!CustomTitle.get().empty()) { // 0xFF in front of the title to skip localization. Or else it will wait for a couple of seconds for the asset of type localize - const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitle.get()); + const auto* title = Utils::String::VA("\x15%s", CustomTitle.get()); // prepare return value operand->internals.stringVal.string = title; @@ -96,9 +95,9 @@ namespace Components } else if (prefix == 0xFF) { - if (!CardTitles::CustomTitles[data].empty()) + if (CustomTitles[data][0] != '\0') { - const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitles[data].data()); + const auto* title = Utils::String::VA("\x15%s", CustomTitles[data]); // prepare return value operand->internals.stringVal.string = title; @@ -156,11 +155,11 @@ namespace Components { std::string list; - for (std::size_t i = 0; i < Game::MAX_CLIENTS; i++) + for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i) { - char playerTitle[18]; + char playerTitle[18]{}; - if (Game::svs_clients[i].header.state >= Game::CS_CONNECTED) + if (Game::svs_clients[i].userinfo[0] != '\0') { strncpy_s(playerTitle, Game::Info_ValueForKey(Game::svs_clients[i].userinfo, "customTitle"), _TRUNCATE); } @@ -180,10 +179,17 @@ namespace Components { for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i) { - const char* playerTitle = Game::Info_ValueForKey(msg, std::to_string(i).c_str()); + const auto index = std::to_string(i); + const auto* playerTitle = Game::Info_ValueForKey(msg, index.data()); - if (playerTitle) CardTitles::CustomTitles[i] = playerTitle; - else CardTitles::CustomTitles[i].clear(); + if (playerTitle[0] == '\0') + { + CustomTitles[i][0] = '\0'; + } + else + { + Game::I_strncpyz(CustomTitles[i], playerTitle, sizeof(CustomTitles[0]) / sizeof(char)); + } } } @@ -191,16 +197,18 @@ namespace Components { Scheduler::Once([] { - CardTitles::CustomTitle = Dvar::Register("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title"); + CustomTitle = Dvar::Register("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title"); }, Scheduler::Pipeline::MAIN); + std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18])); + ServerCommands::OnCommand(21, [](Command::Params* params) { - if (params->get(1) == "customTitles"s && !Dedicated::IsEnabled()) + if (std::strcmp(params->get(1), "customTitles") == 0) { if (params->size() == 3) { - CardTitles::ParseCustomTitles(params->get(2)); + ParseCustomTitles(params->get(2)); return true; } } @@ -209,10 +217,10 @@ namespace Components }); - Utils::Hook(0x62EB26, CardTitles::GetPlayerCardClientInfoStub).install()->quick(); + Utils::Hook(0x62EB26, GetPlayerCardClientInfoStub).install()->quick(); // Table lookup stuff - Utils::Hook(0x62DCC1, CardTitles::TableLookupByRowHookStub).install()->quick(); + Utils::Hook(0x62DCC1, TableLookupByRowHookStub).install()->quick(); Utils::Hook::Nop(0x62DCC6, 1); } } diff --git a/src/Components/Modules/CardTitles.hpp b/src/Components/Modules/CardTitles.hpp index 7dcf5ce8..67b64495 100644 --- a/src/Components/Modules/CardTitles.hpp +++ b/src/Components/Modules/CardTitles.hpp @@ -14,27 +14,27 @@ namespace Components struct CClient { - std::uint32_t IsValid; // 0x0000 - std::uint32_t IsValid2; // 0x0004 - std::uint32_t ClientNumber; // 0x0008 - char Name[16]; // 0x000C - std::uint32_t Team; // 0x001C - std::uint32_t Team2; // 0x0020 - std::uint32_t Rank; // 0x0024 (rank - 1) - std::uint32_t Prestige; // 0x0028 - std::uint32_t Perks; // 0x002C - std::uint32_t Kills; // 0x0030 - std::uint32_t Score; // 0x0034 + std::uint32_t IsValid; // 0x0000 + std::uint32_t IsValid2; // 0x0004 + std::uint32_t ClientNumber; // 0x0008 + char Name[16]; // 0x000C + std::uint32_t Team; // 0x001C + std::uint32_t Team2; // 0x0020 + std::uint32_t Rank; // 0x0024 (rank - 1) + std::uint32_t Prestige; // 0x0028 + std::uint32_t Perks; // 0x002C + std::uint32_t Kills; // 0x0030 + std::uint32_t Score; // 0x0034 std::uint8_t _0x0038[968]; - std::uint32_t ViewAngles; // 0x0400 + std::uint32_t ViewAngles; // 0x0400 std::uint8_t _0x040C[136]; - std::uint32_t IsShooting; // 0x0494 + std::uint32_t IsShooting; // 0x0494 std::uint8_t _0x0498[4]; - std::uint32_t IsZoomed; // 0x049C + std::uint32_t IsZoomed; // 0x049C std::uint8_t _0x04A0[68]; - std::uint32_t weaponID; // 0x04E4 + std::uint32_t weaponID; // 0x04E4 std::uint8_t _0x04E8[24]; - std::uint32_t weaponID2; // 0x0500 + std::uint32_t weaponID2; // 0x0500 std::uint8_t _0x0504[40]; std::uint8_t _padding[8]; }; @@ -44,19 +44,20 @@ namespace Components public: AssertOffset(Game::PlayerCardData, Game::PlayerCardData::name, 0x1C); - static Dvar::Var CustomTitle; - static std::string CustomTitles[18]; - static void SendCustomTitlesToClients(); - static void ParseCustomTitles(const char* msg); CardTitles(); private: + static Dvar::Var CustomTitle; + static char CustomTitles[Game::MAX_CLIENTS][18]; + static CClient* GetClientByIndex(std::uint32_t index); - static std::int32_t GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data); + static int GetPlayerCardClientInfo(int lookupResult, Game::PlayerCardData* data); static void GetPlayerCardClientInfoStub(); static const char* TableLookupByRowHook(Game::Operand* operand, tablelookuprequest_s* request); static void TableLookupByRowHookStub(); + + static void ParseCustomTitles(const char* msg); }; } diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index dd96d737..857d0976 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -186,24 +186,24 @@ namespace Components } } - template<> Dvar::Var Dvar::Register(const char* dvarName, bool value, Flag flag, const char* description) + template<> Dvar::Var Dvar::Register(const char* dvarName, bool value, std::uint16_t flag, const char* description) { - return Game::Dvar_RegisterBool(dvarName, value, flag.val, description); + return Game::Dvar_RegisterBool(dvarName, value, flag, description); } - template<> Dvar::Var Dvar::Register(const char* dvarName, const char* value, Flag flag, const char* description) + template<> Dvar::Var Dvar::Register(const char* dvarName, const char* value, std::uint16_t flag, const char* description) { - return Game::Dvar_RegisterString(dvarName, value, flag.val, description); + return Game::Dvar_RegisterString(dvarName, value, flag, description); } - template<> Dvar::Var Dvar::Register(const char* dvarName, int value, int min, int max, Flag flag, const char* description) + template<> Dvar::Var Dvar::Register(const char* dvarName, int value, int min, int max, std::uint16_t flag, const char* description) { - return Game::Dvar_RegisterInt(dvarName, value, min, max, flag.val, description); + return Game::Dvar_RegisterInt(dvarName, value, min, max, flag, description); } - template<> Dvar::Var Dvar::Register(const char* dvarName, float value, float min, float max, Flag flag, const char* description) + template<> Dvar::Var Dvar::Register(const char* dvarName, float value, float min, float max, std::uint16_t flag, const char* description) { - return Game::Dvar_RegisterFloat(dvarName, value, min, max, flag.val, description); + return Game::Dvar_RegisterFloat(dvarName, value, min, max, flag, description); } void Dvar::ResetDvarsValue() diff --git a/src/Components/Modules/Dvar.hpp b/src/Components/Modules/Dvar.hpp index 7f97a842..a34154c6 100644 --- a/src/Components/Modules/Dvar.hpp +++ b/src/Components/Modules/Dvar.hpp @@ -5,15 +5,6 @@ namespace Components class Dvar : public Component { public: - class Flag - { - public: - Flag(Game::DvarFlags flag) : val(flag) {} - Flag(std::uint16_t flag) : Flag(static_cast(flag)) {} - - Game::DvarFlags val; - }; - class Var { public: @@ -44,8 +35,8 @@ namespace Components ~Dvar(); // Only strings and bools use this type of declaration - template static Var Register(const char* dvarName, T value, Flag flag, const char* description); - template static Var Register(const char* dvarName, T value, T min, T max, Flag flag, const char* description); + template static Var Register(const char* dvarName, T value, std::uint16_t flag, const char* description); + template static Var Register(const char* dvarName, T value, T min, T max, std::uint16_t flag, const char* description); static void ResetDvarsValue(); diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index f1d84b3d..c831f46f 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -7,20 +7,10 @@ namespace Components Utils::Hook Exception::SetFilterHook; int Exception::MiniDumpType; - __declspec(noreturn) void Exception::ErrorLongJmp(jmp_buf _Buf, int _Value) - { - if (!*reinterpret_cast(0x1AD7EB4)) - { - TerminateProcess(GetCurrentProcess(), 1337); - } - - longjmp(_Buf, _Value); - } - - __declspec(noreturn) void Exception::LongJmp(jmp_buf _Buf, int _Value) + __declspec(noreturn) void Exception::LongJmp_Internal_Stub(jmp_buf env, int status) { AssetHandler::ResetBypassState(); - longjmp(_Buf, _Value); + Game::longjmp_internal(env, status); } void Exception::SuspendProcess() @@ -76,7 +66,7 @@ namespace Components return; } - auto lock = GlobalLock(hMem); + auto* lock = GlobalLock(hMem); if (lock != nullptr) { std::memcpy(lock, error.data(), error.size() + 1); @@ -107,17 +97,15 @@ namespace Components errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.\nCopy exception address to clipboard?", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); } - //Exception::SuspendProcess(); - // Message should be copied to the keyboard if no button is pressed if (MessageBoxA(nullptr, errorStr.data(), nullptr, MB_YESNO | MB_ICONERROR) == IDYES) { - Exception::CopyMessageToClipboard(Utils::String::VA("0x%08X", ExceptionInfo->ExceptionRecord->ExceptionAddress)); + CopyMessageToClipboard(Utils::String::VA("0x%08X", ExceptionInfo->ExceptionRecord->ExceptionAddress)); } if (Flags::HasFlag("bigminidumps")) { - Exception::SetMiniDumpType(true, false); + SetMiniDumpType(true, false); } // Current executable name @@ -134,23 +122,22 @@ namespace Components _localtime64_s(<ime, &time); strftime(filenameFriendlyTime, sizeof(filenameFriendlyTime) - 1, "%Y%m%d%H%M%S", <ime); - // Combine with queuedMinidumpsFolder - char filename[MAX_PATH] = { 0 }; - Utils::IO::CreateDir("minidumps"); + // Combine with queued MinidumpsFolder + char filename[MAX_PATH]{}; + CreateDirectoryA("minidumps", nullptr); PathCombineA(filename, "minidumps\\", Utils::String::VA("%s-" VERSION "-%s.dmp", exeFileName, filenameFriendlyTime)); - DWORD fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE; + constexpr auto fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE; HANDLE hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ, fileShare, nullptr, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, nullptr); MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), ExceptionInfo, FALSE }; - if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast(Exception::MiniDumpType), &ex, nullptr, nullptr)) + if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast(MiniDumpType), &ex, nullptr, nullptr)) { - MessageBoxA(nullptr, Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError().data()), "Minidump Error", MB_OK | MB_ICONERROR); + MessageBoxA(nullptr, Utils::String::Format("There was an error creating the minidump ({})! Hit OK to close the program.", Utils::GetLastWindowsError()), "ERROR", MB_OK | MB_ICONERROR); OutputDebugStringA("Failed to create new minidump!"); Utils::OutputDebugLastError(); TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); } - //if (ExceptionInfo->ExceptionRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE) { TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); } @@ -158,54 +145,39 @@ namespace Components return EXCEPTION_CONTINUE_SEARCH; } - LPTOP_LEVEL_EXCEPTION_FILTER WINAPI Exception::SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER) - { - Exception::SetFilterHook.uninstall(); - LPTOP_LEVEL_EXCEPTION_FILTER retval = SetUnhandledExceptionFilter(&Exception::ExceptionFilter); - Exception::SetFilterHook.install(); - return retval; - } - - LPTOP_LEVEL_EXCEPTION_FILTER Exception::Hook() - { - return SetUnhandledExceptionFilter(&Exception::ExceptionFilter); - } - void Exception::SetMiniDumpType(bool codeseg, bool dataseg) { - Exception::MiniDumpType = MiniDumpIgnoreInaccessibleMemory; - Exception::MiniDumpType |= MiniDumpWithHandleData; - Exception::MiniDumpType |= MiniDumpScanMemory; - Exception::MiniDumpType |= MiniDumpWithProcessThreadData; - Exception::MiniDumpType |= MiniDumpWithFullMemoryInfo; - Exception::MiniDumpType |= MiniDumpWithThreadInfo; - //Exception::MiniDumpType |= MiniDumpWithModuleHeaders; + MiniDumpType = MiniDumpIgnoreInaccessibleMemory; + MiniDumpType |= MiniDumpWithHandleData; + MiniDumpType |= MiniDumpScanMemory; + MiniDumpType |= MiniDumpWithProcessThreadData; + MiniDumpType |= MiniDumpWithFullMemoryInfo; + MiniDumpType |= MiniDumpWithThreadInfo; if (codeseg) { - Exception::MiniDumpType |= MiniDumpWithCodeSegs; + MiniDumpType |= MiniDumpWithCodeSegs; } + if (dataseg) { - Exception::MiniDumpType |= MiniDumpWithDataSegs; + MiniDumpType |= MiniDumpWithDataSegs; } } Exception::Exception() { - Exception::SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); - -#if !defined(DEBUG) || defined(FORCE_EXCEPTION_HANDLER) - Exception::SetFilterHook.initialize(SetUnhandledExceptionFilter, Exception::SetUnhandledExceptionFilterStub, HOOK_JUMP); - Exception::SetFilterHook.install(); + SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); SetUnhandledExceptionFilter(&Exception::ExceptionFilter); -#endif - //Utils::Hook(0x4B241F, Exception::ErrorLongJmp, HOOK_CALL).install()->quick(); - Utils::Hook(0x6B8898, Exception::LongJmp, HOOK_JUMP).install()->quick(); + Utils::Hook(0x4B241F, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x61DB44, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x61F17D, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x61F248, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x61F5E7, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); -#ifdef _DEBUG +#ifdef MAP_TEST Command::Add("mapTest", [](Command::Params* params) { Game::UI_UpdateArenas(); @@ -227,6 +199,6 @@ namespace Components Exception::~Exception() { - Exception::SetFilterHook.uninstall(); + SetFilterHook.uninstall(); } } diff --git a/src/Components/Modules/Exception.hpp b/src/Components/Modules/Exception.hpp index 55a04c1f..20a5d0b7 100644 --- a/src/Components/Modules/Exception.hpp +++ b/src/Components/Modules/Exception.hpp @@ -15,9 +15,7 @@ namespace Components private: static void SuspendProcess(); static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo); - static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); - static __declspec(noreturn) void ErrorLongJmp(jmp_buf _Buf, int _Value); - static __declspec(noreturn) void LongJmp(jmp_buf _Buf, int _Value); + static __declspec(noreturn) void LongJmp_Internal_Stub(jmp_buf env, int status); static void CopyMessageToClipboard(const std::string& error); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 34128c5d..62c31846 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -319,7 +319,7 @@ namespace Components auto clientCount = 0; auto maxClientCount = *Game::svs_clientCount; const auto securityLevel = Dvar::Var("sv_securityLevel").get(); - const auto password = Dvar::Var("g_password").get(); + const auto* password = (*Game::g_password)->current.string; if (maxClientCount) { @@ -352,7 +352,7 @@ namespace Components info.set("shortversion", SHORTVERSION); info.set("checksum", std::to_string(Game::Sys_Milliseconds())); info.set("mapname", Dvar::Var("mapname").get()); - info.set("isPrivate", password.empty() ? "0" : "1"); + info.set("isPrivate", *password ? "1" : "0"); info.set("hc", (Dvar::Var("g_hardcore").get() ? "1" : "0")); info.set("securityLevel", std::to_string(securityLevel)); info.set("sv_running", (Dedicated::IsRunning() ? "1" : "0")); diff --git a/src/Components/Modules/Playlist.cpp b/src/Components/Modules/Playlist.cpp index 8e25475f..915042e2 100644 --- a/src/Components/Modules/Playlist.cpp +++ b/src/Components/Modules/Playlist.cpp @@ -9,26 +9,26 @@ namespace Components void Playlist::LoadPlaylist() { // Check if playlist already loaded - if (Utils::Hook::Get(0x1AD3680)) return; + if (*Game::s_havePlaylists) return; // Don't load playlists when dedi and no party if (Dedicated::IsEnabled() && !Dvar::Var("party_enable").get()) { - Utils::Hook::Set(0x1AD3680, true); // Set received to true + *Game::s_havePlaylists = true; Dvar::Var("xblive_privateserver").set(true); return; } Dvar::Var("xblive_privateserver").set(false); - auto playlistFilename = Dvar::Var("playlistFilename").get(); + const auto playlistFilename = Dvar::Var("playlistFilename").get(); FileSystem::File playlist(playlistFilename); if (playlist.exists()) { Logger::Print("Parsing playlist '{}'...\n", playlist.getName()); Game::Playlist_ParsePlaylists(playlist.getBuffer().data()); - Utils::Hook::Set(0x1AD3680, true); // Playlist loaded + *Game::s_havePlaylists = true; } else { @@ -36,18 +36,18 @@ namespace Components } } - DWORD Playlist::StorePlaylistStub(const char** buffer) + char* Playlist::Com_ParseOnLine_Hk(const char** data_p) { - Playlist::MapRelocation.clear(); - Playlist::CurrentPlaylistBuffer = Utils::Compression::ZLib::Compress(*buffer); - return Utils::Hook::Call(0x4C0350)(buffer); + MapRelocation.clear(); + CurrentPlaylistBuffer = Utils::Compression::ZLib::Compress(*data_p); + return Game::Com_ParseOnLine(data_p); } void Playlist::PlaylistRequest(const Network::Address& address, [[maybe_unused]] const std::string& data) { - const auto password = Dvar::Var("g_password").get(); + const auto* password = (*Game::g_password)->current.string; - if (password.length()) + if (*password) { if (password != data) { @@ -58,7 +58,7 @@ namespace Components Logger::Print("Received playlist request, sending currently stored buffer.\n"); - std::string compressedList = Playlist::CurrentPlaylistBuffer; + std::string compressedList = CurrentPlaylistBuffer; Proto::Party::Playlist list; list.set_hash(Utils::Cryptography::JenkinsOneAtATime::Compute(compressedList)); @@ -67,51 +67,48 @@ namespace Components Network::SendCommand(address, "playlistResponse", list.SerializeAsString()); } - void Playlist::PlaylistReponse(const Network::Address& address, [[maybe_unused]] const std::string& data) + void Playlist::PlaylistResponse(const Network::Address& address, [[maybe_unused]] const std::string& data) { - if (Party::PlaylistAwaiting()) + if (!Party::PlaylistAwaiting()) { - if (address == Party::Target()) - { - Proto::Party::Playlist list; + Logger::Print("Received stray playlist response, ignoring it.\n"); + return; + } + + if (address != Party::Target()) + { + Logger::Print("Received playlist from someone else than our target host, ignoring it.\n"); + return; + } + + Proto::Party::Playlist list; - if (!list.ParseFromString(data)) - { - Party::PlaylistError(Utils::String::VA("Received playlist response from %s, but it is invalid.", address.getCString())); - Playlist::ReceivedPlaylistBuffer.clear(); - return; - } - else - { - // Generate buffer and hash - const auto& compressedData = list.buffer(); - const auto hash = Utils::Cryptography::JenkinsOneAtATime::Compute(compressedData); - - //Validate hashes - if (hash != list.hash()) - { - Party::PlaylistError(Utils::String::VA("Received playlist response from %s, but the checksum did not match (%X != %X).", address.getCString(), list.hash(), hash)); - Playlist::ReceivedPlaylistBuffer.clear(); - return; - } - - // Decompress buffer - Playlist::ReceivedPlaylistBuffer = Utils::Compression::ZLib::Decompress(compressedData); - - // Load and continue connection - Logger::Print("Received playlist, loading and continuing connection...\n"); - Game::Playlist_ParsePlaylists(Playlist::ReceivedPlaylistBuffer.data()); - Party::PlaylistContinue(); - } - } - else - { - Logger::Print("Received playlist from someone else than our target host, ignoring it.\n"); - } + if (!list.ParseFromString(data)) + { + Party::PlaylistError(std::format("Received playlist response from {}, but it is invalid.", address.getString())); + ReceivedPlaylistBuffer.clear(); } else { - Logger::Print("Received stray playlist response, ignoring it.\n"); + // Generate buffer and hash + const auto& compressedData = list.buffer(); + const auto hash = Utils::Cryptography::JenkinsOneAtATime::Compute(compressedData); + + // Validate hashes + if (hash != list.hash()) + { + Party::PlaylistError(std::format("Received playlist response from {}, but the checksum did not match ({} != {}).", address.getString(), list.hash(), hash)); + ReceivedPlaylistBuffer.clear(); + return; + } + + // Decompress buffer + ReceivedPlaylistBuffer = Utils::Compression::ZLib::Decompress(compressedData); + + // Load and continue connection + Logger::Print("Received playlist, loading and continuing connection...\n"); + Game::Playlist_ParsePlaylists(ReceivedPlaylistBuffer.data()); + Party::PlaylistContinue(); } } @@ -120,27 +117,27 @@ namespace Components Party::PlaylistError("Error: Invalid Password for Party."); } - void Playlist::MapNameCopy(char *dest, const char *src, int destsize) + void Playlist::MapNameCopy(char* dest, const char* src, int destsize) { Utils::Hook::Call(0x4D6F80)(dest, src, destsize); - Playlist::MapRelocation[dest] = src; + MapRelocation[dest] = src; } - void Playlist::SetMapName(const char* cvar, const char* value) + void Playlist::SetMapName(const char* dvarName, const char* value) { - auto i = Playlist::MapRelocation.find(value); - if (i != Playlist::MapRelocation.end()) + auto i = MapRelocation.find(value); + if (i != MapRelocation.end()) { value = i->second.data(); } - Game::Dvar_SetStringByName(cvar, value); + Game::Dvar_SetStringByName(dvarName, value); } int Playlist::GetMapIndex(const char* mapname) { - auto i = Playlist::MapRelocation.find(mapname); - if (i != Playlist::MapRelocation.end()) + auto i = MapRelocation.find(mapname); + if (i != MapRelocation.end()) { mapname = i->second.data(); } @@ -153,7 +150,7 @@ namespace Components // Default playlists Utils::Hook::Set(0x60B06E, "playlists_default.info"); - // disable playlist download function + // Disable playlist download function Utils::Hook::Set(0x4D4790, 0xC3); // Load playlist, but don't delete it @@ -161,34 +158,34 @@ namespace Components Utils::Hook::Nop(0x4D6E67, 5); Utils::Hook::Nop(0x4D6E71, 2); - // playlist dvar 'validity check' + // Disable Playlist_ValidatePlaylistNum Utils::Hook::Set(0x4B1170, 0xC3); - // disable playlist checking - Utils::Hook::Set(0x5B69E9, 0xEB); // too new - Utils::Hook::Set(0x5B696E, 0xEB); // too old + // Disable playlist checking + Utils::Hook::Set(0x5B69E9, 0xEB); // Too new + Utils::Hook::Set(0x5B696E, 0xEB); // Too old - //Got playlists is true + // Got playlists is true //Utils::Hook::Set(0x1AD3680, true); - Utils::Hook(0x497DB5, Playlist::GetMapIndex, HOOK_CALL).install()->quick(); - Utils::Hook(0x42A19D, Playlist::MapNameCopy, HOOK_CALL).install()->quick(); - Utils::Hook(0x4A6FEE, Playlist::SetMapName, HOOK_CALL).install()->quick(); + Utils::Hook(0x497DB5, GetMapIndex, HOOK_CALL).install()->quick(); + Utils::Hook(0x42A19D, MapNameCopy, HOOK_CALL).install()->quick(); + Utils::Hook(0x4A6FEE, SetMapName, HOOK_CALL).install()->quick(); // Store playlist buffer on load - Utils::Hook(0x42961C, Playlist::StorePlaylistStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x42961C, Com_ParseOnLine_Hk, HOOK_CALL).install()->quick(); // Playlist_ParsePlaylists //if (Dedicated::IsDedicated()) { // Custom playlist loading - Utils::Hook(0x420B5A, Playlist::LoadPlaylist, HOOK_JUMP).install()->quick(); + Utils::Hook(0x420B5A, LoadPlaylist, HOOK_JUMP).install()->quick(); - // disable playlist.ff loading function - Utils::Hook::Set(0x4D6E60, 0xC3); + // disable playlist.ff loading function (Win_LoadPlaylistFastfile) + Utils::Hook::Set(0x4D6E60, 0xC3); } Network::OnClientPacket("getPlaylist", PlaylistRequest); - Network::OnClientPacket("playlistResponse", PlaylistReponse); + Network::OnClientPacket("playlistResponse", PlaylistResponse); Network::OnClientPacket("playlistInvalidPassword", PlaylistInvalidPassword); } } diff --git a/src/Components/Modules/Playlist.hpp b/src/Components/Modules/Playlist.hpp index f4948d0e..397fd807 100644 --- a/src/Components/Modules/Playlist.hpp +++ b/src/Components/Modules/Playlist.hpp @@ -17,14 +17,14 @@ namespace Components static std::string CurrentPlaylistBuffer; static std::unordered_map MapRelocation; - static DWORD StorePlaylistStub(const char** buffer); + static char* Com_ParseOnLine_Hk(const char** data_p); static void PlaylistRequest(const Network::Address& address, const std::string& data); - static void PlaylistReponse(const Network::Address& address, const std::string& data); + static void PlaylistResponse(const Network::Address& address, const std::string& data); static void PlaylistInvalidPassword(const Network::Address& address, const std::string& data); - static void MapNameCopy(char *dest, const char *src, int destsize); - static void SetMapName(const char* cvar, const char* value); + static void MapNameCopy(char* dest, const char* src, int destsize); + static void SetMapName(const char* dvarName, const char* value); static int GetMapIndex(const char* mapname); }; } diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index e161ab5c..59593d18 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -131,7 +131,7 @@ namespace Components Utils::InfoString ServerInfo::GetInfo() { auto maxClientCount = *Game::svs_clientCount; - const auto password = Dvar::Var("g_password").get(); + const auto* password = (*Game::g_password)->current.string; if (!maxClientCount) { @@ -145,7 +145,7 @@ namespace Components info.set("shortversion", SHORTVERSION); info.set("version", (*Game::version)->current.string); info.set("mapname", (*Game::sv_mapname)->current.string); - info.set("isPrivate", password.empty() ? "0" : "1"); + info.set("isPrivate", *password ? "1" : "0"); info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds())))); info.set("aimAssist", (Gamepad::sv_allowAimAssist.get() ? "1" : "0")); info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0")); diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index d0b0cefd..aa362c5d 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -17,7 +17,7 @@ namespace Components { printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); printf("%d\n", REVISION); - ExitProcess(0); + std::exit(0); } Console::FreeNativeConsole(); @@ -28,7 +28,7 @@ namespace Components if (!FirstInstance && !ConnectProtocol::Used() && MessageBoxA(nullptr, "Do you want to start another instance?\nNot all features will be available!", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) { - ExitProcess(0); + std::exit(0); } } } diff --git a/src/DllMain.cpp b/src/DllMain.cpp index 16c2f485..eadda265 100644 --- a/src/DllMain.cpp +++ b/src/DllMain.cpp @@ -49,7 +49,6 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser if (fdwReason == DLL_PROCESS_ATTACH) { SetProcessDEPPolicy(PROCESS_DEP_ENABLE); - Steam::Proxy::RunMod(); std::srand(std::uint32_t(std::time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId())); @@ -72,6 +71,7 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser } #endif + Steam::Proxy::RunMod(); // Install entry point hook Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick(); } diff --git a/src/Game/Common.cpp b/src/Game/Common.cpp index b9b626c2..123fb859 100644 --- a/src/Game/Common.cpp +++ b/src/Game/Common.cpp @@ -31,6 +31,8 @@ namespace Game int* com_errorPrintsCount = reinterpret_cast(0x1AD7910); + int* errorcode = reinterpret_cast(0x1AD7EB4); + char* Com_GetParseThreadInfo() { if (Sys_IsMainThread()) diff --git a/src/Game/Common.hpp b/src/Game/Common.hpp index 012e5f07..8698d685 100644 --- a/src/Game/Common.hpp +++ b/src/Game/Common.hpp @@ -35,7 +35,7 @@ namespace Game typedef void(*Com_BeginParseSession_t)(const char* filename); extern Com_BeginParseSession_t Com_BeginParseSession; - typedef char* (*Com_ParseOnLine_t)(const char** data_p); + typedef char*(*Com_ParseOnLine_t)(const char** data_p); extern Com_ParseOnLine_t Com_ParseOnLine; typedef void(*Com_SkipRestOfLine_t)(const char** data); @@ -71,6 +71,8 @@ namespace Game extern int* com_errorPrintsCount; + extern int* errorcode; + extern char* Com_GetParseThreadInfo(); extern void Com_SetParseNegativeNumbers(int parse); diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp index 8f63be0f..038308e0 100644 --- a/src/Game/Dvars.cpp +++ b/src/Game/Dvars.cpp @@ -52,6 +52,7 @@ namespace Game const dvar_t** g_allowVote = reinterpret_cast(0x19BD644); const dvar_t** g_oldVoting = reinterpret_cast(0x1A45DEC); const dvar_t** g_gametype = reinterpret_cast(0x1A45DC8); + const dvar_t** g_password = reinterpret_cast(0x18835C0); const dvar_t** version = reinterpret_cast(0x1AD7930); diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp index e8532b86..b3397ebd 100644 --- a/src/Game/Dvars.hpp +++ b/src/Game/Dvars.hpp @@ -108,6 +108,7 @@ namespace Game extern const dvar_t** g_allowVote; extern const dvar_t** g_oldVoting; extern const dvar_t** g_gametype; + extern const dvar_t** g_password; extern const dvar_t** version; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 75b6cdd7..a87789a6 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -268,6 +268,8 @@ namespace Game LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140); LargeLocalReset_t LargeLocalReset = LargeLocalReset_t(0x430630); + longjmp_internal_t longjmp_internal = longjmp_internal_t(0x6B8898); + CmdArgs* cmd_args = reinterpret_cast(0x1AAC5D0); CmdArgs* sv_cmd_args = reinterpret_cast(0x1ACF8A0); @@ -405,6 +407,8 @@ namespace Game punctuation_s* default_punctuations = reinterpret_cast(0x797F80); + bool* s_havePlaylists = reinterpret_cast(0x1AD3680); + const char* TableLookup(StringTable* stringtable, int row, int column) { if (!stringtable || !stringtable->values || row >= stringtable->rowCount || column >= stringtable->columnCount) return ""; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index ae9d6323..6f84f841 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -593,6 +593,9 @@ namespace Game typedef void(*LargeLocalReset_t)(); extern LargeLocalReset_t LargeLocalReset; + typedef void(*longjmp_internal_t)(jmp_buf env, int status); + extern longjmp_internal_t longjmp_internal; + constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1; constexpr std::size_t MAX_LOCAL_CLIENTS = 1; constexpr std::size_t MAX_CLIENTS = 18; @@ -739,6 +742,8 @@ namespace Game extern punctuation_s* default_punctuations; + extern bool* s_havePlaylists; + constexpr auto MAX_MSGLEN = 0x20000; ScreenPlacement* ScrPlace_GetFullPlacement(); From 0539fe3e241020356888b2bfe590dc345864bde9 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 25 Dec 2022 19:38:43 +0100 Subject: [PATCH 80/96] [Exception]: Remove this (#668) --- src/Components/Modules/Exception.cpp | 2 +- src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/Party.hpp | 2 +- src/Game/Structs.hpp | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index c831f46f..6c9d30f4 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -169,7 +169,7 @@ namespace Components { SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); - SetUnhandledExceptionFilter(&Exception::ExceptionFilter); + SetUnhandledExceptionFilter(&ExceptionFilter); Utils::Hook(0x4B241F, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); Utils::Hook(0x61DB44, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 62c31846..bf6d7d6e 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -77,7 +77,7 @@ namespace Components return Party::Container.motd; } - Game::dvar_t* Party::RegisterMinPlayers(const char* name, int /*value*/, int /*min*/, int max, Game::DvarFlags flag, const char* description) + Game::dvar_t* Party::RegisterMinPlayers(const char* name, int /*value*/, int /*min*/, int max, unsigned __int16 flag, const char* description) { return Dvar::Register(name, 1, 1, max, Game::DVAR_INIT | flag, description).get(); } diff --git a/src/Components/Modules/Party.hpp b/src/Components/Modules/Party.hpp index dada08a8..3287cecd 100644 --- a/src/Components/Modules/Party.hpp +++ b/src/Components/Modules/Party.hpp @@ -50,7 +50,7 @@ namespace Components static SteamID GenerateLobbyId(); - static Game::dvar_t* RegisterMinPlayers(const char* name, int value, int min, int max, Game::DvarFlags flag, const char* description); + static Game::dvar_t* RegisterMinPlayers(const char* name, int value, int min, int max, unsigned __int16 flag, const char* description); static DWORD UIDvarIntStub(char* dvar); }; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 669d474b..8b12092c 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -27,8 +27,8 @@ namespace Game unsigned __int16 classnum; }; - typedef void(__cdecl* BuiltinFunction)(); - typedef void(__cdecl* BuiltinMethod)(scr_entref_t); + typedef void(*BuiltinFunction)(); + typedef void(*BuiltinMethod)(scr_entref_t); struct BuiltinFunctionDef { @@ -383,7 +383,7 @@ namespace Game SURF_TYPE_COUNT }; - enum DvarFlags : unsigned __int16 + enum : unsigned __int16 { DVAR_NONE = 0, // No flags DVAR_ARCHIVE = 1 << 0, // Set to cause it to be saved to config_mp.cfg of the client From f70c02b42ee8c66191a7ea4d392573bb741b782a Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 26 Dec 2022 13:07:24 +0100 Subject: [PATCH 81/96] [Scheduler]: Use enum class & more (#669) --- src/Components/Loader.cpp | 53 ++++++++++- src/Components/Loader.hpp | 50 ---------- src/Components/Modules/AssetHandler.cpp | 1 + src/Components/Modules/Auth.cpp | 1 + src/Components/Modules/Bans.cpp | 1 + src/Components/Modules/Bots.cpp | 2 + src/Components/Modules/Branding.cpp | 1 + src/Components/Modules/Bullet.cpp | 1 + src/Components/Modules/CardTitles.cpp | 2 + src/Components/Modules/Ceg.cpp | 1 + src/Components/Modules/Changelog.cpp | 4 +- src/Components/Modules/Chat.cpp | 4 + src/Components/Modules/ClanTags.cpp | 3 + src/Components/Modules/ClientCommand.cpp | 2 + src/Components/Modules/ConnectProtocol.cpp | 1 + src/Components/Modules/Console.cpp | 1 + src/Components/Modules/D3D9Ex.cpp | 1 + src/Components/Modules/Debug.cpp | 16 +++- src/Components/Modules/Debug.hpp | 3 +- src/Components/Modules/Dedicated.cpp | 3 + src/Components/Modules/Discovery.cpp | 2 + src/Components/Modules/Download.cpp | 2 + src/Components/Modules/Dvar.cpp | 12 ++- src/Components/Modules/Elevators.cpp | 1 + src/Components/Modules/Exception.cpp | 1 + src/Components/Modules/Friends.cpp | 1 + src/Components/Modules/Gamepad.cpp | 2 + src/Components/Modules/Gametypes.cpp | 102 --------------------- src/Components/Modules/Gametypes.hpp | 17 ---- src/Components/Modules/Lean.cpp | 1 + src/Components/Modules/Logger.cpp | 1 + src/Components/Modules/MapDump.cpp | 24 +---- src/Components/Modules/MapRotation.cpp | 1 + src/Components/Modules/Maps.cpp | 4 + src/Components/Modules/ModList.cpp | 1 + src/Components/Modules/NetworkDebug.cpp | 1 + src/Components/Modules/News.cpp | 2 + src/Components/Modules/Node.cpp | 2 + src/Components/Modules/Party.cpp | 5 + src/Components/Modules/PlayerMovement.cpp | 2 + src/Components/Modules/PlayerName.cpp | 2 + src/Components/Modules/Playlist.cpp | 1 + src/Components/Modules/QuickPatch.cpp | 1 + src/Components/Modules/RCon.cpp | 1 + src/Components/Modules/RawFiles.cpp | 1 + src/Components/Modules/RawMouse.cpp | 22 +++-- src/Components/Modules/Scheduler.cpp | 8 +- src/Components/Modules/Scheduler.hpp | 2 +- src/Components/Modules/Security.cpp | 1 + src/Components/Modules/ServerCommands.cpp | 1 + src/Components/Modules/ServerInfo.cpp | 5 + src/Components/Modules/ServerList.cpp | 3 + src/Components/Modules/Session.cpp | 1 + src/Components/Modules/Singleton.cpp | 2 + src/Components/Modules/SlowMotion.cpp | 1 + src/Components/Modules/SoundMutexFix.cpp | 5 +- src/Components/Modules/StartupMessages.cpp | 1 + src/Components/Modules/Stats.cpp | 3 + src/Components/Modules/StringTable.cpp | 15 +-- src/Components/Modules/StructuredData.cpp | 1 + src/Components/Modules/Theatre.cpp | 2 + src/Components/Modules/Threading.cpp | 1 + src/Components/Modules/UIFeeder.cpp | 1 + src/Components/Modules/UserInfo.cpp | 2 + src/Components/Modules/VisionFile.cpp | 1 + src/Components/Modules/Voice.cpp | 1 + src/Components/Modules/Vote.cpp | 3 + src/Components/Modules/Weapon.cpp | 2 + src/Components/Modules/ZoneBuilder.cpp | 1 + src/Steam/Steam.cpp | 1 + 70 files changed, 205 insertions(+), 222 deletions(-) delete mode 100644 src/Components/Modules/Gametypes.cpp delete mode 100644 src/Components/Modules/Gametypes.hpp diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index ef452178..5c244e66 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -1,5 +1,55 @@ #include +#include "Modules/Bans.hpp" +#include "Modules/Bots.hpp" +#include "Modules/Branding.hpp" +#include "Modules/Bullet.hpp" +#include "Modules/CardTitles.hpp" +#include "Modules/Ceg.hpp" +#include "Modules/Changelog.hpp" +#include "Modules/Chat.hpp" +#include "Modules/ClanTags.hpp" +#include "Modules/ClientCommand.hpp" +#include "Modules/ConnectProtocol.hpp" +#include "Modules/Console.hpp" +#include "Modules/D3D9Ex.hpp" +#include "Modules/Debug.hpp" +#include "Modules/Discovery.hpp" +#include "Modules/Download.hpp" +#include "Modules/Elevators.hpp" +#include "Modules/Gamepad.hpp" +#include "Modules/Lean.hpp" +#include "Modules/MapDump.hpp" +#include "Modules/MapRotation.hpp" +#include "Modules/NetworkDebug.hpp" +#include "Modules/News.hpp" +#include "Modules/PlayerMovement.hpp" +#include "Modules/PlayerName.hpp" +#include "Modules/Playlist.hpp" +#include "Modules/QuickPatch.hpp" +#include "Modules/RawFiles.hpp" +#include "Modules/RawMouse.hpp" +#include "Modules/RCon.hpp" +#include "Modules/Security.hpp" +#include "Modules/ServerCommands.hpp" +#include "Modules/ServerInfo.hpp" +#include "Modules/ServerList.hpp" +#include "Modules/Session.hpp" +#include "Modules/SlowMotion.hpp" +#include "Modules/SoundMutexFix.hpp" +#include "Modules/StartupMessages.hpp" +#include "Modules/Stats.hpp" +#include "Modules/StringTable.hpp" +#include "Modules/StructuredData.hpp" +#include "Modules/Theatre.hpp" +#include "Modules/Threading.hpp" +#include "Modules/UIFeeder.hpp" +#include "Modules/UserInfo.hpp" +#include "Modules/VisionFile.hpp" +#include "Modules/Voice.hpp" +#include "Modules/Vote.hpp" +#include "Modules/Weapon.hpp" + namespace Components { bool Loader::Pregame = true; @@ -65,7 +115,6 @@ namespace Components Register(new FileSystem()); Register(new Friends()); Register(new Gamepad()); - Register(new Gametypes()); Register(new IPCPipe()); Register(new Lean()); Register(new Localization()); @@ -84,9 +133,9 @@ namespace Components Register(new PlayerName()); Register(new Playlist()); Register(new QuickPatch()); - Register(new RCon()); Register(new RawFiles()); Register(new RawMouse()); + Register(new RCon()); Register(new Renderer()); Register(new Scheduler()); Register(new Security()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 33e84015..4957c9df 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -75,74 +75,24 @@ namespace Components #include "Modules/ArenaLength.hpp" #include "Modules/AssetHandler.hpp" -#include "Modules/Bans.hpp" -#include "Modules/Bots.hpp" -#include "Modules/Branding.hpp" -#include "Modules/Bullet.hpp" -#include "Modules/CardTitles.hpp" -#include "Modules/Ceg.hpp" -#include "Modules/Changelog.hpp" -#include "Modules/Chat.hpp" -#include "Modules/ClanTags.hpp" -#include "Modules/ClientCommand.hpp" -#include "Modules/ConnectProtocol.hpp" -#include "Modules/Console.hpp" -#include "Modules/D3D9Ex.hpp" -#include "Modules/Debug.hpp" #include "Modules/Dedicated.hpp" -#include "Modules/Discovery.hpp" -#include "Modules/Download.hpp" -#include "Modules/Elevators.hpp" #include "Modules/Events.hpp" #include "Modules/FastFiles.hpp" #include "Modules/FileSystem.hpp" #include "Modules/Friends.hpp" -#include "Modules/Gamepad.hpp" -#include "Modules/Gametypes.hpp" #include "Modules/IPCPipe.hpp" -#include "Modules/Lean.hpp" #include "Modules/Localization.hpp" -#include "Modules/MapDump.hpp" -#include "Modules/MapRotation.hpp" #include "Modules/Maps.hpp" #include "Modules/Materials.hpp" #include "Modules/Menus.hpp" #include "Modules/ModList.hpp" #include "Modules/ModelSurfs.hpp" -#include "Modules/NetworkDebug.hpp" -#include "Modules/News.hpp" #include "Modules/Node.hpp" #include "Modules/Party.hpp" -#include "Modules/PlayerMovement.hpp" -#include "Modules/PlayerName.hpp" -#include "Modules/Playlist.hpp" -#include "Modules/QuickPatch.hpp" -#include "Modules/RCon.hpp" -#include "Modules/RawFiles.hpp" -#include "Modules/RawMouse.hpp" #include "Modules/Renderer.hpp" #include "Modules/Scheduler.hpp" -#include "Modules/Security.hpp" -#include "Modules/ServerCommands.hpp" -#include "Modules/ServerInfo.hpp" -#include "Modules/ServerList.hpp" -#include "Modules/Session.hpp" -#include "Modules/SlowMotion.hpp" -#include "Modules/SoundMutexFix.hpp" -#include "Modules/StartupMessages.hpp" -#include "Modules/Stats.hpp" -#include "Modules/StringTable.hpp" -#include "Modules/StructuredData.hpp" #include "Modules/TextRenderer.hpp" -#include "Modules/Theatre.hpp" -#include "Modules/Threading.hpp" #include "Modules/Toast.hpp" -#include "Modules/UIFeeder.hpp" -#include "Modules/UserInfo.hpp" -#include "Modules/VisionFile.hpp" -#include "Modules/Voice.hpp" -#include "Modules/Vote.hpp" -#include "Modules/Weapon.hpp" #include "Modules/Window.hpp" #include "Modules/Zones.hpp" diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index 94220280..baf089bf 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -1,4 +1,5 @@ #include +#include "Weapon.hpp" #include "AssetInterfaces/IFont_s.hpp" #include "AssetInterfaces/IWeapon.hpp" diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index e4c61044..9bf90a68 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -1,4 +1,5 @@ #include +#include "Bans.hpp" namespace Components { diff --git a/src/Components/Modules/Bans.cpp b/src/Components/Modules/Bans.cpp index e6674800..955fbe81 100644 --- a/src/Components/Modules/Bans.cpp +++ b/src/Components/Modules/Bans.cpp @@ -1,4 +1,5 @@ #include +#include "Bans.hpp" namespace Components { diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 5caf68fd..3eb92273 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -1,4 +1,6 @@ #include +#include "Bots.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index 63d766e2..0c293357 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -1,4 +1,5 @@ #include +#include "Branding.hpp" #include diff --git a/src/Components/Modules/Bullet.cpp b/src/Components/Modules/Bullet.cpp index d804b93b..881cef52 100644 --- a/src/Components/Modules/Bullet.cpp +++ b/src/Components/Modules/Bullet.cpp @@ -1,4 +1,5 @@ #include +#include "Bullet.hpp" namespace Components { diff --git a/src/Components/Modules/CardTitles.cpp b/src/Components/Modules/CardTitles.cpp index 5e00a4e4..37e9045c 100644 --- a/src/Components/Modules/CardTitles.cpp +++ b/src/Components/Modules/CardTitles.cpp @@ -1,4 +1,6 @@ #include +#include "CardTitles.hpp" +#include "ServerCommands.hpp" namespace Components { diff --git a/src/Components/Modules/Ceg.cpp b/src/Components/Modules/Ceg.cpp index ad5b21cc..cf765d2b 100644 --- a/src/Components/Modules/Ceg.cpp +++ b/src/Components/Modules/Ceg.cpp @@ -1,4 +1,5 @@ #include +#include "Ceg.hpp" namespace Components { diff --git a/src/Components/Modules/Changelog.cpp b/src/Components/Modules/Changelog.cpp index fd82a21c..10851346 100644 --- a/src/Components/Modules/Changelog.cpp +++ b/src/Components/Modules/Changelog.cpp @@ -1,4 +1,6 @@ #include +#include "Changelog.hpp" +#include "UIFeeder.hpp" namespace Components { @@ -54,6 +56,6 @@ namespace Components if (Dedicated::IsEnabled()) return; // Changelog - UIFeeder::Add(62.0f, Changelog::GetChangelogCount, Changelog::GetChangelogText, Changelog::SelectChangelog); + UIFeeder::Add(62.0f, GetChangelogCount, GetChangelogText, SelectChangelog); } } diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 4cb1b3e9..ef7e8eb3 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -1,4 +1,8 @@ #include +#include "Chat.hpp" +#include "PlayerName.hpp" +#include "Voice.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index eda87643..dfa3a664 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -1,4 +1,7 @@ #include +#include "ClanTags.hpp" +#include "PlayerName.hpp" +#include "ServerCommands.hpp" namespace Components { diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index a005cdca..5de247e1 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -1,4 +1,6 @@ #include +#include "ClientCommand.hpp" + #include "GSC/Script.hpp" using namespace Utils::String; diff --git a/src/Components/Modules/ConnectProtocol.cpp b/src/Components/Modules/ConnectProtocol.cpp index fd3c9a77..1542b28e 100644 --- a/src/Components/Modules/ConnectProtocol.cpp +++ b/src/Components/Modules/ConnectProtocol.cpp @@ -1,4 +1,5 @@ #include +#include "ConnectProtocol.hpp" namespace Components { diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index 1a4e105a..04c5b418 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -1,4 +1,5 @@ #include +#include "Console.hpp" #include diff --git a/src/Components/Modules/D3D9Ex.cpp b/src/Components/Modules/D3D9Ex.cpp index 6903e23a..ca5f296f 100644 --- a/src/Components/Modules/D3D9Ex.cpp +++ b/src/Components/Modules/D3D9Ex.cpp @@ -1,4 +1,5 @@ #include +#include "D3D9Ex.hpp" namespace Components { diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index 14eec5a3..e35024c7 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -1,4 +1,6 @@ #include +#include "Debug.hpp" + #include "Game/Engine/ScopedCriticalSection.hpp" namespace Components @@ -6,7 +8,7 @@ namespace Components const Game::dvar_t* Debug::DebugOverlay; const Game::dvar_t* Debug::BugName; - Game::dvar_t** Debug::PlayerDebugHealth = reinterpret_cast(0x7A9F7C); + const Game::dvar_t* Debug::PlayerDebugHealth; const char* Debug::PMFlagsValues[] = { @@ -182,7 +184,7 @@ namespace Components constexpr float color1[] = {0.0f, 0.0f, 0.0f, 1.0f}; constexpr float color2[] = {0.0f, 1.0f, 0.0f, 1.0f}; - assert((*PlayerDebugHealth)->current.enabled); + assert(PlayerDebugHealth->current.enabled); const auto* cgameGlob = Game::cgArray; if (cgameGlob->predictedPlayerState.stats[0] && cgameGlob->predictedPlayerState.stats[2]) @@ -254,7 +256,7 @@ namespace Components break; } - if ((*PlayerDebugHealth)->current.enabled) + if (PlayerDebugHealth->current.enabled) { CG_DrawDebugPlayerHealth(localClientNum); } @@ -348,6 +350,12 @@ namespace Components Game::DVAR_CHEAT | Game::DVAR_CODINFO, "Name appended to the copied console log"); } + const Game::dvar_t* Debug::Dvar_Register_PlayerDebugHealth(const char* name, bool value, [[maybe_unused]] std::uint16_t flags, const char* description) + { + PlayerDebugHealth = Game::Dvar_RegisterBool(name, value, Game::DVAR_NONE, description); + return PlayerDebugHealth; + } + Debug::Debug() { Scheduler::Once(CL_InitDebugDvars, Scheduler::Pipeline::MAIN); @@ -357,6 +365,8 @@ namespace Components Utils::Hook::Set(0x60BCEA, Com_Assert_f); + Utils::Hook(0x4487F7, Dvar_Register_PlayerDebugHealth, HOOK_CALL).install()->quick(); + #ifdef _DEBUG Command::Add("bug", Com_Bug_f); Command::Add("bug_name_inc", Com_BugNameInc_f); diff --git a/src/Components/Modules/Debug.hpp b/src/Components/Modules/Debug.hpp index 893eb25b..eb846014 100644 --- a/src/Components/Modules/Debug.hpp +++ b/src/Components/Modules/Debug.hpp @@ -12,7 +12,7 @@ namespace Components static const Game::dvar_t* BugName; // Game dvars - static Game::dvar_t** PlayerDebugHealth; + static const Game::dvar_t* PlayerDebugHealth; static const char* PMFlagsValues[]; static const char* POFlagsValues[]; @@ -46,5 +46,6 @@ namespace Components static void Com_BugNameInc_f(); static void CL_InitDebugDvars(); + static const Game::dvar_t* Dvar_Register_PlayerDebugHealth(const char* name, bool value, std::uint16_t flags, const char* description); }; } diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 493275ba..589aa997 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -1,4 +1,7 @@ #include +#include "CardTitles.hpp" +#include "ClanTags.hpp" +#include "ServerCommands.hpp" namespace Components { diff --git a/src/Components/Modules/Discovery.cpp b/src/Components/Modules/Discovery.cpp index 14737a18..86bee2ee 100644 --- a/src/Components/Modules/Discovery.cpp +++ b/src/Components/Modules/Discovery.cpp @@ -1,4 +1,6 @@ #include +#include "Discovery.hpp" +#include "ServerList.hpp" namespace Components { diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index ecccc77d..a1fc0c8e 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -1,4 +1,6 @@ #include +#include "Download.hpp" +#include "ServerInfo.hpp" #include diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 857d0976..182afc13 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -230,7 +230,7 @@ namespace Components if (name == lastValidName) return; Utils::String::Trim(name); - std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(name)); + auto saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(name)); if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{')) { Logger::PrintError(Game::CON_CHANNEL_ERROR, "Username '{}' is invalid. It must at least be 3 characters long and not appear empty!\n", name); @@ -241,7 +241,7 @@ namespace Components lastValidName = name; Friends::UpdateName(); } - }, Scheduler::CLIENT, 3s); // Don't need to do this every frame + }, Scheduler::Pipeline::CLIENT, 3s); // Don't need to do this every frame } std::string username = "Unknown Soldier"; @@ -393,13 +393,19 @@ namespace Components // un-cheat cg_fovscale and add archive flags Utils::Hook::Xor(0x4F8E68, Game::DVAR_CHEAT | Game::DVAR_ARCHIVE); + // un-cheat cg_fovMin and add archive flags + Utils::Hook::Xor(0x4F8E9D, Game::DVAR_CHEAT | Game::DVAR_ARCHIVE); + // un-cheat cg_debugInfoCornerOffset and add archive flags Utils::Hook::Xor(0x4F8FC2, Game::DVAR_CHEAT | Game::DVAR_ARCHIVE); // un-cheat cg_drawGun Utils::Hook::Set(0x4F8DC6, Game::DVAR_NONE); - // remove archive flags for cg_hudchatposition + // un-cheat cg_draw2D + Utils::Hook::Set(0x4F8EEE, Game::DVAR_NONE); + + // remove archive flags for cg_hudChatPosition Utils::Hook::Xor(0x4F9992, Game::DVAR_ARCHIVE); // remove write protection from fs_game diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp index dfd09a33..5c4d80da 100644 --- a/src/Components/Modules/Elevators.cpp +++ b/src/Components/Modules/Elevators.cpp @@ -1,4 +1,5 @@ #include +#include "Elevators.hpp" namespace Components { diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index 6c9d30f4..5fbfb89a 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -1,4 +1,5 @@ #include +#include "Console.hpp" #include diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index 29c3f77a..db4a9c27 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -1,4 +1,5 @@ #include +#include "UIFeeder.hpp" namespace Components { diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index e749053e..e352a28a 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -1,4 +1,6 @@ #include +#include "Gamepad.hpp" +#include "RawMouse.hpp" namespace Components { diff --git a/src/Components/Modules/Gametypes.cpp b/src/Components/Modules/Gametypes.cpp deleted file mode 100644 index df8e6735..00000000 --- a/src/Components/Modules/Gametypes.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include - -namespace Components -{ - unsigned int Gametypes::GetGametypeCount() - { - return *Game::gameTypeCount; - } - - const char* Gametypes::GetGametypeText(unsigned int index, int) - { - if (static_cast(*Game::gameTypeCount) > index) - { - return Game::SEH_StringEd_GetString(Game::gameTypes[index].uiName); - } - - return ""; - } - - void Gametypes::SelectGametype(unsigned int index) - { - if (!*Game::gameTypeCount) return; - if (static_cast(*Game::gameTypeCount) <= index) index = 0; - - std::string gametype = Game::gameTypes[index].gameType; - - Dvar::Var("ui_gametype").set(gametype); - //Dvar::Var("g_gametype").set(gametype); - } - - void* Gametypes::BuildGametypeList(const char*, void* buffer, size_t size) - { - std::vector gametypes; - - auto pushGametype = [&](std::string gametype) - { - auto pos = gametype.find_last_of("/\\"); - if (pos != std::string::npos) - { - gametype = gametype.substr(pos + 1); - } - - if (Utils::String::EndsWith(gametype, ".txt")) - { - gametype = gametype.substr(0, gametype.size() - 4); - } - - // No need for that :) - if (gametype == "_gametypes") return; - - if (std::find(gametypes.begin(), gametypes.end(), gametype) == gametypes.end()) - { - gametypes.push_back(gametype); - } - }; - - // Get the gametypes we can find in the filesystem - std::vector rawGametypes = FileSystem::GetFileList("maps/mp/gametypes/", "txt"); - - // Get the gametypes we can find in the database - Game::DB_EnumXAssets(Game::XAssetType::ASSET_TYPE_RAWFILE, [](Game::XAssetHeader header, void* data) - { - std::string name = header.rawfile->name; - std::vector* rawGametypes = reinterpret_cast*>(data); - - if (Utils::String::StartsWith(name, "maps/mp/gametypes/") && Utils::String::EndsWith(name, ".txt")) - { - if (std::count(name.begin(), name.end(), '/') == 3 && std::count(name.begin(), name.end(), '\\') == 0) - { - rawGametypes->push_back(name); - } - } - - }, &rawGametypes, false); - - std::for_each(rawGametypes.begin(), rawGametypes.end(), pushGametype); - - std::string data; - for (auto& gametype : gametypes) - { - if (Game::Scr_AddSourceBuffer(nullptr, Utils::String::Format("maps/mp/gametypes/{}.txt", gametype), nullptr, false)) - { - data.append(gametype); - data.append("\r\n"); - } - } - - // Copy to the actual buffer - std::memcpy(buffer, data.data(), std::min(size, data.size() + 1)); - - return (data.empty() ? nullptr : buffer); - } - - Gametypes::Gametypes() - { - UIFeeder::Add(29.0f, Gametypes::GetGametypeCount, Gametypes::GetGametypeText, Gametypes::SelectGametype); - - // Dynamically grab gametypes - Utils::Hook(0x5FA46C, Gametypes::BuildGametypeList, HOOK_CALL).install()->quick(); // Scr_UpdateGameTypeList - Utils::Hook(0x632155, Gametypes::BuildGametypeList, HOOK_CALL).install()->quick(); // UI_UpdateGameTypesList - } -} diff --git a/src/Components/Modules/Gametypes.hpp b/src/Components/Modules/Gametypes.hpp deleted file mode 100644 index 5576512e..00000000 --- a/src/Components/Modules/Gametypes.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -namespace Components -{ - class Gametypes : public Component - { - public: - Gametypes(); - - private: - static unsigned int GetGametypeCount(); - static const char* GetGametypeText(unsigned int index, int column); - static void SelectGametype(unsigned int index); - - static void* BuildGametypeList(const char* file, void* buffer, size_t size); - }; -} diff --git a/src/Components/Modules/Lean.cpp b/src/Components/Modules/Lean.cpp index 90050a73..29b1403e 100644 --- a/src/Components/Modules/Lean.cpp +++ b/src/Components/Modules/Lean.cpp @@ -1,4 +1,5 @@ #include +#include "Lean.hpp" namespace Components { diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 832bac14..06cfa3f8 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -1,4 +1,5 @@ #include +#include "Console.hpp" namespace Components { diff --git a/src/Components/Modules/MapDump.cpp b/src/Components/Modules/MapDump.cpp index 1271b43c..db84fa6e 100644 --- a/src/Components/Modules/MapDump.cpp +++ b/src/Components/Modules/MapDump.cpp @@ -1,4 +1,5 @@ #include +#include "MapDump.hpp" namespace Components { @@ -362,27 +363,8 @@ namespace Components return image; } - // TODO: This is still wrong. - if (image->mapType == 5 && false) - { - for (auto i = 0; i < 6; ++i) - { - IDirect3DSurface9* surface = nullptr; - image->texture.cubemap->GetCubeMapSurface(D3DCUBEMAP_FACES(i), 0, &surface); - - if (surface) - { - std::string _name = Utils::String::VA("raw/mapdump/%s/textures/%s_%i.png", this->world_->baseName, image->name, i); - D3DXSaveSurfaceToFileA(_name.data(), D3DXIFF_PNG, surface, nullptr, nullptr); - surface->Release(); - } - } - } - else - { - std::string _name = Utils::String::VA("raw/mapdump/%s/textures/%s.png", this->world_->baseName, image->name); - D3DXSaveTextureToFileA(_name.data(), D3DXIFF_PNG, image->texture.map, nullptr); - } + std::string _name = Utils::String::VA("raw/mapdump/%s/textures/%s.png", this->world_->baseName, image->name); + D3DXSaveTextureToFileA(_name.data(), D3DXIFF_PNG, image->texture.map, nullptr); return image; } diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index b349fa80..1367ed41 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -1,4 +1,5 @@ #include +#include "MapRotation.hpp" namespace Components { diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index b13f80c6..b3786320 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -1,4 +1,8 @@ #include +#include "RawFiles.hpp" +#include "StartupMessages.hpp" +#include "Theatre.hpp" +#include "UIFeeder.hpp" namespace Components { diff --git a/src/Components/Modules/ModList.cpp b/src/Components/Modules/ModList.cpp index 65d1e708..2b3a07f6 100644 --- a/src/Components/Modules/ModList.cpp +++ b/src/Components/Modules/ModList.cpp @@ -1,4 +1,5 @@ #include +#include "UIFeeder.hpp" namespace Components { diff --git a/src/Components/Modules/NetworkDebug.cpp b/src/Components/Modules/NetworkDebug.cpp index 45ceb182..97c8bdfa 100644 --- a/src/Components/Modules/NetworkDebug.cpp +++ b/src/Components/Modules/NetworkDebug.cpp @@ -1,4 +1,5 @@ #include +#include "NetworkDebug.hpp" namespace Components { diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 3b839cc8..4f3c72df 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -1,4 +1,6 @@ #include +#include "Changelog.hpp" +#include "News.hpp" #include diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index b5084bab..5ad1dc5d 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -1,4 +1,6 @@ #include +#include "ServerList.hpp" +#include "Session.hpp" namespace Components { diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index bf6d7d6e..7798c760 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -1,4 +1,9 @@ #include +#include "Download.hpp" +#include "Gamepad.hpp" +#include "ServerList.hpp" +#include "Stats.hpp" +#include "Voice.hpp" #include diff --git a/src/Components/Modules/PlayerMovement.cpp b/src/Components/Modules/PlayerMovement.cpp index bbbeb944..749f15df 100644 --- a/src/Components/Modules/PlayerMovement.cpp +++ b/src/Components/Modules/PlayerMovement.cpp @@ -1,4 +1,6 @@ #include +#include "PlayerMovement.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/PlayerName.cpp b/src/Components/Modules/PlayerName.cpp index 5d69c66a..2d32fd47 100644 --- a/src/Components/Modules/PlayerName.cpp +++ b/src/Components/Modules/PlayerName.cpp @@ -1,4 +1,6 @@ #include +#include "ClanTags.hpp" +#include "PlayerName.hpp" namespace Components { diff --git a/src/Components/Modules/Playlist.cpp b/src/Components/Modules/Playlist.cpp index 915042e2..1b355aa4 100644 --- a/src/Components/Modules/Playlist.cpp +++ b/src/Components/Modules/Playlist.cpp @@ -1,4 +1,5 @@ #include +#include "Playlist.hpp" namespace Components { diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 4684d2de..5631fcca 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -1,4 +1,5 @@ #include +#include "QuickPatch.hpp" namespace Components { diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 6bcd6f8c..52e549ce 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -1,4 +1,5 @@ #include +#include "RCon.hpp" namespace Components { diff --git a/src/Components/Modules/RawFiles.cpp b/src/Components/Modules/RawFiles.cpp index e3c3848a..95a8556f 100644 --- a/src/Components/Modules/RawFiles.cpp +++ b/src/Components/Modules/RawFiles.cpp @@ -1,4 +1,5 @@ #include +#include "RawFiles.hpp" namespace Components { diff --git a/src/Components/Modules/RawMouse.cpp b/src/Components/Modules/RawMouse.cpp index f48d8f33..bc046d7b 100644 --- a/src/Components/Modules/RawMouse.cpp +++ b/src/Components/Modules/RawMouse.cpp @@ -1,4 +1,6 @@ #include +#include "Gamepad.hpp" +#include "RawMouse.hpp" namespace Components { @@ -80,7 +82,9 @@ namespace Components if (GetForegroundWindow() == Window::GetWindow()) { if (r_fullscreen.get()) + { IN_ClampMouseMove(); + } static auto oldX = 0, oldY = 0; @@ -109,7 +113,7 @@ namespace Components void RawMouse::IN_RawMouse_Init() { - if (Window::GetWindow() && RawMouse::M_RawInput.get()) + if (Window::GetWindow() && M_RawInput.get()) { Logger::Debug("Raw Mouse Init"); @@ -131,7 +135,7 @@ namespace Components void RawMouse::IN_MouseMove() { - if (RawMouse::M_RawInput.get()) + if (M_RawInput.get()) { IN_RawMouseMove(); } @@ -143,15 +147,15 @@ namespace Components RawMouse::RawMouse() { - Utils::Hook(0x475E65, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick(); - Utils::Hook(0x475E8D, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick(); + Utils::Hook(0x475E65, IN_MouseMove, HOOK_JUMP).install()->quick(); + Utils::Hook(0x475E8D, IN_MouseMove, HOOK_JUMP).install()->quick(); - Utils::Hook(0x467C03, RawMouse::IN_Init, HOOK_CALL).install()->quick(); - Utils::Hook(0x64D095, RawMouse::IN_Init, HOOK_JUMP).install()->quick(); + Utils::Hook(0x467C03, IN_Init, HOOK_CALL).install()->quick(); + Utils::Hook(0x64D095, IN_Init, HOOK_JUMP).install()->quick(); - RawMouse::M_RawInput = Dvar::Register("m_rawinput", true, Game::DVAR_ARCHIVE, "Use raw mouse input, Improves accuracy & has better support for higher polling rates. Use in_restart to take effect if not enabled."); + M_RawInput = Dvar::Register("m_rawinput", true, Game::DVAR_ARCHIVE, "Use raw mouse input, Improves accuracy & has better support for higher polling rates"); - Window::OnWndMessage(WM_INPUT, RawMouse::OnRawInput); - Window::OnCreate(RawMouse::IN_RawMouse_Init); + Window::OnWndMessage(WM_INPUT, OnRawInput); + Window::OnCreate(IN_RawMouse_Init); } } diff --git a/src/Components/Modules/Scheduler.cpp b/src/Components/Modules/Scheduler.cpp index 48246130..7b1e5649 100644 --- a/src/Components/Modules/Scheduler.cpp +++ b/src/Components/Modules/Scheduler.cpp @@ -7,7 +7,7 @@ namespace Components { std::thread Scheduler::Thread; volatile bool Scheduler::Kill = false; - Scheduler::TaskPipeline Scheduler::Pipelines[Pipeline::COUNT]; + Scheduler::TaskPipeline Scheduler::Pipelines[static_cast>(Pipeline::COUNT)]; void Scheduler::TaskPipeline::add(Task&& task) { @@ -64,7 +64,8 @@ namespace Components void Scheduler::Execute(Pipeline type) { assert(type < Pipeline::COUNT); - Pipelines[type].execute(); + const auto index = static_cast>(type); + Pipelines[index].execute(); } void Scheduler::ScrPlace_EndFrame_Hk() @@ -107,7 +108,8 @@ namespace Components task.interval = delay; task.lastCall = std::chrono::high_resolution_clock::now(); - Pipelines[type].add(std::move(task)); + const auto index = static_cast>(type); + Pipelines[index].add(std::move(task)); } void Scheduler::Loop(const std::function& callback, const Pipeline type, diff --git a/src/Components/Modules/Scheduler.hpp b/src/Components/Modules/Scheduler.hpp index 72715b06..d9a7a57b 100644 --- a/src/Components/Modules/Scheduler.hpp +++ b/src/Components/Modules/Scheduler.hpp @@ -5,7 +5,7 @@ namespace Components class Scheduler : public Component { public: - enum Pipeline + enum class Pipeline : int { ASYNC, RENDERER, diff --git a/src/Components/Modules/Security.cpp b/src/Components/Modules/Security.cpp index fbab96e3..9c45e24a 100644 --- a/src/Components/Modules/Security.cpp +++ b/src/Components/Modules/Security.cpp @@ -1,4 +1,5 @@ #include +#include "Security.hpp" namespace Components { diff --git a/src/Components/Modules/ServerCommands.cpp b/src/Components/Modules/ServerCommands.cpp index f5f8863a..fd547914 100644 --- a/src/Components/Modules/ServerCommands.cpp +++ b/src/Components/Modules/ServerCommands.cpp @@ -1,4 +1,5 @@ #include +#include "ServerCommands.hpp" namespace Components { diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 59593d18..4114f2df 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -1,4 +1,9 @@ #include +#include "Gamepad.hpp" +#include "ServerInfo.hpp" +#include "ServerList.hpp" +#include "UIFeeder.hpp" +#include "Voice.hpp" #include diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 6f06ef46..bb39ae5d 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -1,4 +1,7 @@ #include +#include "Discovery.hpp" +#include "ServerList.hpp" +#include "UIFeeder.hpp" #include diff --git a/src/Components/Modules/Session.cpp b/src/Components/Modules/Session.cpp index 1c788437..096ccd24 100644 --- a/src/Components/Modules/Session.cpp +++ b/src/Components/Modules/Session.cpp @@ -1,4 +1,5 @@ #include +#include "Session.hpp" namespace Components { diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index aa362c5d..3986a930 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -1,4 +1,6 @@ #include +#include "ConnectProtocol.hpp" +#include "Console.hpp" #include diff --git a/src/Components/Modules/SlowMotion.cpp b/src/Components/Modules/SlowMotion.cpp index 0d57f701..09df94fc 100644 --- a/src/Components/Modules/SlowMotion.cpp +++ b/src/Components/Modules/SlowMotion.cpp @@ -1,4 +1,5 @@ #include +#include "SlowMotion.hpp" namespace Components { diff --git a/src/Components/Modules/SoundMutexFix.cpp b/src/Components/Modules/SoundMutexFix.cpp index 69662c7b..935ffefd 100644 --- a/src/Components/Modules/SoundMutexFix.cpp +++ b/src/Components/Modules/SoundMutexFix.cpp @@ -1,4 +1,5 @@ #include +#include "SoundMutexFix.hpp" namespace Components { @@ -26,7 +27,7 @@ namespace Components void __stdcall SoundMutexFix::LockSoundMutex(int unk) { - std::lock_guard lock(SoundMutexFix::SNDMutex); + std::lock_guard lock(SNDMutex); DWORD funcPtr = *reinterpret_cast(0x6D7554); // AIL_close_stream Utils::Hook::Call(funcPtr)(unk); @@ -34,6 +35,6 @@ namespace Components SoundMutexFix::SoundMutexFix() { - Utils::Hook(0x689EFE, &SoundMutexFix::LockSoundMutex, HOOK_JUMP).install()->quick(); + Utils::Hook(0x689EFE, &LockSoundMutex, HOOK_JUMP).install()->quick(); } } \ No newline at end of file diff --git a/src/Components/Modules/StartupMessages.cpp b/src/Components/Modules/StartupMessages.cpp index 333171a6..b9b5765e 100644 --- a/src/Components/Modules/StartupMessages.cpp +++ b/src/Components/Modules/StartupMessages.cpp @@ -1,4 +1,5 @@ #include +#include "StartupMessages.hpp" namespace Components { diff --git a/src/Components/Modules/Stats.cpp b/src/Components/Modules/Stats.cpp index 62a61b50..a6ab031e 100644 --- a/src/Components/Modules/Stats.cpp +++ b/src/Components/Modules/Stats.cpp @@ -1,4 +1,7 @@ #include +#include "ServerCommands.hpp" +#include "Stats.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/StringTable.cpp b/src/Components/Modules/StringTable.cpp index e9c82836..44b8a61b 100644 --- a/src/Components/Modules/StringTable.cpp +++ b/src/Components/Modules/StringTable.cpp @@ -1,4 +1,5 @@ #include +#include "StringTable.hpp" namespace Components { @@ -22,8 +23,8 @@ namespace Components if (table) { table->name = allocator->duplicateString(filename); - table->columnCount = parsedTable.getColumns(); - table->rowCount = parsedTable.getRows(); + table->columnCount = static_cast(parsedTable.getColumns()); + table->rowCount = static_cast(parsedTable.getRows()); table->values = allocator->allocateArray(table->columnCount * table->rowCount); @@ -45,12 +46,12 @@ namespace Components } } - StringTable::StringTableMap[filename] = table; + StringTableMap[filename] = table; } } else { - StringTable::StringTableMap[filename] = nullptr; + StringTableMap[filename] = nullptr; } return table; @@ -64,13 +65,13 @@ namespace Components std::string filename = Utils::String::ToLower(_filename); - if (StringTable::StringTableMap.contains(filename)) + if (StringTableMap.contains(filename)) { - header.stringTable = StringTable::StringTableMap[filename]; + header.stringTable = StringTableMap[filename]; } else { - header.stringTable = StringTable::LoadObject(filename); + header.stringTable = LoadObject(filename); } return header; diff --git a/src/Components/Modules/StructuredData.cpp b/src/Components/Modules/StructuredData.cpp index 5164a112..f60437c7 100644 --- a/src/Components/Modules/StructuredData.cpp +++ b/src/Components/Modules/StructuredData.cpp @@ -1,4 +1,5 @@ #include +#include "StructuredData.hpp" namespace Components { diff --git a/src/Components/Modules/Theatre.cpp b/src/Components/Modules/Theatre.cpp index eb01abc7..a48a5b07 100644 --- a/src/Components/Modules/Theatre.cpp +++ b/src/Components/Modules/Theatre.cpp @@ -1,4 +1,6 @@ #include +#include "Theatre.hpp" +#include "UIFeeder.hpp" namespace Components { diff --git a/src/Components/Modules/Threading.cpp b/src/Components/Modules/Threading.cpp index f22315a7..0f77dea2 100644 --- a/src/Components/Modules/Threading.cpp +++ b/src/Components/Modules/Threading.cpp @@ -1,4 +1,5 @@ #include +#include "Threading.hpp" namespace Components { diff --git a/src/Components/Modules/UIFeeder.cpp b/src/Components/Modules/UIFeeder.cpp index 03c445fe..028e82f7 100644 --- a/src/Components/Modules/UIFeeder.cpp +++ b/src/Components/Modules/UIFeeder.cpp @@ -1,4 +1,5 @@ #include +#include "UIFeeder.hpp" namespace Components { diff --git a/src/Components/Modules/UserInfo.cpp b/src/Components/Modules/UserInfo.cpp index ab425dda..4b71931b 100644 --- a/src/Components/Modules/UserInfo.cpp +++ b/src/Components/Modules/UserInfo.cpp @@ -1,4 +1,6 @@ #include +#include "UserInfo.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/VisionFile.cpp b/src/Components/Modules/VisionFile.cpp index 04ef18aa..398d29b3 100644 --- a/src/Components/Modules/VisionFile.cpp +++ b/src/Components/Modules/VisionFile.cpp @@ -1,4 +1,5 @@ #include +#include "VisionFile.hpp" namespace Components { diff --git a/src/Components/Modules/Voice.cpp b/src/Components/Modules/Voice.cpp index 1629656f..10e40a21 100644 --- a/src/Components/Modules/Voice.cpp +++ b/src/Components/Modules/Voice.cpp @@ -1,4 +1,5 @@ #include +#include "Voice.hpp" namespace Components { diff --git a/src/Components/Modules/Vote.cpp b/src/Components/Modules/Vote.cpp index ccf01c45..c75a9e21 100644 --- a/src/Components/Modules/Vote.cpp +++ b/src/Components/Modules/Vote.cpp @@ -1,4 +1,7 @@ #include +#include "ClientCommand.hpp" +#include "MapRotation.hpp" +#include "Vote.hpp" using namespace Utils::String; diff --git a/src/Components/Modules/Weapon.cpp b/src/Components/Modules/Weapon.cpp index bdc0a646..01af8241 100644 --- a/src/Components/Modules/Weapon.cpp +++ b/src/Components/Modules/Weapon.cpp @@ -1,4 +1,6 @@ #include +#include "Weapon.hpp" + #include "GSC/Script.hpp" namespace Components diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index 97285687..4d10a89d 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -1,4 +1,5 @@ #include +#include "Console.hpp" #include diff --git a/src/Steam/Steam.cpp b/src/Steam/Steam.cpp index 3d1ff85f..9e206af9 100644 --- a/src/Steam/Steam.cpp +++ b/src/Steam/Steam.cpp @@ -1,4 +1,5 @@ #include +#include "Components/Modules/StartupMessages.hpp" namespace Steam { From 98a61ee9ed300731d9a5a2b8dd6889697f157728 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 26 Dec 2022 15:14:22 +0100 Subject: [PATCH 82/96] [Debug]: Draw lines from riot shield (#670) --- src/Components/Modules/Bullet.cpp | 80 ++++++++++++++++++++++++++++++ src/Components/Modules/Bullet.hpp | 17 +++++++ src/Components/Modules/Debug.cpp | 36 +++++++------- src/Components/Modules/Debug.hpp | 6 +-- src/Components/Modules/Gamepad.cpp | 2 +- src/Game/Client.cpp | 8 +++ src/Game/Client.hpp | 5 ++ src/Game/Functions.cpp | 4 +- src/Game/Functions.hpp | 10 +++- src/Game/Game.cpp | 7 +++ src/Game/Game.hpp | 5 ++ 11 files changed, 155 insertions(+), 25 deletions(-) diff --git a/src/Components/Modules/Bullet.cpp b/src/Components/Modules/Bullet.cpp index 881cef52..d3310830 100644 --- a/src/Components/Modules/Bullet.cpp +++ b/src/Components/Modules/Bullet.cpp @@ -6,6 +6,14 @@ namespace Components Dvar::Var Bullet::BGSurfacePenetration; Game::dvar_t* Bullet::BGBulletRange; + float Bullet::ContactPointSave[3]; + float Bullet::VCSave[3]; + float Bullet::CalcRicochetSave[3]; + + float Bullet::ColorYellow[] = {1.0f, 1.0f, 0.0f, 1.0f}; + float Bullet::ColorBlue[] = {0.0f, 0.0f, 1.0f, 1.0f}; + float Bullet::ColorOrange[] = {1.0f, 0.7f, 0.0f, 1.0f}; + float Bullet::BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType) { assert(weapDef); @@ -48,6 +56,63 @@ namespace Components *pHoldrand = static_cast(std::rand()); } + void Bullet::BulletRicochet_Save(const float* contactPoint) + { + std::memcpy(ContactPointSave, contactPoint, sizeof(float[3])); + } + + __declspec(naked) void Bullet::BulletRicochet_Stub() + { + __asm + { + pushad + push [esp + 0x20 + 0xC] + call BulletRicochet_Save + add esp, 0x4 + popad + + // Game's code + sub esp, 0x4C + push ebp + mov ebp, dword ptr [esp + 0x60] + + push 0x5D5B08 + ret + } + } + + void Bullet::_VectorMA_Stub(float* va, float scale, float* vb, float* vc) + { + vc[0] = va[0] + scale * vb[0]; + vc[1] = va[1] + scale * vb[1]; + vc[2] = va[2] + scale * vb[2]; + + std::memcpy(VCSave, vc, sizeof(float[3])); + } + + void Bullet::CalcRicochet_Stub(const float* incoming, const float* normal, float* result) + { + Utils::Hook::Call(0x5D59F0)(incoming, normal, result); + std::memcpy(CalcRicochetSave, result, sizeof(float[3])); + } + + int Bullet::Bullet_Fire_Stub(Game::gentity_s* attacker, [[maybe_unused]] float spread, Game::weaponParms* wp, Game::gentity_s* weaponEnt, Game::PlayerHandIndex hand, int gameTime) + { + float tmp[3]; + + Game::G_DebugStar(ContactPointSave, ColorYellow); + + tmp[0] = (CalcRicochetSave[0] * 100.0f) + VCSave[0]; + tmp[1] = (CalcRicochetSave[1] * 100.0f) + VCSave[1]; + tmp[2] = (CalcRicochetSave[2] * 100.0f) + VCSave[1]; + + Game::G_DebugLineWithDuration(VCSave, tmp, ColorOrange, 1, 100); + Game::G_DebugStar(tmp, ColorBlue); + + // Set the spread to 0 when drawing + return Game::Bullet_Fire(attacker, 0.0f, wp, weaponEnt, hand, gameTime); + } + Bullet::Bullet() { BGSurfacePenetration = Dvar::Register("bg_surfacePenetration", 0.0f, @@ -59,5 +124,20 @@ namespace Components Utils::Hook(0x440340, Bullet_FireStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x440368, BG_srand_Hk, HOOK_CALL).install()->quick(); + + std::memset(ContactPointSave, 0, sizeof(float[3])); + std::memset(VCSave, 0, sizeof(float[3])); + std::memset(CalcRicochetSave, 0, sizeof(float[3])); + +#ifdef DEBUG_RIOT_SHIELD + Utils::Hook(0x5D5B00, BulletRicochet_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x5D5B00 + 5, 3); + + Utils::Hook(0x5D5BBA, CalcRicochet_Stub, HOOK_CALL).install()->quick(); + + Utils::Hook(0x5D5BD7, _VectorMA_Stub, HOOK_CALL).install()->quick(); + + Utils::Hook(0x5D5C0B, Bullet_Fire_Stub, HOOK_CALL).install()->quick(); +#endif } } diff --git a/src/Components/Modules/Bullet.hpp b/src/Components/Modules/Bullet.hpp index 84083e3b..8a0abed4 100644 --- a/src/Components/Modules/Bullet.hpp +++ b/src/Components/Modules/Bullet.hpp @@ -12,10 +12,27 @@ namespace Components // Can't use Var class inside assembly stubs static Game::dvar_t* BGBulletRange; + static float ContactPointSave[]; + static float VCSave[]; + static float CalcRicochetSave[]; + + static float ColorYellow[]; + static float ColorBlue[]; + static float ColorOrange[]; + static float BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType); static void Bullet_FireStub(); static void BG_srand_Hk(unsigned int* pHoldrand); + + static void BulletRicochet_Save(const float* contactPoint); + static void BulletRicochet_Stub(); + + static void CalcRicochet_Stub(const float* incoming, const float* normal, float* result); + + static void _VectorMA_Stub(float* va, float scale, float* vb, float* vc); + + static int Bullet_Fire_Stub(Game::gentity_s* attacker, float spread, Game::weaponParms* wp, Game::gentity_s* weaponEnt, Game::PlayerHandIndex hand, int gameTime); }; } diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index e35024c7..9e742f22 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -94,15 +94,15 @@ namespace Components "EF_SOFT", }; - const char Debug::strButtons[] = + const char Debug::StrButtons[] = { '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\0' }; - const char Debug::strTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain."; + const char Debug::StrTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain."; - const float Debug::colorWhite[] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float Debug::ColorWhite[] = {1.0f, 1.0f, 1.0f, 1.0f}; std::string Debug::BuildPMFlagsString(const Game::playerState_s* ps) { @@ -163,19 +163,19 @@ namespace Components auto* const font2 = Game::UI_GetFontHandle(scrPlace, 6, MY_SCALE2); Game::UI_DrawText(scrPlace, "Client View of Flags", maxChars, font2, -60.0f, 0, 1, 1, - MY_SCALE2, colorWhite, 1); + MY_SCALE2, ColorWhite, 1); const auto pmf = BuildPMFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto pof = BuildPOFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto plf = BuildPLFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto pef = BuildPEFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); } void Debug::CG_DrawDebugPlayerHealth(const int localClientNum) @@ -221,25 +221,25 @@ namespace Components auto* const font5 = Game::UI_GetFontHandle(scrPlace, 5, 0.4f); auto* const font6 = Game::UI_GetFontHandle(scrPlace, 6, 0.4f); - sprintf_s(strFinal, strTemplate, font1->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font1->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font2->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font2->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font3->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font3->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font5->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font5->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font6->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font6->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, ColorWhite, 3); } void Debug::CG_DrawDebugOverlays_Hk(const int localClientNum) diff --git a/src/Components/Modules/Debug.hpp b/src/Components/Modules/Debug.hpp index eb846014..ac18b2c5 100644 --- a/src/Components/Modules/Debug.hpp +++ b/src/Components/Modules/Debug.hpp @@ -19,8 +19,8 @@ namespace Components static const char* PLFlagsValues[]; static const char* PEFlagsValues[]; - static const char strButtons[]; - static const char strTemplate[]; + static const char StrButtons[]; + static const char StrTemplate[]; static constexpr auto MY_SCALE2 = 0.5f; static constexpr auto MY_SCALE_2 = 0.201f; @@ -28,7 +28,7 @@ namespace Components static constexpr auto MY_X = -25.0f; static constexpr auto MY_Y = 20.0f; - static const float colorWhite[]; + static const float ColorWhite[]; static std::string BuildPMFlagsString(const Game::playerState_s* ps); static std::string BuildPOFlagsString(const Game::playerState_s* ps); diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index e352a28a..edb34245 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -751,7 +751,7 @@ namespace Components -yawRight }; - Game::cgArray[0].selectedLocationAngle = Game::AngleNormalize360(Game::vectoyaw(&vec)); + Game::cgArray[0].selectedLocationAngle = Game::AngleNormalize360(Game::vectoryaw(&vec)); Game::cgArray[0].selectedAngleLocation[0] = Game::cgArray[0].selectedLocation[0]; Game::cgArray[0].selectedAngleLocation[1] = Game::cgArray[0].selectedLocation[1]; } diff --git a/src/Game/Client.cpp b/src/Game/Client.cpp index 2eef16be..2a690e29 100644 --- a/src/Game/Client.cpp +++ b/src/Game/Client.cpp @@ -25,6 +25,7 @@ namespace Game 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); + CL_AddDebugStarWithText_t CL_AddDebugStarWithText = CL_AddDebugStarWithText_t(0x4D03C0); float* cl_angles = reinterpret_cast(0xB2F8D0); @@ -79,4 +80,11 @@ namespace Game assert(clients[localClientNum].alwaysFalse == false); return &clients[localClientNum]; } + + void CL_AddDebugStar(const float* point, const float* color, int duration, int fromServer) + { + static const float MY_NULLTEXTCOLOR[] = {0.0f, 0.0f, 0.0f, 0.0f}; + + CL_AddDebugStarWithText(point, color, MY_NULLTEXTCOLOR, nullptr, 1.0f, duration, fromServer); + } } diff --git a/src/Game/Client.hpp b/src/Game/Client.hpp index 2f722c7a..13c96884 100644 --- a/src/Game/Client.hpp +++ b/src/Game/Client.hpp @@ -71,6 +71,9 @@ namespace Game 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; + typedef void(*CL_AddDebugStarWithText_t)(const float* point, const float* starColor, const float* textColor, const char* string, float fontsize, int duration, int fromServer); + extern CL_AddDebugStarWithText_t CL_AddDebugStarWithText; + extern float* cl_angles; extern clientConnection_t* clientConnections; @@ -89,4 +92,6 @@ namespace Game extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum); extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum); extern clientActive_t* CL_GetLocalClientGlobals(int localClientNum); + + extern void CL_AddDebugStar(const float* point, const float* color, int duration, int fromServer); } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index a87789a6..c641e670 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -206,8 +206,9 @@ namespace Game Win_GetLanguage_t Win_GetLanguage = Win_GetLanguage_t(0x45CBA0); Vec3UnpackUnitVec_t Vec3UnpackUnitVec = Vec3UnpackUnitVec_t(0x45CA90); - vectoyaw_t vectoyaw = vectoyaw_t(0x45AD10); + vectoryaw_t vectoryaw = vectoryaw_t(0x45AD10); AngleNormalize360_t AngleNormalize360 = AngleNormalize360_t(0x438DC0); + _VectorMA_t _VectorMA = _VectorMA_t(0x5084D0); unzClose_t unzClose = unzClose_t(0x41BF20); @@ -226,6 +227,7 @@ namespace Game AimAssist_ApplyAutoMelee_t AimAssist_ApplyAutoMelee = AimAssist_ApplyAutoMelee_t(0x56A360); Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire = Weapon_RocketLauncher_Fire_t(0x424680); + Bullet_Fire_t Bullet_Fire = Bullet_Fire_t(0x4402C0); Jump_ClearState_t Jump_ClearState = Jump_ClearState_t(0x04B3890); PM_playerTrace_t PM_playerTrace = PM_playerTrace_t(0x458980); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6f84f841..45ed25bf 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -470,12 +470,15 @@ namespace Game typedef void(*Vec3UnpackUnitVec_t)(PackedUnitVec, vec3_t*); extern Vec3UnpackUnitVec_t Vec3UnpackUnitVec; - typedef float(*vectoyaw_t)(vec2_t* vec); - extern vectoyaw_t vectoyaw; + typedef float(*vectoryaw_t)(vec2_t* vec); + extern vectoryaw_t vectoryaw; typedef float(*AngleNormalize360_t)(float val); extern AngleNormalize360_t AngleNormalize360; + typedef void(*_VectorMA_t)(float* va, float scale, float* vb, float* vc); + extern _VectorMA_t _VectorMA; + typedef void(*unzClose_t)(void* handle); extern unzClose_t unzClose; @@ -509,6 +512,9 @@ namespace Game typedef gentity_s*(*Weapon_RocketLauncher_Fire_t)(gentity_s* ent, unsigned int weaponIndex, float spread, weaponParms* wp, const float* gunVel, lockonFireParms* lockParms, bool magicBullet); extern Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire; + typedef int(*Bullet_Fire_t)(gentity_s* attacker, float spread, weaponParms* wp, gentity_s* weaponEnt, PlayerHandIndex hand, int gameTime); + extern Bullet_Fire_t Bullet_Fire; + typedef void(*Jump_ClearState_t)(playerState_s* ps); extern Jump_ClearState_t Jump_ClearState; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index a4fd994d..750c2ccf 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -14,6 +14,8 @@ namespace Game G_LocalizedStringIndex_t G_LocalizedStringIndex = G_LocalizedStringIndex_t(0x4582F0); + G_DebugLineWithDuration_t G_DebugLineWithDuration = G_DebugLineWithDuration_t(0x4C3280); + gentity_t* g_entities = reinterpret_cast(0x18835D8); const char* origErrorMsg = reinterpret_cast(0x79B124); @@ -24,4 +26,9 @@ namespace Game assert(index < MAX_MODELS); return cached_models[index]; } + + void G_DebugStar(const float* point, const float* color) + { + CL_AddDebugStar(point, color, 20, 1); + } } diff --git a/src/Game/Game.hpp b/src/Game/Game.hpp index d094afb9..458d6b20 100644 --- a/src/Game/Game.hpp +++ b/src/Game/Game.hpp @@ -43,6 +43,9 @@ namespace Game typedef int(*G_LocalizedStringIndex_t)(const char* string); extern G_LocalizedStringIndex_t G_LocalizedStringIndex; + typedef void(*G_DebugLineWithDuration_t)(const float* start, const float* end, const float* color, int depthTest, int duration); + extern G_DebugLineWithDuration_t G_DebugLineWithDuration; + constexpr std::size_t MAX_GENTITIES = 2048; constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1; extern gentity_t* g_entities; @@ -50,4 +53,6 @@ namespace Game extern const char* origErrorMsg; extern XModel* G_GetModel(int index); + + extern void G_DebugStar(const float* point, const float* color); } From 9467755ee3bf19d247717d036972d4419b7a151b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:05:54 +0000 Subject: [PATCH 83/96] Bump deps/GSL from `6c6111a` to `46c7271` Bumps [deps/GSL](https://github.com/microsoft/GSL) from `6c6111a` to `46c7271`. - [Release notes](https://github.com/microsoft/GSL/releases) - [Commits](https://github.com/microsoft/GSL/compare/6c6111acb7b5d687ac006969ac96e5b1f21374cd...46c72713f2e8a66782ba0d40c4d6bb3edc9aa382) --- updated-dependencies: - dependency-name: deps/GSL dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/GSL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/GSL b/deps/GSL index 6c6111ac..46c72713 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit 6c6111acb7b5d687ac006969ac96e5b1f21374cd +Subproject commit 46c72713f2e8a66782ba0d40c4d6bb3edc9aa382 From e0296bdfd6b219499635f8133e226f08474f2b9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:05:59 +0000 Subject: [PATCH 84/96] Bump deps/mongoose from `6cedca5` to `311062d` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `6cedca5` to `311062d`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/6cedca5d76d9297a444d14f09ca0424fde7b1006...311062dc411b1ef3805a388d8443cad944024841) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 6cedca5d..311062dc 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 6cedca5d76d9297a444d14f09ca0424fde7b1006 +Subproject commit 311062dc411b1ef3805a388d8443cad944024841 From fc7b10931800ff03d859842ce153688a6fea535e Mon Sep 17 00:00:00 2001 From: Diavolo Date: Mon, 26 Dec 2022 21:24:46 +0100 Subject: [PATCH 85/96] [Dvar]: Protect special dvar --- src/Components/Modules/Dvar.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 182afc13..b15e1721 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -321,7 +321,7 @@ namespace Components { if (AreArchiveDvarsProtected()) { - Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to override saved dvar '{}'\n", dvarName); + Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to override saved dvar '{}'\n", dvar->name); return; } @@ -331,6 +331,12 @@ namespace Components SaveArchiveDvar(dvar); } + if (dvar != nullptr && std::strcmp(dvar->name, "com_errorResolveCommand") == 0) + { + Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to set '{}'\n", dvar->name); + return; + } + Utils::Hook::Call(0x4F52E0)(dvarName, value); } From f53d487b0db189d47d56da5a524dc5e57890f682 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Tue, 27 Dec 2022 10:40:54 +0100 Subject: [PATCH 86/96] [Exception]: Fix --- src/Components/Modules/Exception.cpp | 15 +++++++++++++-- src/Components/Modules/Exception.hpp | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index 5fbfb89a..f02c307b 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -116,7 +116,7 @@ namespace Components PathRemoveExtensionA(exeFileName); // Generate filename - char filenameFriendlyTime[MAX_PATH]; + char filenameFriendlyTime[MAX_PATH]{}; __time64_t time; tm ltime; _time64(&time); @@ -166,11 +166,22 @@ namespace Components } } + LPTOP_LEVEL_EXCEPTION_FILTER WINAPI Exception::SetUnhandledExceptionFilter_Stub(LPTOP_LEVEL_EXCEPTION_FILTER) + { + SetFilterHook.uninstall(); + LPTOP_LEVEL_EXCEPTION_FILTER result = ::SetUnhandledExceptionFilter(&ExceptionFilter); + SetFilterHook.install(); + return result; + } + Exception::Exception() { SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); - SetUnhandledExceptionFilter(&ExceptionFilter); + SetFilterHook.initialize(::SetUnhandledExceptionFilter, SetUnhandledExceptionFilter_Stub, HOOK_JUMP); + SetFilterHook.install(); + + ::SetUnhandledExceptionFilter(&ExceptionFilter); Utils::Hook(0x4B241F, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); Utils::Hook(0x61DB44, LongJmp_Internal_Stub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Exception.hpp b/src/Components/Modules/Exception.hpp index 20a5d0b7..40b5e820 100644 --- a/src/Components/Modules/Exception.hpp +++ b/src/Components/Modules/Exception.hpp @@ -19,6 +19,8 @@ namespace Components static void CopyMessageToClipboard(const std::string& error); + static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter_Stub(LPTOP_LEVEL_EXCEPTION_FILTER); + static int MiniDumpType; static Utils::Hook SetFilterHook; }; From d0164573711301e11fb689ff76219cccfb312c20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Dec 2022 17:02:53 +0000 Subject: [PATCH 87/96] Bump deps/GSL from `46c7271` to `c016bdc` Bumps [deps/GSL](https://github.com/microsoft/GSL) from `46c7271` to `c016bdc`. - [Release notes](https://github.com/microsoft/GSL/releases) - [Commits](https://github.com/microsoft/GSL/compare/46c72713f2e8a66782ba0d40c4d6bb3edc9aa382...c016bdc77f28891cfc42fc219bd5365e89d3ebda) --- updated-dependencies: - dependency-name: deps/GSL dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/GSL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/GSL b/deps/GSL index 46c72713..c016bdc7 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit 46c72713f2e8a66782ba0d40c4d6bb3edc9aa382 +Subproject commit c016bdc77f28891cfc42fc219bd5365e89d3ebda From 068a19cae89547ced5a72b401220e258c918b558 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Dec 2022 17:42:34 +0000 Subject: [PATCH 88/96] Bump deps/zlib from `e554695` to `02a6049` Bumps [deps/zlib](https://github.com/madler/zlib) from `e554695` to `02a6049`. - [Release notes](https://github.com/madler/zlib/releases) - [Commits](https://github.com/madler/zlib/compare/e554695638228b846d49657f31eeff0ca4680e8a...02a6049eb3884c430268bb0fe3296d597a03174c) --- updated-dependencies: - dependency-name: deps/zlib dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/zlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/zlib b/deps/zlib index e5546956..02a6049e 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit e554695638228b846d49657f31eeff0ca4680e8a +Subproject commit 02a6049eb3884c430268bb0fe3296d597a03174c From 4d1baa17bee4e143c8af3c7ca37a5094f3199fd4 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 28 Dec 2022 11:03:14 +0100 Subject: [PATCH 89/96] [Logger]: Refactor --- src/Components/Modules/Logger.cpp | 10 +++--- src/Components/Modules/Logger.hpp | 59 ++++++++++++++++++------------- src/STDInclude.hpp | 1 - src/Steam/Proxy.cpp | 11 +++--- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 06cfa3f8..b87a7813 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -58,7 +58,7 @@ namespace Components } } - void Logger::DebugInternal(std::string_view fmt, std::format_args&& args, [[maybe_unused]] const std::source_location& loc) + void Logger::DebugInternal(const std::string_view& fmt, std::format_args&& args, [[maybe_unused]] const std::source_location& loc) { #ifdef LOGGER_TRACE const auto msg = std::vformat(fmt, args); @@ -71,14 +71,14 @@ namespace Components MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); } - void Logger::PrintInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) + void Logger::PrintInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args) { const auto msg = std::vformat(fmt, args); MessagePrint(channel, msg); } - void Logger::ErrorInternal(const Game::errorParm_t error, const std::string_view fmt, std::format_args&& args) + void Logger::ErrorInternal(const Game::errorParm_t error, const std::string_view& fmt, std::format_args&& args) { #ifdef _DEBUG if (IsDebuggerPresent()) __debugbreak(); @@ -88,7 +88,7 @@ namespace Components Game::Com_Error(error, "%s", msg.data()); } - void Logger::PrintErrorInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) + void Logger::PrintErrorInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args) { const auto msg = "^1Error: " + std::vformat(fmt, args); @@ -101,7 +101,7 @@ namespace Components } } - void Logger::WarningInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args) + void Logger::WarningInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args) { const auto msg = "^3" + std::vformat(fmt, args); diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index ff976a45..2aeace2b 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -14,87 +14,98 @@ namespace Components static void PipeOutput(const std::function& callback); - static void PrintInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); - static void ErrorInternal(Game::errorParm_t error, std::string_view fmt, std::format_args&& args); - static void PrintErrorInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); - static void WarningInternal(Game::conChannel_t channel, std::string_view fmt, std::format_args&& args); - static void DebugInternal(std::string_view fmt, std::format_args&& args, const std::source_location& loc); + static void PrintInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args); + static void ErrorInternal(Game::errorParm_t error, const std::string_view& fmt, std::format_args&& args); + static void PrintErrorInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args); + static void WarningInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args); + static void DebugInternal(const std::string_view& fmt, std::format_args&& args, const std::source_location& loc); - static void Print(std::string_view fmt) + static void Print(const std::string_view& fmt) { PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(0)); } - static void Print(Game::conChannel_t channel, std::string_view fmt) + static void Print(Game::conChannel_t channel, const std::string_view& fmt) { PrintInternal(channel, fmt, std::make_format_args(0)); } template - static void Print(std::string_view fmt, Args&&... args) + static void Print(const std::string_view& fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(args...)); } template - static void Print(Game::conChannel_t channel, std::string_view fmt, Args&&... args) + static void Print(Game::conChannel_t channel, const std::string_view& fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); PrintInternal(channel, fmt, std::make_format_args(args...)); } - static void Error(Game::errorParm_t error, std::string_view fmt) + static void Error(Game::errorParm_t error, const std::string_view& fmt) { ErrorInternal(error, fmt, std::make_format_args(0)); } template - static void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args) + static void Error(Game::errorParm_t error, const std::string_view& fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); ErrorInternal(error, fmt, std::make_format_args(args...)); } - static void Warning(Game::conChannel_t channel, std::string_view fmt) + static void Warning(Game::conChannel_t channel, const std::string_view& fmt) { WarningInternal(channel, fmt, std::make_format_args(0)); } template - static void Warning(Game::conChannel_t channel, std::string_view fmt, Args&&... args) + static void Warning(Game::conChannel_t channel, const std::string_view& fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); WarningInternal(channel, fmt, std::make_format_args(args...)); } - static void PrintError(Game::conChannel_t channel, std::string_view fmt) + static void PrintError(Game::conChannel_t channel, const std::string_view& fmt) { PrintErrorInternal(channel, fmt, std::make_format_args(0)); } template - static void PrintError(Game::conChannel_t channel, std::string_view fmt, Args&&... args) + static void PrintError(Game::conChannel_t channel, const std::string_view& fmt, Args&&... args) { (Utils::String::SanitizeFormatArgs(args), ...); PrintErrorInternal(channel, fmt, std::make_format_args(args...)); } - template - class Debug + struct FormatWithLocation { - public: - Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] const Args&... args, [[maybe_unused]] const std::source_location& loc = std::source_location::current()) + std::string_view format; + std::source_location location; + + FormatWithLocation(const std::string_view& fmt, std::source_location loc = std::source_location::current()) + : format(fmt) + , location(std::move(loc)) + { + } + + FormatWithLocation(const char* fmt, std::source_location loc = std::source_location::current()) + : format(fmt) + , location(std::move(loc)) { -#ifdef _DEBUG - (Utils::String::SanitizeFormatArgs(args), ...); - DebugInternal(fmt, std::make_format_args(args...), loc); -#endif } }; template - Debug(std::string_view fmt, const Args&... args) -> Debug; + static void Debug([[maybe_unused]] const FormatWithLocation& f, [[maybe_unused]] const Args&... args) + { +#ifdef _DEBUG + (Utils::String::SanitizeFormatArgs(args), ...); + DebugInternal(f.format, std::make_format_args(args...), f.location); +#endif + } private: static std::mutex MessageMutex; diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 62a39359..776d1211 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -80,7 +80,6 @@ #include #include -#include #include // Enable additional literals diff --git a/src/Steam/Proxy.cpp b/src/Steam/Proxy.cpp index 4d352322..9ec04148 100644 --- a/src/Steam/Proxy.cpp +++ b/src/Steam/Proxy.cpp @@ -1,4 +1,5 @@ #include +#include namespace Steam { @@ -6,11 +7,11 @@ namespace Steam ::Utils::Library Proxy::Overlay; ISteamClient008* Proxy::SteamClient = nullptr; - IClientEngine* Proxy::ClientEngine = nullptr; - Interface Proxy::ClientUser; - Interface Proxy::ClientFriends; + IClientEngine* Proxy::ClientEngine = nullptr; + Interface Proxy::ClientUser; + Interface Proxy::ClientFriends; - Interface Proxy::Placeholder; + Interface Proxy::Placeholder; Proxy::Handle Proxy::SteamPipe = nullptr; Proxy::Handle Proxy::SteamUser = nullptr; @@ -237,7 +238,7 @@ namespace Steam { std::lock_guard _(Proxy::CallMutex); - for(auto i = Proxy::Calls.begin(); i != Proxy::Calls.end(); ++i) + for (auto i = Proxy::Calls.begin(); i != Proxy::Calls.end(); ++i) { if(i->handled) { From 72677d4b1b14c1f0ccc54cffe60b7f62c80405ed Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 28 Dec 2022 13:37:03 +0100 Subject: [PATCH 90/96] [Logger]: Fix pipe, bruh moment --- src/Components/Modules/Logger.cpp | 4 ++-- src/Components/Modules/Logger.hpp | 4 ++-- src/Components/Modules/RCon.cpp | 2 +- src/Game/Structs.hpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index b87a7813..e355a95e 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -7,7 +7,7 @@ namespace Components std::vector Logger::MessageQueue; std::vector Logger::LoggingAddresses[2]; - std::function Logger::PipeCallback; + void(*Logger::PipeCallback)(const std::string&) = nullptr;; bool Logger::IsConsoleReady() { @@ -125,7 +125,7 @@ namespace Components } } - void Logger::PipeOutput(const std::function& callback) + void Logger::PipeOutput(void(*callback)(const std::string&)) { PipeCallback = callback; } diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 2aeace2b..8bc8f454 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -12,7 +12,7 @@ namespace Components static void Print_Stub(int channel, const char* message, ...); - static void PipeOutput(const std::function& callback); + static void PipeOutput(void(*callback)(const std::string&)); static void PrintInternal(Game::conChannel_t channel, const std::string_view& fmt, std::format_args&& args); static void ErrorInternal(Game::errorParm_t error, const std::string_view& fmt, std::format_args&& args); @@ -112,7 +112,7 @@ namespace Components static std::vector MessageQueue; static std::vector LoggingAddresses[2]; - static std::function PipeCallback; + static void(*PipeCallback)(const std::string&); static void MessagePrint(int channel, const std::string& msg); diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 52e549ce..56cf17ba 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -76,7 +76,7 @@ namespace Components bool RCon::RateLimitCheck(const Network::Address& address, const int time) { - auto ip = address.getIP(); + const auto ip = address.getIP(); if (!RateLimit.contains(ip.full)) { diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 8b12092c..f27366c1 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -6443,7 +6443,7 @@ namespace Game typedef union { unsigned char bytes[4]; - DWORD full; + std::uint32_t full; } netIP_t; struct netadr_t From 37f9d84f2ccd7007a592211e04a612c2f706ae7d Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 28 Dec 2022 15:52:55 +0100 Subject: [PATCH 91/96] [Vote]: Do not load broken menus --- src/Components/Modules/Vote.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Components/Modules/Vote.cpp b/src/Components/Modules/Vote.cpp index c75a9e21..9679907d 100644 --- a/src/Components/Modules/Vote.cpp +++ b/src/Components/Modules/Vote.cpp @@ -326,8 +326,6 @@ namespace Components Menus::Add("ui_mp/scriptmenus/callvote.menu"); Menus::Add("ui_mp/scriptmenus/kickplayer.menu"); - Menus::Add("ui_mp/scriptmenus/changegametype.menu"); - Menus::Add("ui_mp/scriptmenus/changemap.menu"); UIScript::Add("voteKick", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { From 6e8d88bad597a401373b896db688a3f1dc3b0eeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:03:33 +0000 Subject: [PATCH 92/96] Bump deps/mongoose from `311062d` to `73813a8` Bumps [deps/mongoose](https://github.com/cesanta/mongoose) from `311062d` to `73813a8`. - [Release notes](https://github.com/cesanta/mongoose/releases) - [Commits](https://github.com/cesanta/mongoose/compare/311062dc411b1ef3805a388d8443cad944024841...73813a838386f6ebca447eb54c626803163ee257) --- updated-dependencies: - dependency-name: deps/mongoose dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/mongoose | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mongoose b/deps/mongoose index 311062dc..73813a83 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 311062dc411b1ef3805a388d8443cad944024841 +Subproject commit 73813a838386f6ebca447eb54c626803163ee257 From 9abba39d69248f39421998f0b686515bb0ad1045 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 29 Dec 2022 12:34:43 +0100 Subject: [PATCH 93/96] [ServerList]: Display warning message for recoverable error (#682) --- src/Components/Modules/Logger.cpp | 2 +- src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/Playlist.cpp | 2 +- src/Components/Modules/ServerInfo.cpp | 13 +- src/Components/Modules/ServerList.cpp | 402 +++++++++++++------------- src/Components/Modules/ServerList.hpp | 8 +- src/Game/Dvars.cpp | 11 + src/Game/Dvars.hpp | 5 + src/Game/Functions.cpp | 8 - src/Utils/InfoString.cpp | 3 +- 10 files changed, 237 insertions(+), 219 deletions(-) diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index e355a95e..c1e446b7 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -20,7 +20,7 @@ namespace Components va_list va; va_start(va, message); - _vsnprintf_s(buf, _TRUNCATE, message, va); + vsnprintf_s(buf, _TRUNCATE, message, va); va_end(va); MessagePrint(channel, {buf}); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 7798c760..4126726f 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -324,7 +324,7 @@ namespace Components auto clientCount = 0; auto maxClientCount = *Game::svs_clientCount; const auto securityLevel = Dvar::Var("sv_securityLevel").get(); - const auto* password = (*Game::g_password)->current.string; + const auto* password = *Game::g_password ? (*Game::g_password)->current.string : ""; if (maxClientCount) { diff --git a/src/Components/Modules/Playlist.cpp b/src/Components/Modules/Playlist.cpp index 1b355aa4..52aa12b5 100644 --- a/src/Components/Modules/Playlist.cpp +++ b/src/Components/Modules/Playlist.cpp @@ -46,7 +46,7 @@ namespace Components void Playlist::PlaylistRequest(const Network::Address& address, [[maybe_unused]] const std::string& data) { - const auto* password = (*Game::g_password)->current.string; + const auto* password = *Game::g_password ? (*Game::g_password)->current.string : ""; if (*password) { diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 4114f2df..1dfcba0c 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -136,7 +136,7 @@ namespace Components Utils::InfoString ServerInfo::GetInfo() { auto maxClientCount = *Game::svs_clientCount; - const auto* password = (*Game::g_password)->current.string; + const auto* password = *Game::g_password ? (*Game::g_password)->current.string : ""; if (!maxClientCount) { @@ -151,7 +151,7 @@ namespace Components info.set("version", (*Game::version)->current.string); info.set("mapname", (*Game::sv_mapname)->current.string); info.set("isPrivate", *password ? "1" : "0"); - info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds())))); + info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(std::to_string(Game::Sys_Milliseconds())))); info.set("aimAssist", (Gamepad::sv_allowAimAssist.get() ? "1" : "0")); info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0")); @@ -260,7 +260,7 @@ namespace Components Dvar::Var("uiSi_aimAssist").set(info.get("aimAssist") == "0" ? "@MENU_DISABLED" : "@MENU_ENABLED"); Dvar::Var("uiSi_voiceChat").set(info.get("voiceChat") == "0" ? "@MENU_DISABLED" : "@MENU_ENABLED"); - switch (atoi(info.get("scr_team_fftype").data())) + switch (std::strtol(info.get("scr_team_fftype").data(), nullptr, 10)) { default: Dvar::Var("uiSi_ffType").set("@MENU_DISABLED"); @@ -276,12 +276,13 @@ namespace Components break; } - if (info.get("fs_game").size() > 5) + if (Utils::String::StartsWith(info.get("fs_game"), "mods/")) { - Dvar::Var("uiSi_ModName").set(info.get("fs_game").data() + 5); + auto mod = info.get("fs_game"); + Dvar::Var("uiSi_ModName").set(mod.substr(5)); } - auto lines = Utils::String::Split(data, '\n'); + const auto lines = Utils::String::Split(data, '\n'); if (lines.size() <= 1) return; diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index bb39ae5d..e50011bc 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -8,7 +8,7 @@ namespace Components { bool ServerList::SortAsc = true; - int ServerList::SortKey = ServerList::Column::Ping; + int ServerList::SortKey = static_cast>(Column::Ping); unsigned int ServerList::CurrentServer = 0; ServerList::Container ServerList::RefreshContainer; @@ -28,17 +28,19 @@ namespace Components std::vector* ServerList::GetList() { - if (ServerList::IsOnlineList()) + if (IsOnlineList()) { - return &ServerList::OnlineList; + return &OnlineList; } - if (ServerList::IsOfflineList()) + + if (IsOfflineList()) { - return &ServerList::OfflineList; + return &OfflineList; } - if (ServerList::IsFavouriteList()) + + if (IsFavouriteList()) { - return &ServerList::FavouriteList; + return &FavouriteList; } return nullptr; @@ -46,41 +48,41 @@ namespace Components bool ServerList::IsFavouriteList() { - return (Dvar::Var("ui_netSource").get() == 2); + return (*Game::ui_netSource)->current.integer == 2; } bool ServerList::IsOfflineList() { - return (Dvar::Var("ui_netSource").get() == 0); + return (*Game::ui_netSource)->current.integer == 0; } bool ServerList::IsOnlineList() { - return (Dvar::Var("ui_netSource").get() == 1); + return (*Game::ui_netSource)->current.integer == 1; } unsigned int ServerList::GetServerCount() { - return ServerList::VisibleList.size(); + return VisibleList.size(); } const char* ServerList::GetServerText(unsigned int index, int column) { - ServerList::ServerInfo* info = ServerList::GetServer(index); + auto* info = GetServer(index); if (info) { - return ServerList::GetServerInfoText(info, column); + return GetServerInfoText(info, column); } return ""; } - const char* ServerList::GetServerInfoText(ServerList::ServerInfo* server, int column, bool sorting) + const char* ServerList::GetServerInfoText(ServerInfo* server, int column, bool sorting) { if (!server) return ""; - switch (column) + switch (static_cast(column)) { case Column::Password: { @@ -115,12 +117,11 @@ namespace Components { return Utils::String::VA("^1%s", Game::UI_LocalizeMapName(server->mapname.data())); } + return Game::UI_LocalizeMapName(server->mapname.data()); } - else - { - return Utils::String::VA("^3%s", Game::UI_LocalizeMapName(server->mapname.data())); - } + + return Utils::String::VA("^3%s", Game::UI_LocalizeMapName(server->mapname.data())); } case Column::Players: @@ -135,8 +136,9 @@ namespace Components case Column::Mod: { - if (server->mod != "") + if (Utils::String::StartsWith(server->mod, "mods/")) { + // Can point to '\0' which is fine return (server->mod.data() + 5); } @@ -149,20 +151,18 @@ namespace Components { return Utils::String::VA("^2%i", server->ping); } - else if (server->ping < 150) // Below this is a medium ping + + if (server->ping < 150) // Below this is a medium ping { return Utils::String::VA("^3%i", server->ping); } - else - { - return Utils::String::VA("^1%i", server->ping); - } - } + return Utils::String::VA("^1%i", server->ping); + } default: { break; - }; + } } return ""; @@ -170,75 +170,75 @@ namespace Components void ServerList::SelectServer(unsigned int index) { - ServerList::CurrentServer = index; + CurrentServer = index; - ServerList::ServerInfo* info = ServerList::GetCurrentServer(); + auto* info = GetCurrentServer(); if (info) { - ServerList::UIServerSelected.set(true); - ServerList::UIServerSelectedMap.set(info->mapname); + UIServerSelected.set(true); + UIServerSelectedMap.set(info->mapname); Dvar::Var("ui_serverSelectedGametype").set(info->gametype); } else { - ServerList::UIServerSelected.set(false); + UIServerSelected.set(false); } } void ServerList::UpdateVisibleList([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - auto list = ServerList::GetList(); + auto* list = GetList(); if (!list) return; - std::vector tempList(*list); + std::vector tempList(*list); if (tempList.empty()) { - ServerList::Refresh(UIScript::Token(), info); + Refresh(UIScript::Token(), info); } else { list->clear(); - std::lock_guard _(ServerList::RefreshContainer.mutex); + std::lock_guard _(RefreshContainer.mutex); - ServerList::RefreshContainer.sendCount = 0; - ServerList::RefreshContainer.sentCount = 0; + RefreshContainer.sendCount = 0; + RefreshContainer.sentCount = 0; for (auto& server : tempList) { - ServerList::InsertRequest(server.addr); + InsertRequest(server.addr); } } } void ServerList::RefreshVisibleList([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - ServerList::RefreshVisibleListInternal(UIScript::Token(), info); + RefreshVisibleListInternal(UIScript::Token(), info); } void ServerList::RefreshVisibleListInternal([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info, bool refresh) { - Dvar::Var("ui_serverSelected").set(false); + Game::Dvar_SetBoolByName("ui_serverSelected", false); - ServerList::VisibleList.clear(); + VisibleList.clear(); - auto list = ServerList::GetList(); + auto* list = GetList(); if (!list) return; if (refresh) { - ServerList::Refresh(UIScript::Token(), info); + Refresh(UIScript::Token(), info); return; } - auto ui_browserShowFull = Dvar::Var("ui_browserShowFull").get(); - auto ui_browserShowEmpty = Dvar::Var("ui_browserShowEmpty").get(); - auto ui_browserShowHardcore = Dvar::Var("ui_browserKillcam").get(); - auto ui_browserShowPassword = Dvar::Var("ui_browserShowPassword").get(); - auto ui_browserMod = Dvar::Var("ui_browserMod").get(); - auto ui_joinGametype = Dvar::Var("ui_joinGametype").get(); + auto ui_browserShowFull = Dvar::Var("ui_browserShowFull").get(); + auto ui_browserShowEmpty = Dvar::Var("ui_browserShowEmpty").get(); + auto ui_browserShowHardcore = Dvar::Var("ui_browserKillcam").get(); + auto ui_browserShowPassword = Dvar::Var("ui_browserShowPassword").get(); + auto ui_browserMod = Dvar::Var("ui_browserMod").get(); + auto ui_joinGametype = (*Game::ui_joinGametype)->current.integer; for (unsigned int i = 0; i < list->size(); ++i) { @@ -257,15 +257,15 @@ namespace Components if ((ui_browserShowPassword == 0 && serverInfo->password) || (ui_browserShowPassword == 1 && !serverInfo->password)) continue; // Don't show modded servers - if ((ui_browserMod == 0 && serverInfo->mod.size()) || (ui_browserMod == 1 && !serverInfo->mod.size())) continue; + if ((ui_browserMod == 0 && static_cast(serverInfo->mod.size())) || (ui_browserMod == 1 && serverInfo->mod.empty())) continue; // Filter by gametype if (ui_joinGametype > 0 && (ui_joinGametype - 1) < *Game::gameTypeCount && Game::gameTypes[(ui_joinGametype - 1)].gameType != serverInfo->gametype) continue; - ServerList::VisibleList.push_back(i); + VisibleList.push_back(i); } - ServerList::SortList(); + SortList(); } void ServerList::Refresh([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) @@ -273,37 +273,38 @@ namespace Components Dvar::Var("ui_serverSelected").set(false); //Localization::Set("MPUI_SERVERQUERIED", "Sent requests: 0/0"); -// ServerList::OnlineList.clear(); -// ServerList::OfflineList.clear(); -// ServerList::FavouriteList.clear(); - - auto list = ServerList::GetList(); +#if 0 + OnlineList.clear(); + OfflineList.clear(); + FavouriteList.clear(); +#endif + auto* list = GetList(); if (list) list->clear(); - ServerList::VisibleList.clear(); + VisibleList.clear(); { - std::lock_guard _(ServerList::RefreshContainer.mutex); - ServerList::RefreshContainer.servers.clear(); - ServerList::RefreshContainer.sendCount = 0; - ServerList::RefreshContainer.sentCount = 0; + std::lock_guard _(RefreshContainer.mutex); + RefreshContainer.servers.clear(); + RefreshContainer.sendCount = 0; + RefreshContainer.sentCount = 0; } - if (ServerList::IsOfflineList()) + if (IsOfflineList()) { Discovery::Perform(); } - else if (ServerList::IsOnlineList()) + else if (IsOnlineList()) { const auto masterPort = Dvar::Var("masterPort").get(); const auto masterServerName = Dvar::Var("masterServerName").get(); // Check if our dvars can properly convert to a address Game::netadr_t masterServerAddr; - if (!ServerList::GetMasterServer(masterServerName, masterPort, masterServerAddr)) + if (!GetMasterServer(masterServerName, masterPort, masterServerAddr)) { Logger::Print("Could not resolve address for {}:{}", masterServerName, masterPort); - Toast::Show("cardicon_headshot", "^1Error", Utils::String::VA("Could not resolve address for %s:%u", masterServerName, masterPort), 5000); + Toast::Show("cardicon_headshot", "^1Error", Utils::String::VA("Could not resolve address for %s:%i", masterServerName, masterPort), 5000); UseMasterServer = false; return; } @@ -312,16 +313,16 @@ namespace Components UseMasterServer = true; - ServerList::RefreshContainer.awatingList = true; - ServerList::RefreshContainer.awaitTime = Game::Sys_Milliseconds(); - ServerList::RefreshContainer.host = Network::Address(Utils::String::VA("%s:%u", masterServerName, masterPort)); + RefreshContainer.awatingList = true; + RefreshContainer.awaitTime = Game::Sys_Milliseconds(); + RefreshContainer.host = Network::Address(Utils::String::VA("%s:%u", masterServerName, masterPort)); Logger::Print("Sending serverlist request to master\n"); - Network::SendCommand(ServerList::RefreshContainer.host, "getservers", Utils::String::VA("IW4 %i full empty", PROTOCOL)); + Network::SendCommand(RefreshContainer.host, "getservers", Utils::String::VA("IW4 %i full empty", PROTOCOL)); } - else if (ServerList::IsFavouriteList()) + else if (IsFavouriteList()) { - ServerList::LoadFavourties(); + LoadFavourties(); } } @@ -409,22 +410,22 @@ namespace Components const auto data = nlohmann::json(servers); Utils::IO::WriteFile(FavouriteFile, data.dump()); - auto list = ServerList::GetList(); + auto* list = GetList(); if (list) list->clear(); - ServerList::RefreshVisibleListInternal(UIScript::Token(), nullptr); + RefreshVisibleListInternal(UIScript::Token(), nullptr); Game::ShowMessageBox("Server removed from favourites.", "Success"); } void ServerList::LoadFavourties() { - if (!ServerList::IsFavouriteList()) + if (!IsFavouriteList()) { return; } - auto list = ServerList::GetList(); + auto* list = GetList(); if (list) list->clear(); const auto parseData = Utils::IO::ReadFile(FavouriteFile); @@ -455,20 +456,20 @@ namespace Components for (const auto& server : servers) { if (!server.is_string()) continue; - ServerList::InsertRequest(server.get()); + InsertRequest(server.get()); } } void ServerList::InsertRequest(Network::Address address) { - std::lock_guard _(ServerList::RefreshContainer.mutex); + std::lock_guard _(RefreshContainer.mutex); - ServerList::Container::ServerContainer container; + Container::ServerContainer container; container.sent = false; container.target = address; bool alreadyInserted = false; - for (auto &server : ServerList::RefreshContainer.servers) + for (auto &server : RefreshContainer.servers) { if (server.target == container.target) { @@ -479,34 +480,34 @@ namespace Components if (!alreadyInserted) { - ServerList::RefreshContainer.servers.push_back(container); + RefreshContainer.servers.push_back(container); - auto list = ServerList::GetList(); + auto* list = GetList(); if (list) { for (auto& server : *list) { if (server.addr == container.target) { - --ServerList::RefreshContainer.sendCount; - --ServerList::RefreshContainer.sentCount; + --RefreshContainer.sendCount; + --RefreshContainer.sentCount; break; } } } - ++ServerList::RefreshContainer.sendCount; + ++RefreshContainer.sendCount; } } void ServerList::Insert(const Network::Address& address, const Utils::InfoString& info) { - std::lock_guard _(ServerList::RefreshContainer.mutex); + std::lock_guard _(RefreshContainer.mutex); - for (auto i = ServerList::RefreshContainer.servers.begin(); i != ServerList::RefreshContainer.servers.end();) + for (auto i = RefreshContainer.servers.begin(); i != RefreshContainer.servers.end();) { // Our desired server - if (i->target == address && i->sent) + if ((i->target == address) && i->sent) { // Challenge did not match if (i->challenge != info.get("challenge")) @@ -523,16 +524,16 @@ namespace Components server.gametype = info.get("gametype"); server.shortversion = info.get("shortversion"); server.mod = info.get("fs_game"); - server.matchType = atoi(info.get("matchtype").data()); - server.clients = atoi(info.get("clients").data()); - server.bots = atoi(info.get("bots").data()); - server.securityLevel = atoi(info.get("securityLevel").data()); - server.maxClients = atoi(info.get("sv_maxclients").data()); - server.password = (atoi(info.get("isPrivate").data()) != 0); - server.aimassist = (atoi(info.get("aimAssist").data()) != 0); - server.voice = (atoi(info.get("voiceChat").data()) != 0); - server.hardcore = (atoi(info.get("hc").data()) != 0); - server.svRunning = (atoi(info.get("sv_running").data()) != 0); + server.matchType = std::strtol(info.get("matchtype").data(), nullptr, 10); + server.clients = std::strtol(info.get("clients").data(), nullptr, 10); + server.bots = std::strtol(info.get("bots").data(), nullptr, 10); + server.securityLevel = std::strtol(info.get("securityLevel").data(), nullptr, 10); + server.maxClients = std::strtol(info.get("sv_maxclients").data(), nullptr, 10); + server.password = info.get("isPrivate") == "1"s; + server.aimassist = info.get("aimAssist") == "1"; + server.voice = info.get("voiceChat") == "1"s; + server.hardcore = info.get("hc") == "1"s; + server.svRunning = info.get("sv_running") == "1"s; server.ping = (Game::Sys_Milliseconds() - i->sendTime); server.addr = address; @@ -542,18 +543,20 @@ namespace Components server.mod = TextRenderer::StripMaterialTextIcons(server.mod); // Remove server from queue - i = ServerList::RefreshContainer.servers.erase(i); + i = RefreshContainer.servers.erase(i); // Servers with more than 18 players or less than 0 players are faking for sure // So lets ignore those if (server.clients > 18 || server.maxClients > 18 || server.clients < 0 || server.maxClients < 0) + { return; + } // Check if already inserted and remove - auto list = ServerList::GetList(); + auto* list = GetList(); if (!list) return; - unsigned int k = 0; + std::size_t k = 0; for (auto j = list->begin(); j != list->end(); ++k) { if (j->addr == address) @@ -567,11 +570,11 @@ namespace Components } // Also remove from visible list - for (auto j = ServerList::VisibleList.begin(); j != ServerList::VisibleList.end();) + for (auto j = VisibleList.begin(); j != VisibleList.end();) { if (*j == k) { - j = ServerList::VisibleList.erase(j); + j = VisibleList.erase(j); } else { @@ -581,15 +584,15 @@ namespace Components if (info.get("gamename") == "IW4"s && server.matchType #if !defined(DEBUG) && defined(VERSION_FILTER) - && ServerList::CompareVersion(server.shortversion, SHORTVERSION) + && CompareVersion(server.shortversion, SHORTVERSION) #endif ) { - auto lList = ServerList::GetList(); + auto* lList = GetList(); if (lList) { lList->push_back(server); - ServerList::RefreshVisibleListInternal(UIScript::Token(), nullptr); + RefreshVisibleListInternal(UIScript::Token(), nullptr); } } } @@ -609,10 +612,18 @@ namespace Components while (subVersions2.size() >= 3) subVersions2.pop_back(); if (subVersions1.size() != subVersions2.size()) return false; - for (unsigned int i = 0; i < subVersions1.size(); ++i) + for (std::size_t i = 0; i < subVersions1.size(); ++i) { - if (atoi(subVersions1[i].data()) != atoi(subVersions2[i].data())) + try { + if (std::stoi(subVersions1[i]) != std::stoi(subVersions2[i])) + { + return false; + } + } + catch (const std::exception& ex) + { + Logger::Warning(Game::CON_CHANNEL_CONSOLEONLY, "{} while performing numeric comparison between {} and {}\n", ex.what(), subVersions1[i], subVersions2[i]); return false; } } @@ -622,20 +633,20 @@ namespace Components ServerList::ServerInfo* ServerList::GetCurrentServer() { - return ServerList::GetServer(ServerList::CurrentServer); + return GetServer(CurrentServer); } void ServerList::SortList() { // Only sort when the serverlist is open - if (!ServerList::IsServerListOpen()) return; + if (!IsServerListOpen()) return; - std::stable_sort(ServerList::VisibleList.begin(), ServerList::VisibleList.end(), [](const unsigned int &server1, const unsigned int &server2) -> bool + std::ranges::stable_sort(VisibleList, [](const unsigned int& server1, const unsigned int& server2) -> bool { ServerInfo* info1 = nullptr; ServerInfo* info2 = nullptr; - auto list = ServerList::GetList(); + auto* list = GetList(); if (!list) return false; if (list->size() > server1) info1 = &(*list)[server1]; @@ -645,35 +656,36 @@ namespace Components if (!info2) return false; // Numerical comparisons - if (ServerList::SortKey == ServerList::Column::Ping) + if (SortKey == static_cast>(Column::Ping)) { return info1->ping < info2->ping; } - else if (ServerList::SortKey == ServerList::Column::Players) + + if (SortKey == static_cast>(Column::Players)) { return info1->clients < info2->clients; } - std::string text1 = Utils::String::ToLower(TextRenderer::StripColors(ServerList::GetServerInfoText(info1, ServerList::SortKey, true))); - std::string text2 = Utils::String::ToLower(TextRenderer::StripColors(ServerList::GetServerInfoText(info2, ServerList::SortKey, true))); + auto text1 = Utils::String::ToLower(TextRenderer::StripColors(GetServerInfoText(info1, SortKey, true))); + auto text2 = Utils::String::ToLower(TextRenderer::StripColors(GetServerInfoText(info2, SortKey, true))); // ASCII-based comparison return text1.compare(text2) < 0; }); - if (!ServerList::SortAsc) std::reverse(ServerList::VisibleList.begin(), ServerList::VisibleList.end()); + if (!SortAsc) std::ranges::reverse(VisibleList); } ServerList::ServerInfo* ServerList::GetServer(unsigned int index) { - if (ServerList::VisibleList.size() > index) + if (VisibleList.size() > index) { - auto list = ServerList::GetList(); + auto* list = GetList(); if (!list) return nullptr; - if (list->size() > ServerList::VisibleList[index]) + if (list->size() > VisibleList[index]) { - return &(*list)[ServerList::VisibleList[index]]; + return &(*list)[VisibleList[index]]; } } @@ -683,40 +695,42 @@ namespace Components void ServerList::Frame() { static Utils::Time::Interval frameLimit; - const auto interval = static_cast(1000.0f / ServerList::NETServerFrames.get()); + const auto interval = static_cast(1000.0f / static_cast(NETServerFrames.get())); if (!frameLimit.elapsed(std::chrono::milliseconds(interval))) + { return; + } frameLimit.update(); - std::lock_guard _(ServerList::RefreshContainer.mutex); + std::lock_guard _(RefreshContainer.mutex); - if (ServerList::RefreshContainer.awatingList) + if (RefreshContainer.awatingList) { // Stop counting if we are out of the server browser menu - if (!ServerList::IsServerListOpen()) + if (!IsServerListOpen()) { - ServerList::RefreshContainer.awatingList = false; + RefreshContainer.awatingList = false; } // Check if we haven't got a response within 5 seconds - if (Game::Sys_Milliseconds() - ServerList::RefreshContainer.awaitTime > 5000) + if (Game::Sys_Milliseconds() - RefreshContainer.awaitTime > 5000) { - ServerList::RefreshContainer.awatingList = false; + RefreshContainer.awatingList = false; - Logger::Print("We haven't received a response from the master within {} seconds!\n", (Game::Sys_Milliseconds() - ServerList::RefreshContainer.awaitTime) / 1000); - Toast::Show("cardicon_headshot", "^1Error", "Failed to reach master server, using node servers instead.", 5000); + Logger::Print("We haven't received a response from the master within {} seconds!\n", (Game::Sys_Milliseconds() - RefreshContainer.awaitTime) / 1000); + Toast::Show("cardicon_headshot", "^3Warning", "Failed to reach master server. Using node system instead.", 5000); UseMasterServer = false; Node::Synchronize(); } } - auto requestLimit = ServerList::NETServerQueryLimit.get(); - for (unsigned int i = 0; i < ServerList::RefreshContainer.servers.size() && requestLimit > 0; ++i) + auto requestLimit = NETServerQueryLimit.get(); + for (std::size_t i = 0; i < RefreshContainer.servers.size() && requestLimit > 0; ++i) { - ServerList::Container::ServerContainer* server = &ServerList::RefreshContainer.servers[i]; + auto* server = &RefreshContainer.servers[i]; if (server->sent) continue; // Found server we can send a request to @@ -726,47 +740,43 @@ namespace Components server->sendTime = Game::Sys_Milliseconds(); server->challenge = Utils::Cryptography::Rand::GenerateChallenge(); - ++ServerList::RefreshContainer.sentCount; + ++RefreshContainer.sentCount; Network::SendCommand(server->target, "getinfo", server->challenge); - // Display in the menu, like in COD4 + // Display in the menu, like in CoD4 - Disabled to avoid spamming? //Localization::Set("MPUI_SERVERQUERIED", Utils::String::VA("Sent requests: %d/%d", ServerList::RefreshContainer.sentCount, ServerList::RefreshContainer.sendCount)); } - ServerList::UpdateVisibleInfo(); + UpdateVisibleInfo(); } void ServerList::UpdateSource() { - Dvar::Var netSource("ui_netSource"); + auto source = (*Game::ui_netSource)->current.integer; - int source = netSource.get(); - - if (++source > netSource.get()->domain.integer.max) + if (++source > (*Game::ui_netSource)->domain.integer.max) { source = 0; } - netSource.set(source); + Game::Dvar_SetInt(*Game::ui_netSource, source); - ServerList::RefreshVisibleListInternal(UIScript::Token(), nullptr, true); + RefreshVisibleListInternal(UIScript::Token(), nullptr, true); } void ServerList::UpdateGameType() { - Dvar::Var joinGametype("ui_joinGametype"); - - int gametype = joinGametype.get(); + auto gametype = (*Game::ui_joinGametype)->current.integer; if (++gametype > *Game::gameTypeCount) { gametype = 0; } - joinGametype.set(gametype); + Game::Dvar_SetInt(*Game::ui_joinGametype, gametype); - ServerList::RefreshVisibleListInternal(UIScript::Token(), nullptr); + RefreshVisibleListInternal(UIScript::Token(), nullptr); } void ServerList::UpdateVisibleInfo() @@ -775,7 +785,7 @@ namespace Components static int players = 0; static int bots = 0; - auto list = ServerList::GetList(); + auto list = GetList(); if (list) { @@ -783,7 +793,7 @@ namespace Components int newPlayers = 0; int newBots = 0; - for (unsigned int i = 0; i < list->size(); ++i) + for (std::size_t i = 0; i < list->size(); ++i) { newPlayers += list->at(i).clients; newBots += list->at(i).bots; @@ -816,47 +826,45 @@ namespace Components ServerList::ServerList() { - ServerList::OnlineList.clear(); - ServerList::OfflineList.clear(); - ServerList::FavouriteList.clear(); - ServerList::VisibleList.clear(); + OnlineList.clear(); + OfflineList.clear(); + FavouriteList.clear(); + VisibleList.clear(); Scheduler::Once([] { - ServerList::UIServerSelected = Dvar::Register("ui_serverSelected", false, + UIServerSelected = Dvar::Register("ui_serverSelected", false, Game::DVAR_NONE, "Whether a server has been selected in the serverlist"); - ServerList::UIServerSelectedMap = Dvar::Register("ui_serverSelectedMap", "mp_afghan", + UIServerSelectedMap = Dvar::Register("ui_serverSelectedMap", "mp_afghan", Game::DVAR_NONE, "Map of the selected server"); - ServerList::NETServerQueryLimit = Dvar::Register("net_serverQueryLimit", 1, + NETServerQueryLimit = Dvar::Register("net_serverQueryLimit", 1, 1, 10, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server queries per frame"); - ServerList::NETServerFrames = Dvar::Register("net_serverFrames", 30, + NETServerFrames = Dvar::Register("net_serverFrames", 30, 1, 60, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server query frames per second"); }, Scheduler::Pipeline::MAIN); // Fix ui_netsource dvar Utils::Hook::Nop(0x4CDEEC, 5); // Don't reset the netsource when gametypes aren't loaded - Dvar::Register("ui_netSource", 1, 0, 2, Game::DVAR_ARCHIVE, reinterpret_cast(0x6D9F08)); - //Localization::Set("MPUI_SERVERQUERIED", "Sent requests: 0/0"); Localization::Set("MPUI_SERVERQUERIED", "Servers: 0\nPlayers: 0 (0)"); Network::OnClientPacket("getServersResponse", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { - if (ServerList::RefreshContainer.host != address) return; // Only parse from host we sent to + if (RefreshContainer.host != address) return; // Only parse from host we sent to - ServerList::RefreshContainer.awatingList = false; + RefreshContainer.awatingList = false; - std::lock_guard _(ServerList::RefreshContainer.mutex); + std::lock_guard _(RefreshContainer.mutex); int offset = 0; - int count = ServerList::RefreshContainer.servers.size(); - ServerList::MasterEntry* entry = nullptr; + auto count = RefreshContainer.servers.size(); + MasterEntry* entry = nullptr; // Find first entry do { - entry = reinterpret_cast(const_cast(data.data()) + offset++); + entry = reinterpret_cast(const_cast(data.data()) + offset++); } while (!entry->HasSeparator() && !entry->IsEndToken()); for (int i = 0; !entry[i].IsEndToken() && entry[i].HasSeparator(); ++i) @@ -866,29 +874,29 @@ namespace Components serverAddr.setPort(ntohs(entry[i].port)); serverAddr.setType(Game::NA_IP); - ServerList::InsertRequest(serverAddr); + InsertRequest(serverAddr); } - Logger::Print("Parsed {} servers from master\n", ServerList::RefreshContainer.servers.size() - count); + Logger::Print("Parsed {} servers from master\n", RefreshContainer.servers.size() - count); }); // Set default masterServerName + port and save it Utils::Hook::Set(0x60AD92, "master.xlabs.dev"); - Utils::Hook::Set(0x60AD90, Game::DVAR_NONE); // masterServerName - Utils::Hook::Set(0x60ADC6, Game::DVAR_NONE); // masterPort + Utils::Hook::Set(0x60AD90, Game::DVAR_NONE); // masterServerName + Utils::Hook::Set(0x60ADC6, Game::DVAR_NONE); // masterPort // Add server list feeder - UIFeeder::Add(2.0f, ServerList::GetServerCount, ServerList::GetServerText, ServerList::SelectServer); + UIFeeder::Add(2.0f, GetServerCount, GetServerText, SelectServer); // Add required UIScripts - UIScript::Add("UpdateFilter", ServerList::RefreshVisibleList); - UIScript::Add("RefreshFilter", ServerList::UpdateVisibleList); + UIScript::Add("UpdateFilter", RefreshVisibleList); + UIScript::Add("RefreshFilter", UpdateVisibleList); - UIScript::Add("RefreshServers", ServerList::Refresh); + UIScript::Add("RefreshServers", Refresh); UIScript::Add("JoinServer", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - auto* serverInfo = ServerList::GetServer(ServerList::CurrentServer); + auto* serverInfo = GetServer(CurrentServer); if (serverInfo) { Party::Connect(serverInfo->addr); @@ -897,53 +905,53 @@ namespace Components UIScript::Add("ServerSort", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - auto key = token.get(); - if (ServerList::SortKey == key) + const auto key = token.get(); + if (SortKey == key) { - ServerList::SortAsc = !ServerList::SortAsc; + SortAsc = !SortAsc; } else { - ServerList::SortKey = key; - ServerList::SortAsc = true; + SortKey = key; + SortAsc = true; } - Logger::Print("Sorting server list by token: {}\n", ServerList::SortKey); - ServerList::SortList(); + Logger::Print("Sorting server list by token: {}\n", SortKey); + SortList(); }); UIScript::Add("CreateListFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - auto* serverInfo = ServerList::GetCurrentServer(); + auto* serverInfo = GetCurrentServer(); if (info) { - ServerList::StoreFavourite(serverInfo->addr.getString()); + StoreFavourite(serverInfo->addr.getString()); } }); UIScript::Add("CreateFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - ServerList::StoreFavourite(Dvar::Var("ui_favoriteAddress").get()); + StoreFavourite(Dvar::Var("ui_favoriteAddress").get()); }); UIScript::Add("CreateCurrentServerFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { if (Game::CL_IsCgameInitialized()) { - std::string addressText = Network::Address(*Game::connectedHost).getString(); - if (addressText != "0.0.0.0:0" && addressText != "loopback") + const auto addressText = Network::Address(*Game::connectedHost).getString(); + if (addressText != "0.0.0.0:0"s && addressText != "loopback"s) { - ServerList::StoreFavourite(addressText); + StoreFavourite(addressText); } } }); UIScript::Add("DeleteFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - auto* serverInfo = ServerList::GetCurrentServer(); + auto* serverInfo = GetCurrentServer(); if (serverInfo) { - ServerList::RemoveFavourite(serverInfo->addr.getString()); + RemoveFavourite(serverInfo->addr.getString()); } }); @@ -951,7 +959,7 @@ namespace Components Command::Add("playerCount", [](Command::Params*) { auto count = 0; - for (const auto& server : ServerList::OnlineList) + for (const auto& server : OnlineList) { count += server.clients; } @@ -960,17 +968,17 @@ namespace Components }); #endif // Add required ownerDraws - UIScript::AddOwnerDraw(220, ServerList::UpdateSource); - UIScript::AddOwnerDraw(253, ServerList::UpdateGameType); + UIScript::AddOwnerDraw(220, UpdateSource); + UIScript::AddOwnerDraw(253, UpdateGameType); // Add frame callback - Scheduler::Loop(ServerList::Frame, Scheduler::Pipeline::CLIENT); + Scheduler::Loop(Frame, Scheduler::Pipeline::CLIENT); } ServerList::~ServerList() { - std::lock_guard _(ServerList::RefreshContainer.mutex); - ServerList::RefreshContainer.awatingList = false; - ServerList::RefreshContainer.servers.clear(); + std::lock_guard _(RefreshContainer.mutex); + RefreshContainer.awatingList = false; + RefreshContainer.servers.clear(); } } diff --git a/src/Components/Modules/ServerList.hpp b/src/Components/Modules/ServerList.hpp index b65036e0..834f90e5 100644 --- a/src/Components/Modules/ServerList.hpp +++ b/src/Components/Modules/ServerList.hpp @@ -57,7 +57,7 @@ namespace Components static bool UseMasterServer; private: - enum Column + enum class Column : int { Password, Matchtype, @@ -69,6 +69,8 @@ namespace Components Gametype, Mod, Ping, + + Count }; static constexpr auto* FavouriteFile = "players/favourites.json"; @@ -83,13 +85,13 @@ namespace Components uint16_t port; }; - bool IsEndToken() + bool IsEndToken() const { // End of transmission or file token return (token[0] == 'E' && token[1] == 'O' && (token[2] == 'T' || token[2] == 'F')); } - bool HasSeparator() + bool HasSeparator() const { return (token[6] == '\\'); } diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp index 038308e0..be172a8a 100644 --- a/src/Game/Dvars.cpp +++ b/src/Game/Dvars.cpp @@ -22,6 +22,15 @@ namespace Game Dvar_DisplayableValue_t Dvar_DisplayableValue = Dvar_DisplayableValue_t(0x4B5530); Dvar_Reset_t Dvar_Reset = Dvar_Reset_t(0x4FEFD0); + Dvar_SetFromStringByName_t Dvar_SetFromStringByName = Dvar_SetFromStringByName_t(0x4F52E0); + Dvar_SetFromStringByNameFromSource_t Dvar_SetFromStringByNameFromSource = Dvar_SetFromStringByNameFromSource_t(0x4FC770); + Dvar_SetStringByName_t Dvar_SetStringByName = Dvar_SetStringByName_t(0x44F060); + Dvar_SetString_t Dvar_SetString = Dvar_SetString_t(0x4A9580); + Dvar_SetBool_t Dvar_SetBool = Dvar_SetBool_t(0x4A9510); + Dvar_SetBoolByName_t Dvar_SetBoolByName = Dvar_SetBoolByName_t(0x45C4D0); + Dvar_SetFloat_t Dvar_SetFloat = Dvar_SetFloat_t(0x40BB20); + Dvar_SetInt_t Dvar_SetInt = Dvar_SetInt_t(0x421DA0); + const dvar_t** com_developer = reinterpret_cast(0x1AD78E8); const dvar_t** com_developer_script = reinterpret_cast(0x1AD8F10); const dvar_t** com_timescale = reinterpret_cast(0x1AD7920); @@ -61,7 +70,9 @@ namespace Game const dvar_t** ui_currentMap = reinterpret_cast(0x62E2834); const dvar_t** ui_gametype = reinterpret_cast(0x62E2828); const dvar_t** ui_mapname = reinterpret_cast(0x62E279C); + const dvar_t** ui_joinGametype = reinterpret_cast(0x62E2840); const dvar_t** ui_netGameType = reinterpret_cast(0x62E2838); + const dvar_t** ui_netSource = reinterpret_cast(0x62E27E8); const dvar_t** loc_warnings = reinterpret_cast(0x62C8700); const dvar_t** loc_warningsAsErrors = reinterpret_cast(0x62C86FC); diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp index b3397ebd..f54eaba7 100644 --- a/src/Game/Dvars.hpp +++ b/src/Game/Dvars.hpp @@ -48,6 +48,9 @@ namespace Game typedef void(*Dvar_SetBool_t)(const dvar_t* dvar, bool enabled); extern Dvar_SetBool_t Dvar_SetBool; + typedef void(*Dvar_SetBoolByName_t)(const char* dvarName, bool value); + extern Dvar_SetBoolByName_t Dvar_SetBoolByName; + typedef void(*Dvar_SetFloat_t)(const dvar_t* dvar, float value); extern Dvar_SetFloat_t Dvar_SetFloat; @@ -117,7 +120,9 @@ namespace Game extern const dvar_t** ui_currentMap; extern const dvar_t** ui_gametype; extern const dvar_t** ui_mapname; + extern const dvar_t** ui_joinGametype; extern const dvar_t** ui_netGameType; + extern const dvar_t** ui_netSource; extern const dvar_t** loc_warnings; extern const dvar_t** loc_warningsAsErrors; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index c641e670..ed6f44c8 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -164,14 +164,6 @@ namespace Game SEH_ReadCharFromString_t SEH_ReadCharFromString = SEH_ReadCharFromString_t(0x486560); SEH_GetCurrentLanguage_t SEH_GetCurrentLanguage = SEH_GetCurrentLanguage_t(0x4F6110); - Dvar_SetFromStringByName_t Dvar_SetFromStringByName = Dvar_SetFromStringByName_t(0x4F52E0); - Dvar_SetFromStringByNameFromSource_t Dvar_SetFromStringByNameFromSource = Dvar_SetFromStringByNameFromSource_t(0x4FC770); - Dvar_SetStringByName_t Dvar_SetStringByName = Dvar_SetStringByName_t(0x44F060); - Dvar_SetString_t Dvar_SetString = Dvar_SetString_t(0x4A9580); - Dvar_SetBool_t Dvar_SetBool = Dvar_SetBool_t(0x4A9510); - Dvar_SetFloat_t Dvar_SetFloat = Dvar_SetFloat_t(0x40BB20); - Dvar_SetInt_t Dvar_SetInt = Dvar_SetInt_t(0x421DA0); - SND_Init_t SND_Init = SND_Init_t(0x46A630); SND_InitDriver_t SND_InitDriver = SND_InitDriver_t(0x4F5090); diff --git a/src/Utils/InfoString.cpp b/src/Utils/InfoString.cpp index 9eb8c37b..bfefdff2 100644 --- a/src/Utils/InfoString.cpp +++ b/src/Utils/InfoString.cpp @@ -19,8 +19,7 @@ namespace Utils std::string InfoString::get(const std::string& key) const { - const auto value = this->keyValuePairs.find(key); - if (value != this->keyValuePairs.end()) + if (const auto value = this->keyValuePairs.find(key); value != this->keyValuePairs.end()) { return value->second; } From e6349468c2a707503805fd0ac08b33ff78bd5f97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:02:49 +0000 Subject: [PATCH 94/96] Bump deps/protobuf from `7ce9c41` to `8d5fded` Bumps [deps/protobuf](https://github.com/google/protobuf) from `7ce9c41` to `8d5fded`. - [Release notes](https://github.com/google/protobuf/releases) - [Commits](https://github.com/google/protobuf/compare/7ce9c415455c098409222702b3b4572b47232882...8d5fdedd42ef361dcfc1531fba4f33470273f375) --- updated-dependencies: - dependency-name: deps/protobuf dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/protobuf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/protobuf b/deps/protobuf index 7ce9c415..8d5fdedd 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 7ce9c415455c098409222702b3b4572b47232882 +Subproject commit 8d5fdedd42ef361dcfc1531fba4f33470273f375 From ed8e97dfc68f5f0374acd1faed6ee80bd605bfde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 17:02:52 +0000 Subject: [PATCH 95/96] Bump deps/GSL from `c016bdc` to `f94c1f6` Bumps [deps/GSL](https://github.com/microsoft/GSL) from `c016bdc` to `f94c1f6`. - [Release notes](https://github.com/microsoft/GSL/releases) - [Commits](https://github.com/microsoft/GSL/compare/c016bdc77f28891cfc42fc219bd5365e89d3ebda...f94c1f6f2b5e141d5f6eb3d284cd4a8cf9a81aac) --- updated-dependencies: - dependency-name: deps/GSL dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/GSL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/GSL b/deps/GSL index c016bdc7..f94c1f6f 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit c016bdc77f28891cfc42fc219bd5365e89d3ebda +Subproject commit f94c1f6f2b5e141d5f6eb3d284cd4a8cf9a81aac From 30e3b76413689adbd6434667bc4b38d196c8a0e9 Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 30 Dec 2022 21:25:57 +0100 Subject: [PATCH 96/96] [General]: Update changelog (#685) --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fed073f..358e25a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,51 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0.3.0/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.7.7] - 2022-12-31 + +### Added + +- Add `r_forceTechnique` Dvar to debug techniques on materials. +- Add `IsSprinting` GSC method (#587) +- Add `StorageLoad` GSC function (#595) +- Add `bg_climbAnything` Dvar (#663) +- Add ClanTag support for bots (#645) +- Add `sv_randomBotNames` Dvar (#665) +- Add support for parsing localized strings files (.str & .json) (#621) +- Add `callvote` menus (#613) +- IW3x-port converts Technique Sets between CoD4 and CoD6 properly. +- Add new map porting utility tool that makes the map porting process between CoD4 to CoD6 easy. + +### Changed + +- `r_drawModelNames` now uses ground lighting when available. +- Speculars are now enabled on custom maps. +- Techset(s) get loaded from disk first rather than memory. +- Use CSO format for Vertex Shaders & Pixel Shaders on ZoneBuilder to allow replacement/swapping. +- New map porting utility tool builds teams directly into the map. + +### Fixed + +- Fix bug where ZoneBuilder would not build loaded sounds correctly. +- Fix bug where ZoneBuilder no longer differentiates assets depending on their name. +- Fix building FX with ZoneBuilder. +- Fix branding in ZoneBuilder generated zones. +- Fix Script String crash when building zones. +- Fix the changelog menu (#583) +- Fix bug when adding commands (#609) +- Fix bug where some ported maps would either crash or lag (mp_zavod, mp_kowloon, ...) +- Fix GSC conversion from CoD4 to CoD6 (Specular Scale, Create Exp Fog, Create FX, ...) +- The map porting process from CoD4 to IW4x has improved. +- Ported map zones are about 40% lighter than before. +- Static models are now lit correctly depending on their position and ground lighting. +- New map porting utility ports sounds and effects properly. + +### Known issues + +- HTTPS is not supported for fast downloads at the moment. +- Sound issue fix is experimental as the bug is not fully understood. +- `reloadmenus` command does not free resources used by custom menus. + ## [0.7.6] - 2022-11-22 ### Added