From d7d06ea47bb172d804dde691a6f8e096e6d81810 Mon Sep 17 00:00:00 2001 From: Edo Date: Sat, 6 May 2023 14:20:56 +0100 Subject: [PATCH] [Command]: Refactor (#1013) --- src/Components/Modules/Auth.cpp | 2 +- src/Components/Modules/Bans.cpp | 13 +++-- src/Components/Modules/Bans.hpp | 2 + src/Components/Modules/Bots.cpp | 68 ++++++++++++----------- src/Components/Modules/Bots.hpp | 2 + src/Components/Modules/CardTitles.cpp | 3 +- src/Components/Modules/Chat.cpp | 22 +++++--- src/Components/Modules/Chat.hpp | 2 +- src/Components/Modules/ClanTags.cpp | 2 +- src/Components/Modules/Command.cpp | 8 +-- src/Components/Modules/Command.hpp | 12 ++-- src/Components/Modules/Debug.cpp | 2 +- src/Components/Modules/Debug.hpp | 2 +- src/Components/Modules/Dedicated.cpp | 9 +-- src/Components/Modules/FastFiles.cpp | 4 +- src/Components/Modules/Friends.cpp | 29 ---------- src/Components/Modules/Friends.hpp | 2 - src/Components/Modules/Gamepad.cpp | 10 ++-- src/Components/Modules/Gamepad.hpp | 10 ++-- src/Components/Modules/IPCPipe.cpp | 2 +- src/Components/Modules/Logger.cpp | 19 +++---- src/Components/Modules/MapDump.cpp | 2 +- src/Components/Modules/MapRotation.cpp | 4 +- src/Components/Modules/Maps.cpp | 4 +- src/Components/Modules/Menus.cpp | 9 +-- src/Components/Modules/Network.cpp | 32 +++++++++++ src/Components/Modules/Network.hpp | 2 + src/Components/Modules/Node.cpp | 17 +++--- src/Components/Modules/Node.hpp | 2 +- src/Components/Modules/Party.cpp | 4 +- src/Components/Modules/QuickPatch.cpp | 2 +- src/Components/Modules/RCon.cpp | 6 +- src/Components/Modules/RawFiles.cpp | 4 +- src/Components/Modules/ServerCommands.hpp | 2 +- src/Components/Modules/Stats.cpp | 4 +- src/Components/Modules/StructuredData.cpp | 14 ----- src/Components/Modules/ZoneBuilder.cpp | 18 +++--- src/Components/Modules/Zones.cpp | 13 +---- src/DllMain.cpp | 12 ++-- src/Game/Client.cpp | 1 + src/Game/Functions.cpp | 3 +- src/Game/Functions.hpp | 5 +- src/STDInclude.hpp | 6 +- 43 files changed, 190 insertions(+), 201 deletions(-) diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index 3024699b..4b0ee31a 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -511,7 +511,7 @@ namespace Components if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) { - Command::Add("securityLevel", [](Command::Params* params) + Command::Add("securityLevel", [](const Command::Params* params) { if (params->size() < 2) { diff --git a/src/Components/Modules/Bans.cpp b/src/Components/Modules/Bans.cpp index ae3be8af..69cc4e6e 100644 --- a/src/Components/Modules/Bans.cpp +++ b/src/Components/Modules/Bans.cpp @@ -232,9 +232,9 @@ namespace Components SaveBans(&list); } - Bans::Bans() + void Bans::AddServerCommands() { - Command::Add("banClient", [](Command::Params* params) + Command::AddSV("banClient", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -278,11 +278,11 @@ namespace Components return; } - const std::string reason = params->size() < 3 ? "EXE_ERR_BANNED_PERM" : params->join(2); + const auto reason = params->size() < 3 ? "EXE_ERR_BANNED_PERM"s : params->join(2); BanClient(cl, reason); }); - Command::Add("unbanClient", [](Command::Params* params) + Command::AddSV("unbanClient", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -317,4 +317,9 @@ namespace Components } }); } + + Bans::Bans() + { + Events::OnSVInit(AddServerCommands); + } } diff --git a/src/Components/Modules/Bans.hpp b/src/Components/Modules/Bans.hpp index 8545d94b..61aa981b 100644 --- a/src/Components/Modules/Bans.hpp +++ b/src/Components/Modules/Bans.hpp @@ -29,5 +29,7 @@ namespace Components static void LoadBans(BanList* list); static void SaveBans(const BanList* list); + + static void AddServerCommands(); }; } diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index cad90b55..ee8c6397 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -407,37 +407,9 @@ namespace Components } } - Bots::Bots() + void Bots::AddServerCommands() { - AssertOffset(Game::client_s, bIsTestClient, 0x41AF0); - AssertOffset(Game::client_s, ping, 0x212C8); - AssertOffset(Game::client_s, 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\""); - - // Intercept sprintf for the connect string - Utils::Hook(0x48ADAB, BuildConnectString, 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, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); - - Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick(); - - 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 - { - g_botai[clientNum].active = false; - }); - - CleanBotArray(); - - Command::Add("spawnBot", [](Command::Params* params) + Command::AddSV("spawnBot", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -467,8 +439,7 @@ namespace Components if (input == end) { - Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} optional or optional <\"all\">\n", - input, params->get(0)); + Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} optional or optional <\"all\">\n", input, params->get(0)); return; } } @@ -480,6 +451,39 @@ namespace Components Spawn(count); }); + } + + Bots::Bots() + { + AssertOffset(Game::client_s, bIsTestClient, 0x41AF0); + AssertOffset(Game::client_s, ping, 0x212C8); + AssertOffset(Game::client_s, 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\""); + + // Intercept sprintf for the connect string + Utils::Hook(0x48ADAB, BuildConnectString, 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, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + + Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick(); + + 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 + { + g_botai[clientNum].active = false; + }); + + Events::OnSVInit(AddServerCommands); + + CleanBotArray(); AddScriptMethods(); diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index 81a38bb8..30925db3 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -36,5 +36,7 @@ namespace Components static bool IsFull(); static void CleanBotArray(); + + static void AddServerCommands(); }; } diff --git a/src/Components/Modules/CardTitles.cpp b/src/Components/Modules/CardTitles.cpp index d3e44442..3ff49ffb 100644 --- a/src/Components/Modules/CardTitles.cpp +++ b/src/Components/Modules/CardTitles.cpp @@ -202,7 +202,7 @@ namespace Components std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18])); - ServerCommands::OnCommand(21, [](Command::Params* params) + ServerCommands::OnCommand(21, [](const Command::Params* params) { if (std::strcmp(params->get(1), "customTitles") == 0) { @@ -214,7 +214,6 @@ namespace Components } return false; - }); Utils::Hook(0x62EB26, GetPlayerCardClientInfoStub).install()->quick(); diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 5b7ecf38..3ace57fc 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -380,9 +380,9 @@ namespace Components }); } - void Chat::AddChatCommands() + void Chat::AddServerCommands() { - Command::AddSV("muteClient", [](Command::Params* params) + Command::AddSV("muteClient", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -405,7 +405,7 @@ namespace Components } }); - Command::AddSV("unmute", [](Command::Params* params) + Command::AddSV("unmute", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -446,7 +446,7 @@ namespace Components } }); - Command::AddSV("say", [](Command::Params* params) + Command::AddSV("say", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -471,7 +471,7 @@ namespace Components } }); - Command::AddSV("tell", [](Command::Params* params) + Command::AddSV("tell", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -499,7 +499,7 @@ namespace Components } }); - Command::AddSV("sayraw", [](Command::Params* params) + Command::AddSV("sayraw", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -514,7 +514,7 @@ namespace Components Logger::Print("Raw: {}\n", message); }); - Command::AddSV("tellraw", [](Command::Params* params) + Command::AddSV("tellraw", [](const Command::Params* params) { if (!Dedicated::IsRunning()) { @@ -610,7 +610,7 @@ namespace Components cg_chatWidth = Dvar::Register("cg_chatWidth", 52, 1, std::numeric_limits::max(), Game::DVAR_ARCHIVE, "The normalized maximum width of a chat message"); sv_disableChat = Dvar::Register("sv_disableChat", false, Game::DVAR_NONE, "Disable chat messages from clients"); - Events::OnSVInit(AddChatCommands); + Events::OnSVInit(AddServerCommands); LoadMutedList(); @@ -622,6 +622,12 @@ namespace Components // Change logic that does word splitting with new lines for chat messages to support fonticons Utils::Hook(0x592E10, CG_AddToTeamChat_Stub, HOOK_JUMP).install()->quick(); + // Add back removed command from CoD4 + Command::Add("mp_QuickMessage", []() -> void + { + Command::Execute("openmenu quickmessage"); + }); + AddScriptFunctions(); // Avoid duplicates diff --git a/src/Components/Modules/Chat.hpp b/src/Components/Modules/Chat.hpp index 5a33d118..b054f468 100644 --- a/src/Components/Modules/Chat.hpp +++ b/src/Components/Modules/Chat.hpp @@ -42,7 +42,7 @@ namespace Components static void SaveMutedList(const muteList& list); static void LoadMutedList(); - static void AddChatCommands(); + static void AddServerCommands(); static int GetCallbackReturn(); static int ChatCallback(Game::gentity_s* self, const char* codePos, const char* message, int mode); diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index 2dd4a956..8e049e3c 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -240,7 +240,7 @@ namespace Components std::memset(&ClientState, 0, sizeof(char[Game::MAX_CLIENTS][MAX_CLAN_NAME_LENGTH])); - ServerCommands::OnCommand(22, [](Command::Params* params) + ServerCommands::OnCommand(22, [](const Command::Params* params) { if (std::strcmp(params->get(1), "clanNames") == 0) { diff --git a/src/Components/Modules/Command.cpp b/src/Components/Modules/Command.cpp index c4a0e4ff..8ff9a88b 100644 --- a/src/Components/Modules/Command.cpp +++ b/src/Components/Modules/Command.cpp @@ -2,8 +2,8 @@ namespace Components { - std::unordered_map> Command::FunctionMap; - std::unordered_map> Command::FunctionMapSV; + std::unordered_map Command::FunctionMap; + std::unordered_map Command::FunctionMapSV; std::string Command::Params::join(const int index) const { @@ -68,7 +68,7 @@ namespace Components }); } - void Command::Add(const char* name, const std::function& callback) + void Command::Add(const char* name, const commandCallback& callback) { const auto command = Utils::String::ToLower(name); @@ -80,7 +80,7 @@ namespace Components FunctionMap.insert_or_assign(command, callback); } - void Command::AddSV(const char* name, const std::function& callback) + void Command::AddSV(const char* name, const commandCallback& callback) { if (Loader::IsPregame()) { diff --git a/src/Components/Modules/Command.hpp b/src/Components/Modules/Command.hpp index 41cb5ec9..5b6477fc 100644 --- a/src/Components/Modules/Command.hpp +++ b/src/Components/Modules/Command.hpp @@ -54,19 +54,21 @@ namespace Components Command(); - static Game::cmd_function_s* Allocate(); + using commandCallback = std::function; static void Add(const char* name, const std::function& callback); - static void Add(const char* name, const std::function& callback); + static void Add(const char* name, const commandCallback& callback); static void AddRaw(const char* name, void(*callback)(), bool key = false); - static void AddSV(const char* name, const std::function& callback); + static void AddSV(const char* name, const commandCallback& callback); static void Execute(std::string command, bool sync = true); static Game::cmd_function_s* Find(const std::string& command); private: - static std::unordered_map> FunctionMap; - static std::unordered_map> FunctionMapSV; + static std::unordered_map FunctionMap; + static std::unordered_map FunctionMapSV; + + static Game::cmd_function_s* Allocate(); static void AddRawSV(const char* name, void(*callback)()); diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index a5c66fb3..768bb510 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -272,7 +272,7 @@ namespace Components assert(0 && "a"); } - void Debug::Com_Bug_f(Command::Params* params) + void Debug::Com_Bug_f(const Command::Params* params) { char newFileName[MAX_PATH]{}; char to_ospath[MAX_OSPATH]{}; diff --git a/src/Components/Modules/Debug.hpp b/src/Components/Modules/Debug.hpp index 57691886..fe83cf7a 100644 --- a/src/Components/Modules/Debug.hpp +++ b/src/Components/Modules/Debug.hpp @@ -40,7 +40,7 @@ namespace Components static void CG_DrawDebugOverlays_Hk(int localClientNum); static void Com_Assert_f(); - static void Com_Bug_f(Command::Params* params); + static void Com_Bug_f(const Command::Params* params); static void Com_BugNameInc_f(); static void CL_InitDebugDvars(); diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 100a1ab2..e2e5b2e8 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -267,7 +267,6 @@ namespace Components Game::DvarValue value; value.integer = 0; Game::Dvar_SetVariant(const_cast(com_dedicated), value, Game::DVAR_SOURCE_INTERNAL); - } }); @@ -291,14 +290,10 @@ namespace Components } else { - for (int i = 0; i < ARRAYSIZE(PlayerGuids); ++i) - { - PlayerGuids[i][0].bits = 0; - PlayerGuids[i][1].bits = 0; - } + ZeroMemory(PlayerGuids, sizeof(PlayerGuids)); // Intercept server commands - ServerCommands::OnCommand(20, [](Command::Params* params) + ServerCommands::OnCommand(20, [](const Command::Params* params) { for (int client = 0; client < 18; client++) { diff --git a/src/Components/Modules/FastFiles.cpp b/src/Components/Modules/FastFiles.cpp index e56732f1..d2a35cbd 100644 --- a/src/Components/Modules/FastFiles.cpp +++ b/src/Components/Modules/FastFiles.cpp @@ -609,7 +609,7 @@ namespace Components }, Scheduler::Pipeline::RENDERER); } - Command::Add("loadzone", [](Command::Params* params) + Command::Add("loadzone", [](const Command::Params* params) { if (params->size() < 2) return; @@ -621,7 +621,7 @@ namespace Components Game::DB_LoadXAssets(&info, 1, true); }); - Command::Add("awaitDatabase", [](Command::Params*) + Command::Add("awaitDatabase", []() { Logger::Print("Waiting for database...\n"); while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(100ms); diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index dea87d13..8f884641 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -461,21 +461,6 @@ namespace Components Friends::CurrentFriend = index; } - void Friends::AddFriend(SteamID user) - { - if (Steam::Proxy::ClientFriends && Steam::Proxy::SteamFriends) - { - if (Steam::Proxy::ClientFriends.invoke("AddFriend", user)) - { - Toast::Show("cardicon_joystick", Steam::Proxy::SteamFriends->GetFriendPersonaName(user), "friend request sent", 3000); - } - else - { - Toast::Show("cardicon_stop", Steam::Proxy::SteamFriends->GetFriendPersonaName(user), "unable to send friend request", 3000); - } - } - } - int Friends::GetGame(SteamID user) { int appId = 0; @@ -574,20 +559,6 @@ namespace Components Friends::CLAnonymous = Dvar::Register("cl_anonymous", false, Game::DVAR_ARCHIVE, "Enable invisible mode for Steam"); Friends::CLNotifyFriendState = Dvar::Register("cl_notifyFriendState", true, Game::DVAR_ARCHIVE, "Update friends about current game status"); - Command::Add("addFriend", [](Command::Params* params) - { - if (params->size() < 2) - { - Logger::Print("Usage: {} \n", params->get(0)); - return; - } - - SteamID id; - id.bits = std::strtoull(params->get(1), nullptr, 16); - - Friends::AddFriend(id); - }); - // Hook Live_ShowFriendsList Utils::Hook(0x4D6C70, []() { diff --git a/src/Components/Modules/Friends.hpp b/src/Components/Modules/Friends.hpp index 4bc0075f..e59cfdab 100644 --- a/src/Components/Modules/Friends.hpp +++ b/src/Components/Modules/Friends.hpp @@ -19,8 +19,6 @@ namespace Components static void RequestPresence(SteamID user); static std::string GetPresence(SteamID user, const std::string& key); - static void AddFriend(SteamID user); - static int GetGame(SteamID user); static bool IsInvisible(); diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index b7552c67..0fe01d91 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -1760,7 +1760,7 @@ namespace Components return Game::GPAD_MAP_NONE; } - void Gamepad::Axis_Bind_f(Command::Params* params) + void Gamepad::Axis_Bind_f(const Command::Params* params) { if (params->size() < 4) { @@ -1796,7 +1796,7 @@ namespace Components Gamepad_BindAxis(0, physicalAxis, virtualAxis, mapping); } - void Gamepad::Axis_Unbindall_f(Command::Params*) + void Gamepad::Axis_Unbindall_f() { auto& gamePadGlobal = gamePadGlobals[0]; @@ -1807,19 +1807,19 @@ namespace Components } } - void Gamepad::Bind_GP_SticksConfigs_f(Command::Params*) + void Gamepad::Bind_GP_SticksConfigs_f() { const auto* stickConfigName = gpad_sticksConfig.get(); Game::Cbuf_AddText(0, Utils::String::VA("exec %s\n", stickConfigName)); } - void Gamepad::Bind_GP_ButtonsConfigs_f(Command::Params*) + void Gamepad::Bind_GP_ButtonsConfigs_f() { const auto* buttonConfigName = gpad_buttonConfig.get(); Game::Cbuf_AddText(0, Utils::String::VA("exec %s\n", buttonConfigName)); } - void Gamepad::Scores_Toggle_f(Command::Params*) + void Gamepad::Scores_Toggle_f() { if (Game::cgArray[0].nextSnap) { diff --git a/src/Components/Modules/Gamepad.hpp b/src/Components/Modules/Gamepad.hpp index 5ff132d2..3409d80c 100644 --- a/src/Components/Modules/Gamepad.hpp +++ b/src/Components/Modules/Gamepad.hpp @@ -184,11 +184,11 @@ namespace Components static Game::GamepadPhysicalAxis StringToPhysicalAxis(const char* str); static Game::GamepadVirtualAxis StringToVirtualAxis(const char* str); static Game::GamepadMapping StringToGamePadMapping(const char* str); - static void Axis_Bind_f(Command::Params* params); - static void Axis_Unbindall_f(Command::Params* params); - static void Bind_GP_SticksConfigs_f(Command::Params* params); - static void Bind_GP_ButtonsConfigs_f(Command::Params* params); - static void Scores_Toggle_f(Command::Params* params); + static void Axis_Bind_f(const Command::Params* params); + static void Axis_Unbindall_f(); + static void Bind_GP_SticksConfigs_f(); + static void Bind_GP_ButtonsConfigs_f(); + static void Scores_Toggle_f(); static void InitDvars(); static void CG_RegisterDvars_Hk(); diff --git a/src/Components/Modules/IPCPipe.cpp b/src/Components/Modules/IPCPipe.cpp index 64d9a31d..f14132d7 100644 --- a/src/Components/Modules/IPCPipe.cpp +++ b/src/Components/Modules/IPCPipe.cpp @@ -225,7 +225,7 @@ namespace Components }); // Test pipe functionality by sending pings - Command::Add("ipcping", []([[maybe_unused]] Command::Params* params) + Command::Add("ipcping", []() { Logger::Print("Sending ping to pipe!\n"); Write("ping", {}); diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 851b04ea..033f377b 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -274,20 +274,20 @@ namespace Components void Logger::AddServerCommands() { - Command::AddSV("log_add", [](Command::Params* params) + Command::AddSV("log_add", [](const Command::Params* params) { if (params->size() < 2) return; std::unique_lock lock(LoggingMutex); Network::Address addr(params->get(1)); - if (std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr) == LoggingAddresses[0].end()) + if (std::ranges::find(LoggingAddresses[0], addr) == LoggingAddresses[0].end()) { LoggingAddresses[0].push_back(addr); } }); - Command::AddSV("log_del", [](Command::Params* params) + Command::AddSV("log_del", [](const Command::Params* params) { if (params->size() < 2) return; @@ -304,8 +304,7 @@ namespace Components { Network::Address addr(params->get(1)); - const auto i = std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr); - if (i != LoggingAddresses[0].end()) + if (const auto i = std::ranges::find(LoggingAddresses[0], addr); i != LoggingAddresses[0].end()) { LoggingAddresses[0].erase(i); Print("Address {} removed\n", addr.getString()); @@ -317,7 +316,7 @@ namespace Components } }); - Command::AddSV("log_list", []([[maybe_unused]] Command::Params* params) + Command::AddSV("log_list", []([[maybe_unused]] const Command::Params* params) { Print("# ID: Address\n"); Print("-------------\n"); @@ -330,20 +329,20 @@ namespace Components } }); - Command::AddSV("g_log_add", [](Command::Params* params) + Command::AddSV("g_log_add", [](const Command::Params* params) { if (params->size() < 2) return; 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()) + if (std::ranges::find(LoggingAddresses[1], addr) == LoggingAddresses[1].end()) { LoggingAddresses[1].push_back(addr); } }); - Command::AddSV("g_log_del", [](Command::Params* params) + Command::AddSV("g_log_del", [](const Command::Params* params) { if (params->size() < 2) return; @@ -372,7 +371,7 @@ namespace Components } }); - Command::AddSV("g_log_list", [](Command::Params*) + Command::AddSV("g_log_list", []([[maybe_unused]] const Command::Params* params) { Print("# ID: Address\n"); Print("-------------\n"); diff --git a/src/Components/Modules/MapDump.cpp b/src/Components/Modules/MapDump.cpp index db84fa6e..c4dc4bcc 100644 --- a/src/Components/Modules/MapDump.cpp +++ b/src/Components/Modules/MapDump.cpp @@ -434,7 +434,7 @@ namespace Components MapDump::MapDump() { - Command::Add("dumpmap", [](Command::Params*) + Command::Add("dumpmap", []() { if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) { diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index e3f109ff..0d8f463a 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -176,7 +176,7 @@ namespace Components void MapRotation::AddMapRotationCommands() { - Command::AddSV("addMap", [](Command::Params* params) + Command::AddSV("addMap", [](const Command::Params* params) { if (params->size() < 2) { @@ -187,7 +187,7 @@ namespace Components DedicatedRotation.addEntry("map", params->get(1)); }); - Command::AddSV("addGametype", [](Command::Params* params) + Command::AddSV("addGametype", [](const Command::Params* params) { if (params->size() < 2) { diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 072319f5..46ff7ff4 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -838,7 +838,7 @@ namespace Components Utils::Hook(0x5A9D51, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5B34DD, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick(); - Command::Add("delayReconnect", []([[maybe_unused]] Command::Params* params) + Command::Add("delayReconnect", []() { Scheduler::Once([] { @@ -852,7 +852,7 @@ namespace Components Utils::Hook(0x4A7251, Maps::LoadNewMapCommand, HOOK_CALL).install()->quick(); } - // Download the map before a maprotation if necessary + // Download the map before a map rotation if necessary // Conflicts with Theater's SV map rotation check, but this one is safer! Utils::Hook(0x5AA91C, Maps::RotateCheckStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 0328a1bd..44f58e10 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -828,7 +828,7 @@ namespace Components // make Com_Error and similar go back to main_text instead of menu_xboxlive. Utils::Hook::SetString(0x6FC790, "main_text"); - Command::Add("openmenu", [](Command::Params* params) + Command::Add("openmenu", [](const Command::Params* params) { if (params->size() != 2) { @@ -845,7 +845,7 @@ namespace Components Game::Menus_OpenByName(Game::uiContext, params->get(1)); }); - Command::Add("reloadmenus", []([[maybe_unused]] Command::Params* params) + Command::Add("reloadmenus", []() { // Close all menus Game::Menus_CloseAll(Game::uiContext); @@ -868,11 +868,6 @@ namespace Components } }); - Command::Add("mp_QuickMessage", [](Command::Params*) - { - Command::Execute("openmenu quickmessage"); - }); - // Define custom menus here Add("ui_mp/changelog.menu"); Add("ui_mp/theater_menu.menu"); diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 76746907..53e74399 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -341,6 +341,33 @@ namespace Components } } + int Network::Sys_StringToSockaddr_Hk(const char* s, sockaddr* sadr) + { + hostent* h; + ZeroMemory(sadr, sizeof(*sadr)); + + ((sockaddr_in*)sadr)->sin_family = AF_INET; + ((sockaddr_in*)sadr)->sin_port = 0; + + if (Game::I_isdigit(*s)) + { + // ReSharper disable once CppDeprecatedEntity + *(int*)&((sockaddr_in*)sadr)->sin_addr = static_cast(::inet_addr(s)); + } + else + { + // ReSharper disable once CppDeprecatedEntity + if ((h = ::gethostbyname(s)) == nullptr) + { + return false; + } + + *(int*)&((sockaddr_in*)sadr)->sin_addr = *(int*)h->h_addr_list[0]; + } + + return true; + } + Network::Network() { AssertSize(Game::netadr_t, 20); @@ -374,6 +401,10 @@ namespace Components // Handle client packets Utils::Hook(0x5AA703, CL_HandleCommandStub, HOOK_JUMP).install()->quick(); + // Use the version of Sys_StringToSockaddr made by 3arc + Utils::Hook(0x44E23C, Sys_StringToSockaddr_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x64D480, Sys_StringToSockaddr_Hk, HOOK_CALL).install()->quick(); + // Disable unused OOB packets handlers just to be sure Utils::Hook::Set(0x5AA5B6, 0xEB); // CL_SteamServerAuth Utils::Hook::Set(0x5AA69F, 0xEB); // echo @@ -413,6 +444,7 @@ namespace Components auto* clc = Game::CL_GetLocalClientConnection(0); if (!Game::NET_CompareBaseAdr(clc->serverAddress, *address)) { + Logger::Debug("Ignoring stray 'print' network message from '{}'", Game::NET_AdrToString(*address)); return; } diff --git a/src/Components/Modules/Network.hpp b/src/Components/Modules/Network.hpp index 547628ed..d9e2e020 100644 --- a/src/Components/Modules/Network.hpp +++ b/src/Components/Modules/Network.hpp @@ -89,6 +89,8 @@ namespace Components static bool CL_HandleCommand(Game::netadr_t* address, const char* command, Game::msg_t* message); static void CL_HandleCommandStub(); + + static int Sys_StringToSockaddr_Hk(const char* s, sockaddr* sadr); }; } diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index cb122cc7..2e655361 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -13,7 +13,7 @@ namespace Components std::recursive_mutex Node::Mutex; std::vector Node::Nodes; - bool Node::wasIngame = false; + bool Node::WasIngame = false; bool Node::Entry::isValid() { @@ -154,14 +154,14 @@ namespace Components { if (ServerList::UseMasterServer) return; // don't run node frame if master server is active - if (*Game::clcState > 0) + if (Game::CL_GetLocalClientConnectionState(0) != Game::CA_DISCONNECTED) { - wasIngame = true; - return; // don't run while ingame because it can still cause lag spikes on lower end PCs + WasIngame = true; + return; // don't run while in-game because it can still cause lag spikes on lower end PCs } } - if (wasIngame) // our last frame we were ingame and now we aren't so touch all nodes + if (WasIngame) // our last frame we were in-game and now we aren't so touch all nodes { for (auto i = Node::Nodes.begin(); i != Node::Nodes.end();++i) { @@ -170,7 +170,8 @@ namespace Components i->lastRequest.reset(); i->lastResponse.reset(); } - wasIngame = false; + + WasIngame = false; } static Utils::Time::Interval frameLimit; @@ -344,7 +345,7 @@ namespace Components Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN); - Command::Add("listnodes", [](Command::Params*) + Command::Add("listnodes", [](const Command::Params*) { Logger::Print("Nodes: {}\n", Node::Nodes.size()); @@ -355,7 +356,7 @@ namespace Components } }); - Command::Add("addnode", [](Command::Params* params) + Command::Add("addnode", [](const Command::Params* params) { if (params->size() < 2) return; Node::Add({ params->get(1) }); diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index e6e992ad..35623d52 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -44,7 +44,7 @@ namespace Components private: static std::recursive_mutex Mutex; static std::vector Nodes; - static bool wasIngame; + static bool WasIngame; static void HandleResponse(Network::Address address, const std::string& data); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 0c85560f..8dfad7db 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -293,7 +293,7 @@ namespace Components Utils::Hook::Xor(0x4D376D, Game::DVAR_LATCH); Utils::Hook::Xor(0x5E3789, Game::DVAR_LATCH); - Command::Add("connect", [](Command::Params* params) + Command::Add("connect", [](const Command::Params* params) { if (params->size() < 2) { @@ -311,7 +311,7 @@ namespace Components } }); - Command::Add("reconnect", [](Command::Params*) + Command::Add("reconnect", []() { Connect(Container.target); }); diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index b4086ff9..c8c900cf 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -522,7 +522,7 @@ namespace Components Command::Add("unlockstats", QuickPatch::UnlockStats); - Command::Add("dumptechsets", [](Command::Params* param) + Command::Add("dumptechsets", [](const Command::Params* param) { if (param->size() != 2) { diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 70b8e785..d7074420 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -21,7 +21,7 @@ namespace Components void RCon::AddCommands() { - Command::Add("rcon", [](Command::Params* params) + Command::Add("rcon", [](const Command::Params* params) { if (params->size() < 2) return; @@ -60,7 +60,7 @@ namespace Components Logger::Print("You are connected to an invalid server\n"); }); - Command::Add("remoteCommand", [](Command::Params* params) + Command::Add("remoteCommand", [](const Command::Params* params) { if (params->size() < 2) return; @@ -79,7 +79,7 @@ namespace Components } }); - Command::AddSV("RconWhitelistAdd", [](Command::Params* params) + Command::AddSV("RconWhitelistAdd", [](const Command::Params* params) { if (params->size() < 2) { diff --git a/src/Components/Modules/RawFiles.cpp b/src/Components/Modules/RawFiles.cpp index d914d38d..aecb2cde 100644 --- a/src/Components/Modules/RawFiles.cpp +++ b/src/Components/Modules/RawFiles.cpp @@ -124,7 +124,7 @@ namespace Components Utils::Hook(0x631640, GetMenuBuffer, HOOK_JUMP).install()->quick(); Utils::Hook(0x463500, Com_LoadInfoString_Hk, HOOK_JUMP).install()->quick(); - Command::Add("dumpraw", [](Command::Params* params) + Command::Add("dumpraw", [](const Command::Params* params) { if (params->size() < 2) { @@ -140,7 +140,7 @@ namespace Components return; } - const char* data = Game::Scr_AddSourceBuffer(nullptr, file.getName().data(), nullptr, false); + const auto* data = Game::Scr_AddSourceBuffer(nullptr, file.getName().data(), nullptr, false); if (data) { diff --git a/src/Components/Modules/ServerCommands.hpp b/src/Components/Modules/ServerCommands.hpp index ee46e676..3d8002b8 100644 --- a/src/Components/Modules/ServerCommands.hpp +++ b/src/Components/Modules/ServerCommands.hpp @@ -7,7 +7,7 @@ namespace Components public: ServerCommands(); - using serverCommandHandler = std::function; + using serverCommandHandler = std::function; static void OnCommand(std::int32_t cmd, const serverCommandHandler& callback); private: diff --git a/src/Components/Modules/Stats.cpp b/src/Components/Modules/Stats.cpp index 9472a1d0..d23739a6 100644 --- a/src/Components/Modules/Stats.cpp +++ b/src/Components/Modules/Stats.cpp @@ -162,7 +162,7 @@ namespace Components Utils::Hook::Set(0x4CC5F9, 0xEB); // 'M' Seems to be used on Xbox only for parsing platform specific ranks - ServerCommands::OnCommand('M', [](Command::Params* params) + ServerCommands::OnCommand('M', [](const Command::Params* params) { const auto* arg1 = params->get(1); const auto* arg2 = params->get(2); @@ -171,7 +171,7 @@ namespace Components return true; }); - Command::Add("statGet", []([[maybe_unused]] Command::Params* params) + Command::Add("statGet", [](const Command::Params* params) { if (params->size() < 2) { diff --git a/src/Components/Modules/StructuredData.cpp b/src/Components/Modules/StructuredData.cpp index e8dd0ca1..121a0f8c 100644 --- a/src/Components/Modules/StructuredData.cpp +++ b/src/Components/Modules/StructuredData.cpp @@ -157,20 +157,6 @@ namespace Components // 15 or more custom classes Utils::Hook::Set(0x60A2FE, NUM_CUSTOM_CLASSES); - -#ifdef _DEBUG - // Reset empty names - Command::Add("checkClasses", [](Command::Params*) - { - for (int i = 0; i < NUM_CUSTOM_CLASSES; ++i) - { - // TODO: Correctly lookup using structured data - char* className = (reinterpret_cast(0x1AD3694) - 4 + 3003 + (64 * i) + 0x29); - if (!*className) strcpy_s(className, 24, Game::SEH_StringEd_GetString(Utils::String::VA("CLASS_SLOT%i", i + 1))); - } - }); -#endif - return; } AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, const std::string& filename, bool* /*restrict*/) diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index f1c54bf6..6a26a07c 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -1211,7 +1211,7 @@ namespace Components } }); - Command::Add("verifyzone", [](Command::Params* params) + Command::Add("verifyzone", [](const Command::Params* params) { if (params->size() < 2) return; @@ -1250,7 +1250,7 @@ namespace Components Logger::Print("\n"); }); - Command::Add("buildzone", [](Command::Params* params) + Command::Add("buildzone", [](const Command::Params* params) { if (params->size() < 2) return; @@ -1260,7 +1260,7 @@ namespace Components Zone(zoneName).build(); }); - Command::Add("buildall", []([[maybe_unused]] Command::Params* params) + Command::Add("buildall", []() { auto path = std::format("{}\\zone_source", (*Game::fs_basepath)->current.string); auto zoneSources = FileSystem::GetSysFileList(path, "csv", false); @@ -1327,7 +1327,7 @@ namespace Components } }); - Command::Add("buildtechsets", [](Command::Params*) + Command::Add("buildtechsets", [](const Command::Params*) { Utils::IO::CreateDir("zone_source/techsets"); Utils::IO::CreateDir("zone/techsets"); @@ -1580,7 +1580,7 @@ namespace Components Zone("techsets/techsets").build(); }); - Command::Add("listassets", [](Command::Params* params) + Command::Add("listassets", [](const Command::Params* params) { if (params->size() < 2) return; Game::XAssetType type = Game::DB_GetXAssetNameType(params->get(1)); @@ -1595,7 +1595,7 @@ namespace Components } }); - Command::Add("loadtempzone", [](Command::Params* params) + Command::Add("loadtempzone", [](const Command::Params* params) { if (params->size() < 2) return; @@ -1609,7 +1609,7 @@ namespace Components } }); - Command::Add("unloadtempzones", [](Command::Params*) + Command::Add("unloadtempzones", [](const Command::Params*) { Game::XZoneInfo info; info.name = nullptr; @@ -1619,7 +1619,7 @@ namespace Components AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded }); - Command::Add("materialInfoDump", [](Command::Params*) + Command::Add("materialInfoDump", [](const Command::Params*) { Game::DB_EnumXAssets(Game::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void*) { @@ -1628,7 +1628,7 @@ namespace Components }, nullptr, false); }); - Command::Add("iwiDump", [](Command::Params* params) + Command::Add("iwiDump", [](const Command::Params* params) { if (params->size() < 2) return; diff --git a/src/Components/Modules/Zones.cpp b/src/Components/Modules/Zones.cpp index 115306a5..17226290 100644 --- a/src/Components/Modules/Zones.cpp +++ b/src/Components/Modules/Zones.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -3482,7 +3482,7 @@ namespace Components if (ZoneBuilder::IsEnabled()) { - Command::Add("decryptImages", [](Command::Params*) + Command::Add("decryptImages", []() { auto images = FileSystem::GetSysFileList("iw4x/images", "iwi"); Logger::Print("decrypting {} images...\n", images.size()); @@ -3516,7 +3516,7 @@ namespace Components Logger::Print("decrypted {} images!\n", images.size()); }); - Command::Add("decryptSounds", []([[maybe_unused]] Command::Params* params) + Command::Add("decryptSounds", []() { auto sounds = FileSystem::GetSysFileList("iw4x/sound", "iwi"); Logger::Print("decrypting {} sounds...\n", sounds.size()); @@ -3653,13 +3653,6 @@ namespace Components Utils::Hook(0x4597DD, Zones::LoadStatement, HOOK_CALL).install()->quick(); Utils::Hook(0x471A39, Zones::LoadWindowImage, HOOK_JUMP).install()->quick(); - -#ifdef DEBUG - // Easy dirty disk debugging - Utils::Hook::Set(0x4CF7F0, 0xC3CC); - // disable _invoke_watson to allow debugging - Utils::Hook::Set(0x6B9602, 0xCCCC); -#endif } } #pragma optimize( "", on ) diff --git a/src/DllMain.cpp b/src/DllMain.cpp index 1bcf5707..3f92b015 100644 --- a/src/DllMain.cpp +++ b/src/DllMain.cpp @@ -58,12 +58,12 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser if (!binary || std::memcmp(binary, BASEGAME_NAME, 14) != 0) #endif { - MessageBoxA(nullptr, - "Failed to load game binary.\n" - "You did not install the iw4x-rawfiles!\n" - "Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client", - "ERROR", - MB_ICONERROR + MessageBoxA(nullptr, + "Failed to load game binary.\n" + "You did not install the iw4x-rawfiles!\n" + "Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client", + "ERROR", + MB_ICONERROR ); return FALSE; } diff --git a/src/Game/Client.cpp b/src/Game/Client.cpp index 77a8e6cf..de491e1d 100644 --- a/src/Game/Client.cpp +++ b/src/Game/Client.cpp @@ -58,6 +58,7 @@ namespace Game connstate_t CL_GetLocalClientConnectionState(const int localClientNum) { + AssertOffset(clientUIActive_t, connectionState, 0x9B8); AssertIn(localClientNum, STATIC_MAX_LOCAL_CLIENTS); return clientUIActives[localClientNum].connectionState; diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 97de97b1..86afc062 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -238,6 +238,7 @@ namespace Game I_strncpyz_t I_strncpyz = I_strncpyz_t(0x4D6F80); I_CleanStr_t I_CleanStr = I_CleanStr_t(0x4AD470); + I_isdigit_t I_isdigit = I_isdigit_t(0x4E71E0); XNAddrToString_t XNAddrToString = XNAddrToString_t(0x452690); @@ -318,8 +319,6 @@ namespace Game infoParm_t* infoParams = reinterpret_cast(0x79D260); // Count 0x1E - clientState_t* clcState = reinterpret_cast(0xB2C540); - GfxScene* scene = reinterpret_cast(0x6944914); Console* con = reinterpret_cast(0x9FCCF8); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index b694b0b8..843bc7f5 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -554,6 +554,9 @@ namespace Game typedef char*(*I_CleanStr_t)(char* string); extern I_CleanStr_t I_CleanStr; + typedef bool(*I_isdigit_t)(int c); + extern I_isdigit_t I_isdigit; + typedef void(*XNAddrToString_t)(const XNADDR* xnaddr, char* str); extern XNAddrToString_t XNAddrToString; @@ -659,8 +662,6 @@ namespace Game extern infoParm_t* infoParams; - extern clientState_t* clcState; - extern GfxScene* scene; extern Console* con; diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index aa045a9f..59bbb4ea 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -2,15 +2,11 @@ #ifndef RC_INVOKED -#define VC_EXTRALEAN #define WIN32_LEAN_AND_MEAN #define _CRT_SECURE_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _USE_MATH_DEFINES -// Requires Visual Leak Detector plugin: http://vld.codeplex.com/ -#define VLD_FORCE_ENABLE -//#include - #include #include #include