From 52c960247342cb55133f72589644daa65462e83c Mon Sep 17 00:00:00 2001 From: Diavolo Date: Thu, 16 Jun 2022 16:15:26 +0200 Subject: [PATCH] [Dedicated] Fix --- src/Components/Loader.cpp | 3 + src/Components/Modules/Branding.cpp | 19 +- src/Components/Modules/Chat.cpp | 2 +- src/Components/Modules/Command.cpp | 4 +- src/Components/Modules/Command.hpp | 5 +- src/Components/Modules/ConnectProtocol.cpp | 2 +- src/Components/Modules/Dedicated.cpp | 22 +-- src/Components/Modules/Download.cpp | 2 +- src/Components/Modules/Dvar.cpp | 39 ++-- src/Components/Modules/FastFiles.cpp | 41 ++-- src/Components/Modules/Friends.cpp | 2 +- src/Components/Modules/Logger.cpp | 212 +++++++++++---------- src/Components/Modules/Logger.hpp | 38 ++-- src/Components/Modules/Maps.cpp | 14 +- src/Components/Modules/Maps.hpp | 2 + src/Components/Modules/Node.cpp | 32 ++-- src/Components/Modules/Node.hpp | 2 +- src/Components/Modules/Party.cpp | 29 +-- src/Components/Modules/QuickPatch.cpp | 3 - src/Components/Modules/Session.cpp | 24 +-- src/Components/Modules/Session.hpp | 2 +- 21 files changed, 264 insertions(+), 235 deletions(-) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 196d645d..43a4acb1 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -115,6 +115,9 @@ namespace Components Loader::Register(new Events()); Loader::Pregame = false; + + // Make sure preDestroy is called when the game shuts down + Scheduler::OnGameShutdown(Loader::PreDestroy); } void Loader::Uninitialize() diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index 2e0b4686..605d0fdf 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -7,6 +7,12 @@ namespace Components Dvar::Var Branding::CGDrawVersionY; Game::dvar_t** Branding::Version = reinterpret_cast(0x1AD7930); +#ifdef _DEBUG + constexpr auto* BUILD_TYPE = "IW4x_DEV MP"; +#else + constexpr auto* BUILD_TYPE = "IW4x MP"; +#endif + void Branding::CG_DrawVersion() { // Default values @@ -45,15 +51,9 @@ namespace Components const char* Branding::GetVersionString() { -#ifdef _DEBUG - const auto* buildType = "IW4x_DEV MP"; -#else - const auto* buildType = "IW4x MP"; -#endif - // IW4x is technically a beta const auto* result = Utils::String::VA("%s %s build %s %s", - buildType, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast(0x7170A0)); + BUILD_TYPE, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast(0x7170A0)); return result; } @@ -103,6 +103,11 @@ namespace Components // Short version dvar Utils::Hook::Set(0x60BD91, SHORTVERSION); + // Com_Init_Try_Block_Function + Utils::Hook::Set(0x60BAF4, BUILD_TYPE); + Utils::Hook::Set(0x60BAEf, SHORTVERSION); + Utils::Hook::Set(0x60BAE5, __DATE__); + Utils::Hook(0x4B12B0, Branding::GetBuildNumber, HOOK_JUMP).install()->quick(); // Version string color diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 69bcff29..d40e2082 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -410,7 +410,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_flag::DVAR_NONE, "Disable chat messages from clients"); - Scheduler::Once(Chat::AddChatCommands, Scheduler::Pipeline::MAIN); + Scheduler::OnGameInitialized(AddChatCommands, Scheduler::Pipeline::SERVER); // Intercept chat sending Utils::Hook(0x4D000B, PreSayStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Command.cpp b/src/Components/Modules/Command.cpp index a0acb4a8..7e9f58dd 100644 --- a/src/Components/Modules/Command.cpp +++ b/src/Components/Modules/Command.cpp @@ -84,7 +84,7 @@ namespace Components { if (Loader::IsPregame()) { - MessageBoxA(nullptr, "Registering server commands in pregamestate is illegal!", nullptr, MB_ICONERROR); + MessageBoxA(nullptr, "Registering server commands in pregame state is illegal!", nullptr, MB_ICONERROR); #ifdef DEBUG __debugbreak(); @@ -103,7 +103,7 @@ namespace Components Command::AddRaw(name, Game::Cbuf_AddServerText); } - FunctionMapSV.insert_or_assign(command, std::move(callback)); + FunctionMapSV.insert_or_assign(command, callback); } void Command::AddRaw(const char* name, void(*callback)(), bool key) diff --git a/src/Components/Modules/Command.hpp b/src/Components/Modules/Command.hpp index cf67995c..d6538080 100644 --- a/src/Components/Modules/Command.hpp +++ b/src/Components/Modules/Command.hpp @@ -53,9 +53,8 @@ namespace Components static void Add(const char* name, const std::function& callback); static void Add(const char* name, const std::function& callback); - static void AddSV(const char* name, const std::function& callback); static void AddRaw(const char* name, void(*callback)(), bool key = false); - static void AddRawSV(const char* name, void(*callback)()); + static void AddSV(const char* name, const std::function& callback); static void Execute(std::string command, bool sync = true); static Game::cmd_function_t* Find(const std::string& command); @@ -64,6 +63,8 @@ namespace Components static std::unordered_map> FunctionMap; static std::unordered_map> FunctionMapSV; + static void AddRawSV(const char* name, void(*callback)()); + static void MainCallback(); static void MainCallbackSV(); }; diff --git a/src/Components/Modules/ConnectProtocol.cpp b/src/Components/Modules/ConnectProtocol.cpp index 703bb2f5..d8d8023a 100644 --- a/src/Components/Modules/ConnectProtocol.cpp +++ b/src/Components/Modules/ConnectProtocol.cpp @@ -232,7 +232,7 @@ namespace Components // Only skip intro here, invocation will be done later. Utils::Hook::Set(0x60BECF, 0xEB); - Scheduler::Once([]() + Scheduler::Once([] { Command::Execute("openmenu popup_reconnectingtoparty", false); }, Scheduler::Pipeline::CLIENT, 8s); diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 684582e1..7d68e749 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -140,9 +140,6 @@ namespace Components void Dedicated::AddDedicatedCommands() { - Dvar::Register("sv_sayName", "^7Console", Game::dvar_flag::DVAR_NONE, "The name to pose as for 'say' commands"); - Dvar::Register("sv_motd", "", Game::dvar_flag::DVAR_NONE, "A custom message of the day for servers"); - // Say command Command::AddSV("say", [](Command::Params* params) { @@ -214,7 +211,7 @@ namespace Components if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) { // Make sure all callbacks are handled - Scheduler::Loop(Steam::SteamAPI_RunCallbacks, Scheduler::Pipeline::MAIN); + Scheduler::Loop(Steam::SteamAPI_RunCallbacks, Scheduler::Pipeline::SERVER); Dedicated::SVLanOnly = Dvar::Register("sv_lanOnly", false, Game::dvar_flag::DVAR_NONE, "Don't act as node"); @@ -282,7 +279,13 @@ namespace Components if (!ZoneBuilder::IsEnabled()) { - Scheduler::Once(Dedicated::AddDedicatedCommands, Scheduler::Pipeline::MAIN); + Scheduler::Once([] + { + Dvar::Register("sv_sayName", "^7Console", Game::dvar_flag::DVAR_NONE, "The name to pose as for 'say' commands"); + Dvar::Register("sv_motd", "", Game::dvar_flag::DVAR_NONE, "A custom message of the day for servers"); + }, Scheduler::Pipeline::MAIN); + + Scheduler::OnGameInitialized(Dedicated::AddDedicatedCommands, Scheduler::Pipeline::SERVER); // Post initialization point Utils::Hook(0x60BFBF, Dedicated::PostInitializationStub, HOOK_JUMP).install()->quick(); @@ -295,13 +298,8 @@ namespace Components }, Scheduler::Pipeline::SERVER, 10s); // Heartbeats - Scheduler::Loop([] - { - if (Dvar::Var("sv_maxclients").get() > 0) - { - Dedicated::Heartbeat(); - } - }, Scheduler::Pipeline::SERVER, 2min); + Scheduler::Once(Dedicated::Heartbeat, Scheduler::Pipeline::SERVER); + Scheduler::Loop(Dedicated::Heartbeat, Scheduler::Pipeline::SERVER, 2min); } } else diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 6e1d06b1..d16e76ee 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -961,7 +961,7 @@ namespace Components }, Scheduler::Pipeline::MAIN); - Events::OnVMShutdown([]() + Events::OnVMShutdown([] { Download::ScriptDownloads.clear(); }); diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index bddfbcf2..bd8506b8 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -213,26 +213,29 @@ namespace Components Game::dvar_t* Dvar::Dvar_RegisterName(const char* name, const char* /*default*/, unsigned __int16 flags, const char* description) { // Name watcher - Scheduler::Loop([] + if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) { - static std::string lastValidName = "Unknown Soldier"; - auto name = Dvar::Var("name").get(); - - // 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))); - if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{')) + Scheduler::Loop([] { - Logger::Print("Username '{}' is invalid. It must at least be 3 characters long and not appear empty!\n", name); - Dvar::Var("name").set(lastValidName); - } - else - { - lastValidName = name; - Friends::UpdateName(); - } - }, Scheduler::MAIN, 3s); // Don't need to do this every frame + static std::string lastValidName = "Unknown Soldier"; + auto name = Dvar::Var("name").get(); + + // 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))); + if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{')) + { + Logger::Print("Username '{}' is invalid. It must at least be 3 characters long and not appear empty!\n", name); + Dvar::Var("name").set(lastValidName); + } + else + { + lastValidName = name; + Friends::UpdateName(); + } + }, Scheduler::CLIENT, 3s); // Don't need to do this every frame + } std::string username = "Unknown Soldier"; diff --git a/src/Components/Modules/FastFiles.cpp b/src/Components/Modules/FastFiles.cpp index f728b786..5ac44386 100644 --- a/src/Components/Modules/FastFiles.cpp +++ b/src/Components/Modules/FastFiles.cpp @@ -569,28 +569,31 @@ namespace Components FastFiles::AddZonePath("zone\\patch\\"); FastFiles::AddZonePath("zone\\dlc\\"); - Scheduler::Loop([]() + if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) { - if (FastFiles::Current().empty() || !Dvar::Var("ui_zoneDebug").get()) return; - - auto* const font = Game::R_RegisterFont("fonts/consoleFont", 0); - float color[4] = {1.0f, 1.0f, 1.0f, (Game::CL_IsCgameInitialized() ? 0.3f : 1.0f)}; - - auto FFTotalSize = *reinterpret_cast(0x10AA5D8); - auto FFCurrentOffset = *reinterpret_cast(0x10AA608); - - float fastfileLoadProgress = (float(FFCurrentOffset) / float(FFTotalSize)) * 100.0f; - if (std::isinf(fastfileLoadProgress)) + Scheduler::Loop([] { - fastfileLoadProgress = 100.0f; - } - else if (std::isnan(fastfileLoadProgress)) - { - fastfileLoadProgress = 0.0f; - } + if (FastFiles::Current().empty() || !Dvar::Var("ui_zoneDebug").get()) return; - Game::R_AddCmdDrawText(Utils::String::VA("Loading FastFile: %s [%0.1f%%]", FastFiles::Current().data(), fastfileLoadProgress), 0x7FFFFFFF, font, 5.0f, static_cast(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL); - }, Scheduler::Pipeline::RENDERER); + auto* const font = Game::R_RegisterFont("fonts/consoleFont", 0); + float color[4] = {1.0f, 1.0f, 1.0f, (Game::CL_IsCgameInitialized() ? 0.3f : 1.0f)}; + + auto FFTotalSize = *reinterpret_cast(0x10AA5D8); + auto FFCurrentOffset = *reinterpret_cast(0x10AA608); + + float fastfileLoadProgress = (float(FFCurrentOffset) / float(FFTotalSize)) * 100.0f; + if (std::isinf(fastfileLoadProgress)) + { + fastfileLoadProgress = 100.0f; + } + else if (std::isnan(fastfileLoadProgress)) + { + fastfileLoadProgress = 0.0f; + } + + Game::R_AddCmdDrawText(Utils::String::VA("Loading FastFile: %s [%0.1f%%]", FastFiles::Current().data(), fastfileLoadProgress), std::numeric_limits::max(), font, 5.0f, static_cast(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL); + }, Scheduler::Pipeline::RENDERER); + } Command::Add("loadzone", [](Command::Params* params) { diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index a7dc04c2..bb0cff57 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -724,7 +724,7 @@ namespace Components Friends::UpdateState(); Friends::UpdateFriends(); - }, Scheduler::Pipeline::MAIN); + }, Scheduler::Pipeline::CLIENT); } Friends::~Friends() diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 98382d14..f2e59616 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -246,6 +246,111 @@ namespace Components } } + void Logger::AddServerCommands() + { + Command::AddSV("log_add", [](Command::Params* params) + { + if (params->size() < 2) return; + + Network::Address addr(params->get(1)); + + if (std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr) == Logger::LoggingAddresses[0].end()) + { + Logger::LoggingAddresses[0].push_back(addr); + } + }); + + Command::AddSV("log_del", [](Command::Params* params) + { + if (params->size() < 2) return; + + int num = atoi(params->get(1)); + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[0].size()) + { + auto addr = Logger::LoggingAddresses[0].begin() + num; + Logger::Print("Address {} removed\n", addr->getCString()); + Logger::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()) + { + Logger::LoggingAddresses[0].erase(i); + Logger::Print("Address {} removed\n", addr.getCString()); + } + else + { + Logger::Print("Address {} not found!\n", addr.getCString()); + } + } + }); + + Command::AddSV("log_list", [](Command::Params*) + { + Logger::Print("# ID: Address\n"); + Logger::Print("-------------\n"); + + for (unsigned int i = 0; i < Logger::LoggingAddresses[0].size(); ++i) + { + Logger::Print("{}: {}\n", i, Logger::LoggingAddresses[0][i].getCString()); + } + }); + + Command::AddSV("g_log_add", [](Command::Params* params) + { + if (params->size() < 2) return; + + const Network::Address addr(params->get(1)); + + if (std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr) == Logger::LoggingAddresses[1].end()) + { + Logger::LoggingAddresses[1].push_back(addr); + } + }); + + Command::AddSV("g_log_del", [](Command::Params* params) + { + if (params->size() < 2) return; + + int num = atoi(params->get(1)); + if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[1].size()) + { + const auto addr = Logger::LoggingAddresses[1].begin() + num; + Logger::Print("Address {} removed\n", addr->getCString()); + Logger::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()) + { + Logger::LoggingAddresses[1].erase(i); + Logger::Print("Address {} removed\n", addr.getCString()); + } + else + { + Logger::Print("Address {} not found!\n", addr.getCString()); + } + } + }); + + Command::AddSV("g_log_list", [](Command::Params*) + { + Logger::Print("# ID: Address\n"); + Logger::Print("-------------\n"); + + for (std::size_t i = 0; i < Logger::LoggingAddresses[1].size(); ++i) + { + Logger::Print("{}: {}\n", i, Logger::LoggingAddresses[1][i].getCString()); + } + }); + } + Logger::Logger() { Dvar::Register("iw4x_onelog", false, Game::dvar_flag::DVAR_LATCH | Game::dvar_flag::DVAR_ARCHIVE, "Only write the game log to the 'userraw' OS folder"); @@ -253,7 +358,7 @@ namespace Components Logger::PipeOutput(nullptr); - Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::MAIN); + Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::SERVER); Utils::Hook(0x4B0218, Logger::GameLogStub, HOOK_CALL).install()->quick(); Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).install()->quick(); @@ -263,110 +368,7 @@ namespace Components Utils::Hook(Game::Com_Printf, Logger::PrintStub, HOOK_JUMP).install()->quick(); } - Scheduler::Once([] - { - Command::AddSV("log_add", [](Command::Params* params) - { - if (params->size() < 2) return; - - Network::Address addr(params->get(1)); - - if (std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr) == Logger::LoggingAddresses[0].end()) - { - Logger::LoggingAddresses[0].push_back(addr); - } - }); - - Command::AddSV("log_del", [](Command::Params* params) - { - if (params->size() < 2) return; - - int num = atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[0].size()) - { - auto addr = Logger::LoggingAddresses[0].begin() + num; - Logger::Print("Address %s removed\n", addr->getCString()); - Logger::LoggingAddresses[0].erase(addr); - } - else - { - Network::Address addr(params->get(1)); - - auto i = std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr); - if (i != Logger::LoggingAddresses[0].end()) - { - Logger::LoggingAddresses[0].erase(i); - Logger::Print("Address %s removed\n", addr.getCString()); - } - else - { - Logger::Print("Address %s not found!\n", addr.getCString()); - } - } - }); - - Command::AddSV("log_list", [](Command::Params*) - { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); - - for (unsigned int i = 0; i < Logger::LoggingAddresses[0].size(); ++i) - { - Logger::Print("#%03d: %5s\n", i, Logger::LoggingAddresses[0][i].getCString()); - } - }); - - Command::AddSV("g_log_add", [](Command::Params* params) - { - if (params->size() < 2) return; - - Network::Address addr(params->get(1)); - - if (std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr) == Logger::LoggingAddresses[1].end()) - { - Logger::LoggingAddresses[1].push_back(addr); - } - }); - - Command::AddSV("g_log_del", [](Command::Params* params) - { - if (params->size() < 2) return; - - int num = atoi(params->get(1)); - if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast(num) < Logger::LoggingAddresses[1].size()) - { - auto addr = Logger::LoggingAddresses[1].begin() + num; - Logger::Print("Address %s removed\n", addr->getCString()); - Logger::LoggingAddresses[1].erase(addr); - } - else - { - Network::Address addr(params->get(1)); - - auto i = std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr); - if (i != Logger::LoggingAddresses[1].end()) - { - Logger::LoggingAddresses[1].erase(i); - Logger::Print("Address %s removed\n", addr.getCString()); - } - else - { - Logger::Print("Address %s not found!\n", addr.getCString()); - } - } - }); - - Command::AddSV("g_log_list", [](Command::Params*) - { - Logger::Print("# ID: Address\n"); - Logger::Print("-------------\n"); - - for (unsigned int i = 0; i < Logger::LoggingAddresses[1].size(); ++i) - { - Logger::Print("#%03d: %5s\n", i, Logger::LoggingAddresses[1][i].getCString()); - } - }); - }, Scheduler::Pipeline::MAIN); + Scheduler::OnGameInitialized(Logger::AddServerCommands, Scheduler::Pipeline::SERVER); } Logger::~Logger() diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 4ff9fdd0..7af904a8 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -23,99 +23,99 @@ namespace Components static void WarningInternal(int channel, std::string_view fmt, std::format_args&& args); static void DebugInternal(bool verbose, const std::source_location& srcLoc, std::string_view fmt, std::format_args&& args); - static inline void Print(std::string_view fmt) + __forceinline static void Print(std::string_view fmt) { PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(0)); } - static inline void Print(int channel, std::string_view fmt) + __forceinline static void Print(int channel, std::string_view fmt) { PrintInternal(channel, fmt, std::make_format_args(0)); } template - static inline void Print(std::string_view fmt, Args&&... args) + __forceinline static void Print(std::string_view fmt, Args&&... args) { PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(args...)); } template - static inline void Print(int channel, std::string_view fmt, Args&&... args) + __forceinline static void Print(int channel, std::string_view fmt, Args&&... args) { PrintInternal(channel, fmt, std::make_format_args(args...)); } - static inline void Error(Game::errorParm_t error, std::string_view fmt) + __forceinline static void Error(Game::errorParm_t error, std::string_view fmt) { ErrorInternal(error, fmt, std::make_format_args(0)); } template - static inline void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args) + __forceinline static void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args) { ErrorInternal(error, fmt, std::make_format_args(args...)); } - static inline void Warning(int channel, std::string_view fmt) + __forceinline static void Warning(int channel, std::string_view fmt) { WarningInternal(channel, fmt, std::make_format_args(0)); } template - static inline void Warning(int channel, std::string_view fmt, Args&&... args) + __forceinline static void Warning(int channel, std::string_view fmt, Args&&... args) { WarningInternal(channel, fmt, std::make_format_args(args...)); } - static inline void PrintError(int channel, std::string_view fmt) + __forceinline static void PrintError(int channel, std::string_view fmt) { PrintErrorInternal(channel, fmt, std::make_format_args(0)); } template - static inline void PrintError(int channel, std::string_view fmt, Args&&... args) + __forceinline static void PrintError(int channel, std::string_view fmt, Args&&... args) { PrintErrorInternal(channel, fmt, std::make_format_args(args...)); } #ifdef _DEBUG - static inline void DebugInfo([[maybe_unused]] std::string_view fmt) + __forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt) { DebugInternal(true, std::source_location::current(), fmt, std::make_format_args(0)); } template - static inline void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) + __forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) { DebugInternal(true, std::source_location::current(), fmt, std::make_format_args(args...)); } - static inline void Debug([[maybe_unused]] std::string_view fmt) + __forceinline static void Debug([[maybe_unused]] std::string_view fmt) { DebugInternal(false, std::source_location::current(), fmt, std::make_format_args(0)); } template - static inline void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) + __forceinline static void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) { DebugInternal(false, std::source_location::current(), fmt, std::make_format_args(args...)); } #else - static inline void DebugInfo([[maybe_unused]] std::string_view fmt) + __forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt) { } template - static inline void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) + __forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) { } - static inline void Debug([[maybe_unused]] std::string_view fmt) + __forceinline static void Debug([[maybe_unused]] std::string_view fmt) { } template - static inline void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) + __forceinline static void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args) { } #endif @@ -136,5 +136,7 @@ namespace Components static void RedirectOSPath(const char* file, char* folder); static void NetworkLog(const char* data, bool gLog); + + static void AddServerCommands(); }; } diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 65e40a3d..cb4cf148 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -7,6 +7,8 @@ namespace Components std::vector> Maps::DependencyList; std::vector Maps::CurrentDependencies; + Dvar::Var Maps::RListSModels; + bool Maps::SPMap; std::vector Maps::DlcPacks; @@ -775,7 +777,7 @@ namespace Components Scheduler::Once([] { Dvar::Register("isDlcInstalled_All", false, Game::DVAR_EXTERNAL | Game::DVAR_WRITEPROTECTED, ""); - Dvar::Register("r_listSModels", false, Game::DVAR_NONE, "Display a list of visible SModels"); + Maps::RListSModels = Dvar::Register("r_listSModels", false, Game::DVAR_NONE, "Display a list of visible SModels"); Maps::AddDlc({ 1, "Stimulus Pack", {"mp_complex", "mp_compact", "mp_storm", "mp_overgrown", "mp_crash"} }); Maps::AddDlc({ 2, "Resurgence Pack", {"mp_abandon", "mp_vacant", "mp_trailerpark", "mp_strike", "mp_fuel2"} }); @@ -882,7 +884,7 @@ namespace Components Utils::Hook(0x5A9D51, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5B34DD, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick(); - Command::Add("delayReconnect", [](Command::Params*) + Command::Add("delayReconnect", []([[maybe_unused]] Command::Params* params) { Scheduler::Once([] { @@ -913,10 +915,16 @@ namespace Components // Allow hiding specific smodels Utils::Hook(0x50E67C, Maps::HideModelStub, HOOK_CALL).install()->quick(); + if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) + { + return; + } + + // Client only Scheduler::Loop([] { auto*& gameWorld = *reinterpret_cast(0x66DEE94); - if (!Game::CL_IsCgameInitialized() || !gameWorld || !Dvar::Var("r_listSModels").get()) return; + if (!Game::CL_IsCgameInitialized() || !gameWorld || !Maps::RListSModels.get()) return; std::map models; for (unsigned int i = 0; i < gameWorld->dpvs.smodelCount; ++i) diff --git a/src/Components/Modules/Maps.hpp b/src/Components/Modules/Maps.hpp index 75f9df7a..80e015c2 100644 --- a/src/Components/Modules/Maps.hpp +++ b/src/Components/Modules/Maps.hpp @@ -83,6 +83,8 @@ namespace Components static std::vector> DependencyList; static std::vector CurrentDependencies; + static Dvar::Var RListSModels; + static void GetBSPName(char* buffer, size_t size, const char* format, const char* mapname); static void LoadAssetRestrict(Game::XAssetType type, Game::XAssetHeader asset, const std::string& name, bool* restrict); static void LoadMapZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync); diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 57a1e73b..991d1ba0 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -146,7 +146,7 @@ namespace Components if (!address.isValid()) return; - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); for (auto& session : Node::Nodes) { if (session.address == address) return; @@ -160,7 +160,7 @@ namespace Components std::vector Node::GetNodes() { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); return Node::Nodes; } @@ -197,7 +197,7 @@ namespace Components if (!frameLimit.elapsed(std::chrono::milliseconds(interval))) return; frameLimit.update(); - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); Dvar::Var queryLimit("net_serverQueryLimit"); int sentRequests = 0; @@ -220,7 +220,7 @@ namespace Components void Node::Synchronize() { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); for (auto& node : Node::Nodes) { //if (node.isValid()) // Comment out to simulate 'syncnodes' behaviour @@ -237,7 +237,7 @@ namespace Components Logger::DebugInfo("Received response from {}\n", address.getCString()); - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); for (int i = 0; i < list.nodes_size(); ++i) { @@ -282,9 +282,9 @@ namespace Components } } - void Node::SendList(Network::Address address) + void Node::SendList(const Network::Address& address) { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); // need to keep the message size below 1404 bytes else recipient will just drop it std::vector nodeListReponseMessages; @@ -320,11 +320,13 @@ namespace Components auto i = 0; for (const auto& nodeListData : nodeListReponseMessages) { - Scheduler::Once([&] + Scheduler::Once([=] { - Logger::DebugInfo("Sending {} nodeListResponse length to {}\n", nodeListData.length(), address.getCString()); +#ifdef DEBUG_NODE + Logger::Debug("Sending {} nodeListResponse length to {}\n", nodeListData.length(), address.getCString()); +#endif Session::Send(address, "nodeListResponse", nodeListData); - }, Scheduler::Pipeline::MAIN, NODE_SEND_RATE * i++); + }, Scheduler::Pipeline::SERVER, NODE_SEND_RATE * i++); } } @@ -344,16 +346,16 @@ namespace Components Node::StoreNodes(false); }, Scheduler::Pipeline::ASYNC); - Scheduler::Loop(Node::RunFrame, Scheduler::Pipeline::MAIN); + Scheduler::Loop(Node::RunFrame, Scheduler::Pipeline::SERVER); Session::Handle("nodeListResponse", Node::HandleResponse); - Session::Handle("nodeListRequest", [](Network::Address address, const std::string&) + Session::Handle("nodeListRequest", [](const Network::Address& address, const std::string&) { Node::SendList(address); }); // Load stored nodes - auto loadNodes = []() + auto loadNodes = [] { Node::LoadNodePreset(); Node::LoadNodes(); @@ -374,7 +376,7 @@ namespace Components { Logger::Print("Nodes: {}\n", Node::Nodes.size()); - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); for (auto& node : Node::Nodes) { Logger::Print("{}\t({})\n", node.address.getCString(), node.isValid() ? "Valid" : "Invalid"); @@ -390,7 +392,7 @@ namespace Components Node::~Node() { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Node::Mutex); Node::StoreNodes(true); Node::Nodes.clear(); } diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index 253cc8d4..965e6955 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -51,7 +51,7 @@ namespace Components static void HandleResponse(Network::Address address, const std::string& data); - static void SendList(Network::Address address); + static void SendList(const Network::Address& address); static void LoadNodePreset(); static void LoadNodes(); diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index e48791cf..7d1e2d64 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -286,27 +286,30 @@ namespace Components Party::Connect(Party::Container.target); }); - Scheduler::Loop([] + if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) { - if (Party::Container.valid) + Scheduler::Loop([] { - if ((Game::Sys_Milliseconds() - Party::Container.joinTime) > 10'000) + if (Party::Container.valid) { - Party::Container.valid = false; - Party::ConnectError("Server connection timed out."); + if ((Game::Sys_Milliseconds() - Party::Container.joinTime) > 10'000) + { + Party::Container.valid = false; + Party::ConnectError("Server connection timed out."); + } } - } - if (Party::Container.awaitingPlaylist) - { - if ((Game::Sys_Milliseconds() - Party::Container.requestTime) > 5'000) + if (Party::Container.awaitingPlaylist) { - Party::Container.awaitingPlaylist = false; - Party::ConnectError("Playlist request timed out."); + if ((Game::Sys_Milliseconds() - Party::Container.requestTime) > 5'000) + { + Party::Container.awaitingPlaylist = false; + Party::ConnectError("Playlist request timed out."); + } } - } - }, Scheduler::Pipeline::CLIENT); + }, Scheduler::Pipeline::CLIENT); + } // Basic info handler Network::OnPacket("getInfo", [](const Network::Address& address, [[maybe_unused]] const std::string& data) diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 80c8f4b4..d63a583f 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -263,9 +263,6 @@ namespace Components Utils::Hook(0x4FA448, QuickPatch::Dvar_RegisterConMinicon, HOOK_CALL).install()->quick(); - // Make sure preDestroy is called when the game shuts down - Scheduler::OnGameShutdown(Loader::PreDestroy); - // protocol version (workaround for hacks) Utils::Hook::Set(0x4FB501, PROTOCOL); diff --git a/src/Components/Modules/Session.cpp b/src/Components/Modules/Session.cpp index d6b175d5..1f575184 100644 --- a/src/Components/Modules/Session.cpp +++ b/src/Components/Modules/Session.cpp @@ -15,7 +15,7 @@ namespace Components std::queue> Session::SignatureQueue; - void Session::Send(Network::Address target, const std::string& command, const std::string& data) + void Session::Send(const Network::Address& target, const std::string& command, const std::string& data) { #ifdef DISABLE_SESSION class DelayedResend @@ -26,27 +26,27 @@ namespace Components std::string data; }; - DelayedResend* delayData = new DelayedResend; + auto* delayData = new DelayedResend; delayData->target = target; delayData->command = command; delayData->data = data; Network::SendCommand(target, command, data); - Scheduler::Once([delayData]() + Scheduler::Once([delayData] { Network::SendCommand(delayData->target, delayData->command, delayData->data); delete delayData; - }, Scheduler::Pipeline::MAIN, 500ms + std::chrono::milliseconds(rand() % 200)); + }, Scheduler::Pipeline::SERVER, 500ms + std::chrono::milliseconds(std::rand() % 200)); #else - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); auto queue = Session::PacketQueue.find(target); if (queue == Session::PacketQueue.end()) { Session::PacketQueue[target] = std::queue>(); queue = Session::PacketQueue.find(target); - if (queue == Session::PacketQueue.end()) Logger::Error("Failed to enqueue session packet!\n"); + if (queue == Session::PacketQueue.end()) Logger::Error(Game::ERR_FATAL, "Failed to enqueue session packet!\n"); } std::shared_ptr packet = std::make_shared(); @@ -63,14 +63,14 @@ namespace Components #ifdef DISABLE_SESSION Network::OnPacket(packet, callback); #else - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); Session::PacketHandlers[packet] = callback; #endif } void Session::RunFrame() { - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); for (auto queue = Session::PacketQueue.begin(); queue != Session::PacketQueue.end();) { @@ -155,7 +155,7 @@ namespace Components Session::Frame frame; frame.challenge = Utils::Cryptography::Rand::GenerateChallenge(); - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); Session::Sessions[address] = frame; Network::SendCommand(address, "sessionAck", frame.challenge); @@ -163,13 +163,13 @@ namespace Components Network::OnPacket("sessionAck", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); Session::SignatureQueue.push({ address, data }); }); Network::OnPacket("sessionFin", [](Network::Address& address, [[maybe_unused]] const std::string& data) { - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); auto frame = Session::Sessions.find(address); if (frame == Session::Sessions.end()) return; @@ -195,7 +195,7 @@ namespace Components Session::~Session() { - std::lock_guard _(Session::Mutex); + std::lock_guard _(Session::Mutex); Session::PacketHandlers.clear(); Session::PacketQueue.clear(); Session::SignatureQueue = std::queue>(); diff --git a/src/Components/Modules/Session.hpp b/src/Components/Modules/Session.hpp index 557d528a..83177d58 100644 --- a/src/Components/Modules/Session.hpp +++ b/src/Components/Modules/Session.hpp @@ -34,7 +34,7 @@ namespace Components bool unitTest() override; void preDestroy() override; - static void Send(Network::Address target, const std::string& command, const std::string& data = ""); + 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); private: