From b195d96abbb5f7b3e16b33ef13839953cb19d42f Mon Sep 17 00:00:00 2001 From: Edo Date: Tue, 29 Nov 2022 14:18:10 +0000 Subject: [PATCH] [GSC]: Script aliases (#610) --- src/Components/Modules/Bots.cpp | 44 +++--- src/Components/Modules/Debug.cpp | 2 +- src/Components/Modules/Dvar.cpp | 3 +- src/Components/Modules/GSC/Script.cpp | 74 +++++++--- src/Components/Modules/GSC/Script.hpp | 10 +- .../Modules/GSC/ScriptExtension.cpp | 30 ----- .../Modules/GSC/ScriptExtension.hpp | 1 - src/Components/Modules/GSC/ScriptPatches.cpp | 30 +++++ src/Components/Modules/GSC/ScriptPatches.hpp | 2 + src/Components/Modules/Logger.cpp | 126 +++++++++--------- src/Components/Modules/Node.cpp | 2 +- src/Components/Modules/PlayerName.cpp | 2 +- src/Components/Modules/RCon.cpp | 2 +- src/STDInclude.hpp | 25 ++-- src/Utils/String.cpp | 4 +- src/Utils/String.hpp | 62 ++++++--- 16 files changed, 243 insertions(+), 176 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 9f9c08bb..75d30db1 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -7,10 +7,10 @@ namespace Components struct BotMovementInfo { - int buttons; // Actions - int8_t forward; - int8_t right; - uint16_t weapon; + std::int32_t buttons; // Actions + std::int8_t forward; + std::int8_t right; + std::uint16_t weapon; bool active; }; @@ -19,7 +19,7 @@ namespace Components struct BotAction { std::string action; - int key; + std::int32_t key; }; static const BotAction BotActions[] = @@ -47,7 +47,7 @@ namespace Components static bool loadedNames = false; // Load file only once const char* botName; - if (Bots::BotNames.empty() && !loadedNames) + if (BotNames.empty() && !loadedNames) { FileSystem::File bots("bots.txt"); loadedNames = true; @@ -59,20 +59,20 @@ namespace Components for (auto& name : names) { Utils::String::Replace(name, "\r", ""); - name = Utils::String::Trim(name); + Utils::String::Trim(name); if (!name.empty()) { - Bots::BotNames.push_back(name); + BotNames.push_back(name); } } } } - if (!Bots::BotNames.empty()) + if (!BotNames.empty()) { - botId %= Bots::BotNames.size(); - botName = Bots::BotNames[botId++].data(); + botId %= BotNames.size(); + botName = BotNames[botId++].data(); } else { @@ -125,8 +125,7 @@ namespace Components void Bots::AddMethods() { - Script::AddMethod("IsBot", Bots::GScr_isTestClient); // Usage: self IsBot(); - Script::AddMethod("IsTestClient", Bots::GScr_isTestClient); // Usage: self IsTestClient(); + Script::AddMethMultiple(GScr_isTestClient, false, {"IsTestClient", "IsBot"}); // Usage: self IsTestClient(); Script::AddMethod("BotStop", [](Game::scr_entref_t entref) // Usage: BotStop(); { @@ -240,7 +239,8 @@ namespace Components return; } - Game::usercmd_s userCmd = {0}; + Game::usercmd_s userCmd; + ZeroMemory(&userCmd, sizeof(Game::usercmd_s)); userCmd.serverTime = *Game::svs_time; @@ -260,7 +260,7 @@ namespace Components pushad push edi - call Bots::BotAiAction + call BotAiAction add esp, 4 popad @@ -284,7 +284,7 @@ namespace Components push [esp + 0x20 + 0x8] push [esp + 0x20 + 0x8] - call Bots::G_SelectWeaponIndex + call G_SelectWeaponIndex add esp, 0x8 popad @@ -307,12 +307,12 @@ namespace Components Utils::Hook::Set(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\""); // Intercept sprintf for the connect string - Utils::Hook(0x48ADAB, Bots::BuildConnectString, HOOK_CALL).install()->quick(); + Utils::Hook(0x48ADAB, BuildConnectString, HOOK_CALL).install()->quick(); - Utils::Hook(0x627021, Bots::SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x627241, Bots::SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x627021, SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x627241, SV_BotUserMove_Hk, HOOK_CALL).install()->quick(); - Utils::Hook(0x441B80, Bots::G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); // Reset BotMovementInfo.active when client is dropped Events::OnClientDisconnect([](const int clientNum) @@ -365,10 +365,10 @@ namespace Components Toast::Show("cardicon_headshot", "^2Success", Utils::String::VA("Spawning %d %s...", count, (count == 1 ? "bot" : "bots")), 3000); Logger::Debug("Spawning {} {}", count, (count == 1 ? "bot" : "bots")); - Bots::Spawn(count); + Spawn(count); }); - Bots::AddMethods(); + AddMethods(); // In case a loaded mod didn't call "BotStop" before the VM shutdown Events::OnVMShutdown([] diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index c0fb92ae..1347d95f 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -318,7 +318,7 @@ namespace Components return; } - if (strncmp(BugName->current.string, "bug", 3) != 0) + if (std::strncmp(BugName->current.string, "bug", 3) != 0) { Game::Dvar_SetString(BugName, "bug0"); return; diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index a01a6314..aaa34ca9 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -229,7 +229,8 @@ namespace Components // Don't perform any checks if name didn't change if (name == lastValidName) return; - std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(Utils::String::Trim(name))); + Utils::String::Trim(name); + std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(name)); if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{')) { Logger::PrintError(Game::CON_CHANNEL_ERROR, "Username '{}' is invalid. It must at least be 3 characters long and not appear empty!\n", name); diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 45bbc432..30126f84 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -3,8 +3,8 @@ namespace Components { - std::unordered_map Script::CustomScrFunctions; - std::unordered_map Script::CustomScrMethods; + std::vector Script::CustomScrFunctions; + std::vector Script::CustomScrMethods; std::string Script::ScriptName; std::vector Script::ScriptNameStack; @@ -278,43 +278,74 @@ namespace Components Game::GScr_LoadGameTypeScript(); } - void Script::AddFunction(const std::string& name, Game::BuiltinFunction func, bool type) + void Script::AddFunction(const std::string& name, const Game::BuiltinFunction func, const bool type) { ScriptFunction toAdd; toAdd.actionFunc = func; toAdd.type = type; + toAdd.aliases.push_back({Utils::String::ToLower(name)}); - CustomScrFunctions.insert_or_assign(Utils::String::ToLower(name), toAdd); + CustomScrFunctions.emplace_back(toAdd); } - void Script::AddMethod(const std::string& name, Game::BuiltinMethod func, bool type) + void Script::AddMethod(const std::string& name, const Game::BuiltinMethod func, const bool type) { ScriptMethod toAdd; toAdd.actionFunc = func; toAdd.type = type; + toAdd.aliases.push_back({Utils::String::ToLower(name)}); - CustomScrMethods.insert_or_assign(Utils::String::ToLower(name), toAdd); + CustomScrMethods.emplace_back(toAdd); + } + + void Script::AddFuncMultiple(Game::BuiltinFunction func, bool type, scriptNames aliases) + { + ScriptFunction toAdd; + auto aliasesToAdd = Utils::String::ApplyToLower(aliases); + + toAdd.actionFunc = func; + toAdd.type = type; + toAdd.aliases = std::move(aliasesToAdd); + + CustomScrFunctions.emplace_back(toAdd); + } + + void Script::AddMethMultiple(Game::BuiltinMethod func, bool type, scriptNames aliases) + { + ScriptMethod toAdd; + auto aliasesToAdd = Utils::String::ApplyToLower(aliases); + + toAdd.actionFunc = func; + toAdd.type = type; + toAdd.aliases = std::move(aliasesToAdd); + + CustomScrMethods.emplace_back(toAdd); } Game::BuiltinFunction Script::BuiltIn_GetFunctionStub(const char** pName, int* type) { if (pName != nullptr) { - // If no function was found let's call game's function - if (const auto itr = CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != CustomScrFunctions.end()) + const auto name = Utils::String::ToLower(*pName); + for (const auto& func : CustomScrFunctions) { - *type = itr->second.type; - return itr->second.actionFunc; - } + if (std::ranges::find(func.aliases, name) != func.aliases.end()) + { + *type = func.type; + return func.actionFunc; + } + } } else { - for (const auto& [name, builtin] : CustomScrFunctions) + for (const auto& func : CustomScrFunctions) { - Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); + const auto& name = func.aliases[0]; + Game::Scr_RegisterFunction(reinterpret_cast(func.actionFunc), name.data()); } } + // If no function was found let's call game's function return Utils::Hook::Call(0x5FA2B0)(pName, type); // BuiltIn_GetFunction } @@ -322,21 +353,26 @@ namespace Components { if (pName != nullptr) { - // If no method was found let's call game's function - if (const auto itr = CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != CustomScrMethods.end()) + const auto name = Utils::String::ToLower(*pName); + for (const auto& meth : CustomScrMethods) { - *type = itr->second.type; - return itr->second.actionFunc; + if (std::ranges::find(meth.aliases, name) != meth.aliases.end()) + { + *type = meth.type; + return meth.actionFunc; + } } } else { - for (const auto& [name, builtin] : CustomScrMethods) + for (const auto& meth : CustomScrMethods) { - Game::Scr_RegisterFunction(reinterpret_cast(builtin.actionFunc), name.data()); + const auto& name = meth.aliases[0]; + Game::Scr_RegisterFunction(reinterpret_cast(meth.actionFunc), name.data()); } } + // If no method was found let's call game's function return Utils::Hook::Call(0x5FA360)(pName, type); // Player_GetMethod } diff --git a/src/Components/Modules/GSC/Script.hpp b/src/Components/Modules/GSC/Script.hpp index 8c4742ba..c3a27a00 100644 --- a/src/Components/Modules/GSC/Script.hpp +++ b/src/Components/Modules/GSC/Script.hpp @@ -7,9 +7,13 @@ namespace Components public: Script(); + using scriptNames = std::vector; static void AddFunction(const std::string& name, Game::BuiltinFunction func, bool type = false); static void AddMethod(const std::string& name, Game::BuiltinMethod func, bool type = false); + static void AddFuncMultiple(Game::BuiltinFunction func, bool type, scriptNames); + static void AddMethMultiple(Game::BuiltinMethod func, bool type, scriptNames); + static Game::client_t* GetClient(const Game::gentity_t* gentity); static const char* GetCodePosForParam(int index); @@ -40,16 +44,18 @@ namespace Components { Game::BuiltinFunction actionFunc; bool type; + scriptNames aliases; }; struct ScriptMethod { Game::BuiltinMethod actionFunc; bool type; + scriptNames aliases; }; - static std::unordered_map CustomScrFunctions; - static std::unordered_map CustomScrMethods; + static std::vector CustomScrFunctions; + static std::vector CustomScrMethods; static std::string ScriptName; static std::vector ScriptNameStack; diff --git a/src/Components/Modules/GSC/ScriptExtension.cpp b/src/Components/Modules/GSC/ScriptExtension.cpp index 94e08aa3..0b30a4f0 100644 --- a/src/Components/Modules/GSC/ScriptExtension.cpp +++ b/src/Components/Modules/GSC/ScriptExtension.cpp @@ -273,30 +273,6 @@ namespace Components }); } - void ScriptExtension::Scr_TableLookupIStringByRow() - { - if (Game::Scr_GetNumParam() < 3) - { - Game::Scr_Error("USAGE: tableLookupIStringByRow( filename, rowNum, returnValueColumnNum )\n"); - return; - } - - const auto* fileName = Game::Scr_GetString(0); - const auto rowNum = Game::Scr_GetInt(1); - const auto returnValueColumnNum = Game::Scr_GetInt(2); - - const auto* table = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, fileName).stringTable; - - if (table == nullptr) - { - Game::Scr_ParamError(0, Utils::String::VA("%s does not exist\n", fileName)); - return; - } - - const auto* value = Game::StringTable_GetColumnValueForRow(table, rowNum, returnValueColumnNum); - Game::Scr_AddIString(value); - } - void ScriptExtension::AddEntityFields() { AddEntityField("entityflags", Game::F_INT, @@ -330,16 +306,10 @@ namespace Components AddEntityFields(); AddClientFields(); - // Correct builtin function pointer - Utils::Hook::Set(0x79A90C, Scr_TableLookupIStringByRow); - Utils::Hook(0x4EC721, GScr_AddFieldsForEntityStub, HOOK_CALL).install()->quick(); // GScr_AddFieldsForEntity Utils::Hook(0x41BED2, Scr_SetObjectFieldStub, HOOK_CALL).install()->quick(); // SetEntityFieldValue Utils::Hook(0x5FBF01, Scr_SetClientFieldStub, HOOK_CALL).install()->quick(); // Scr_SetObjectField Utils::Hook(0x4FF413, Scr_GetEntityFieldStub, HOOK_CALL).install()->quick(); // Scr_GetObjectField - - // Fix format string in Scr_RandomFloatRange - Utils::Hook::Set(0x5F10C6, "Scr_RandomFloatRange parms: %f %f "); } } diff --git a/src/Components/Modules/GSC/ScriptExtension.hpp b/src/Components/Modules/GSC/ScriptExtension.hpp index cc6cb694..c153f24c 100644 --- a/src/Components/Modules/GSC/ScriptExtension.hpp +++ b/src/Components/Modules/GSC/ScriptExtension.hpp @@ -27,6 +27,5 @@ namespace Components static void AddMethods(); static void AddEntityFields(); static void AddClientFields(); - static void Scr_TableLookupIStringByRow(); }; } diff --git a/src/Components/Modules/GSC/ScriptPatches.cpp b/src/Components/Modules/GSC/ScriptPatches.cpp index 4e7843d8..3c2b6197 100644 --- a/src/Components/Modules/GSC/ScriptPatches.cpp +++ b/src/Components/Modules/GSC/ScriptPatches.cpp @@ -20,8 +20,38 @@ namespace Components return &Game::g_hudelems[entref.entnum]; } + void ScriptPatches::Scr_TableLookupIStringByRow_Hk() + { + if (Game::Scr_GetNumParam() < 3) + { + Game::Scr_Error("USAGE: tableLookupIStringByRow( filename, rowNum, returnValueColumnNum )\n"); + return; + } + + const auto* fileName = Game::Scr_GetString(0); + const auto rowNum = Game::Scr_GetInt(1); + const auto returnValueColumnNum = Game::Scr_GetInt(2); + + const auto* table = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_STRINGTABLE, fileName).stringTable; + + if (table == nullptr) + { + Game::Scr_ParamError(0, Utils::String::VA("%s does not exist\n", fileName)); + return; + } + + const auto* value = Game::StringTable_GetColumnValueForRow(table, rowNum, returnValueColumnNum); + Game::Scr_AddIString(value); + } + ScriptPatches::ScriptPatches() { + // Fix format string in Scr_RandomFloatRange + Utils::Hook::Set(0x5F10C6, "Scr_RandomFloatRange parms: %f %f "); + + // Correct builtin function pointer + Utils::Hook::Set(0x79A90C, Scr_TableLookupIStringByRow_Hk); + Script::AddMethod("ClearHudText", [](Game::scr_entref_t entref) -> void { auto* hud = HECmd_GetHudElem(entref); diff --git a/src/Components/Modules/GSC/ScriptPatches.hpp b/src/Components/Modules/GSC/ScriptPatches.hpp index cf4787d0..6d69a2fd 100644 --- a/src/Components/Modules/GSC/ScriptPatches.hpp +++ b/src/Components/Modules/GSC/ScriptPatches.hpp @@ -9,5 +9,7 @@ namespace Components private: static Game::game_hudelem_s* HECmd_GetHudElem(Game::scr_entref_t entref); + + static void Scr_TableLookupIStringByRow_Hk(); }; } diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 7d24c198..9b9e8257 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -22,7 +22,7 @@ namespace Components _vsnprintf_s(buf, _TRUNCATE, message, va); va_end(va); - Logger::MessagePrint(channel, {buf}); + MessagePrint(channel, {buf}); } void Logger::MessagePrint(const int channel, const std::string& msg) @@ -42,14 +42,14 @@ namespace Components return; } - if (!Logger::IsConsoleReady()) + if (!IsConsoleReady()) { OutputDebugStringA(out.data()); } if (!Game::Sys_IsMainThread()) { - Logger::EnqueueMessage(msg); + EnqueueMessage(msg); } else { @@ -67,14 +67,14 @@ namespace Components const auto out = std::format("^2{}\n", msg); #endif - Logger::MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); + MessagePrint(Game::CON_CHANNEL_DONT_FILTER, out); } void Logger::PrintInternal(int channel, std::string_view fmt, std::format_args&& args) { const auto msg = std::vformat(fmt, args); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); } void Logger::ErrorInternal(const Game::errorParm_t error, const std::string_view fmt, std::format_args&& args) @@ -92,7 +92,7 @@ namespace Components const auto msg = "^1Error: " + std::vformat(fmt, args); ++(*Game::com_errorPrintsCount); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); if (*Game::cls_uiStarted != 0 && (*Game::com_fixedConsolePosition == 0)) { @@ -104,36 +104,36 @@ namespace Components { const auto msg = "^3" + std::vformat(fmt, args); - Logger::MessagePrint(channel, msg); + MessagePrint(channel, msg); } void Logger::Frame() { - std::unique_lock _(Logger::MessageMutex); + std::unique_lock _(MessageMutex); - for (auto i = Logger::MessageQueue.begin(); i != Logger::MessageQueue.end();) + for (auto i = MessageQueue.begin(); i != MessageQueue.end();) { Game::Com_PrintMessage(Game::CON_CHANNEL_DONT_FILTER, i->data(), 0); - if (!Logger::IsConsoleReady()) + if (!IsConsoleReady()) { OutputDebugStringA(i->data()); } - i = Logger::MessageQueue.erase(i); + i = MessageQueue.erase(i); } } void Logger::PipeOutput(const std::function& callback) { - Logger::PipeCallback = callback; + PipeCallback = callback; } void Logger::PrintMessagePipe(const char* data) { - if (Logger::PipeCallback) + if (PipeCallback) { - Logger::PipeCallback(data); + PipeCallback(data); } } @@ -144,7 +144,7 @@ namespace Components return; } - for (const auto& addr : Logger::LoggingAddresses[gLog & 1]) + for (const auto& addr : LoggingAddresses[gLog & 1]) { Network::SendCommand(addr, "print", data); } @@ -169,20 +169,20 @@ namespace Components } // Allow the network log to run even if logFile was not opened - Logger::NetworkLog(string, true); + NetworkLog(string, true); } __declspec(naked) void Logger::PrintMessage_Stub() { __asm { - mov eax, Logger::PipeCallback + mov eax, PipeCallback test eax, eax jz returnPrint pushad push [esp + 28h] - call Logger::PrintMessagePipe + call PrintMessagePipe add esp, 4h popad retn @@ -191,7 +191,7 @@ namespace Components pushad push 0 push [esp + 2Ch] - call Logger::NetworkLog + call NetworkLog add esp, 8h popad @@ -205,8 +205,8 @@ namespace Components void Logger::EnqueueMessage(const std::string& message) { - std::unique_lock _(Logger::MessageMutex); - Logger::MessageQueue.push_back(message); + std::unique_lock _(MessageMutex); + MessageQueue.push_back(message); } void Logger::RedirectOSPath(const char* file, char* folder) @@ -232,7 +232,7 @@ namespace Components push [esp + 28h] push [esp + 30h] - call Logger::RedirectOSPath + call RedirectOSPath add esp, 8h @@ -256,9 +256,9 @@ namespace Components Network::Address addr(params->get(1)); - if (std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr) == Logger::LoggingAddresses[0].end()) + if (std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr) == LoggingAddresses[0].end()) { - Logger::LoggingAddresses[0].push_back(addr); + LoggingAddresses[0].push_back(addr); } }); @@ -267,37 +267,37 @@ namespace Components if (params->size() < 2) return; const auto num = atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[0].size()) + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[0].size()) { auto addr = Logger::LoggingAddresses[0].begin() + num; - Logger::Print("Address {} removed\n", addr->getString()); - Logger::LoggingAddresses[0].erase(addr); + Print("Address {} removed\n", addr->getString()); + LoggingAddresses[0].erase(addr); } else { Network::Address addr(params->get(1)); - const auto i = std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr); - if (i != Logger::LoggingAddresses[0].end()) + const auto i = std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr); + if (i != LoggingAddresses[0].end()) { - Logger::LoggingAddresses[0].erase(i); - Logger::Print("Address {} removed\n", addr.getString()); + LoggingAddresses[0].erase(i); + Print("Address {} removed\n", addr.getString()); } else { - Logger::Print("Address {} not found!\n", addr.getString()); + Print("Address {} not found!\n", addr.getString()); } } }); - Command::AddSV("log_list", [](Command::Params*) + Command::AddSV("log_list", []([[maybe_unused]] Command::Params* params) { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); + Print("# ID: Address\n"); + Print("-------------\n"); - for (unsigned int i = 0; i < Logger::LoggingAddresses[0].size(); ++i) + for (unsigned int i = 0; i < LoggingAddresses[0].size(); ++i) { - Logger::Print("#{:03d}: {}\n", i, Logger::LoggingAddresses[0][i].getString()); + Print("#{:03d}: {}\n", i, LoggingAddresses[0][i].getString()); } }); @@ -307,9 +307,9 @@ namespace Components const Network::Address addr(params->get(1)); - if (std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr) == Logger::LoggingAddresses[1].end()) + if (std::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr) == LoggingAddresses[1].end()) { - Logger::LoggingAddresses[1].push_back(addr); + LoggingAddresses[1].push_back(addr); } }); @@ -318,37 +318,37 @@ namespace Components if (params->size() < 2) return; const auto num = std::atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[1].size()) + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < LoggingAddresses[1].size()) { - const auto addr = Logger::LoggingAddresses[1].begin() + num; - Logger::Print("Address {} removed\n", addr->getString()); - Logger::LoggingAddresses[1].erase(addr); + const auto addr = LoggingAddresses[1].begin() + num; + Print("Address {} removed\n", addr->getString()); + LoggingAddresses[1].erase(addr); } else { const Network::Address addr(params->get(1)); - const auto i = std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr); - if (i != Logger::LoggingAddresses[1].end()) + const auto i = std::ranges::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr); + if (i != LoggingAddresses[1].end()) { - Logger::LoggingAddresses[1].erase(i); - Logger::Print("Address {} removed\n", addr.getString()); + LoggingAddresses[1].erase(i); + Print("Address {} removed\n", addr.getString()); } else { - Logger::Print("Address {} not found!\n", addr.getString()); + Print("Address {} not found!\n", addr.getString()); } } }); Command::AddSV("g_log_list", [](Command::Params*) { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); + Print("# ID: Address\n"); + Print("-------------\n"); - for (std::size_t i = 0; i < Logger::LoggingAddresses[1].size(); ++i) + for (std::size_t i = 0; i < LoggingAddresses[1].size(); ++i) { - Logger::Print("#{:03d}: {}\n", i, Logger::LoggingAddresses[1][i].getString()); + Print("#{:03d}: {}\n", i, LoggingAddresses[1][i].getString()); } }); } @@ -356,30 +356,28 @@ namespace Components Logger::Logger() { Dvar::Register("iw4x_onelog", false, Game::DVAR_LATCH | Game::DVAR_ARCHIVE, "Only write the game log to the 'userraw' OS folder"); - Utils::Hook(0x642139, Logger::BuildOSPath_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x642139, BuildOSPath_Stub, HOOK_JUMP).install()->quick(); - Logger::PipeOutput(nullptr); + Scheduler::Loop(Frame, Scheduler::Pipeline::SERVER); - Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::SERVER); - - Utils::Hook(Game::G_LogPrintf, Logger::G_LogPrintf_Hk, HOOK_JUMP).install()->quick(); - Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessage_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::G_LogPrintf, G_LogPrintf_Hk, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::Com_PrintMessage, PrintMessage_Stub, HOOK_JUMP).install()->quick(); if (Loader::IsPerformingUnitTests()) { - Utils::Hook(Game::Com_Printf, Logger::Print_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(Game::Com_Printf, Print_Stub, HOOK_JUMP).install()->quick(); } - Events::OnSVInit(Logger::AddServerCommands); + Events::OnSVInit(AddServerCommands); } Logger::~Logger() { - Logger::LoggingAddresses[0].clear(); - Logger::LoggingAddresses[1].clear(); + LoggingAddresses[0].clear(); + LoggingAddresses[1].clear(); - std::unique_lock lock(Logger::MessageMutex); - Logger::MessageQueue.clear(); + std::unique_lock lock(MessageMutex); + MessageQueue.clear(); lock.unlock(); // Flush the console log diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 6ebe6811..19ce000c 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -59,7 +59,7 @@ namespace Components for (auto& node : nodeList) { Utils::String::Replace(node, "\r", ""); - node = Utils::String::Trim(node); + Utils::String::Trim(node); Node::Add(node); } } diff --git a/src/Components/Modules/PlayerName.cpp b/src/Components/Modules/PlayerName.cpp index 11ca774d..5d69c66a 100644 --- a/src/Components/Modules/PlayerName.cpp +++ b/src/Components/Modules/PlayerName.cpp @@ -18,7 +18,7 @@ namespace Components } std::string readablePlayerName(buffer); - readablePlayerName = Utils::String::Trim(readablePlayerName); + Utils::String::Trim(readablePlayerName); if (readablePlayerName.size() < 3) { diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 57fa3324..b7c0ab20 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -127,8 +127,8 @@ namespace Components Network::OnClientPacket("rcon", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { std::string data_ = data; - Utils::String::Trim(data_); + const auto pos = data.find_first_of(' '); if (pos == std::string::npos) { diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 2e994240..71999f73 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -28,23 +28,24 @@ #pragma warning(disable: 4244) #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #pragma warning(pop) diff --git a/src/Utils/String.cpp b/src/Utils/String.cpp index 13e18025..f14ecd31 100644 --- a/src/Utils/String.cpp +++ b/src/Utils/String.cpp @@ -145,9 +145,9 @@ namespace Utils::String } // Trim from both ends - std::string& Trim(std::string& str) + void Trim(std::string& str) { - return LTrim(RTrim(str)); + LTrim(RTrim(str)); } std::string Convert(const std::wstring& wstr) diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index 84c900fb..cf2417f3 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -11,7 +11,7 @@ namespace Utils::String VAProvider() : currentBuffer(0) {} ~VAProvider() = default; - const char* get(const char* format, va_list ap) + [[nodiscard]] const char* get(const char* format, va_list ap) { ++this->currentBuffer %= ARRAYSIZE(this->stringPool); auto entry = &this->stringPool[this->currentBuffer]; @@ -82,37 +82,61 @@ namespace Utils::String } } - const char* VA(const char* fmt, ...); + [[nodiscard]] const char* VA(const char* fmt, ...); - std::string ToLower(const std::string& text); - std::string ToUpper(const std::string& text); + [[nodiscard]] std::string ToLower(const std::string& text); + [[nodiscard]] std::string ToUpper(const std::string& text); - bool Compare(const std::string& lhs, const std::string& rhs); + template + [[nodiscard]] OutputIter ApplyToLower(OutputIter container) + { + OutputIter result; + std::ranges::transform(container, std::back_inserter(result), [](const std::string& s) -> std::string + { + return ToLower(s); + }); - std::vector Split(const std::string& str, char delim); + return result; + } + + template + [[nodiscard]] OutputIter ApplyToUpper(OutputIter container) + { + OutputIter result; + std::ranges::transform(container, std::back_inserter(result), [](const std::string& s) -> std::string + { + return ToUpper(s); + }); + + return result; + } + + [[nodiscard]] bool Compare(const std::string& lhs, const std::string& rhs); + + [[nodiscard]] std::vector Split(const std::string& str, char delim); void Replace(std::string& str, const std::string& from, const std::string& to); - bool StartsWith(const std::string& haystack, const std::string& needle); - bool EndsWith(const std::string& haystack, const std::string& needle); + [[nodiscard]] bool StartsWith(const std::string& haystack, const std::string& needle); + [[nodiscard]] bool EndsWith(const std::string& haystack, const std::string& needle); - bool IsNumber(const std::string& str); + [[nodiscard]] bool IsNumber(const std::string& str); std::string& LTrim(std::string& str); std::string& RTrim(std::string& str); - std::string& Trim(std::string& str); + void Trim(std::string& str); - std::string Convert(const std::wstring& wstr); - std::wstring Convert(const std::string& str); + [[nodiscard]] std::string Convert(const std::wstring& wstr); + [[nodiscard]] std::wstring Convert(const std::string& str); - std::string FormatTimeSpan(int milliseconds); - std::string FormatBandwidth(std::size_t bytes, int milliseconds); + [[nodiscard]] std::string FormatTimeSpan(int milliseconds); + [[nodiscard]] std::string FormatBandwidth(std::size_t bytes, int milliseconds); - std::string DumpHex(const std::string& data, const std::string& separator = " "); + [[nodiscard]] std::string DumpHex(const std::string& data, const std::string& separator = " "); - std::string XOR(std::string str, char value); + [[nodiscard]] std::string XOR(std::string str, char value); - std::string EncodeBase64(const char* input, unsigned long inputSize); - std::string EncodeBase64(const std::string& input); + [[nodiscard]] std::string EncodeBase64(const char* input, unsigned long inputSize); + [[nodiscard]] std::string EncodeBase64(const std::string& input); - std::string EncodeBase128(const std::string& input); + [[nodiscard]] std::string EncodeBase128(const std::string& input); }