From a2437c6f4805b1f8d562a01cae50abfcbf71cb75 Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 31 Mar 2023 16:59:08 +0200 Subject: [PATCH 01/51] [PlayerName]: Display error message to user (#889) --- src/Components/Modules/PlayerName.cpp | 55 ++++++++++++++------------- src/Components/Modules/PlayerName.hpp | 6 +-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/Components/Modules/PlayerName.cpp b/src/Components/Modules/PlayerName.cpp index d03cc88f..f0d758e8 100644 --- a/src/Components/Modules/PlayerName.cpp +++ b/src/Components/Modules/PlayerName.cpp @@ -6,26 +6,6 @@ namespace Components { Dvar::Var PlayerName::sv_allowColoredNames; - bool PlayerName::IsBadChar(int c) - { - if (c == '%') - { - return true; - } - - if (c == '~') - { - return true; - } - - if (c < 32 || c > 126) - { - return true; - } - - return false; - } - void PlayerName::UserInfoCopy(char* buffer, const char* name, const int size) { if (!sv_allowColoredNames.get()) @@ -83,6 +63,26 @@ namespace Components return string; } + bool PlayerName::IsBadChar(int c) + { + if (c == '%') + { + return true; + } + + if (c == '~') + { + return true; + } + + if (c < 32 || c > 126) + { + return true; + } + + return false; + } + bool PlayerName::CopyClientNameCheck(char* dest, const char* source, int size) { Utils::Hook::Call(0x4D6F80)(dest, source, size); // I_strncpyz @@ -103,10 +103,15 @@ namespace Components return true; } + void PlayerName::DropClient(Game::client_t* drop) + { + const auto* reason = "Invalid name detected"; + Network::SendCommand(drop->header.netchan.remoteAddress, "error", reason); + Game::SV_DropClient(drop, reason, false); + } + __declspec(naked) void PlayerName::SV_UserinfoChangedStub() { - using namespace Game; - __asm { call CopyClientNameCheck @@ -116,11 +121,9 @@ namespace Components pushad - push 1 // tellThem - push INVALID_NAME_MSG // reason push edi // drop - call SV_DropClient - add esp, 0xC + call DropClient + add esp, 0x4 popad diff --git a/src/Components/Modules/PlayerName.hpp b/src/Components/Modules/PlayerName.hpp index f216e14e..e88c3e99 100644 --- a/src/Components/Modules/PlayerName.hpp +++ b/src/Components/Modules/PlayerName.hpp @@ -13,15 +13,13 @@ namespace Components private: static Dvar::Var sv_allowColoredNames; - // Message used when kicking players - static constexpr auto INVALID_NAME_MSG = "Invalid name detected"; - - static bool IsBadChar(int c); static char* CleanStrStub(char* string); static void ClientCleanName(); + static bool IsBadChar(int c); static bool CopyClientNameCheck(char* dest, const char* source, int size); + static void DropClient(Game::client_t* drop); static void SV_UserinfoChangedStub(); }; } From ba98f78e9951cbcb2b43dab78eb3672076afc030 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 17:16:26 +0000 Subject: [PATCH 02/51] Bump deps/libtomcrypt from `2a1b284` to `05f9407` Bumps [deps/libtomcrypt](https://github.com/libtom/libtomcrypt) from `2a1b284` to `05f9407`. - [Release notes](https://github.com/libtom/libtomcrypt/releases) - [Commits](https://github.com/libtom/libtomcrypt/compare/2a1b284677a51f587ab7cd9d97395e0c0c93a447...05f94077cc0aa42f550e85d2785a92b668117ada) --- updated-dependencies: - dependency-name: deps/libtomcrypt dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtomcrypt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtomcrypt b/deps/libtomcrypt index 2a1b2846..05f94077 160000 --- a/deps/libtomcrypt +++ b/deps/libtomcrypt @@ -1 +1 @@ -Subproject commit 2a1b284677a51f587ab7cd9d97395e0c0c93a447 +Subproject commit 05f94077cc0aa42f550e85d2785a92b668117ada From 606b7ab54c2a061981809d9ed063e3b0dd831c20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 17:16:33 +0000 Subject: [PATCH 03/51] Bump deps/libtommath from `03de03d` to `886126c` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `03de03d` to `886126c`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/03de03dee753442d4b23166982514639c4ccbc39...886126cb45bac67da77f4238bef6ffb843e9e26f) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 03de03de..886126cb 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 03de03dee753442d4b23166982514639c4ccbc39 +Subproject commit 886126cb45bac67da77f4238bef6ffb843e9e26f From 3f5db59ff12b0e114fdf2b6003956165c6cf70cb Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 2 Apr 2023 21:53:45 +0200 Subject: [PATCH 04/51] [Utils]: Small cleanup (#893) --- src/Utils/InfoString.cpp | 22 ++++++++++++---------- src/Utils/InfoString.hpp | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Utils/InfoString.cpp b/src/Utils/InfoString.cpp index 523d7c0e..0dbd6429 100644 --- a/src/Utils/InfoString.cpp +++ b/src/Utils/InfoString.cpp @@ -10,17 +10,17 @@ namespace Utils void InfoString::set(const std::string& key, const std::string& value) { - this->keyValuePairs[key] = value; + this->keyValuePairs_[key] = value; } void InfoString::remove(const std::string& key) { - this->keyValuePairs.erase(key); + this->keyValuePairs_.erase(key); } std::string InfoString::get(const std::string& key) const { - if (const auto value = this->keyValuePairs.find(key); value != this->keyValuePairs.end()) + if (const auto value = this->keyValuePairs_.find(key); value != this->keyValuePairs_.end()) { return value->second; } @@ -35,13 +35,16 @@ namespace Utils buffer = buffer.substr(1); } - const auto keyValues = Utils::String::Split(buffer, '\\'); - + const auto keyValues = String::Split(buffer, '\\'); for (std::size_t i = 0; !keyValues.empty() && i < (keyValues.size() - 1); i += 2) { const auto& key = keyValues[i]; const auto& value = keyValues[i + 1]; - this->keyValuePairs[key] = value; + + if (!this->keyValuePairs_.contains(key)) + { + this->keyValuePairs_[key] = value; + } } } @@ -50,8 +53,7 @@ namespace Utils std::string infoString; auto first = true; - - for (const auto& [key, value] : this->keyValuePairs) + for (const auto& [key, value] : this->keyValuePairs_) { if (first) first = false; else infoString.append("\\"); @@ -67,7 +69,7 @@ namespace Utils #ifdef _DEBUG void InfoString::dump() { - for (const auto& [key, value] : this->keyValuePairs) + for (const auto& [key, value] : this->keyValuePairs_) { OutputDebugStringA(String::VA("%s: %s\n", key.data(), value.data())); } @@ -76,6 +78,6 @@ namespace Utils nlohmann::json InfoString::to_json() const { - return this->keyValuePairs; + return this->keyValuePairs_; } } diff --git a/src/Utils/InfoString.hpp b/src/Utils/InfoString.hpp index 3229eebb..ff0243ba 100644 --- a/src/Utils/InfoString.hpp +++ b/src/Utils/InfoString.hpp @@ -21,7 +21,8 @@ namespace Utils [[nodiscard]] nlohmann::json to_json() const; private: - std::unordered_map keyValuePairs; + std::unordered_map keyValuePairs_; + void parse(std::string buffer); }; } From daf6da1cfa0c92d8cb538f7acb01e9a92d9e7bec Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 3 Apr 2023 13:13:42 +0200 Subject: [PATCH 05/51] [Logger]: Make use of Scr_LogString & ScrCmd_LogString_Stub (#895) --- src/Components/Modules/Logger.cpp | 60 ++++++++++++++++++++++--------- src/Components/Modules/Logger.hpp | 7 ++++ src/Game/Dvars.cpp | 1 + src/Game/Dvars.hpp | 1 + src/STDInclude.hpp | 1 + 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index e5798d5b..3ac40ab2 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -3,10 +3,16 @@ namespace Components { + using namespace Utils::String; + std::mutex Logger::MessageMutex; std::vector Logger::MessageQueue; + + std::mutex Logger::LoggingMutex; std::vector Logger::LoggingAddresses[2]; + Dvar::Var Logger::IW4x_oneLog; + void(*Logger::PipeCallback)(const std::string&) = nullptr;; bool Logger::IsConsoleReady() @@ -23,7 +29,7 @@ namespace Components vsnprintf_s(buf, _TRUNCATE, message, va); va_end(va); - MessagePrint(channel, {buf}); + MessagePrint(channel, std::string{ buf }); } void Logger::MessagePrint(const int channel, const std::string& msg) @@ -145,6 +151,7 @@ namespace Components return; } + std::unique_lock lock(LoggingMutex); for (const auto& addr : LoggingAddresses[gLog & 1]) { Network::SendCommand(addr, "print", data); @@ -216,13 +223,13 @@ namespace Components void Logger::RedirectOSPath(const char* file, char* folder) { - if (Dvar::Var("g_log").get() == file) + if (std::strcmp((*Game::g_log)->current.string, file) == 0) { - if (folder != "userraw"s) + if (std::strcmp(folder, "userraw") != 0) { - if (Dvar::Var("iw4x_onelog").get()) + if (IW4x_oneLog.get()) { - strcpy_s(folder, 256, "userraw"); + strncpy_s(folder, 256, "userraw", _TRUNCATE); } } } @@ -234,11 +241,9 @@ namespace Components { pushad - push [esp + 28h] - push [esp + 30h] - + push [esp + 20h + 8h] + push [esp + 20h + 10h] call RedirectOSPath - add esp, 8h popad @@ -253,14 +258,25 @@ namespace Components } } + void Logger::LSP_LogString_Stub([[maybe_unused]] int localControllerIndex, const char* string) + { + NetworkLog(string, false); + } + + void Logger::LSP_LogStringAboutUser_Stub([[maybe_unused]] int localControllerIndex, std::uint64_t xuid, const char* string) + { + NetworkLog(VA("%" PRIx64 ";%s", xuid, string), false); + } + void Logger::AddServerCommands() { Command::AddSV("log_add", [](Command::Params* params) { if (params->size() < 2) return; - Network::Address addr(params->get(1)); + std::unique_lock lock(LoggingMutex); + Network::Address addr(params->get(1)); if (std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr) == LoggingAddresses[0].end()) { LoggingAddresses[0].push_back(addr); @@ -271,8 +287,10 @@ namespace Components { if (params->size() < 2) return; + std::unique_lock lock(LoggingMutex); + 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()) + if (!std::strcmp(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()); @@ -300,6 +318,8 @@ namespace Components Print("# ID: Address\n"); Print("-------------\n"); + std::unique_lock lock(LoggingMutex); + for (unsigned int i = 0; i < LoggingAddresses[0].size(); ++i) { Print("#{:03d}: {}\n", i, LoggingAddresses[0][i].getString()); @@ -310,8 +330,9 @@ namespace Components { if (params->size() < 2) return; - const Network::Address addr(params->get(1)); + std::unique_lock lock(LoggingMutex); + const Network::Address addr(params->get(1)); if (std::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr) == LoggingAddresses[1].end()) { LoggingAddresses[1].push_back(addr); @@ -322,8 +343,10 @@ namespace Components { if (params->size() < 2) return; + std::unique_lock lock(LoggingMutex); + const auto num = std::atoi(params->get(1)); - if (!std::strcmp(Utils::String::VA("%i", num), params->get(1)) && static_cast(num) < LoggingAddresses[1].size()) + if (!std::strcmp(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()); @@ -332,7 +355,6 @@ namespace Components else { const Network::Address addr(params->get(1)); - const auto i = std::ranges::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr); if (i != LoggingAddresses[1].end()) { @@ -351,6 +373,7 @@ namespace Components Print("# ID: Address\n"); Print("-------------\n"); + std::unique_lock lock(LoggingMutex); for (std::size_t i = 0; i < LoggingAddresses[1].size(); ++i) { Print("#{:03d}: {}\n", i, LoggingAddresses[1][i].getString()); @@ -360,7 +383,7 @@ 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"); + IW4x_oneLog = Dvar::Register("iw4x_onelog", false, Game::DVAR_LATCH, "Only write the game log to the 'userraw' OS folder"); Utils::Hook(0x642139, BuildOSPath_Stub, HOOK_JUMP).install()->quick(); Scheduler::Loop(Frame, Scheduler::Pipeline::SERVER); @@ -368,6 +391,9 @@ namespace Components Utils::Hook(Game::G_LogPrintf, G_LogPrintf_Hk, HOOK_JUMP).install()->quick(); Utils::Hook(Game::Com_PrintMessage, PrintMessage_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5F67AE, LSP_LogString_Stub, HOOK_CALL).install()->quick(); // Scr_LogString + Utils::Hook(0x5F67EE, LSP_LogStringAboutUser_Stub, HOOK_CALL).install()->quick(); // ScrCmd_LogString_Stub + if (Loader::IsPerformingUnitTests()) { Utils::Hook(Game::Com_Printf, Print_Stub, HOOK_JUMP).install()->quick(); @@ -378,12 +404,12 @@ namespace Components Logger::~Logger() { + std::unique_lock lock_logging(LoggingMutex); LoggingAddresses[0].clear(); LoggingAddresses[1].clear(); - std::unique_lock lock(MessageMutex); + std::unique_lock lock_message(MessageMutex); MessageQueue.clear(); - lock.unlock(); // Flush the console log if (*Game::logfile) diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 8bc8f454..00d174f7 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -110,8 +110,12 @@ namespace Components private: static std::mutex MessageMutex; static std::vector MessageQueue; + + static std::mutex LoggingMutex; static std::vector LoggingAddresses[2]; + static Dvar::Var IW4x_oneLog; + static void(*PipeCallback)(const std::string&); static void MessagePrint(int channel, const std::string& msg); @@ -128,6 +132,9 @@ namespace Components static void NetworkLog(const char* data, bool gLog); + static void LSP_LogString_Stub(int localControllerIndex, const char* string); + static void LSP_LogStringAboutUser_Stub(int localControllerIndex, std::uint64_t xuid, const char* string); + static void AddServerCommands(); }; } diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp index 2a5b18a8..44eb19b0 100644 --- a/src/Game/Dvars.cpp +++ b/src/Game/Dvars.cpp @@ -71,6 +71,7 @@ namespace Game 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** g_log = reinterpret_cast(0x1A45D9C); const dvar_t** cg_chatHeight = reinterpret_cast(0x7ED398); const dvar_t** cg_chatTime = reinterpret_cast(0x9F5DE8); diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp index 906b83e6..58d0f77a 100644 --- a/src/Game/Dvars.hpp +++ b/src/Game/Dvars.hpp @@ -123,6 +123,7 @@ namespace Game extern const dvar_t** g_oldVoting; extern const dvar_t** g_gametype; extern const dvar_t** g_password; + extern const dvar_t** g_log; extern const dvar_t** cg_chatHeight; extern const dvar_t** cg_chatTime; diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 4009d601..aa045a9f 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include From bacaec491fbca2b6ee9be2a79ce8c39bf1d9e685 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 3 Apr 2023 13:49:37 +0200 Subject: [PATCH 06/51] [Logging]: Fix (#896) --- src/Components/Modules/Logger.cpp | 6 ++++-- src/Components/Modules/Logger.hpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 3ac40ab2..69864abc 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -8,7 +8,7 @@ namespace Components std::mutex Logger::MessageMutex; std::vector Logger::MessageQueue; - std::mutex Logger::LoggingMutex; + std::recursive_mutex Logger::LoggingMutex; std::vector Logger::LoggingAddresses[2]; Dvar::Var Logger::IW4x_oneLog; @@ -223,7 +223,9 @@ namespace Components void Logger::RedirectOSPath(const char* file, char* folder) { - if (std::strcmp((*Game::g_log)->current.string, file) == 0) + const auto* g_log = (*Game::g_log) ? (*Game::g_log)->current.string : ""; + + if (std::strcmp(g_log, file) == 0) { if (std::strcmp(folder, "userraw") != 0) { diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 00d174f7..2ada2a40 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -111,7 +111,7 @@ namespace Components static std::mutex MessageMutex; static std::vector MessageQueue; - static std::mutex LoggingMutex; + static std::recursive_mutex LoggingMutex; static std::vector LoggingAddresses[2]; static Dvar::Var IW4x_oneLog; From 2fc7836cd1574be0bd1b1c84b66fc28b513e6b56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:58:37 +0000 Subject: [PATCH 07/51] Bump deps/libtommath from `886126c` to `53fdf5f` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `886126c` to `53fdf5f`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/886126cb45bac67da77f4238bef6ffb843e9e26f...53fdf5f9c73cb4fde599dd07e54bac8264f7b236) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 886126cb..53fdf5f9 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 886126cb45bac67da77f4238bef6ffb843e9e26f +Subproject commit 53fdf5f9c73cb4fde599dd07e54bac8264f7b236 From 8693252da4c61fd11f078c52d3a2cdb3665b0d47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:58:43 +0000 Subject: [PATCH 08/51] Bump deps/libtomcrypt from `05f9407` to `fae62af` Bumps [deps/libtomcrypt](https://github.com/libtom/libtomcrypt) from `05f9407` to `fae62af`. - [Release notes](https://github.com/libtom/libtomcrypt/releases) - [Commits](https://github.com/libtom/libtomcrypt/compare/05f94077cc0aa42f550e85d2785a92b668117ada...fae62af0ab16f469c2512ec04575dd60ca018657) --- updated-dependencies: - dependency-name: deps/libtomcrypt dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtomcrypt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtomcrypt b/deps/libtomcrypt index 05f94077..fae62af0 160000 --- a/deps/libtomcrypt +++ b/deps/libtomcrypt @@ -1 +1 @@ -Subproject commit 05f94077cc0aa42f550e85d2785a92b668117ada +Subproject commit fae62af0ab16f469c2512ec04575dd60ca018657 From d214cb0e58ddd19fedceffd95da877d03dcca4c2 Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 4 Apr 2023 12:49:34 +0200 Subject: [PATCH 09/51] [Maps]: Undo shipment hack in preparation of rawfiles fix (#900) --- src/Components/Modules/Maps.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 04c761ef..be59087f 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -321,12 +321,6 @@ namespace Components format = "maps/%s.d3dbsp"; } - // Redirect shipment to shipment long - if (mapname == "mp_shipment"s) - { - mapname = "mp_shipment_long"; - } - _snprintf_s(buffer, size, _TRUNCATE, format, mapname); } From 05b02b3428ca7e2ea34d652c1097db4a9e7163a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:58:05 +0000 Subject: [PATCH 10/51] Bump deps/iw4-open-formats from `cf45b46` to `5be0ced` Bumps [deps/iw4-open-formats](https://github.com/XLabsProject/iw4-open-formats) from `cf45b46` to `5be0ced`. - [Release notes](https://github.com/XLabsProject/iw4-open-formats/releases) - [Commits](https://github.com/XLabsProject/iw4-open-formats/compare/cf45b460fe32a8c858b30445df779e29821cfdee...5be0cedd5ac10a006a496ffb47ad99e12f1ceec5) --- updated-dependencies: - dependency-name: deps/iw4-open-formats dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/iw4-open-formats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats index cf45b460..5be0cedd 160000 --- a/deps/iw4-open-formats +++ b/deps/iw4-open-formats @@ -1 +1 @@ -Subproject commit cf45b460fe32a8c858b30445df779e29821cfdee +Subproject commit 5be0cedd5ac10a006a496ffb47ad99e12f1ceec5 From 86ea44cdc99909c3a2c8c95d0643cd4897f510d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 17:57:52 +0000 Subject: [PATCH 11/51] Bump deps/libtommath from `53fdf5f` to `37bd262` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `53fdf5f` to `37bd262`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/53fdf5f9c73cb4fde599dd07e54bac8264f7b236...37bd262cc22aeffaac5b9528ade3bf07fe8ea424) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 53fdf5f9..37bd262c 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 53fdf5f9c73cb4fde599dd07e54bac8264f7b236 +Subproject commit 37bd262cc22aeffaac5b9528ade3bf07fe8ea424 From dd0ddda091facfa546b4305d6079b71acd3740b7 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Thu, 6 Apr 2023 09:27:20 +0200 Subject: [PATCH 12/51] [General]: Cleanup --- .../Modules/GSC/ScriptExtension.cpp | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/src/Components/Modules/GSC/ScriptExtension.cpp b/src/Components/Modules/GSC/ScriptExtension.cpp index 2d8919ed..9ce1c5c2 100644 --- a/src/Components/Modules/GSC/ScriptExtension.cpp +++ b/src/Components/Modules/GSC/ScriptExtension.cpp @@ -273,51 +273,6 @@ namespace Components::GSC void ScriptExtension::AddMethods() { - // ScriptExtension methods - Script::AddMethod("GetIp", [](const Game::scr_entref_t entref) // gsc: self GetIp() - { - const auto* ent = Script::Scr_GetPlayerEntity(entref); - const auto* client = Script::GetClient(ent); - - std::string ip = Game::NET_AdrToString(client->header.netchan.remoteAddress); - - const auto extractIPAddress = [](const std::string& input) -> std::string - { - const auto colonPos = input.find(':'); - if (colonPos == std::string::npos) - { - return input; - } - - auto ipAddress = input.substr(0, colonPos); - return ipAddress; - }; - - ip = extractIPAddress(ip); - - Game::Scr_AddString(ip.data()); - }); - - Script::AddMethod("GetPing", [](const Game::scr_entref_t entref) // gsc: self GetPing() - { - const auto* ent = Script::Scr_GetPlayerEntity(entref); - const auto* client = Script::GetClient(ent); - - Game::Scr_AddInt(client->ping); - }); - - Script::AddMethod("SetPing", [](const Game::scr_entref_t entref) // gsc: self SetPing() - { - auto ping = Game::Scr_GetInt(0); - - ping = std::clamp(ping, 0, 999); - - const auto* ent = Script::Scr_GetPlayerEntity(entref); - auto* client = Script::GetClient(ent); - - client->ping = ping; - }); - // PlayerCmd_AreControlsFrozen GSC function from Black Ops 2 Script::AddMethod("AreControlsFrozen", [](Game::scr_entref_t entref) // Usage: self AreControlsFrozen(); { From bc000fd9bee23aad4615043398dd9549755c3c88 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 6 Apr 2023 14:27:51 +0200 Subject: [PATCH 13/51] [General]: use std::format more often (#904) --- src/Components/Modules/Chat.cpp | 2 ++ src/Components/Modules/Download.cpp | 2 +- src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/ServerInfo.cpp | 8 ++++---- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 0e4e4537..b7fbd4e2 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -79,6 +79,8 @@ namespace Components return text; } + Logger::Print("{}: {}\n", Game::svs_clients[player - Game::g_entities].name, (text + msgIndex)); + for (const auto& callback : SayCallbacks) { if (!ChatCallback(player, callback.getPos(), (text + msgIndex), mode)) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index de1360a9..41cc285c 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -453,7 +453,7 @@ namespace Components // Insert default values playerInfo["score"] = 0; playerInfo["ping"] = 0; - playerInfo["name"] = ""; + playerInfo["name"] = "Unknown Soldier"; playerInfo["test_client"] = 0; if (Dedicated::IsRunning()) diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index b77a70c3..58c03510 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -434,7 +434,7 @@ namespace Components info.set("wwwDownload", (Download::SV_wwwDownload.get() ? "1" : "0")); info.set("wwwUrl", Download::SV_wwwBaseUrl.get()); - Network::SendCommand(address, "infoResponse", "\\" + info.build()); + Network::SendCommand(address, "infoResponse", info.build()); }); Network::OnClientPacket("infoResponse", [](const Network::Address& address, [[maybe_unused]] const std::string& data) diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 7dd1ede3..d7058bcd 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -238,10 +238,10 @@ namespace Components name = namePtr; } - playerList.append(Utils::String::VA("%i %i \"%s\"\n", score, ping, name.data())); + playerList.append(std::format("{} {} \"{}\"\n", score, ping, name)); } - Network::SendCommand(address, "statusResponse", "\\" + info.build() + "\n" + playerList + "\n"); + Network::SendCommand(address, "statusResponse", info.build() + "\n"s + playerList + "\n"s); }); Network::OnClientPacket("statusResponse", [](const Network::Address& address, [[maybe_unused]] const std::string& data) @@ -302,13 +302,13 @@ namespace Components if (currentData.size() < 3) continue; // Insert score - player.score = atoi(currentData.substr(0, currentData.find_first_of(' ')).data()); + player.score = std::strtol(currentData.substr(0, currentData.find_first_of(' ')).data(), nullptr, 10); // Remove score currentData = currentData.substr(currentData.find_first_of(' ') + 1); // Insert ping - player.ping = atoi(currentData.substr(0, currentData.find_first_of(' ')).data()); + player.ping = std::strtol(currentData.substr(0, currentData.find_first_of(' ')).data(), nullptr, 10); // Remove ping currentData = currentData.substr(currentData.find_first_of(' ') + 1); From 4e9ec3f0af6765470182b5102b33849828df86a0 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 6 Apr 2023 17:28:57 +0200 Subject: [PATCH 14/51] [Server]: Enforce password verification for private clients (#905) --- src/Components/Modules/Auth.cpp | 6 +++--- src/Components/Modules/Auth.hpp | 2 +- src/Components/Modules/Security.cpp | 7 +++++-- src/Game/Dvars.cpp | 1 + src/Game/Dvars.hpp | 1 + 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index 3dc576ed..cf7bcfc9 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -66,7 +66,7 @@ namespace Components } } - void Auth::SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char *format, int len) + void Auth::SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char* format, int len) { // Ensure our certificate is loaded Steam::SteamUser()->GetSteamID(); @@ -185,8 +185,8 @@ namespace Components Utils::InfoString infostr(params[2]); // Read the required data - const auto& steamId = infostr.get("xuid"); - const auto& challenge = infostr.get("challenge"); + const auto steamId = infostr.get("xuid"); + const auto challenge = infostr.get("challenge"); if (steamId.empty() || challenge.empty()) { diff --git a/src/Components/Modules/Auth.hpp b/src/Components/Modules/Auth.hpp index 48e821f7..541bd925 100644 --- a/src/Components/Modules/Auth.hpp +++ b/src/Components/Modules/Auth.hpp @@ -45,7 +45,7 @@ namespace Components static Utils::Cryptography::ECC::Key GuidKey; static std::vector BannedUids; - static void SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char *format, int len); + static void SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char* format, int len); static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr); static void DirectConnectStub(); diff --git a/src/Components/Modules/Security.cpp b/src/Components/Modules/Security.cpp index a1854c30..e20a175c 100644 --- a/src/Components/Modules/Security.cpp +++ b/src/Components/Modules/Security.cpp @@ -128,8 +128,8 @@ namespace Components Utils::Hook(0x4A9F56, MsgReadBitsCompressCheckCL, HOOK_CALL).install()->quick(); // CL_ParseServerMessage Utils::Hook(0x407376, SVCanReplaceServerCommand, HOOK_CALL).install()->quick(); // SV_CanReplaceServerCommand - Utils::Hook::Set(0x412370, 0xC3); // SV_SteamAuthClient - Utils::Hook::Set(0x5A8C70, 0xC3); // CL_HandleRelayPacket + Utils::Hook::Set(0x412370, 0xC3); // SV_SteamAuthClient + Utils::Hook::Set(0x5A8C70, 0xC3); // CL_HandleRelayPacket Utils::Hook::Nop(0x41698E, 5); // Disable Svcmd_EntityList_f @@ -149,6 +149,9 @@ namespace Components // Fix packets causing buffer overflow Utils::Hook(0x6267E3, NET_DeferPacketToClientStub, HOOK_CALL).install()->quick(); + // The client can fake the info string + Utils::Hook::Set(0x460F6D, 0xEB); // SV_DirectConnect + // Prevent curl 7_19_4 from running // Call to DL_Init from Live_Init Utils::Hook::Nop(0x420937, 5); diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp index 44eb19b0..7731e674 100644 --- a/src/Game/Dvars.cpp +++ b/src/Game/Dvars.cpp @@ -49,6 +49,7 @@ namespace Game const dvar_t** fs_gameDirVar = reinterpret_cast(0x63D0CC0); const dvar_t** fs_homepath = reinterpret_cast(0x63D4FD8); + const dvar_t** sv_privatePassword = reinterpret_cast(0x62C7C14); const dvar_t** sv_hostname = reinterpret_cast(0x2098D98); const dvar_t** sv_gametype = reinterpret_cast(0x2098DD4); const dvar_t** sv_mapname = reinterpret_cast(0x2098DDC); diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp index 58d0f77a..0abf921d 100644 --- a/src/Game/Dvars.hpp +++ b/src/Game/Dvars.hpp @@ -101,6 +101,7 @@ namespace Game extern const dvar_t** fs_gameDirVar; extern const dvar_t** fs_homepath; + extern const dvar_t** sv_privatePassword; extern const dvar_t** sv_hostname; extern const dvar_t** sv_gametype; extern const dvar_t** sv_mapname; From 2b74bdbe104aaa3ed0eff5d4bc3ba8869a0740cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:12:16 +0000 Subject: [PATCH 15/51] Bump deps/libtommath from `37bd262` to `3f10a28` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `37bd262` to `3f10a28`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/37bd262cc22aeffaac5b9528ade3bf07fe8ea424...3f10a28885601256c8b5261be3b15c926c93393d) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 37bd262c..3f10a288 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 37bd262cc22aeffaac5b9528ade3bf07fe8ea424 +Subproject commit 3f10a28885601256c8b5261be3b15c926c93393d From 44ca51e11b15aa8d7714cb7964bb8be19e6d87d3 Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 6 Apr 2023 19:57:40 +0200 Subject: [PATCH 16/51] [Server]: Complete sv_privatePassword implementation (#908) --- src/Components/Modules/Auth.cpp | 196 ++++++++++++++++---------- src/Components/Modules/Auth.hpp | 4 + src/Components/Modules/ServerList.cpp | 8 +- 3 files changed, 131 insertions(+), 77 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index cf7bcfc9..f150b107 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -19,10 +19,12 @@ namespace Components 0xf7e33c4081337fa3, 0x6f5597f103cc50e9 }; + + bool Auth::HasAccessToReservedSlot; void Auth::Frame() { - if (Auth::TokenContainer.generating) + if (TokenContainer.generating) { static double mseconds = 0; static Utils::Time::Interval interval; @@ -31,38 +33,38 @@ namespace Components { interval.update(); - int diff = Game::Sys_Milliseconds() - Auth::TokenContainer.startTime; - double hashPMS = (Auth::TokenContainer.hashes * 1.0) / diff; - double requiredHashes = std::pow(2, Auth::TokenContainer.targetLevel + 1) - Auth::TokenContainer.hashes; + int diff = Game::Sys_Milliseconds() - TokenContainer.startTime; + double hashPMS = (TokenContainer.hashes * 1.0) / diff; + double requiredHashes = std::pow(2, TokenContainer.targetLevel + 1) - TokenContainer.hashes; mseconds = requiredHashes / hashPMS; if (mseconds < 0) mseconds = 0; } - Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", Utils::String::VA("Increasing security level from %d to %d (est. %s)", Auth::GetSecurityLevel(), Auth::TokenContainer.targetLevel, Utils::String::FormatTimeSpan(static_cast(mseconds)).data())); + Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", Utils::String::VA("Increasing security level from %d to %d (est. %s)",GetSecurityLevel(), TokenContainer.targetLevel, Utils::String::FormatTimeSpan(static_cast(mseconds)).data())); } - else if (Auth::TokenContainer.thread.joinable()) + else if (TokenContainer.thread.joinable()) { - Auth::TokenContainer.thread.join(); - Auth::TokenContainer.generating = false; + TokenContainer.thread.join(); + TokenContainer.generating = false; - Auth::StoreKey(); - Logger::Debug("Security level is {}", Auth::GetSecurityLevel()); + StoreKey(); + Logger::Debug("Security level is {}",GetSecurityLevel()); Command::Execute("closemenu security_increase_popmenu", false); - if (!Auth::TokenContainer.cancel) + if (!TokenContainer.cancel) { - if (Auth::TokenContainer.command.empty()) + if (TokenContainer.command.empty()) { - Game::ShowMessageBox(Utils::String::VA("Your new security level is %d", Auth::GetSecurityLevel()), "Success"); + Game::ShowMessageBox(Utils::String::VA("Your new security level is %d", GetSecurityLevel()), "Success"); } else { - Toast::Show("cardicon_locked", "Success", Utils::String::VA("Your new security level is %d", Auth::GetSecurityLevel()), 5000); - Command::Execute(Auth::TokenContainer.command, false); + Toast::Show("cardicon_locked", "Success", Utils::String::VA("Your new security level is %d", GetSecurityLevel()), 5000); + Command::Execute(TokenContainer.command, false); } } - Auth::TokenContainer.cancel = false; + TokenContainer.cancel = false; } } @@ -70,15 +72,15 @@ namespace Components { // Ensure our certificate is loaded Steam::SteamUser()->GetSteamID(); - if (!Auth::GuidKey.isValid()) + if (!GuidKey.isValid()) { Logger::Error(Game::ERR_SERVERDISCONNECT, "Connecting failed: Guid key is invalid!"); return; } - if (std::find(Auth::BannedUids.begin(), Auth::BannedUids.end(), Steam::SteamUser()->GetSteamID().bits) != Auth::BannedUids.end()) + if (std::find(BannedUids.begin(), BannedUids.end(), Steam::SteamUser()->GetSteamID().bits) != BannedUids.end()) { - Auth::GenerateKey(); + GenerateKey(); Logger::Error(Game::ERR_SERVERDISCONNECT, "Your online profile is invalid. A new key has been generated."); return; } @@ -121,9 +123,9 @@ namespace Components Game::SV_Cmd_EndTokenizedString(); Proto::Auth::Connect connectData; - connectData.set_token(Auth::GuidToken.toString()); - connectData.set_publickey(Auth::GuidKey.getPublicKey()); - connectData.set_signature(Utils::Cryptography::ECC::SignMessage(Auth::GuidKey, challenge)); + connectData.set_token(GuidToken.toString()); + connectData.set_publickey(GuidKey.getPublicKey()); + connectData.set_signature(Utils::Cryptography::ECC::SignMessage(GuidKey, challenge)); connectData.set_infostring(connectString); Network::SendCommand(sock, adr, "connect", connectData.SerializeAsString()); @@ -182,7 +184,7 @@ namespace Components } // Parse the infostring - Utils::InfoString infostr(params[2]); + Utils::InfoString infostr(params.get(2)); // Read the required data const auto steamId = infostr.get("xuid"); @@ -206,13 +208,13 @@ namespace Components return; } - if (std::find(Auth::BannedUids.begin(), Auth::BannedUids.end(), xuid) != Auth::BannedUids.end()) + if (std::find(BannedUids.begin(), BannedUids.end(), xuid) != BannedUids.end()) { Network::Send(address, "error\nYour online profile is invalid. Delete your players folder and restart ^2IW4x^7."); return; } - if (xuid != Auth::GetKeyHash(connectData.publickey())) + if (xuid != GetKeyHash(connectData.publickey())) { Network::Send(address, "error\nXUID doesn't match the certificate!"); return; @@ -230,7 +232,7 @@ namespace Components // Verify the security level auto ourLevel = Dvar::Var("sv_securityLevel").get(); - auto userLevel = Auth::GetZeroBits(connectData.token(), connectData.publickey()); + auto userLevel = GetZeroBits(connectData.token(), connectData.publickey()); if (userLevel < ourLevel) { @@ -252,7 +254,7 @@ namespace Components lea eax, [esp + 20h] push eax push esi - call Auth::ParseConnectData + call ParseConnectData pop esi pop eax popad @@ -262,6 +264,44 @@ namespace Components } } + char* Auth::Info_ValueForKeyStub(const char* s, const char* key) + { + auto* value = Game::Info_ValueForKey(s, key); + + HasAccessToReservedSlot = std::strcmp((*Game::sv_privatePassword)->current.string, value) == 0; + + return value; + } + + __declspec(naked) void Auth::DirectConnectPrivateClientStub() + { + __asm + { + push eax + + mov al, HasAccessToReservedSlot + test al, al + + pop eax + + je noAccess + + // Set the number of private clients to 0 if the client has the right password + xor eax, eax + jmp safeContinue + + noAccess: + mov eax, dword ptr [edx + 0x10] + + safeContinue: + // Game code skipped by hook + add esp, 0xC + + push 0x460FB3 + ret + } + } + unsigned __int64 Auth::GetKeyHash(const std::string& key) { std::string hash = Utils::Cryptography::SHA1::Compute(key); @@ -276,18 +316,18 @@ namespace Components unsigned __int64 Auth::GetKeyHash() { - Auth::LoadKey(); - return Auth::GetKeyHash(Auth::GuidKey.getPublicKey()); + LoadKey(); + return GetKeyHash(GuidKey.getPublicKey()); } void Auth::StoreKey() { - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled() && Auth::GuidKey.isValid()) + if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled() && GuidKey.isValid()) { Proto::Auth::Certificate cert; - cert.set_token(Auth::GuidToken.toString()); - cert.set_ctoken(Auth::ComputeToken.toString()); - cert.set_privatekey(Auth::GuidKey.serialize(PK_PRIVATE)); + cert.set_token(GuidToken.toString()); + cert.set_ctoken(ComputeToken.toString()); + cert.set_privatekey(GuidKey.serialize(PK_PRIVATE)); Utils::IO::WriteFile("players/guid.dat", cert.SerializeAsString()); } @@ -295,30 +335,30 @@ namespace Components void Auth::GenerateKey() { - Auth::GuidToken.clear(); - Auth::ComputeToken.clear(); - Auth::GuidKey = Utils::Cryptography::ECC::GenerateKey(512); - Auth::StoreKey(); + GuidToken.clear(); + ComputeToken.clear(); + GuidKey = Utils::Cryptography::ECC::GenerateKey(512); + StoreKey(); } void Auth::LoadKey(bool force) { if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; - if (!force && Auth::GuidKey.isValid()) return; + if (!force && GuidKey.isValid()) return; Proto::Auth::Certificate cert; if (cert.ParseFromString(::Utils::IO::ReadFile("players/guid.dat"))) { - Auth::GuidKey.deserialize(cert.privatekey()); - Auth::GuidToken = cert.token(); - Auth::ComputeToken = cert.ctoken(); + GuidKey.deserialize(cert.privatekey()); + GuidToken = cert.token(); + ComputeToken = cert.ctoken(); } else { - Auth::GuidKey.free(); + GuidKey.free(); } - if (!Auth::GuidKey.isValid()) + if (!GuidKey.isValid()) { Auth::GenerateKey(); } @@ -326,32 +366,32 @@ namespace Components uint32_t Auth::GetSecurityLevel() { - return Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.getPublicKey()); + return GetZeroBits(GuidToken, GuidKey.getPublicKey()); } void Auth::IncreaseSecurityLevel(uint32_t level, const std::string& command) { - if (Auth::GetSecurityLevel() >= level) return; + if (GetSecurityLevel() >= level) return; - if (!Auth::TokenContainer.generating) + if (!TokenContainer.generating) { - Auth::TokenContainer.cancel = false; - Auth::TokenContainer.targetLevel = level; - Auth::TokenContainer.command = command; + TokenContainer.cancel = false; + TokenContainer.targetLevel = level; + TokenContainer.command = command; // Open menu Command::Execute("openmenu security_increase_popmenu", true); // Start thread - Auth::TokenContainer.thread = std::thread([&level]() + TokenContainer.thread = std::thread([&level]() { - Auth::TokenContainer.generating = true; - Auth::TokenContainer.hashes = 0; - Auth::TokenContainer.startTime = Game::Sys_Milliseconds(); - Auth::IncrementToken(Auth::GuidToken, Auth::ComputeToken, Auth::GuidKey.getPublicKey(), Auth::TokenContainer.targetLevel, &Auth::TokenContainer.cancel, &Auth::TokenContainer.hashes); - Auth::TokenContainer.generating = false; + TokenContainer.generating = true; + TokenContainer.hashes = 0; + TokenContainer.startTime = Game::Sys_Milliseconds(); + IncrementToken(GuidToken, ComputeToken, GuidKey.getPublicKey(), TokenContainer.targetLevel, &TokenContainer.cancel, &TokenContainer.hashes); + TokenContainer.generating = false; - if (Auth::TokenContainer.cancel) + if (TokenContainer.cancel) { Logger::Print("Token incrementation thread terminated\n"); } @@ -399,7 +439,7 @@ namespace Components } // Check if we already have the desired security level - uint32_t lastLevel = Auth::GetZeroBits(token, publicKey); + uint32_t lastLevel = GetZeroBits(token, publicKey); uint32_t level = lastLevel; if (level >= zeroBits) return; @@ -407,7 +447,7 @@ namespace Components { ++computeToken; if (count) ++(*count); - level = Auth::GetZeroBits(computeToken, publicKey); + level = GetZeroBits(computeToken, publicKey); // Store level if higher than the last one if (level >= lastLevel) @@ -425,30 +465,36 @@ namespace Components Auth::Auth() { - Auth::TokenContainer.cancel = false; - Auth::TokenContainer.generating = false; + TokenContainer.cancel = false; + TokenContainer.generating = false; + + HasAccessToReservedSlot = false; Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", ""); // Load the key - Auth::LoadKey(true); + LoadKey(true); Steam::SteamUser()->GetSteamID(); - Scheduler::Loop(Auth::Frame, Scheduler::Pipeline::MAIN); + Scheduler::Loop(Frame, Scheduler::Pipeline::MAIN); // Register dvar Dvar::Register("sv_securityLevel", 23, 0, 512, Game::DVAR_SERVERINFO, "Security level for GUID certificates (POW)"); // Install registration hook - Utils::Hook(0x6265F9, Auth::DirectConnectStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x41D3E3, Auth::SendConnectDataStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x6265F9, DirectConnectStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x460EF5, Info_ValueForKeyStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x460FAD, DirectConnectPrivateClientStub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x460FAD + 5, 1); + + Utils::Hook(0x41D3E3, SendConnectDataStub, HOOK_CALL).install()->quick(); // SteamIDs can only contain 31 bits of actual 'id' data. // The other 33 bits are steam internal data like universe and so on. // Using only 31 bits for fingerprints is pretty insecure. // The function below verifies the integrity steam's part of the SteamID. // Patching that check allows us to use 64 bit for fingerprints. - Utils::Hook::Set(0x4D0D60, 0xC301B0); + Utils::Hook::Set(0x4D0D60, 0xC301B0); // Guid command Command::Add("guid", [] @@ -462,42 +508,42 @@ namespace Components { if (params->size() < 2) { - const auto level = Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.getPublicKey()); + const auto level = GetZeroBits(GuidToken, GuidKey.getPublicKey()); Logger::Print("Your current security level is {}\n", level); - Logger::Print("Your security token is: {}\n", Utils::String::DumpHex(Auth::GuidToken.toString(), "")); - Logger::Print("Your computation token is: {}\n", Utils::String::DumpHex(Auth::ComputeToken.toString(), "")); + Logger::Print("Your security token is: {}\n", Utils::String::DumpHex(GuidToken.toString(), "")); + Logger::Print("Your computation token is: {}\n", Utils::String::DumpHex(ComputeToken.toString(), "")); Toast::Show("cardicon_locked", "^5Security Level", Utils::String::VA("Your security level is %d", level), 3000); } else { const auto level = std::strtoul(params->get(1), nullptr, 10); - Auth::IncreaseSecurityLevel(level); + IncreaseSecurityLevel(level); } }); } UIScript::Add("security_increase_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - Auth::TokenContainer.cancel = true; + TokenContainer.cancel = true; Logger::Print("Token incrementation process canceled!\n"); }); } Auth::~Auth() { - Auth::StoreKey(); + StoreKey(); } void Auth::preDestroy() { - Auth::TokenContainer.cancel = true; - Auth::TokenContainer.generating = false; + TokenContainer.cancel = true; + TokenContainer.generating = false; // Terminate thread - if (Auth::TokenContainer.thread.joinable()) + if (TokenContainer.thread.joinable()) { - Auth::TokenContainer.thread.join(); + TokenContainer.thread.join(); } } diff --git a/src/Components/Modules/Auth.hpp b/src/Components/Modules/Auth.hpp index 541bd925..5ab438ce 100644 --- a/src/Components/Modules/Auth.hpp +++ b/src/Components/Modules/Auth.hpp @@ -44,10 +44,14 @@ namespace Components static Utils::Cryptography::Token ComputeToken; static Utils::Cryptography::ECC::Key GuidKey; static std::vector BannedUids; + + static bool HasAccessToReservedSlot; static void SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char* format, int len); static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr); static void DirectConnectStub(); + static char* Info_ValueForKeyStub(const char* s, const char* key); + static void DirectConnectPrivateClientStub(); static void Frame(); }; diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 2900c1ba..2c0697ea 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -936,7 +936,7 @@ namespace Components UIScript::Add("CreateListFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { auto* serverInfo = GetCurrentServer(); - if (info) + if (info && serverInfo && serverInfo->addr.isValid()) { StoreFavourite(serverInfo->addr.getString()); } @@ -944,7 +944,11 @@ namespace Components UIScript::Add("CreateFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - StoreFavourite(Dvar::Var("ui_favoriteAddress").get()); + const auto value = Dvar::Var("ui_favoriteAddress").get(); + if (!value.empty()) + { + StoreFavourite(value); + } }); UIScript::Add("CreateCurrentServerFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) From 64ed0ba7fba3ed5d68d6b2f6b599e03fc88f1f5c Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 7 Apr 2023 11:52:46 +0200 Subject: [PATCH 17/51] [General]: Use some static assert (#909) --- src/Components/Modules/Bots.cpp | 29 +++++++++++++++++++++-------- src/Components/Modules/Bots.hpp | 2 ++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 337f4708..5f4dae7d 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -278,10 +278,8 @@ namespace Components return; } - const auto entnum = cl->gentity->s.number; - // Keep test client functionality - if (!g_botai[entnum].active) + if (!g_botai[cl - Game::svs_clients].active) { Game::SV_BotUserMove(cl); return; @@ -292,10 +290,10 @@ namespace Components userCmd.serverTime = *Game::svs_time; - userCmd.buttons = g_botai[entnum].buttons; - userCmd.forwardmove = g_botai[entnum].forward; - userCmd.rightmove = g_botai[entnum].right; - userCmd.weapon = g_botai[entnum].weapon; + userCmd.buttons = g_botai[cl - Game::svs_clients].buttons; + userCmd.forwardmove = g_botai[cl - Game::svs_clients].forward; + userCmd.rightmove = g_botai[cl - Game::svs_clients].right; + userCmd.weapon = g_botai[cl - Game::svs_clients].weapon; userCmd.angles[0] = ANGLE2SHORT((cl->gentity->client->ps.viewangles[0] - cl->gentity->client->ps.delta_angles[0])); userCmd.angles[1] = ANGLE2SHORT((cl->gentity->client->ps.viewangles[1] - cl->gentity->client->ps.delta_angles[1])); @@ -349,10 +347,23 @@ namespace Components } } + int Bots::SV_GetClientPing_Hk(const int clientNum) + { + AssertIn(clientNum, Game::MAX_CLIENTS); + + if (Game::SV_IsTestClient(clientNum)) + { + return -1; + } + + return Game::svs_clients[clientNum].ping; + } + Bots::Bots() { AssertOffset(Game::client_t, bIsTestClient, 0x41AF0); AssertOffset(Game::client_t, ping, 0x212C8); + AssertOffset(Game::client_t, gentity, 0x212A0); // 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\\clanAbbrev\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\""); @@ -365,10 +376,12 @@ namespace Components Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).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) + Events::OnClientDisconnect([](const int clientNum) -> void { g_botai[clientNum].active = false; }); diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index b7423914..92a492b7 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -27,5 +27,7 @@ namespace Components static void G_SelectWeaponIndex(int clientNum, int iWeaponIndex); static void G_SelectWeaponIndex_Hk(); + + static int SV_GetClientPing_Hk(int clientNum); }; } From 2a55829d5ae61c647cd66c47d1e143e66aefba98 Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 7 Apr 2023 19:38:23 +0200 Subject: [PATCH 18/51] [IO]: Refactor GSC funcs (#910) --- src/Components/Modules/Bots.cpp | 3 + src/Components/Modules/GSC/IO.cpp | 126 ++++++++++++++++-------------- src/Components/Modules/GSC/IO.hpp | 2 + 3 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 5f4dae7d..a3962991 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -269,6 +269,9 @@ namespace Components g_botai[entref.entnum].right = static_cast(rightInt); g_botai[entref.entnum].active = true; }); + + GSC::Script::AddMethod("SetPing", []([[maybe_unused]] const Game::scr_entref_t entref) + {}); } void Bots::BotAiAction(Game::client_t* cl) diff --git a/src/Components/Modules/GSC/IO.cpp b/src/Components/Modules/GSC/IO.cpp index af5ac692..fd9176a2 100644 --- a/src/Components/Modules/GSC/IO.cpp +++ b/src/Components/Modules/GSC/IO.cpp @@ -10,19 +10,29 @@ namespace Components::GSC std::filesystem::path IO::Path; + bool IO::ValidatePath(const char* function, const char* path) + { + for (std::size_t i = 0; i < std::extent_v; ++i) + { + if (std::strstr(path, ForbiddenStrings[i]) != nullptr) + { + Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "{}: directory traversal is not allowed!\n", function); + return false; + } + } + + return true; + } + void IO::GScr_OpenFile() { const auto* filepath = Game::Scr_GetString(0); const auto* mode = Game::Scr_GetString(1); - for (std::size_t i = 0; i < std::extent_v; ++i) + if (!ValidatePath("OpenFile", filepath)) { - if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr) - { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "OpenFile: directory traversal is not allowed!\n"); - Game::Scr_AddInt(-1); - return; - } + Game::Scr_AddInt(-1); + return; } if (mode != "read"s) @@ -97,27 +107,11 @@ namespace Components::GSC const auto* text = Game::Scr_GetString(1); const auto* mode = Game::Scr_GetString(2); - if (!filepath) + if (!ValidatePath("FileWrite", filepath)) { - Game::Scr_ParamError(0, "FileWrite: filepath is not defined!"); return; } - if (!text || !mode) - { - Game::Scr_Error("FileWrite: Illegal parameters!"); - return; - } - - for (std::size_t i = 0; i < std::extent_v; ++i) - { - if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr) - { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileWrite: directory traversal is not allowed!\n"); - return; - } - } - if (mode != "append"s && mode != "write"s) { Logger::Warning(Game::CON_CHANNEL_PARSERSCRIPT, "FileWrite: mode not defined or was wrong, defaulting to 'write'\n"); @@ -132,21 +126,11 @@ namespace Components::GSC Script::AddFunction("FileRead", [] // gsc: FileRead() { const auto* filepath = Game::Scr_GetString(0); - if (!filepath) + if (!ValidatePath("FileRead", filepath)) { - Game::Scr_ParamError(0, "FileRead: filepath is not defined!"); return; } - for (std::size_t i = 0; i < std::extent_v; ++i) - { - if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr) - { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileRead: directory traversal is not allowed!\n"); - return; - } - } - const auto scriptData = Path / "scriptdata"s / filepath; std::string file; @@ -163,21 +147,11 @@ namespace Components::GSC Script::AddFunction("FileExists", [] // gsc: FileExists() { const auto* filepath = Game::Scr_GetString(0); - if (!filepath) + if (!ValidatePath("FileExists", filepath)) { - Game::Scr_ParamError(0, "FileExists: filepath is not defined!"); return; } - for (std::size_t i = 0; i < std::extent_v; ++i) - { - if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr) - { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileExists: directory traversal is not allowed!\n"); - return; - } - } - const auto scriptData = Path / "scriptdata"s / filepath; Game::Scr_AddBool(Utils::IO::FileExists(scriptData.string())); }); @@ -185,25 +159,63 @@ namespace Components::GSC Script::AddFunction("FileRemove", [] // gsc: FileRemove() { const auto* filepath = Game::Scr_GetString(0); - if (!filepath) + if (!ValidatePath("FileRemove", filepath)) { - Game::Scr_ParamError(0, "FileRemove: filepath is not defined!"); return; } - for (std::size_t i = 0; i < std::extent_v; ++i) - { - if (std::strstr(filepath, ForbiddenStrings[i]) != nullptr) - { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileRemove: directory traversal is not allowed!\n"); - return; - } - } - const auto scriptData = Path / "scriptdata"s / filepath; Game::Scr_AddBool(Utils::IO::RemoveFile(scriptData.string())); }); + Script::AddFunction("FileRename", [] // gsc: FileRename(, ) + { + const auto* filepath = Game::Scr_GetString(0); + const auto* destpath = Game::Scr_GetString(0); + if (!ValidatePath("FileRename", filepath) || !ValidatePath("FileRename", destpath)) + { + return; + } + + const auto from = Path / "scriptdata"s / filepath; + const auto to = Path / "scriptdata"s / destpath; + + std::error_code err; + std::filesystem::rename(from, to, err); + if (err.value()) + { + Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileRename: failed to rename file! Error message: {}\n", err.message()); + Game::Scr_AddInt(-1); + return; + } + + Game::Scr_AddInt(1); + }); + + Script::AddFunction("FileCopy", [] // gsc: FileCopy(, ) + { + const auto* filepath = Game::Scr_GetString(0); + const auto* destpath = Game::Scr_GetString(0); + if (!ValidatePath("FileCopy", filepath) || !ValidatePath("FileCopy", destpath)) + { + return; + } + + const auto from = Path / "scriptdata"s / filepath; + const auto to = Path / "scriptdata"s / destpath; + + std::error_code err; + std::filesystem::copy(from, to, err); + if (err.value()) + { + Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileCopy: failed to copy file! Error message: {}\n", err.message()); + Game::Scr_AddInt(-1); + return; + } + + Game::Scr_AddInt(1); + }); + Script::AddFunction("ReadStream", GScr_ReadStream); } diff --git a/src/Components/Modules/GSC/IO.hpp b/src/Components/Modules/GSC/IO.hpp index 11729c89..f77ddc65 100644 --- a/src/Components/Modules/GSC/IO.hpp +++ b/src/Components/Modules/GSC/IO.hpp @@ -14,6 +14,8 @@ namespace Components::GSC static std::filesystem::path Path; + static bool ValidatePath(const char* function, const char* path); + static void GScr_OpenFile(); static void GScr_ReadStream(); static void GScr_CloseFile(); From 9524a2e571fcc1c916749956034b372d0bb8d36f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 17:57:45 +0000 Subject: [PATCH 19/51] Bump deps/rapidjson from `012be85` to `949c771` Bumps [deps/rapidjson](https://github.com/Tencent/rapidjson) from `012be85` to `949c771`. - [Release notes](https://github.com/Tencent/rapidjson/releases) - [Commits](https://github.com/Tencent/rapidjson/compare/012be8528783cdbf4b7a9e64f78bd8f056b97e24...949c771b03de448bdedea80c44a4a5f65284bfeb) --- updated-dependencies: - dependency-name: deps/rapidjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/rapidjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/rapidjson b/deps/rapidjson index 012be852..949c771b 160000 --- a/deps/rapidjson +++ b/deps/rapidjson @@ -1 +1 @@ -Subproject commit 012be8528783cdbf4b7a9e64f78bd8f056b97e24 +Subproject commit 949c771b03de448bdedea80c44a4a5f65284bfeb From 6198c0bac5c643b415b43ffb8e3e68823a7805c8 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 8 Apr 2023 12:22:50 +0200 Subject: [PATCH 20/51] [IO]: Support fs_game mod folder (#913) --- src/Components/Modules/GSC/IO.cpp | 45 +++++++++++++++++++------------ src/Components/Modules/GSC/IO.hpp | 3 ++- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Components/Modules/GSC/IO.cpp b/src/Components/Modules/GSC/IO.cpp index fd9176a2..662bc079 100644 --- a/src/Components/Modules/GSC/IO.cpp +++ b/src/Components/Modules/GSC/IO.cpp @@ -8,7 +8,7 @@ namespace Components::GSC FILE* IO::openScriptIOFileHandle; - std::filesystem::path IO::Path; + std::filesystem::path IO::DefaultDestPath; bool IO::ValidatePath(const char* function, const char* path) { @@ -24,6 +24,17 @@ namespace Components::GSC return true; } + std::filesystem::path IO::BuildPath(const char* path) + { + const std::filesystem::path fsGame = (*Game::fs_gameDirVar)->current.string; + if (!fsGame.empty()) + { + return fsGame / "scriptdata"s / path; + } + + return DefaultDestPath / "scriptdata"s / path; + } + void IO::GScr_OpenFile() { const auto* filepath = Game::Scr_GetString(0); @@ -49,10 +60,10 @@ namespace Components::GSC return; } - const auto scriptData = Path / "scriptdata"s / filepath; + const auto dest = BuildPath(filepath); _set_errno(0); - const auto result = fopen_s(&openScriptIOFileHandle, scriptData.string().data(), "r"); + const auto result = fopen_s(&openScriptIOFileHandle, dest.string().data(), "r"); if (result || !openScriptIOFileHandle) { Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "OpenFile failed. '{}'", result); @@ -119,8 +130,8 @@ namespace Components::GSC } const auto append = mode == "append"s; - const auto scriptData = Path / "scriptdata"s / filepath; - Utils::IO::WriteFile(scriptData.string(), text, append); + const auto dest = BuildPath(filepath); + Utils::IO::WriteFile(dest.string(), text, append); }); Script::AddFunction("FileRead", [] // gsc: FileRead() @@ -131,12 +142,12 @@ namespace Components::GSC return; } - const auto scriptData = Path / "scriptdata"s / filepath; + const auto dest = BuildPath(filepath); std::string file; - if (!Utils::IO::ReadFile(scriptData.string(), &file)) + if (!Utils::IO::ReadFile(dest.string(), &file)) { - Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileRead: file '{}' not found!\n", scriptData.string()); + Logger::PrintError(Game::CON_CHANNEL_PARSERSCRIPT, "FileRead: file '{}' not found!\n", dest.string()); return; } @@ -152,8 +163,8 @@ namespace Components::GSC return; } - const auto scriptData = Path / "scriptdata"s / filepath; - Game::Scr_AddBool(Utils::IO::FileExists(scriptData.string())); + const auto dest = BuildPath(filepath); + Game::Scr_AddBool(Utils::IO::FileExists(dest.string())); }); Script::AddFunction("FileRemove", [] // gsc: FileRemove() @@ -164,8 +175,8 @@ namespace Components::GSC return; } - const auto scriptData = Path / "scriptdata"s / filepath; - Game::Scr_AddBool(Utils::IO::RemoveFile(scriptData.string())); + const auto dest = BuildPath(filepath); + Game::Scr_AddBool(Utils::IO::RemoveFile(dest.string())); }); Script::AddFunction("FileRename", [] // gsc: FileRename(, ) @@ -177,8 +188,8 @@ namespace Components::GSC return; } - const auto from = Path / "scriptdata"s / filepath; - const auto to = Path / "scriptdata"s / destpath; + const auto from = BuildPath(filepath); + const auto to = BuildPath(destpath); std::error_code err; std::filesystem::rename(from, to, err); @@ -201,8 +212,8 @@ namespace Components::GSC return; } - const auto from = Path / "scriptdata"s / filepath; - const auto to = Path / "scriptdata"s / destpath; + const auto from = BuildPath(filepath); + const auto to = BuildPath(destpath); std::error_code err; std::filesystem::copy(from, to, err); @@ -222,7 +233,7 @@ namespace Components::GSC IO::IO() { openScriptIOFileHandle = nullptr; - Path = "userraw"s; + DefaultDestPath = "userraw"s; AddScriptFunctions(); diff --git a/src/Components/Modules/GSC/IO.hpp b/src/Components/Modules/GSC/IO.hpp index f77ddc65..45a9a0b8 100644 --- a/src/Components/Modules/GSC/IO.hpp +++ b/src/Components/Modules/GSC/IO.hpp @@ -12,9 +12,10 @@ namespace Components::GSC static FILE* openScriptIOFileHandle; - static std::filesystem::path Path; + static std::filesystem::path DefaultDestPath; static bool ValidatePath(const char* function, const char* path); + static std::filesystem::path BuildPath(const char* path); static void GScr_OpenFile(); static void GScr_ReadStream(); From b6082da91ab09176feefab4995f0206ee0337636 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 8 Apr 2023 15:39:32 +0200 Subject: [PATCH 21/51] [FS]: Imrove spead of patch (#914) --- src/Components/Modules/FileSystem.cpp | 14 +++++++++++--- src/Components/Modules/FileSystem.hpp | 2 +- src/Components/Modules/GSC/ScriptError.cpp | 6 +++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Components/Modules/FileSystem.cpp b/src/Components/Modules/FileSystem.cpp index 9762fce4..02b27006 100644 --- a/src/Components/Modules/FileSystem.cpp +++ b/src/Components/Modules/FileSystem.cpp @@ -278,9 +278,17 @@ namespace Components } } - int FileSystem::ExecIsFSStub(const char* execFilename) + int FileSystem::Cmd_Exec_f_Stub(const char* s0, [[maybe_unused]] const char* s1) { - return !File(execFilename).exists(); + int f; + auto len = Game::FS_FOpenFileByMode(s0, &f, Game::FS_READ); + if (len < 0) + { + return 1; // Not found + } + + Game::FS_FCloseFile(f); + return 0; // Found } void FileSystem::FsStartupSync(const char* a1) @@ -335,7 +343,7 @@ namespace Components Utils::Hook(Game::FS_FreeFile, FreeFile, HOOK_JUMP).install()->quick(); // Filesystem config checks - Utils::Hook(0x6098FD, ExecIsFSStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x6098FD, Cmd_Exec_f_Stub, HOOK_CALL).install()->quick(); // Don't strip the folders from the config name (otherwise our ExecIsFSStub fails) Utils::Hook::Nop(0x6098F2, 5); diff --git a/src/Components/Modules/FileSystem.hpp b/src/Components/Modules/FileSystem.hpp index 3a403027..cb721369 100644 --- a/src/Components/Modules/FileSystem.hpp +++ b/src/Components/Modules/FileSystem.hpp @@ -112,7 +112,7 @@ namespace Components static void RegisterFolders(); static void StartupStub(); - static int ExecIsFSStub(const char* execFilename); + static int Cmd_Exec_f_Stub(const char* s0, const char* s1); static void FsStartupSync(const char* a1); static void FsRestartSync(int localClientNum, int checksumFeed); diff --git a/src/Components/Modules/GSC/ScriptError.cpp b/src/Components/Modules/GSC/ScriptError.cpp index 8b4def7b..3a197a5a 100644 --- a/src/Components/Modules/GSC/ScriptError.cpp +++ b/src/Components/Modules/GSC/ScriptError.cpp @@ -754,7 +754,7 @@ namespace Components::GSC assert(scrParserGlob.saveSourceBufferLookupLen > 0); --scrParserGlob.saveSourceBufferLookupLen; - auto* saveSourceBuffer = scrParserGlob.saveSourceBufferLookup + scrParserGlob.saveSourceBufferLookupLen; + const auto* saveSourceBuffer = scrParserGlob.saveSourceBufferLookup + scrParserGlob.saveSourceBufferLookupLen; const auto len = saveSourceBuffer->len; assert(len >= -1); @@ -799,7 +799,7 @@ namespace Components::GSC if (Game::FindVariable(Game::scrCompilePub->loadedscripts, name)) { Game::SL_RemoveRefToString(name); - auto filePosPtr = Game::FindVariable(Game::scrCompilePub->scriptsPos, name); + const auto filePosPtr = Game::FindVariable(Game::scrCompilePub->scriptsPos, name); return filePosPtr ? Game::FindObject(Game::scrCompilePub->scriptsPos, filePosPtr) : 0; } @@ -809,7 +809,7 @@ namespace Components::GSC sprintf_s(extFilename, "%s.gsc", Game::SL_ConvertToString(static_cast(name))); const auto* oldSourceBuf = scrParserPub.sourceBuf; - auto* sourceBuffer = Scr_AddSourceBuffer(Game::SL_ConvertToString(static_cast(name)), extFilename, Game::TempMalloc(0), true); + const auto* sourceBuffer = Scr_AddSourceBuffer(Game::SL_ConvertToString(static_cast(name)), extFilename, Game::TempMalloc(0), true); if (!sourceBuffer) { From fbe7b1cf10fb8d769149259b269382451263f025 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 9 Apr 2023 15:19:04 +0200 Subject: [PATCH 22/51] [Command]: Return if empty --- src/Components/Modules/Command.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Components/Modules/Command.cpp b/src/Components/Modules/Command.cpp index 0aa4430c..b203f7d2 100644 --- a/src/Components/Modules/Command.cpp +++ b/src/Components/Modules/Command.cpp @@ -116,6 +116,11 @@ namespace Components void Command::Execute(std::string command, bool sync) { + if (command.empty()) + { + return; + } + command.append("\n"); // Make sure it's terminated assert(command.size() < Game::MAX_CMD_LINE); From 9b1f49252ee42f43084e53150aae0bae44c315a6 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 9 Apr 2023 18:26:25 +0200 Subject: [PATCH 23/51] [MapRotation]: Refactor (#916) --- src/Components/Modules/Command.cpp | 2 +- src/Components/Modules/MapRotation.cpp | 71 ++++++++++++++++++-------- src/Components/Modules/MapRotation.hpp | 32 +++++++++++- src/Components/Modules/Maps.cpp | 8 ++- src/Components/Modules/Network.cpp | 4 +- src/Components/Modules/Network.hpp | 6 +-- src/Components/Modules/Session.cpp | 4 +- src/Components/Modules/Session.hpp | 4 +- 8 files changed, 96 insertions(+), 35 deletions(-) diff --git a/src/Components/Modules/Command.cpp b/src/Components/Modules/Command.cpp index b203f7d2..c4a0e4ff 100644 --- a/src/Components/Modules/Command.cpp +++ b/src/Components/Modules/Command.cpp @@ -121,7 +121,7 @@ namespace Components return; } - command.append("\n"); // Make sure it's terminated + command.push_back('\n'); // Make sure it's terminated assert(command.size() < Game::MAX_CMD_LINE); diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index 8ed6ad4a..de84131e 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -1,5 +1,6 @@ #include #include "MapRotation.hpp" +#include "Party.hpp" namespace Components { @@ -25,7 +26,7 @@ namespace Components void MapRotation::RotationData::addEntry(const std::string& key, const std::string& value) { - this->rotationEntries_.emplace_back(std::make_pair(key, value)); + this->rotationEntries_.emplace_back(key, value); } std::size_t MapRotation::RotationData::getEntriesSize() const noexcept @@ -36,7 +37,7 @@ namespace Components MapRotation::RotationData::rotationEntry& MapRotation::RotationData::getNextEntry() { const auto index = this->index_; - ++this->index_ %= this->rotationEntries_.size(); // Point index_ to the next entry + ++this->index_ %= this->rotationEntries_.size(); return this->rotationEntries_.at(index); } @@ -45,6 +46,19 @@ namespace Components return this->rotationEntries_.at(this->index_); } + void MapRotation::RotationData::setHandler(const std::string& key, const rotationCallback& callback) + { + this->rotationHandlers_[key] = callback; + } + + void MapRotation::RotationData::callHandler(const rotationEntry& entry) const + { + if (const auto itr = this->rotationHandlers_.find(entry.first); itr != this->rotationHandlers_.end()) + { + itr->second(entry.second); + } + } + void MapRotation::RotationData::parse(const std::string& data) { const auto tokens = Utils::String::Split(data, ' '); @@ -54,14 +68,12 @@ namespace Components const auto& key = tokens[i]; const auto& value = tokens[i + 1]; - if (key == "map"s || key == "gametype"s) + if (!this->containsHandler(key)) { - this->addEntry(key, value); - } - else - { - throw MapRotationParseError(); + throw MapRotationParseError(std::format("Invalid key {}", key)); } + + this->addEntry(key, value); } } @@ -78,6 +90,16 @@ namespace Components }); } + bool MapRotation::RotationData::containsHandler(const std::string& key) const + { + return this->rotationHandlers_.contains(key); + } + + void MapRotation::RotationData::clear() noexcept + { + this->rotationEntries_.clear(); + } + nlohmann::json MapRotation::RotationData::to_json() const { std::vector mapVector; @@ -97,8 +119,8 @@ namespace Components auto mapRotationJson = nlohmann::json { - {"maps", mapVector}, - {"gametypes", gametypeVector}, + { "maps", mapVector }, + { "gametypes", gametypeVector }, }; return mapRotationJson; @@ -183,7 +205,7 @@ namespace Components return false; } - if (Dvar::Var("party_enable").get() && Dvar::Var("party_host").get()) + if (Party::IsEnabled() && Dvar::Var("party_host").get()) { Logger::Warning(Game::CON_CHANNEL_SERVER, "Not performing map rotation as we are hosting a party!\n"); return false; @@ -212,6 +234,13 @@ namespace Components Game::Dvar_SetStringByName("g_gametype", gametype.data()); } + void MapRotation::ApplyExec(const std::string& name) + { + assert(!name.empty()); + Command::Execute(std::format("exec {}", name), false); + Command::Execute(std::format("exec game_settings/{}", name), false); + } + void MapRotation::RestartCurrentMap() { std::string svMapname = (*Game::sv_mapname)->current.string; @@ -234,21 +263,15 @@ namespace Components while (i < rotation.getEntriesSize()) { const auto& entry = rotation.getNextEntry(); + rotation.callHandler(entry); + Logger::Print("MapRotation: applying key '{}' with value '{}'\n", entry.first, entry.second); + if (entry.first == "map"s) { - Logger::Print("Loading new map: '{}'", entry.second); - ApplyMap(entry.second); - // Map was found so we exit the loop break; } - if (entry.first == "gametype"s) - { - Logger::Print("Applying new gametype: '{}'", entry.second); - ApplyGametype(entry.second); - } - ++i; } @@ -374,13 +397,15 @@ namespace Components AddMapRotationCommands(); Utils::Hook::Set(0x4152E8, SV_MapRotate_f); + DedicatedRotation.setHandler("map", ApplyMap); + DedicatedRotation.setHandler("gametype", ApplyGametype); + DedicatedRotation.setHandler("exec", ApplyExec); + Events::OnDvarInit(RegisterMapRotationDvars); } bool MapRotation::unitTest() { - RotationData rotation; - Logger::Debug("Testing map rotation parsing..."); const auto* normal = "map mp_highrise map mp_terminal map mp_firingrange map mp_trailerpark gametype dm map mp_shipment_long"; @@ -395,6 +420,8 @@ namespace Components return false; } + DedicatedRotation.clear(); + const auto* mistake = "spdevmap mp_dome"; auto success = false; diff --git a/src/Components/Modules/MapRotation.hpp b/src/Components/Modules/MapRotation.hpp index 68e51b23..3acbd4f3 100644 --- a/src/Components/Modules/MapRotation.hpp +++ b/src/Components/Modules/MapRotation.hpp @@ -14,9 +14,27 @@ namespace Components bool unitTest() override; private: - struct MapRotationParseError : public std::exception + class MapRotationParseError : public std::runtime_error { - [[nodiscard]] const char* what() const noexcept override { return "Map Rotation Parse Error"; } + private: + static std::string fmt(const std::string& message) + { + std::string error = "Map Rotation Parse Error"; + + if (!message.empty()) + { + error.append(": "); + error.append(message); + } + + return error; + } + + public: + MapRotationParseError(const std::string& message) + : std::runtime_error(fmt(message)) + { + } }; class RotationData @@ -24,6 +42,8 @@ namespace Components public: using rotationEntry = std::pair; + using rotationCallback = std::function; + RotationData(); void randomize(); @@ -36,15 +56,22 @@ namespace Components rotationEntry& getNextEntry(); rotationEntry& peekNextEntry(); + void setHandler(const std::string& key, const rotationCallback& callback); + void callHandler(const rotationEntry& entry) const; + void parse(const std::string& data); [[nodiscard]] bool empty() const noexcept; [[nodiscard]] bool contains(const std::string& key, const std::string& value) const; + [[nodiscard]] bool containsHandler(const std::string& key) const; + + void clear() noexcept; [[nodiscard]] nlohmann::json to_json() const; private: std::vector rotationEntries_; + std::unordered_map rotationHandlers_; std::size_t index_; }; @@ -67,6 +94,7 @@ namespace Components static bool ShouldRotate(); static void ApplyMap(const std::string& map); static void ApplyGametype(const std::string& gametype); + static void ApplyExec(const std::string& name); static void RestartCurrentMap(); static void ApplyRotation(RotationData& rotation); static void ApplyMapRotationCurrent(const std::string& data); diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index be59087f..da4a65f3 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -316,11 +316,17 @@ namespace Components void Maps::GetBSPName(char* buffer, size_t size, const char* format, const char* mapname) { - if (!Utils::String::StartsWith(mapname, "mp_") && !Utils::String::StartsWith(mapname, "zm_")) + if (!Utils::String::StartsWith(mapname, "mp_")) { format = "maps/%s.d3dbsp"; } + // TODO: Remove this hack by using CoD4 version of the map + if (std::strcmp(mapname, "mp_shipment") == 0) + { + mapname = "mp_shipment_long"; + } + _snprintf_s(buffer, size, _TRUNCATE, format, mapname); } diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 00c551a2..7ce68157 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -4,7 +4,7 @@ namespace Components { Utils::Signal Network::StartupSignal; // Packet interception - std::unordered_map Network::CL_Callbacks; + std::unordered_map Network::CL_Callbacks; Network::Address::Address() { @@ -283,7 +283,7 @@ namespace Components Utils::Hook::Call(0x414D40)(client, msg); } - void Network::OnClientPacket(const std::string& command, const NetworkCallback& callback) + void Network::OnClientPacket(const std::string& command, const networkCallback& callback) { CL_Callbacks[Utils::String::ToLower(command)] = callback; } diff --git a/src/Components/Modules/Network.hpp b/src/Components/Modules/Network.hpp index bd55a5cc..89e46bec 100644 --- a/src/Components/Modules/Network.hpp +++ b/src/Components/Modules/Network.hpp @@ -48,7 +48,7 @@ namespace Components typedef void(CallbackRaw)(); - using NetworkCallback = std::function; + using networkCallback = std::function; Network(); @@ -72,11 +72,11 @@ namespace Components static void BroadcastRange(unsigned int min, unsigned int max, const std::string& data); static void BroadcastAll(const std::string& data); - static void OnClientPacket(const std::string& command, const NetworkCallback& callback); + static void OnClientPacket(const std::string& command, const networkCallback& callback); private: static Utils::Signal StartupSignal; - static std::unordered_map CL_Callbacks; + static std::unordered_map CL_Callbacks; static void NetworkStart(); static void NetworkStartStub(); diff --git a/src/Components/Modules/Session.cpp b/src/Components/Modules/Session.cpp index 6058f334..77fbc22b 100644 --- a/src/Components/Modules/Session.cpp +++ b/src/Components/Modules/Session.cpp @@ -14,7 +14,7 @@ namespace Components Utils::Cryptography::ECC::Key Session::SignatureKey; - std::unordered_map Session::PacketHandlers; + std::unordered_map Session::PacketHandlers; std::queue> Session::SignatureQueue; @@ -61,7 +61,7 @@ namespace Components #endif } - void Session::Handle(const std::string& packet, const Network::NetworkCallback& callback) + void Session::Handle(const std::string& packet, const Network::networkCallback& callback) { #ifdef DISABLE_SESSION Network::OnClientPacket(packet, callback); diff --git a/src/Components/Modules/Session.hpp b/src/Components/Modules/Session.hpp index 181d9ce6..5a2cfbca 100644 --- a/src/Components/Modules/Session.hpp +++ b/src/Components/Modules/Session.hpp @@ -35,7 +35,7 @@ namespace Components void preDestroy() override; static void Send(const Network::Address& target, const std::string& command, const std::string& data = ""); - static void Handle(const std::string& packet, const Network::NetworkCallback& callback); + static void Handle(const std::string& packet, const Network::networkCallback& callback); private: static volatile bool Terminate; @@ -46,7 +46,7 @@ namespace Components static Utils::Cryptography::ECC::Key SignatureKey; - static std::unordered_map PacketHandlers; + static std::unordered_map PacketHandlers; static std::queue> SignatureQueue; From 33ebf76a8faf7b07ae5f39b8d6c4636506f2f3c3 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 9 Apr 2023 18:39:32 +0200 Subject: [PATCH 24/51] [MapRotation]: Exec only from this folder (#917) --- src/Components/Modules/MapRotation.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index de84131e..a449c763 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -70,7 +70,7 @@ namespace Components if (!this->containsHandler(key)) { - throw MapRotationParseError(std::format("Invalid key {}", key)); + throw MapRotationParseError(std::format("Invalid key '{}'", key)); } this->addEntry(key, value); @@ -237,7 +237,6 @@ namespace Components void MapRotation::ApplyExec(const std::string& name) { assert(!name.empty()); - Command::Execute(std::format("exec {}", name), false); Command::Execute(std::format("exec game_settings/{}", name), false); } From 11a7160a382e47e88e61d8fdd8fae3a60dcf2abb Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 9 Apr 2023 19:18:20 +0200 Subject: [PATCH 25/51] [Dvar]: Un-Cheat some harmless dvars --- src/Components/Modules/Dvar.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index f6ae52b2..2ee57d5d 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -411,6 +411,24 @@ namespace Components // un-cheat cg_draw2D Utils::Hook::Set(0x4F8EEE, Game::DVAR_NONE); + // un-cheat cg_overheadNamesFarScale + Utils::Hook::Set(0x4FA7C4, Game::DVAR_NONE); + + // un-cheat cg_overheadNamesSize + Utils::Hook::Set(0x4FA7F9, Game::DVAR_NONE); + + // un-cheat cg_overheadRankSize + Utils::Hook::Set(0x4FA863, Game::DVAR_NONE); + + // un-cheat cg_overheadIconSize + Utils::Hook::Set(0x4FA833, Game::DVAR_NONE); + + // un-cheat cg_overheadTitleSize + Utils::Hook::Set(0x4FA898, Game::DVAR_NONE); + + // un-cheat cg_overheadNamesGlow + Utils::Hook::Set(0x4FA8C9, Game::DVAR_NONE); + // remove archive flags for cg_hudChatPosition Utils::Hook::Xor(0x4F9992, Game::DVAR_ARCHIVE); From 39a003fca963e6ba1a2e0dfb5b29da5861456357 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 17:58:16 +0000 Subject: [PATCH 26/51] Bump deps/iw4-open-formats from `5be0ced` to `505a7c8` Bumps [deps/iw4-open-formats](https://github.com/XLabsProject/iw4-open-formats) from `5be0ced` to `505a7c8`. - [Release notes](https://github.com/XLabsProject/iw4-open-formats/releases) - [Commits](https://github.com/XLabsProject/iw4-open-formats/compare/5be0cedd5ac10a006a496ffb47ad99e12f1ceec5...505a7c8e85fbcbdae50cb9a661e440cd59b3bd62) --- updated-dependencies: - dependency-name: deps/iw4-open-formats dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/iw4-open-formats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats index 5be0cedd..505a7c8e 160000 --- a/deps/iw4-open-formats +++ b/deps/iw4-open-formats @@ -1 +1 @@ -Subproject commit 5be0cedd5ac10a006a496ffb47ad99e12f1ceec5 +Subproject commit 505a7c8e85fbcbdae50cb9a661e440cd59b3bd62 From 625a80afc8f511b9181002d3491defb03bd2f2a9 Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 11 Apr 2023 14:56:01 +0200 Subject: [PATCH 27/51] [General]: Cleanup (#921) --- src/Components/Modules/ServerInfo.cpp | 9 +++++++-- src/Utils/Cryptography.cpp | 10 +++++----- src/Utils/Cryptography.hpp | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index d7058bcd..01efbf97 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -86,7 +86,6 @@ namespace Components const auto* cxt = Game::ScrPlace_GetActivePlacement(localClientNum); auto addressText = Network::Address(*Game::connectedHost).getString(); - if (addressText == "0.0.0.0:0"s || addressText == "loopback"s) { addressText = "Listen Server"s; @@ -251,7 +250,13 @@ namespace Components return; } - const Utils::InfoString info(data.substr(0, data.find_first_of('\n'))); + const auto pos = data.find_first_of('\n'); + if (pos == std::string::npos) + { + return; + } + + const Utils::InfoString info(data.substr(0, pos)); Dvar::Var("uiSi_ServerName").set(info.get("sv_hostname")); Dvar::Var("uiSi_MaxClients").set(info.get("sv_maxclients")); diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 8209f152..7d003641 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -188,7 +188,7 @@ namespace Utils std::string hash(reinterpret_cast(buffer), sizeof(buffer)); if (!hex) return hash; - return String::DumpHex(hash, ""); + return String::DumpHex(hash, {}); } #pragma endregion @@ -212,7 +212,7 @@ namespace Utils std::string hash(reinterpret_cast(buffer), sizeof(buffer)); if (!hex) return hash; - return String::DumpHex(hash, ""); + return String::DumpHex(hash, {}); } #pragma endregion @@ -236,7 +236,7 @@ namespace Utils std::string hash(reinterpret_cast(buffer), sizeof(buffer)); if (!hex) return hash; - return String::DumpHex(hash, ""); + return String::DumpHex(hash, {}); } #pragma endregion @@ -260,7 +260,7 @@ namespace Utils std::string hash(reinterpret_cast(buffer), sizeof(buffer)); if (!hex) return hash; - return String::DumpHex(hash, ""); + return String::DumpHex(hash, {}); } #pragma endregion @@ -272,7 +272,7 @@ namespace Utils return Compute(data.data(), data.size()); } - unsigned int JenkinsOneAtATime::Compute(const char *key, std::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) diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index 09f66010..f3b48560 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -335,7 +335,7 @@ namespace Utils { public: static unsigned int Compute(const std::string& data); - static unsigned int Compute(const char *key, std::size_t len); + static unsigned int Compute(const char* key, std::size_t len); }; } } From 85fcd744759463262fcaaf479f638b76bf1db28c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 17:57:58 +0000 Subject: [PATCH 28/51] Bump deps/libtommath from `3f10a28` to `0df542c` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `3f10a28` to `0df542c`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/3f10a28885601256c8b5261be3b15c926c93393d...0df542cb70f621bbeec207be1949832fb1442479) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 3f10a288..0df542cb 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 3f10a28885601256c8b5261be3b15c926c93393d +Subproject commit 0df542cb70f621bbeec207be1949832fb1442479 From c319ca7456d0ac6be09574848b1373811d21c6ac Mon Sep 17 00:00:00 2001 From: Edo Date: Thu, 13 Apr 2023 15:26:59 +0200 Subject: [PATCH 29/51] [Dvar]: Update comment (#924) --- src/Components/Modules/Dvar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 2ee57d5d..a732a894 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -486,7 +486,7 @@ namespace Components Utils::Hook(0x636608, SetFromStringByNameExternal, HOOK_CALL).install()->quick(); Utils::Hook(0x636695, SetFromStringByNameExternal, HOOK_CALL).install()->quick(); - // Hook Dvar_SetFromStringByName inside CG_SetClientDvarFromServer so we can reset dvars when the player leaves the server + // Hook Dvar_SetFromStringByName inside CG_SetClientDvarFromServer so we can protect dvars Utils::Hook(0x59386A, DvarSetFromStringByName_Stub, HOOK_CALL).install()->quick(); // For debugging From c1f6d56aaf5e91cf09c256fccde73d2baab420b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Apr 2023 18:02:29 +0000 Subject: [PATCH 30/51] Bump deps/zlib from `eb0e038` to `5799c14` Bumps [deps/zlib](https://github.com/madler/zlib) from `eb0e038` to `5799c14`. - [Release notes](https://github.com/madler/zlib/releases) - [Commits](https://github.com/madler/zlib/compare/eb0e038b297f2c9877ed8b3515c6718a4b65d485...5799c14c8526bf1aaa130c021982f831d155b46d) --- 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 eb0e038b..5799c14c 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit eb0e038b297f2c9877ed8b3515c6718a4b65d485 +Subproject commit 5799c14c8526bf1aaa130c021982f831d155b46d From f0485be3b3294014a4ca3190db8a1b42e759405f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Apr 2023 18:02:33 +0000 Subject: [PATCH 31/51] Bump deps/iw4-open-formats from `505a7c8` to `aeca35a` Bumps [deps/iw4-open-formats](https://github.com/XLabsProject/iw4-open-formats) from `505a7c8` to `aeca35a`. - [Release notes](https://github.com/XLabsProject/iw4-open-formats/releases) - [Commits](https://github.com/XLabsProject/iw4-open-formats/compare/505a7c8e85fbcbdae50cb9a661e440cd59b3bd62...aeca35a37ea4dff7fa5483604d77bd9be5ffbc1e) --- updated-dependencies: - dependency-name: deps/iw4-open-formats dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/iw4-open-formats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats index 505a7c8e..aeca35a3 160000 --- a/deps/iw4-open-formats +++ b/deps/iw4-open-formats @@ -1 +1 @@ -Subproject commit 505a7c8e85fbcbdae50cb9a661e440cd59b3bd62 +Subproject commit aeca35a37ea4dff7fa5483604d77bd9be5ffbc1e From 9160436b05ca2e00c822312cc0185f2c839bf3b3 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 15 Apr 2023 12:19:56 +0200 Subject: [PATCH 32/51] [General]: Fix dvar name (#927) --- src/Components/Modules/Bots.cpp | 18 +++++++++++++++++- src/Components/Modules/Bots.hpp | 1 + src/Components/Modules/ClanTags.cpp | 6 +++--- src/Components/Modules/ClanTags.hpp | 2 ++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index a3962991..b679a28c 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -1,6 +1,7 @@ #include #include "Bots.hpp" +#include "ClanTags.hpp" #include "GSC/Script.hpp" @@ -10,6 +11,8 @@ namespace Components { + constexpr std::size_t MAX_NAME_LENGTH = 16; + std::vector Bots::BotNames; Dvar::Var Bots::SVRandomBotNames; @@ -57,6 +60,16 @@ namespace Components std::ranges::shuffle(BotNames, gen); } + std::string Bots::TruncBotString(const std::string& input, const std::size_t length) + { + if (length > input.size()) + { + return input; + } + + return input.substr(length); + } + void Bots::LoadBotNames() { FileSystem::File bots("bots.txt"); @@ -94,6 +107,9 @@ namespace Components entry = entry.substr(0, pos); } + entry = TruncBotString(entry, MAX_NAME_LENGTH - 1); + clanAbbrev = TruncBotString(clanAbbrev, ClanTags::MAX_CLAN_NAME_LENGTH - 1); + BotNames.emplace_back(entry, clanAbbrev); } @@ -381,7 +397,7 @@ namespace Components Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).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) -> void diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index 92a492b7..b7094629 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -14,6 +14,7 @@ namespace Components static Dvar::Var SVRandomBotNames; static void RandomizeBotNames(); + static std::string TruncBotString(const std::string& input, std::size_t length); static void LoadBotNames(); static int BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port); diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index 0db83001..40233a4c 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -8,7 +8,7 @@ namespace Components const Game::dvar_t* ClanTags::ClanName; // bgs_t and clientState_s do not have this - char ClanTags::ClientState[Game::MAX_CLIENTS][5]; + char ClanTags::ClientState[Game::MAX_CLIENTS][MAX_CLAN_NAME_LENGTH]; const char* ClanTags::GetClanTagWithName(int clientNum, const char* playerName) { @@ -73,7 +73,7 @@ namespace Components void ClanTags::CL_SanitizeClanName() { - char saneNameBuf[5]{}; + char saneNameBuf[MAX_CLAN_NAME_LENGTH]{}; auto* saneName = saneNameBuf; assert(ClanName); @@ -238,7 +238,7 @@ namespace Components ClanName = Game::Dvar_RegisterString("clanName", "", Game::DVAR_ARCHIVE, "Your clan abbreviation"); }); - std::memset(&ClientState, 0, sizeof(char[Game::MAX_CLIENTS][5])); + std::memset(&ClientState, 0, sizeof(char[Game::MAX_CLIENTS][MAX_CLAN_NAME_LENGTH])); ServerCommands::OnCommand(22, [](Command::Params* params) { diff --git a/src/Components/Modules/ClanTags.hpp b/src/Components/Modules/ClanTags.hpp index 6618504b..72b6c9ad 100644 --- a/src/Components/Modules/ClanTags.hpp +++ b/src/Components/Modules/ClanTags.hpp @@ -5,6 +5,8 @@ namespace Components class ClanTags : public Component { public: + static constexpr std::size_t MAX_CLAN_NAME_LENGTH = 5; + ClanTags(); static const char* GetClanTagWithName(int clientNum, const char* playerName); From e945652dc1bb21c6dcdfacb4ffb50ece757888c0 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 10:47:02 +0200 Subject: [PATCH 33/51] [Auth]: Improve sv_privateClients patch (#928) --- src/Components/Modules/Auth.cpp | 34 ++++++++------------------------- src/Components/Modules/Auth.hpp | 2 +- src/Components/Modules/Bots.cpp | 2 +- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index f150b107..98372d44 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -273,33 +273,16 @@ namespace Components return value; } - __declspec(naked) void Auth::DirectConnectPrivateClientStub() + int Auth::NET_IsLocalAddressStub(Game::netadr_t adr) { - __asm + if (HasAccessToReservedSlot) { - push eax - - mov al, HasAccessToReservedSlot - test al, al - - pop eax - - je noAccess - - // Set the number of private clients to 0 if the client has the right password - xor eax, eax - jmp safeContinue - - noAccess: - mov eax, dword ptr [edx + 0x10] - - safeContinue: - // Game code skipped by hook - add esp, 0xC - - push 0x460FB3 - ret + // Bypass sv_privateClients if client has the password + return 1; } + + // Only bypass if address is local. Original behaviour + return Utils::Hook::Call(0x402BD0)(adr); } unsigned __int64 Auth::GetKeyHash(const std::string& key) @@ -484,8 +467,7 @@ namespace Components // Install registration hook Utils::Hook(0x6265F9, DirectConnectStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x460EF5, Info_ValueForKeyStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x460FAD, DirectConnectPrivateClientStub, HOOK_JUMP).install()->quick(); - Utils::Hook::Nop(0x460FAD + 5, 1); + Utils::Hook(0x460F89, NET_IsLocalAddressStub, HOOK_CALL).install()->quick(); Utils::Hook(0x41D3E3, SendConnectDataStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Auth.hpp b/src/Components/Modules/Auth.hpp index 5ab438ce..9f10db42 100644 --- a/src/Components/Modules/Auth.hpp +++ b/src/Components/Modules/Auth.hpp @@ -51,7 +51,7 @@ namespace Components static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr); static void DirectConnectStub(); static char* Info_ValueForKeyStub(const char* s, const char* key); - static void DirectConnectPrivateClientStub(); + static int NET_IsLocalAddressStub(Game::netadr_t adr); static void Frame(); }; diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index b679a28c..2deaba89 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -168,7 +168,7 @@ namespace Components Scheduler::Once([ent] { - Game::Scr_AddString(Utils::String::VA("class%u", Utils::Cryptography::Rand::GenerateInt() % 5u)); + Game::Scr_AddString(Utils::String::Format("class{}", std::rand() % 5)); Game::Scr_AddString("changeclass"); Game::Scr_Notify(ent, static_cast(Game::SL_GetString("menuresponse", 0)), 2); }, Scheduler::Pipeline::SERVER, 1s); From d53fc404b218054b15a3a0f06576d93faba7d32e Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 11:05:51 +0200 Subject: [PATCH 34/51] [Auth]: Undo this (#929) --- src/Components/Modules/Auth.cpp | 34 +++++++++++++++++++++++++-------- src/Components/Modules/Auth.hpp | 2 +- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index 98372d44..f150b107 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -273,16 +273,33 @@ namespace Components return value; } - int Auth::NET_IsLocalAddressStub(Game::netadr_t adr) + __declspec(naked) void Auth::DirectConnectPrivateClientStub() { - if (HasAccessToReservedSlot) + __asm { - // Bypass sv_privateClients if client has the password - return 1; - } + push eax - // Only bypass if address is local. Original behaviour - return Utils::Hook::Call(0x402BD0)(adr); + mov al, HasAccessToReservedSlot + test al, al + + pop eax + + je noAccess + + // Set the number of private clients to 0 if the client has the right password + xor eax, eax + jmp safeContinue + + noAccess: + mov eax, dword ptr [edx + 0x10] + + safeContinue: + // Game code skipped by hook + add esp, 0xC + + push 0x460FB3 + ret + } } unsigned __int64 Auth::GetKeyHash(const std::string& key) @@ -467,7 +484,8 @@ namespace Components // Install registration hook Utils::Hook(0x6265F9, DirectConnectStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x460EF5, Info_ValueForKeyStub, HOOK_CALL).install()->quick(); - Utils::Hook(0x460F89, NET_IsLocalAddressStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x460FAD, DirectConnectPrivateClientStub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x460FAD + 5, 1); Utils::Hook(0x41D3E3, SendConnectDataStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Auth.hpp b/src/Components/Modules/Auth.hpp index 9f10db42..5ab438ce 100644 --- a/src/Components/Modules/Auth.hpp +++ b/src/Components/Modules/Auth.hpp @@ -51,7 +51,7 @@ namespace Components static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr); static void DirectConnectStub(); static char* Info_ValueForKeyStub(const char* s, const char* key); - static int NET_IsLocalAddressStub(Game::netadr_t adr); + static void DirectConnectPrivateClientStub(); static void Frame(); }; From c9b1566e38fdc719e6703fc77073be75767869bb Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 11:27:19 +0200 Subject: [PATCH 35/51] [Bots]: sv_replaceTestClients dvar (#930) --- src/Components/Modules/Auth.cpp | 4 ++++ src/Components/Modules/Bots.cpp | 26 +++++++++++++++++++++++--- src/Components/Modules/Bots.hpp | 5 ++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index f150b107..86a377c6 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -4,6 +4,7 @@ #include #include "Bans.hpp" +#include "Bots.hpp" namespace Components { @@ -270,6 +271,9 @@ namespace Components HasAccessToReservedSlot = std::strcmp((*Game::sv_privatePassword)->current.string, value) == 0; + // This stubs runs right before the 'server is full check' so we can call this here + Bots::SV_DirectConnect_Full_Check(); + return value; } diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 2deaba89..f53c61cb 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -15,7 +15,8 @@ namespace Components std::vector Bots::BotNames; - Dvar::Var Bots::SVRandomBotNames; + const Game::dvar_t* Bots::sv_randomBotNames; + const Game::dvar_t* Bots::sv_replaceBots; struct BotMovementInfo { @@ -113,7 +114,7 @@ namespace Components BotNames.emplace_back(entry, clanAbbrev); } - if (SVRandomBotNames.get()) + if (sv_randomBotNames->current.enabled) { RandomizeBotNames(); } @@ -378,6 +379,24 @@ namespace Components return Game::svs_clients[clientNum].ping; } + void Bots::SV_DirectConnect_Full_Check() + { + if (!sv_replaceBots->current.enabled) + { + return; + } + + for (auto i = 0; i < (*Game::sv_maxclients)->current.integer; ++i) + { + auto* cl = &Game::svs_clients[i]; + if (cl->bIsTestClient) + { + Game::SV_DropClient(cl, "EXE_DISCONNECTED", false); + return; + } + } + } + Bots::Bots() { AssertOffset(Game::client_t, bIsTestClient, 0x41AF0); @@ -397,7 +416,8 @@ namespace Components Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick(); - SVRandomBotNames = Dvar::Register("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); + sv_randomBotNames = Game::Dvar_RegisterBool("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); + sv_replaceBots = Game::Dvar_RegisterBool("sv_replaceBots", false, Game::DVAR_NONE, "Test clients will be replaced by connecting players when the server is full."); // Reset BotMovementInfo.active when client is dropped Events::OnClientDisconnect([](const int clientNum) -> void diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index b7094629..f2e7642c 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -7,11 +7,14 @@ namespace Components public: Bots(); + static void SV_DirectConnect_Full_Check(); + private: using botData = std::pair< std::string, std::string>; static std::vector BotNames; - static Dvar::Var SVRandomBotNames; + static const Game::dvar_t* sv_randomBotNames; + static const Game::dvar_t* sv_replaceBots; static void RandomizeBotNames(); static std::string TruncBotString(const std::string& input, std::size_t length); From 9401543a132944b555388143fead7f3ac9c32f9d Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 11:36:06 +0200 Subject: [PATCH 36/51] [Auth]: Edit comment (#931) --- src/Components/Modules/Auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index 86a377c6..a0fae972 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -271,7 +271,7 @@ namespace Components HasAccessToReservedSlot = std::strcmp((*Game::sv_privatePassword)->current.string, value) == 0; - // This stubs runs right before the 'server is full check' so we can call this here + // This stub runs right before the 'server is full check' so we can call this here Bots::SV_DirectConnect_Full_Check(); return value; From 23bfc3e89abf010dbd53d1b1228a0319b47c06fc Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 12:09:47 +0200 Subject: [PATCH 37/51] [Bots]: Fix (#932) --- src/Components/Modules/Bots.cpp | 25 ++++++++++++++++++++++++- src/Components/Modules/Bots.hpp | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index f53c61cb..a5686140 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -379,9 +379,26 @@ namespace Components return Game::svs_clients[clientNum].ping; } + bool Bots::IsFull() + { + auto i = 0; + while (i < *Game::svs_clientCount) + { + if (Game::svs_clients[i].header.state == Game::CS_FREE) + { + // Free slot was found + break; + } + + ++i; + } + + return i == *Game::svs_clientCount; + } + void Bots::SV_DirectConnect_Full_Check() { - if (!sv_replaceBots->current.enabled) + if (!sv_replaceBots->current.enabled && !IsFull()) { return; } @@ -440,6 +457,12 @@ namespace Components return; } + if (IsFull()) + { + Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Server is full.\n"); + return; + } + std::size_t count = 1; if (params->size() > 1) diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index f2e7642c..0fe3d883 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -33,5 +33,7 @@ namespace Components static void G_SelectWeaponIndex_Hk(); static int SV_GetClientPing_Hk(int clientNum); + + static bool IsFull(); }; } From e05fa7f6a040b1b7e3fe43f8fb61e6fc57b12576 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 12:30:12 +0200 Subject: [PATCH 38/51] [Bots]: :man_facepalming: I'm blind (#933) --- src/Components/Modules/Bots.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index a5686140..d3539023 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -398,7 +398,7 @@ namespace Components void Bots::SV_DirectConnect_Full_Check() { - if (!sv_replaceBots->current.enabled && !IsFull()) + if (!sv_replaceBots->current.enabled || !IsFull()) { return; } @@ -409,6 +409,7 @@ namespace Components if (cl->bIsTestClient) { Game::SV_DropClient(cl, "EXE_DISCONNECTED", false); + cl->header.state = Game::CS_FREE; return; } } From 6fb59fff1f4c742d743f159c9c44e436852a7b58 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 13:01:58 +0200 Subject: [PATCH 39/51] [Bots]: Cleanup (#934) --- src/Components/Modules/Bots.cpp | 24 +++++++++++------------- src/Components/Modules/Bots.hpp | 2 ++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index d3539023..8b0f13df 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -415,6 +415,15 @@ namespace Components } } + void Bots::CleanBotArray() + { + ZeroMemory(&g_botai, sizeof(g_botai)); + for (std::size_t i = 0; i < std::extent_v; ++i) + { + g_botai[i].weapon = 1; // Prevent the bots from defaulting to the 'none' weapon + } + } + Bots::Bots() { AssertOffset(Game::client_t, bIsTestClient, 0x41AF0); @@ -443,12 +452,7 @@ namespace Components g_botai[clientNum].active = false; }); - // Zero the bot command array - for (std::size_t i = 0; i < std::extent_v; ++i) - { - ZeroMemory(&g_botai[i], sizeof(BotMovementInfo)); - g_botai[i].weapon = 1; // Prevent the bots from defaulting to the 'none' weapon - } + CleanBotArray(); Command::Add("spawnBot", [](Command::Params* params) { @@ -497,12 +501,6 @@ namespace Components AddScriptMethods(); // In case a loaded mod didn't call "BotStop" before the VM shutdown - Events::OnVMShutdown([] - { - for (std::size_t i = 0; i < std::extent_v; ++i) - { - g_botai[i].active = false; - } - }); + Events::OnVMShutdown(CleanBotArray); } } diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index 0fe3d883..23d253f3 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -35,5 +35,7 @@ namespace Components static int SV_GetClientPing_Hk(int clientNum); static bool IsFull(); + + static void CleanBotArray(); }; } From a304d64fa729e6e7d8b4ac0c52c4a469d116ff7d Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 14:22:01 +0200 Subject: [PATCH 40/51] [Deps]: Update rapidjson (#935) --- deps/premake/rapidjson.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deps/premake/rapidjson.lua b/deps/premake/rapidjson.lua index d1085120..0dc3b4b9 100644 --- a/deps/premake/rapidjson.lua +++ b/deps/premake/rapidjson.lua @@ -3,6 +3,10 @@ rapidjson = { } function rapidjson.import() + defines { + "RAPIDJSON_HAS_STDSTRING" + } + rapidjson.includes() end From bf57ab2daab62c76777f7e6df79895ed5519ab89 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Apr 2023 15:07:09 +0200 Subject: [PATCH 41/51] [Bans]: Correct small mistake (#936) --- src/Components/Modules/Bans.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Bans.cpp b/src/Components/Modules/Bans.cpp index 0d259589..b7702656 100644 --- a/src/Components/Modules/Bans.cpp +++ b/src/Components/Modules/Bans.cpp @@ -266,7 +266,7 @@ namespace Components return; } - const auto* cl = &Game::svs_clients[clientNum]; + auto* cl = &Game::svs_clients[clientNum]; if (cl->header.state < Game::CS_ACTIVE) { Logger::Print("Client {} is not active\n", clientNum); @@ -279,7 +279,7 @@ namespace Components } const std::string reason = params->size() < 3 ? "EXE_ERR_BANNED_PERM" : params->join(2); - BanClient(&Game::svs_clients[clientNum], reason); + BanClient(cl, reason); }); Command::Add("unbanClient", [](Command::Params* params) From 0b9d41af3dfd35230e895469b69f000049811bf6 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 17 Apr 2023 12:27:31 +0200 Subject: [PATCH 42/51] [Chat]: Catch Edge Case (#937) --- src/Components/Modules/Chat.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index b7fbd4e2..0b53f85e 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -40,24 +40,16 @@ namespace Components // Prevent callbacks from adding a new callback (would make the vector iterator invalid) CanAddCallback = false; - // Chat messages sent through the console do not begin with \x15 + // Chat messages sent through the console do not begin with \x15. In some cases it contains \x14 auto msgIndex = 0; - if (text[msgIndex] == '\x15') + while (text[msgIndex] == '\x15' || text[msgIndex] == '\x14') { - msgIndex = 1; + ++msgIndex; } if (text[msgIndex] == '/') { SendChat = false; - - if (msgIndex == 1) - { - // Overwrite / with \x15 - text[msgIndex] = text[msgIndex - 1]; - } - // Skip over the first character - ++text; } if (IsMuted(player)) @@ -72,7 +64,7 @@ namespace Components Game::SV_GameSendServerCommand(player - Game::g_entities, Game::SV_CMD_RELIABLE, Utils::String::VA("%c \"Chat is disabled\"", 0x65)); } - // Message might be empty after processing the '/' + // Message might be empty after the special characters if (text[msgIndex] == '\0') { SendChat = false; From bf59472b6cbe7c9b9419307e47295a3554fb0a82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 10:36:06 +0000 Subject: [PATCH 43/51] Bump deps/zlib from `5799c14` to `6658868` Bumps [deps/zlib](https://github.com/madler/zlib) from `5799c14` to `6658868`. - [Release notes](https://github.com/madler/zlib/releases) - [Commits](https://github.com/madler/zlib/compare/5799c14c8526bf1aaa130c021982f831d155b46d...66588683b36042154ad35140bf9fcbb60c5d573c) --- 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 5799c14c..66588683 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit 5799c14c8526bf1aaa130c021982f831d155b46d +Subproject commit 66588683b36042154ad35140bf9fcbb60c5d573c From 8514ec863bc382bd1d0665da970e331e4e9fa006 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 17 Apr 2023 13:08:44 +0200 Subject: [PATCH 44/51] [Dvars]: Remove archive flag for this (#940) --- src/Components/Modules/Dvar.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index a732a894..8138faac 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -432,6 +432,9 @@ namespace Components // remove archive flags for cg_hudChatPosition Utils::Hook::Xor(0x4F9992, Game::DVAR_ARCHIVE); + // remove archive flags for sv_hostname + Utils::Hook::Xor(0x4D3786, Game::DVAR_ARCHIVE); + // remove write protection from fs_game Utils::Hook::Xor(0x6431EA, Game::DVAR_INIT); @@ -444,13 +447,13 @@ namespace Components static float volume = 1.0f; Utils::Hook::Set(0x408078, &volume); - // Uncheat ui_showList + // un-cheat ui_showList Utils::Hook::Xor(0x6310DC, Game::DVAR_CHEAT); - // Uncheat ui_debugMode + // un-cheat ui_debugMode Utils::Hook::Xor(0x6312DE, Game::DVAR_CHEAT); - // Uncheat jump_slowdownEnable + // un-cheat jump_slowdownEnable Utils::Hook::Xor(0x4EFABE, Game::DVAR_CHEAT); // Hook dvar 'name' registration From f93269bd0c59306d142ef06cccf69d0c80cd68f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 11:12:14 +0000 Subject: [PATCH 45/51] Bump deps/iw4-open-formats from `aeca35a` to `1bc514d` Bumps [deps/iw4-open-formats](https://github.com/XLabsProject/iw4-open-formats) from `aeca35a` to `1bc514d`. - [Release notes](https://github.com/XLabsProject/iw4-open-formats/releases) - [Commits](https://github.com/XLabsProject/iw4-open-formats/compare/aeca35a37ea4dff7fa5483604d77bd9be5ffbc1e...1bc514d4c981532d1195b420a8fc0ce809c65944) --- updated-dependencies: - dependency-name: deps/iw4-open-formats dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/iw4-open-formats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats index aeca35a3..1bc514d4 160000 --- a/deps/iw4-open-formats +++ b/deps/iw4-open-formats @@ -1 +1 @@ -Subproject commit aeca35a37ea4dff7fa5483604d77bd9be5ffbc1e +Subproject commit 1bc514d4c981532d1195b420a8fc0ce809c65944 From 777215b90ac62e97722545ba3cd50b6cbb56e2ae Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 17 Apr 2023 14:47:29 +0200 Subject: [PATCH 46/51] [General]: Clean global headers (#941) --- src/Components/Loader.cpp | 13 ++++- src/Components/Loader.hpp | 11 ----- src/Components/Modules/Auth.cpp | 3 ++ src/Components/Modules/Chat.cpp | 1 + src/Components/Modules/ConnectProtocol.cpp | 1 + src/Components/Modules/Console.cpp | 1 + src/Components/Modules/Debug.cpp | 1 + src/Components/Modules/Discord.cpp | 1 + src/Components/Modules/Dvar.cpp | 3 ++ src/Components/Modules/Exception.cpp | 57 +++++++++------------- src/Components/Modules/Exception.hpp | 2 +- src/Components/Modules/Friends.cpp | 5 ++ src/Components/Modules/IPCPipe.cpp | 2 + src/Components/Modules/Materials.cpp | 1 + src/Components/Modules/ModList.cpp | 1 + src/Components/Modules/ModelSurfs.cpp | 1 + src/Components/Modules/Node.cpp | 1 + src/Components/Modules/Party.cpp | 3 ++ src/Components/Modules/PlayerName.cpp | 1 + src/Components/Modules/QuickPatch.cpp | 6 +++ src/Components/Modules/RawMouse.cpp | 1 + src/Components/Modules/ServerInfo.cpp | 1 + src/Components/Modules/ServerList.cpp | 3 ++ src/Components/Modules/TextRenderer.cpp | 1 + src/Components/Modules/Toast.cpp | 3 ++ src/Components/Modules/Window.cpp | 1 + src/Steam/Interfaces/SteamUser.cpp | 1 + 27 files changed, 80 insertions(+), 46 deletions(-) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index de0f2420..cce1e935 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -2,6 +2,7 @@ #include #include "Modules/ArenaLength.hpp" +#include "Modules/Auth.hpp" #include "Modules/Bans.hpp" #include "Modules/Bots.hpp" #include "Modules/Branding.hpp" @@ -20,13 +21,20 @@ #include "Modules/Discovery.hpp" #include "Modules/Download.hpp" #include "Modules/Elevators.hpp" +#include "Modules/Exception.hpp" #include "Modules/FastFiles.hpp" +#include "Modules/Friends.hpp" #include "Modules/Gamepad.hpp" +#include "Modules/IPCPipe.hpp" #include "Modules/Lean.hpp" #include "Modules/MapDump.hpp" #include "Modules/MapRotation.hpp" +#include "Modules/Materials.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" @@ -46,13 +54,16 @@ #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/VisionFile.hpp" #include "Modules/Voice.hpp" #include "Modules/Vote.hpp" #include "Modules/Weapon.hpp" +#include "Modules/Window.hpp" #include "Modules/BotLib/lPrecomp.hpp" @@ -97,7 +108,7 @@ namespace Components Register(new Logger()); Register(new UIScript()); Register(new ZoneBuilder()); - + Register(new ArenaLength()); Register(new AssetHandler()); Register(new Bans()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index dee129b3..d4282cdc 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -62,10 +62,8 @@ namespace Components } // Priority -#include "Modules/Auth.hpp" #include "Modules/Command.hpp" #include "Modules/Dvar.hpp" -#include "Modules/Exception.hpp" #include "Modules/Flags.hpp" #include "Modules/Network.hpp" #include "Modules/Logger.hpp" @@ -77,20 +75,11 @@ namespace Components #include "Modules/Dedicated.hpp" #include "Modules/Events.hpp" #include "Modules/FileSystem.hpp" -#include "Modules/Friends.hpp" -#include "Modules/IPCPipe.hpp" #include "Modules/Localization.hpp" #include "Modules/Maps.hpp" -#include "Modules/Materials.hpp" #include "Modules/Menus.hpp" -#include "Modules/ModList.hpp" -#include "Modules/ModelSurfs.hpp" -#include "Modules/Node.hpp" #include "Modules/Renderer.hpp" #include "Modules/Scheduler.hpp" -#include "Modules/TextRenderer.hpp" -#include "Modules/Toast.hpp" -#include "Modules/Window.hpp" #include "Modules/Zones.hpp" #include "Modules/GSC/GSC.hpp" diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index a0fae972..af3dbb3c 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -3,8 +3,11 @@ #include +#include "Auth.hpp" #include "Bans.hpp" #include "Bots.hpp" +#include "Friends.hpp" +#include "Toast.hpp" namespace Components { diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 0b53f85e..d3aa5397 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -1,6 +1,7 @@ #include #include "Chat.hpp" #include "PlayerName.hpp" +#include "TextRenderer.hpp" #include "Voice.hpp" #include "GSC/Script.hpp" diff --git a/src/Components/Modules/ConnectProtocol.cpp b/src/Components/Modules/ConnectProtocol.cpp index 4a44ad34..1793b44a 100644 --- a/src/Components/Modules/ConnectProtocol.cpp +++ b/src/Components/Modules/ConnectProtocol.cpp @@ -1,5 +1,6 @@ #include #include "ConnectProtocol.hpp" +#include "IPCPipe.hpp" namespace Components { diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index c30824cd..56acd131 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -1,5 +1,6 @@ #include #include "Console.hpp" +#include "TextRenderer.hpp" #include "Terminus_4.49.1.ttf.hpp" diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index 5b8bcfcd..4e7b7c95 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -1,5 +1,6 @@ #include #include "Debug.hpp" +#include "TextRenderer.hpp" #include "Game/Engine/ScopedCriticalSection.hpp" diff --git a/src/Components/Modules/Discord.cpp b/src/Components/Modules/Discord.cpp index 9087d734..b487e106 100644 --- a/src/Components/Modules/Discord.cpp +++ b/src/Components/Modules/Discord.cpp @@ -1,6 +1,7 @@ #include #include "Discord.hpp" #include "Party.hpp" +#include "TextRenderer.hpp" #include diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 8138faac..665abae7 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -1,5 +1,8 @@ #include +#include "Friends.hpp" +#include "TextRenderer.hpp" + namespace Components { Dvar::Var Dvar::Name; diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index 7860a375..0bb0db17 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -1,5 +1,8 @@ #include + #include "Console.hpp" +#include "Exception.hpp" +#include "Window.hpp" #include @@ -50,32 +53,39 @@ namespace Components Game::Sys_SuspendOtherThreads(); } - void Exception::CopyMessageToClipboard(const std::string& error) + void Exception::CopyMessageToClipboard(const char* error) { const auto hWndNewOwner = GetDesktopWindow(); const auto result = OpenClipboard(hWndNewOwner); if (result == FALSE) + { return; + } - EmptyClipboard(); - auto* hMem = GlobalAlloc(GMEM_MOVEABLE, error.size() + 1); - - if (hMem == nullptr) + const auto _0 = gsl::finally([] { CloseClipboard(); + }); + + EmptyClipboard(); + + const auto len = std::strlen(error); + auto* hMem = GlobalAlloc(GMEM_MOVEABLE, len + 1); + + if (!hMem) + { return; } auto* lock = GlobalLock(hMem); - if (lock != nullptr) + if (lock) { - std::memcpy(lock, error.data(), error.size() + 1); + std::memcpy(lock, error, len + 1); GlobalUnlock(hMem); - SetClipboardData(1, hMem); + SetClipboardData(CF_TEXT, hMem); } - CloseClipboard(); GlobalFree(hMem); } @@ -88,18 +98,18 @@ namespace Components return EXCEPTION_CONTINUE_EXECUTION; } - std::string errorStr; + const char* error; if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { - errorStr = "Termination because of a stack overflow.\nCopy exception address to clipboard?"; + error = "Termination because of a stack overflow.\nCopy exception address to clipboard?"; } else { - errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.\nCopy exception address to clipboard?", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); + error = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.\nCopy exception address to clipboard?", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); } // Message should be copied to the keyboard if no button is pressed - if (MessageBoxA(nullptr, errorStr.data(), nullptr, MB_YESNO | MB_ICONERROR) == IDYES) + if (MessageBoxA(nullptr, error, nullptr, MB_YESNO | MB_ICONERROR) == IDYES) { CopyMessageToClipboard(Utils::String::VA("0x%08X", ExceptionInfo->ExceptionRecord->ExceptionAddress)); } @@ -136,8 +146,8 @@ namespace Components 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); #ifdef _DEBUG OutputDebugStringA("Failed to create new minidump!"); -#endif Utils::OutputDebugLastError(); +#endif TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); } @@ -190,25 +200,6 @@ namespace Components 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 MAP_TEST - Command::Add("mapTest", [](Command::Params* params) - { - Game::UI_UpdateArenas(); - - std::string command; - for (auto i = 0; i < (params->size() >= 2 ? atoi(params->get(1)) : *Game::arenaCount); ++i) - { - const auto* mapName = ArenaLength::NewArenas[i % *Game::arenaCount].mapName; - - if (!(i % 2)) command.append("wait 250;disconnect;wait 750;"); // Test a disconnect - else command.append("wait 500;"); // Test direct map switch - command.append(Utils::String::VA("map %s;", mapName)); - } - - Command::Execute(command, false); - }); -#endif } Exception::~Exception() diff --git a/src/Components/Modules/Exception.hpp b/src/Components/Modules/Exception.hpp index 40b5e820..9967144d 100644 --- a/src/Components/Modules/Exception.hpp +++ b/src/Components/Modules/Exception.hpp @@ -17,7 +17,7 @@ namespace Components static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo); static __declspec(noreturn) void LongJmp_Internal_Stub(jmp_buf env, int status); - static void CopyMessageToClipboard(const std::string& error); + static void CopyMessageToClipboard(const char* error); static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter_Stub(LPTOP_LEVEL_EXCEPTION_FILTER); diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index 900c2111..dea87d13 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -5,7 +5,12 @@ #include #pragma warning(pop) +#include "Friends.hpp" +#include "Materials.hpp" +#include "Node.hpp" #include "Party.hpp" +#include "TextRenderer.hpp" +#include "Toast.hpp" #include "UIFeeder.hpp" namespace Components diff --git a/src/Components/Modules/IPCPipe.cpp b/src/Components/Modules/IPCPipe.cpp index ea2f2980..64d9a31d 100644 --- a/src/Components/Modules/IPCPipe.cpp +++ b/src/Components/Modules/IPCPipe.cpp @@ -1,6 +1,8 @@ #include #include +#include "IPCPipe.hpp" + namespace Components { Pipe IPCPipe::ServerPipe; diff --git a/src/Components/Modules/Materials.cpp b/src/Components/Modules/Materials.cpp index 69176b08..16178a44 100644 --- a/src/Components/Modules/Materials.cpp +++ b/src/Components/Modules/Materials.cpp @@ -1,4 +1,5 @@ #include +#include "Materials.hpp" namespace Components { diff --git a/src/Components/Modules/ModList.cpp b/src/Components/Modules/ModList.cpp index 13f6c3ab..7782fb33 100644 --- a/src/Components/Modules/ModList.cpp +++ b/src/Components/Modules/ModList.cpp @@ -1,4 +1,5 @@ #include +#include "ModList.hpp" #include "UIFeeder.hpp" namespace Components diff --git a/src/Components/Modules/ModelSurfs.cpp b/src/Components/Modules/ModelSurfs.cpp index 4c5424a4..e7e888eb 100644 --- a/src/Components/Modules/ModelSurfs.cpp +++ b/src/Components/Modules/ModelSurfs.cpp @@ -1,4 +1,5 @@ #include +#include "ModelSurfs.hpp" namespace Components { diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 7c796801..cb122cc7 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -4,6 +4,7 @@ #include +#include "Node.hpp" #include "ServerList.hpp" #include "Session.hpp" diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 58c03510..efe579e0 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -1,8 +1,11 @@ #include #include +#include "Auth.hpp" #include "Download.hpp" +#include "Friends.hpp" #include "Gamepad.hpp" +#include "Node.hpp" #include "Party.hpp" #include "ServerList.hpp" #include "Stats.hpp" diff --git a/src/Components/Modules/PlayerName.cpp b/src/Components/Modules/PlayerName.cpp index f0d758e8..826b97d5 100644 --- a/src/Components/Modules/PlayerName.cpp +++ b/src/Components/Modules/PlayerName.cpp @@ -1,6 +1,7 @@ #include #include "ClanTags.hpp" #include "PlayerName.hpp" +#include "TextRenderer.hpp" namespace Components { diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 41fc91b9..b4086ff9 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -2,6 +2,8 @@ #include #include "QuickPatch.hpp" +#include "TextRenderer.hpp" +#include "Toast.hpp" namespace Components { @@ -196,10 +198,14 @@ namespace Components void QuickPatch::CL_KeyEvent_OnEscape() { if (Game::Con_CancelAutoComplete()) + { return; + } if (TextRenderer::HandleFontIconAutocompleteKey(0, TextRenderer::FONT_ICON_ACI_CONSOLE, Game::K_ESCAPE)) + { return; + } // Close console Game::Key_RemoveCatcher(0, ~Game::KEYCATCH_CONSOLE); diff --git a/src/Components/Modules/RawMouse.cpp b/src/Components/Modules/RawMouse.cpp index bc046d7b..7a7ea662 100644 --- a/src/Components/Modules/RawMouse.cpp +++ b/src/Components/Modules/RawMouse.cpp @@ -1,6 +1,7 @@ #include #include "Gamepad.hpp" #include "RawMouse.hpp" +#include "Window.hpp" namespace Components { diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 01efbf97..dfae403b 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -1,6 +1,7 @@ #include #include +#include "Friends.hpp" #include "Gamepad.hpp" #include "Party.hpp" #include "ServerInfo.hpp" diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 2c0697ea..fa7b0e68 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -2,8 +2,11 @@ #include #include "Discovery.hpp" +#include "Node.hpp" #include "Party.hpp" #include "ServerList.hpp" +#include "TextRenderer.hpp" +#include "Toast.hpp" #include "UIFeeder.hpp" #include diff --git a/src/Components/Modules/TextRenderer.cpp b/src/Components/Modules/TextRenderer.cpp index 6c677179..dfc6d6f6 100644 --- a/src/Components/Modules/TextRenderer.cpp +++ b/src/Components/Modules/TextRenderer.cpp @@ -1,4 +1,5 @@ #include +#include "TextRenderer.hpp" namespace Game { diff --git a/src/Components/Modules/Toast.cpp b/src/Components/Modules/Toast.cpp index 80df444a..78c78ca0 100644 --- a/src/Components/Modules/Toast.cpp +++ b/src/Components/Modules/Toast.cpp @@ -1,5 +1,8 @@ #include +#include "Materials.hpp" +#include "Toast.hpp" + namespace Components { std::queue Toast::Queue; diff --git a/src/Components/Modules/Window.cpp b/src/Components/Modules/Window.cpp index 5ed7e497..395135dc 100644 --- a/src/Components/Modules/Window.cpp +++ b/src/Components/Modules/Window.cpp @@ -1,6 +1,7 @@ #include #include "FastFiles.hpp" +#include "Window.hpp" namespace Components { diff --git a/src/Steam/Interfaces/SteamUser.cpp b/src/Steam/Interfaces/SteamUser.cpp index 26f8ce43..46b42887 100644 --- a/src/Steam/Interfaces/SteamUser.cpp +++ b/src/Steam/Interfaces/SteamUser.cpp @@ -1,4 +1,5 @@ #include +#include "Components/Modules/Auth.hpp" STEAM_IGNORE_WARNINGS_START From ed059c280ac571ed54733d9bb436541e4b91d17b Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 19 Apr 2023 10:07:11 +0200 Subject: [PATCH 47/51] [Network]: Change code style (#942) --- src/Components/Modules/Network.cpp | 17 ----------- src/Components/Modules/Network.hpp | 2 -- src/Components/Modules/Security.cpp | 45 ++++++++++++++++++++--------- src/Components/Modules/Security.hpp | 16 +++++----- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 7ce68157..6e98e466 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -269,20 +269,6 @@ namespace Components } } - void Network::SV_ExecuteClientMessageStub(Game::client_t* client, Game::msg_t* msg) - { - if (client->reliableAcknowledge < 0) - { - 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"); - return; - } - - Utils::Hook::Call(0x414D40)(client, msg); - } - void Network::OnClientPacket(const std::string& command, const networkCallback& callback) { CL_Callbacks[Utils::String::ToLower(command)] = callback; @@ -366,9 +352,6 @@ namespace Components // Prevent recvfrom error spam Utils::Hook(0x46531A, PacketErrorCheck, HOOK_JUMP).install()->quick(); - - // Fix server freezer exploit - Utils::Hook(0x626996, SV_ExecuteClientMessageStub, HOOK_CALL).install()->quick(); // Handle client packets Utils::Hook(0x5AA703, CL_HandleCommandStub, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/Network.hpp b/src/Components/Modules/Network.hpp index 89e46bec..fcd8262a 100644 --- a/src/Components/Modules/Network.hpp +++ b/src/Components/Modules/Network.hpp @@ -83,8 +83,6 @@ namespace Components static void PacketErrorCheck(); - static void SV_ExecuteClientMessageStub(Game::client_t* client, Game::msg_t* msg); - static bool CL_HandleCommand(Game::netadr_t* address, const char* command, const Game::msg_t* message); static void CL_HandleCommandStub(); diff --git a/src/Components/Modules/Security.cpp b/src/Components/Modules/Security.cpp index e20a175c..eda2a36b 100644 --- a/src/Components/Modules/Security.cpp +++ b/src/Components/Modules/Security.cpp @@ -3,7 +3,7 @@ namespace Components { - int Security::MsgReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size) + int Security::Msg_ReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size) { static unsigned char buffer[0x8000]; @@ -16,7 +16,7 @@ namespace Components return size; } - int Security::MsgReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size) + int Security::Msg_ReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size) { static unsigned char buffer[0x100000]; @@ -29,7 +29,7 @@ namespace Components return size; } - int Security::SVCanReplaceServerCommand(Game::client_t* /*client*/, const char* /*cmd*/) + int Security::SV_CanReplaceServerCommand_Hk([[maybe_unused]] Game::client_t* client, [[maybe_unused]] const char* cmd) { // This is a fix copied from V2. As I don't have time to investigate, let's simply trust them return -1; @@ -40,7 +40,7 @@ namespace Components return std::min(std::atol(string), 18); } - void Security::SelectStringTableEntryInDvarStub() + void Security::SelectStringTableEntryInDvar_Stub() { Command::ClientParams params; @@ -76,7 +76,7 @@ namespace Components Game::CL_SelectStringTableEntryInDvar_f(); } - __declspec(naked) int Security::G_GetClientScore() + __declspec(naked) int Security::G_GetClientScore_Hk() { __asm { @@ -96,12 +96,12 @@ namespace Components } } - void Security::G_LogPrintfStub(const char* fmt) + void Security::G_LogPrintf_Stub(const char* fmt) { Game::G_LogPrintf("%s", fmt); } - void Security::NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message) + void Security::NET_DeferPacketToClient_Hk(Game::netadr_t* net_from, Game::msg_t* net_message) { assert(net_from); assert(net_message); @@ -121,12 +121,26 @@ namespace Components InterlockedIncrement(&Game::deferredQueue->send); } + void Security::SV_ExecuteClientMessage_Stub(Game::client_t* client, Game::msg_t* msg) + { + if ((client->reliableSequence - client->reliableAcknowledge) < 0) + { + 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; + Game::SV_DropClient(client, "EXE_LOSTRELIABLECOMMANDS", true); + return; + } + + Utils::Hook::Call(0x414D40)(client, msg); + } + Security::Security() { // Exploit fixes - Utils::Hook(0x414D92, MsgReadBitsCompressCheckSV, HOOK_CALL).install()->quick(); // SV_ExecuteClientCommands - Utils::Hook(0x4A9F56, MsgReadBitsCompressCheckCL, HOOK_CALL).install()->quick(); // CL_ParseServerMessage - Utils::Hook(0x407376, SVCanReplaceServerCommand, HOOK_CALL).install()->quick(); // SV_CanReplaceServerCommand + Utils::Hook(0x414D92, Msg_ReadBitsCompressCheckSV, HOOK_CALL).install()->quick(); // SV_ExecuteClientCommands + Utils::Hook(0x4A9F56, Msg_ReadBitsCompressCheckCL, HOOK_CALL).install()->quick(); // CL_ParseServerMessage + Utils::Hook(0x407376, SV_CanReplaceServerCommand_Hk, HOOK_CALL).install()->quick(); // SV_CanReplaceServerCommand Utils::Hook::Set(0x412370, 0xC3); // SV_SteamAuthClient Utils::Hook::Set(0x5A8C70, 0xC3); // CL_HandleRelayPacket @@ -134,20 +148,23 @@ namespace Components Utils::Hook::Nop(0x41698E, 5); // Disable Svcmd_EntityList_f // Patch selectStringTableEntryInDvar - Utils::Hook::Set(0x405959, SelectStringTableEntryInDvarStub); + Utils::Hook::Set(0x405959, SelectStringTableEntryInDvar_Stub); // Patch G_GetClientScore for uninitialized game - Utils::Hook(0x469AC0, G_GetClientScore, HOOK_JUMP).install()->quick(); + Utils::Hook(0x469AC0, G_GetClientScore_Hk, HOOK_JUMP).install()->quick(); // Requests can be malicious Utils::Hook(0x5B67ED, AtolAdjustPlayerLimit, HOOK_CALL).install()->quick(); // PartyHost_HandleJoinPartyRequest // Patch unsecure call to G_LogPrint inside GScr_LogPrint // This function is unsafe because IW devs forgot to G_LogPrintf("%s", fmt) - Utils::Hook(0x5F70B5, G_LogPrintfStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5F70B5, G_LogPrintf_Stub, HOOK_CALL).install()->quick(); // Fix packets causing buffer overflow - Utils::Hook(0x6267E3, NET_DeferPacketToClientStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x6267E3, NET_DeferPacketToClient_Hk, HOOK_CALL).install()->quick(); + + // Fix server freezer exploit + Utils::Hook(0x626996, SV_ExecuteClientMessage_Stub, HOOK_CALL).install()->quick(); // The client can fake the info string Utils::Hook::Set(0x460F6D, 0xEB); // SV_DirectConnect diff --git a/src/Components/Modules/Security.hpp b/src/Components/Modules/Security.hpp index 081cbd90..d70d8537 100644 --- a/src/Components/Modules/Security.hpp +++ b/src/Components/Modules/Security.hpp @@ -7,20 +7,22 @@ namespace Components public: Security(); - static int MsgReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size); - static int MsgReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size); + static int Msg_ReadBitsCompressCheckSV(const unsigned char* from, unsigned char* to, int size); + static int Msg_ReadBitsCompressCheckCL(const unsigned char* from, unsigned char* to, int size); private: - static int SVCanReplaceServerCommand(Game::client_t* client, const char* cmd); + static int SV_CanReplaceServerCommand_Hk(Game::client_t* client, const char* cmd); static long AtolAdjustPlayerLimit(const char* string); - static void SelectStringTableEntryInDvarStub(); + static void SelectStringTableEntryInDvar_Stub(); - static int G_GetClientScore(); + static int G_GetClientScore_Hk(); - static void G_LogPrintfStub(const char* fmt); + static void G_LogPrintf_Stub(const char* fmt); - static void NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message); + static void NET_DeferPacketToClient_Hk(Game::netadr_t* net_from, Game::msg_t* net_message); + + static void SV_ExecuteClientMessage_Stub(Game::client_t* client, Game::msg_t* msg); }; } From 70be263918b7228e40c7c3b455433096619b5a24 Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 19 Apr 2023 15:53:07 +0200 Subject: [PATCH 48/51] [Bots]: I misread std::string docs (#943) --- src/Components/Modules/Bots.cpp | 19 ++++--------------- src/Components/Modules/Bots.hpp | 1 - 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 8b0f13df..a598c4ef 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -6,8 +6,8 @@ #include "GSC/Script.hpp" // From Quake-III -#define ANGLE2SHORT(x) ((int)((x) * (USHRT_MAX + 1) / 360.0f) & USHRT_MAX) -#define SHORT2ANGLE(x) ((x)* (360.0f / (USHRT_MAX + 1))) +#define ANGLE2SHORT(x) ((int)((x) * (USHRT_MAX + 1) / 360.0f) & USHRT_MAX) +#define SHORT2ANGLE(x) ((x)* (360.0f / (USHRT_MAX + 1))) namespace Components { @@ -61,16 +61,6 @@ namespace Components std::ranges::shuffle(BotNames, gen); } - std::string Bots::TruncBotString(const std::string& input, const std::size_t length) - { - if (length > input.size()) - { - return input; - } - - return input.substr(length); - } - void Bots::LoadBotNames() { FileSystem::File bots("bots.txt"); @@ -102,14 +92,13 @@ namespace Components // Only start copying over from non-null characters (otherwise it can be "<=") if ((pos + 1) < entry.size()) { - clanAbbrev = entry.substr(pos + 1); + clanAbbrev = entry.substr(pos + 1, ClanTags::MAX_CLAN_NAME_LENGTH - 1); } entry = entry.substr(0, pos); } - entry = TruncBotString(entry, MAX_NAME_LENGTH - 1); - clanAbbrev = TruncBotString(clanAbbrev, ClanTags::MAX_CLAN_NAME_LENGTH - 1); + entry = entry.substr(0, MAX_NAME_LENGTH - 1); BotNames.emplace_back(entry, clanAbbrev); } diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index 23d253f3..9d7526e1 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -17,7 +17,6 @@ namespace Components static const Game::dvar_t* sv_replaceBots; static void RandomizeBotNames(); - static std::string TruncBotString(const std::string& input, std::size_t length); static void LoadBotNames(); static int BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port); From a39febed668c0910ee1712009b8f0d142b3732df Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 19 Apr 2023 19:53:29 +0200 Subject: [PATCH 49/51] [General]: New versioning system (#944) --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ premake5.lua | 6 +----- src/Components/Modules/Branding.cpp | 18 ++++++++---------- src/Components/Modules/Console.cpp | 6 +++--- src/Components/Modules/News.cpp | 2 -- src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/ServerInfo.cpp | 2 +- src/Components/Modules/ServerList.cpp | 8 +------- src/Components/Modules/Singleton.cpp | 2 +- src/Components/Modules/ZoneBuilder.cpp | 2 +- src/Resource.rc | 16 ++++++++-------- 11 files changed, 51 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c35b7fb2..6944b407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,36 @@ 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/). +## r4190 - 2023-04-19 + +### Added + +- Add `LogString` GSC function (#895) +- Add `LogString` GSC method (#895) +- Add `sv_replaceTestClients` Dvar (#930) + +### Changed + +- `sv_mapRotationCurrent` supports `exec` directive for executing cfg scripts from the `game_settings` folder + +### Fixed + +- `sv_privatePassword` will work as intended (#908) + +### Known issues + +- Sound issue fix is experimental as the bug is not fully understood. + ## [0.7.9] - 2023-03-31 ### Added + - Game scripts can be loaded from the `scripts/mp`, `scripts/mp/` and `scripts/mp/` folders (#859) - Add `ReadStream` GSC function (#862) - Add `IString` GSC function (#877) ### Changed + - Test Clients will no longer receive names from the Xlabs Patreon website. The old behaviour was restored (#852) - Enabled `OpenFile` GSC function (#862) - Enabled `CloseFile` GSC function (#862) @@ -20,6 +42,7 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0. - `CastFloat` GSC function was renamed to `Float` (#880) ### Fixed + - Fix bug where knife lounges would not work with a gamepad (#848) - Fix rare RCon crash (#861) - Fix bug where `sv_RandomBotNames` stopped working (#876) @@ -32,6 +55,7 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0. ## [0.7.8] - 2023-03-17 ### Added + - Clients can unprotect "saved" Dvars using the command line argument `-unprotect-dvars` (#694) - Clients can protect all Dvars from being modified by the server using the command line argument `-protect-dvars` (#823) - Add helpful information to script-related errors (#721) @@ -54,6 +78,7 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0. - Add new map porting utility tool that makes the map porting process between CoD8 to CoD6 easy ### Changed + - Servers can no longer modify client Dvars that are saved in the client's config (#694) - `banClient` and `muteClient` server commands do not apply to bots anymore (#730) - Remove `zb_prefer_disk_assets` Dvar (#772) @@ -61,6 +86,7 @@ The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0. - Test Clients will receive names from the Xlabs Patreon website in addition to the names from the bots.txt file (#771) ### Fixed + - Fix bug where`reloadmenus` command would not free resources used by custom menus (#740) - Fix bug where demo playback would stop when opening a laptop based killstreak (#699) - Fix bug where mod download speed was inexplicably slow (#707) diff --git a/premake5.lua b/premake5.lua index a311c929..f81f657a 100644 --- a/premake5.lua +++ b/premake5.lua @@ -158,15 +158,11 @@ newaction { versionHeader:write("#define GIT_DIRTY " .. revDirty .. "\n") versionHeader:write("#define GIT_TAG " .. cstrquote(tagName) .. "\n") versionHeader:write("\n") - versionHeader:write("// Legacy definitions (needed for update check)\n") + versionHeader:write("// New revision definition. Will be used from now on\n") versionHeader:write("#define REVISION " .. revNumber .. "\n") versionHeader:write("\n") - versionHeader:write("// Version transformed for RC files\n") - versionHeader:write("#define VERSION_RC " .. table.concat(vertonumarr(tagName, revNumber), ",") .. "\n") - versionHeader:write("\n") versionHeader:write("// Alias definitions\n") versionHeader:write("#define VERSION GIT_DESCRIBE\n") - versionHeader:write("#define SHORTVERSION " .. cstrquote(table.concat(vertonumarr(tagName, revNumber), ".")) .. "\n") versionHeader:close() local versionHeader = assert(io.open(wks.location .. "/src/version.hpp", "w")) versionHeader:write("/*\n") diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index 0c293357..e95e32bb 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -48,16 +48,14 @@ namespace Components const char* Branding::GetBuildNumber() { - return SHORTVERSION " latest " __DATE__ " " __TIME__; + return VERSION " latest " __DATE__ " " __TIME__; } const char* Branding::GetVersionString() { // IW4x is technically a beta - const auto* result = Utils::String::VA("%s %s build %s %s", + return Utils::String::VA("%s %s build %s %s", BUILD_TYPE, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast(0x7170A0)); - - return result; } void Branding::Dvar_SetVersionString(const Game::dvar_t* dvar, [[maybe_unused]] const char* value) @@ -100,14 +98,14 @@ namespace Components Branding::RegisterBrandingDvars(); // UI version string - Utils::Hook::Set(0x43F73B, "IW4x: " VERSION); + Utils::Hook::Set(0x43F73B, "IW4x - " GIT_TAG); // Short version dvar - Utils::Hook::Set(0x60BD91, SHORTVERSION); + Utils::Hook::Set(0x60BD91, GIT_TAG); // Com_Init_Try_Block_Function Utils::Hook::Set(0x60BAF4, BUILD_TYPE); - Utils::Hook::Set(0x60BAEf, SHORTVERSION); + Utils::Hook::Set(0x60BAEf, GIT_TAG); Utils::Hook::Set(0x60BAE5, __DATE__); // G_InitGame @@ -132,15 +130,15 @@ namespace Components // Console title if (ZoneBuilder::IsEnabled()) { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): ZoneBuilder"); + Utils::Hook::Set(0x4289E8, "IW4x (" GIT_TAG "): ZoneBuilder"); } else if (Dedicated::IsEnabled()) { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Dedicated"); + Utils::Hook::Set(0x4289E8, "IW4x (" GIT_TAG "): Dedicated"); } else { - Utils::Hook::Set(0x4289E8, "IW4x (" VERSION "): Console"); + Utils::Hook::Set(0x4289E8, "IW4x (" GIT_TAG "): Console"); } } } diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index 56acd131..0a91504d 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -96,14 +96,14 @@ namespace Components } else if (IsWindow(GetWindow()) != FALSE) { - SetWindowTextA(GetWindow(), Utils::String::VA("IW4x(" VERSION ") : %s", hostname.data())); + SetWindowTextA(GetWindow(), Utils::String::VA("IW4x(" GIT_TAG ") : %s", hostname.data())); } } void Console::ShowPrompt() { wattron(InputWindow, COLOR_PAIR(10) | A_BOLD); - wprintw(InputWindow, "%s> ", VERSION); + wprintw(InputWindow, "%s> ", GIT_TAG); } void Console::RefreshOutput() @@ -860,7 +860,7 @@ namespace Components AssertOffset(Game::clientUIActive_t, keyCatchers, 0x9B0); // Console '%s: %s> ' string - Utils::Hook::Set(0x5A44B4, "IW4x MP: " VERSION "> "); + Utils::Hook::Set(0x5A44B4, "IW4x_MP: " GIT_TAG "> "); // Patch console color static float consoleColor[] = { 0.70f, 1.00f, 0.00f, 1.00f }; diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index e79ead0d..39a4b4e6 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -2,8 +2,6 @@ #include "Changelog.hpp" #include "News.hpp" -#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 efe579e0..c70231ac 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -386,7 +386,7 @@ namespace Components 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("version", GIT_TAG); info.set("checksum", std::to_string(Game::Sys_Milliseconds())); info.set("mapname", Dvar::Var("mapname").get()); info.set("isPrivate", *password ? "1" : "0"); diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index dfae403b..b342a142 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -149,7 +149,7 @@ namespace Components info.set("gamename", "IW4"); info.set("sv_maxclients", std::to_string(maxClientCount)); info.set("protocol", std::to_string(PROTOCOL)); - info.set("shortversion", SHORTVERSION); + info.set("version", GIT_TAG); info.set("version", (*Game::version)->current.string); info.set("mapname", (*Game::sv_mapname)->current.string); info.set("isPrivate", *password ? "1" : "0"); diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index fa7b0e68..cca7be6e 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -9,8 +9,6 @@ #include "Toast.hpp" #include "UIFeeder.hpp" -#include - namespace Components { bool ServerList::SortAsc = true; @@ -587,11 +585,7 @@ namespace Components } } - if (info.get("gamename") == "IW4"s && server.matchType -#if !defined(DEBUG) && defined(VERSION_FILTER) - && CompareVersion(server.shortversion, SHORTVERSION) -#endif - ) + if (info.get("gamename") == "IW4"s && server.matchType) { auto* lList = GetList(); if (lList) diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index 218e6825..5b419c0e 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -18,7 +18,7 @@ namespace Components if (Flags::HasFlag("version")) { printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); - printf("%d\n", REVISION); + printf("Revision: %i\n", REVISION); ExitProcess(EXIT_SUCCESS); } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index c1b7a133..be5813b7 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -978,7 +978,7 @@ namespace Components } Logger::Print(" --------------------------------------------------------------------------------\n"); - Logger::Print(" IW4x ZoneBuilder ({})\n", VERSION); + 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"); diff --git a/src/Resource.rc b/src/Resource.rc index cda9e955..9936e4b1 100644 --- a/src/Resource.rc +++ b/src/Resource.rc @@ -10,7 +10,7 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "windows.h" +#include "Windows.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -29,7 +29,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 1 TEXTINCLUDE BEGIN - "#include ""windows.h""\r\n" + "#include ""Windows.h""\r\n" "\0" END @@ -47,8 +47,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_RC - PRODUCTVERSION VERSION_RC + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -63,18 +63,18 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "CompanyName", "IW4x" + VALUE "CompanyName", "XLabsProject" #ifdef _DEBUG VALUE "FileDescription", "IW4 client modification (DEBUG)" #else VALUE "FileDescription", "IW4 client modification" #endif - VALUE "FileVersion", SHORTVERSION + VALUE "FileVersion", GIT_TAG VALUE "InternalName", "iw4x" - VALUE "LegalCopyright", "Copyright 2022 The IW4x Team. All rights reserved." + VALUE "LegalCopyright", "Copyright 2023 The XLabsProject Team. All rights reserved." VALUE "OriginalFilename", "iw4x.dll" VALUE "ProductName", "IW4x" - VALUE "ProductVersion", SHORTVERSION + VALUE "ProductVersion", GIT_TAG END END BLOCK "VarFileInfo" From 0404590b89c70b3dc9cfe909040b76636f08f1e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:59:11 +0000 Subject: [PATCH 50/51] Bump deps/zlib from `6658868` to `b8a8373` Bumps [deps/zlib](https://github.com/madler/zlib) from `6658868` to `b8a8373`. - [Release notes](https://github.com/madler/zlib/releases) - [Commits](https://github.com/madler/zlib/compare/66588683b36042154ad35140bf9fcbb60c5d573c...b8a8373ec195c8d286fe7e81e78b4a6d31bd859f) --- 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 66588683..b8a8373e 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit 66588683b36042154ad35140bf9fcbb60c5d573c +Subproject commit b8a8373ec195c8d286fe7e81e78b4a6d31bd859f From 90382ca5d45892d6d84e8b980ad9df58f57066f0 Mon Sep 17 00:00:00 2001 From: Edo Date: Wed, 19 Apr 2023 20:31:56 +0200 Subject: [PATCH 51/51] [CI]: Update draft-new-release.yml (#946) --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 1c4b90e3..9609dc02 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -18,7 +18,7 @@ jobs: id: normalize_version run: | version="${{ github.event.inputs.version }}" - version="v${version#v}" + version="r${version#v}" echo "::set-output name=version::$version" # Set up committer info and GPG key