From ec31a5239e6552bbd8e6ed981da8cc2d5b84e687 Mon Sep 17 00:00:00 2001 From: Stanbroek <32653890+Stanbroek@users.noreply.github.com> Date: Sun, 19 Sep 2021 15:55:55 +0200 Subject: [PATCH] Open-source release for Rocket Plugin 0.6.8. - Add nullcheck marco's everywhere. - Changed the log marco names to avoid conflicts. - Added Notifier to clear physics cache. - Upgraded to c++20. - Rewrote CrazyRumble. - Split RocketPlugin.cpp into modules. - Split ExternalFunctions.cpp into external modules. - Added colored logs. --- .../include/utils/cvarmanagerwrapperdebug.h | 317 +++- .../include/utils/exception_safety.h | 53 +- .../include/utils/filesystem.h | 54 + .../include/utils/parser_w.h | 170 +- .../include/utils/se_exception.h | 31 +- .../include/utils/stackwalker.h | 393 ++-- .../include/utils/stringify.h | 24 +- .../include/utils/threading.h | 188 +- .../BakkesModAdditions/include/utils/timer.h | 52 + .../include/utils/win32_error_category.h | 10 +- .../BakkesModAdditions/include/utils/xorstr.h | 154 -- source/External/BakkesModSDK | 2 +- source/External/simdjson | 2 +- source/RocketPlugin/ExternalFunctions.cpp | 313 ---- .../ExternalModules/ExternalFunctions.cpp | 152 ++ .../ExternalModules/ExternalModules.cpp | 154 ++ .../ExternalModules/ExternalModules.h | 109 ++ .../RocketPlugin/ExternalModules/RPTests.cpp | 37 + source/RocketPlugin/GameModes/BoostMod.cpp | 66 +- source/RocketPlugin/GameModes/BoostMod.h | 6 +- source/RocketPlugin/GameModes/BoostShare.cpp | 109 +- source/RocketPlugin/GameModes/BoostShare.h | 3 +- source/RocketPlugin/GameModes/BoostSteal.cpp | 5 +- source/RocketPlugin/GameModes/BoostSteal.h | 3 +- source/RocketPlugin/GameModes/CrazyRumble.cpp | 293 +-- source/RocketPlugin/GameModes/CrazyRumble.h | 66 +- source/RocketPlugin/GameModes/Drainage.cpp | 23 +- source/RocketPlugin/GameModes/Drainage.h | 3 +- source/RocketPlugin/GameModes/Empty.h | 3 +- source/RocketPlugin/GameModes/Juggernaut.cpp | 39 +- source/RocketPlugin/GameModes/Juggernaut.h | 3 +- source/RocketPlugin/GameModes/KeepAway.cpp | 80 +- source/RocketPlugin/GameModes/KeepAway.h | 3 +- .../RocketPlugin/GameModes/RocketGameMode.h | 191 +- .../GameModes/RumbleItems/RumbleConstants.inc | 60 +- .../GameModes/RumbleItems/RumbleItems.cpp | 382 ++-- .../GameModes/RumbleItems/RumbleItems.h | 308 +++- .../RocketPlugin/GameModes/SacredGround.cpp | 30 +- source/RocketPlugin/GameModes/SacredGround.h | 4 +- source/RocketPlugin/GameModes/SmallCars.cpp | 24 +- source/RocketPlugin/GameModes/SmallCars.h | 4 +- source/RocketPlugin/GameModes/Tag.cpp | 62 +- source/RocketPlugin/GameModes/Tag.h | 4 +- source/RocketPlugin/GameModes/Zombies.cpp | 61 +- source/RocketPlugin/GameModes/Zombies.h | 3 +- source/RocketPlugin/Modules/BallMods.cpp | 101 ++ source/RocketPlugin/Modules/BallMods.h | 20 + source/RocketPlugin/Modules/BotSettings.cpp | 141 ++ source/RocketPlugin/Modules/BotSettings.h | 23 + .../RocketPlugin/Modules/CarPhysicsMods.cpp | 304 ++++ source/RocketPlugin/Modules/CarPhysicsMods.h | 44 + source/RocketPlugin/Modules/Empty.cpp | 8 + source/RocketPlugin/Modules/Empty.h | 14 + source/RocketPlugin/Modules/GameControls.cpp | 74 + source/RocketPlugin/Modules/GameControls.h | 20 + .../Modules/LocalMatchSettings.cpp | 253 +++ .../RocketPlugin/Modules/LocalMatchSettings.h | 32 + source/RocketPlugin/Modules/PlayerMods.cpp | 123 ++ source/RocketPlugin/Modules/PlayerMods.h | 22 + .../Modules/RocketPluginModule.cpp | 4 + .../RocketPlugin/Modules/RocketPluginModule.h | 15 + source/RocketPlugin/Networking/Networking.cpp | 29 +- source/RocketPlugin/Networking/Networking.h | 6 +- source/RocketPlugin/Networking/P2PHost.cpp | 72 +- source/RocketPlugin/Networking/UPnPClient.cpp | 207 ++- source/RocketPlugin/RLConstants.inc | 10 +- .../RocketPlugin/{Config.cpp => RPConfig.cpp} | 115 +- source/RocketPlugin/{Config.h => RPConfig.h} | 27 +- source/RocketPlugin/RocketPlugin.cpp | 1606 +++-------------- source/RocketPlugin/RocketPlugin.h | 183 +- source/RocketPlugin/RocketPlugin.rc | 192 +- source/RocketPlugin/RocketPlugin.vcxproj | 400 ++-- .../RocketPlugin/RocketPlugin.vcxproj.filters | 489 ++--- source/RocketPlugin/RocketPluginGUI.cpp | 1441 ++++++++------- source/RocketPlugin/RocketPluginServer.cpp | 194 -- source/RocketPlugin/RocketPluginServer.h | 122 -- source/RocketPlugin/Version.h | 8 +- source/RocketPlugin/pch.h | 9 +- 78 files changed, 5326 insertions(+), 5035 deletions(-) create mode 100644 source/External/BakkesModAdditions/include/utils/filesystem.h create mode 100644 source/External/BakkesModAdditions/include/utils/timer.h delete mode 100644 source/External/BakkesModAdditions/include/utils/xorstr.h delete mode 100644 source/RocketPlugin/ExternalFunctions.cpp create mode 100644 source/RocketPlugin/ExternalModules/ExternalFunctions.cpp create mode 100644 source/RocketPlugin/ExternalModules/ExternalModules.cpp create mode 100644 source/RocketPlugin/ExternalModules/ExternalModules.h create mode 100644 source/RocketPlugin/ExternalModules/RPTests.cpp create mode 100644 source/RocketPlugin/Modules/BallMods.cpp create mode 100644 source/RocketPlugin/Modules/BallMods.h create mode 100644 source/RocketPlugin/Modules/BotSettings.cpp create mode 100644 source/RocketPlugin/Modules/BotSettings.h create mode 100644 source/RocketPlugin/Modules/CarPhysicsMods.cpp create mode 100644 source/RocketPlugin/Modules/CarPhysicsMods.h create mode 100644 source/RocketPlugin/Modules/Empty.cpp create mode 100644 source/RocketPlugin/Modules/Empty.h create mode 100644 source/RocketPlugin/Modules/GameControls.cpp create mode 100644 source/RocketPlugin/Modules/GameControls.h create mode 100644 source/RocketPlugin/Modules/LocalMatchSettings.cpp create mode 100644 source/RocketPlugin/Modules/LocalMatchSettings.h create mode 100644 source/RocketPlugin/Modules/PlayerMods.cpp create mode 100644 source/RocketPlugin/Modules/PlayerMods.h create mode 100644 source/RocketPlugin/Modules/RocketPluginModule.cpp create mode 100644 source/RocketPlugin/Modules/RocketPluginModule.h rename source/RocketPlugin/{Config.cpp => RPConfig.cpp} (71%) rename source/RocketPlugin/{Config.h => RPConfig.h} (59%) delete mode 100644 source/RocketPlugin/RocketPluginServer.cpp delete mode 100644 source/RocketPlugin/RocketPluginServer.h diff --git a/source/External/BakkesModAdditions/include/utils/cvarmanagerwrapperdebug.h b/source/External/BakkesModAdditions/include/utils/cvarmanagerwrapperdebug.h index f9fd8d9..c562c75 100644 --- a/source/External/BakkesModAdditions/include/utils/cvarmanagerwrapperdebug.h +++ b/source/External/BakkesModAdditions/include/utils/cvarmanagerwrapperdebug.h @@ -4,6 +4,7 @@ #include #include #include +#include /// https://fmt.dev/latest/syntax.html #ifndef FMT_HEADER_ONLY @@ -11,50 +12,47 @@ #endif #pragma warning(push, 0) #include "fmt/format.h" -#include "fmt/os.h" -#include "fmt/chrono.h" -#include "fmt/ranges.h" #include "fmt/ostream.h" +#include "fmt/color.h" #pragma warning(pop) #pragma warning(push, 0) #include "bakkesmod/wrappers/cvarmanagerwrapper.h" #pragma warning(pop) -#define __WIDETEXT(s) L##s -#define WIDETEXT(s) __WIDETEXT(s) -#define __STRINGIZE(s) #s -#define STRINGIZE(s) __STRINGIZE(s) +//#include "threading.h" +static bool is_game_thread(); +static bool is_render_thread(); -typedef unsigned int ImU32; -#ifndef IMGUI_API - #define COL32(R, G, B, A) ((static_cast(A) << 24) | (static_cast(B) << 16) | (static_cast(G) << 8) | static_cast(R)) -#else - #define COL32 IM_COL32 +#ifndef STRINGIZE + #define STRINGIZE2(s) #s + #define STRINGIZE(s) STRINGIZE2(s) #endif -constexpr ImU32 TraceColor = COL32(0x21, 0x96, 0xF3, 0xFF); -constexpr ImU32 InfoColor = COL32(0x9E, 0x9E, 0x9E, 0xFF); -constexpr ImU32 WarningColor = COL32(0xFF, 0x98, 0x00, 0xFF); -constexpr ImU32 ErrorColor = COL32(0xF4, 0x43, 0x36, 0xFF); -constexpr ImU32 CriticalColor = COL32(0x9C, 0x27, 0xB0, 0xFF); +#if defined(BMDEBUG) && defined(DEBUG) + #error Cannot define BMDEBUG and DEBUG. +#endif -#undef COL32 +#if defined(BMDEBUG) + #define DEBUG +#endif -static constexpr auto _filename(std::string_view path) -{ - return path.substr(path.find_last_of('\\') + 1); -} -#define __FILENAME__ (_filename(__FILE__)) +constexpr fmt::rgb TraceColor = fmt::rgb(0x21, 0x96, 0xF3); +constexpr fmt::rgb InfoColor = fmt::rgb(0x9E, 0x9E, 0x9E); +constexpr fmt::rgb WarningColor = fmt::rgb(0xFF, 0x98, 0x00); +constexpr fmt::rgb ErrorColor = fmt::rgb(0xF4, 0x43, 0x36); +constexpr fmt::rgb CriticalColor = fmt::rgb(0x9C, 0x27, 0xB0); -static constexpr auto _filename(std::wstring_view path) +static constexpr std::string_view filename_(const std::string_view& path) { - return path.substr(path.find_last_of(L'\\') + 1); + return path.substr(path.find_last_of('\\') + 1); } -#define __WIDEFILENAME__ (_filename(WIDETEXT(__FILE__))) +#ifndef PRETTY_FILENAME + #define PRETTY_FILENAME (filename_(__FILE__)) +#endif extern std::shared_ptr LogLevel; class CVarManagerWrapperDebug; @@ -74,14 +72,29 @@ class CVarManagerWrapperDebug : public CVarManagerWrapper critical = 1 << 4, all = -1, - normal = error | critical + normal = info | error | critical }; private: - void debug_log(const std::string& text, const int level, [[maybe_unused]] const ImU32 color) + std::string get_thread() const + { +#ifdef DEBUG + if (is_game_thread()) { + return "Game Thread: "; + } + if (is_render_thread()) { + return "Game Thread: "; + } + return fmt::format("Thread #{:s}: ", std::this_thread::get_id()); +#else + return ""; +#endif + } + + void debug_log(const std::string& text, const int level) { if (LogLevel && (*LogLevel & level)) { - log(text/*, color*/); + log(get_thread() + text); } } @@ -89,79 +102,257 @@ class CVarManagerWrapperDebug : public CVarManagerWrapper template void trace_log(const std::string& text, Args&&... args) { - debug_log(fmt::format("TRACE: " + text, args...), level_enum::trace, TraceColor); + debug_log(fmt::format(fg(TraceColor), "TRACE: " + text, args...), level_enum::trace); } template void info_log(const std::string& text, Args&&... args) { - debug_log(fmt::format("INFO: " + text, args...), level_enum::info, InfoColor); + debug_log(fmt::format(fg(InfoColor), "INFO: " + text, args...), level_enum::info); } template void warning_log(const std::string& text, Args&&... args) { - debug_log(fmt::format("WARNING: " + text, args...), level_enum::warning, WarningColor); + debug_log(fmt::format(fg(WarningColor), "WARNING: " + text, args...), level_enum::warning); } template void error_log(const std::string& text, Args&&... args) { - debug_log(fmt::format("ERROR: " + text, args...), level_enum::error, ErrorColor); + debug_log(fmt::format(fg(ErrorColor), "ERROR: " + text, args...), level_enum::error); } template void critical_log(const std::string& text, Args&&... args) { - debug_log(fmt::format("CRITICAL: " + text, args...), level_enum::critical, CriticalColor); + debug_log(fmt::format(fg(CriticalColor), "CRITICAL: " + text, args...), level_enum::critical); } -}; -#ifdef DEBUG - static std::string _replace_brackets(const std::string_view& original) + static constexpr std::string replace_brackets(const std::string_view& original) { - std::string retval; - retval.resize(original.size() * 2 + 1); + std::string str; + str.reserve(original.size() * 2 + 1); - size_t i = 0; for (const char c : original) { - retval[i++] = c; + str += c; if (c == '{' || c == '}') { - retval[i++] = c; + str += c; } } - retval.resize(i); + str.shrink_to_fit(); - return retval; + return str; } +}; - #define PREPEND_DEBUG_INFO(...) _replace_brackets(__FILENAME__) + ": " + _replace_brackets(__FUNCTION__) + "(), " STRINGIZE(__LINE__) ": " + __VA_ARGS__ +#ifdef DEBUG + #define PREPEND_DEBUG_INFO(...) CVarManagerWrapperDebug::replace_brackets(PRETTY_FILENAME) + ": " + CVarManagerWrapperDebug::replace_brackets(__FUNCTION__) + "(), " STRINGIZE(__LINE__) ": " + __VA_ARGS__ + //#define PREPEND_DEBUG_INFO(...) CVarManagerWrapperDebug::replace_brackets(PRETTY_FILENAME) + ": " + CVarManagerWrapperDebug::replace_brackets(__PRETTY_FUNCTION__) + "(), " STRINGIZE(__LINE__) ": " + __VA_ARGS__ #else #define PREPEND_DEBUG_INFO(...) __VA_ARGS__ #endif -#define LOG(...) GlobalCVarManager->log(fmt::format(PREPEND_DEBUG_INFO(__VA_ARGS__))) -#define TRACE_LOG(...) GlobalCVarManager->trace_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) -#define INFO_LOG(...) GlobalCVarManager->info_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) -#define WARNING_LOG(...) GlobalCVarManager->warning_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) -#define ERROR_LOG(...) GlobalCVarManager->error_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) -#define CRITICAL_LOG(...) GlobalCVarManager->critical_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) +#define BM_LOG(...) GlobalCVarManager->log(fmt::format(PREPEND_DEBUG_INFO(__VA_ARGS__))) +#define BM_TRACE_LOG(...) GlobalCVarManager->trace_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) +#define BM_INFO_LOG(...) GlobalCVarManager->info_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) +#define BM_WARNING_LOG(...) GlobalCVarManager->warning_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) +#define BM_ERROR_LOG(...) GlobalCVarManager->error_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) +#define BM_CRITICAL_LOG(...) GlobalCVarManager->critical_log (PREPEND_DEBUG_INFO(__VA_ARGS__)) #ifdef DEBUG - #define _TRACE_LOG(...) TRACE_LOG("*" + __VA_ARGS__) - #define _INFO_LOG(...) INFO_LOG("*" + __VA_ARGS__) - #define _WARNING_LOG(...) WARNING_LOG("*" + __VA_ARGS__) - #define _ERROR_LOG(...) ERROR_LOG("*" + __VA_ARGS__) - #define _CRITICAL_LOG(...) CRITICAL_LOG("*" + __VA_ARGS__) + #define BM_DEBUG_TRACE_LOG(...) BM_TRACE_LOG(std::string("*") + __VA_ARGS__) + #define BM_DEBUG_INFO_LOG(...) BM_INFO_LOG(std::string("*") + __VA_ARGS__) + #define BM_DEBUG_WARNING_LOG(...) BM_WARNING_LOG(std::string("*") + __VA_ARGS__) + #define BM_DEBUG_ERROR_LOG(...) BM_ERROR_LOG(std::string("*") + __VA_ARGS__) + #define BM_DEBUG_CRITICAL_LOG(...) BM_CRITICAL_LOG(std::string("*") + __VA_ARGS__) #else #ifdef _WIN32 - #define __NOOP __noop + #define NOOP_ __noop #else - #define __NOOP (void(0)) + #define NOOP_ (void(0)) #endif - #define _TRACE_LOG(...) __NOOP - #define _INFO_LOG(...) __NOOP - #define _WARNING_LOG(...) __NOOP - #define _ERROR_LOG(...) __NOOP - #define _CRITICAL_LOG(...) __NOOP + #define BM_DEBUG_TRACE_LOG(...) NOOP_ + #define BM_DEBUG_INFO_LOG(...) NOOP_ + #define BM_DEBUG_WARNING_LOG(...) NOOP_ + #define BM_DEBUG_ERROR_LOG(...) NOOP_ + #define BM_DEBUG_CRITICAL_LOG(...) NOOP_ +#endif + + +#define EXPAND_(x) x + +#define GET_3TH_ARG_(arg1, arg2, arg3, ...) arg3 +#define GET_4TH_ARG_(arg1, arg2, arg3, arg4, ...) arg4 + +#define CHECK_VALUE(value_check, log, ret) \ + if (value_check) { \ + log; \ + ret; \ + } + +#define CHECK_IF_VALUES_ARE_EQUAL(lvalue, rvalue) \ + CHECK_VALUE((lvalue) != (rvalue), BM_ERROR_LOG(#lvalue " == " #rvalue " failed: {}, != {}", (lvalue), (rvalue)), ) + +#define CHECK_IF_VALUE_IS_NULLPTR_LOG(value, logger, ret) \ + CHECK_VALUE((value) == nullptr, logger("could not get the " #value), ret) + +#define CHECK_IF_VALUE_IS_NULLPTR(value, ret) \ + CHECK_VALUE((value) == nullptr, , ret) + +#define CHECK_IF_BM_VALUE_IS_NULL_LOG(value, logger, ret) \ + CHECK_VALUE((value).IsNull(), logger("could not get the " #value), ret) + +#define CHECK_IF_BM_VALUE_IS_NULL(value, ret) \ + CHECK_VALUE((value).IsNull(), , ret) + +#define CHECK_IF_TARRAY_INDEX_IS_VALID_LOG(arr, idx, logger, ret) \ + CHECK_VALUE(!(arr).IsValid() || !(arr).IsValidIndex(idx), logger("could not get the " #arr), ret) + +#define CHECK_IF_TARRAY_INDEX_IS_VALID(arr, idx, ret) \ + CHECK_VALUE(!(arr).IsValid() || !(arr).IsValidIndex(idx), , ret) + +#define CHECK_IF_BM_ARRAY_INDEX_IS_VALID_LOG(arr, idx, logger, ret) \ + CHECK_VALUE((arr).IsNull() || (arr).Count() <= (idx), logger("could not get the " #arr), ret) + +#define CHECK_IF_BM_ARRAY_INDEX_IS_VALID(arr, idx, ret) \ + CHECK_VALUE((arr).IsNull() || (arr).Count() <= (idx), , ret) + + +/* NULLCHECK */ + +#define NULLCHECK_WITHOUT_RETURN(value) \ + CHECK_IF_VALUE_IS_NULLPTR_LOG(value, BM_DEBUG_ERROR_LOG, return) + +#define NULLCHECK_WITH_RETURN(value, ret) \ + CHECK_IF_VALUE_IS_NULLPTR_LOG(value, BM_DEBUG_ERROR_LOG, return (ret)) + +#define NULLCHECK(...) \ + EXPAND_(GET_3TH_ARG_(__VA_ARGS__, NULLCHECK_WITH_RETURN, NULLCHECK_WITHOUT_RETURN)(__VA_ARGS__)) + +#define NULLCHECK_SILENT_WITHOUT_RETURN(value) \ + CHECK_IF_VALUE_IS_NULLPTR(value, return) + +#define NULLCHECK_SILENT_WITH_RETURN(value, ret) \ + CHECK_IF_VALUE_IS_NULLPTR(value, return (ret)) + +#define NULLCHECK_SILENT(...) \ + EXPAND_(GET_3TH_ARG_(__VA_ARGS__, NULLCHECK_SILENT_WITH_RETURN, NULLCHECK_SILENT_WITHOUT_RETURN)(__VA_ARGS__)) + +#define NULLCHECK_BREAK(value) \ + CHECK_IF_VALUE_IS_NULLPTR_LOG(value, BM_DEBUG_WARNING_LOG, break) + +#define NULLCHECK_BREAK_SILENT(value) \ + CHECK_IF_VALUE_IS_NULLPTR(value, break) + + +/* BMCHECK */ + +#define BMCHECK_WITHOUT_RETURN(value) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_ERROR_LOG, return) + +#define BMCHECK_WITH_RETURN(value, ret) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_ERROR_LOG, return (ret)) + +#define BMCHECK(...) \ + EXPAND_(GET_3TH_ARG_(__VA_ARGS__, BMCHECK_WITH_RETURN, BMCHECK_WITHOUT_RETURN)(__VA_ARGS__)) + +#define BMCHECK_SILENT_WITHOUT_RETURN(value) \ + CHECK_IF_BM_VALUE_IS_NULL(value, return) + +#define BMCHECK_SILENT_WITH_RETURN(value, ret) \ + CHECK_IF_BM_VALUE_IS_NULL(value, return (ret)) + +#define BMCHECK_SILENT(...) \ + EXPAND_(GET_3TH_ARG_(__VA_ARGS__, BMCHECK_SILENT_WITH_RETURN, BMCHECK_SILENT_WITHOUT_RETURN)(__VA_ARGS__)) + +#define BMCHECK_DEBUG_WITHOUT_RETURN(value) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_DEBUG_ERROR_LOG, return) + +#define BMCHECK_DEBUG_WITH_RETURN(value, ret) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_DEBUG_ERROR_LOG, return (ret)) + +#define BMCHECK_DEBUG(...) \ + EXPAND_(GET_3TH_ARG_(__VA_ARGS__, BMCHECK_DEBUG_WITH_RETURN, BMCHECK_DEBUG_WITHOUT_RETURN)(__VA_ARGS__)) + +#define BMCHECK_BREAK(value) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_DEBUG_WARNING_LOG, break) + +#define BMCHECK_BREAK_SILENT(value) \ + CHECK_IF_BM_VALUE_IS_NULL(value, break) + + +/* NULLCHECK_LOOP */ + +#define NULLCHECK_LOOP(value) \ + CHECK_IF_VALUE_IS_NULLPTR_LOG(value, BM_DEBUG_WARNING_LOG, continue) + +#define NULLCHECK_LOOP_SILENT(value) \ + CHECK_IF_VALUE_IS_NULLPTR(value, continue) + + +/* BMCHECK_LOOP */ + +#define BMCHECK_LOOP(value) \ + CHECK_IF_BM_VALUE_IS_NULL_LOG(value, BM_WARNING_LOG, continue) + +#define BMCHECK_LOOP_SILENT(value) \ + CHECK_IF_BM_VALUE_IS_NULL(value, continue) + + +/* NULLCHECK_TARRAY */ + +#define NULLCHECK_TARRAY_WITHOUT_INDEX(arr) \ + CHECK_IF_TARRAY_INDEX_IS_VALID_LOG(arr, 0, BM_DEBUG_WARNING_LOG, return) + +#define NULLCHECK_TARRAY_WITHOUT_RETURN(arr, idx) \ + CHECK_IF_TARRAY_INDEX_IS_VALID_LOG(arr, idx, BM_DEBUG_WARNING_LOG, return) + +#define NULLCHECK_TARRAY_WITH_RETURN(arr, idx, ret) \ + CHECK_IF_TARRAY_INDEX_IS_VALID_LOG(arr, idx, BM_DEBUG_WARNING_LOG, return (ret)) + +#define NULLCHECK_TARRAY(...) \ + EXPAND_(GET_4TH_ARG_(__VA_ARGS__, NULLCHECK_TARRAY_WITH_RETURN, NULLCHECK_TARRAY_WITHOUT_RETURN, NULLCHECK_TARRAY_WITHOUT_INDEX)(__VA_ARGS__)) + +#define NULLCHECK_TARRAY_SILENT_WITHOUT_INDEX(arr, idx) \ + CHECK_IF_TARRAY_INDEX_IS_VALID(arr, 0, return) + +#define NULLCHECK_TARRAY_SILENT_WITHOUT_RETURN(arr, idx) \ + CHECK_IF_TARRAY_INDEX_IS_VALID(arr, idx, return) + +#define NULLCHECK_TARRAY_SILENT_WITH_RETURN(arr, idx, ret) \ + CHECK_IF_TARRAY_INDEX_IS_VALID(arr, idx, return (ret)) + +#define NULLCHECK_TARRAY_SILENT(...) \ + EXPAND_(GET_4TH_ARG_(__VA_ARGS__, NULLCHECK_TARRAY_SILENT_WITH_RETURN, NULLCHECK_TARRAY_SILENT_WITHOUT_RETURN, NULLCHECK_TARRAY_SILENT_WITHOUT_INDEX)(__VA_ARGS__)) + + +/* BMCHECK_ARRAY */ + +#define BMCHECK_ARRAY_WITHOUT_INDEX(arr) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID_LOG(arr, 0, BM_WARNING_LOG, return) + +#define BMCHECK_ARRAY_WITHOUT_RETURN(arr, idx) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID_LOG(arr, idx, BM_WARNING_LOG, return) + +#define BMCHECK_ARRAY_WITH_RETURN(arr, idx, ret) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID_LOG(arr, idx, BM_WARNING_LOG, return (ret)) + +#define BMCHECK_ARRAY(...) \ + EXPAND_(GET_4TH_ARG_(__VA_ARGS__, BMCHECK_ARRAY_WITH_RETURN, BMCHECK_ARRAY_WITHOUT_RETURN, BMCHECK_ARRAY_WITHOUT_INDEX)(__VA_ARGS__)) + +#define BMCHECK_ARRAY_SILENT_WITHOUT_INDEX(arr) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID(arr, 0, return) + +#define BMCHECK_ARRAY_SILENT_WITHOUT_RETURN(arr, idx) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID(arr, idx, return) + +#define BMCHECK_ARRAY_SILENT_WITH_RETURN(arr, idx, ret) \ + CHECK_IF_BM_ARRAY_INDEX_IS_VALID(arr, idx, return (ret)) + +#define BMCHECK_ARRAY_SILENT(...) \ + EXPAND_(GET_4TH_ARG_(__VA_ARGS__, BMCHECK_ARRAY_SILENT_WITH_RETURN, BMCHECK_ARRAY_SILENT_WITHOUT_RETURN, BMCHECK_ARRAY_SILENT_WITHOUT_INDEX)(__VA_ARGS__)) + +#ifdef BMDEBUG + #undef DEBUG #endif diff --git a/source/External/BakkesModAdditions/include/utils/exception_safety.h b/source/External/BakkesModAdditions/include/utils/exception_safety.h index a33fa22..4580977 100644 --- a/source/External/BakkesModAdditions/include/utils/exception_safety.h +++ b/source/External/BakkesModAdditions/include/utils/exception_safety.h @@ -16,26 +16,26 @@ //}) #define LOG_EXCEPTIONS(desc, msg, trace) \ - LOG("=== Critical error: ===\n{}\n{}\n\n{}", desc, msg, trace) + BM_LOG("=== Critical error: ===\n{:s}\n{:s}\n\n{:s}", desc, msg, trace) #define CATCH_EXCEPTIONS(desc) \ catch (const std::exception& e) { \ try { \ LOG_EXCEPTIONS(desc, e.what(), StackWalkerBM().DumpCallStack()); \ } \ - catch (...) { CRITICAL_LOG("Failed to get callstack {}", e.what()); } \ + catch (...) { BM_CRITICAL_LOG("Failed to get callstack {:s}", e.what()); } \ } \ catch (const SE_Exception& e) { \ try { \ LOG_EXCEPTIONS(desc, e.getSeMessage(), StackWalkerBM().DumpCallStack(e.GetExceptionPointers())); \ } \ - catch (...) { CRITICAL_LOG("Failed to get callstack {}", e.getSeMessage()); } \ + catch (...) { BM_CRITICAL_LOG("Failed to get callstack {:s}", e.getSeMessage()); } \ } \ catch (...) { \ try { \ LOG_EXCEPTIONS(desc, "Unknown exception", StackWalkerBM().DumpCallStack()); \ } \ - catch (...) { CRITICAL_LOG("Failed to get callstack"); } \ + catch (...) { BM_CRITICAL_LOG("Failed to get callstack"); } \ } #define TRY_CATCH_EXCEPTIONS(body, desc) \ @@ -47,22 +47,22 @@ inline void Nothing(void*) {} -inline int LogCallStack(const std::string& desc, PEXCEPTION_POINTERS pExceptionPointers) +static inline int LogCallStack(const std::string& desc, PEXCEPTION_POINTERS pExceptionPointers) { if (pExceptionPointers == nullptr || pExceptionPointers->ExceptionRecord == nullptr) { - CRITICAL_LOG("could not get the exception record"); + BM_CRITICAL_LOG("could not get the exception record"); return EXCEPTION_CONTINUE_SEARCH; } const DWORD exceptionCode = pExceptionPointers->ExceptionRecord->ExceptionCode; std::string exceptionMessage = GetExceptionMessage(exceptionCode); - const std::string exceptionCallStack = StackWalkerBM().DumpCallStack(pExceptionPointers); + const std::string exceptionCallStack = to_string(StackWalkerBM().DumpCallStack(pExceptionPointers)); if (exceptionMessage.empty()) { try { // MSVC exception ptr hack. // https://github.com/microsoft/STL/blob/68b344c9dcda6ddf1a8fca112cb9033f9e50e787/stl/src/excptptr.cpp#L476 - auto exceptionRecord = std::shared_ptr(pExceptionPointers->ExceptionRecord, Nothing); + const auto exceptionRecord = std::shared_ptr(pExceptionPointers->ExceptionRecord, Nothing); __ExceptionPtrRethrow(&exceptionRecord); } catch (const std::exception& e) { @@ -92,7 +92,7 @@ inline int LogCallStack(const std::string& desc, PEXCEPTION_POINTERS pExceptionP } template -inline bool GuardedFunction(const std::string& desc, Func lambda) +static inline bool GuardedFunction(const std::string& desc, Func lambda) { __try { lambda(); @@ -100,17 +100,16 @@ inline bool GuardedFunction(const std::string& desc, Func lambda) } __except (LogCallStack(desc, GetExceptionInformation())) { MessageBox(NULL, - "Addional info should be provided in the F6 console.\n" - "A crashdump should be located in \"%appdata%\\bakkesmod\\bakkesmod\\crashes\".\n" - "You can continue to use BakkesMod and Rocket Plugin.", - "Rocket Plugin Error", MB_OK | MB_ICONERROR); + TEXT("Addional info should be provided in the F6 console.\n") + TEXT("A crashdump should be located in \"%appdata%\\bakkesmod\\bakkesmod\\crashes\"."), + TEXT("Rocket Plugin Error"), MB_OK | MB_ICONERROR); } return false; } #define TRY_EXCEPT(desc, body, args) \ - if (GuardedFunction(desc, [&]() { body(args); })) return; + if (GuardedFunction(desc, [&]() { body(args); })) { return; } #define CATCH_FUNCTION(func, body, args, desc, before, after) \ func \ @@ -125,10 +124,10 @@ inline bool GuardedFunction(const std::string& desc, Func lambda) CATCH_FUNCTION(funcOverride, body, args, desc, before, after) \ func -#define CATCH_ONLOAD \ - CATCH_OVERRIDE_FUNCTION(void onLoad(), void OnLoad(), OnLoad, \ - , "Game thread exception:", SET_SE_TRANSLATOR;, \ - cvarManager->executeCommand("plugin unload RocketPlugin");) +#define CATCH_ONLOAD \ + CATCH_OVERRIDE_FUNCTION(void onLoad(), void OnLoad(), OnLoad, \ + , "Game thread exception:", SET_SE_TRANSLATOR;, \ + cvarManager->executeCommand("sleep 100; plugin unload RocketPlugin");) #define CATCH_ONUNLOAD \ CATCH_OVERRIDE_FUNCTION(void onUnload(), void OnUnload(), OnUnload, \ @@ -141,9 +140,9 @@ inline bool GuardedFunction(const std::string& desc, Func lambda) ImGui::GetStateStorage()->Clear(); \ ImGui::NewFrame();) -#define CATCH_RENDER_SETTINGS \ - CATCH_OVERRIDE_FUNCTION(void RenderSettings(), void OnRenderSettings(), OnRenderSettings, \ - , "Rendering thread exception:", SET_SE_TRANSLATOR;, \ +#define CATCH_RENDER_SETTINGS \ + CATCH_OVERRIDE_FUNCTION(void RenderSettings(), void OnRenderSettings(), OnRenderSettings, \ + , "Rendering thread exception:", SET_SE_TRANSLATOR;, \ cvarManager->executeCommand("closemenu settings");) #define CATCH_HOOK_EVENT \ @@ -166,9 +165,9 @@ inline bool GuardedFunction(const std::string& desc, Func lambda) callback, caller COMMA_ params COMMA_ _eventName, + quote(eventName) + ", Game thread exception:", \ gameWrapper->HookEventWithCallerPost LPARENT_ eventName COMMA_ [=](T caller, void* params, const std::string& _eventName) LBRACKET_, RBRACKET_ RPARENT_;) -#define CATCH_SET_TIMEOUT \ - CATCH_FUNCTION(void SetTimeout(const std::function& theLambda, float time) const, \ - theLambda, gw, "Game thread exception:", \ +#define CATCH_SET_TIMEOUT \ + CATCH_FUNCTION(void SetTimeout(const std::function& theLambda, const float time) const, \ + theLambda, gw, "Game thread exception:", \ gameWrapper->SetTimeout LPARENT_ [=](GameWrapper* gw) LBRACKET_, RBRACKET_ COMMA_ time RPARENT_;) #define CATCH_EXECUTE \ @@ -176,9 +175,9 @@ inline bool GuardedFunction(const std::string& desc, Func lambda) theLambda, gw, "Game thread exception:", \ gameWrapper->Execute LPARENT_ [=](GameWrapper* gw) LBRACKET_, RBRACKET_ RPARENT_;) -#define CATCH_REGISTER_NOTIFIER \ - CATCH_FUNCTION(void RegisterNotifier(const std::string& cvar, const std::function)>& notifier, const std::string& description, unsigned char permissions) const, \ - notifier, arguments, + quote(cvar) + ", Game thread exception:", \ +#define CATCH_REGISTER_NOTIFIER \ + CATCH_FUNCTION(void RegisterNotifier(const std::string& cvar, const std::function)>& notifier, const std::string& description, const unsigned char permissions) const, \ + notifier, arguments, + quote(cvar) + ", Game thread exception:", \ cvarManager->registerNotifier LPARENT_ cvar COMMA_ [=](const std::vector& arguments) LBRACKET_, RBRACKET_ COMMA_ description COMMA_ permissions RPARENT_;) #define CATCH_DEFAULT_BM_FUNCTIONS \ diff --git a/source/External/BakkesModAdditions/include/utils/filesystem.h b/source/External/BakkesModAdditions/include/utils/filesystem.h new file mode 100644 index 0000000..46340f3 --- /dev/null +++ b/source/External/BakkesModAdditions/include/utils/filesystem.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include + + +static inline bool has_extension(const std::string& fileExtension, const std::vector& extensions) +{ + // Filter out unwanted file extensions. + return std::ranges::any_of(extensions, [&](const std::string& extension) { + return fileExtension == extension; + }); +} + + +static inline std::vector iterate_directory(const std::filesystem::path& directory, + const std::vector& extensions, const int depth = 0, const int maxDepth = 3) +{ + if (depth > maxDepth) { + return std::vector(); + } + + std::vector files; + for (const std::filesystem::directory_entry& file : std::filesystem::directory_iterator(directory)) { + const std::filesystem::path& filePath = file.path(); + if (file.is_directory()) { + std::vector directoryFiles = iterate_directory( + filePath, extensions, depth + 1, maxDepth); + // Remove if directory is empty. + if (!directoryFiles.empty()) { + files.insert(files.end(), directoryFiles.begin(), directoryFiles.end()); + } + } + else if (has_extension(filePath.extension().string(), extensions)) { + files.push_back(filePath); + } + } + + return files; +} + + +template...>>> +static inline std::vector get_files_from_dir(const std::filesystem::path& directory, const int maxDepth, const TArgs... extension) +{ + if (!exists(directory)) { + return std::vector(); + } + + const std::vector fileExtensions = { extension... }; + + return iterate_directory(directory, fileExtensions, 0, maxDepth); +} diff --git a/source/External/BakkesModAdditions/include/utils/parser_w.h b/source/External/BakkesModAdditions/include/utils/parser_w.h index d49f7fa..b9a5944 100644 --- a/source/External/BakkesModAdditions/include/utils/parser_w.h +++ b/source/External/BakkesModAdditions/include/utils/parser_w.h @@ -1,85 +1,85 @@ -#pragma once -#include -#include -#include - - -/* - * Wide string parser equivalents. - */ - -// Checks if the given string starts with given string. -inline bool string_starts_with(const std::wstring& wstr, const std::wstring& begin) -{ - return wstr.compare(0, begin.length(), begin) == 0; -} - - -// Splits the string by delimiter. -inline size_t split(const std::wstring& wstr, std::vector& wstrs, const wchar_t delimiter) -{ - size_t pos = wstr.find(delimiter); - size_t initialPos = 0; - wstrs.clear(); - - // Decompose statement. - while (pos != std::string::npos) { - wstrs.push_back(wstr.substr(initialPos, pos - initialPos)); - initialPos = pos + 1; - - pos = wstr.find(delimiter, initialPos); - } - - // Add the last one. - wstrs.push_back(wstr.substr(initialPos, std::min(pos, wstr.size()) - initialPos)); - - return wstrs.size(); -} - - -// Trim from start. -inline std::wstring& ltrim(std::wstring& wstr) { - wstr.erase(wstr.begin(), std::find_if(wstr.begin(), wstr.end(), [](const int wc) { - return !std::isspace(wc); - })); - - return wstr; -} - - -// Trim from end. -inline std::wstring& rtrim(std::wstring& wstr) { - wstr.erase(std::find_if(wstr.rbegin(), wstr.rend(), [](const int wc) { - return !std::isspace(wc); - }).base(), wstr.end()); - - return wstr; -} - - -// Trim from both ends. -inline std::wstring& trim(std::wstring& wstr) { - return ltrim(rtrim(wstr)); -} - - -// Replaces the first occurrence with the other string. -inline bool replace(std::wstring& wstr, const std::wstring& from, const std::wstring& to) { - const size_t start_pos = wstr.find(from); - if (start_pos == std::string::npos) { - return false; - } - wstr.replace(start_pos, from.length(), to); - - return true; -} - - -// Replaces all occurrences with the other string. -inline void replace_all(std::wstring& wstr, const std::wstring& from, const std::wstring& to) { - size_t start_pos = wstr.find(from); - while (start_pos != std::string::npos) { - wstr.replace(start_pos, from.length(), to); - start_pos = wstr.find(from); - } -} +#pragma once +#include +#include +#include + + +/* + * Wide string parser equivalents. + */ + +// Checks if the given string starts with given string. +inline bool string_starts_with(const std::wstring& wstr, const std::wstring& begin) +{ + return wstr.compare(0, begin.length(), begin) == 0; +} + + +// Splits the string by delimiter. +inline size_t split(const std::wstring& wstr, std::vector& wstrs, const wchar_t delimiter) +{ + size_t pos = wstr.find(delimiter); + size_t initialPos = 0; + wstrs.clear(); + + // Decompose statement. + while (pos != std::string::npos) { + wstrs.push_back(wstr.substr(initialPos, pos - initialPos)); + initialPos = pos + 1; + + pos = wstr.find(delimiter, initialPos); + } + + // Add the last one. + wstrs.push_back(wstr.substr(initialPos, std::min(pos, wstr.size()) - initialPos)); + + return wstrs.size(); +} + + +// Trim from start. +inline std::wstring& ltrim(std::wstring& wstr) { + wstr.erase(wstr.begin(), std::find_if(wstr.begin(), wstr.end(), [](const int wc) { + return !std::isspace(wc); + })); + + return wstr; +} + + +// Trim from end. +inline std::wstring& rtrim(std::wstring& wstr) { + wstr.erase(std::find_if(wstr.rbegin(), wstr.rend(), [](const int wc) { + return !std::isspace(wc); + }).base(), wstr.end()); + + return wstr; +} + + +// Trim from both ends. +inline std::wstring& trim(std::wstring& wstr) { + return ltrim(rtrim(wstr)); +} + + +// Replaces the first occurrence with the other string. +inline bool replace(std::wstring& wstr, const std::wstring& from, const std::wstring& to) { + const size_t start_pos = wstr.find(from); + if (start_pos == std::string::npos) { + return false; + } + wstr.replace(start_pos, from.length(), to); + + return true; +} + + +// Replaces all occurrences with the other string. +inline void replace_all(std::wstring& wstr, const std::wstring& from, const std::wstring& to) { + size_t start_pos = wstr.find(from); + while (start_pos != std::string::npos) { + wstr.replace(start_pos, from.length(), to); + start_pos = wstr.find(from); + } +} diff --git a/source/External/BakkesModAdditions/include/utils/se_exception.h b/source/External/BakkesModAdditions/include/utils/se_exception.h index dacf644..fbb73f8 100644 --- a/source/External/BakkesModAdditions/include/utils/se_exception.h +++ b/source/External/BakkesModAdditions/include/utils/se_exception.h @@ -1,6 +1,6 @@ /// From https://docs.microsoft.com/en-us/cpp/cpp/exception-handling-differences?view=msvc-160#example---use-a-custom-translation-function #pragma once -#include +//#include #include #include @@ -60,22 +60,21 @@ inline std::string GetExceptionMessage(const DWORD exceptionCode) class SE_Exception { public: - SE_Exception(const SE_Exception& e) : nSE(e.nSE), pExp(e.pExp) {} - SE_Exception(const unsigned int nSE_, EXCEPTION_POINTERS* pExp_) : nSE(nSE_), pExp(pExp_) {} + SE_Exception(const SE_Exception& e) = default; + SE_Exception(const unsigned int nSE_, EXCEPTION_POINTERS* pExp_) : nSE(nSE_), pExp(pExp_) {} ~SE_Exception() = default; SE_Exception(SE_Exception&&) = default; SE_Exception& operator=(const SE_Exception&) = default; SE_Exception& operator=(SE_Exception&&) = default; - static void se_trans_func(unsigned int nSE, EXCEPTION_POINTERS* pEP) { throw SE_Exception(nSE, pEP); } - static _se_translator_function SetSETranslator() { return _set_se_translator(se_trans_func); } + [[ noreturn ]] static void se_trans_func(const unsigned int nSE, EXCEPTION_POINTERS* pEP) { throw SE_Exception(nSE, pEP); } + //static _se_translator_function SetSETranslator() { return _set_se_translator(se_trans_func); } static std::string FormatSeMessage(const DWORD messageId) { char error[2048]; DWORD len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, - LoadLibrary(TEXT("NTDLL.DLL")), static_cast(messageId), - NULL, error, sizeof error, NULL); + LoadLibrary(TEXT("NTDLL.DLL")), messageId, NULL, error, sizeof error, NULL); if (len == 0) { return "N/A (0x" + to_hex(messageId) + ")"; } @@ -100,12 +99,12 @@ class SE_Exception { }; -class Scoped_SE_Translator -{ -private: - const _se_translator_function old_SE_translator; -public: - Scoped_SE_Translator() noexcept - : old_SE_translator{ SE_Exception::SetSETranslator() } {} - ~Scoped_SE_Translator() noexcept { _set_se_translator(old_SE_translator); } -}; +//class Scoped_SE_Translator +//{ +//public: +// Scoped_SE_Translator() noexcept : old_SE_translator{ SE_Exception::SetSETranslator() } {} +// ~Scoped_SE_Translator() noexcept { _set_se_translator(old_SE_translator); } +// +//private: +// _se_translator_function old_SE_translator; +//}; diff --git a/source/External/BakkesModAdditions/include/utils/stackwalker.h b/source/External/BakkesModAdditions/include/utils/stackwalker.h index e9eb3bc..8120ff6 100644 --- a/source/External/BakkesModAdditions/include/utils/stackwalker.h +++ b/source/External/BakkesModAdditions/include/utils/stackwalker.h @@ -35,8 +35,18 @@ * * **********************************************************************/ #pragma once +#if defined(UNICODE) && !defined(DBGHELP_TRANSLATE_TCHAR) + #define DBGHELP_TRANSLATE_TCHAR + + #define strcpy_s wcscpy_s + #define strncpy_s wcsncpy_s + #define _strdup _wcsdup + #define strcat_s wcscat_s + #define strlen wcslen + #define strrchr wcsrchr +#endif + #include -#include #include #include #pragma comment(lib, "version.lib") @@ -48,11 +58,14 @@ #include #pragma comment(lib, "Psapi.lib") +#include "utils/stringify.h" + #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif #include "fmt/format.h" -#include "se_exception.h" +#include "fmt/xchar.h" +#include "fmt/chrono.h" #define USED_CONTEXT_FLAGS CONTEXT_FULL #define STACKWALK_MAX_NAMELEN 1024 @@ -63,6 +76,39 @@ RtlCaptureContext(&(c)); \ } while (0); +#if defined(UNICODE) +static BOOL SymGetSymFromAddrW64( + _In_ HANDLE hProcess, + _In_ DWORD64 qwAddr, + _Out_opt_ PDWORD64 pdwDisplacement, + _Inout_ PIMAGEHLP_SYMBOLW64 Symbol +) +{ + const SIZE_T symSize = sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN; + PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)malloc(symSize); + ZeroMemory(pSym, symSize); + pSym->SizeOfStruct = Symbol->SizeOfStruct; + pSym->Address = Symbol->Address; + pSym->Size = Symbol->Size; + pSym->Flags = Symbol->Flags; + pSym->MaxNameLength = Symbol->MaxNameLength; + + BOOL ret = SymGetSymFromAddr64(hProcess, qwAddr, pdwDisplacement, pSym); + Symbol->SizeOfStruct = pSym->SizeOfStruct; + Symbol->Address = pSym->Address; + Symbol->Size = pSym->Size; + Symbol->Flags = pSym->Flags; + Symbol->MaxNameLength = pSym->MaxNameLength; + MultiByteToWideChar(CP_UTF8, NULL, pSym->Name, pSym->MaxNameLength, Symbol->Name, Symbol->MaxNameLength); + + return ret; +} + +#define IMAGEHLP_SYMBOL64 IMAGEHLP_SYMBOLW64 +#define PIMAGEHLP_SYMBOL64 PIMAGEHLP_SYMBOLW64 +#define SymGetSymFromAddr64 SymGetSymFromAddrW64 +#endif + extern std::filesystem::path BakkesModCrashesFolder; EXTERN_C IMAGE_DOS_HEADER __ImageBase; @@ -106,7 +152,7 @@ class StackWalker } StackWalkOptions; StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags - LPCSTR szSymPath = NULL, + LPCTSTR szSymPath = NULL, DWORD dwProcessId = GetCurrentProcessId(), HANDLE hProcess = GetCurrentProcess()) { @@ -145,10 +191,10 @@ class StackWalker return TRUE; // Build the sym-path: - char* szSymPath = NULL; + PTCHAR szSymPath = NULL; if ((m_options & SymBuildPath) != 0) { const size_t nSymPathLen = 4096; - szSymPath = (char*)malloc(nSymPathLen); + szSymPath = (PTCHAR)malloc(nSymPathLen); if (szSymPath == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; @@ -157,24 +203,24 @@ class StackWalker // Now first add the (optional) provided sympath: if (m_szSymPath != NULL) { strcat_s(szSymPath, nSymPathLen, m_szSymPath); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } - strcat_s(szSymPath, nSymPathLen, ".;"); + strcat_s(szSymPath, nSymPathLen, TEXT(".;")); const size_t nTempLen = 1024; - char szTemp[nTempLen]; + TCHAR szTemp[nTempLen]; // Now add the current directory: - if (GetCurrentDirectoryA(nTempLen, szTemp) > 0) { + if (GetCurrentDirectory(nTempLen, szTemp) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } // Now add the path for the main-module: - if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0) { + if (GetModuleFileName(NULL, szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; - for (char* p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) { + for (PTCHAR p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) { // locate the rightmost path separator if ((*p == '\\') || (*p == '/') || (*p == ':')) { *p = 0; @@ -183,40 +229,39 @@ class StackWalker } // for (search for path separator...) if (strlen(szTemp) > 0) { strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } } - if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0) { + if (GetEnvironmentVariable(TEXT("_NT_SYMBOL_PATH"), szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } - if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0) { + if (GetEnvironmentVariable(TEXT("_NT_ALTERNATE_SYMBOL_PATH"), szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } - if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0) { + if (GetEnvironmentVariable(TEXT("SYSTEMROOT"), szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); // also add the "system32"-directory: - strcat_s(szTemp, nTempLen, "\\system32"); + strcat_s(szTemp, nTempLen, TEXT("\\system32")); strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); + strcat_s(szSymPath, nSymPathLen, TEXT(";")); } if ((m_options & SymUseSymSrv) != 0) { - if (GetEnvironmentVariableA("SYSTEMDRIVE", szTemp, nTempLen) > 0) { + if (GetEnvironmentVariable(TEXT("SYSTEMDRIVE"), szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, "SRV*"); + strcat_s(szSymPath, nSymPathLen, TEXT("SRV*")); strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, "\\websymbols"); - strcat_s(szSymPath, nSymPathLen, "*https://msdl.microsoft.com/download/symbols;"); + strcat_s(szSymPath, nSymPathLen, TEXT("\\websymbols")); + strcat_s(szSymPath, nSymPathLen, TEXT("*https://msdl.microsoft.com/download/symbols;")); } else - strcat_s(szSymPath, nSymPathLen, - "SRV*c:\\websymbols*https://msdl.microsoft.com/download/symbols;"); + strcat_s(szSymPath, nSymPathLen, TEXT("SRV*c:\\websymbols*https://msdl.microsoft.com/download/symbols;")); } } // if SymBuildPath @@ -302,7 +347,7 @@ class StackWalker if (!StackWalk64(imageType, m_hProcess, hThread, &s, &c, myReadProcMem, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { // INFO: "StackWalk64" does not set "GetLastError"... - _ERROR_LOG("StackWalk64, GetLastError: {:X} (Address: {:p})", 0, (LPVOID)s.AddrPC.Offset); + BM_DEBUG_ERROR_LOG("StackWalk64, GetLastError: {:X} (Address: {:p})", 0, (LPVOID)s.AddrPC.Offset); break; } @@ -318,7 +363,7 @@ class StackWalker csEntry.moduleName[0] = 0; if (s.AddrPC.Offset == s.AddrReturn.Offset) { if ((m_MaxRecursionCount > 0) && (curRecursionCount > m_MaxRecursionCount)) { - _ERROR_LOG("StackWalk64-Endless-Callstack!, GetLastError: {:X} (Address: {:p})", 0, (LPVOID)s.AddrPC.Offset); + BM_DEBUG_ERROR_LOG("StackWalk64-Endless-Callstack!, GetLastError: {:X} (Address: {:p})", 0, (LPVOID)s.AddrPC.Offset); break; } curRecursionCount++; @@ -334,7 +379,7 @@ class StackWalker UnDecorateSymbolName(pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE); } else { - _ERROR_LOG("SymGetSymFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); + BM_DEBUG_ERROR_LOG("SymGetSymFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); } // show line number info, NT5.0-method @@ -344,7 +389,7 @@ class StackWalker MyStrCpy(csEntry.lineFileName, STACKWALK_MAX_NAMELEN, Line.FileName); } else { - _ERROR_LOG("SymGetLineFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); + BM_DEBUG_ERROR_LOG("SymGetLineFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); } // show module info @@ -352,34 +397,34 @@ class StackWalker // got module info OK switch (Module.SymType) { case SymNone: - csEntry.symTypeString = "-nosymbols-"; + csEntry.symTypeString = TEXT("-nosymbols-"); break; case SymCoff: - csEntry.symTypeString = "COFF"; + csEntry.symTypeString = TEXT("COFF"); break; case SymCv: - csEntry.symTypeString = "CV"; + csEntry.symTypeString = TEXT("CV"); break; case SymPdb: - csEntry.symTypeString = "PDB"; + csEntry.symTypeString = TEXT("PDB"); break; case SymExport: - csEntry.symTypeString = "-exported-"; + csEntry.symTypeString = TEXT("-exported-"); break; case SymDeferred: - csEntry.symTypeString = "-deferred-"; + csEntry.symTypeString = TEXT("-deferred-"); break; case SymSym: - csEntry.symTypeString = "SYM"; + csEntry.symTypeString = TEXT("SYM"); break; case SymDia: - csEntry.symTypeString = "DIA"; + csEntry.symTypeString = TEXT("DIA"); break; case 8: //SymVirtual: - csEntry.symTypeString = "Virtual"; + csEntry.symTypeString = TEXT("Virtual"); break; default: - _TRACE_LOG("symtype={:ld}", Module.SymType); + BM_DEBUG_TRACE_LOG("symtype={:ld}", Module.SymType); csEntry.symTypeString = NULL; break; } @@ -389,7 +434,7 @@ class StackWalker MyStrCpy(csEntry.loadedImageName, STACKWALK_MAX_NAMELEN, Module.LoadedImageName); } // got module info OK else - _ERROR_LOG("SymGetModuleInfo64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); + BM_DEBUG_ERROR_LOG("SymGetModuleInfo64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)s.AddrPC.Offset); } // we seem to have a valid PC CallStackEntryType et = nextEntry; @@ -432,7 +477,7 @@ class StackWalker pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); pSym->MaxNameLength = STACKWALK_MAX_NAMELEN; if (SymGetSymFromAddr64(m_hProcess, dwAddress, &dwDisplacement, pSym) == FALSE) { - _ERROR_LOG("SymGetSymFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)dwAddress); + BM_DEBUG_ERROR_LOG("SymGetSymFromAddr64, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)dwAddress); return FALSE; } // Object name output @@ -447,18 +492,18 @@ class StackWalker typedef struct CallStackEntry { DWORD64 offset; // if 0, we have no valid entry - CHAR name[STACKWALK_MAX_NAMELEN]; - CHAR undName[STACKWALK_MAX_NAMELEN]; - CHAR undFullName[STACKWALK_MAX_NAMELEN]; + TCHAR name[STACKWALK_MAX_NAMELEN]; + TCHAR undName[STACKWALK_MAX_NAMELEN]; + TCHAR undFullName[STACKWALK_MAX_NAMELEN]; DWORD64 offsetFromSmybol; DWORD offsetFromLine; DWORD lineNumber; - CHAR lineFileName[STACKWALK_MAX_NAMELEN]; + TCHAR lineFileName[STACKWALK_MAX_NAMELEN]; DWORD symType; - LPCSTR symTypeString; - CHAR moduleName[STACKWALK_MAX_NAMELEN]; + LPCTSTR symTypeString; + TCHAR moduleName[STACKWALK_MAX_NAMELEN]; DWORD64 baseOfImage; - CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; + TCHAR loadedImageName[STACKWALK_MAX_NAMELEN]; } CallStackEntry; typedef enum CallStackEntryType @@ -468,9 +513,9 @@ class StackWalker lastEntry } CallStackEntryType; - virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName) + virtual void OnSymInit(LPCTSTR szSearchPath, DWORD symOptions, LPCTSTR szUserName) { - std::string buffer = fmt::format("SymInit: Symbol-SearchPath: '{:s}', symOptions: {:d}, UserName: '{:s}'", + auto buffer = fmt::format(TEXT("SymInit: Symbol-SearchPath: '{:s}', symOptions: {:d}, UserName: '{:s}'"), szSearchPath, symOptions, szUserName); OnOutput(buffer.c_str()); // Getting the OS-version is deprecated. @@ -484,63 +529,63 @@ class StackWalker // OnOutput(buffer.c_str()); //} } - - virtual void OnLoadModule(LPCSTR img, - LPCSTR mod, + + virtual void OnLoadModule(LPCTSTR img, + LPCTSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, - LPCSTR symType, - LPCSTR pdbName, + LPCTSTR symType, + LPCTSTR pdbName, ULONGLONG fileVersion) { - std::string buffer; + std::basic_string buffer; if (fileVersion == 0) - buffer = fmt::format("{:s}:{:s} ({:p}), size: {:d} (result: {:d}), SymType: '{:s}', PDB: '{:s}'", + buffer = fmt::format(TEXT("{:s}:{:s} ({:p}), size: {:d} (result: {:d}), SymType: '{:s}', PDB: '{:s}'"), img, mod, (LPVOID)baseAddr, size, result, symType, pdbName); else { DWORD v4 = (DWORD)(fileVersion & 0xFFFF); DWORD v3 = (DWORD)((fileVersion >> 16) & 0xFFFF); DWORD v2 = (DWORD)((fileVersion >> 32) & 0xFFFF); DWORD v1 = (DWORD)((fileVersion >> 48) & 0xFFFF); - buffer = fmt::format("{:s}:{:s} ({:p}), size: {:d} (result: {:d}), SymType: '{:s}', PDB: '{:s}', fileVersion: {:d}.{:d}.{:d}.{:d}", + buffer = fmt::format(TEXT("{:s}:{:s} ({:p}), size: {:d} (result: {:d}), SymType: '{:s}', PDB: '{:s}', fileVersion: {:d}.{:d}.{:d}.{:d}"), img, mod, (LPVOID)baseAddr, size, result, symType, pdbName, v1, v2, v3, v4); } OnOutput(buffer.c_str()); } - + virtual void OnCallStackEntry(CallStackEntryType eType, CallStackEntry& entry) { if (eType != lastEntry && entry.offset != 0) { - std::string function = to_hex(entry.offset); - if (entry.undFullName[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.undFullName); - else if (entry.undName[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.undName); - else if (entry.name[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.name); - std::string filename = "(filename not available)"; - if (entry.lineFileName[0] != '\0') - filename = fmt::format("[File={:s}:{:d}]", entry.lineFileName, entry.lineNumber); - std::string moduleName = "(module-name not available)"; - if (entry.moduleName[0] != '\0') - moduleName = fmt::format("[in {:s}]", entry.moduleName); - - OnOutput(fmt::format("{:s} {:s} {:s}", function, filename, moduleName).c_str()); + std::basic_string function = fmt::format(TEXT("0x{:X}"), entry.offset); + if (entry.undFullName[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.undFullName); + else if (entry.undName[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.undName); + else if (entry.name[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.name); + std::basic_string filename = TEXT("(filename not available)"); + if (entry.lineFileName[0] != TEXT('\0')) + filename = fmt::format(TEXT("[File={:s}:{:d}]"), entry.lineFileName, entry.lineNumber); + std::basic_string moduleName = TEXT("(module-name not available)"); + if (entry.moduleName[0] != TEXT('\0')) + moduleName = fmt::format(TEXT("[in {:s}]"), entry.moduleName); + + OnOutput(fmt::format(TEXT("{:s} {:s} {:s}"), function, filename, moduleName).c_str()); } } - - virtual void OnOutput([[maybe_unused]] LPCSTR szText) + + virtual void OnOutput([[maybe_unused]] LPCTSTR szText) { - _INFO_LOG(szText); + BM_DEBUG_INFO_LOG(to_string(szText)); } HANDLE m_hProcess; DWORD m_dwProcessId; BOOL m_modulesLoaded; - LPSTR m_szSymPath; + LPTSTR m_szSymPath; int m_options; int m_MaxRecursionCount; @@ -554,13 +599,13 @@ class StackWalker SIZE_T st; BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st); *lpNumberOfBytesRead = (DWORD)st; - //__TRACE_LOG("ReadMemory: hProcess: {:p}, baseAddr: {:p}, buffer: {:p}, size: {:d}, read: {:d}, result: {:d}", hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, (DWORD)st, (DWORD)bRet); + //__BM_TRACE_LOG("ReadMemory: hProcess: {:p}, baseAddr: {:p}, buffer: {:p}, size: {:d}, read: {:d}, result: {:d}", hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, (DWORD)st, (DWORD)bRet); return bRet; } private: - static void MyStrCpy(char* szDest, size_t nMaxDestSize, const char* szSrc) + static void MyStrCpy(PTCHAR szDest, size_t nMaxDestSize, const TCHAR* szSrc) { if (nMaxDestSize <= 0) return; @@ -570,13 +615,13 @@ class StackWalker szDest[nMaxDestSize - 1] = 0; } - BOOL Init(LPCSTR szSymPath) + BOOL Init(LPCTSTR szSymPath) { // SymInitialize if (szSymPath != NULL) szSymPath = _strdup(szSymPath); if (SymInitialize(m_hProcess, szSymPath, FALSE) == FALSE) - _ERROR_LOG("SymInitialize, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)0); + BM_DEBUG_ERROR_LOG("SymInitialize, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)0); DWORD symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES; @@ -584,12 +629,12 @@ class StackWalker //symOptions |= SYMOPT_NO_PROMPTS; symOptions = SymSetOptions(symOptions); - char buf[STACKWALK_MAX_NAMELEN] = { 0 }; + TCHAR buf[STACKWALK_MAX_NAMELEN] = { 0 }; if (SymGetSearchPath(m_hProcess, buf, STACKWALK_MAX_NAMELEN) == FALSE) - _ERROR_LOG("SymGetSearchPath, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)0); - char szUserName[1024] = { 0 }; + BM_DEBUG_ERROR_LOG("SymGetSearchPath, GetLastError: {:X} (Address: {:p})", GetLastError(), (LPVOID)0); + TCHAR szUserName[1024] = { 0 }; DWORD dwSize = 1024; - GetUserNameA(szUserName, &dwSize); + GetUserName(szUserName, &dwSize); OnSymInit(buf, symOptions, szUserName); return TRUE; @@ -626,24 +671,24 @@ class StackWalker DWORD cbNeeded; MODULEINFO mi; HMODULE* hMods = NULL; - char* tt = NULL; - char* tt2 = NULL; + PTCHAR tt = NULL; + PTCHAR tt2 = NULL; const SIZE_T TTBUFLEN = 8096; int cnt = 0; hMods = (HMODULE*)malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof(HMODULE))); - tt = (char*)malloc(sizeof(char) * TTBUFLEN); - tt2 = (char*)malloc(sizeof(char) * TTBUFLEN); + tt = (PTCHAR)malloc(sizeof(TCHAR) * TTBUFLEN); + tt2 = (PTCHAR)malloc(sizeof(TCHAR) * TTBUFLEN); if ((hMods == NULL) || (tt == NULL) || (tt2 == NULL)) goto cleanup; if (!EnumProcessModules(hProcess, hMods, TTBUFLEN, &cbNeeded)) { - _ERROR_LOG("EPM failed, GetLastError: {:X}", GetLastError()); + BM_DEBUG_ERROR_LOG("EPM failed, GetLastError: {:X}", GetLastError()); goto cleanup; } if (cbNeeded > TTBUFLEN) { - _ERROR_LOG("More than {} module handles.", TTBUFLEN); + BM_DEBUG_ERROR_LOG("More than {:d} module handles.", TTBUFLEN); goto cleanup; } @@ -652,14 +697,14 @@ class StackWalker GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)); // image file name tt[0] = 0; - GetModuleFileNameExA(hProcess, hMods[i], tt, TTBUFLEN); + GetModuleFileNameEx(hProcess, hMods[i], tt, TTBUFLEN); // module name tt2[0] = 0; - GetModuleBaseNameA(hProcess, hMods[i], tt2, TTBUFLEN); + GetModuleBaseName(hProcess, hMods[i], tt2, TTBUFLEN); DWORD dwRes = LoadModule(hProcess, tt, tt2, (DWORD64)mi.lpBaseOfDll, mi.SizeOfImage); if (dwRes != ERROR_SUCCESS) - _ERROR_LOG("StackWalk64, GetLastError: {:X} (Address: {:p})", dwRes, (LPVOID)0); + BM_DEBUG_ERROR_LOG("StackWalk64, GetLastError: {:X} (Address: {:p})", dwRes, (LPVOID)0); cnt++; } @@ -674,15 +719,15 @@ class StackWalker return cnt != 0; } - DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size) + DWORD LoadModule(HANDLE hProcess, LPCTSTR img, LPCTSTR mod, DWORD64 baseAddr, DWORD size) { - CHAR* szImg = _strdup(img); - CHAR* szMod = _strdup(mod); + PTCHAR szImg = _strdup(img); + PTCHAR szMod = _strdup(mod); DWORD result = ERROR_SUCCESS; if ((szImg == NULL) || (szMod == NULL)) result = ERROR_NOT_ENOUGH_MEMORY; else { - if (SymLoadModule64(hProcess, 0, szImg, szMod, baseAddr, size) == 0) + if (SymLoadModuleEx(hProcess, 0, szImg, szMod, baseAddr, size, NULL, NULL) == 0) result = GetLastError(); } ULONGLONG fileVersion = 0; @@ -691,11 +736,11 @@ class StackWalker if ((m_options & RetrieveFileVersion) != 0) { VS_FIXEDFILEINFO* fInfo = NULL; DWORD dwHandle; - DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle); + DWORD dwSize = GetFileVersionInfoSize(szImg, &dwHandle); if (dwSize > 0) { LPVOID vData = malloc(dwSize); if (vData != NULL) { - if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0) { + if (GetFileVersionInfo(szImg, dwHandle, dwSize, vData) != 0) { UINT len; TCHAR szSubBlock[] = _T("\\"); if (VerQueryValue(vData, szSubBlock, (LPVOID*)&fInfo, &len) == 0) @@ -712,39 +757,39 @@ class StackWalker // Retrieve some additional-infos about the module IMAGEHLP_MODULE64 Module; - const char* szSymType = "-unknown-"; + const TCHAR* szSymType = TEXT("-unknown-"); if (GetModuleInfo(hProcess, baseAddr, &Module) != FALSE) { switch (Module.SymType) { case SymNone: - szSymType = "-nosymbols-"; + szSymType = TEXT("-nosymbols-"); break; case SymCoff: // 1 - szSymType = "COFF"; + szSymType = TEXT("COFF"); break; case SymCv: // 2 - szSymType = "CV"; + szSymType = TEXT("CV"); break; case SymPdb: // 3 - szSymType = "PDB"; + szSymType = TEXT("PDB"); break; case SymExport: // 4 - szSymType = "-exported-"; + szSymType = TEXT("-exported-"); break; case SymDeferred: // 5 - szSymType = "-deferred-"; + szSymType = TEXT("-deferred-"); break; case SymSym: // 6 - szSymType = "SYM"; + szSymType = TEXT("SYM"); break; case 7: // SymDia: - szSymType = "DIA"; + szSymType = TEXT("DIA"); break; case 8: //SymVirtual: - szSymType = "Virtual"; + szSymType = TEXT("Virtual"); break; } } - LPCSTR pdbName = Module.LoadedImageName; + LPCTSTR pdbName = Module.LoadedImageName; if (Module.LoadedPdbName[0] != 0) pdbName = Module.LoadedPdbName; OnLoadModule(img, mod, baseAddr, size, result, szSymType, pdbName, @@ -796,7 +841,7 @@ class StackWalker class StackWalkerBM final : public StackWalker { public: - std::string DumpCallStack(EXCEPTION_POINTERS* pExceptionPointers = nullptr) + std::basic_string DumpCallStack(EXCEPTION_POINTERS* pExceptionPointers = nullptr) { // Secret windows hacks. static_assert(sizeof std::exception_ptr == sizeof std::shared_ptr @@ -806,7 +851,7 @@ class StackWalkerBM final : public StackWalker if (pExceptionPointers == nullptr) { std::exception_ptr exceptionPtr = std::current_exception(); if (!exceptionPtr) { - return "No callStack available"; + return TEXT("No callStack available"); } auto exceptionRecord = static_cast*>(reinterpret_cast(&exceptionPtr)); exceptionPointers.ExceptionRecord = exceptionRecord->get(); @@ -818,97 +863,96 @@ class StackWalkerBM final : public StackWalker ShowCallStack(GetCurrentThread(), exceptionPointers.ContextRecord); const BOOL ret = WriteFullDump(GetMiniDumpFile().c_str(), &exceptionPointers); - _TRACE_LOG("WriteFullDump -> {}", ret == TRUE); + BM_DEBUG_TRACE_LOG("WriteFullDump -> {}", ret == TRUE); return callStack; } - std::string GetCallStack() + std::basic_string GetCallStack() { return callStack; } private: - std::string GetFileVersion() + std::basic_string GetFileVersion() { - const std::string defaultFileVersion = "0.0.0.0"; + const std::basic_string defaultFileVersion = TEXT("0.0.0.0"); - CHAR dllPath[MAX_PATH]; - if (GetModuleFileNameA((HINSTANCE)&__ImageBase, dllPath, _countof(dllPath)) == NULL) { - _ERROR_LOG("GetModuleFileNameA, GetLastError: {:X}", GetLastError()); + TCHAR dllPath[MAX_PATH]; + if (GetModuleFileName((HINSTANCE)&__ImageBase, dllPath, _countof(dllPath)) == NULL) { + BM_DEBUG_ERROR_LOG("GetModuleFileName, GetLastError: {:X}", GetLastError()); return defaultFileVersion; } - DWORD fileVersionSize = GetFileVersionInfoSizeA(dllPath, NULL); + DWORD fileVersionSize = GetFileVersionInfoSize(dllPath, NULL); if (fileVersionSize == NULL) { - _ERROR_LOG("GetFileVersionInfoSizeA, GetLastError: {:X}", GetLastError()); + BM_DEBUG_ERROR_LOG("GetFileVersionInfoSize, GetLastError: {:X}", GetLastError()); return defaultFileVersion; } std::vector fileVersion(fileVersionSize); - if (GetFileVersionInfoA(dllPath, NULL, fileVersionSize, fileVersion.data()) == FALSE) { - _ERROR_LOG("GetFileVersionInfoA, GetLastError: {:X}", GetLastError()); + if (GetFileVersionInfo(dllPath, NULL, fileVersionSize, fileVersion.data()) == FALSE) { + BM_DEBUG_ERROR_LOG("GetFileVersionInfo, GetLastError: {:X}", GetLastError()); return defaultFileVersion; } VS_FIXEDFILEINFO* pFileInfo = NULL; UINT pLenFileInfo = 0; - if (!VerQueryValueA(fileVersion.data(), "\\", (LPVOID*)&pFileInfo, &pLenFileInfo)) { - _ERROR_LOG("VerQueryValueA, GetLastError: {:X}", GetLastError()); + if (!VerQueryValue(fileVersion.data(), TEXT("\\"), (LPVOID*)&pFileInfo, &pLenFileInfo)) { + BM_DEBUG_ERROR_LOG("VerQueryValue, GetLastError: {:X}", GetLastError()); return defaultFileVersion; } - return fmt::format("{}.{}.{}.{}", + return fmt::format(TEXT("{:d}.{:d}.{:d}.{:d}"), (pFileInfo->dwFileVersionMS >> 16) & 0xffff, (pFileInfo->dwFileVersionMS) & 0xffff, (pFileInfo->dwFileVersionLS >> 16) & 0xffff, (pFileInfo->dwFileVersionLS) & 0xffff); } - std::string GetMiniDumpFile() + std::basic_string GetMiniDumpFile() { - char pluginName[512] = "Unknown"; + TCHAR pluginName[512] = TEXT("Unknown"); SetLastError(ERROR_SUCCESS); - GetModuleFileNameA((HINSTANCE)&__ImageBase, pluginName, sizeof pluginName); + GetModuleFileName((HINSTANCE)&__ImageBase, pluginName, sizeof pluginName); if (GetLastError()) { - _WARNING_LOG("GetModuleFileNameA, GetLastError: {:X}", GetLastError()); - strcpy_s(pluginName, "Unknown"); + BM_DEBUG_WARNING_LOG("GetModuleFileName, GetLastError: {:X}", GetLastError()); + strcpy_s(pluginName, TEXT("Unknown")); } else { - char* filename = strrchr(pluginName, '\\') + 1; - strncpy_s(pluginName, filename, strrchr(pluginName, '.') - filename); - } - - char dllPath[MAX_PATH]; - if (GetModuleFileNameA((HINSTANCE)&__ImageBase, dllPath, _countof(dllPath)) == NULL) { - _WARNING_LOG("GetModuleFileNameA, GetLastError: {:X}", GetLastError()); - dllPath[0] = '\0'; + PTCHAR filename = strrchr(pluginName, TEXT('\\')) + 1; + strncpy_s(pluginName, filename, strrchr(pluginName, TEXT('.')) - filename); } + - std::string pluginVersion = GetFileVersion(); + std::basic_string pluginVersion = GetFileVersion(); - std::string localTime = "0.0.0-0.0.0"; + std::basic_string localTime = TEXT("0.0.0-0.0.0"); tm currentTimeInfo; const std::time_t currentTime = std::time(nullptr); if (!localtime_s(¤tTimeInfo, ¤tTime)) { - localTime = fmt::format("{:%Y.%m.%d-%H.%M.%S}", currentTimeInfo); + localTime = fmt::format(TEXT("{:%Y.%m.%d-%H.%M.%S}"), currentTimeInfo); } - std::string fileName = fmt::format("{:s}-v{:s}-{:s}.dmp", pluginName, pluginVersion, localTime); - + std::basic_string fileName = fmt::format(TEXT("{:s}-v{:s}-{:s}.dmp"), pluginName, pluginVersion, localTime); + +#ifdef UNICODE + return (BakkesModCrashesFolder / fileName).wstring(); +#else return (BakkesModCrashesFolder / fileName).string(); +#endif } - BOOL WriteFullDump(LPCSTR lpFileName, EXCEPTION_POINTERS* exceptionPointers) + BOOL WriteFullDump(LPCTSTR lpFileName, EXCEPTION_POINTERS* exceptionPointers) { if (exceptionPointers == nullptr) { return FALSE; } - _TRACE_LOG(lpFileName); - HANDLE hFile = CreateFileA(lpFileName, GENERIC_ALL, NULL, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); + BM_DEBUG_TRACE_LOG(to_string(lpFileName)); + HANDLE hFile = CreateFile(lpFileName, GENERIC_ALL, NULL, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile == INVALID_HANDLE_VALUE) { - _ERROR_LOG("CreateFileA, GetLastError: {:X}", GetLastError()); + BM_DEBUG_ERROR_LOG("CreateFile, GetLastError: {:X}", GetLastError()); return FALSE; } @@ -936,7 +980,7 @@ class StackWalkerBM final : public StackWalker CloseHandle(hFile); if (!Result) { - _ERROR_LOG("MiniDumpWriteDump, GetLastError: {:X}", GetLastError()); + BM_DEBUG_ERROR_LOG("MiniDumpWriteDump, GetLastError: {:X}", GetLastError()); return FALSE; } @@ -946,26 +990,37 @@ class StackWalkerBM final : public StackWalker void OnCallStackEntry(const CallStackEntryType eType, CallStackEntry& entry) override { if (eType != lastEntry && entry.offset != 0) { - std::string function = to_hex(entry.offset); - if (entry.undFullName[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.undFullName); - else if (entry.undName[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.undName); - else if (entry.name[0] != '\0') - function = fmt::format("{:s} {:s}()", function, entry.name); - std::string filename = "(filename not available)"; - if (entry.lineFileName[0] != '\0') - filename = fmt::format("[File={:s}:{:d}]", entry.lineFileName, entry.lineNumber); - std::string moduleName = "(module-name not available)"; - if (entry.moduleName[0] != '\0') + std::basic_string function = fmt::format(TEXT("0x{:X}"), entry.offset); + if (entry.undFullName[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.undFullName); + else if (entry.undName[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.undName); + else if (entry.name[0] != TEXT('\0')) + function = fmt::format(TEXT("{:s} {:s}()"), function, entry.name); + std::basic_string filename = TEXT("(filename not available)"); + if (entry.lineFileName[0] != TEXT('\0')) + filename = fmt::format(TEXT("[File={:s}:{:d}]"), entry.lineFileName, entry.lineNumber); + std::basic_string moduleName = TEXT("(module-name not available)"); + if (entry.moduleName[0] != TEXT('\0')) //moduleName = fmt::format("[in {:s}]", entry.moduleName); - moduleName = fmt::format("[in {:s}]", entry.loadedImageName); + moduleName = fmt::format(TEXT("[in {:s}]"), entry.loadedImageName); - callStack += fmt::format("{:s} {:s} {:s}\n", function, filename, moduleName); + callStack += fmt::format(TEXT("{:s} {:s} {:s}\n"), function, filename, moduleName); } } - void OnOutput(LPCSTR) override {} + void OnOutput(LPCTSTR) override {} - std::string callStack; + std::basic_string callStack; }; + +#undef strcpy_s +#undef strncpy_s +#undef _strdup +#undef strcat_s +#undef strlen +#undef strrchr + +#undef IMAGEHLP_SYMBOL64 +#undef PIMAGEHLP_SYMBOL64 +#undef SymGetSymFromAddr64 diff --git a/source/External/BakkesModAdditions/include/utils/stringify.h b/source/External/BakkesModAdditions/include/utils/stringify.h index e1e6730..40ae2ec 100644 --- a/source/External/BakkesModAdditions/include/utils/stringify.h +++ b/source/External/BakkesModAdditions/include/utils/stringify.h @@ -55,8 +55,8 @@ inline std::string get_addr(const void* ptr) inline std::string to_lower(const std::string& str) { std::string str_cpy = str; - std::transform(str_cpy.begin(), str_cpy.end(), str_cpy.begin(), - [](unsigned char c) { return static_cast(std::tolower(c)); }); + std::ranges::transform(str_cpy, str_cpy.begin(), + [](const unsigned char c) { return static_cast(std::tolower(c)); }); return str_cpy; } @@ -64,8 +64,8 @@ inline std::string to_lower(const std::string& str) inline std::wstring to_lower(const std::wstring& wstr) { std::wstring wstr_cpy = wstr; - std::transform(wstr_cpy.begin(), wstr_cpy.end(), wstr_cpy.begin(), - [](wchar_t c) { return static_cast(std::tolower(c)); }); + std::ranges::transform(wstr_cpy, wstr_cpy.begin(), + [](const wchar_t c) { return static_cast(std::tolower(c)); }); return wstr_cpy; } @@ -74,8 +74,8 @@ inline std::wstring to_lower(const std::wstring& wstr) inline std::string to_upper(const std::string& str) { std::string str_cpy = str; - std::transform(str_cpy.begin(), str_cpy.end(), str_cpy.begin(), - [](unsigned char c) { return static_cast(std::toupper(c)); }); + std::ranges::transform(str_cpy, str_cpy.begin(), + [](const unsigned char c) { return static_cast(std::toupper(c)); }); return str_cpy; } @@ -83,8 +83,8 @@ inline std::string to_upper(const std::string& str) inline std::wstring to_upper(const std::wstring& wstr) { std::wstring wstr_cpy = wstr; - std::transform(wstr_cpy.begin(), wstr_cpy.end(), wstr_cpy.begin(), - [](wchar_t c) { return static_cast(std::toupper(c)); }); + std::ranges::transform(wstr_cpy, wstr_cpy.begin(), + [](const wchar_t c) { return static_cast(std::toupper(c)); }); return wstr_cpy; } @@ -143,11 +143,11 @@ inline std::wstring to_wstring(const std::string& str) struct case_insensitive_less { - bool operator()(const std::string& _Left, const std::string& _Right) const { - return to_lower(_Left) < to_lower(_Right); + bool operator()(const std::string& left, const std::string& right) const { + return to_lower(left) < to_lower(right); } - bool operator()(const std::wstring& _Left, const std::wstring& _Right) const { - return to_lower(_Left) < to_lower(_Right); + bool operator()(const std::wstring& left, const std::wstring& right) const { + return to_lower(left) < to_lower(right); } }; diff --git a/source/External/BakkesModAdditions/include/utils/threading.h b/source/External/BakkesModAdditions/include/utils/threading.h index c281318..adafd7b 100644 --- a/source/External/BakkesModAdditions/include/utils/threading.h +++ b/source/External/BakkesModAdditions/include/utils/threading.h @@ -1,10 +1,10 @@ #pragma once #include #include +#include #include #include #include -#include #include #ifndef FMT_HEADER_ONLY @@ -13,60 +13,118 @@ #include "fmt/format.h" #include "fmt/ostream.h" -#include "exception_safety.h" - extern std::thread::id GameThreadId; extern std::thread::id RenderThreadId; -inline std::thread save_thread(const std::function& lambda, const std::string& comment = "") +template +static inline std::thread save_thread(const std::string& comment, const std::function& lambda) +{ + return std::thread([=]() -> void { + try { + return lambda(); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + }); +} + + +template +static inline std::thread save_thread(const std::string& comment, void(*func)(Args...), const Args&&... args) +{ + return std::thread([=]() -> void { + try { + return func(std::forward(args)...); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + }); +} + + +template +static inline std::thread save_thread(const std::string& comment, void(Cls::*func)(Args...), Cls* cls, const Args&&... args) +{ + return std::thread([=]() -> void { + try { + return (cls->*func)(std::forward(args)...); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + }); +} + + +template +static inline std::future save_promise(const std::string& comment, const std::function& lambda) +{ + return std::async([=]() -> Ret { + try { + return lambda(); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + return Ret{}; + }); +} + + +template +static inline std::future save_promise(const std::string& comment, Ret(*func)(Args...), const Args&&... args) +{ + return std::async([=]() -> Ret { + try { + return func(std::forward(args)...); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + return Ret{}; + }); +} + + +template +static inline std::future save_promise(const std::string& comment, Ret(Cls::* func)(Args...), Cls* cls, const Args&&... args) { - return std::thread([=]() { - SET_SE_TRANSLATOR; - TRY_CATCH_EXCEPTIONS(lambda();, fmt::format("thread#{} {}", std::this_thread::get_id(), comment)); + return std::async([=]() -> Ret { + try { + return (cls->*func)(std::forward(args)...); + } + catch (...) { + BM_CRITICAL_LOG("thread #{:s} {:s} crashed", std::this_thread::get_id(), comment); + } + return Ret{}; }); } -//template -//std::thread save_thread(const std::function& lambda, _Cls* cls) -//{ -// return std::thread([=]() { -// try { -// lambda(cls); -// } -// catch (...) { -// std::stringstream ss; -// ss << std::this_thread::get_id(); -// CRITICAL_LOG("thread #{} crashed", ss.str()); -// } -// }); -//} - - -//template -//std::thread save_thread(const std::function lambda, _Cls* cls, _Args... args) -//{ -// return std::thread([=]() { -// try { -// lambda(cls, args...); -// } -// catch (...) { -// std::stringstream ss; -// ss << std::this_thread::get_id(); -// CRITICAL_LOG("thread #{} crashed", ss.str()); -// } -// }); -//} - - -inline bool is_game_thread() +static inline void set_game_thread() +{ + GameThreadId = std::this_thread::get_id(); +} + + +static inline void set_game_thread_once() +{ + if (GameThreadId == std::thread::id()) { + set_game_thread(); + } +} + + +static inline bool is_game_thread() { return std::this_thread::get_id() == GameThreadId; } -inline void assert_game_thread([[maybe_unused]] const wchar_t* message, [[maybe_unused]] const wchar_t* file = L"", [[maybe_unused]] unsigned int line = 0) +static inline void assert_game_thread([[maybe_unused]] const wchar_t* message, [[maybe_unused]] const wchar_t* file = L"", [[maybe_unused]] const unsigned int line = 0) { if (!is_game_thread()) { #ifndef NDEBUG @@ -76,13 +134,27 @@ inline void assert_game_thread([[maybe_unused]] const wchar_t* message, [[maybe_ } -inline bool is_render_thread() +static inline void set_render_thread() +{ + RenderThreadId = std::this_thread::get_id(); +} + + +static inline void set_render_thread_once() +{ + if (RenderThreadId == std::thread::id()) { + set_render_thread(); + } +} + + +static inline bool is_render_thread() { return std::this_thread::get_id() == RenderThreadId; } -inline void assert_render_thread([[maybe_unused]] const wchar_t* message, [[maybe_unused]] const wchar_t* file = L"", [[maybe_unused]] unsigned int line = 0) +static inline void assert_render_thread([[maybe_unused]] const wchar_t* message, [[maybe_unused]] const wchar_t* file = L"", [[maybe_unused]] const unsigned int line = 0) { if (!is_render_thread()) { #ifndef NDEBUG @@ -115,9 +187,7 @@ class JobQueue /// Creates a save thread to queue to call jobs on. JobQueue(catch_exceptions_t) { - thread = save_thread([this]() { - entry(); - }, "JobQueue"); + thread = save_thread("JobQueue", &JobQueue::entry, this); } /// Waits for the last job to finish and removes queue. @@ -134,9 +204,9 @@ class JobQueue } JobQueue(const JobQueue&) = delete; - JobQueue(JobQueue&&) = default; + JobQueue(JobQueue&&) = delete; JobQueue& operator=(const JobQueue&) = delete; - JobQueue& operator=(JobQueue&&) = default; + JobQueue& operator=(JobQueue&&) = delete; /// Adds job_t's to the job queue to be execute on a separate thread. /// function to be executed @@ -193,7 +263,7 @@ class JobQueue }; -template 0), int> = 0> +template 0), int> = 0> class JobPool { public: @@ -202,7 +272,7 @@ class JobPool /// Creates threads to queue jobs on. JobPool() { - for (size_t i = _Threads; i > 0; --i) { + for (size_t i = Threads; i > 0; --i) { jobPool.push_back(std::make_unique()); } wait(); @@ -211,7 +281,7 @@ class JobPool /// Creates save threads to queue jobs on. JobPool(catch_exceptions_t) { - for (size_t i = _Threads; i > 0; --i) { + for (size_t i = Threads; i > 0; --i) { jobPool.push_back(std::make_unique(catch_exceptions)); } wait(); @@ -224,8 +294,8 @@ class JobPool explicit JobPool(const job_t& job, const size_t begin, const size_t end) { const size_t jobs = end - begin; - const size_t step = jobs / _Threads + (jobs % _Threads == 0 ? 0 : 1); - for (size_t i = _Threads; i > 0; i--) { + const size_t step = jobs / Threads + (jobs % Threads == 0 ? 0 : 1); + for (size_t i = Threads; i > 0; --i) { threadPool.push_back(std::thread(&JobPool::execute, this, job, (i - 1) * step, std::min(i * step, jobs))); } } @@ -237,11 +307,11 @@ class JobPool explicit JobPool(const job_t& job, const size_t begin, const size_t end, catch_exceptions_t) { const size_t jobs = end - begin; - const size_t step = jobs / _Threads + (jobs % _Threads == 0 ? 0 : 1); - for (size_t i = _Threads; i > 0; i--) { - threadPool.push_back(save_thread([=]() { + const size_t step = jobs / Threads + (jobs % Threads == 0 ? 0 : 1); + for (size_t i = Threads; i > 0; --i) { + threadPool.push_back(save_thread("JobPool", [=]() { execute(job, (i - 1) * step, std::min(i * step, jobs)); - }, "JobPool")); + })); } } @@ -263,7 +333,7 @@ class JobPool void addJob(const job_t& job, const size_t begin, const size_t end = 0) { const size_t jobs = std::max(begin, end) - std::min(begin, end); - const size_t step = jobs / _Threads + (jobs % _Threads == 0 ? 0 : 1); + const size_t step = jobs / Threads + (jobs % Threads == 0 ? 0 : 1); for (size_t i = 0; i < jobPool.size(); i++) { jobPool[i]->addJob([=]() { execute(job, i * step, std::min((i + 1) * step, jobs)); @@ -284,7 +354,7 @@ class JobPool } private: - void execute(const job_t& job, const size_t begin, const size_t end) + void execute(const job_t& job, const size_t begin, const size_t end) const { for (size_t i = begin; i < end; i++) { job(i); diff --git a/source/External/BakkesModAdditions/include/utils/timer.h b/source/External/BakkesModAdditions/include/utils/timer.h new file mode 100644 index 0000000..9fd4cb6 --- /dev/null +++ b/source/External/BakkesModAdditions/include/utils/timer.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include + +#include "fmt/chrono.h" + + +class Timer +{ +public: + Timer() : timePoint(std::chrono::system_clock::now()) {} + ~Timer() = default; + + std::chrono::system_clock::duration Duration() const + { + return std::chrono::system_clock::now() - timePoint; + } + + std::string Str() const + { + const std::chrono::system_clock::duration duration = Duration(); + + if (auto hours = std::chrono::duration_cast(duration); hours.count() > 0) { + return fmt::format("{}", hours); + } + if (auto minutes = std::chrono::duration_cast(duration); minutes.count() > 0) { + return fmt::format("{}", minutes); + } + if (auto seconds = std::chrono::duration_cast(duration); seconds.count() > 0) { + return fmt::format("{}", seconds); + } + if (auto milliseconds = std::chrono::duration_cast(duration); milliseconds.count() > 0) { + return fmt::format("{}", milliseconds); + } + if (auto microseconds = std::chrono::duration_cast(duration); microseconds.count() > 0) { + return fmt::format("{}", microseconds); + } + if (auto nanoseconds = std::chrono::duration_cast(duration); nanoseconds.count() > 0) { + return fmt::format("{}", nanoseconds); + } + + return fmt::format("{}", duration); + } + + Timer(Timer&&) = delete; + Timer(const Timer&) = delete; + Timer& operator=(Timer&&) = delete; + Timer& operator=(const Timer&) = delete; + +private: + std::chrono::system_clock::time_point timePoint; +}; diff --git a/source/External/BakkesModAdditions/include/utils/win32_error_category.h b/source/External/BakkesModAdditions/include/utils/win32_error_category.h index bdc1703..03c5423 100644 --- a/source/External/BakkesModAdditions/include/utils/win32_error_category.h +++ b/source/External/BakkesModAdditions/include/utils/win32_error_category.h @@ -9,7 +9,7 @@ /// Wrap the Win32 error code so we have a distinct type. struct win32_error_code { - explicit win32_error_code(DWORD e) noexcept : Error(e) {} + explicit win32_error_code(const DWORD e) noexcept : Error(e) {} DWORD Error; }; @@ -21,13 +21,13 @@ namespace detail { public: /// Return a short descriptive name for the category. - _NODISCARD char const* name() const noexcept override final + _NODISCARD char const* name() const noexcept final { return "Win32Error"; } /// Return what each error code means in text. - _NODISCARD std::string message(int errVal) const override final + _NODISCARD std::string message(int errVal) const final { char error[1024]; DWORD len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, @@ -93,9 +93,7 @@ namespace std class win32_error : public std::exception { public: - using _Mybase = exception; - - explicit win32_error(const DWORD e) : _Mybase(make_win32_error_code(e).message().c_str()) {} + explicit win32_error(const DWORD e) : std::exception(make_win32_error_code(e).message().c_str()) {} }; diff --git a/source/External/BakkesModAdditions/include/utils/xorstr.h b/source/External/BakkesModAdditions/include/utils/xorstr.h deleted file mode 100644 index ea029d8..0000000 --- a/source/External/BakkesModAdditions/include/utils/xorstr.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2010-2014, Sebastien Andrivet -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#pragma once -#include -#include -#include -#include - -namespace xorstr_impl { - -#ifdef _MSC_VER -#define XORSTR_INLINE __forceinline -#else -#define XORSTR_INLINE inline -#endif - -constexpr auto time = __TIME__; -constexpr auto seed = static_cast(time[7]) + - static_cast(time[6]) * 10 + - static_cast(time[4]) * 60 + - static_cast(time[3]) * 600 + - static_cast(time[1]) * 3600 + - static_cast(time[0]) * 36000; - -// 1988, Stephen Park and Keith Miller -// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard" -// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation: -// with 32-bit math and without division - -template -struct random_generator { -private: - static constexpr unsigned a = 16807; // 7^5 - static constexpr unsigned m = 2147483647; // 2^31 - 1 - static constexpr unsigned s = random_generator::value; - static constexpr unsigned lo = a * (s & 0xFFFF); // multiply lower 16 bits by 16807 - static constexpr unsigned hi = a * (s >> 16); // multiply higher 16 bits by 16807 - static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // combine lower 15 bits of hi with lo's upper bits - static constexpr unsigned hi2 = hi >> 15; // discard lower 15 bits of hi - static constexpr unsigned lo3 = lo2 + hi; - -public: - static constexpr unsigned max = m; - static constexpr unsigned value = lo3 > m ? lo3 - m : lo3; -}; - -template <> -struct random_generator<0> { - static constexpr unsigned value = seed; -}; - -template -struct random_int { - static constexpr auto value = random_generator::value % M; -}; - -template -struct random_char { - static const char value = static_cast(1 + random_int::value); -}; - -template -struct string { -private: - const char key_; - std::array encrypted_; - - constexpr char enc(char c) const { - return c ^ key_; - } - - char dec(char c) const { - return c ^ key_; - } - -public: - template - constexpr XORSTR_INLINE string(const char* str, std::index_sequence) : - key_(random_char::value), encrypted_{ { enc(str[Is])... } } {} - - XORSTR_INLINE decltype(auto) decrypt() { - for (size_t i = 0; i < N; ++i) { - encrypted_[i] = dec(encrypted_[i]); - } - encrypted_[N] = '\0'; - return encrypted_.data(); - } -}; - -template -struct arr { -private: - const T key_; - std::array encrypted_; - - constexpr T enc(T c) const { - return c ^ key_; - } - - T dec(T c) const { - return c ^ key_; - } - -public: - template - constexpr XORSTR_INLINE arr(const T* str, std::index_sequence) : - key_(random_char::value), encrypted_{ { enc(str[Is])... } } {} - - XORSTR_INLINE decltype(auto) decrypt() { - for (size_t i = 0; i < N; ++i) { - encrypted_[i] = dec(encrypted_[i]); - } - return encrypted_.data(); - } -}; - -#undef XORSTR_INLINE - -} // namespace xorstr_impl - -#define xorstr(s) (xorstr_impl::string(s, std::make_index_sequence()).decrypt()) - -#define xorarr(t, data) xorstr_impl::arr((t*)data, std::make_index_sequence()).decrypt(); - -#define E(s) xorstr(s) diff --git a/source/External/BakkesModSDK b/source/External/BakkesModSDK index 4203254..e39042e 160000 --- a/source/External/BakkesModSDK +++ b/source/External/BakkesModSDK @@ -1 +1 @@ -Subproject commit 4203254a25631e337b5aaed7afe5f183a21df54d +Subproject commit e39042e5d482f11ed1923658174bcc246bd43fd4 diff --git a/source/External/simdjson b/source/External/simdjson index e9b893f..33d926b 160000 --- a/source/External/simdjson +++ b/source/External/simdjson @@ -1 +1 @@ -Subproject commit e9b893ff1b13c6a70135827c62b3f3d65938d135 +Subproject commit 33d926bd4448e2e087511f34e49461230691a503 diff --git a/source/RocketPlugin/ExternalFunctions.cpp b/source/RocketPlugin/ExternalFunctions.cpp deleted file mode 100644 index 1355eb1..0000000 --- a/source/RocketPlugin/ExternalFunctions.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include "RocketPlugin.h" - -#include "GameModes/Tag.h" -#include "GameModes/KeepAway.h" -#include "GameModes/BoostShare.h" -#include "GameModes/BoostSteal.h" -#include "GameModes/CrazyRumble.h" - -#include "RLConstants.inc" - - -bool RocketPlugin::isMapJoinable(const std::filesystem::path&) -{ - WARNING_LOG("redacted function"); - - return false; -} - - -std::wstring RocketPlugin::getPlayerNickname(const uint64_t) const -{ - WARNING_LOG("redacted function"); - - return L""; -} - - -void RocketPlugin::getSubscribedWorkshopMapsAsync(const bool) -{ - WARNING_LOG("redacted function"); -} - - -void RocketPlugin::setMatchSettings(const std::string&) const -{ - WARNING_LOG("redacted function"); -} - - -void RocketPlugin::setMatchMapName(const std::string&) const -{ - WARNING_LOG("redacted function"); -} - - -bool RocketPlugin::setSearchStatus(const std::wstring&, const bool) const -{ - WARNING_LOG("redacted function"); - - return false; -} - - -void RocketPlugin::broadcastJoining() -{ - WARNING_LOG("redacted function"); -} - - -bool RocketPlugin::isHostingLocalGame() const -{ - WARNING_LOG("redacted function"); - - return false; -} - - -bool RocketPlugin::preLoadMap(const std::filesystem::path&, const bool, const bool) -{ - WARNING_LOG("redacted function"); - - return false; -} - - -void RocketPlugin::registerExternalNotifiers() -{ -#ifdef DEBUG - RegisterNotifier("rp_test_paths", [this](const std::vector&) { - LOG(absolute(BINDS_FILE_PATH).string()); - LOG(absolute(CONFIG_FILE_PATH).string()); - LOG(absolute(PRESETS_PATH).string()); - LOG(absolute(PRO_TIPS_FILE_PATH).string()); - LOG(absolute(CUSTOM_MAPS_PATH).string()); - LOG(absolute(WORKSHOP_MAPS_PATH).string()); - }, "Logs paths", PERMISSION_ALL); - - RegisterNotifier("rp_test_logs", [this](const std::vector&) { - LOG("normal log"); - TRACE_LOG("trace log"); - INFO_LOG("info log"); - WARNING_LOG("warning log"); - ERROR_LOG("error log"); - CRITICAL_LOG("critical log"); - }, "Logs a bunch", PERMISSION_ALL); - - RegisterNotifier("rp_run_tests", [this](const std::vector& arguments) { - std::vector tests = { "", "", "" }; - if (arguments.size() >= 2) { - tests = std::vector(arguments.begin() + 1, arguments.end()); - } - - if (std::find(tests.begin(), tests.end(), "x") != tests.end()) { - } - }, "Runs a bunch of tests", PERMISSION_ALL); - - RegisterNotifier("rp_crash", [this](const std::vector&) { - *static_cast(nullptr) = 0; - }, "Crashes by dereferencing nullptr", PERMISSION_ALL); - - RegisterNotifier("rp_throw", [this](const std::vector&) { - throw std::runtime_error("NotifierInterrupt"); - }, "Throws exception", PERMISSION_ALL); - - RegisterNotifier("rp_dump_cache", [this](const std::vector&) { - LOG("Join Maps:"); - LOG("Current Join Map: {}", quote(currentJoinMap.u8string())); - for (const auto& [path, name] : joinableMaps) { - LOG("\t{}: {}", quote(absolute(path).u8string()), quote(name)); - } - if (enableWorkshopMaps || enableCustomMaps) { - LOG("Custom Maps:"); - LOG("Current Maps: {}", quote(currentMap)); - for (const auto& [path, name] : customMapPaths) { - LOG("\t{}: {}", quote(absolute(path).u8string()), quote(name)); - } - } - else { - LOG("Maps:"); - LOG("Current Maps: {}", quote(currentMap)); - for (const auto& [internal, name] : maps) { - LOG("\t{}: {}", quote(internal), quote(name)); - } - } - LOG("Game Modes:"); - LOG("Selected Game Mode: {}", quote(gameModes.GetSelected())); - for (size_t i = 0; i < gameModes.InternalName.size(); i++) { - LOG("\t{}: {}", quote(gameModes.InternalName[i]), quote(gameModes.DisplayName[i])); - } - LOG("Bot Difficulties:"); - LOG("Selected Bot Difficulty: {}", quote(botDifficulties.GetSelected())); - for (size_t i = 0; i < botDifficulties.InternalName.size(); i++) { - LOG("\t{}: {}", quote(botDifficulties.InternalName[i]), quote(botDifficulties.DisplayName[i])); - } - LOG("Custom Colors:"); - LOG("\tDefault Blue Primary Color: {:X}", ImGui::ColorConvertFloat4ToU32(defaultBluePrimaryColor)); - LOG("\tDefault Orange Primary Color: {:X}", ImGui::ColorConvertFloat4ToU32(defaultOrangePrimaryColor)); - LOG("\tClub Color Hues: {}", clubColorHues); - std::string clubColorBuffer; - for (size_t i = 0; i < clubColors.size(); i++) { - if (i != 0 && i % clubColorHues == 0) { - LOG("\t{}", clubColorBuffer); - clubColorBuffer.clear(); - } - clubColorBuffer += to_hex(ImGui::ColorConvertFloat4ToU32(clubColors[i])) + ", "; - } - if (!clubColorBuffer.empty()) { - LOG("\t{}", clubColorBuffer); - } - LOG("\tDefault Blue Accent Color: {:X}", ImGui::ColorConvertFloat4ToU32(defaultBlueAccentColor)); - LOG("\tDefault Orange Accent Color: {:X}", ImGui::ColorConvertFloat4ToU32(defaultOrangeAccentColor)); - LOG("\tCustom Color Hues: {}", customColorHues); - std::string customColorBuffer; - for (size_t i = 0; i < customColors.size(); i++) { - if (i != 0 && i % customColorHues == 0) { - LOG("\t{}", customColorBuffer); - customColorBuffer.clear(); - } - customColorBuffer += to_hex(ImGui::ColorConvertFloat4ToU32(customColors[i])) + ", "; - } - if (!customColorBuffer.empty()) { - LOG("\t{}", customColorBuffer); - } - LOG("Mutators:"); - for (const GameSetting& mutator : mutators) { - LOG("\t{} ({}):", quote(mutator.InternalCategoryName), quote(mutator.DisplayCategoryName)); - for (size_t i = 0; i < mutator.InternalName.size(); i++) { - LOG("\t\t{}: {}", quote(mutator.InternalName[i]), quote(mutator.DisplayName[i])); - } - } - }, "Prints current cache", PERMISSION_ALL); - - RegisterNotifier("rp_dump_selected_match_settings", [this](const std::vector&) { - if (enableWorkshopMaps || enableCustomMaps) { - if (customMapPaths.find(currentMap) == customMapPaths.end()) { - ERROR_LOG("No map selected to host."); - } - LOG("MapName: {}", quote(std::filesystem::absolute(currentMap).string())); - } - else { - if (maps.find(currentMap) == maps.end()) { - ERROR_LOG("No map selected to host."); - } - LOG("MapName: {}", quote(currentMap)); - } - if (joinableMaps.find(currentJoinMap) == joinableMaps.end()) { - ERROR_LOG("No map selected to join."); - } - LOG("JoinMapName: {}", quote(absolute(currentJoinMap).u8string())); - LOG("GameMode: {}", quote(gameModes.GetSelected())); - LOG("GameModeIndex: {}", gameModes.CurrentSelected); - LOG("MaxPlayerCount: {}", playerCount); - LOG("Bot Difficulty: {}", quote(botDifficulties.GetSelected())); - LOG("Password: {}", quote(hostPswd)); - - LOG("TeamSettings 1"); - LOG("\tName: {}", quote(team1Name)); - LOG("\tColors"); - LOG("\t\tTeamColorID: {:d}", team1PrimCol); - LOG("\t\tCustomColorID: {:d}", team1AccCol); - LOG("\t\tbTeamColorSet: {}", team1PrimCol != -1); - LOG("\t\tbCustomColorSet: {}", team1AccCol != -1); - LOG("TeamSettings 2"); - LOG("\tName: {}", quote(team2Name)); - LOG("\tColors"); - LOG("\t\tTeamColorID: {:d}", team2PrimCol); - LOG("\t\tCustomColorID: {:d}", team2AccCol); - LOG("\t\tbTeamColorSet: {}", team2PrimCol != -1); - LOG("\t\tbCustomColorSet: {}", team2AccCol != -1); - LOG("bClubServer: {}", clubMatch); - - LOG("Mutators:"); - for (const GameSetting& mutator : mutators) { - LOG("\t{}: {}", quote(mutator.InternalCategoryName), quote(mutator.GetSelected())); - } - }, "Print selected match settings", PERMISSION_ALL); -#endif -} - - -void RocketPlugin::registerExternalHooks() -{ - WARNING_LOG("redacted function"); -} - - -void RocketPlugin::loadRLConstants() -{ - gameModes = RLConstants::GAME_MODES; - maps = RLConstants::MAPS; - botDifficulties = RLConstants::BOT_DIFFICULTIES; - customColorHues = RLConstants::CUSTOM_HUE_COUNT; - customColors = RLConstants::CUSTOM_COLORS; - clubColorHues = RLConstants::CLUB_HUE_COUNT; - clubColors = RLConstants::CUSTOM_COLORS; - defaultBluePrimaryColor = RLConstants::DEFAULT_BLUE_PRIMARY_COLOR; - defaultBlueAccentColor = RLConstants::DEFAULT_BLUE_ACCENT_COLOR; - defaultOrangePrimaryColor = RLConstants::DEFAULT_ORANGE_PRIMARY_COLOR; - defaultOrangeAccentColor = RLConstants::DEFAULT_ORANGE_ACCENT_COLOR; - mutators = RLConstants::MUTATORS; -} - - -bool RocketPlugin::isCurrentMapModded() const -{ - WARNING_LOG("redacted function"); - - return false; -} - - -void BoostShare::removePickups() const -{ - WARNING_LOG("redacted function"); -} - - -void BoostSteal::stealBoost(CarWrapper, void*) const -{ - WARNING_LOG("redacted function"); -} - - -void CrazyRumble::onGiveItem(const ActorWrapper&) const -{ - WARNING_LOG("redacted function"); -} - - -void CrazyRumble::updateDispensers(const bool, const bool) const -{ - WARNING_LOG("redacted function"); -} - - -void CrazyRumble::updateDispenserItemPool(const ActorWrapper&) const -{ - WARNING_LOG("redacted function"); -} - - -void CrazyRumble::updateDispenserMaxTimeTillItem(const ActorWrapper&) const -{ - WARNING_LOG("redacted function"); -} - - -void KeepAway::onCarTouch(void*) -{ - WARNING_LOG("redacted function"); -} - - -void Tag::onCarImpact(CarWrapper, void*) -{ - WARNING_LOG("redacted function"); -} - - -void Tag::onRumbleItemActivated(ActorWrapper, void*) -{ - WARNING_LOG("redacted function"); -} diff --git a/source/RocketPlugin/ExternalModules/ExternalFunctions.cpp b/source/RocketPlugin/ExternalModules/ExternalFunctions.cpp new file mode 100644 index 0000000..8d5d0eb --- /dev/null +++ b/source/RocketPlugin/ExternalModules/ExternalFunctions.cpp @@ -0,0 +1,152 @@ +#include "RocketPlugin.h" + +#include "GameModes/Tag.h" +#include "GameModes/KeepAway.h" +#include "GameModes/BoostShare.h" +#include "GameModes/BoostSteal.h" +#include "GameModes/CrazyRumble.h" + +#include "RLConstants.inc" + + +bool RocketPlugin::isMapJoinable(const std::filesystem::path&) +{ + BM_WARNING_LOG("redacted function"); + + return false; +} + + +std::wstring RocketPlugin::getPlayerNickname(const uint64_t) const +{ + BM_WARNING_LOG("redacted function"); + + return L""; +} + + +void RocketPlugin::getSubscribedWorkshopMapsAsync(const bool) +{ + BM_WARNING_LOG("redacted function"); +} + + +void RocketPlugin::setMatchSettings(const std::string&) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void RocketPlugin::setMatchMapName(const std::string&) const +{ + BM_WARNING_LOG("redacted function"); +} + + +bool RocketPlugin::setSearchStatus(const std::wstring&, const bool) const +{ + BM_WARNING_LOG("redacted function"); + + return false; +} + + +void RocketPlugin::broadcastJoining() +{ + BM_WARNING_LOG("redacted function"); +} + + +bool RocketPlugin::isHostingLocalGame() const +{ + BM_WARNING_LOG("redacted function"); + + return false; +} + + +bool RocketPlugin::preLoadMap(const std::filesystem::path&, const bool, const bool) +{ + BM_WARNING_LOG("redacted function"); + + return false; +} + + +void RocketPlugin::loadRLConstants() +{ + gameModes = RLConstants::GAME_MODES; + maps = RLConstants::MAPS; + botDifficulties = RLConstants::BOT_DIFFICULTIES; + customColorHues = RLConstants::CUSTOM_HUE_COUNT; + customColors = RLConstants::CUSTOM_COLORS; + clubColorHues = RLConstants::CLUB_HUE_COUNT; + clubColors = RLConstants::CUSTOM_COLORS; + defaultBluePrimaryColor = RLConstants::DEFAULT_BLUE_PRIMARY_COLOR; + defaultBlueAccentColor = RLConstants::DEFAULT_BLUE_ACCENT_COLOR; + defaultOrangePrimaryColor = RLConstants::DEFAULT_ORANGE_PRIMARY_COLOR; + defaultOrangeAccentColor = RLConstants::DEFAULT_ORANGE_ACCENT_COLOR; + mutators = RLConstants::MUTATORS; +} + + +bool RocketPlugin::isCurrentMapModded() const +{ + BM_WARNING_LOG("redacted function"); + + return false; +} + + +void BoostShare::removePickups() const +{ + BM_WARNING_LOG("redacted function"); +} + + +void BoostSteal::stealBoost(CarWrapper, void*) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void CrazyRumble::onGiveItem(const ActorWrapper&) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void CrazyRumble::updateDispensers(const bool, const bool) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void CrazyRumble::updateDispenserItemPool(const ActorWrapper&) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void CrazyRumble::updateDispenserMaxTimeTillItem(const ActorWrapper&) const +{ + BM_WARNING_LOG("redacted function"); +} + + +void KeepAway::onCarTouch(void*) +{ + BM_WARNING_LOG("redacted function"); +} + + +void Tag::onCarImpact(CarWrapper, void*) +{ + BM_WARNING_LOG("redacted function"); +} + + +void Tag::onRumbleItemActivated(ActorWrapper, void*) +{ + BM_WARNING_LOG("redacted function"); +} diff --git a/source/RocketPlugin/ExternalModules/ExternalModules.cpp b/source/RocketPlugin/ExternalModules/ExternalModules.cpp new file mode 100644 index 0000000..5c27bdc --- /dev/null +++ b/source/RocketPlugin/ExternalModules/ExternalModules.cpp @@ -0,0 +1,154 @@ +#include "ExternalModules.h" + +#include "RocketPlugin.h" + + +/* + * BakkesMod plugin overrides + */ + +/// Registers notifiers for Rocket Plugin. +void RocketPlugin::registerExternalCVars() +{ + // std::string cvar, std::string defaultValue, std::string desc = "", bool searchAble = true, bool hasMin = false, float min = 0, bool hasMax = false, float max = 0, bool saveToCfg = true + for (const auto& [cvar, defaultValue] : ExternalModules::ExternalCVars) { + cvarManager->registerCvar(cvar, defaultValue); + } +} + + +/// Registers notifiers for Rocket Plugin. +void RocketPlugin::registerExternalNotifiers() +{ + for (const auto& [cvar, notifier, description, permissions] : ExternalModules::ExternalNotifiers) { + RegisterNotifier(cvar, notifier, description, permissions); + } + +#ifdef DEBUG + RegisterNotifier("rp_dump_cache", [this](const std::vector&) { + BM_INFO_LOG("Join Maps:"); + BM_INFO_LOG("Current Join Map: {:s}", quote(currentJoinMap.string())); + for (const auto& [path, name] : joinableMaps) { + BM_INFO_LOG("\t{:s}: {:s}", quote(absolute(path).string()), quote(name)); + } + if (enableWorkshopMaps || enableCustomMaps) { + BM_INFO_LOG("Custom Maps:"); + BM_INFO_LOG("Current Maps: {:s}", quote(currentMap)); + for (const auto& [path, name] : customMapPaths) { + BM_INFO_LOG("\t{:s}: {:s}", quote(absolute(path).string()), quote(name)); + } + } + else { + BM_INFO_LOG("Maps:"); + BM_INFO_LOG("Current Maps: {:s}", quote(currentMap)); + for (const auto& [internal, name] : maps) { + BM_INFO_LOG("\t{:s}: {:s}", quote(internal), quote(name)); + } + } + BM_INFO_LOG("Game Modes:"); + BM_INFO_LOG("Selected Game Mode: {:s}", quote(gameModes.GetSelected())); + for (size_t i = 0; i < gameModes.InternalName.size(); i++) { + BM_INFO_LOG("\t{:s}: {:s}", quote(gameModes.InternalName[i]), quote(gameModes.DisplayName[i])); + } + BM_INFO_LOG("Bot Difficulties:"); + BM_INFO_LOG("Selected Bot Difficulty: {:s}", quote(botDifficulties.GetSelected())); + for (size_t i = 0; i < botDifficulties.InternalName.size(); i++) { + BM_INFO_LOG("\t{:s}: {:s}", quote(botDifficulties.InternalName[i]), quote(botDifficulties.DisplayName[i])); + } + BM_INFO_LOG("Custom Colors:"); + BM_INFO_LOG("\tDefault Blue Primary Color: {:#X}", ImGui::ColorConvertFloat4ToU32(defaultBluePrimaryColor)); + BM_INFO_LOG("\tDefault Orange Primary Color: {:#X}", ImGui::ColorConvertFloat4ToU32(defaultOrangePrimaryColor)); + BM_INFO_LOG("\tClub Color Hues: {:d}", clubColorHues); + std::string clubColorBuffer; + for (size_t i = 0; i < clubColors.size(); i++) { + if (i != 0 && i % clubColorHues == 0) { + BM_INFO_LOG("\t{:s}", clubColorBuffer); + clubColorBuffer.clear(); + } + clubColorBuffer += to_hex(ImGui::ColorConvertFloat4ToU32(clubColors[i])) + ", "; + } + if (!clubColorBuffer.empty()) { + BM_INFO_LOG("\t{:s}", clubColorBuffer); + } + BM_INFO_LOG("\tDefault Blue Accent Color: {:#X}", ImGui::ColorConvertFloat4ToU32(defaultBlueAccentColor)); + BM_INFO_LOG("\tDefault Orange Accent Color: {:#X}", ImGui::ColorConvertFloat4ToU32(defaultOrangeAccentColor)); + BM_INFO_LOG("\tCustom Color Hues: {:d}", customColorHues); + std::string customColorBuffer; + for (size_t i = 0; i < customColors.size(); i++) { + if (i != 0 && i % customColorHues == 0) { + BM_INFO_LOG("\t{:s}", customColorBuffer); + customColorBuffer.clear(); + } + customColorBuffer += to_hex(ImGui::ColorConvertFloat4ToU32(customColors[i])) + ", "; + } + if (!customColorBuffer.empty()) { + BM_INFO_LOG("\t{:s}", customColorBuffer); + } + BM_INFO_LOG("Mutators:"); + for (const GameSetting& mutator : mutators) { + BM_INFO_LOG("\t{:s} ({:s}):", quote(mutator.InternalCategoryName), quote(mutator.DisplayCategoryName)); + for (size_t i = 0; i < mutator.InternalName.size(); i++) { + BM_INFO_LOG("\t\t{:s}: {:s}", quote(mutator.InternalName[i]), quote(mutator.DisplayName[i])); + } + } + }, "Prints current cache", PERMISSION_ALL); + + RegisterNotifier("rp_dump_selected_match_settings", [this](const std::vector&) { + if (enableWorkshopMaps || enableCustomMaps) { + if (customMapPaths.find(currentMap) == customMapPaths.end()) { + BM_ERROR_LOG("No map selected to host."); + } + BM_INFO_LOG("MapName: {:s}", quote(std::filesystem::absolute(currentMap).string())); + } + else { + if (maps.find(currentMap) == maps.end()) { + BM_ERROR_LOG("No map selected to host."); + } + BM_INFO_LOG("MapName: {:s}", quote(currentMap)); + } + if (joinableMaps.find(currentJoinMap) == joinableMaps.end()) { + BM_ERROR_LOG("No map selected to join."); + } + BM_INFO_LOG("JoinMapName: {:s}", quote(absolute(currentJoinMap).string())); + BM_INFO_LOG("GameMode: {:s}", quote(gameModes.GetSelected())); + BM_INFO_LOG("GameModeIndex: {:d}", gameModes.CurrentSelected); + BM_INFO_LOG("MaxPlayerCount: {:d}", playerCount); + BM_INFO_LOG("Bot Difficulty: {:s}", quote(botDifficulties.GetSelected())); + BM_INFO_LOG("Password: {:s}", quote(hostPswd)); + + BM_INFO_LOG("TeamSettings 1"); + BM_INFO_LOG("\tName: {:s}", quote(team1Name)); + BM_INFO_LOG("\tColors"); + BM_INFO_LOG("\t\tTeamColorID: {:d}", team1PrimCol); + BM_INFO_LOG("\t\tCustomColorID: {:d}", team1AccCol); + BM_INFO_LOG("\t\tbTeamColorSet: {}", team1PrimCol != -1); + BM_INFO_LOG("\t\tbCustomColorSet: {}", team1AccCol != -1); + BM_INFO_LOG("TeamSettings 2"); + BM_INFO_LOG("\tName: {:s}", quote(team2Name)); + BM_INFO_LOG("\tColors"); + BM_INFO_LOG("\t\tTeamColorID: {:d}", team2PrimCol); + BM_INFO_LOG("\t\tCustomColorID: {:d}", team2AccCol); + BM_INFO_LOG("\t\tbTeamColorSet: {}", team2PrimCol != -1); + BM_INFO_LOG("\t\tbCustomColorSet: {}", team2AccCol != -1); + BM_INFO_LOG("bClubServer: {}", clubMatch); + + BM_INFO_LOG("Mutators:"); + for (const GameSetting& mutator : mutators) { + BM_INFO_LOG("\t{:s}: {:s}", quote(mutator.InternalCategoryName), quote(mutator.GetSelected())); + } + }, "Print selected match settings", PERMISSION_ALL); +#endif +} + + +/// Register hooks for Rocket Plugin. +void RocketPlugin::registerExternalHooks() +{ + for (const auto& [eventName, callback] : ExternalModules::ExternalEventHooksPre) { + HookEventWithCaller(eventName, callback); + } + + for (const auto& [eventName, callback] : ExternalModules::ExternalEventHooksPost) { + HookEventWithCallerPost(eventName, callback); + } +} diff --git a/source/RocketPlugin/ExternalModules/ExternalModules.h b/source/RocketPlugin/ExternalModules/ExternalModules.h new file mode 100644 index 0000000..80959e3 --- /dev/null +++ b/source/RocketPlugin/ExternalModules/ExternalModules.h @@ -0,0 +1,109 @@ +#pragma once + + +namespace ExternalModules +{ + inline std::vector>> ExternalModules; + inline std::vector> ExternalCVars; + inline std::vector&)>, std::string, unsigned char>> ExternalNotifiers; + inline std::vector>> ExternalEventHooksPre; + inline std::vector>> ExternalEventHooksPost; + + template + static void RegisterModule(Ret(*func)(Args...), const Args&&... args) + { + ExternalModules.emplace_back([=]() -> void { + func(std::forward(args)...); + }); + } + + static void RegisterNotifier(const std::string& cvar, const std::function&)>& notifier, const std::string& description, unsigned char permissions) + { + ExternalNotifiers.emplace_back(cvar, notifier, description, permissions); + } + + static void RegisterHookEvent(const std::string& eventName, const std::function& callback) + { + ExternalEventHooksPre.emplace_back(eventName, [=](const ActorWrapper&, const void*, const std::string& eventName_) -> void { + callback(eventName_); + }); + } + + template>* = nullptr> + static void RegisterHookEventWithCaller(const std::string& eventName, const std::function& callback) + { + ExternalEventHooksPre.emplace_back(eventName, [=](const ActorWrapper &caller, const void* params, const std::string& eventName_) -> void { + callback(T(caller.memory_address), params, eventName_); + }); + } + + static void RegisterHookEventPost(const std::string& eventName, const std::function& callback) + { + ExternalEventHooksPost.emplace_back(eventName, [=](const ActorWrapper &, const void* params, const std::string& eventName_) -> void { + callback(eventName_); + }); + } + + template>* = nullptr> + static void RegisterHookEventWithCallerPost(const std::string& eventName, const std::function& callback) + { + ExternalEventHooksPost.emplace_back(eventName, [=](const ActorWrapper &caller, const void* params, const std::string& eventName_) -> void { + callback(T(caller.memory_address), params, eventName_); + }); + } +} + + +#define CONCAT2(A, B) A ## B + +#define CONCAT(A, B) CONCAT2(A, B) + +#pragma section(".CRT$XCU", read) +#define RP_CTOR(fn) \ + static void fn(void); \ + __declspec(allocate(".CRT$XCU")) \ + void(*CONCAT(fn, _))(void) = &fn; \ + static void fn(void) + +#define COUNTER(name) CONCAT(name, __COUNTER__) + +#define RP_EXTERNAL_MODULE(...) \ + RP_CTOR(COUNTER(external_module_)) { \ + ExternalModules::RegisterModule(__VA_ARGS__); \ + } + +#define RP_EXTERNAL_NOTIFIER \ + RP_CTOR(COUNTER(external_notifier_)) { \ + ExternalModules::RegisterNotifier + +#define RP_EXTERNAL_HOOK_EVENT \ + RP_CTOR(COUNTER(external_hook_)) { \ + ExternalModules::RegisterHookEvent + +#define RP_EXTERNAL_HOOK_EVENT_WITH_CALLER \ + RP_CTOR(COUNTER(external_hook_)) { \ + ExternalModules::RegisterHookEventWithCaller + +#define RP_EXTERNAL_HOOK_EVENT_POST \ + RP_CTOR(COUNTER(external_hook_)) { \ + ExternalModules::RegisterHookEventPost + +#define RP_EXTERNAL_HOOK_EVENT_WITH_CALLER_POST \ + RP_CTOR(COUNTER(external_hook_)) { \ + ExternalModules::RegisterHookEventWithCallerPost + +#ifdef DEBUG + #define RP_EXTERNAL_DEBUG_MODULE RP_EXTERNAL_MODULE + #define RP_EXTERNAL_DEBUG_NOTIFIER RP_EXTERNAL_NOTIFIER + #define RP_EXTERNAL_DEBUG_HOOK_EVENT RP_EXTERNAL_HOOK_EVENT + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_WITH_CALLER RP_EXTERNAL_HOOK_EVENT_WITH_CALLER + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_POST RP_EXTERNAL_HOOK_EVENT_POST + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_WITH_CALLER_POST RP_EXTERNAL_HOOK_EVENT_WITH_CALLER_POST +#else + #define RP_EXTERNAL_DEBUG_MODULE(...) static void COUNTER(empty_func_)() { __noop; } + #define RP_EXTERNAL_DEBUG_NOTIFIER(...) static void COUNTER(empty_func_)() { __noop + #define RP_EXTERNAL_DEBUG_HOOK_EVENT(...) static void COUNTER(empty_func_)() { __noop + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_WITH_CALLER(...) static void COUNTER(empty_func_)() { __noop + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_POST(...) static void COUNTER(empty_func_)() { __noop + #define RP_EXTERNAL_DEBUG_HOOK_EVENT_WITH_CALLER_POST(...) static void COUNTER(empty_func_)() { __noop +#endif diff --git a/source/RocketPlugin/ExternalModules/RPTests.cpp b/source/RocketPlugin/ExternalModules/RPTests.cpp new file mode 100644 index 0000000..5eeec6c --- /dev/null +++ b/source/RocketPlugin/ExternalModules/RPTests.cpp @@ -0,0 +1,37 @@ +#include "RocketPlugin.h" + +#include "ExternalModules.h" + + +/* + * Test stuff + */ + +RP_EXTERNAL_DEBUG_NOTIFIER("rp_test_paths", [](const std::vector&) { + BM_INFO_LOG(absolute(BINDS_FILE_PATH).string()); + BM_INFO_LOG(absolute(CONFIG_FILE_PATH).string()); + BM_INFO_LOG(absolute(PRESETS_PATH).string()); + BM_INFO_LOG(absolute(PRO_TIPS_FILE_PATH).string()); + BM_INFO_LOG(absolute(CUSTOM_MAPS_PATH).string()); + BM_INFO_LOG(absolute(WORKSHOP_MAPS_PATH).string()); +}, "Logs paths", PERMISSION_ALL); } + + +RP_EXTERNAL_DEBUG_NOTIFIER("rp_test_logs", [](const std::vector&) { + BM_LOG("normal log"); + BM_TRACE_LOG("trace log"); + BM_INFO_LOG("info log"); + BM_WARNING_LOG("warning log"); + BM_ERROR_LOG("error log"); + BM_CRITICAL_LOG("critical log"); +}, "Logs a bunch", PERMISSION_ALL); } + + +RP_EXTERNAL_DEBUG_NOTIFIER("rp_crash", [](const std::vector&) { + *static_cast(nullptr) = 0; +}, "Crashes by dereferencing nullptr", PERMISSION_ALL); } + + +RP_EXTERNAL_DEBUG_NOTIFIER("rp_throw", [](const std::vector&) { + throw std::runtime_error("NotifierInterrupt"); +}, "Throws exception", PERMISSION_ALL); } diff --git a/source/RocketPlugin/GameModes/BoostMod.cpp b/source/RocketPlugin/GameModes/BoostMod.cpp index 3590be4..3eec04d 100644 --- a/source/RocketPlugin/GameModes/BoostMod.cpp +++ b/source/RocketPlugin/GameModes/BoostMod.cpp @@ -2,7 +2,7 @@ // A general team based boost modifier game mode for Rocket Plugin. // // Author: Al12 and Stanbroek -// Version: 0.1.3 24/12/20 +// Version: 0.1.4 15/08/21 // BMSDK version: 95 #include "BoostMod.h" @@ -42,11 +42,13 @@ bool BoostMod::IsActive() void BoostMod::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& caller, void*, const std::string&) { onTick(caller); }); - HookEventWithCaller("Function GameEvent_Soccar_TA.Countdown.BeginState", + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Countdown.BeginState", [this](const ServerWrapper& caller, void*, const std::string&) { onTick(caller); }); @@ -96,16 +98,10 @@ void BoostMod::renderSingleOption(BoostModifier& boostModifier, const bool toggl /// instance of the server void BoostMod::onTick(ServerWrapper server) { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); for (TeamWrapper team : server.GetTeams()) { - if (team.IsNull()) { - WARNING_LOG("could not get the team"); - continue; - } + BMCHECK_LOOP(team); BoostModifier boostModifier; const int teamIndex = team.GetTeamIndex(); @@ -117,12 +113,14 @@ void BoostMod::onTick(ServerWrapper server) } for (PriWrapper player : team.GetMembers()) { - if (player.IsNull() || player.GetCar().IsNull() || player.GetCar().GetBoostComponent().IsNull()) { - WARNING_LOG("could not get the players car boost component"); - continue; - } + BMCHECK_LOOP(player); + + CarWrapper car = player.GetCar(); + BMCHECK_LOOP(car); + + BoostWrapper boostComponent = car.GetBoostComponent(); + BMCHECK_LOOP(boostComponent); - BoostWrapper boostComponent = player.GetCar().GetBoostComponent(); // Max boost. if (boostComponent.GetCurrentBoostAmount() * 100 > boostModifier.MaxBoost) { boostComponent.SetBoostAmount(boostModifier.MaxBoost / 100.f); @@ -133,27 +131,27 @@ void BoostMod::onTick(ServerWrapper server) boostComponent.SetRechargeDelay(0); switch (boostModifier.BoostAmountModifier) { // No boost - case 1: - boostComponent.SetBoostAmount(0); - boostComponent.ClientGiveBoost(0); - break; + case 1: + boostComponent.SetBoostAmount(0); + boostComponent.ClientGiveBoost(0); + break; // Unlimited - case 2: - boostComponent.SetBoostAmount(1); - boostComponent.ClientGiveBoost(0); - break; + case 2: + boostComponent.SetBoostAmount(1); + boostComponent.ClientGiveBoost(0); + break; // Recharge (slow) - case 3: - boostComponent.SetRechargeRate(0.06660f); - boostComponent.SetRechargeDelay(2); - break; + case 3: + boostComponent.SetRechargeRate(0.06660f); + boostComponent.SetRechargeDelay(2); + break; // Recharge (fast) - case 4: - boostComponent.SetRechargeRate(0.16660f); - boostComponent.SetRechargeDelay(2); - break; - default: - break; + case 4: + boostComponent.SetRechargeRate(0.16660f); + boostComponent.SetRechargeDelay(2); + break; + default: + break; } } } diff --git a/source/RocketPlugin/GameModes/BoostMod.h b/source/RocketPlugin/GameModes/BoostMod.h index f40e8b0..426672a 100644 --- a/source/RocketPlugin/GameModes/BoostMod.h +++ b/source/RocketPlugin/GameModes/BoostMod.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class BoostMod final : public RocketGameMode { public: - explicit BoostMod(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + BoostMod() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; @@ -14,7 +13,8 @@ class BoostMod final : public RocketGameMode std::string GetGameModeName() override; private: - struct BoostModifier { + struct BoostModifier + { // Whether the modifier should be considered. bool Enabled = false; // Maximum amount of boost player can have. (Range: 0-100) diff --git a/source/RocketPlugin/GameModes/BoostShare.cpp b/source/RocketPlugin/GameModes/BoostShare.cpp index 94e63e3..0246d93 100644 --- a/source/RocketPlugin/GameModes/BoostShare.cpp +++ b/source/RocketPlugin/GameModes/BoostShare.cpp @@ -2,7 +2,7 @@ // A boost sharing game mode for Rocket Plugin. // // Author: Stanbroek -// Version: 0.0.3 15/04/21 +// Version: 0.0.4 28/08/21 // BMSDK version: 95 #include "BoostShare.h" @@ -11,11 +11,11 @@ /// Renders the available options for the game mode. void BoostShare::RenderOptions() { - const unsigned short minBoostPool = 0; - const unsigned short maxBoostPool = 200; + constexpr unsigned short minBoostPool = 0; + constexpr unsigned short maxBoostPool = 200; ImGui::SliderScalar("boost pool", ImGuiDataType_U16, &boostPool, &minBoostPool, &maxBoostPool, "%d"); if (ImGui::IsItemJustReleased()) { - gameWrapper->Execute([this](GameWrapper*) { + Execute([this](GameWrapper*) { distributeBoostPool(); }); } @@ -34,13 +34,18 @@ bool BoostShare::IsActive() void BoostShare::Activate(const bool active) { if (active && !isActive) { - HookEvent("Function TAGame.GameEvent_TA.Init", [this](const std::string&) { - initialize(); - }); - HookEvent("Function GameEvent_Soccar_TA.Countdown.BeginState", [this](const std::string&) { - distributeBoostPool(); - }); - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEvent( + "Function TAGame.GameEvent_TA.Init", + [this](const std::string&) { + initialize(); + }); + HookEvent( + "Function GameEvent_Soccar_TA.Countdown.BeginState", + [this](const std::string&) { + distributeBoostPool(); + }); + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& server, void* params, const std::string&) { onTick(server, params); }); @@ -76,34 +81,22 @@ void BoostShare::initialize() const /// Gets called post 'Function GameEvent_Soccar_TA.Countdown.BeginState'. void BoostShare::distributeBoostPool() const { - ServerWrapper game = gameWrapper->GetGameEventAsServer(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); ArrayWrapper cars = game.GetCars(); - if (cars.Count() == 0) { - ERROR_LOG("could not get any cars"); - return; - } + BMCHECK_ARRAY(cars, 0); const int boostPerCar = boostPool / cars.Count(); for (CarWrapper car : cars) { - if (car.IsNull()) { - WARNING_LOG("could not get the car"); - continue; - } + BMCHECK_LOOP(car); BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - WARNING_LOG("could not get the boost component"); - continue; - } + BMCHECK_LOOP(boostComponent); boostComponent.SetBoostAmount(static_cast(boostPerCar) / 100.f); boostComponent.ClientGiveBoost(0); - TRACE_LOG("set {} there boost to {}", quote(car.GetOwnerName()), boostPerCar); + BM_TRACE_LOG("set {:s} there boost to {:d}", quote(car.GetOwnerName()), boostPerCar); } } @@ -114,10 +107,7 @@ void BoostShare::distributeBoostPool() const /// Delay since last update void BoostShare::onTick(ServerWrapper server, void* params) const { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); // delta time since last tick in seconds. const float deltaTime = *static_cast(params); @@ -126,20 +116,14 @@ void BoostShare::onTick(ServerWrapper server, void* params) const ArrayWrapper cars = server.GetCars(); if (cars.Count() == 1) { CarWrapper car = cars.Get(0); - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - return; - } + BMCHECK(car); if (!car.GetInput().ActivateBoost) { return; } BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - ERROR_LOG("could not get the boost component"); - return; - } + BMCHECK(boostComponent); boostComponent.SetBoostAmount(static_cast(boostPool) / 100.f); boostComponent.ClientGiveBoost(0); @@ -148,39 +132,27 @@ void BoostShare::onTick(ServerWrapper server, void* params) const // Otherwise distribute it among the others. for (CarWrapper car : cars) { - if (car.IsNull()) { - WARNING_LOG("could not get the car"); - continue; - } + BMCHECK_LOOP(car); if (!car.GetInput().ActivateBoost) { continue; } BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - WARNING_LOG("could not get the boost component"); - continue; - } + BMCHECK_LOOP(boostComponent); const std::uintptr_t carAddr = car.memory_address; const float boostConsumed = deltaTime * boostComponent.GetBoostConsumptionRate(); const float boostPerCar = boostConsumed / (static_cast(cars.Count()) - 1); for (CarWrapper otherCar : cars) { - if (otherCar.IsNull()) { - WARNING_LOG("could not get the other car"); - continue; - } + BMCHECK_LOOP(otherCar); if (otherCar.memory_address == carAddr) { continue; } BoostWrapper otherBoostComponent = otherCar.GetBoostComponent(); - if (otherBoostComponent.IsNull()) { - WARNING_LOG("could not get the other boost component"); - continue; - } + BMCHECK_LOOP(otherBoostComponent); otherBoostComponent.GiveBoost2(boostPerCar); } @@ -189,37 +161,26 @@ void BoostShare::onTick(ServerWrapper server, void* params) const // Calculate current boost pool. float currentBoostPool = 0; for (CarWrapper car : cars) { - if (car.IsNull()) { - WARNING_LOG("could not get the other car"); - continue; - } + BMCHECK_LOOP(car); BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - WARNING_LOG("could not get the boost component"); - continue; - } + BMCHECK_LOOP(boostComponent); currentBoostPool += boostComponent.GetCurrentBoostAmount(); } // Correct boost pool. - const float boostPerCar = (static_cast(boostPool) / 100 - currentBoostPool) / static_cast(cars.Count()); + const float boostPerCar = (static_cast(boostPool) / 100 - currentBoostPool) / + static_cast(cars.Count()); if (boostPerCar == 0.f) { return; } for (CarWrapper car : cars) { - if (car.IsNull()) { - WARNING_LOG("could not get the other car"); - continue; - } + BMCHECK_LOOP(car); BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - WARNING_LOG("could not get the boost component"); - continue; - } + BMCHECK_LOOP(boostComponent); boostComponent.GiveBoost2(boostPerCar); } diff --git a/source/RocketPlugin/GameModes/BoostShare.h b/source/RocketPlugin/GameModes/BoostShare.h index 6f3f114..9d59193 100644 --- a/source/RocketPlugin/GameModes/BoostShare.h +++ b/source/RocketPlugin/GameModes/BoostShare.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class BoostShare final : public RocketGameMode { public: - explicit BoostShare(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + BoostShare() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/BoostSteal.cpp b/source/RocketPlugin/GameModes/BoostSteal.cpp index c824822..8798059 100644 --- a/source/RocketPlugin/GameModes/BoostSteal.cpp +++ b/source/RocketPlugin/GameModes/BoostSteal.cpp @@ -2,7 +2,7 @@ // A boost stealing game mode for Rocket Plugin. // // Author: Stanbroek -// Version: 0.1.0 24/12/20 +// Version: 0.1.1 15/08/21 // BMSDK version: 95 #include "BoostSteal.h" @@ -27,7 +27,8 @@ bool BoostSteal::IsActive() void BoostSteal::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function TAGame.Car_TA.Demolish", + HookEventWithCaller( + "Function TAGame.Car_TA.Demolish", [this](const CarWrapper& car, void* params, const std::string&) { stealBoost(car, params); }); diff --git a/source/RocketPlugin/GameModes/BoostSteal.h b/source/RocketPlugin/GameModes/BoostSteal.h index 507780f..7f758b2 100644 --- a/source/RocketPlugin/GameModes/BoostSteal.h +++ b/source/RocketPlugin/GameModes/BoostSteal.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class BoostSteal final : public RocketGameMode { public: - explicit BoostSteal(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + BoostSteal() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/CrazyRumble.cpp b/source/RocketPlugin/GameModes/CrazyRumble.cpp index 8799576..1ddbfce 100644 --- a/source/RocketPlugin/GameModes/CrazyRumble.cpp +++ b/source/RocketPlugin/GameModes/CrazyRumble.cpp @@ -2,83 +2,56 @@ // A crazy rumble customizer game mode for Rocket Plugin. // // Author: Stanbroek -// Version: 0.3.1 16/04/21 +// Version: 0.3.3 07/09/21 // BMSDK version: 95 #include "CrazyRumble.h" -#include "RumbleItems/RumbleConstants.inc" - /// Renders the available options for the game mode. void CrazyRumble::RenderOptions() { if (refreshRumbleConstants) { if (!rumbleConstantsRequest.valid()) { - rumbleConstantsRequest = rocketPlugin->ConstantsConfig->RequestRumbleConstants(); + rumbleConstantsRequest = Outer()->ConstantsConfig->RequestRumbleConstants(); } if (rumbleConstantsRequest._Is_ready()) { refreshRumbleConstants = false; const auto& [successful, data] = rumbleConstantsRequest.get(); - if (!successful || !RPConfig::ParseRumbleItems(data, this)) { - rocketPlugin->Execute([this](GameWrapper*) { - WARNING_LOG("could not load rumble items"); - InitializeItemsValues(); - }); - } -#ifdef DEBUG - else { - rocketPlugin->Execute([this](GameWrapper*) { - TRACE_LOG("loading rumble items from game files."); - InitializeItemsValues(); - }); + if (successful) { + RPConfig::ParseRumbleItems(data, this); } -#endif } } bool shouldUpdateCars = false; + bool shouldUpdateItemPool = false; ImGui::Text("Presets:"); ImGui::Spacing(); if (ImGui::Button("Bumper Cars")) { ResetItemsValues(); - powerhitter.DemolishCars = false; - powerhitter.ActivationDuration = 300.0f; + for (const std::shared_ptr& rumbleItem : rumbleItems) { + rumbleItem->Enabled = false; + } + powerhitter->Enabled = true; + powerhitter->DemolishCars = false; + powerhitter->ActivationDuration = 300.0f; shouldUpdateCars = true; + shouldUpdateItemPool = true; } ImGui::SameLine(); if (ImGui::Button("Target Everything")) { ResetItemsValues(); - boot.CanTargetBall = true; - boot.CanTargetCars = true; - boot.CanTargetEnemyCars = true; - boot.CanTargetTeamCars = true; - disruptor.CanTargetBall = true; - disruptor.CanTargetCars = true; - disruptor.CanTargetEnemyCars = true; - disruptor.CanTargetTeamCars = true; - freezer.CanTargetBall = true; - freezer.CanTargetCars = true; - freezer.CanTargetEnemyCars = true; - freezer.CanTargetTeamCars = true; - grapplingHook.CanTargetBall = true; - grapplingHook.CanTargetCars = true; - grapplingHook.CanTargetEnemyCars = true; - grapplingHook.CanTargetTeamCars = true; - haymaker.CanTargetBall = true; - haymaker.CanTargetCars = true; - haymaker.CanTargetEnemyCars = true; - haymaker.CanTargetTeamCars = true; - plunger.CanTargetBall = true; - plunger.CanTargetCars = true; - plunger.CanTargetEnemyCars = true; - plunger.CanTargetTeamCars = true; - swapper.CanTargetBall = true; - swapper.CanTargetCars = true; - swapper.CanTargetEnemyCars = true; - swapper.CanTargetTeamCars = true; + for (const std::shared_ptr& rumbleItem : rumbleItems) { + if (const std::shared_ptr& targetedRumbleItem = std::dynamic_pointer_cast(rumbleItem)) { + targetedRumbleItem->CanTargetBall = true; + targetedRumbleItem->CanTargetCars = true; + targetedRumbleItem->CanTargetEnemyCars = true; + targetedRumbleItem->CanTargetTeamCars = true; + } + } shouldUpdateCars = true; } ImGui::SameLine(); @@ -119,7 +92,7 @@ void CrazyRumble::RenderOptions() shouldUpdateCars = true; } if (ImGui::SliderInt("till next item", &maxTimeTillItem, 0, 20, "%d seconds")) { - rocketPlugin->Execute([this](GameWrapper*) { + Execute([this](GameWrapper*) { updateDispensers(true, false); }); } @@ -151,78 +124,24 @@ void CrazyRumble::RenderOptions() ImGui::Text("Per item customization:"); ImGui::Spacing(); - bool shouldUpdateItemPool = ImGui::Checkbox("##EnableBoot", &boot.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Boot")) { - shouldUpdateCars |= boot.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableDisruptor", &disruptor.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Disruptor")) { - shouldUpdateCars |= disruptor.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableFreezer", &freezer.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Freezer")) { - shouldUpdateCars |= freezer.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableGrapplingHook", &grapplingHook.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Grappling Hook")) { - shouldUpdateCars |= grapplingHook.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableHaymaker", &haymaker.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Haymaker")) { - shouldUpdateCars |= haymaker.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableMagnetizer", &magnetizer.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Magnetizer")) { - shouldUpdateCars |= magnetizer.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnablePlunger", &plunger.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Plunger")) { - shouldUpdateCars |= plunger.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnablePowerhitter", &powerhitter.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Powerhitter")) { - shouldUpdateCars |= powerhitter.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableSpikes", &spikes.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Spikes")) { - shouldUpdateCars |= spikes.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableSwapper", &swapper.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Swapper")) { - shouldUpdateCars |= swapper.Render(); - } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableTornado", &tornado.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Tornado")) { - shouldUpdateCars |= tornado.Render(); + for (const std::shared_ptr& rumbleItem : rumbleItems) { + shouldUpdateItemPool |= ImGui::Checkbox(fmt::format("##Enable{:s}", rumbleItem->DisplayName).c_str(), &rumbleItem->Enabled); + ImGui::SameLine(); + if (ImGui::CollapsingHeader(rumbleItem->DisplayName.c_str())) { + shouldUpdateCars |= rumbleItem->Render(); + } } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableHaunted", &haunted.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Haunted")) { - shouldUpdateCars |= haunted.Render(); + + if (shouldUpdateItemPool) { + Execute([this](GameWrapper*) { + updateDispensers(false, true); + }); } - shouldUpdateItemPool |= ImGui::Checkbox("##EnableRugby", &rugby.Enabled); - ImGui::SameLine(); - if (ImGui::CollapsingHeader("Rugby")) { - shouldUpdateCars |= rugby.Render(); + if (shouldUpdateCars) { + Execute([this](GameWrapper*) { + updateRumbleOptions(); + }); } - - rocketPlugin->Execute([this, shouldUpdateItemPool](GameWrapper*) { - updateDispensers(false, shouldUpdateItemPool); - }); - rocketPlugin->Execute([this, shouldUpdateCars](GameWrapper*) { - updateRumbleOptions(shouldUpdateCars); - }); } @@ -238,11 +157,13 @@ bool CrazyRumble::IsActive() void CrazyRumble::Activate(const bool active) { if (active && !isActive) { - HookEventWithCallerPost("Function TAGame.ItemPool_TA.GiveItem", + HookEventWithCallerPost( + "Function TAGame.ItemPool_TA.GiveItem", [this](const ActorWrapper& caller, void*, const std::string&) { onGiveItem(caller); }); - HookEventWithCallerPost("Function TAGame.PlayerItemDispenser_TA.Init", + HookEventWithCallerPost( + "Function TAGame.PlayerItemDispenser_TA.Init", [this](const ActorWrapper& caller, void*, const std::string&) { updateDispenserItemPool(caller); updateDispenserMaxTimeTillItem(caller); @@ -267,46 +188,19 @@ std::string CrazyRumble::GetGameModeName() } -/// Initializes default rumble items values. -void CrazyRumble::InitializeItemsValues() -{ - boot = RumbleConstants::boot; - disruptor = RumbleConstants::disruptor; - freezer = RumbleConstants::freezer; - grapplingHook = RumbleConstants::grapplingHook; - haymaker = RumbleConstants::haymaker; - magnetizer = RumbleConstants::magnetizer; - plunger = RumbleConstants::plunger; - powerhitter = RumbleConstants::powerhitter; - spikes = RumbleConstants::spikes; - swapper = RumbleConstants::swapper; - tornado = RumbleConstants::tornado; - haunted = RumbleConstants::haunted; - rugby = RumbleConstants::rugby; -} - - +/// Resets the rumble items values void CrazyRumble::ResetItemsValues() { forceMultiplier = 1.f; rangeMultiplier = 1.f; durationMultiplier = 1.f; - boot.Reset(RumbleConstants::boot); - disruptor.Reset(RumbleConstants::disruptor); - freezer.Reset(RumbleConstants::freezer); - grapplingHook.Reset(RumbleConstants::grapplingHook); - haymaker.Reset(RumbleConstants::haymaker); - magnetizer.Reset(RumbleConstants::magnetizer); - plunger.Reset(RumbleConstants::plunger); - powerhitter.Reset(RumbleConstants::powerhitter); - spikes.Reset(RumbleConstants::spikes); - swapper.Reset(RumbleConstants::swapper); - tornado.Reset(RumbleConstants::tornado); - haunted.Reset(RumbleConstants::haunted); - rugby.Reset(RumbleConstants::rugby); + for (const std::shared_ptr& rumbleItem : rumbleItems) { + rumbleItem->Reset(); + } } + /// Resets the rumble items values, with an optional multiplier. /// Multiplier of the force /// Multiplier of the range @@ -318,40 +212,20 @@ void CrazyRumble::UpdateItemsValues(const float newForceMultiplier, const float rangeMultiplier = newRangeMultiplier; durationMultiplier = newDurationMultiplier; - boot.Multiply(RumbleConstants::boot, forceMultiplier, rangeMultiplier, durationMultiplier); - disruptor.Multiply(RumbleConstants::disruptor, forceMultiplier, rangeMultiplier, durationMultiplier); - freezer.Multiply(RumbleConstants::freezer, forceMultiplier, rangeMultiplier, durationMultiplier); - grapplingHook.Multiply(RumbleConstants::grapplingHook, forceMultiplier, rangeMultiplier, durationMultiplier); - haymaker.Multiply(RumbleConstants::haymaker, forceMultiplier, rangeMultiplier, durationMultiplier); - magnetizer.Multiply(RumbleConstants::magnetizer, forceMultiplier, rangeMultiplier, durationMultiplier); - plunger.Multiply(RumbleConstants::plunger, forceMultiplier, rangeMultiplier, durationMultiplier); - powerhitter.Multiply(RumbleConstants::powerhitter, forceMultiplier, rangeMultiplier, durationMultiplier); - spikes.Multiply(RumbleConstants::spikes, forceMultiplier, rangeMultiplier, durationMultiplier); - swapper.Multiply(RumbleConstants::swapper, forceMultiplier, rangeMultiplier, durationMultiplier); - tornado.Multiply(RumbleConstants::tornado, forceMultiplier, rangeMultiplier, durationMultiplier); - haunted.Multiply(RumbleConstants::haunted, forceMultiplier, rangeMultiplier, durationMultiplier); - rugby.Multiply(RumbleConstants::rugby, forceMultiplier, rangeMultiplier, durationMultiplier); + for (const std::shared_ptr& rumbleItem : rumbleItems) { + rumbleItem->Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + } } /// Updates the rumble options for every car. -void CrazyRumble::updateRumbleOptions(const bool update) const +void CrazyRumble::updateRumbleOptions() const { - if (!update) { - return; - } - - ServerWrapper game = gameWrapper->GetGameEventAsServer(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); for (CarWrapper car : game.GetCars()) { - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - continue; - } + BMCHECK_LOOP(car); updateRumbleOptions(car); } @@ -362,60 +236,19 @@ void CrazyRumble::updateRumbleOptions(const bool update) const /// car to set the rumble options for void CrazyRumble::updateRumbleOptions(CarWrapper car) const { - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - return; - } + BMCHECK(car); - RumblePickupComponentWrapper rumbleItem = car.GetAttachedPickup(); - if (rumbleItem.IsNull()) { - ERROR_LOG("could not get rumble item"); - return; - } + RumblePickupComponentWrapper attachedPickup = car.GetAttachedPickup(); + BMCHECK(attachedPickup); - const std::string rumbleItemName = rumbleItem.GetPickupName().ToString(); - if (rumbleItemName == "BallMagnet") { - magnetizer.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "CarSpring") { - boot.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "BallSpring") { - haymaker.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "Tornado") { - tornado.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "GrapplingHook") { - grapplingHook.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "Powerhitter") { - powerhitter.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "EnemyBooster") { - disruptor.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "BallLasso") { - plunger.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "BallVelcro") { - spikes.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "BallFreeze") { - freezer.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "EnemySwapper") { - swapper.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "HauntedBallBeam") { - haunted.Update(rumbleItem.memory_address); - } - else if (rumbleItemName == "RugbySpikes") { - rugby.Update(rumbleItem.memory_address); - } - else { - ERROR_LOG("unknown rumble item {}", quote(rumbleItemName)); + const std::string rumbleItemName = attachedPickup.GetPickupName().ToString(); + for (const std::shared_ptr& rumbleItem : rumbleItems) { + if (rumbleItem->InternalName == rumbleItemName) { + rumbleItem->Update(attachedPickup.memory_address); + // TODO, replicate rumble settings. + return; + } } - // TODO, replicate rumble settings. + BM_ERROR_LOG("unknown rumble item {:s}", quote(rumbleItemName)); } diff --git a/source/RocketPlugin/GameModes/CrazyRumble.h b/source/RocketPlugin/GameModes/CrazyRumble.h index 229de84..fb58c7d 100644 --- a/source/RocketPlugin/GameModes/CrazyRumble.h +++ b/source/RocketPlugin/GameModes/CrazyRumble.h @@ -1,28 +1,57 @@ #pragma once -#include "Config.h" -#include "RocketPlugin.h" +#include "RPConfig.h" #include "GameModes/RocketGameMode.h" #include "RumbleItems/RumbleItems.h" +#include "RumbleItems/RumbleConstants.inc" class CrazyRumble final : public RocketGameMode { public: - explicit CrazyRumble(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + CrazyRumble() + { + typeIdx = std::make_unique(typeid(*this)); + + boot = std::make_unique(&RumbleConstants::boot); + rumbleItems.push_back(boot); + disruptor = std::make_unique(&RumbleConstants::disruptor); + rumbleItems.push_back(disruptor); + freezer = std::make_unique(&RumbleConstants::freezer); + rumbleItems.push_back(freezer); + grapplingHook = std::make_unique(&RumbleConstants::grapplingHook); + rumbleItems.push_back(grapplingHook); + haymaker = std::make_unique(&RumbleConstants::haymaker); + rumbleItems.push_back(haymaker); + magnetizer = std::make_unique(&RumbleConstants::magnetizer); + rumbleItems.push_back(magnetizer); + plunger = std::make_unique(&RumbleConstants::plunger); + rumbleItems.push_back(plunger); + powerhitter = std::make_unique(&RumbleConstants::powerhitter); + rumbleItems.push_back(powerhitter); + spikes = std::make_unique(&RumbleConstants::spikes); + rumbleItems.push_back(spikes); + swapper = std::make_unique(&RumbleConstants::swapper); + rumbleItems.push_back(swapper); + tornado = std::make_unique(&RumbleConstants::tornado); + rumbleItems.push_back(tornado); + haunted = std::make_unique(&RumbleConstants::haunted); + rumbleItems.push_back(haunted); + rugby = std::make_unique(&RumbleConstants::rugby); + rumbleItems.push_back(rugby); + } void RenderOptions() override; bool IsActive() override; void Activate(bool active) override; std::string GetGameModeName() override; - void InitializeItemsValues(); void ResetItemsValues(); void UpdateItemsValues(float newForceMultiplier, float newRangeMultiplier, float newDurationMultiplier); private: void onGiveItem(const ActorWrapper& caller) const; - void updateRumbleOptions(bool update = true) const; + void updateRumbleOptions() const; void updateRumbleOptions(CarWrapper car) const; void updateDispensers(bool updateMaxTimeTillItem = true, bool updateItemPool = true) const; void updateDispenserItemPool(const ActorWrapper& dispenser) const; @@ -33,20 +62,21 @@ class CrazyRumble final : public RocketGameMode float durationMultiplier = 1.0f; int maxTimeTillItem = 10; - BallCarSpringWrapper boot; - BoostOverrideWrapper disruptor; - BallFreezeWrapper freezer; - GrapplingHookWrapper grapplingHook; - BallCarSpringWrapper haymaker; - GravityWrapper magnetizer; - BattarangWrapper plunger; - HitForceWrapper powerhitter; - VelcroWrapper spikes; - SwapperWrapper swapper; - TornadoWrapper tornado; - HauntedWrapper haunted; - RugbyWrapper rugby; + std::shared_ptr boot; + std::shared_ptr disruptor; + std::shared_ptr freezer; + std::shared_ptr grapplingHook; + std::shared_ptr haymaker; + std::shared_ptr magnetizer; + std::shared_ptr plunger; + std::shared_ptr powerhitter; + std::shared_ptr spikes; + std::shared_ptr swapper; + std::shared_ptr tornado; + std::shared_ptr haunted; + std::shared_ptr rugby; bool refreshRumbleConstants = true; + std::vector> rumbleItems; std::future> rumbleConstantsRequest; }; diff --git a/source/RocketPlugin/GameModes/Drainage.cpp b/source/RocketPlugin/GameModes/Drainage.cpp index 76619e7..53de554 100644 --- a/source/RocketPlugin/GameModes/Drainage.cpp +++ b/source/RocketPlugin/GameModes/Drainage.cpp @@ -2,7 +2,7 @@ // A boost draining game mode for Rocket Plugin. // // Author: Stanbroek -// Version: 0.1.0 24/12/20 +// Version: 0.1.1 15/08/21 // BMSDK version: 95 #include "Drainage.h" @@ -28,7 +28,8 @@ bool Drainage::IsActive() void Drainage::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& caller, void* params, const std::string&) { onTick(caller, params); }); @@ -55,25 +56,17 @@ std::string Drainage::GetGameModeName() /// Delay since last update void Drainage::onTick(ServerWrapper server, void* params) const { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); + NULLCHECK(params); // dt since last tick in seconds const float dt = *static_cast(params); for (CarWrapper car : server.GetCars()) { - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - continue; - } + BMCHECK_LOOP(car); BoostWrapper boost = car.GetBoostComponent(); - if (boost.IsNull()) { - ERROR_LOG("could not get the boost component"); - continue; - } + BMCHECK_LOOP(boost); const float boostAmount = boost.GetCurrentBoostAmount(); if (boostAmount > 0) { @@ -82,7 +75,7 @@ void Drainage::onTick(ServerWrapper server, void* params) const } } else { - TRACE_LOG("{} exploded", quote(car.GetOwnerName())); + BM_TRACE_LOG("{:s} exploded", quote(car.GetOwnerName())); car.Demolish2(*dynamic_cast(&car)); } } diff --git a/source/RocketPlugin/GameModes/Drainage.h b/source/RocketPlugin/GameModes/Drainage.h index 23e2a47..55d24ad 100644 --- a/source/RocketPlugin/GameModes/Drainage.h +++ b/source/RocketPlugin/GameModes/Drainage.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class Drainage final : public RocketGameMode { public: - explicit Drainage(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + Drainage() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/Empty.h b/source/RocketPlugin/GameModes/Empty.h index bebb79c..84a9233 100644 --- a/source/RocketPlugin/GameModes/Empty.h +++ b/source/RocketPlugin/GameModes/Empty.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class Empty final : public RocketGameMode { public: - explicit Empty(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + Empty() : RocketGameMode(typeid(*this)) {} void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/Juggernaut.cpp b/source/RocketPlugin/GameModes/Juggernaut.cpp index 4289d89..bc71c0b 100644 --- a/source/RocketPlugin/GameModes/Juggernaut.cpp +++ b/source/RocketPlugin/GameModes/Juggernaut.cpp @@ -2,7 +2,7 @@ // Scoring makes you the juggernaut, but there can only be one. // // Author: Stanbroek -// Version: 0.2.1 16/04/21 +// Version: 0.2.2 28/08/21 // BMSDK version: 95 #include "Juggernaut.h" @@ -38,19 +38,23 @@ bool Juggernaut::IsActive() void Juggernaut::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function TAGame.GameEvent_TA.EventMatchStarted", + HookEventWithCaller( + "Function TAGame.GameEvent_TA.EventMatchStarted", [this](const ActorWrapper&, void*, const std::string&) { initGame(); }); - HookEventWithCaller("Function TAGame.PRI_TA.EventScoredGoal", + HookEventWithCaller( + "Function TAGame.PRI_TA.EventScoredGoal", [this](const ActorWrapper& caller, void*, const std::string&) { onGoalScored(caller); }); - HookEventWithCaller("Function TAGame.PRI_TA.GiveScore", + HookEventWithCaller( + "Function TAGame.PRI_TA.GiveScore", [this](const ActorWrapper& caller, void*, const std::string&) { onGiveScorePre(caller); }); - HookEventWithCallerPost("Function TAGame.PRI_TA.GiveScore", + HookEventWithCallerPost( + "Function TAGame.PRI_TA.GiveScore", [this](const ActorWrapper& caller, void*, const std::string&) { onGiveScorePost(caller); }); @@ -81,23 +85,20 @@ std::string Juggernaut::GetGameModeName() void Juggernaut::onGoalScored(ActorWrapper caller) { PriWrapper scorer = PriWrapper(caller.memory_address); - if (scorer.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } + BMCHECK(scorer); - std::vector players = rocketPlugin->GetPlayers(); + const std::vector players = Outer()->playerMods.GetPlayers(); for (PriWrapper player : players) { player.ServerChangeTeam(NOT_JUGGERNAUT_TEAM); } if (scorer.GetPlayerID() == juggernaut) { - TRACE_LOG("the juggernaut scored"); + BM_TRACE_LOG("the juggernaut scored"); juggernaut = -1; scorer.SetMatchGoals(scorer.GetMatchGoals() + 1); } else { - TRACE_LOG("the juggernaut got scored on"); + BM_TRACE_LOG("the juggernaut got scored on"); juggernaut = scorer.GetPlayerID(); scorer.ServerChangeTeam(JUGGERNAUT_TEAM); } @@ -110,10 +111,7 @@ void Juggernaut::onGoalScored(ActorWrapper caller) void Juggernaut::onGiveScorePre(ActorWrapper caller) { PriWrapper player = PriWrapper(caller.memory_address); - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } + BMCHECK(player); lastNormalGoals = player.GetMatchGoals(); } @@ -125,10 +123,7 @@ void Juggernaut::onGiveScorePre(ActorWrapper caller) void Juggernaut::onGiveScorePost(ActorWrapper caller) const { PriWrapper player = PriWrapper(caller.memory_address); - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } + BMCHECK(player); player.SetMatchGoals(lastNormalGoals); } @@ -138,9 +133,9 @@ void Juggernaut::onGiveScorePost(ActorWrapper caller) const void Juggernaut::initGame() { juggernaut = -1; - std::vector players = rocketPlugin->GetPlayers(); + const std::vector players = Outer()->playerMods.GetPlayers(); for (PriWrapper player : players) { player.ServerChangeTeam(NOT_JUGGERNAUT_TEAM); } - TRACE_LOG("initialized juggernaut game mode"); + BM_TRACE_LOG("initialized juggernaut game mode"); } diff --git a/source/RocketPlugin/GameModes/Juggernaut.h b/source/RocketPlugin/GameModes/Juggernaut.h index b718967..546de65 100644 --- a/source/RocketPlugin/GameModes/Juggernaut.h +++ b/source/RocketPlugin/GameModes/Juggernaut.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class Juggernaut final : public RocketGameMode { public: - explicit Juggernaut(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + Juggernaut() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/KeepAway.cpp b/source/RocketPlugin/GameModes/KeepAway.cpp index 8384b57..930ec0b 100644 --- a/source/RocketPlugin/GameModes/KeepAway.cpp +++ b/source/RocketPlugin/GameModes/KeepAway.cpp @@ -2,9 +2,12 @@ // Touch the ball to get points. // // Author: Stanbroek -// Version: 0.2.2 15/04/21 +// Version: 0.2.3 28/08/21 // BMSDK version: 95 +// BUG's: +// - Clients still get normal points. + #include "KeepAway.h" @@ -20,7 +23,7 @@ void KeepAway::RenderOptions() } } if (ImGui::Button("Reset points")) { - rocketPlugin->Execute([this](GameWrapper*) { + Execute([this](GameWrapper*) { resetPoints(); }); } @@ -44,27 +47,33 @@ void KeepAway::Activate(const bool active) if (active && !isActive) { lastTouched = emptyPlayer; timeSinceLastPoint = 0; - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& caller, void* params, const std::string&) { onTick(caller, params); }); - HookEventWithCaller("Function TAGame.PRI_TA.GiveScore", + HookEventWithCaller( + "Function TAGame.PRI_TA.GiveScore", [this](const ActorWrapper& caller, void*, const std::string&) { onGiveScorePre(caller); }); - HookEventWithCallerPost("Function TAGame.PRI_TA.GiveScore", + HookEventWithCallerPost( + "Function TAGame.PRI_TA.GiveScore", [this](const ActorWrapper& caller, void*, const std::string&) { onGiveScorePost(caller); }); - HookEventWithCaller("Function TAGame.Ball_TA.EventCarTouch", + HookEventWithCaller( + "Function TAGame.Ball_TA.EventCarTouch", [this](const BallWrapper&, void* params, const std::string&) { onCarTouch(params); }); - HookEventWithCaller("Function TAGame.Car_TA.OnHitBall", + HookEventWithCaller( + "Function TAGame.Car_TA.OnHitBall", [this](const CarWrapper& car, void*, const std::string&) { onBallTouch(car); }); - HookEventWithCaller("Function TAGame.GameEvent_Soccar_TA.EventGoalScored", + HookEventWithCaller( + "Function TAGame.GameEvent_Soccar_TA.EventGoalScored", [this](const ActorWrapper&, void*, const std::string&) { lastTouched = emptyPlayer; }); @@ -96,10 +105,7 @@ std::string KeepAway::GetGameModeName() /// Delay since last update void KeepAway::onTick(ServerWrapper server, void* params) { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); if (lastTouched == emptyPlayer) { return; @@ -113,18 +119,15 @@ void KeepAway::onTick(ServerWrapper server, void* params) } const int points = static_cast(floorf(timeSinceLastPoint / secPerPoint)); - std::vector players = rocketPlugin->GetPlayers(true); + const std::vector players = Outer()->playerMods.GetPlayers(true); for (PriWrapper player : players) { if (player.GetUniqueIdWrapper().GetUID() == lastTouched) { player.SetMatchScore(player.GetMatchScore() + points); player.ForceNetUpdate2(); TeamInfoWrapper team = player.GetTeam(); - if (!team.IsNull()) { - rocketPlugin->SetScore(player.GetTeamNum(), team.GetScore() + points); - } - else { - WARNING_LOG("could not get players team"); - } + BMCHECK_LOOP(team); + + Outer()->matchSettings.SetScore(player.GetTeamNum(), team.GetScore() + points); } } @@ -141,10 +144,7 @@ void KeepAway::onGiveScorePre(ActorWrapper caller) return; } PriWrapper player = PriWrapper(caller.memory_address); - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } + BMCHECK(player); lastNormalScore = player.GetMatchScore(); } @@ -160,10 +160,7 @@ void KeepAway::onGiveScorePost(ActorWrapper caller) const } PriWrapper player = PriWrapper(caller.memory_address); - if (player.IsNull()) { - ERROR_LOG("could not get the actor"); - return; - } + BMCHECK(player); player.SetMatchScore(lastNormalScore); player.ForceNetUpdate2(); @@ -175,19 +172,13 @@ void KeepAway::onGiveScorePost(ActorWrapper caller) const /// that touched the ball void KeepAway::onBallTouch(CarWrapper car) { - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - return; - } + BMCHECK(car); PriWrapper pri = car.GetPRI(); - if (pri.IsNull()) { - ERROR_LOG("could not get the pri"); - return; - } + BMCHECK(pri); lastTouched = pri.GetUniqueIdWrapper().GetUID(); - TRACE_LOG("{} touched the ball", quote(car.GetOwnerName())); + BM_TRACE_LOG("{:s} touched the ball", quote(car.GetOwnerName())); timeSinceLastPoint = 0; } @@ -198,27 +189,18 @@ void KeepAway::resetPoints() lastTouched = emptyPlayer; timeSinceLastPoint = 0; - ServerWrapper game = rocketPlugin->GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the local game"); - return; - } + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); for (PriWrapper player : game.GetPRIs()) { - if (player.IsNull()) { - WARNING_LOG("could not get the pri"); - continue; - } + BMCHECK_LOOP(player); player.SetMatchScore(0); player.ForceNetUpdate2(); } for (TeamWrapper team : game.GetTeams()) { - if (team.IsNull()) { - WARNING_LOG("could not get the pri"); - continue; - } + BMCHECK_LOOP(team); team.SetScore(0); } diff --git a/source/RocketPlugin/GameModes/KeepAway.h b/source/RocketPlugin/GameModes/KeepAway.h index eb2d425..5454c15 100644 --- a/source/RocketPlugin/GameModes/KeepAway.h +++ b/source/RocketPlugin/GameModes/KeepAway.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class KeepAway final : public RocketGameMode { public: - explicit KeepAway(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + KeepAway() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/GameModes/RocketGameMode.h b/source/RocketPlugin/GameModes/RocketGameMode.h index 1575b03..73fc5c1 100644 --- a/source/RocketPlugin/GameModes/RocketGameMode.h +++ b/source/RocketPlugin/GameModes/RocketGameMode.h @@ -1,11 +1,12 @@ #pragma once #include "RocketPlugin.h" +#include "Modules/RocketPluginModule.h" -class RocketGameMode +class RocketGameMode : public RocketPluginModule { public: - explicit RocketGameMode(RocketPlugin* rp) { rocketPlugin = rp; gameWrapper = rp->gameWrapper; } + RocketGameMode() = default; virtual ~RocketGameMode() = default; RocketGameMode(const RocketGameMode&) = delete; RocketGameMode(RocketGameMode&&) = delete; @@ -13,71 +14,68 @@ class RocketGameMode RocketGameMode& operator=(RocketGameMode&&) = delete; /* RocketGameMode event hook functions */ - typedef std::function Event; + using EventCallback = RocketPlugin::EventCallback; - template - void HookPre(Caller caller, void* params, const std::string& eventName) + template + void HookPre(Caller caller, void* params, const std::string& eventName) const { - auto funcIt = rocketPlugin->callbacksPre.find(eventName); - if (funcIt != rocketPlugin->callbacksPre.end()) { + const auto funcIt = Outer()->callbacksPre.find(eventName); + if (funcIt != Outer()->callbacksPre.end()) { for (auto& [type, func] : funcIt->second) { func(static_cast(&caller), params, eventName); } } } - void HookEvent(const std::string& eventName, const std::function& callback) + void HookEvent(const std::string& eventName, const std::function& callback) const { - TRACE_LOG("{} hooking {}", quote(_typeid->name()), quote(eventName)); - - const auto it = rocketPlugin->callbacksPre.find(eventName); - if (it == rocketPlugin->callbacksPre.end()) { - rocketPlugin->callbacksPre[eventName] = std::unordered_map(); - rocketPlugin->HookEventWithCaller( - eventName, [this](const ActorWrapper& caller, void* params, const std::string& _eventName) { - HookPre(caller, params, _eventName); - } - ); + BM_TRACE_LOG("{:s} hooking {:s}", quote(typeIdx->name()), quote(eventName)); + + const auto it = Outer()->callbacksPre.find(eventName); + if (it == Outer()->callbacksPre.end()) { + Outer()->callbacksPre[eventName] = std::unordered_map(); + Outer()->HookEventWithCaller(eventName, + [this](const ActorWrapper& caller, void* params, const std::string& eventName_) { + HookPre(caller, params, eventName_); + }); } - rocketPlugin->callbacksPre[eventName].try_emplace( - *_typeid, [this, callback](void*, void*, const std::string& _eventName) { - callback(_eventName); + Outer()->callbacksPre[eventName].try_emplace(*typeIdx, + [this, callback](void*, void*, const std::string& eventName_) { + callback(eventName_); }); } - template + template void HookEventWithCaller(const std::string& eventName, std::function callback) const { - TRACE_LOG("{} hooking {} with caller", quote(_typeid->name()), quote(eventName)); - - const auto it = rocketPlugin->callbacksPre.find(eventName); - if (it == rocketPlugin->callbacksPre.end()) { - rocketPlugin->callbacksPre[eventName] = std::unordered_map(); - rocketPlugin->HookEventWithCaller( - eventName, [this](const Caller& caller, void* params, const std::string& _eventName) { - HookPre(caller, params, _eventName); - } - ); + BM_TRACE_LOG("{:s} hooking {:s} with caller", quote(typeIdx->name()), quote(eventName)); + + const auto it = Outer()->callbacksPre.find(eventName); + if (it == Outer()->callbacksPre.end()) { + Outer()->callbacksPre[eventName] = std::unordered_map(); + Outer()->HookEventWithCaller(eventName, + [this](const Caller& caller, void* params, const std::string& eventName_) { + HookPre(caller, params, eventName_); + }); } - rocketPlugin->callbacksPre[eventName].try_emplace( - *_typeid, [this, callback](void* caller, void* params, std::string _eventName) { - callback(*static_cast(caller), params, _eventName); - } - ); + Outer()->callbacksPre[eventName].try_emplace(*typeIdx, + [this, callback](void* caller, void* params, std::string eventName_) { + callback(*static_cast(caller), params, eventName_); + }); } void UnhookEvent(const std::string& eventName) const { - TRACE_LOG("{} unhooked {}", quote(_typeid->name()), quote(eventName)); + BM_TRACE_LOG("{:s} unhooked {:s}", quote(typeIdx->name()), quote(eventName)); - auto funcIt = rocketPlugin->callbacksPre.find(eventName); - if (funcIt == rocketPlugin->callbacksPre.end()) { + const auto funcIt = Outer()->callbacksPre.find(eventName); + if (funcIt == Outer()->callbacksPre.end()) { return; } - const auto eventIt = funcIt->second.find(*_typeid); + const auto eventIt = funcIt->second.find(*typeIdx); if (eventIt == funcIt->second.end()) { return; } @@ -85,74 +83,70 @@ class RocketGameMode funcIt->second.erase(eventIt); if (funcIt->second.empty()) { - gameWrapper->UnhookEvent(eventName); - rocketPlugin->callbacksPre.erase(funcIt); + Outer()->UnhookEvent(eventName); + Outer()->callbacksPre.erase(funcIt); } } - template - void HookPost(Caller caller, void* params, const std::string& eventName) + template + void HookPost(Caller caller, void* params, const std::string& eventName) const { - auto funcIt = rocketPlugin->callbacksPost.find(eventName); - if (funcIt != rocketPlugin->callbacksPost.end()) { + const auto funcIt = Outer()->callbacksPost.find(eventName); + if (funcIt != Outer()->callbacksPost.end()) { for (auto& [type, func] : funcIt->second) { func(static_cast(&caller), params, eventName); } } } - void HookEventPost(const std::string& eventName, const std::function& callback) + void HookEventPost(const std::string& eventName, const std::function& callback) const { - TRACE_LOG("{} hooking post {}", quote(_typeid->name()), quote(eventName)); - - const auto it = rocketPlugin->callbacksPost.find(eventName); - if (it == rocketPlugin->callbacksPost.end()) { - rocketPlugin->callbacksPost[eventName] = std::unordered_map(); - rocketPlugin->HookEventWithCallerPost( - eventName, [this](const ActorWrapper& caller, void* params, const std::string& _eventName) { - HookPost(caller, params, _eventName); - } - ); + BM_TRACE_LOG("{:s} hooking post {:s}", quote(typeIdx->name()), quote(eventName)); + + const auto it = Outer()->callbacksPost.find(eventName); + if (it == Outer()->callbacksPost.end()) { + Outer()->callbacksPost[eventName] = std::unordered_map(); + Outer()->HookEventWithCallerPost(eventName, + [this](const ActorWrapper& caller, void* params, const std::string& eventName_) { + HookPost(caller, params, eventName_); + }); } - rocketPlugin->callbacksPost[eventName].try_emplace( - *_typeid, [this, callback](void*, void*, const std::string& _eventName) { - callback(_eventName); - } - ); + Outer()->callbacksPost[eventName].try_emplace(*typeIdx, + [this, callback](void*, void*, const std::string& eventName_) { + callback(eventName_); + }); } - template - void HookEventWithCallerPost(const std::string& eventName, std::function callback) + template + void HookEventWithCallerPost(const std::string& eventName, std::function callback) const { - TRACE_LOG("{} hooking post {} with caller", quote(_typeid->name()), quote(eventName)); - - const auto it = rocketPlugin->callbacksPost.find(eventName); - if (it == rocketPlugin->callbacksPost.end()) { - rocketPlugin->callbacksPost[eventName] = std::unordered_map(); - rocketPlugin->HookEventWithCallerPost( - eventName, [this](const Caller& caller, void* params, const std::string& _eventName) { - HookPost(caller, params, _eventName); - } - ); + BM_TRACE_LOG("{:s} hooking post {:s} with caller", quote(typeIdx->name()), quote(eventName)); + + const auto it = Outer()->callbacksPost.find(eventName); + if (it == Outer()->callbacksPost.end()) { + Outer()->callbacksPost[eventName] = std::unordered_map(); + Outer()->HookEventWithCallerPost(eventName, + [this](const Caller& caller, void* params, const std::string& eventName_) { + HookPost(caller, params, eventName_); + }); } - rocketPlugin->callbacksPost[eventName].try_emplace( - *_typeid, [this, callback](void* caller, void* params, std::string _eventName) { - callback(*static_cast(caller), params, _eventName); - } - ); + Outer()->callbacksPost[eventName].try_emplace(*typeIdx, + [this, callback](void* caller, void* params, std::string eventName_) { + callback(*static_cast(caller), params, eventName_); + }); } void UnhookEventPost(const std::string& eventName) const { - TRACE_LOG("{} unhooked post {}", quote(_typeid->name()), quote(eventName)); + BM_TRACE_LOG("{:s} unhooked post {:s}", quote(typeIdx->name()), quote(eventName)); - auto funcIt = rocketPlugin->callbacksPost.find(eventName); - if (funcIt == rocketPlugin->callbacksPost.end()) { + const auto funcIt = Outer()->callbacksPost.find(eventName); + if (funcIt == Outer()->callbacksPost.end()) { return; } - const auto eventIt = funcIt->second.find(*_typeid); + const auto eventIt = funcIt->second.find(*typeIdx); if (eventIt == funcIt->second.end()) { return; } @@ -160,20 +154,37 @@ class RocketGameMode funcIt->second.erase(eventIt); if (funcIt->second.empty()) { - gameWrapper->UnhookEventPost(eventName); - rocketPlugin->callbacksPost.erase(funcIt); + Outer()->UnhookEventPost(eventName); + Outer()->callbacksPost.erase(funcIt); } } + void SetTimeout(const std::function& theLambda, const float time) const + { + Outer()->SetTimeout(theLambda, time); + } + + void Execute(const std::function& theLambda) const + { + Outer()->Execute(theLambda); + } + + void RegisterNotifier(const std::string& cvar, const std::function)>& notifier, + const std::string& description, const unsigned char permissions) const + { + Outer()->RegisterNotifier(cvar, notifier, description, permissions); + } + /* Virtual game mode functions */ virtual void RenderOptions() {} virtual bool IsActive() = 0; virtual void Activate(bool) = 0; - virtual std::string GetGameModeName() { return "Rocket Plugin Game Mode"; } + virtual std::string GetGameModeName() + { + return "Rocket Plugin Game Mode"; + } protected: bool isActive = false; - RocketPlugin* rocketPlugin = nullptr; - std::shared_ptr _typeid; - std::shared_ptr gameWrapper; + std::unique_ptr typeIdx; }; diff --git a/source/RocketPlugin/GameModes/RumbleItems/RumbleConstants.inc b/source/RocketPlugin/GameModes/RumbleItems/RumbleConstants.inc index fba59e4..f3c0399 100644 --- a/source/RocketPlugin/GameModes/RumbleItems/RumbleConstants.inc +++ b/source/RocketPlugin/GameModes/RumbleItems/RumbleConstants.inc @@ -7,8 +7,10 @@ namespace RumbleConstants { { { - true, - 99.f + "Boot", + "CarSpring", + true, + 99.f }, false, true, @@ -30,8 +32,10 @@ namespace RumbleConstants const BoostOverrideWrapper disruptor = { { { - true, - 5.f + "Disruptor", + "EnemyBooster", + true, + 5.f }, false, true, @@ -43,8 +47,10 @@ namespace RumbleConstants const BallFreezeWrapper freezer = { { { - true, - 4.f + "Freezer", + "BallFreeze", + true, + 4.f }, true, false, @@ -59,8 +65,10 @@ namespace RumbleConstants const GrapplingHookWrapper grapplingHook = { { { - true, - 6.f + "Grappling Hook", + "GrapplingHook", + true, + 6.f }, true, false, @@ -77,8 +85,10 @@ namespace RumbleConstants { { { - true, - 99.f + "Haymaker", + "BallSpring", + true, + 99.f }, true, false, @@ -99,6 +109,8 @@ namespace RumbleConstants }; const GravityWrapper magnetizer = { { + "Magnetizer", + "BallMagnet", true, 6.f }, @@ -111,8 +123,10 @@ namespace RumbleConstants { { { - true, - 99.f + "Plunger", + "BallLasso", + true, + 99.f }, true, false, @@ -135,6 +149,8 @@ namespace RumbleConstants }; const HitForceWrapper powerhitter = { { + "Powerhitter", + "Powerhitter", true, 12.f }, @@ -146,6 +162,8 @@ namespace RumbleConstants }; const VelcroWrapper spikes = { { + "Spikes", + "BallVelcro", true, 12.f }, @@ -159,8 +177,10 @@ namespace RumbleConstants const SwapperWrapper swapper = { { { - true, - 0.75f + "Swapper", + "EnemySwapper", + true, + 0.75f }, false, true, @@ -171,6 +191,8 @@ namespace RumbleConstants }; const TornadoWrapper tornado = { { + "Tornado", + "Tornado", true, 8.f }, @@ -187,8 +209,10 @@ namespace RumbleConstants const HauntedWrapper haunted = { { { - true, - 99.f + "Haunted", + "HauntedBallBeam", + true, + 4.f }, 3500.f, 1200.f, @@ -197,8 +221,10 @@ namespace RumbleConstants }; const RugbyWrapper rugby = { { + "Rugby", + "RugbySpikes", true, - 99.f + 100000000000000000.f } }; } diff --git a/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.cpp b/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.cpp index d3d6ebd..0fee6fc 100644 --- a/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.cpp +++ b/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.cpp @@ -2,7 +2,7 @@ // Rumble items wrappers for the RocketPlugin plugin. // // Author: Stanbroek -// Version: 0.6.5 05/02/21 +// Version: 0.6.6 15/08/21 #include "RumbleItems.h" @@ -16,23 +16,24 @@ bool RumbleWrapper::Render() } -void RumbleWrapper::Reset(const RumbleWrapper def) +void RumbleWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = RumbleWrapper(Archetype); Enabled = wasEnabled; } -void RumbleWrapper::Update(RumblePickupComponentWrapper item) const +void RumbleWrapper::Update(const std::uintptr_t item) const { - item.SetActivationDuration(ActivationDuration); + RumblePickupComponentWrapper rumbleItem = item; + rumbleItem.SetActivationDuration(ActivationDuration); } -void RumbleWrapper::Multiply(const RumbleWrapper def, const float, const float, const float durationMultiplier) +void RumbleWrapper::Multiply(const float, const float, const float durationMultiplier) { - ActivationDuration = def.ActivationDuration * durationMultiplier; + ActivationDuration = Archetype->ActivationDuration * durationMultiplier; } @@ -49,29 +50,32 @@ bool TargetedWrapper::Render() } -void TargetedWrapper::Reset(const TargetedWrapper def) +void TargetedWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = TargetedWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void TargetedWrapper::Update(TargetedPickup item) const +void TargetedWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetbCanTargetBall(CanTargetBall); - item.SetbCanTargetCars(CanTargetCars); - item.SetbCanTargetEnemyCars(CanTargetEnemyCars); - item.SetbCanTargetTeamCars(CanTargetTeamCars); - item.SetRange(Range); + Super::Update(item); + TargetedPickup rumbleItem = item; + rumbleItem.SetbCanTargetBall(CanTargetBall); + rumbleItem.SetbCanTargetCars(CanTargetCars); + rumbleItem.SetbCanTargetEnemyCars(CanTargetEnemyCars); + rumbleItem.SetbCanTargetTeamCars(CanTargetTeamCars); + rumbleItem.SetRange(Range); } -void TargetedWrapper::Multiply(const TargetedWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void TargetedWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - Range = def.Range * rangeMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const TargetedWrapper* arch = dynamic_cast(Archetype); + Range = arch->Range * rangeMultiplier; } @@ -92,41 +96,44 @@ bool SpringWrapper::Render() } -void SpringWrapper::Reset(const SpringWrapper def) +void SpringWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = SpringWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void SpringWrapper::Update(SpringPickup item) const +void SpringWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetForce(Force); - item.SetVerticalForce(VerticalForce); - item.SetTorque(Torque); - item.SetRelativeForceNormalDirection(RelativeForceNormalDirection); - item.SetMaxSpringLength(MaxSpringLength); - item.SetConstantForce(ConstantForce); - item.SetMinSpringLength(MinSpringLength); - item.SetWeldedForceScalar(WeldedForceScalar); - item.SetWeldedVerticalForce(WeldedVerticalForce); + Super::Update(item); + SpringPickup rumbleItem = item; + rumbleItem.SetForce(Force); + rumbleItem.SetVerticalForce(VerticalForce); + rumbleItem.SetTorque(Torque); + rumbleItem.SetRelativeForceNormalDirection(RelativeForceNormalDirection); + rumbleItem.SetMaxSpringLength(MaxSpringLength); + rumbleItem.SetConstantForce(ConstantForce); + rumbleItem.SetMinSpringLength(MinSpringLength); + rumbleItem.SetWeldedForceScalar(WeldedForceScalar); + rumbleItem.SetWeldedVerticalForce(WeldedVerticalForce); } -void SpringWrapper::Multiply(const SpringWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void SpringWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - Force = def.Force * forceMultiplier; - VerticalForce = def.VerticalForce * forceMultiplier; - Torque = def.Torque * forceMultiplier; - RelativeForceNormalDirection = def.RelativeForceNormalDirection * forceMultiplier; - MaxSpringLength = def.MaxSpringLength * rangeMultiplier; - ConstantForce = def.ConstantForce * forceMultiplier; - MinSpringLength = def.MinSpringLength * rangeMultiplier; - WeldedForceScalar = def.WeldedForceScalar * forceMultiplier; - WeldedVerticalForce = def.WeldedVerticalForce * forceMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const SpringWrapper* arch = dynamic_cast(Archetype); + Force = arch->Force * forceMultiplier; + VerticalForce = arch->VerticalForce * forceMultiplier; + Torque = arch->Torque * forceMultiplier; + RelativeForceNormalDirection = arch->RelativeForceNormalDirection * forceMultiplier; + MaxSpringLength = arch->MaxSpringLength * rangeMultiplier; + ConstantForce = arch->ConstantForce * forceMultiplier; + MinSpringLength = arch->MinSpringLength * rangeMultiplier; + WeldedForceScalar = arch->WeldedForceScalar * forceMultiplier; + WeldedVerticalForce = arch->WeldedVerticalForce * forceMultiplier; } @@ -136,23 +143,24 @@ bool BallCarSpringWrapper::Render() } -void BallCarSpringWrapper::Reset(const BallCarSpringWrapper def) +void BallCarSpringWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = BallCarSpringWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void BallCarSpringWrapper::Update(BallCarSpringPickup item) const +void BallCarSpringWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); + Super::Update(item); } -void BallCarSpringWrapper::Multiply(const BallCarSpringWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void BallCarSpringWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -162,23 +170,24 @@ bool BoostOverrideWrapper::Render() } -void BoostOverrideWrapper::Reset(const BoostOverrideWrapper def) +void BoostOverrideWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = BoostOverrideWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void BoostOverrideWrapper::Update(BoostOverridePickup item) const +void BoostOverrideWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); + Super::Update(item); } -void BoostOverrideWrapper::Multiply(const BoostOverrideWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void BoostOverrideWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -193,28 +202,31 @@ bool BallFreezeWrapper::Render() } -void BallFreezeWrapper::Reset(const BallFreezeWrapper def) +void BallFreezeWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = BallFreezeWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void BallFreezeWrapper::Update(BallFreezePickup item) const +void BallFreezeWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetbMaintainMomentum(MaintainMomentum); - item.SetTimeToStop(TimeToStop); - item.SetStopMomentumPercentage(StopMomentumPercentage); + Super::Update(item); + BallFreezePickup rumbleItem = item; + rumbleItem.SetbMaintainMomentum(MaintainMomentum); + rumbleItem.SetTimeToStop(TimeToStop); + rumbleItem.SetStopMomentumPercentage(StopMomentumPercentage); } -void BallFreezeWrapper::Multiply(const BallFreezeWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void BallFreezeWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - TimeToStop = def.TimeToStop * durationMultiplier; - StopMomentumPercentage = def.StopMomentumPercentage * durationMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const BallFreezeWrapper* arch = dynamic_cast(Archetype); + TimeToStop = arch->TimeToStop * durationMultiplier; + StopMomentumPercentage = arch->StopMomentumPercentage * durationMultiplier; } @@ -230,31 +242,34 @@ bool GrapplingHookWrapper::Render() } -void GrapplingHookWrapper::Reset(const GrapplingHookWrapper def) +void GrapplingHookWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = GrapplingHookWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void GrapplingHookWrapper::Update(GrapplingHookPickup item) const +void GrapplingHookWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetImpulse(Impulse); - item.SetForce(Force); - item.SetMaxRopeLength(MaxRopeLength); - item.SetPredictionSpeed(PredictionSpeed); + Super::Update(item); + GrapplingHookPickup rumbleItem = item; + rumbleItem.SetImpulse(Impulse); + rumbleItem.SetForce(Force); + rumbleItem.SetMaxRopeLength(MaxRopeLength); + rumbleItem.SetPredictionSpeed(PredictionSpeed); } -void GrapplingHookWrapper::Multiply(const GrapplingHookWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void GrapplingHookWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - Impulse = def.Impulse * forceMultiplier; - Force = def.Force * forceMultiplier; - MaxRopeLength = def.MaxRopeLength * rangeMultiplier; - PredictionSpeed = def.PredictionSpeed * durationMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const GrapplingHookWrapper* arch = dynamic_cast(Archetype); + Impulse = arch->Impulse * forceMultiplier; + Force = arch->Force * forceMultiplier; + MaxRopeLength = arch->MaxRopeLength * rangeMultiplier; + PredictionSpeed = arch->PredictionSpeed * durationMultiplier; } @@ -269,28 +284,31 @@ bool GravityWrapper::Render() } -void GravityWrapper::Reset(const GravityWrapper def) +void GravityWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = GravityWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void GravityWrapper::Update(GravityPickup item) const +void GravityWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetBallGravity(BallGravity); - item.SetRange(Range); - item.SetbDeactivateOnTouch(DeactivateOnTouch); + Super::Update(item); + GravityPickup rumbleItem = item; + rumbleItem.SetBallGravity(BallGravity); + rumbleItem.SetRange(Range); + rumbleItem.SetbDeactivateOnTouch(DeactivateOnTouch); } -void GravityWrapper::Multiply(const GravityWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void GravityWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - //BallGravity = def.BallGravity * forceMultiplier; - Range = def.Range * rangeMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const GravityWrapper* arch = dynamic_cast(Archetype); + //BallGravity = arch->BallGravity * forceMultiplier; + Range = arch->Range * rangeMultiplier; } @@ -300,23 +318,24 @@ bool BallLassoWrapper::Render() } -void BallLassoWrapper::Reset(const BallLassoWrapper def) +void BallLassoWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = BallLassoWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void BallLassoWrapper::Update(BallLassoPickup item) const +void BallLassoWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); + Super::Update(item); } -void BallLassoWrapper::Multiply(const BallLassoWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void BallLassoWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -329,25 +348,28 @@ bool BattarangWrapper::Render() } -void BattarangWrapper::Reset(const BattarangWrapper def) +void BattarangWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = BattarangWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void BattarangWrapper::Update(BattarangPickup item) const +void BattarangWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetSpinSpeed(SpinSpeed); + Super::Update(item); + BattarangPickup rumbleItem = item; + rumbleItem.SetSpinSpeed(SpinSpeed); } -void BattarangWrapper::Multiply(const BattarangWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void BattarangWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - SpinSpeed = def.SpinSpeed * forceMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const BattarangWrapper* arch = dynamic_cast(Archetype); + SpinSpeed = arch->SpinSpeed * forceMultiplier; } @@ -364,30 +386,33 @@ bool HitForceWrapper::Render() } -void HitForceWrapper::Reset(const HitForceWrapper def) +void HitForceWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = HitForceWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void HitForceWrapper::Update(HitForcePickup item) const +void HitForceWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetbBallForce(BallForce); - item.SetbCarForce(CarForce); - item.SetbDemolishCars(DemolishCars); - item.SetBallHitForce(BallHitForce); - item.SetCarHitForce(CarHitForce); + Super::Update(item); + HitForcePickup rumbleItem = item; + rumbleItem.SetbBallForce(BallForce); + rumbleItem.SetbCarForce(CarForce); + rumbleItem.SetbDemolishCars(DemolishCars); + rumbleItem.SetBallHitForce(BallHitForce); + rumbleItem.SetCarHitForce(CarHitForce); } -void HitForceWrapper::Multiply(const HitForceWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void HitForceWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - BallHitForce = def.BallHitForce * forceMultiplier; - CarHitForce = def.CarHitForce * forceMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const HitForceWrapper* arch = dynamic_cast(Archetype); + BallHitForce = arch->BallHitForce * forceMultiplier; + CarHitForce = arch->CarHitForce * forceMultiplier; } @@ -405,35 +430,38 @@ bool VelcroWrapper::Render() } -void VelcroWrapper::Reset(const VelcroWrapper def) +void VelcroWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = VelcroWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void VelcroWrapper::Update(VelcroPickup item) const +void VelcroWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetAfterHitDuration(AfterHitDuration); - item.SetPostBreakDuration(PostBreakDuration); - item.SetMinBreakForce(MinBreakForce); - item.SetMinBreakTime(MinBreakTime); - item.SetAttachTime(AttachTime); - item.SetBreakTime(BreakTime); + Super::Update(item); + VelcroPickup rumbleItem = item; + rumbleItem.SetAfterHitDuration(AfterHitDuration); + rumbleItem.SetPostBreakDuration(PostBreakDuration); + rumbleItem.SetMinBreakForce(MinBreakForce); + rumbleItem.SetMinBreakTime(MinBreakTime); + rumbleItem.SetAttachTime(AttachTime); + rumbleItem.SetBreakTime(BreakTime); } -void VelcroWrapper::Multiply(const VelcroWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void VelcroWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - AfterHitDuration = def.AfterHitDuration * durationMultiplier; - PostBreakDuration = def.PostBreakDuration * durationMultiplier; - MinBreakForce = def.MinBreakForce * forceMultiplier; - MinBreakTime = def.MinBreakTime * durationMultiplier; - AttachTime = def.AttachTime * durationMultiplier; - BreakTime = def.BreakTime * durationMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const VelcroWrapper* arch = dynamic_cast(Archetype); + AfterHitDuration = arch->AfterHitDuration * durationMultiplier; + PostBreakDuration = arch->PostBreakDuration * durationMultiplier; + MinBreakForce = arch->MinBreakForce * forceMultiplier; + MinBreakTime = arch->MinBreakTime * durationMultiplier; + AttachTime = arch->AttachTime * durationMultiplier; + BreakTime = arch->BreakTime * durationMultiplier; } @@ -443,23 +471,24 @@ bool SwapperWrapper::Render() } -void SwapperWrapper::Reset(const SwapperWrapper def) +void SwapperWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = SwapperWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void SwapperWrapper::Update(SwapperPickup item) const +void SwapperWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); + Super::Update(item); } -void SwapperWrapper::Multiply(const SwapperWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void SwapperWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -480,41 +509,44 @@ bool TornadoWrapper::Render() } -void TornadoWrapper::Reset(const TornadoWrapper def) +void TornadoWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = TornadoWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void TornadoWrapper::Update(TornadoPickup item) const +void TornadoWrapper::Update(const std::uintptr_t item) const { - Super::Update(static_cast(item)); - item.SetHeight(Height); - item.SetRadius(Radius); - item.SetRotationalForce(RotationalForce); - item.SetTorque(Torque); - item.SetFXScale(FxScale); - item.SetMeshScale(MeshScale); - item.SetMaxVelocityOffset(MaxVelocityOffset); - item.SetBallMultiplier(BallMultiplier); - item.SetVelocityEase(VelocityEase); + Super::Update(item); + TornadoPickup rumbleItem = item; + rumbleItem.SetHeight(Height); + rumbleItem.SetRadius(Radius); + rumbleItem.SetRotationalForce(RotationalForce); + rumbleItem.SetTorque(Torque); + rumbleItem.SetFXScale(FxScale); + rumbleItem.SetMeshScale(MeshScale); + rumbleItem.SetMaxVelocityOffset(MaxVelocityOffset); + rumbleItem.SetBallMultiplier(BallMultiplier); + rumbleItem.SetVelocityEase(VelocityEase); } -void TornadoWrapper::Multiply(const TornadoWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void TornadoWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); - Height = def.Height * rangeMultiplier; - Radius = def.Radius * rangeMultiplier; - RotationalForce = def.RotationalForce * forceMultiplier; - Torque = def.Torque * forceMultiplier; - FxScale = def.FxScale * rangeMultiplier; - MeshScale = def.MeshScale * rangeMultiplier; - MaxVelocityOffset = def.MaxVelocityOffset * forceMultiplier; - BallMultiplier = def.BallMultiplier * forceMultiplier; - VelocityEase = def.VelocityEase * forceMultiplier; + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); + const TornadoWrapper* arch = dynamic_cast(Archetype); + Height = arch->Height * rangeMultiplier; + Radius = arch->Radius * rangeMultiplier; + RotationalForce = arch->RotationalForce * forceMultiplier; + Torque = arch->Torque * forceMultiplier; + FxScale = arch->FxScale * rangeMultiplier; + MeshScale = arch->MeshScale * rangeMultiplier; + MaxVelocityOffset = arch->MaxVelocityOffset * forceMultiplier; + BallMultiplier = arch->BallMultiplier * forceMultiplier; + VelocityEase = arch->VelocityEase * forceMultiplier; } @@ -524,17 +556,18 @@ bool HauntedWrapper::Render() } -void HauntedWrapper::Reset(const HauntedWrapper def) +void HauntedWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = HauntedWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void HauntedWrapper::Multiply(const HauntedWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void HauntedWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -544,15 +577,16 @@ bool RugbyWrapper::Render() } -void RugbyWrapper::Reset(const RugbyWrapper def) +void RugbyWrapper::Reset() { const bool wasEnabled = Enabled; - *this = def; + *this = RugbyWrapper(dynamic_cast(Archetype)); Enabled = wasEnabled; } -void RugbyWrapper::Multiply(const RugbyWrapper def, const float forceMultiplier, const float rangeMultiplier, const float durationMultiplier) +void RugbyWrapper::Multiply(const float forceMultiplier, const float rangeMultiplier, + const float durationMultiplier) { - Super::Multiply(static_cast(def), forceMultiplier, rangeMultiplier, durationMultiplier); + Super::Multiply(forceMultiplier, rangeMultiplier, durationMultiplier); } diff --git a/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.h b/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.h index e0d42cb..8a23f70 100644 --- a/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.h +++ b/source/RocketPlugin/GameModes/RumbleItems/RumbleItems.h @@ -1,13 +1,31 @@ #pragma once +#include class RumbleWrapper { public: - bool Render(); - void Reset(RumbleWrapper def); - void Update(RumblePickupComponentWrapper item) const; - void Multiply(RumbleWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr RumbleWrapper(const std::string displayName, const std::string internalName, const bool enabled, const float activationDuration) : + DisplayName(std::move(displayName)), + InternalName(std::move(internalName)), + Enabled(enabled), + ActivationDuration(activationDuration) {} + explicit constexpr RumbleWrapper(const RumbleWrapper* archetype) : + Archetype(archetype), + DisplayName(archetype->DisplayName), + InternalName(archetype->InternalName), + Enabled(archetype->Enabled), + ActivationDuration(archetype->ActivationDuration) {} + virtual ~RumbleWrapper() = default; + + virtual bool Render(); + virtual void Reset(); + virtual void Update(std::uintptr_t item) const; + virtual void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier); + + const RumbleWrapper* Archetype = nullptr; + /*const*/ std::string DisplayName; + /*const*/ std::string InternalName; bool Enabled; float ActivationDuration; @@ -18,10 +36,26 @@ class TargetedWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(TargetedWrapper def); - void Update(TargetedPickup item) const; - void Multiply(TargetedWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr TargetedWrapper(const Super& super, const bool canTargetBall, const bool canTargetCars, + const bool canTargetEnemyCars, const bool canTargetTeamCars, const float range) : + Super(super), + CanTargetBall(canTargetBall), + CanTargetCars(canTargetCars), + CanTargetEnemyCars(canTargetEnemyCars), + CanTargetTeamCars(canTargetTeamCars), + Range(range) {} + explicit constexpr TargetedWrapper(const TargetedWrapper* archetype) : + Super(archetype), + CanTargetBall(archetype->CanTargetBall), + CanTargetCars(archetype->CanTargetCars), + CanTargetEnemyCars(archetype->CanTargetEnemyCars), + CanTargetTeamCars(archetype->CanTargetTeamCars), + Range(archetype->Range) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; bool CanTargetBall; bool CanTargetCars; @@ -35,10 +69,35 @@ class SpringWrapper : public TargetedWrapper { using Super = TargetedWrapper; public: - bool Render(); - void Reset(SpringWrapper def); - void Update(SpringPickup item) const; - void Multiply(SpringWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr SpringWrapper(const Super& super, const float force, const float verticalForce, const Vector& torque, + const float relativeForceNormalDirection, const float maxSpringLength, const float constantForce, + const float minSpringLength, const float weldedForceScalar, const float weldedVerticalForce) : + Super(super), + Force(force), + VerticalForce(verticalForce), + Torque(torque), + RelativeForceNormalDirection(relativeForceNormalDirection), + MaxSpringLength(maxSpringLength), + ConstantForce(constantForce), + MinSpringLength(minSpringLength), + WeldedForceScalar(weldedForceScalar), + WeldedVerticalForce(weldedVerticalForce) {} + explicit constexpr SpringWrapper(const SpringWrapper* archetype) : + Super(archetype), + Force(archetype->Force), + VerticalForce(archetype->VerticalForce), + Torque(archetype->Torque), + RelativeForceNormalDirection(archetype->RelativeForceNormalDirection), + MaxSpringLength(archetype->MaxSpringLength), + ConstantForce(archetype->ConstantForce), + MinSpringLength(archetype->MinSpringLength), + WeldedForceScalar(archetype->WeldedForceScalar), + WeldedVerticalForce(archetype->WeldedVerticalForce) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float Force; float VerticalForce; @@ -56,10 +115,13 @@ class BallCarSpringWrapper : public SpringWrapper { using Super = SpringWrapper; public: - bool Render(); - void Reset(BallCarSpringWrapper def); - void Update(BallCarSpringPickup item) const; - void Multiply(BallCarSpringWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr BallCarSpringWrapper(const Super& super) : Super(super) {} + explicit constexpr BallCarSpringWrapper(const BallCarSpringWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; @@ -67,10 +129,13 @@ class BoostOverrideWrapper : public TargetedWrapper { using Super = TargetedWrapper; public: - bool Render(); - void Reset(BoostOverrideWrapper def); - void Update(BoostOverridePickup item) const; - void Multiply(BoostOverrideWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr BoostOverrideWrapper(const Super& super) : Super(super) {} + explicit constexpr BoostOverrideWrapper(const BoostOverrideWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; @@ -78,10 +143,22 @@ class BallFreezeWrapper : public TargetedWrapper { using Super = TargetedWrapper; public: - bool Render(); - void Reset(BallFreezeWrapper def); - void Update(BallFreezePickup item) const; - void Multiply(BallFreezeWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr BallFreezeWrapper(const Super& super, const bool maintainMomentum, const float timeToStop, + const float stopMomentumPercentage) : + Super(super), + MaintainMomentum(maintainMomentum), + TimeToStop(timeToStop), + StopMomentumPercentage(stopMomentumPercentage) {} + explicit constexpr BallFreezeWrapper(const BallFreezeWrapper* archetype) : + Super(archetype), + MaintainMomentum(archetype->MaintainMomentum), + TimeToStop(archetype->TimeToStop), + StopMomentumPercentage(archetype->StopMomentumPercentage) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; bool MaintainMomentum; float TimeToStop; @@ -93,10 +170,24 @@ class GrapplingHookWrapper : public TargetedWrapper { using Super = TargetedWrapper; public: - bool Render(); - void Reset(GrapplingHookWrapper def); - void Update(GrapplingHookPickup item) const; - void Multiply(GrapplingHookWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr GrapplingHookWrapper(const Super& super, const float impulse, const float force, + const float maxRopeLength, const float predictionSpeed) : + Super(super), + Impulse(impulse), + Force(force), + MaxRopeLength(maxRopeLength), + PredictionSpeed(predictionSpeed) {} + explicit constexpr GrapplingHookWrapper(const GrapplingHookWrapper* archetype) : + Super(archetype), + Impulse(archetype->Impulse), + Force(archetype->Force), + MaxRopeLength(archetype->MaxRopeLength), + PredictionSpeed(archetype->PredictionSpeed) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float Impulse; float Force; @@ -109,10 +200,21 @@ class GravityWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(GravityWrapper def); - void Update(GravityPickup item) const; - void Multiply(GravityWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr GravityWrapper(const Super& super, const float ballGravity, const float range, const bool deactivateOnTouch) : + Super(super), + BallGravity(ballGravity), + Range(range), + DeactivateOnTouch(deactivateOnTouch) {} + explicit constexpr GravityWrapper(const GravityWrapper* archetype) : + Super(archetype), + BallGravity(archetype->BallGravity), + Range(archetype->Range), + DeactivateOnTouch(archetype->DeactivateOnTouch) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float BallGravity; float Range; @@ -124,10 +226,13 @@ class BallLassoWrapper : public SpringWrapper { using Super = SpringWrapper; public: - bool Render(); - void Reset(BallLassoWrapper def); - void Update(BallLassoPickup item) const; - void Multiply(BallLassoWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr BallLassoWrapper(const Super& super) : Super(super) {} + explicit constexpr BallLassoWrapper(const BallLassoWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; @@ -135,10 +240,17 @@ class BattarangWrapper : public BallLassoWrapper { using Super = BallLassoWrapper; public: - bool Render(); - void Reset(BattarangWrapper def); - void Update(BattarangPickup item) const; - void Multiply(BattarangWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr BattarangWrapper(const Super& super, const float spinSpeed) : + Super(super), + SpinSpeed(spinSpeed) {} + explicit constexpr BattarangWrapper(const BattarangWrapper* archetype) : + Super(archetype), + SpinSpeed(archetype->SpinSpeed) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float SpinSpeed; }; @@ -148,10 +260,26 @@ class HitForceWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(HitForceWrapper def); - void Update(HitForcePickup item) const; - void Multiply(HitForceWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr HitForceWrapper(const Super& super, const bool ballForce, const bool carForce, const bool demolishCars, + const float ballHitForce, const float carHitForce) : + Super(super), + BallForce(ballForce), + CarForce(carForce), + DemolishCars(demolishCars), + BallHitForce(ballHitForce), + CarHitForce(carHitForce) {} + explicit constexpr HitForceWrapper(const HitForceWrapper* archetype) : + Super(archetype), + BallForce(archetype->BallForce), + CarForce(archetype->CarForce), + DemolishCars(archetype->DemolishCars), + BallHitForce(archetype->BallHitForce), + CarHitForce(archetype->CarHitForce) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; bool BallForce; bool CarForce; @@ -165,10 +293,28 @@ class VelcroWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(VelcroWrapper def); - void Update(VelcroPickup item) const; - void Multiply(VelcroWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr VelcroWrapper(const Super& super, const float afterHitDuration, const float postBreakDuration, + const float minBreakForce, const float minBreakTime, const float attachTime, const float breakTime) : + Super(super), + AfterHitDuration(afterHitDuration), + PostBreakDuration(postBreakDuration), + MinBreakForce(minBreakForce), + MinBreakTime(minBreakTime), + AttachTime(attachTime), + BreakTime(breakTime) {} + explicit constexpr VelcroWrapper(const VelcroWrapper* archetype) : + Super(archetype), + AfterHitDuration(archetype->AfterHitDuration), + PostBreakDuration(archetype->PostBreakDuration), + MinBreakForce(archetype->MinBreakForce), + MinBreakTime(archetype->MinBreakTime), + AttachTime(archetype->AttachTime), + BreakTime(archetype->BreakTime) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float AfterHitDuration; float PostBreakDuration; @@ -183,10 +329,13 @@ class SwapperWrapper : public TargetedWrapper { using Super = TargetedWrapper; public: - bool Render(); - void Reset(SwapperWrapper def); - void Update(SwapperPickup item) const; - void Multiply(SwapperWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr SwapperWrapper(const Super& super) : Super(super) {} + explicit constexpr SwapperWrapper(const SwapperWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; @@ -194,10 +343,35 @@ class TornadoWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(TornadoWrapper def); - void Update(TornadoPickup item) const; - void Multiply(TornadoWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr TornadoWrapper(const Super& super, const float height, const float radius, const float rotationalForce, + const float torque, const Vector& fxScale, const Vector& meshScale, const float maxVelocityOffset, + const float ballMultiplier, const float velocityEase) : + Super(super), + Height(height), + Radius(radius), + RotationalForce(rotationalForce), + Torque(torque), + FxScale(fxScale), + MeshScale(meshScale), + MaxVelocityOffset(maxVelocityOffset), + BallMultiplier(ballMultiplier), + VelocityEase(velocityEase) {} + explicit constexpr TornadoWrapper(const TornadoWrapper* archetype) : + Super(archetype), + Height(archetype->Height), + Radius(archetype->Radius), + RotationalForce(archetype->RotationalForce), + Torque(archetype->Torque), + FxScale(archetype->FxScale), + MeshScale(archetype->MeshScale), + MaxVelocityOffset(archetype->MaxVelocityOffset), + BallMultiplier(archetype->BallMultiplier), + VelocityEase(archetype->VelocityEase) {} + + bool Render() override; + void Reset() override; + void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; float Height; float Radius; @@ -215,10 +389,13 @@ class HauntedWrapper : public GravityWrapper { using Super = GravityWrapper; public: - bool Render(); - void Reset(HauntedWrapper def); - //void Update(HauntedPickup item) const; - void Multiply(HauntedWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr HauntedWrapper(const Super& super) : Super(super) {} + explicit constexpr HauntedWrapper(const HauntedWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + //void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; @@ -226,8 +403,11 @@ class RugbyWrapper : public RumbleWrapper { using Super = RumbleWrapper; public: - bool Render(); - void Reset(RugbyWrapper def); - //void Update(RugbyPickup item) const; - void Multiply(RugbyWrapper def, float forceMultiplier, float rangeMultiplier, float durationMultiplier); + constexpr RugbyWrapper(const Super& super) : Super(super) {} + explicit constexpr RugbyWrapper(const RugbyWrapper* archetype) : Super(archetype) {} + + bool Render() override; + void Reset() override; + //void Update(std::uintptr_t item) const override; + void Multiply(float forceMultiplier, float rangeMultiplier, float durationMultiplier) override; }; diff --git a/source/RocketPlugin/GameModes/SacredGround.cpp b/source/RocketPlugin/GameModes/SacredGround.cpp index 125ead8..8f38772 100644 --- a/source/RocketPlugin/GameModes/SacredGround.cpp +++ b/source/RocketPlugin/GameModes/SacredGround.cpp @@ -2,7 +2,7 @@ // A Rocket Plugin game mode where you have to stay close to your own goal. // // Author: Stanbroek -// Version: 0.0.1 17/04/21 +// Version: 0.0.2 15/08/21 // BMSDK version: 95 #include "SacredGround.h" @@ -27,10 +27,11 @@ bool SacredGround::IsActive() void SacredGround::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", - [this](const ServerWrapper& caller, void*, const std::string&) { - onTick(caller); - }); + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", + [this](const ServerWrapper& caller, void*, const std::string&) { + onTick(caller); + }); } else if (!active && isActive) { UnhookEvent("Function GameEvent_Soccar_TA.Active.Tick"); @@ -66,27 +67,18 @@ float GetDistance(const Vector& p1, const Vector& p2) /// instance of the current server void SacredGround::onTick(ServerWrapper server) const { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); for (CarWrapper car : server.GetCars()) { - if (car.IsNull()) { - WARNING_LOG("could not get the car"); - continue; - } + BMCHECK_LOOP(car); const Vector carLocation = car.GetLocation(); unsigned char closedGoal = car.GetTeamNum2(); float closedGoalDistance = std::numeric_limits::max(); for (GoalWrapper goal : server.GetGoals()) { - if (goal.IsNull()) { - WARNING_LOG("could not get the goal"); - continue; - } - + BMCHECK_LOOP(goal); + const float distance = GetDistance(carLocation, goal.GetLocation()); if (distance < closedGoalDistance) { closedGoal = goal.GetTeamNum(); @@ -98,7 +90,7 @@ void SacredGround::onTick(ServerWrapper server) const if (demoOnGround && !car.AnyWheelTouchingGround()) { continue; } - TRACE_LOG("demolished {}, closed goal was {}", quote(car.GetOwnerName()), closedGoal); + BM_TRACE_LOG("demolished {:s}, closed goal was {:d}", quote(car.GetOwnerName()), closedGoal); car.Demolish(); } } diff --git a/source/RocketPlugin/GameModes/SacredGround.h b/source/RocketPlugin/GameModes/SacredGround.h index 68e0864..6648fbf 100644 --- a/source/RocketPlugin/GameModes/SacredGround.h +++ b/source/RocketPlugin/GameModes/SacredGround.h @@ -6,8 +6,8 @@ class SacredGround final : public RocketGameMode { public: - explicit SacredGround(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } - + SacredGround() { typeIdx = std::make_unique(typeid(*this)); } + void RenderOptions() override; bool IsActive() override; void Activate(bool active) override; diff --git a/source/RocketPlugin/GameModes/SmallCars.cpp b/source/RocketPlugin/GameModes/SmallCars.cpp index ff57190..ae36e26 100644 --- a/source/RocketPlugin/GameModes/SmallCars.cpp +++ b/source/RocketPlugin/GameModes/SmallCars.cpp @@ -2,14 +2,14 @@ // Should scale cars properly. // // Author: Stanbroek -// Version: 0.0.1 13/07/21 +// Version: 0.0.2 28/08/21 // BMSDK version: 95 #include "SmallCars.h" #define UPDATE_FLOAT_COMPONENT_(type, component, scale) \ if (b##component) { \ - TRACE_LOG(#type"::"#component": {}", (scale)); \ + BM_TRACE_LOG(#type"::"#component": {:.3f}", (scale)); \ obj##type.Set##component(obj##type.Get##component() * (scale)); \ } @@ -43,7 +43,7 @@ /// Renders the available options for the game mode. void SmallCars::RenderOptions() { - ServerWrapper game = rocketPlugin->GetGame(); + ServerWrapper game = Outer()->GetGame(); if (game.IsNull()) { ImGui::TextUnformatted("You must be in a game"); return; @@ -67,24 +67,23 @@ void SmallCars::RenderOptions() AirControlComponentWrapper objAirControlComponentWrapper = objCarWrapper.GetAirControlComponent(); JumpComponentWrapper objJumpComponentWrapper = objCarWrapper.GetJumpComponent(); DoubleJumpComponentWrapper objDoubleJumpComponentWrapper = objCarWrapper.GetDoubleJumpComponent(); - if (objFlipCarComponentWrapper.IsNull() || objVehicleSimWrapper.IsNull() || - objBoostWrapper.IsNull() || objDodgeComponentWrapper.IsNull() || - objAirControlComponentWrapper.IsNull() || objJumpComponentWrapper.IsNull() || - objDoubleJumpComponentWrapper.IsNull()) { + if (objFlipCarComponentWrapper.IsNull() || objVehicleSimWrapper.IsNull() || objBoostWrapper.IsNull() || + objDodgeComponentWrapper.IsNull() || objAirControlComponentWrapper.IsNull() || objJumpComponentWrapper.IsNull() + || objDoubleJumpComponentWrapper.IsNull()) { ImGui::TextUnformatted("Car components must be valid"); return; } - const float carScale = rocketPlugin->GetCarScale(objCarWrapper.GetPRI()); + const float carScale = Outer()->carPhysicsMods.GetCarScale(objCarWrapper.GetPRI()); float carScaleTmp = carScale; if (ImGui::SliderFloat("Car Scale", &carScaleTmp, 0.1f, 2.0f, "%.1fX")) { - rocketPlugin->Execute([this, player = objCarWrapper.GetPRI(), newCarScale = carScaleTmp](GameWrapper*) { - rocketPlugin->SetCarScale(player, newCarScale, true); + Execute([this, player = objCarWrapper.GetPRI(), newCarScale = carScaleTmp](GameWrapper*) { + Outer()->carPhysicsMods.SetCarScale(player, newCarScale, true); }); } if (isActive && oldScale != carScale) { - TRACE_LOG("{:.3f} -> {:.3f}", oldScale, carScale); + BM_TRACE_LOG("{:.3f} -> {:.3f}", oldScale, carScale); UPDATE_FLOAT_COMPONENT(CarWrapper, MaxLinearSpeed); UPDATE_FLOAT_COMPONENT(CarWrapper, MaxAngularSpeed); UPDATE_FLOAT_COMPONENT(FlipCarComponentWrapper, FlipCarImpulse); @@ -256,7 +255,8 @@ bool SmallCars::IsActive() void SmallCars::Activate(const bool active) { if (active && !isActive) { - HookEventWithCaller("Function TAGame.Car_TA.PostBeginPlay", + HookEventWithCaller( + "Function TAGame.Car_TA.PostBeginPlay", [this](const ServerWrapper&, void*, const std::string&) { oldScale = 1; }); diff --git a/source/RocketPlugin/GameModes/SmallCars.h b/source/RocketPlugin/GameModes/SmallCars.h index 2d743e9..68c7bd1 100644 --- a/source/RocketPlugin/GameModes/SmallCars.h +++ b/source/RocketPlugin/GameModes/SmallCars.h @@ -6,8 +6,8 @@ class SmallCars final : public RocketGameMode { public: - explicit SmallCars(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } - + SmallCars() { typeIdx = std::make_unique(typeid(*this)); } + void RenderOptions() override; bool IsActive() override; void Activate(bool active) override; diff --git a/source/RocketPlugin/GameModes/Tag.cpp b/source/RocketPlugin/GameModes/Tag.cpp index e46dad1..aacdc35 100644 --- a/source/RocketPlugin/GameModes/Tag.cpp +++ b/source/RocketPlugin/GameModes/Tag.cpp @@ -2,7 +2,7 @@ // Tag others by bumping other and try to survive until the very end. // // Author: Stanbroek -// Version: 0.1.2 16/04/21 +// Version: 0.1.4 12/09/21 // BMSDK version: 95 #include "Tag.h" @@ -12,7 +12,8 @@ void Tag::RenderOptions() { ImGui::Checkbox("Enable Rumble Touches", &enableRumbleTouches); - ImGui::SliderFloat("(0 for infinite)##TimeTillDemolition", &timeTillDemolition, 1, 60, "%.1f Seconds Till Demolition"); + ImGui::SliderFloat( + "(0 for infinite)##TimeTillDemolition", &timeTillDemolition, 1, 60, "%.1f Seconds Till Demolition"); ImGui::SliderFloat("##InvulnerabilityPeriod", &invulnerabilityPeriod, 0, 1, "%.1f Seconds Invulnerable"); ImGui::Separator(); @@ -22,9 +23,9 @@ void Tag::RenderOptions() tagOptionChanged = true; taggedOption = TaggedOption::NONE; } - if (ImGui::RadioButton("Unlimited Boost", taggedOption == TaggedOption::UNLIMITED_BOOST)) { + if (ImGui::RadioButton("Forced Boost", taggedOption == TaggedOption::FORCED_BOOST)) { tagOptionChanged = true; - taggedOption = TaggedOption::UNLIMITED_BOOST; + taggedOption = TaggedOption::FORCED_BOOST; } ImGui::BeginDisabled(); if (ImGui::RadioButton("Different Color", taggedOption == TaggedOption::DIFFERENT_COLOR)) { @@ -54,18 +55,22 @@ bool Tag::IsActive() void Tag::Activate(const bool active) { if (active && !isActive) { - HookEvent("Function TAGame.GameEvent_TA.EventMatchStarted", [this](const std::string&) { - tagRandomPlayer(); - }); - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEvent( + "Function TAGame.GameEvent_TA.EventMatchStarted", [this](const std::string&) { + tagRandomPlayer(); + }); + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& caller, void* params, const std::string&) { onTick(caller, params); }); - HookEventWithCaller("Function TAGame.Car_TA.ApplyCarImpactForces", + HookEventWithCaller( + "Function TAGame.Car_TA.ApplyCarImpactForces", [this](const CarWrapper& caller, void* params, const std::string&) { onCarImpact(caller, params); }); - HookEventWithCaller("Function TAGame.SpecialPickup_Targeted_TA.TryActivate", + HookEventWithCaller( + "Function TAGame.SpecialPickup_Targeted_TA.TryActivate", [this](const ActorWrapper& caller, void* params, const std::string&) { onRumbleItemActivated(caller, params); }); @@ -95,11 +100,12 @@ std::string Tag::GetGameModeName() void Tag::tagRandomPlayer() { timeTagged = 0; - std::vector players = rocketPlugin->GetPlayers(false, true); - + const std::vector players = Outer()->playerMods.GetPlayers(false, true); if (players.size() <= 1) { - tagged = emptyPlayer; - ERROR_LOG("no players to tag"); + if (tagged != emptyPlayer) { + tagged = emptyPlayer; + BM_WARNING_LOG("no players to tag"); + } return; } @@ -108,7 +114,7 @@ void Tag::tagRandomPlayer() const std::uniform_int_distribution distribution(0, players.size() - 1); PriWrapper randomPlayer = players[distribution(generator)]; tagged = randomPlayer.GetUniqueIdWrapper().GetUID(); - TRACE_LOG("{} is now tagged", quote(randomPlayer.GetPlayerName().ToString())); + BM_TRACE_LOG("{:s} is now tagged", quote(randomPlayer.GetPlayerName().ToString())); addHighlight(randomPlayer); } @@ -116,7 +122,7 @@ void Tag::tagRandomPlayer() /// Highlights the tagged player. void Tag::highlightTaggedPlayer() const { - std::vector players = rocketPlugin->GetPlayers(true); + const std::vector players = Outer()->playerMods.GetPlayers(true); for (PriWrapper player : players) { if (player.GetUniqueIdWrapper().GetUID() == tagged) { addHighlight(player); @@ -134,7 +140,7 @@ void Tag::addHighlight(PriWrapper player) const switch (taggedOption) { case TaggedOption::NONE: break; - case TaggedOption::UNLIMITED_BOOST: + case TaggedOption::FORCED_BOOST: if (!car.IsNull() && !car.GetBoostComponent().IsNull()) { car.GetBoostComponent().SetUnlimitedBoost2(true); car.SetbOverrideBoostOn(true); @@ -149,7 +155,7 @@ void Tag::addHighlight(PriWrapper player) const /// Removes the highlights from the tagged player. void Tag::removeHighlightsTaggedPlayer() const { - std::vector players = rocketPlugin->GetPlayers(true); + const std::vector players = Outer()->playerMods.GetPlayers(true); for (PriWrapper player : players) { if (player.GetUniqueIdWrapper().GetUID() == tagged) { removeHighlights(player); @@ -162,17 +168,12 @@ void Tag::removeHighlightsTaggedPlayer() const /// player to remove the highlight from void Tag::removeHighlights(PriWrapper player) const { - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } + BMCHECK(player); // Unlimited Boost CarWrapper car = player.GetCar(); - if (car.IsNull()) { - ERROR_LOG("could not get the car"); - return; - } + BMCHECK(car); + car.GetBoostComponent().SetUnlimitedBoost2(false); car.SetbOverrideBoostOn(false); // Different Color @@ -186,10 +187,7 @@ void Tag::removeHighlights(PriWrapper player) const /// Delay since last update void Tag::onTick(ServerWrapper server, void* params) { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); if (tagged == emptyPlayer) { tagRandomPlayer(); @@ -203,10 +201,10 @@ void Tag::onTick(ServerWrapper server, void* params) return; } - std::vector players = rocketPlugin->GetPlayers(true); + const std::vector players = Outer()->playerMods.GetPlayers(true); for (PriWrapper player : players) { if (player.GetUniqueIdWrapper().GetUID() == tagged) { - rocketPlugin->Demolish(player); + Outer()->playerMods.Demolish(player); player.ServerChangeTeam(-1); } } diff --git a/source/RocketPlugin/GameModes/Tag.h b/source/RocketPlugin/GameModes/Tag.h index b880b01..491e311 100644 --- a/source/RocketPlugin/GameModes/Tag.h +++ b/source/RocketPlugin/GameModes/Tag.h @@ -6,7 +6,7 @@ class Tag final : public RocketGameMode { public: - explicit Tag(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + Tag() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; @@ -34,7 +34,7 @@ class Tag final : public RocketGameMode enum class TaggedOption { NONE, - UNLIMITED_BOOST, + FORCED_BOOST, DIFFERENT_COLOR }; diff --git a/source/RocketPlugin/GameModes/Zombies.cpp b/source/RocketPlugin/GameModes/Zombies.cpp index a6fc474..ba824be 100644 --- a/source/RocketPlugin/GameModes/Zombies.cpp +++ b/source/RocketPlugin/GameModes/Zombies.cpp @@ -2,7 +2,7 @@ // A zombie survival game mode for Rocket Plugin. // // Author: Stanbroek -// Version: 0.2.3 16/04/21 +// Version: 0.2.4 28/08/21 // BMSDK version: 95 #include "Zombies.h" @@ -12,13 +12,13 @@ void Zombies::RenderOptions() { if (ImGui::InputInt("# Zombies", &numZombies)) { - rocketPlugin->Execute([this, newNumZombies = numZombies](GameWrapper*) { + Execute([this, newNumZombies = numZombies](GameWrapper*) { prepareZombies(newNumZombies); }); } std::vector playersNames; - if (rocketPlugin->IsInGame()) { - playersNames = rocketPlugin->GetPlayersNames(); + if (Outer()->IsInGame()) { + playersNames = Outer()->playerMods.GetPlayersNames(); } ImGui::Checkbox("Zombies Have Unlimited Boost", &zombiesHaveUnlimitedBoost); ImGui::Combo("Player to hunt", &selectedPlayer, playersNames, "No players found"); @@ -37,14 +37,17 @@ bool Zombies::IsActive() void Zombies::Activate(const bool active) { if (active && !isActive) { - HookEvent("Function TAGame.GameEvent_TA.EventMatchStarted", [this](const std::string&) { - prepareZombies(numZombies); - }); - HookEventWithCaller("Function GameEvent_Soccar_TA.Active.Tick", + HookEvent( + "Function TAGame.GameEvent_TA.EventMatchStarted", [this](const std::string&) { + prepareZombies(numZombies); + }); + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Active.Tick", [this](const ServerWrapper& caller, void*, const std::string&) { onTick(caller); }); - HookEventWithCaller("Function GameEvent_Soccar_TA.Countdown.BeginState", + HookEventWithCaller( + "Function GameEvent_Soccar_TA.Countdown.BeginState", [this](const ServerWrapper& caller, void*, const std::string&) { onTick(caller); }); @@ -54,7 +57,7 @@ void Zombies::Activate(const bool active) UnhookEvent("Function TAGame.GameEvent_TA.EventMatchStarted"); UnhookEvent("Function GameEvent_Soccar_TA.Active.Tick"); UnhookEvent("Function GameEvent_Soccar_TA.Countdown.BeginState"); - rocketPlugin->ResetBalls(); + Outer()->gameControls.ResetBalls(); } isActive = active; @@ -73,41 +76,31 @@ std::string Zombies::GetGameModeName() /// Number of zombies that chase you void Zombies::prepareZombies(const int newNumZombies) const { - ServerWrapper game = gameWrapper->GetGameEventAsServer(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); game.SetUnfairTeams(true); game.SetbFillWithAI(true); - rocketPlugin->SetNumBotsPerTeam(newNumZombies); - rocketPlugin->SetBallsScale(0.01f); - TRACE_LOG("set number of bots to {}", newNumZombies); + Outer()->botSettings.SetNumBotsPerTeam(newNumZombies); + Outer()->ballMods.SetBallsScale(0.01f); + BM_TRACE_LOG("set number of bots to {:d}", newNumZombies); } /// Updates the game every game tick. void Zombies::onTick(ServerWrapper server) { - if (server.IsNull()) { - ERROR_LOG("could not get the server"); - return; - } + BMCHECK(server); std::vector players; for (PriWrapper pri : server.GetPRIs()) { if (pri.IsNull() || pri.GetbBot()) { if (zombiesHaveUnlimitedBoost) { CarWrapper car = pri.GetCar(); - if (car.IsNull()) { - continue; - } + BMCHECK_LOOP(car); BoostWrapper boostComponent = car.GetBoostComponent(); - if (boostComponent.IsNull()) { - continue; - } + BMCHECK_LOOP(boostComponent); boostComponent.SetBoostAmount(100.0f); } @@ -119,21 +112,15 @@ void Zombies::onTick(ServerWrapper server) if (selectedPlayer >= players.size()) { selectedPlayer = 0; - ERROR_LOG("selected player is out of range"); + BM_ERROR_LOG("selected player is out of range"); return; } CarWrapper target = players[selectedPlayer].GetCar(); - if (target.IsNull()) { - ERROR_LOG("could not get the target"); - return; - } + BMCHECK(target); BallWrapper ball = server.GetBall(); - if (ball.IsNull()) { - ERROR_LOG("could not get the ball"); - return; - } + BMCHECK(ball); ball.SetVelocity(Vector(0, 0, 1)); ball.SetLocation(target.GetLocation()); diff --git a/source/RocketPlugin/GameModes/Zombies.h b/source/RocketPlugin/GameModes/Zombies.h index 7ad6e99..2443ebf 100644 --- a/source/RocketPlugin/GameModes/Zombies.h +++ b/source/RocketPlugin/GameModes/Zombies.h @@ -1,12 +1,11 @@ #pragma once -#include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" class Zombies final : public RocketGameMode { public: - explicit Zombies(RocketPlugin* rp) : RocketGameMode(rp) { _typeid = std::make_shared(typeid(*this)); } + Zombies() { typeIdx = std::make_unique(typeid(*this)); } void RenderOptions() override; bool IsActive() override; diff --git a/source/RocketPlugin/Modules/BallMods.cpp b/source/RocketPlugin/Modules/BallMods.cpp new file mode 100644 index 0000000..d8bdc8c --- /dev/null +++ b/source/RocketPlugin/Modules/BallMods.cpp @@ -0,0 +1,101 @@ +// BallMods.cpp +// Ball mods for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "BallMods.h" +#include "RocketPlugin.h" + + +/// Sets the number of balls in the current game. +/// The new number of balls +void BallMods::SetNumBalls(const int newNumBalls) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetTotalGameBalls(newNumBalls); + + const float ballScale = GetBallsScale(); + game.ResetBalls(); + SetBallsScale(ballScale); +} + + +/// Gets the number of balls in the current game. +/// The number of balls +int BallMods::GetNumBalls() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 0); + + return game.GetTotalGameBalls(); +} + + +/// Sets the scale of the balls in the current game. +/// The new scale of the balls +void BallMods::SetBallsScale(float newBallsScale) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + // The game crashes with negative ball scale. + if (newBallsScale <= 0) { + BM_WARNING_LOG("ball scale out of bounds"); + newBallsScale = 1.0f; + } + + game.ResetBalls(); + for (BallWrapper ball : game.GetGameBalls()) { + BMCHECK_LOOP(ball); + + ball.SetBallScale(newBallsScale); + } +} + + +/// Gets the scale of the balls in the current game. +/// The scale of the balls +float BallMods::GetBallsScale() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 1.f); + + BallWrapper ball = game.GetBall(); + BMCHECK_SILENT(ball, 1.f); + + const float ballScale = ball.GetReplicatedBallScale(); + + return ballScale > 0 ? ballScale : 1.0f; +} + + +/// Sets the max velocity of the balls in the current game. +/// The new max velocity of the balls +void BallMods::SetMaxBallVelocity(const float newMaxBallVelocity) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + for (BallWrapper ball : game.GetGameBalls()) { + BMCHECK_LOOP(ball); + + ball.SetMaxLinearSpeed(newMaxBallVelocity); + } +} + + +/// Gets the max velocity of the balls in the current game. +/// The max velocity of the balls +float BallMods::GetMaxBallVelocity() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 6000.f); + + BallWrapper ball = game.GetBall(); + BMCHECK_SILENT(ball, 6000.f); + + return ball.GetMaxLinearSpeed(); +} diff --git a/source/RocketPlugin/Modules/BallMods.h b/source/RocketPlugin/Modules/BallMods.h new file mode 100644 index 0000000..88a4180 --- /dev/null +++ b/source/RocketPlugin/Modules/BallMods.h @@ -0,0 +1,20 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class BallMods final : RocketPluginModule +{ + friend RocketPlugin; +public: + void SetNumBalls(int newNumBalls) const; + int GetNumBalls() const; + void SetBallsScale(float newBallsScale) const; + float GetBallsScale() const; + void SetMaxBallVelocity(float newMaxBallVelocity) const; + float GetMaxBallVelocity() const; + +protected: + +}; diff --git a/source/RocketPlugin/Modules/BotSettings.cpp b/source/RocketPlugin/Modules/BotSettings.cpp new file mode 100644 index 0000000..0d9245a --- /dev/null +++ b/source/RocketPlugin/Modules/BotSettings.cpp @@ -0,0 +1,141 @@ +// BotSettings.cpp +// Bot settings for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "BotSettings.h" +#include "RocketPlugin.h" + + +/// Sets the number of bots per team in the current game. +/// The new maximum number of bots per team +void BotSettings::SetMaxNumBots(const bool newMaxNumBots) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetNumBots(newMaxNumBots); +} + + +/// Gets the maximum number of bots per team in the current game. +/// The maximum number of bots per team +int BotSettings::GetMaxNumBots() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 0); + + return game.GetNumBots(); +} + + +/// Sets the number of bots per team in the game. +/// The new number of bots per team +void BotSettings::SetNumBotsPerTeam(const int newNumBotsPerTeam) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + const int maxTeamSize = game.GetMaxTeamSize(); + const bool isFilledWithAI = game.GetbFillWithAI(); + game.SetMaxTeamSize(newNumBotsPerTeam); + game.SetbFillWithAI(true); + + const int oldMaxNumBotsPerTeam = game.GetNumBots(); + game.SetNumBots(newNumBotsPerTeam); + // UpdateBotCount() only adds/removes one bot at a time. + for (int botsToAdd = std::max(oldMaxNumBotsPerTeam, newNumBotsPerTeam) * 2; botsToAdd > 0; --botsToAdd) { + game.UpdateBotCount(); + } + + game.SetMaxTeamSize(maxTeamSize); + game.SetbFillWithAI(isFilledWithAI); +} + + +/// Gets the number of bots per team in the game. +/// The number of bots per team +int BotSettings::GetNumBotsPerTeam() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 0); + + return game.GetNumBots(); +} + + +/// Sets if bots are auto filled in the current game. +/// Bool with if bots should be auto filled +void BotSettings::SetIsAutoFilledWithBots(const bool isAutoFilledWithBots) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetbFillWithAI(isAutoFilledWithBots); +} + + +/// Gets if bots are auto filled in the current game. +/// Bool with if bots are auto filled +bool BotSettings::GetIsAutoFilledWithBots() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, false); + + return game.GetbFillWithAI(); +} + + +/// Sets if teams are unfair in the current game. +/// Bool with if teams should be unfair +void BotSettings::SetIsUnfairTeams(const bool isUnfairTeams) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetbUnfairTeams(isUnfairTeams); +} + + +/// Gets if teams are unfair in the current game. +/// bool with if teams are unfair +bool BotSettings::GetIsUnfairTeams() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, false); + + return game.GetbUnfairTeams(); +} + + +/// Freezes or unfreezes all bots. +void BotSettings::FreezeBots() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + bool firstBot = true; + bool shouldUnFreeze = false; + for (CarWrapper car : game.GetCars()) { + BMCHECK_LOOP(car); + + PriWrapper player = car.GetPRI(); + BMCHECK_LOOP(player); + if (!player.GetbBot()) { + continue; + } + + if (firstBot) { + shouldUnFreeze = car.GetbFrozen(); + firstBot = false; + } + + if (shouldUnFreeze) { + car.SetFrozen(false); + } + else { + car.SetFrozen(true); + } + } +} diff --git a/source/RocketPlugin/Modules/BotSettings.h b/source/RocketPlugin/Modules/BotSettings.h new file mode 100644 index 0000000..3461b12 --- /dev/null +++ b/source/RocketPlugin/Modules/BotSettings.h @@ -0,0 +1,23 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class BotSettings final : RocketPluginModule +{ + friend RocketPlugin; +public: + void SetMaxNumBots(bool newMaxNumBots) const; + int GetMaxNumBots() const; + void SetNumBotsPerTeam(int newNumBotsPerTeam) const; + int GetNumBotsPerTeam() const; + void SetIsAutoFilledWithBots(bool isAutoFilledWithBots) const; + bool GetIsAutoFilledWithBots() const; + void SetIsUnfairTeams(bool isUnfairTeams) const; + bool GetIsUnfairTeams() const; + void FreezeBots() const; + +protected: + +}; diff --git a/source/RocketPlugin/Modules/CarPhysicsMods.cpp b/source/RocketPlugin/Modules/CarPhysicsMods.cpp new file mode 100644 index 0000000..c5da3b9 --- /dev/null +++ b/source/RocketPlugin/Modules/CarPhysicsMods.cpp @@ -0,0 +1,304 @@ +// CarPhysicsMods.cpp +// Car physics mods for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "CarPhysicsMods.h" +#include "RocketPlugin.h" + + +CarPhysicsMods::CarPhysics::CarPhysics(const RocketPlugin* rp, const PriWrapper player) +{ + CarScale = rp->carPhysicsMods.GetCarScale(player); + CarHasCollision = rp->carPhysicsMods.GetbCarCollision(player); + CarIsFrozen = rp->carPhysicsMods.GetCarIsFrozen(player); + TorqueRate = rp->carPhysicsMods.GetTorqueRate(player); + MaxCarVelocity = rp->carPhysicsMods.GetMaxCarVelocity(player); + GroundStickyForce = rp->carPhysicsMods.GetGroundStickyForce(player); + WallStickyForce = rp->carPhysicsMods.GetWallStickyForce(player); +} + + +/// Sets the car physics for the player. +/// Gets called on 'TAGame.Car_TA.EventVehicleSetup'. +/// The players car to set the physics of +void CarPhysicsMods::SetPhysics(CarWrapper car) +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + BMCHECK(car); + + PriWrapper player = car.GetPRI(); + BMCHECK(player); + + const auto& it = carPhysics.find(player.GetUniqueIdWrapper().GetUID()); + if (it == carPhysics.end()) { + return; + } + + const CarPhysics playerCarPhysics = it->second; + SetCarScale(player, playerCarPhysics.CarScale); + SetbCarCollision(player, playerCarPhysics.CarHasCollision); + SetCarIsFrozen(player, playerCarPhysics.CarIsFrozen); + SetTorqueRate(player, playerCarPhysics.TorqueRate); + SetMaxCarVelocity(player, playerCarPhysics.MaxCarVelocity); + SetGroundStickyForce(player, playerCarPhysics.GroundStickyForce); + SetWallStickyForce(player, playerCarPhysics.WallStickyForce); +} + + +/// Gets the car physics for the player. +/// The player to get the car physics from +/// The car physics for the player +CarPhysicsMods::CarPhysics CarPhysicsMods::GetPhysics(PriWrapper player) +{ + BMCHECK_SILENT(player, CarPhysics(Outer(), player)); + + const auto& it = carPhysics.find(player.GetUniqueIdWrapper().GetUID()); + if (it == carPhysics.end()) { + return CarPhysics(Outer(), player); + } + + return it->second; +} + + +/// Gets the car physics for the player and saves them when not found. +/// The player to get the car physics from +/// The car physics for the player +CarPhysicsMods::CarPhysics& CarPhysicsMods::GetPhysicsCache(PriWrapper player) +{ + const uint64_t steamID = player.GetUniqueIdWrapper().GetUID(); + return carPhysics.try_emplace(steamID, CarPhysics(Outer(), player)).first->second; +} + + +/// Sets the if the players car has collision in the current game. +/// the player to update the car of +/// Bool with if the players car should have collision +void CarPhysicsMods::SetbCarCollision(PriWrapper player, const bool carHasCollision) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + GetPhysicsCache(player).CarHasCollision = carHasCollision; + car.SetbCollideActors(carHasCollision); +} + + +/// Gets the if the players car has collision in the current game. +/// The player to check the car of +/// Bool with if the players car has collision +bool CarPhysicsMods::GetbCarCollision(PriWrapper player) const +{ + BMCHECK_SILENT(player, true); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, true); + + return car.GetbCollideActors(); +} + + +/// Sets the players car scale in the current game. +/// The player to update the car of +/// The players car scale +/// Bool with if the car should respawn in place +void CarPhysicsMods::SetCarScale(PriWrapper player, const float newCarScale, const bool shouldRespawn) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + GetPhysicsCache(player).CarScale = newCarScale; + car.SetCarScale(newCarScale); + if (shouldRespawn) { + player.GetCar().RespawnInPlace(); + } +} + + +/// Gets the players car scale in the current game. +/// The player to check the car of +/// The players car scale +float CarPhysicsMods::GetCarScale(PriWrapper player) const +{ + BMCHECK_SILENT(player, 1.f); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, 1.f); + + const float carScale = car.GetReplicatedCarScale(); + + return carScale > 0 ? carScale : 1.0f; +} + + +/// Sets the if the players car should be frozen in the current game. +/// The player to update the car of +/// Bool with if the players car should be frozen +void CarPhysicsMods::SetCarIsFrozen(PriWrapper player, const bool carIsFrozen) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + GetPhysicsCache(player).CarIsFrozen = carIsFrozen; + car.SetFrozen(carIsFrozen); +} + + +/// Gets the if the players car is frozen in the current game. +/// The player to update the car of +/// Bool with if the players car is frozen +bool CarPhysicsMods::GetCarIsFrozen(PriWrapper player) const +{ + BMCHECK_SILENT(player, false); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, false); + + return car.GetbFrozen(); +} + + +/// Sets the players car drive torque in the current game. +/// The player to update the car of +/// The new drive torque of the players car +void CarPhysicsMods::SetTorqueRate(PriWrapper player, const float torqueRate) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + GetPhysicsCache(player).TorqueRate = torqueRate; + car.GetVehicleSim().SetDriveTorque(torqueRate * 100000); +} + + +/// Gets the players car drive torque in the current game. +/// The player to check the car of +/// The drive torque of the players car +float CarPhysicsMods::GetTorqueRate(PriWrapper player) const +{ + BMCHECK_SILENT(player, 2.88f); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, 2.88f); + + return car.GetVehicleSim().GetDriveTorque() / 100000; +} + + +/// Sets the players car max velocity in the current game. +/// The player to update the car of +/// The new max velocity of the players car +void CarPhysicsMods::SetMaxCarVelocity(PriWrapper player, const float maxCarVelocity) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + GetPhysicsCache(player).MaxCarVelocity = maxCarVelocity; + car.SetMaxLinearSpeed(maxCarVelocity); +} + + +/// Gets the players car max velocity in the current game. +/// the player to check the car of +/// The max velocity of the players car +float CarPhysicsMods::GetMaxCarVelocity(PriWrapper player) const +{ + BMCHECK_SILENT(player, 2300.f); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, 2300.f); + + return car.GetMaxLinearSpeed(); +} + + +/// Gets the players car sticky force in the current game. +/// The player to get the sticky force of the car of +/// The sticky force of the players car +StickyForceData CarPhysicsMods::GetStickyForce(PriWrapper player) const +{ + BMCHECK_SILENT(player, StickyForceData()); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, StickyForceData()); + + return car.GetStickyForce(); +} + + +/// Sets the players car ground sticky force in the current game. +/// The player to update the car of +/// The new ground sticky force of the players car +void CarPhysicsMods::SetGroundStickyForce(PriWrapper player, const float groundStickyForce) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + StickyForceData sfd = GetStickyForce(player); + sfd.Ground = groundStickyForce; + + GetPhysicsCache(player).GroundStickyForce = groundStickyForce; + car.SetStickyForce(sfd); +} + + +/// Gets the players car ground sticky force in the current game. +/// The player to check the car of +/// The ground sticky force of the players car +float CarPhysicsMods::GetGroundStickyForce(PriWrapper player) const +{ + BMCHECK_SILENT(player, .5f); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, .5f); + + return car.GetStickyForce().Ground; +} + + +/// Sets the players car wall sticky force in the current game. +/// The player to update the car of +/// The new wall sticky force of the players car +void CarPhysicsMods::SetWallStickyForce(PriWrapper player, const float wallStickyForce) +{ + BMCHECK(player); + + CarWrapper car = player.GetCar(); + BMCHECK(car); + + StickyForceData sfd = GetStickyForce(player); + sfd.Wall = wallStickyForce; + + GetPhysicsCache(player).WallStickyForce = wallStickyForce; + car.SetStickyForce(sfd); +} + + +/// Gets the players car wall sticky force in the current game. +/// The player to check the car of +/// The wall sticky force of the players car +float CarPhysicsMods::GetWallStickyForce(PriWrapper player) const +{ + BMCHECK_SILENT(player, 1.5f); + + CarWrapper car = player.GetCar(); + BMCHECK_SILENT(car, 1.5f); + + return car.GetStickyForce().Wall; +} diff --git a/source/RocketPlugin/Modules/CarPhysicsMods.h b/source/RocketPlugin/Modules/CarPhysicsMods.h new file mode 100644 index 0000000..7f3c8a4 --- /dev/null +++ b/source/RocketPlugin/Modules/CarPhysicsMods.h @@ -0,0 +1,44 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class CarPhysicsMods final : RocketPluginModule +{ + friend RocketPlugin; +public: + struct CarPhysics { + CarPhysics(const RocketPlugin* rp, PriWrapper player); + + float CarScale; + bool CarHasCollision; + bool CarIsFrozen; + float TorqueRate; + float MaxCarVelocity; + float GroundStickyForce; + float WallStickyForce; + }; + void SetPhysics(CarWrapper car); + CarPhysics GetPhysics(PriWrapper player); + CarPhysics& GetPhysicsCache(PriWrapper player); + void SetbCarCollision(PriWrapper player, bool carHasCollision); + bool GetbCarCollision(PriWrapper player) const; + void SetCarScale(PriWrapper player, float newCarScale, bool shouldRespawn = false); + float GetCarScale(PriWrapper player) const; + void SetCarIsFrozen(PriWrapper player, bool carIsFrozen); + bool GetCarIsFrozen(PriWrapper player) const; + void SetTorqueRate(PriWrapper player, float torqueRate); + float GetTorqueRate(PriWrapper player) const; + void SetMaxCarVelocity(PriWrapper player, float maxCarVelocity); + float GetMaxCarVelocity(PriWrapper player) const; + StickyForceData GetStickyForce(PriWrapper player) const; + void SetGroundStickyForce(PriWrapper player, float groundStickyForce); + float GetGroundStickyForce(PriWrapper player) const; + void SetWallStickyForce(PriWrapper player, float wallStickyForce); + float GetWallStickyForce(PriWrapper player) const; + +protected: + size_t selectedPlayer = 0; + std::unordered_map carPhysics; +}; diff --git a/source/RocketPlugin/Modules/Empty.cpp b/source/RocketPlugin/Modules/Empty.cpp new file mode 100644 index 0000000..f12e3f1 --- /dev/null +++ b/source/RocketPlugin/Modules/Empty.cpp @@ -0,0 +1,8 @@ +// Empty.cpp +// Module template for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "Empty.h" +#include "RocketPlugin.h" diff --git a/source/RocketPlugin/Modules/Empty.h b/source/RocketPlugin/Modules/Empty.h new file mode 100644 index 0000000..af8eeca --- /dev/null +++ b/source/RocketPlugin/Modules/Empty.h @@ -0,0 +1,14 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class Empty final : RocketPluginModule +{ + friend RocketPlugin; +public: + +protected: + +}; diff --git a/source/RocketPlugin/Modules/GameControls.cpp b/source/RocketPlugin/Modules/GameControls.cpp new file mode 100644 index 0000000..458b4de --- /dev/null +++ b/source/RocketPlugin/Modules/GameControls.cpp @@ -0,0 +1,74 @@ +// GameControls.cpp +// Game controls for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "GameControls.h" +#include "RocketPlugin.h" + + +/// Forces overtime in the current game. +void GameControls::ForceOvertime() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.ForceOvertime(); +} + + +/// Pauses the current game. +void GameControls::PauseServer() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + PlayerControllerWrapper pc = game.GetPauser(); + if (pc.IsNull()) { + Outer()->cvarManager->executeCommand("mp_pause", false); + } + else { + Outer()->cvarManager->executeCommand("mp_unpause", false); + } +} + + +/// Resets the current game. +void GameControls::ResetMatch() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.StartNewRound(); +} + + +/// Ends the current game. +void GameControls::EndMatch() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.EndGame(); +} + + +/// Resets the players in the current game. +void GameControls::ResetPlayers() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.ResetPlayers(); +} + + +/// Resets the balls in the current game. +void GameControls::ResetBalls() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.ResetBalls(); +} diff --git a/source/RocketPlugin/Modules/GameControls.h b/source/RocketPlugin/Modules/GameControls.h new file mode 100644 index 0000000..e8ca06f --- /dev/null +++ b/source/RocketPlugin/Modules/GameControls.h @@ -0,0 +1,20 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class GameControls final : RocketPluginModule +{ + friend RocketPlugin; +public: + void ForceOvertime() const; + void PauseServer() const; + void ResetMatch() const; + void EndMatch() const; + void ResetPlayers() const; + void ResetBalls() const; + +protected: + +}; diff --git a/source/RocketPlugin/Modules/LocalMatchSettings.cpp b/source/RocketPlugin/Modules/LocalMatchSettings.cpp new file mode 100644 index 0000000..8926186 --- /dev/null +++ b/source/RocketPlugin/Modules/LocalMatchSettings.cpp @@ -0,0 +1,253 @@ +// LocalMatchSettings.cpp +// Local match settings for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "LocalMatchSettings.h" +#include "RocketPlugin.h" + + +/// Sets max players in the current game. +/// New number of players +void LocalMatchSettings::SetMaxPlayers(const int newNumPlayers) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetMaxPlayers(newNumPlayers); +} + + +/// Gets max players in the current game. +/// Max number of players +int LocalMatchSettings::GetMaxPlayers() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 16); + + return game.GetMaxPlayers(); +} + + +/// Sets max team size in the current game. +/// New team size +void LocalMatchSettings::SetMaxTeamSize(const int newTeamSize) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetMaxTeamSize(newTeamSize); +} + + +/// Gets max team size in the current game. +/// Max team size +int LocalMatchSettings::GetMaxTeamSize() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 3); + + return game.GetMaxTeamSize(); +} + + +/// Sets respawn time in the current game. +/// New respawn time +void LocalMatchSettings::SetRespawnTime(const int newRespawnTime) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetRespawnTime(newRespawnTime); +} + + +/// Gets respawn time in the current game. +/// Respawn time +int LocalMatchSettings::GetRespawnTime() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, 3); + + return game.GetRespawnTime(); +} + + +/// Sets the score of the given team in the current game. +/// Team to set the score of +/// New score +void LocalMatchSettings::SetScore(int team, int newScore) const +{ + switch (team) { + case 0: + return SetScoreBlue(newScore); + case 1: + return SetScoreOrange(newScore); + default: + BM_ERROR_LOG("team #{:d} not found", team); + } +} + + +/// Gets the score of the given team in the current game. +/// Team to get the score of +/// Teams score +int LocalMatchSettings::GetScore(int team) const +{ + switch (team) { + case 0: + return GetScoreBlue(); + case 1: + return GetScoreOrange(); + default: + BM_ERROR_LOG("invalid team #{:d}", team); + return 0; + } +} + + +/// Sets blues score in the current game. +/// New score +void LocalMatchSettings::SetScoreBlue(const int newScore) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + ArrayWrapper teams = game.GetTeams(); + if (teams.Count() < 1) { + BM_ERROR_LOG("could not get the blue team"); + return; + } + + TeamWrapper blueTeam = teams.Get(0); + BMCHECK(blueTeam); + + blueTeam.SetScore(newScore); +} + + +/// Gets blues score in the current game. +/// Blues score +int LocalMatchSettings::GetScoreBlue() const +{ + ServerWrapper game = Outer()->GetGame(true); + BMCHECK_SILENT(game, 0); + + ArrayWrapper teams = game.GetTeams(); + if (teams.Count() < 1) { + BM_ERROR_LOG("could not get the blue team"); + return 0; + } + + TeamWrapper blueTeam = teams.Get(0); + BMCHECK(blueTeam, 0); + + return blueTeam.GetScore(); +} + + +/// Sets oranges score in the current game. +/// New score +void LocalMatchSettings::SetScoreOrange(const int newScore) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + ArrayWrapper teams = game.GetTeams(); + if (teams.Count() < 2) { + BM_ERROR_LOG("could not get the orange team"); + return; + } + + TeamWrapper orangeTeam = teams.Get(1); + BMCHECK(orangeTeam); + + orangeTeam.SetScore(newScore); +} + + +/// Gets oranges score in the current game. +/// Oranges score +int LocalMatchSettings::GetScoreOrange() const +{ + ServerWrapper game = Outer()->GetGame(true); + BMCHECK_SILENT(game, 0); + + ArrayWrapper teams = game.GetTeams(); + if (teams.Count() < 2) { + BM_ERROR_LOG("could not get the orange team"); + return 0; + } + + TeamWrapper orangeTeam = teams.Get(1); + BMCHECK(orangeTeam, 0); + + return orangeTeam.GetScore(); +} + + +/// Sets the time remaining in the current game. +/// The new time remaining +void LocalMatchSettings::SetGameTimeRemaining(const int newGameTimeRemaining) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetGameTimeRemaining(static_cast(newGameTimeRemaining)); +} + + +/// Gets the time remaining in the current game. +/// The time remaining +int LocalMatchSettings::GetGameTimeRemaining() const +{ + ServerWrapper game = Outer()->GetGame(true); + BMCHECK_SILENT(game, 0); + + return static_cast(ceil(game.GetGameTimeRemaining())); +} + + +/// Sets if the goal delay is disabled in the current game. +/// Bool with if the goal delay should be disabled +void LocalMatchSettings::SetIsGoalDelayDisabled(const bool isGoalDelayDisabled) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetbDisableGoalDelay(isGoalDelayDisabled); +} + + +/// Gets if the goal delay is disabled in the current game. +/// Bool with if the goal delay is disabled +bool LocalMatchSettings::GetIsGoalDelayDisabled() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, false); + + return game.GetbDisableGoalDelay(); +} + + +/// Sets if there is unlimited time in the current game. +/// Bool with if there should be unlimited time +void LocalMatchSettings::SetIsUnlimitedTime(const bool isUnlimitedTime) const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK(game); + + game.SetbUnlimitedTime(isUnlimitedTime); +} + + +/// Gets if there is unlimited time in the current game. +/// bool with if there is unlimited time +bool LocalMatchSettings::GetIsUnlimitedTime() const +{ + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, false); + + return game.GetbUnlimitedTime(); +} diff --git a/source/RocketPlugin/Modules/LocalMatchSettings.h b/source/RocketPlugin/Modules/LocalMatchSettings.h new file mode 100644 index 0000000..8182fed --- /dev/null +++ b/source/RocketPlugin/Modules/LocalMatchSettings.h @@ -0,0 +1,32 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class LocalMatchSettings final : RocketPluginModule +{ + friend RocketPlugin; +public: + void SetMaxPlayers(int newNumPlayers) const; + int GetMaxPlayers() const; + void SetMaxTeamSize(int newTeamSize) const; + int GetMaxTeamSize() const; + void SetRespawnTime(int newRespawnTime) const; + int GetRespawnTime() const; + void SetScore(int team, int newScore) const; + int GetScore(int team) const; + void SetScoreBlue(int newScore) const; + int GetScoreBlue() const; + void SetScoreOrange(int newScore) const; + int GetScoreOrange() const; + void SetGameTimeRemaining(int newGameTimeRemaining) const; + int GetGameTimeRemaining() const; + void SetIsGoalDelayDisabled(bool isGoalDelayDisabled) const; + bool GetIsGoalDelayDisabled() const; + void SetIsUnlimitedTime(bool isUnlimitedTime) const; + bool GetIsUnlimitedTime() const; + +protected: + +}; diff --git a/source/RocketPlugin/Modules/PlayerMods.cpp b/source/RocketPlugin/Modules/PlayerMods.cpp new file mode 100644 index 0000000..e0d9d27 --- /dev/null +++ b/source/RocketPlugin/Modules/PlayerMods.cpp @@ -0,0 +1,123 @@ +// PlayerMods.cpp +// Player mods for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "PlayerMods.h" +#include "RocketPlugin.h" + + +/// Gets the players in the current game. +/// Bool with if the output should include bots +/// Bool with if the output should only include alive players +/// List of players +std::vector PlayerMods::GetPlayers(const bool includeBots, const bool mustBeAlive) const +{ + std::vector players; + ServerWrapper game = Outer()->GetGame(); + BMCHECK_SILENT(game, players); + + if (mustBeAlive) { + for (CarWrapper car : game.GetCars()) { + if (car.IsNull() || car.GetPRI().IsNull() || (!includeBots && car.GetPRI().GetbBot())) { + continue; + } + + players.push_back(car.GetPRI()); + } + } + else { + for (PriWrapper pri : game.GetPRIs()) { + if (pri.IsNull() || (!includeBots && pri.GetbBot())) { + continue; + } + + players.push_back(pri); + } + } + + return players; +} + + +/// Gets the player names of the players in the current game. +/// Bool with if the output should include bots +/// Bool with if the output should only include alive players +/// List of players names +std::vector PlayerMods::GetPlayersNames(const bool includeBots, const bool mustBeAlive) const +{ + return GetPlayersNames(GetPlayers(includeBots, mustBeAlive)); +} + + +/// Gets the player names of the given players. +/// List of players to get the names from +/// List of players names +std::vector PlayerMods::GetPlayersNames(const std::vector& players) const +{ + std::vector playersNames; + for (PriWrapper player : players) { + playersNames.push_back(player.GetPlayerName().ToString()); + } + + return playersNames; +} + + +/// Sets if the players is admin in the current game. +/// The to update +/// Bool with if the player should be admin +void PlayerMods::SetIsAdmin(PriWrapper player, const bool isAdmin) const +{ + BMCHECK(player); + + player.SetbMatchAdmin(isAdmin); +} + + +/// Gets if the players is admin in the current game. +/// The to check +/// Bool with if the players is admin +bool PlayerMods::GetIsAdmin(PriWrapper player) const +{ + BMCHECK_SILENT(player, false); + + return player.GetbMatchAdmin(); +} + + +/// Sets if the players is hidden in the current game. +/// The to update +/// Bool with if the player should be hidden +void PlayerMods::SetIsHidden(PriWrapper player, const bool isHidden) const +{ + BMCHECK(player); + BMCHECK(player.GetCar()); + + player.GetCar().SetHidden2(isHidden); + player.GetCar().SetbHiddenSelf(isHidden); +} + + +/// Gets if the players is hidden in the current game. +/// The to check +/// Bool with if the players are hidden +bool PlayerMods::GetIsHidden(PriWrapper player) const +{ + BMCHECK_SILENT(player, false); + BMCHECK_SILENT(player.GetCar(), false); + + return player.GetCar().GetbHidden(); +} + + +/// Demolishes the given player. +/// The to demolish +void PlayerMods::Demolish(PriWrapper player) const +{ + BMCHECK(player); + BMCHECK(player.GetCar()); + + player.GetCar().Demolish(); +} diff --git a/source/RocketPlugin/Modules/PlayerMods.h b/source/RocketPlugin/Modules/PlayerMods.h new file mode 100644 index 0000000..7839136 --- /dev/null +++ b/source/RocketPlugin/Modules/PlayerMods.h @@ -0,0 +1,22 @@ +#pragma once +#include "RocketPluginModule.h" + + +class RocketPlugin; + +class PlayerMods final : RocketPluginModule +{ + friend RocketPlugin; +public: + std::vector GetPlayers(bool includeBots = false, bool mustBeAlive = false) const; + std::vector GetPlayersNames(bool includeBots = false, bool mustBeAlive = false) const; + std::vector GetPlayersNames(const std::vector& players) const; + void SetIsAdmin(PriWrapper player, bool isAdmin) const; + bool GetIsAdmin(PriWrapper player) const; + void SetIsHidden(PriWrapper player, bool isHidden) const; + bool GetIsHidden(PriWrapper player) const; + void Demolish(PriWrapper player) const; + +protected: + +}; diff --git a/source/RocketPlugin/Modules/RocketPluginModule.cpp b/source/RocketPlugin/Modules/RocketPluginModule.cpp new file mode 100644 index 0000000..17e991d --- /dev/null +++ b/source/RocketPlugin/Modules/RocketPluginModule.cpp @@ -0,0 +1,4 @@ +#include "RocketPluginModule.h" + + +RocketPlugin* RocketPluginModule::rocketPlugin = nullptr; diff --git a/source/RocketPlugin/Modules/RocketPluginModule.h b/source/RocketPlugin/Modules/RocketPluginModule.h new file mode 100644 index 0000000..a5b7a11 --- /dev/null +++ b/source/RocketPlugin/Modules/RocketPluginModule.h @@ -0,0 +1,15 @@ +#pragma once +class RocketPlugin; + +class RocketPluginModule +{ + friend RocketPlugin; +public: + static RocketPlugin* Outer() + { + return rocketPlugin; + } + +protected: + static RocketPlugin* rocketPlugin; +}; diff --git a/source/RocketPlugin/Networking/Networking.cpp b/source/RocketPlugin/Networking/Networking.cpp index 99968ae..1b33ed5 100644 --- a/source/RocketPlugin/Networking/Networking.cpp +++ b/source/RocketPlugin/Networking/Networking.cpp @@ -1,8 +1,8 @@ // Networking.cpp -// General networking calls for the RocketPlugin plugin. +// General networking calls for Rocket Plugin. // // Author: Stanbroek -// Version: 0.6.5 05/02/21 +// Version: 0.6.8 18/09/21 #include "Networking.h" @@ -93,8 +93,7 @@ std::string Networking::GetHostStatusHint(const DestAddrType addrType, const Hos std::string Networking::IPv4ToString(const void* addr) { const unsigned char* ip = static_cast(addr); - return std::to_string(ip[0]) + "." + std::to_string(ip[1]) + "." + std::to_string(ip[2]) + "." + - std::to_string(ip[3]); + return fmt::format("{:d}.{:d}.{:d}.{:d}", ip[0], ip[1], ip[2], ip[3]); } @@ -224,8 +223,7 @@ bool Networking::IsValidDomainName(const std::string& addr) /// Size of the receive buffer /// Error code std::error_code Networking::NetworkRequest(const std::string& host, const unsigned short port, const int protocol, - const char* sendBuf, const size_t sendBufSize, char* recvBuf, - const size_t recvBufSize) + const char* sendBuf, const size_t sendBufSize, char* recvBuf, const size_t recvBufSize) { // Initialize WinSock. WSADATA wsaData; @@ -310,8 +308,9 @@ std::error_code Networking::NetworkRequest(const std::string& host, const unsign sockaddr_in addrRetDest{}; int addrRetDestSize = sizeof addrRetDest; // Receive a datagram from the receiver. - if (recvfrom(sendSocket, recvBuf, static_cast(recvBufSize), NULL, - reinterpret_cast(&addrRetDest), &addrRetDestSize) == SOCKET_ERROR) { + if (recvfrom( + sendSocket, recvBuf, static_cast(recvBufSize), NULL, reinterpret_cast(&addrRetDest), + &addrRetDestSize) == SOCKET_ERROR) { const std::error_code error = make_winsock_error_code(); closesocket(sendSocket); WSACleanup(); @@ -347,13 +346,13 @@ std::error_code Networking::GetInternalIPAddress(std::string& ipAddr) // Make a second call to GetIpAddrTable to get the actual data we want. dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0); if (dwRetVal == NO_ERROR) { - TRACE_LOG("got {} entries", pIPAddrTable->dwNumEntries); + BM_TRACE_LOG("got {:d} entries", pIPAddrTable->dwNumEntries); for (size_t i = 0; i < pIPAddrTable->dwNumEntries; i++) { if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY) { IN_ADDR inAddr; - inAddr.s_addr = static_cast(pIPAddrTable->table[i].dwAddr); + inAddr.s_addr = pIPAddrTable->table[i].dwAddr; ipAddr = IPv4ToString(&inAddr); - TRACE_LOG("found {}", quote(ipAddr)); + BM_TRACE_LOG("found {:s}", quote(ipAddr)); if (IsPrivateIPv4(ipAddr)) { break; } @@ -362,13 +361,13 @@ std::error_code Networking::GetInternalIPAddress(std::string& ipAddr) } } else { - ERROR_LOG("failed to get the ip addr table"); + BM_ERROR_LOG("failed to get the ip addr table"); } free(pIPAddrTable); pIPAddrTable = nullptr; } else { - ERROR_LOG("failed to alloc the ip addr table"); + BM_ERROR_LOG("failed to alloc the ip addr table"); } return make_win32_error_code(dwRetVal); @@ -407,8 +406,8 @@ std::error_code Networking::GetExternalIPAddress(const std::string& host, std::s std::string sendBuf = "GET / HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n"; char recvBuf[1024] = ""; - const std::error_code error = NetworkRequest(host, 80, IPPROTO_TCP, sendBuf.data(), sendBuf.size() + 1, recvBuf, - sizeof recvBuf); + const std::error_code error = NetworkRequest( + host, 80, IPPROTO_TCP, sendBuf.data(), sendBuf.size() + 1, recvBuf, sizeof recvBuf); if (error) { return error; } diff --git a/source/RocketPlugin/Networking/Networking.h b/source/RocketPlugin/Networking/Networking.h index 93efc07..a8f3962 100644 --- a/source/RocketPlugin/Networking/Networking.h +++ b/source/RocketPlugin/Networking/Networking.h @@ -39,7 +39,7 @@ namespace Networking bool IsValidDomainName(const std::string& addr); std::error_code NetworkRequest(const std::string& host, unsigned short port, int protocol, const char* sendBuf, - size_t sendBufSize, char* recvBuf = nullptr, size_t recvBufSize = 0); + size_t sendBufSize, char* recvBuf = nullptr, size_t recvBufSize = 0); std::error_code GetInternalIPAddress(std::string& ipAddr); std::error_code GetExternalIPAddress(const std::string& host, std::string* ipAddr, bool threaded = false); @@ -65,7 +65,7 @@ class UPnPClient bool DiscoveryFinished() const { return discoveryStatus == DiscoveryStatus::DISCOVERY_FINISHED; } void ForwardPort(unsigned short internalPort, unsigned short externalPort, unsigned long portLeaseDuration, - bool threaded = true); + bool threaded = true); std::string GetForwardPortStatus() const; bool ServiceForwardPortFailed() const { return addPortMappingStatus == ServiceStatus::SERVICE_ERROR; } bool ServiceForwardPortActive() const { return addPortMappingStatus == ServiceStatus::SERVICE_BUSY; } @@ -105,7 +105,7 @@ class UPnPClient void clearDevices(); std::unique_ptr discoverThread; - IUPnPService* gtoServices[2] = {nullptr, nullptr}; + IUPnPService* gtoServices[2] = { nullptr, nullptr }; IUPnPDevice* gtoDevice = nullptr; std::string deviceFriendlyName; diff --git a/source/RocketPlugin/Networking/P2PHost.cpp b/source/RocketPlugin/Networking/P2PHost.cpp index 0390f81..faae3d3 100644 --- a/source/RocketPlugin/Networking/P2PHost.cpp +++ b/source/RocketPlugin/Networking/P2PHost.cpp @@ -1,8 +1,8 @@ // P2PHost.cpp -// UDP hole punching using STUN for the RocketPlugin plugin. +// UDP hole punching using STUN for Rocket Plugin. // // Author: Stanbroek -// Version: 0.6.5 05/02/21 +// Version: 0.6.8 18/09/21 // // References: // https://en.wikipedia.org/wiki/UDP_hole_punching @@ -76,7 +76,7 @@ SOCKET GetBoundSocket(const u_short port, const std::string& localIP = "0.0.0.0" // Create a socket for sending data. const SOCKET sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sendSocket == INVALID_SOCKET) { - ERROR_LOG("failed to create a socket: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to create a socket: {:s}", quote(make_winsock_error_code().message())); return INVALID_SOCKET; } @@ -89,7 +89,7 @@ SOCKET GetBoundSocket(const u_short port, const std::string& localIP = "0.0.0.0" } addrSrc.sin_port = htons(port); if (bind(sendSocket, reinterpret_cast(&addrSrc), sizeof addrSrc) == SOCKET_ERROR) { - ERROR_LOG("failed to bind the socket: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to bind the socket: {:s}", quote(make_winsock_error_code().message())); closesocket(sendSocket); return INVALID_SOCKET; } @@ -98,7 +98,7 @@ SOCKET GetBoundSocket(const u_short port, const std::string& localIP = "0.0.0.0" BOOL bOptVal = TRUE; const int bOptLen = sizeof BOOL; if (setsockopt(sendSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&bOptVal), bOptLen) == SOCKET_ERROR) { - ERROR_LOG("failed set SO_REUSEADDR: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed set SO_REUSEADDR: {:s}", quote(make_winsock_error_code().message())); closesocket(sendSocket); return INVALID_SOCKET; } @@ -110,7 +110,7 @@ SOCKET GetBoundSocket(const u_short port, const std::string& localIP = "0.0.0.0" void FillBuffer(char* buf, const size_t bufLen, size_t& offset, void* src, const size_t srcSize) { if (offset + srcSize >= bufLen) { - ERROR_LOG("{} >= {}", offset + srcSize, bufLen); + BM_ERROR_LOG("{:d} >= {:d}", offset + srcSize, bufLen); return; } @@ -242,28 +242,28 @@ StunResponse ParseStunResponse(char* buf, int bufLen) { StunResponse resp; if (bufLen < 20) { - ERROR_LOG("got an empty stun response"); + BM_ERROR_LOG("got an empty stun response"); return resp; } resp.MsgType = static_cast(buf[0] << 8 | buf[1]); if (!IS_SUCCESS_RESP(resp.MsgType)) { - ERROR_LOG("got an unsuccessful stun response: {:#X}", resp.MsgType); + BM_ERROR_LOG("got an unsuccessful stun response: {:#X}", resp.MsgType); return resp; } resp.MsgLen = static_cast(buf[2] << 8 | buf[3]); if (resp.MsgLen < 12 || resp.MsgLen + 20 > bufLen) { - ERROR_LOG("got an invalid response message length"); + BM_ERROR_LOG("got an invalid response message length"); return resp; } if (memcpy_s(resp.Cookie, 4, buf + 4, 4) != 0) { - ERROR_LOG("got an invalid response cookie"); + BM_ERROR_LOG("got an invalid response cookie"); return resp; } if (memcpy_s(resp.TransId, 12, buf + 8, 12) != 0) { - ERROR_LOG("got an invalid response transaction id"); + BM_ERROR_LOG("got an invalid response transaction id"); return resp; } @@ -288,7 +288,7 @@ StunResponse ParseStunResponse(char* buf, int bufLen) resp.Addr.Family = static_cast(buf[base + 5]); if (resp.Addr.Family == IPV4) { resp.Addr.Port = htons(*reinterpret_cast(buf + base + 6)) ^ MAGIC_COOKIE_END; - uint32_t ip = ntohl(htonl(*reinterpret_cast(buf + base + 8)) ^ MAGIC_COOKIE); + const uint32_t ip = ntohl(htonl(*reinterpret_cast(buf + base + 8)) ^ MAGIC_COOKIE); resp.Addr.IP = Networking::IPv4ToString(&ip); break; } @@ -312,7 +312,7 @@ StunResponse ParseStunResponse(char* buf, int bufLen) /// to store the response in /// Whether the request errored int SendStunRequest(const SOCKET sock, sockaddr addrDest, const u_short attrType, const bool changeIP, - const bool changePort, StunResponse* resp) + const bool changePort, StunResponse* resp) { // Send a datagram to the receiver up to three times. int iResult = 0; @@ -323,10 +323,10 @@ int SendStunRequest(const SOCKET sock, sockaddr addrDest, const u_short attrType for (size_t i = 0; i < sendBufLen; i++) { strBuf += " " + to_hex(sendBuf[i]); } - TRACE_LOG("sending buf[{}]: {}", sendBufLen, quote(strBuf)); + BM_TRACE_LOG("sending buf[{:d}]: {:s}", sendBufLen, quote(strBuf)); for (int i = 0; i < 3; i++) { if (sendto(sock, sendBuf, static_cast(sendBufLen), 0, &addrDest, sizeof addrDest) == SOCKET_ERROR) { - ERROR_LOG("failed to send data: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to send data: {:s}", quote(make_winsock_error_code().message())); return SOCKET_ERROR; } @@ -336,17 +336,17 @@ int SendStunRequest(const SOCKET sock, sockaddr addrDest, const u_short attrType FD_SET(sock, &fds); iResult = select(NULL, &fds, nullptr, nullptr, &NETWORK_TIMEOUT); if (iResult == SOCKET_ERROR) { - ERROR_LOG("failed to get the socket status: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to get the socket status: {:s}", quote(make_winsock_error_code().message())); return SOCKET_ERROR; } if (iResult != 0) { break; } - WARNING_LOG("stun request timed out"); + BM_WARNING_LOG("stun request timed out"); } // Connection timed out. if (iResult == 0) { - ERROR_LOG("stun request timed out"); + BM_ERROR_LOG("stun request timed out"); return SOCKET_ERROR; } @@ -355,15 +355,16 @@ int SendStunRequest(const SOCKET sock, sockaddr addrDest, const u_short attrType int addrRetDestSize = sizeof addrRetDest; // Receive a datagram from the receiver. char recvBuf[1024]; - const size_t recvBufLen = sizeof recvBuf; + constexpr size_t recvBufLen = sizeof recvBuf; if (recvfrom(sock, recvBuf, static_cast(recvBufLen), NULL, &addrRetDest, &addrRetDestSize) == SOCKET_ERROR) { - ERROR_LOG("failed to receive data: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to receive data: {:s}", quote(make_winsock_error_code().message())); return SOCKET_ERROR; } *resp = ParseStunResponse(recvBuf, recvBufLen); - TRACE_LOG("recieved response: {{ MsgType: {}, MsgLen: {}, Cookie: {}, TransId: {}, Addr: {} }}", - resp->MsgType, resp->MsgLen, to_hex(resp->Cookie, 4), to_hex(resp->TransId, 12), + BM_TRACE_LOG( + "recieved response: {{ MsgType: {:X}, MsgLen: {:d}, Cookie: {:s}, TransId: {:s}, Addr: {:s} }}", resp->MsgType, + resp->MsgLen, to_hex(resp->Cookie, 4), to_hex(resp->TransId, 12), quote(resp->Addr.IP + ":" + std::to_string(resp->Addr.Port))); return 0; @@ -396,7 +397,8 @@ std::vector ParseStunServers(const std::filesystem::path& path) hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (getaddrinfo(ip.c_str(), port.c_str(), &hints, &result) != 0) { - ERROR_LOG("failed to translate {}, {}", quote(ip + ":" + port), quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to translate {:s}, {:s}", quote(ip + ":" + port), + quote(make_winsock_error_code().message())); continue; } @@ -410,7 +412,7 @@ std::vector ParseStunServers(const std::filesystem::path& path) std::string FormatAddr(sockaddr* addr) { - sockaddr_in* addrIn = reinterpret_cast(addr); + const sockaddr_in* addrIn = reinterpret_cast(addr); return Networking::IPv4ToString(&addrIn->sin_addr) + ":" + std::to_string(ntohs(addrIn->sin_port)); } @@ -436,7 +438,7 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) if (iResult != 0) { natType = NATType::NAT_ERROR; lastError = make_winsock_error_code(); - ERROR_LOG("failed to initiate winsock: {}", quote(lastError.message())); + BM_ERROR_LOG("failed to initiate winsock: {:s}", quote(lastError.message())); return; } @@ -456,7 +458,7 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) std::string stunServerAddr; for (sockaddr stunServer : ParseStunServers(STUN_SERVICES_FILE_PATH)) { stunServerAddr = FormatAddr(&stunServer); - TRACE_LOG("sending first stun request to {}", quote(stunServerAddr)); + BM_TRACE_LOG("sending first stun request to {:s}", quote(stunServerAddr)); if (SendStunRequest(sendSocket, stunServer, RESPONSE_ADDRESS, false, false, &resp1) != SOCKET_ERROR) { server = stunServer; responded = true; @@ -464,7 +466,9 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) } natType = NATType::NAT_ERROR; lastError = make_winsock_error_code(); - ERROR_LOG("failed to connect to {}: {}", quote(stunServerAddr), quote(lastError ? lastError.message() : "Connection timed out.")); + BM_ERROR_LOG( + "failed to connect to {:s}: {:s}", quote(stunServerAddr), + quote(lastError ? lastError.message() : "Connection timed out.")); } if (!responded) { natType = NATType::NAT_BLOCKED; @@ -482,7 +486,7 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) // Send second STUN request. StunResponse resp2; - TRACE_LOG("sending second stun request to {} which IP change request", quote(stunServerAddr)); + BM_TRACE_LOG("sending second stun request to {:s} which IP change request", quote(stunServerAddr)); if (SendStunRequest(sendSocket, server, CHANGE_REQUEST, true, true, &resp1) != SOCKET_ERROR) { natType = NATType::NAT_FULL_CONE; closesocket(sendSocket); @@ -492,7 +496,7 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) // Send third STUN request. StunResponse resp3; - TRACE_LOG("sending third stun request to {}", quote(stunServerAddr)); + BM_TRACE_LOG("sending third stun request to {:s}", quote(stunServerAddr)); if (SendStunRequest(sendSocket, server, RESPONSE_ADDRESS, false, false, &resp1) == SOCKET_ERROR) { natType = NATType::NAT_ERROR; lastError = make_winsock_error_code(); @@ -504,7 +508,7 @@ void P2PHost::FindNATType(unsigned short port, bool threaded) if (resp1.Addr.IP == resp3.Addr.IP && resp1.Addr.Port == resp3.Addr.Port) { // Send fourth STUN request. StunResponse resp4; - TRACE_LOG("sending fourth stun request to {} which port change request", quote(stunServerAddr)); + BM_TRACE_LOG("sending fourth stun request to {:s} which port change request", quote(stunServerAddr)); if (SendStunRequest(sendSocket, server, CHANGE_REQUEST, false, true, &resp1) == SOCKET_ERROR) { natType = NATType::NAT_RESTRICTED; } @@ -537,7 +541,7 @@ void P2PHost::PunchPort(const std::string& ip, unsigned short port, const bool t // Initialize WinSock. WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - ERROR_LOG("failed to initiate winsock: {}", quote(make_winsock_error_code().message())); + BM_ERROR_LOG("failed to initiate winsock: {:s}", quote(make_winsock_error_code().message())); return; } @@ -560,9 +564,9 @@ void P2PHost::PunchPort(const std::string& ip, unsigned short port, const bool t // Send a datagram to the receiver char sendBuf = '\0'; - const size_t sendBufLen = sizeof sendBuf; - sendto(sendSocket, &sendBuf, static_cast(sendBufLen), 0, reinterpret_cast(&addrDest), - sizeof addrDest); + constexpr size_t sendBufLen = sizeof sendBuf; + sendto( + sendSocket, &sendBuf, static_cast(sendBufLen), 0, reinterpret_cast(&addrDest), sizeof addrDest); closesocket(sendSocket); WSACleanup(); diff --git a/source/RocketPlugin/Networking/UPnPClient.cpp b/source/RocketPlugin/Networking/UPnPClient.cpp index b94e7c6..134ab9f 100644 --- a/source/RocketPlugin/Networking/UPnPClient.cpp +++ b/source/RocketPlugin/Networking/UPnPClient.cpp @@ -1,8 +1,8 @@ // UPnPClient.cpp -// UPnP port forwarding for the RocketPlugin plugin. +// UPnP port forwarding for Rocket Plugin. // // Author: Stanbroek -// Version: 0.6.5 05/02/21 +// Version: 0.6.8 18/09/21 // // References: // https://tools.ietf.org/html/rfc6970 @@ -55,8 +55,7 @@ std::string FormatHResult(const HRESULT hResult) } char errorBuf[1024]; - DWORD length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, - hResult, 0, errorBuf, sizeof errorBuf, nullptr); + DWORD length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, hResult, 0, errorBuf, sizeof errorBuf, nullptr); if (length == 0) { return "Unknown error: (" + to_hex(hResult) + ", " + to_hex(GetLastError()) + ")"; } @@ -78,7 +77,7 @@ std::string FormatHResult(const HRESULT hResult) /// Whether it should look for the port forward services /// Error code HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoServices[2], bool* gtoFound, - const bool saveServices = false) + const bool saveServices = false) { bool shouldRelease = true; IUnknown* pUnk = nullptr; @@ -98,10 +97,10 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS if (SUCCEEDED(hr)) { BSTR bstrServiceTypeIdentifier = nullptr; if (SUCCEEDED(pService->get_ServiceTypeIdentifier(&bstrServiceTypeIdentifier))) { - TRACE_LOG("found {}", quote(to_string(bstrServiceTypeIdentifier))); + BM_TRACE_LOG("found {:s}", quote(to_string(bstrServiceTypeIdentifier))); if (saveServices) { if (COMPARE(bstrServiceTypeIdentifier, UPNP_WAN_IP_CONNECTION)) { - TRACE_LOG("Found UPNP_WAN_IP_CONNECTION"); + BM_TRACE_LOG("Found UPNP_WAN_IP_CONNECTION"); if (gtoServices[0] == nullptr) { gtoServices[0] = pService; } @@ -111,7 +110,7 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS shouldRelease = false; } if (COMPARE(bstrServiceTypeIdentifier, UPNP_WAN_PPP_CONNECTION)) { - TRACE_LOG("Found UPNP_WAN_PPP_CONNECTION"); + BM_TRACE_LOG("Found UPNP_WAN_PPP_CONNECTION"); if (gtoServices[0] == nullptr) { gtoServices[0] = pService; } @@ -123,7 +122,7 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS } else { if (COMPARE(bstrServiceTypeIdentifier, UPNP_WAN_COMMON_INTERFACE_CONFIG)) { - TRACE_LOG("Found UPNP_WAN_COMMON_INTERFACE_CONFIG"); + BM_TRACE_LOG("Found UPNP_WAN_COMMON_INTERFACE_CONFIG"); *gtoFound = true; } } @@ -131,11 +130,11 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS SysFreeString(bstrServiceTypeIdentifier); } else { - ERROR_LOG("failed to get the service type identifier: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get the service type identifier: {:s}", quote(FormatHResult(hr))); } } else { - ERROR_LOG("failed to query the UPnP service: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to query the UPnP service: {:s}", quote(FormatHResult(hr))); } VariantClear(&varCurService); if (shouldRelease) { @@ -146,12 +145,12 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS } else { - ERROR_LOG("failed to query the enum variant: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to query the enum variant: {:s}", quote(FormatHResult(hr))); } pUnk->Release(); } else { - ERROR_LOG("failed to receives a reference to the enumerator interface: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to receives a reference to the enumerator interface: {:s}", quote(FormatHResult(hr))); } return hr; @@ -166,10 +165,10 @@ HRESULT TraverseServiceCollection(IUPnPServices* pusServices, IUPnPService* gtoS /// Whether it should look for the port forward services /// Error code HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice, IUPnPService* gtoServices[2], - unsigned int depth = 0, bool saveDevice = false) + unsigned int depth = 0, bool saveDevice = false) { if (depth >= MAX_DEVICE_CHILD_DEPTH) { - WARNING_LOG("reached max device child depth"); + BM_WARNING_LOG("reached max device child depth"); return S_OK; } @@ -200,7 +199,7 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice #ifdef DEBUG BSTR bstrFriendlyName = nullptr; if (SUCCEEDED(pParentDevice->get_FriendlyName(&bstrFriendlyName))) { - TRACE_LOG("found {}", quote(to_string(bstrFriendlyName))); + BM_TRACE_LOG("found {:s}", quote(to_string(bstrFriendlyName))); SysFreeString(bstrFriendlyName); } #endif @@ -210,7 +209,8 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice TraverseServiceCollection(pusParentsServices, gtoServices, >oFound); } else { - ERROR_LOG("failed to get the parent device services: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG( + "failed to get the parent device services: {:s}", quote(FormatHResult(hr))); } if (gtoFound) { saveDevice = true; @@ -219,18 +219,18 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice pParentDevice->Release(); } else { - ERROR_LOG("failed to get the parent device: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get the parent device: {:s}", quote(FormatHResult(hr))); } } } else { - ERROR_LOG("failed to get if device is a root device: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get if device is a root device: {:s}", quote(FormatHResult(hr))); } } #ifdef DEBUG BSTR bstrFriendlyName = nullptr; if (SUCCEEDED(pDevice->get_FriendlyName(&bstrFriendlyName))) { - TRACE_LOG("found {}", quote(to_string(bstrFriendlyName))); + BM_TRACE_LOG("found {:s}", quote(to_string(bstrFriendlyName))); SysFreeString(bstrFriendlyName); } #endif @@ -240,7 +240,7 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice hr = TraverseServiceCollection(pusServices, gtoServices, >oFound, saveDevice); } else { - ERROR_LOG("failed to get the services: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get the services: {:s}", quote(FormatHResult(hr))); } if (depth != 0 || gtoFound) { @@ -251,21 +251,21 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice IUPnPDevices* pDevicesChildren = nullptr; hr = pDevice->get_Children(&pDevicesChildren); if (SUCCEEDED(hr)) { - hr = TraverseDeviceCollection(pDevicesChildren, gtoDevice, gtoServices, ++depth, - gtoFound); + hr = TraverseDeviceCollection( + pDevicesChildren, gtoDevice, gtoServices, ++depth, gtoFound); } else { - ERROR_LOG("failed to get the children: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get the children: {:s}", quote(FormatHResult(hr))); } } } else { - ERROR_LOG("failed to get if device has any children: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get if device has any children: {:s}", quote(FormatHResult(hr))); } } } else { - ERROR_LOG("failed to query the UPnP device: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to query the UPnP device: {:s}", quote(FormatHResult(hr))); } VariantClear(&varCurDevice); if (!saveDevice) { @@ -279,12 +279,12 @@ HRESULT TraverseDeviceCollection(IUPnPDevices* pDevices, IUPnPDevice** gtoDevice pEnumVar->Release(); } else { - ERROR_LOG("failed to query the enum variant: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to query the enum variant: {:s}", quote(FormatHResult(hr))); } pUnk->Release(); } else { - ERROR_LOG("failed to receives a reference to the enumerator interface: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to receives a reference to the enumerator interface: {:s}", quote(FormatHResult(hr))); } return hr; @@ -298,10 +298,11 @@ void UPnPClient::discoverDevices(const std::wstring& typeUri) BSTR typeUriBStr = SysAllocString(typeUri.c_str()); IUPnPDevices* pDevices = nullptr; IUPnPDeviceFinder* pUPnPDeviceFinder = nullptr; - HRESULT hResult = CoCreateInstance(CLSID_UPnPDeviceFinder, nullptr, CLSCTX_INPROC_SERVER, - IID_IUPnPDeviceFinder, reinterpret_cast(&pUPnPDeviceFinder)); + HRESULT hResult = CoCreateInstance( + CLSID_UPnPDeviceFinder, nullptr, CLSCTX_INPROC_SERVER, IID_IUPnPDeviceFinder, + reinterpret_cast(&pUPnPDeviceFinder)); if (FAILED(hResult)) { - ERROR_LOG("failed to create a UPnP device finder: {}", quote(FormatHResult(hResult))); + BM_ERROR_LOG("failed to create a UPnP device finder: {:s}", quote(FormatHResult(hResult))); return; } @@ -313,11 +314,11 @@ void UPnPClient::discoverDevices(const std::wstring& typeUri) hResult = TraverseDeviceCollection(pDevices, >oDevice, gtoServices); } else { - ERROR_LOG("failed to get the device count: {}", quote(FormatHResult(hResult))); + BM_ERROR_LOG("failed to get the device count: {:s}", quote(FormatHResult(hResult))); } } else { - ERROR_LOG("failed to find any {} devices: {}", quote(to_string(typeUri)), quote(FormatHResult(hResult))); + BM_ERROR_LOG("failed to find any {:s} devices: {:s}", quote(to_string(typeUri)), quote(FormatHResult(hResult))); } pUPnPDeviceFinder->Release(); SysFreeString(typeUriBStr); @@ -340,17 +341,16 @@ void UPnPClient::discoverDevices(const std::wstring& typeUri) /// Port mapping lease duration in seconds /// Error code HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& returnStatus, - USHORT inPortMappingNumberOfEntries, BSTR* outRemoteHost, USHORT* outExternalPort, - BSTR* outPortMappingProtocol, USHORT* outInternalPort, BSTR* outInternalClient, - VARIANT_BOOL* outPortMappingEnabled, BSTR* outPortMappingDescription, - ULONG* outPortMappingLeaseDuration) + USHORT inPortMappingNumberOfEntries, BSTR* outRemoteHost, USHORT* outExternalPort, BSTR* outPortMappingProtocol, + USHORT* outInternalPort, BSTR* outInternalClient, VARIANT_BOOL* outPortMappingEnabled, + BSTR* outPortMappingDescription, ULONG* outPortMappingLeaseDuration) { HRESULT hr = S_OK; BSTR bstrActionName = SysAllocString(L"GetGenericPortMappingEntry"); SAFEARRAYBOUND inArgsBound[1]; SAFEARRAY* psaInArgs = nullptr; SAFEARRAY* psaOutArgs = nullptr; - LONG rgIndices[1] = {0}; + LONG rgIndices[1] = { 0 }; VARIANT varInArgs; VARIANT varOutArgs; VARIANT varRet; @@ -388,10 +388,10 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (varRet.vt == VT_BSTR) { returnStatus = to_string(varRet.bstrVal); - TRACE_LOG("returned {}", quote(returnStatus)); + BM_TRACE_LOG("returned {:s}", quote(returnStatus)); } else if (varRet.vt != VT_EMPTY) { - TRACE_LOG("returned {:#X}", varRet.vt); + BM_TRACE_LOG("returned {:#X}", varRet.vt); } } @@ -401,7 +401,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return psaOutArgs = V_ARRAY(&varOutArgs); rgIndices[0] = 0; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_BSTR) { *outRemoteHost = varTemp.bstrVal; @@ -409,7 +409,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 1; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_UI2) { *outExternalPort = varTemp.uiVal; } @@ -417,7 +417,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 2; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_BSTR) { *outPortMappingProtocol = varTemp.bstrVal; } @@ -425,7 +425,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 3; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_UI2) { *outInternalPort = varTemp.uiVal; } @@ -433,7 +433,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 4; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_BSTR) { *outInternalClient = varTemp.bstrVal; } @@ -441,7 +441,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 5; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_BOOL) { *outPortMappingEnabled = varTemp.boolVal; } @@ -449,7 +449,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 6; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_BSTR) { *outPortMappingDescription = varTemp.bstrVal; } @@ -457,7 +457,7 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return if (SUCCEEDED(hr)) { rgIndices[0] = 7; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr) && varTemp.vt == VT_UI4) { *outPortMappingLeaseDuration = varTemp.ulVal; } @@ -498,16 +498,15 @@ HRESULT GetGenericPortMappingEntry(IUPnPService* gtoService, std::string& return /// Port mapping lease duration in seconds /// Error code HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& returnStatus, BSTR inRemoteHost, - USHORT inExternalPort, BSTR inPortMappingProtocol, USHORT* outInternalPort, - BSTR* outInternalClient, VARIANT_BOOL* outPortMappingEnabled, - BSTR* outPortMappingDescription, ULONG* outPortMappingLeaseDuration) + USHORT inExternalPort, BSTR inPortMappingProtocol, USHORT* outInternalPort, BSTR* outInternalClient, + VARIANT_BOOL* outPortMappingEnabled, BSTR* outPortMappingDescription, ULONG* outPortMappingLeaseDuration) { HRESULT hr = S_OK; BSTR bstrActionName = SysAllocString(L"GetSpecificPortMappingEntry"); SAFEARRAYBOUND inArgsBound[1]; SAFEARRAY* psaInArgs = nullptr; SAFEARRAY* psaOutArgs = nullptr; - LONG rgIndices[1] = {0}; + LONG rgIndices[1] = { 0 }; VARIANT varInArgs; VARIANT varOutArgs; VARIANT varRet; @@ -557,10 +556,10 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur if (varRet.vt == VT_BSTR) { returnStatus = to_string(varRet.bstrVal); - TRACE_LOG("returned {}", quote(returnStatus)); + BM_TRACE_LOG("returned {:s}", quote(returnStatus)); } else if (varRet.vt != VT_EMPTY) { - TRACE_LOG("returned {:#X}", varRet.vt); + BM_TRACE_LOG("returned {:#X}", varRet.vt); } } @@ -570,14 +569,14 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur psaOutArgs = V_ARRAY(&varOutArgs); rgIndices[0] = 0; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outInternalPort = varTemp.uiVal; } if (SUCCEEDED(hr)) { rgIndices[0] = 1; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outInternalClient = varTemp.bstrVal; } @@ -585,7 +584,7 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur if (SUCCEEDED(hr)) { rgIndices[0] = 2; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outPortMappingEnabled = varTemp.boolVal; } @@ -593,7 +592,7 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur if (SUCCEEDED(hr)) { rgIndices[0] = 3; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outPortMappingDescription = varTemp.bstrVal; } @@ -601,7 +600,7 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur if (SUCCEEDED(hr)) { rgIndices[0] = 4; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outPortMappingLeaseDuration = varTemp.ulVal; } @@ -644,16 +643,15 @@ HRESULT GetSpecificPortMappingEntry(IUPnPService* gtoService, std::string& retur /// Port mapping lease duration in seconds /// Error code HRESULT AddPortMapping(IUPnPService* gtoService, std::string& returnStatus, BSTR inRemoteHost, USHORT inExternalPort, - BSTR inPortMappingProtocol, USHORT inInternalPort, BSTR inInternalClient, - VARIANT_BOOL inPortMappingEnabled, BSTR inPortMappingDescription, - ULONG inPortMappingLeaseDuration) + BSTR inPortMappingProtocol, USHORT inInternalPort, BSTR inInternalClient, VARIANT_BOOL inPortMappingEnabled, + BSTR inPortMappingDescription, ULONG inPortMappingLeaseDuration) { - HRESULT hr = S_OK; - BSTR bstrActionName = SysAllocString(L"AddPortMapping"); + HRESULT hr = S_OK; + BSTR bstrActionName = SysAllocString(L"AddPortMapping"); SAFEARRAYBOUND inArgsBound[1]; SAFEARRAY* psaInArgs = nullptr; SAFEARRAY* psaOutArgs = nullptr; - LONG rgIndices[1] = {0}; + LONG rgIndices[1] = { 0 }; VARIANT varInArgs; VARIANT varOutArgs; VARIANT varRet; @@ -733,10 +731,10 @@ HRESULT AddPortMapping(IUPnPService* gtoService, std::string& returnStatus, BSTR if (varRet.vt == VT_BSTR) { returnStatus = to_string(varRet.bstrVal); - TRACE_LOG("returned {}", quote(returnStatus)); + BM_TRACE_LOG("returned {:s}", quote(returnStatus)); } else if (varRet.vt != VT_EMPTY) { - TRACE_LOG("returned {:#X}", varRet.vt); + BM_TRACE_LOG("returned {:#X}", varRet.vt); } } @@ -782,14 +780,14 @@ HRESULT AddPortMapping(IUPnPService* gtoService, std::string& returnStatus, BSTR /// Port mapping protocol /// Error code HRESULT DeletePortMapping(IUPnPService* gtoService, std::string& returnStatus, BSTR inRemoteHost, USHORT inExternalPort, - BSTR inPortMappingProtocol) + BSTR inPortMappingProtocol) { - HRESULT hr = S_OK; - BSTR bstrActionName = SysAllocString(L"DeletePortMapping"); + HRESULT hr = S_OK; + BSTR bstrActionName = SysAllocString(L"DeletePortMapping"); SAFEARRAYBOUND inArgsBound[1]; SAFEARRAY* psaInArgs = nullptr; SAFEARRAY* psaOutArgs = nullptr; - LONG rgIndices[1] = {0}; + LONG rgIndices[1] = { 0 }; VARIANT varInArgs; VARIANT varOutArgs; VARIANT varRet; @@ -839,10 +837,10 @@ HRESULT DeletePortMapping(IUPnPService* gtoService, std::string& returnStatus, B if (varRet.vt == VT_BSTR) { returnStatus = to_string(varRet.bstrVal); - TRACE_LOG("returned {}", quote(returnStatus)); + BM_TRACE_LOG("returned {:s}", quote(returnStatus)); } else if (varRet.vt != VT_EMPTY) { - TRACE_LOG("returned {:#X}", varRet.vt); + BM_TRACE_LOG("returned {:#X}", varRet.vt); } } @@ -882,12 +880,12 @@ HRESULT DeletePortMapping(IUPnPService* gtoService, std::string& returnStatus, B /// Error code HRESULT GetExternalIPAddress(IUPnPService* gtoService, std::string& returnStatus, BSTR* outExternalIPAddress) { - HRESULT hr = S_OK; - BSTR bstrActionName = SysAllocString(L"GetExternalIPAddress"); + HRESULT hr = S_OK; + BSTR bstrActionName = SysAllocString(L"GetExternalIPAddress"); SAFEARRAYBOUND inArgsBound[1]; SAFEARRAY* psaInArgs = nullptr; SAFEARRAY* psaOutArgs = nullptr; - LONG rgIndices[1] = {0}; + LONG rgIndices[1] = { 0 }; VARIANT varInArgs; VARIANT varOutArgs; VARIANT varRet; @@ -918,10 +916,10 @@ HRESULT GetExternalIPAddress(IUPnPService* gtoService, std::string& returnStatus if (varRet.vt == VT_BSTR) { returnStatus = to_string(varRet.bstrVal); - TRACE_LOG("returned {}", quote(returnStatus)); + BM_TRACE_LOG("returned {:s}", quote(returnStatus)); } else if (varRet.vt != VT_EMPTY) { - TRACE_LOG("returned {:#X}", varRet.vt); + BM_TRACE_LOG("returned {:#X}", varRet.vt); } } @@ -931,7 +929,7 @@ HRESULT GetExternalIPAddress(IUPnPService* gtoService, std::string& returnStatus psaOutArgs = V_ARRAY(&varOutArgs); rgIndices[0] = 0; - hr = SafeArrayGetElement(psaOutArgs, rgIndices, static_cast(&varTemp)); + hr = SafeArrayGetElement(psaOutArgs, rgIndices, &varTemp); if (SUCCEEDED(hr)) { *outExternalIPAddress = varTemp.bstrVal; } @@ -962,7 +960,7 @@ HRESULT GetExternalIPAddress(IUPnPService* gtoService, std::string& returnStatus /// Time in seconds for the port to be opened /// Whether the action should be executed on another thread void UPnPClient::ForwardPort(const unsigned short internalPort, const unsigned short externalPort, - const unsigned long portLeaseDuration, const bool threaded) + const unsigned long portLeaseDuration, const bool threaded) { if (threaded) { discoverThread->addJob([=]() { @@ -982,19 +980,19 @@ void UPnPClient::ForwardPort(const unsigned short internalPort, const unsigned s VARIANT_BOOL inPortMappingEnabled = VARIANT_TRUE; BSTR inPortMappingDescription = SysAllocString(L"RL port forward for local play"); ULONG inPortMappingLeaseDuration = portLeaseDuration; - HRESULT hResult = AddPortMapping(gtoServices[0], addPortMappingReturnStatus, inRemoteHost, inExternalPort, - inPortMappingProtocol, inInternalPort, inInternalClient, inPortMappingEnabled, - inPortMappingDescription, inPortMappingLeaseDuration); + HRESULT hResult = AddPortMapping( + gtoServices[0], addPortMappingReturnStatus, inRemoteHost, inExternalPort, inPortMappingProtocol, inInternalPort, + inInternalClient, inPortMappingEnabled, inPortMappingDescription, inPortMappingLeaseDuration); if (SUCCEEDED(hResult)) { USHORT outInternalPort = 0; BSTR outInternalClient = nullptr; VARIANT_BOOL outPortMappingEnabled = VARIANT_FALSE; BSTR outPortMappingDescription = nullptr; ULONG outPortMappingLeaseDuration = 0; - hResult = GetSpecificPortMappingEntry(gtoServices[0], deletePortMappingReturnStatus, inRemoteHost, - inExternalPort, inPortMappingProtocol, &outInternalPort, - &outInternalClient, &outPortMappingEnabled, &outPortMappingDescription, - &outPortMappingLeaseDuration); + hResult = GetSpecificPortMappingEntry( + gtoServices[0], deletePortMappingReturnStatus, inRemoteHost, inExternalPort, inPortMappingProtocol, + &outInternalPort, &outInternalClient, &outPortMappingEnabled, &outPortMappingDescription, + &outPortMappingLeaseDuration); if (SUCCEEDED(hResult)) { addPortMappingReturnStatus = std::to_string(externalPort) + " for " + internalIPAddress; addPortMappingStatus = ServiceStatus::SERVICE_UPDATED_PORT_MAPPING; @@ -1040,8 +1038,8 @@ void UPnPClient::ClosePort(const unsigned short externalPort, const bool threade BSTR inRemoteHost = SysAllocString(L""); USHORT inExternalPort = externalPort; BSTR inPortMappingProtocol = SysAllocString(L"UDP"); - HRESULT hResult = DeletePortMapping(gtoServices[0], deletePortMappingReturnStatus, inRemoteHost, inExternalPort, - inPortMappingProtocol); + HRESULT hResult = DeletePortMapping( + gtoServices[0], deletePortMappingReturnStatus, inRemoteHost, inExternalPort, inPortMappingProtocol); if (SUCCEEDED(hResult)) { deletePortMappingReturnStatus = std::to_string(externalPort) + " for " + internalIPAddress; deletePortMappingStatus = ServiceStatus::SERVICE_UPDATED_PORT_MAPPING; @@ -1082,15 +1080,15 @@ void UPnPClient::findOpenPorts(const bool threaded) VARIANT_BOOL outPortMappingEnabled = VARIANT_FALSE; BSTR outPortMappingDescription = nullptr; ULONG outPortMappingLeaseDuration = 0; - hResult = GetGenericPortMappingEntry(gtoServices[0], deletePortMappingReturnStatus, - inPortMappingNumberOfEntries, &outRemoteHost, &outExternalPort, - &outPortMappingProtocol, &outInternalPort, &outInternalClient, - &outPortMappingEnabled, &outPortMappingDescription, - &outPortMappingLeaseDuration); + hResult = GetGenericPortMappingEntry( + gtoServices[0], deletePortMappingReturnStatus, inPortMappingNumberOfEntries, &outRemoteHost, + &outExternalPort, &outPortMappingProtocol, &outInternalPort, &outInternalClient, &outPortMappingEnabled, + &outPortMappingDescription, &outPortMappingLeaseDuration); if (SUCCEEDED(hResult)) { - TRACE_LOG("{}: {} {} {} {} {} {} {} {}", inPortMappingNumberOfEntries, to_string(outRemoteHost), - outExternalPort, to_string(outPortMappingProtocol), outInternalPort, to_string(outInternalClient), - outPortMappingEnabled, to_string(outPortMappingDescription), outPortMappingLeaseDuration); + BM_TRACE_LOG( + "{:d}: {:s} {:d} {:s} {:d} {:s} {} {:s} {:d}", inPortMappingNumberOfEntries, to_string(outRemoteHost), outExternalPort, + to_string(outPortMappingProtocol), outInternalPort, to_string(outInternalClient), outPortMappingEnabled == VARIANT_TRUE, + to_string(outPortMappingDescription), outPortMappingLeaseDuration); inPortMappingNumberOfEntries++; if (to_string(outInternalClient) == internalIPAddress) { openPorts.push_back(outExternalPort); @@ -1142,13 +1140,11 @@ void UPnPClient::FindDevices(const bool threaded) return; } - std::vector const deviceList = { + const std::vector deviceList = { //L"urn:schemas-upnp-org:device:InternetGatewayDevice:2", //L"urn:schemas-upnp-org:service:WANIPConnection:2", - L"urn:schemas-upnp-org:device:InternetGatewayDevice:1", - L"urn:schemas-upnp-org:service:WANIPConnection:1", - L"urn:schemas-upnp-org:service:WANPPPConnection:1", - L"upnp:rootdevice" + L"urn:schemas-upnp-org:device:InternetGatewayDevice:1", L"urn:schemas-upnp-org:service:WANIPConnection:1", + L"urn:schemas-upnp-org:service:WANPPPConnection:1", L"upnp:rootdevice" //L"ssdp:all" }; @@ -1175,7 +1171,7 @@ void UPnPClient::FindDevices(const bool threaded) } else { // Swap WANPPPConnection and WANIPConnection, so GTOServices[0] always works. - TRACE_LOG("Swapping WANPPPConnection and WANIPConnection"); + BM_TRACE_LOG("Swapping WANPPPConnection and WANIPConnection"); IUPnPService* tmp = gtoServices[0]; gtoServices[0] = gtoServices[1]; gtoServices[1] = tmp; @@ -1221,7 +1217,7 @@ std::string UPnPClient::getDeviceFriendlyName(IUPnPDevice* pDevice) } else { deviceFriendlyName = "Unknown Name\n" + quote(FormatHResult(hr)); - ERROR_LOG("failed to get the friendly name: {}", quote(FormatHResult(hr))); + BM_ERROR_LOG("failed to get the friendly name: {:s}", quote(FormatHResult(hr))); } } @@ -1289,7 +1285,8 @@ std::string UPnPClient::GetClosePortStatus() const return ""; case ServiceStatus::SERVICE_ERROR: if (FAILED(deletePortMappingResult.value())) { - return "Error: " + deletePortMappingReturnStatus + "\n" + FormatHResult(deletePortMappingResult.value()); + return "Error: " + deletePortMappingReturnStatus + "\n" + + FormatHResult(deletePortMappingResult.value()); } if (!deletePortMappingReturnStatus.empty()) { return "Error: " + deletePortMappingReturnStatus; diff --git a/source/RocketPlugin/RLConstants.inc b/source/RocketPlugin/RLConstants.inc index a606718..86c6c45 100644 --- a/source/RocketPlugin/RLConstants.inc +++ b/source/RocketPlugin/RLConstants.inc @@ -6,7 +6,7 @@ namespace RLConstants const RocketPlugin::GameSetting GAME_MODES { "GameModes", "Game Modes", 0, { "Soccar", "Hoops", "Snow Day", "Rumble", "", "Dropshot", "Heatseeker", "Gridiron" }, - { "TAGame.GameInfo_Soccar_TA", "TAGame.GameInfo_Basketball_TA", "TAGame.GameInfo_Hockey_TA", "TAGame.GameInfo_Items_TA", "None", "TAGame.GameInfo_Breakout_TA", "TAGame.GameInfo_GodBall_TA", "TAGame.GameInfo_Football_TA" } + { "TAGame.GameInfo_Soccar_TA", "TAGame.GameInfo_Basketball_TA", "TAGame.Gameinfo_Hockey_TA", "TAGame.GameInfo_Items_TA", "None", "TAGame.GameInfo_Breakout_TA", "TAGame.GameInfo_GodBall_TA", "TAGame.GameInfo_Football_TA" } }; const std::map MAPS { @@ -26,8 +26,9 @@ namespace RLConstants { "Labs_Cosmic_V4_P", "Cosmic (New)" }, { "Labs_DoubleGoal_P", "Double Goal (Old)" }, { "Labs_DoubleGoal_V2_P", "Double Goal (New)" }, - { "Labs_Galleon_Mast_P", "Galleon Retro" }, + { "Labs_Galleon_Mast_P", "Galleon Retro" }, { "Labs_Galleon_P", "Galleon" }, + { "Labs_Holyfield_P", "Loophole" }, { "Labs_Octagon_02_P", "Octagon (New)" }, { "Labs_Octagon_P", "Octagon (Old)" }, { "Labs_Underpass_P", "Underpass" }, @@ -61,6 +62,7 @@ namespace RLConstants { "eurostadium_snownight_p", "Mannfield (Snowy)" }, { "farm_p", "Farmstead" }, { "music_p", "Neon Fields" }, + { "outlaw_p", "Deadeye Canyon" }, { "stadium_day_p", "DFH Stadium (Day)" }, { "throwbackhockey_p", "Throwback Stadium (Snowy)" }, { "throwbackstadium_P", "Throwback Stadium" }, @@ -75,7 +77,7 @@ namespace RLConstants }; #define IM_VEC3(R, G, B) ImVec4(R, G, B, 1) - const int CUSTOM_HUE_COUNT = 15; + constexpr int CUSTOM_HUE_COUNT = 15; const std::vector CUSTOM_COLORS { IM_VEC3(0.900000f, 0.900000f, 0.900000f), IM_VEC3(1.000000f, 0.500000f, 0.500000f), IM_VEC3(1.000000f, 0.625000f, 0.500000f), IM_VEC3(1.000000f, 0.812500f, 0.500000f), IM_VEC3(0.937500f, 1.000000f, 0.500000f), IM_VEC3(0.687500f, 1.000000f, 0.500000f), IM_VEC3(0.500000f, 1.000000f, 0.500000f), IM_VEC3(0.500000f, 1.000000f, 0.700000f), IM_VEC3(0.500000f, 0.916667f, 1.000000f), IM_VEC3(0.500000f, 0.691666f, 1.000000f), IM_VEC3(0.500000f, 0.533333f, 1.000000f), IM_VEC3(0.683334f, 0.500000f, 1.000000f), IM_VEC3(0.900000f, 0.500000f, 1.000000f), IM_VEC3(1.000000f, 0.500000f, 0.816666f), IM_VEC3(1.000000f, 0.500000f, 0.583333f), IM_VEC3(0.750000f, 0.750000f, 0.750000f), IM_VEC3(1.000000f, 0.350000f, 0.350000f), IM_VEC3(1.000000f, 0.512500f, 0.350000f), IM_VEC3(1.000000f, 0.756250f, 0.350000f), IM_VEC3(0.918750f, 1.000000f, 0.350000f), IM_VEC3(0.593750f, 1.000000f, 0.350000f), IM_VEC3(0.350000f, 1.000000f, 0.350000f), IM_VEC3(0.350000f, 1.000000f, 0.610000f), IM_VEC3(0.350000f, 0.891666f, 1.000000f), IM_VEC3(0.350000f, 0.599166f, 1.000000f), IM_VEC3(0.350000f, 0.393333f, 1.000000f), IM_VEC3(0.588334f, 0.350000f, 1.000000f), IM_VEC3(0.870000f, 0.350000f, 1.000000f), IM_VEC3(1.000000f, 0.350000f, 0.761666f), IM_VEC3(1.000000f, 0.350000f, 0.458334f), @@ -85,7 +87,7 @@ namespace RLConstants IM_VEC3(0.150000f, 0.150000f, 0.150000f), IM_VEC3(0.400000f, 0.000000f, 0.000000f), IM_VEC3(0.400000f, 0.100000f, 0.000000f), IM_VEC3(0.400000f, 0.250000f, 0.000000f), IM_VEC3(0.350000f, 0.400000f, 0.000000f), IM_VEC3(0.150000f, 0.400000f, 0.000000f), IM_VEC3(0.000000f, 0.400000f, 0.000000f), IM_VEC3(0.000000f, 0.400000f, 0.160000f), IM_VEC3(0.000000f, 0.333333f, 0.400000f), IM_VEC3(0.000000f, 0.153333f, 0.400000f), IM_VEC3(0.000000f, 0.026667f, 0.400000f), IM_VEC3(0.146667f, 0.000000f, 0.400000f), IM_VEC3(0.320000f, 0.000000f, 0.400000f), IM_VEC3(0.400000f, 0.000000f, 0.253333f), IM_VEC3(0.400000f, 0.000000f, 0.066667f), IM_VEC3(0.020000f, 0.020000f, 0.020000f), IM_VEC3(0.200000f, 0.000000f, 0.000000f), IM_VEC3(0.200000f, 0.050000f, 0.000000f), IM_VEC3(0.200000f, 0.125000f, 0.000000f), IM_VEC3(0.175000f, 0.200000f, 0.000000f), IM_VEC3(0.075000f, 0.200000f, 0.000000f), IM_VEC3(0.000000f, 0.200000f, 0.000000f), IM_VEC3(0.000000f, 0.200000f, 0.080000f), IM_VEC3(0.000000f, 0.166667f, 0.200000f), IM_VEC3(0.000000f, 0.076667f, 0.200000f), IM_VEC3(0.000000f, 0.013333f, 0.200000f), IM_VEC3(0.073333f, 0.000000f, 0.200000f), IM_VEC3(0.160000f, 0.000000f, 0.200000f), IM_VEC3(0.200000f, 0.000000f, 0.126667f), IM_VEC3(0.200000f, 0.000000f, 0.033333f) }; - const int CLUB_HUE_COUNT = 15; + constexpr int CLUB_HUE_COUNT = 15; const std::vector CLUB_COLORS { IM_VEC3(0.900000f, 0.900000f, 0.900000f), IM_VEC3(1.000000f, 0.500000f, 0.500000f), IM_VEC3(1.000000f, 0.625000f, 0.500000f), IM_VEC3(1.000000f, 0.812500f, 0.500000f), IM_VEC3(0.937500f, 1.000000f, 0.500000f), IM_VEC3(0.687500f, 1.000000f, 0.500000f), IM_VEC3(0.500000f, 1.000000f, 0.500000f), IM_VEC3(0.500000f, 1.000000f, 0.700000f), IM_VEC3(0.500000f, 0.916667f, 1.000000f), IM_VEC3(0.500000f, 0.691666f, 1.000000f), IM_VEC3(0.500000f, 0.533333f, 1.000000f), IM_VEC3(0.683334f, 0.500000f, 1.000000f), IM_VEC3(0.900000f, 0.500000f, 1.000000f), IM_VEC3(1.000000f, 0.500000f, 0.816666f), IM_VEC3(1.000000f, 0.500000f, 0.583333f), IM_VEC3(0.750000f, 0.750000f, 0.750000f), IM_VEC3(1.000000f, 0.350000f, 0.350000f), IM_VEC3(1.000000f, 0.512500f, 0.350000f), IM_VEC3(1.000000f, 0.756250f, 0.350000f), IM_VEC3(0.918750f, 1.000000f, 0.350000f), IM_VEC3(0.593750f, 1.000000f, 0.350000f), IM_VEC3(0.350000f, 1.000000f, 0.350000f), IM_VEC3(0.350000f, 1.000000f, 0.610000f), IM_VEC3(0.350000f, 0.891666f, 1.000000f), IM_VEC3(0.350000f, 0.599166f, 1.000000f), IM_VEC3(0.350000f, 0.393333f, 1.000000f), IM_VEC3(0.588334f, 0.350000f, 1.000000f), IM_VEC3(0.870000f, 0.350000f, 1.000000f), IM_VEC3(1.000000f, 0.350000f, 0.761666f), IM_VEC3(1.000000f, 0.350000f, 0.458334f), diff --git a/source/RocketPlugin/Config.cpp b/source/RocketPlugin/RPConfig.cpp similarity index 71% rename from source/RocketPlugin/Config.cpp rename to source/RocketPlugin/RPConfig.cpp index 1eb2f84..47057d1 100644 --- a/source/RocketPlugin/Config.cpp +++ b/source/RocketPlugin/RPConfig.cpp @@ -1,4 +1,10 @@ -#include "Config.h" +// RPConfig.cpp +// Online config for Rocket Plugin. +// +// Author: Stanbroek +// Version: 0.6.8 18/09/21 +// BMSDK version: 95 +#include "RPConfig.h" #include "GameModes/CrazyRumble.h" @@ -6,7 +12,7 @@ constexpr int HttpStatusCodeSuccessOk = 200; /// Waits until all request are finished. -Config::~Config() +BaseConfig::~BaseConfig() { for (const auto& [url, request] : activeRequests) { if (request.valid()) { @@ -20,38 +26,40 @@ Config::~Config() /// Url to send a http request to /// Timeout for the http request, HttpWrapper has a timeout of 3s /// Future with the http request response -std::shared_future> Config::Request(const std::string& url, std::chrono::seconds timeout) +std::shared_future> BaseConfig::Request(const std::string& url, + std::chrono::seconds timeout) { - TRACE_LOG(quote(url)); + BM_TRACE_LOG(quote(url)); if (const auto& it = activeRequests.find(url); it != activeRequests.end()) { return it->second; } - std::shared_future> future = std::async([this, url, timeout]() { - std::mutex mutex; - std::condition_variable condVar; - std::pair response; - - CurlRequest request; - request.url = url; - HttpWrapper::SendCurlJsonRequest(request, - [this, &response, &condVar](const int httpStatusCode, const std::string& data) { - TRACE_LOG("{}", httpStatusCode); - response = std::pair(httpStatusCode == HttpStatusCodeSuccessOk, data); - condVar.notify_all(); - }); - - // Because we do not own the object that holds our callback, so we have to wait until it is finished. - // But if the request errors, we will never hear about it, so we also set a timeout and cross our fingers. - std::unique_lock lock(mutex); - const std::cv_status status = condVar.wait_for(lock, timeout); - if (status == std::cv_status::timeout) { - ERROR_LOG("request to {} timed out", quote(url)); - return std::pair(false, std::string()); - } + std::shared_future> future = save_promise>("", + [this, url, timeout]() { + std::mutex mutex; + std::condition_variable condVar; + std::pair response; + + CurlRequest request; + request.url = url; + HttpWrapper::SendCurlJsonRequest( + request, [this, &response, &condVar](const int httpStatusCode, const std::string& data) { + BM_TRACE_LOG("{:d}", httpStatusCode); + response = std::pair(httpStatusCode == HttpStatusCodeSuccessOk, data); + condVar.notify_all(); + }); + + // Because we do not own the object that holds our callback, so we have to wait until it is finished. + // But if the request errors, we will never hear about it, so we also set a timeout and cross our fingers. + std::unique_lock lock(mutex); + const std::cv_status status = condVar.wait_for(lock, timeout); + if (status == std::cv_status::timeout) { + BM_ERROR_LOG("request to {:s} timed out", quote(url)); + return std::pair(false, std::string()); + } - return response; - }).share(); + return response; + }).share(); activeRequests[url] = future; @@ -65,30 +73,28 @@ std::shared_future> Config::Request(const std::stri /// Bool with if the game settings where parsed successfully bool RPConfig::ParseGameSettings(const std::string& data, RocketPlugin* rocketPlugin) { - simdjson::ondemand::parser parser; + simdjson::ondemand::parser parser; const simdjson::padded_string paddedData = data; - simdjson::ondemand::document doc = parser.iterate(paddedData); + simdjson::ondemand::document doc = parser.iterate(paddedData); try { parseGameModes(doc, rocketPlugin->gameModes); parseBotDifficulties(doc, rocketPlugin->botDifficulties); parseAvailableMaps(doc, rocketPlugin->maps); - parseAvailableColors(doc, rocketPlugin->customColorHues, rocketPlugin->customColors, - rocketPlugin->clubColorHues, rocketPlugin->clubColors, - rocketPlugin->defaultBluePrimaryColor, rocketPlugin->defaultBlueAccentColor, - rocketPlugin->defaultOrangePrimaryColor, rocketPlugin->defaultOrangeAccentColor); + parseAvailableColors( + doc, rocketPlugin->customColorHues, rocketPlugin->customColors, rocketPlugin->clubColorHues, + rocketPlugin->clubColors, rocketPlugin->defaultBluePrimaryColor, rocketPlugin->defaultBlueAccentColor, + rocketPlugin->defaultOrangePrimaryColor, rocketPlugin->defaultOrangeAccentColor); parseAvailableMutators(doc, rocketPlugin->mutators); } catch (const simdjson::simdjson_error& e) { - CRITICAL_LOG("failed to parse game settings, {}", quote(e.what())); + BM_CRITICAL_LOG("failed to parse game settings, {:s}", quote(e.what())); return false; - } - catch (const std::exception& e) { - CRITICAL_LOG("failed to parse game settings, {}", quote(e.what())); + } catch (const std::exception& e) { + BM_CRITICAL_LOG("failed to parse game settings, {:s}", quote(e.what())); return false; - } - catch (...) { - CRITICAL_LOG("failed to parse game settings"); + } catch (...) { + BM_CRITICAL_LOG("failed to parse game settings"); return false; } @@ -113,7 +119,7 @@ std::future> RPConfig::RequestGameSettingConstants( return std::async([this]() { if (gameSettingConstantsConfigUrl.empty()) { if (!requestConfig().get()) { - ERROR_LOG("config request failed"); + BM_ERROR_LOG("config request failed"); return std::pair(false, std::string()); } } @@ -130,7 +136,7 @@ std::future> RPConfig::RequestRumbleConstants() return std::async([this]() { if (rumbleConstantsConfigUrl.empty()) { if (!requestConfig().get()) { - ERROR_LOG("config request failed"); + BM_ERROR_LOG("config request failed"); return std::pair(false, std::string()); } } @@ -146,7 +152,7 @@ std::future> RPConfig::RequestRumbleConstants() RocketPlugin::GameSetting ParseGameSetting(simdjson::ondemand::object gameSettingJson) { RocketPlugin::GameSetting gameSetting; - gameSetting.DisplayCategoryName = std::string_view(gameSettingJson["DisplayCategoryName"]); + gameSetting.DisplayCategoryName = std::string_view(gameSettingJson["DisplayCategoryName"]); gameSetting.InternalCategoryName = std::string_view(gameSettingJson["InternalCategoryName"]); for (simdjson::ondemand::value name : gameSettingJson["DisplayName"].get_array()) { gameSetting.DisplayName.emplace_back(std::string_view(name)); @@ -217,9 +223,8 @@ ImVec4 ParseColor(simdjson::ondemand::array arr) /// Color to save the parsed orange primary color to /// Color to save the parsed orange accent color to void RPConfig::parseAvailableColors(simdjson::ondemand::document& doc, int& customColorHues, - std::vector& customColors, int& clubColorHues, - std::vector& clubColors, ImVec4& bluePrimaryColor, ImVec4& blueAccentColor, - ImVec4& orangePrimaryColor, ImVec4& orangeAccentColor) + std::vector& customColors, int& clubColorHues, std::vector& clubColors, ImVec4& bluePrimaryColor, + ImVec4& blueAccentColor, ImVec4& orangePrimaryColor, ImVec4& orangeAccentColor) { customColorHues = static_cast(doc["CustomColorHues"].get_uint64()); customColors.clear(); @@ -232,10 +237,10 @@ void RPConfig::parseAvailableColors(simdjson::ondemand::document& doc, int& cust clubColors.push_back(ParseColor(value)); } - bluePrimaryColor = ParseColor(doc["DefaultBluePrimaryColor"]); - blueAccentColor = ParseColor(doc["DefaultBlueAccentColor"]); + bluePrimaryColor = ParseColor(doc["DefaultBluePrimaryColor"]); + blueAccentColor = ParseColor(doc["DefaultBlueAccentColor"]); orangePrimaryColor = ParseColor(doc["DefaultOrangePrimaryColor"]); - orangeAccentColor = ParseColor(doc["DefaultOrangeAccentColor"]); + orangeAccentColor = ParseColor(doc["DefaultOrangeAccentColor"]); } @@ -243,7 +248,7 @@ void RPConfig::parseAvailableColors(simdjson::ondemand::document& doc, int& cust /// Json object with available mutators /// Vector to save the parsed available mutators to void RPConfig::parseAvailableMutators(simdjson::ondemand::document& doc, - std::vector& mutators) + std::vector& mutators) { mutators.clear(); for (simdjson::ondemand::value value : doc["Mutators"]) { @@ -256,10 +261,10 @@ void RPConfig::parseAvailableMutators(simdjson::ondemand::document& doc, /// Future with if the request was successful std::future RPConfig::requestConfig() { - return std::async([this]() { + return save_promise("", [this]() { const auto& [requestSuccessful, responseData] = Request(configUrl).get(); if (!requestSuccessful) { - ERROR_LOG("config request failed"); + BM_ERROR_LOG("config request failed"); return false; } @@ -271,7 +276,7 @@ std::future RPConfig::requestConfig() simdjson::error_code error = dom["RLConstants"].get(strView); if (error) { failed = true; - ERROR_LOG("could not get RLConstants, {}", simdjson::error_message(error)); + BM_ERROR_LOG("could not get RLConstants, {:s}", simdjson::error_message(error)); } else { gameSettingConstantsConfigUrl = strView; @@ -280,7 +285,7 @@ std::future RPConfig::requestConfig() error = dom["RumbleConstants"].get(strView); if (error) { failed = true; - ERROR_LOG("could not get RumbleConstants, {}", simdjson::error_message(error)); + BM_ERROR_LOG("could not get RumbleConstants, {:s}", simdjson::error_message(error)); } else { rumbleConstantsConfigUrl = strView; diff --git a/source/RocketPlugin/Config.h b/source/RocketPlugin/RPConfig.h similarity index 59% rename from source/RocketPlugin/Config.h rename to source/RocketPlugin/RPConfig.h index 6fa56c0..d83a87e 100644 --- a/source/RocketPlugin/Config.h +++ b/source/RocketPlugin/RPConfig.h @@ -2,28 +2,28 @@ #include "RocketPlugin.h" -class Config +class BaseConfig { public: - Config() = default; - ~Config(); - Config(Config&& other) = delete; - Config(const Config& other) = delete; - Config& operator=(Config&& other) = delete; - Config& operator=(const Config& other) = delete; + BaseConfig() = default; + ~BaseConfig(); + BaseConfig(BaseConfig&& other) = delete; + BaseConfig(const BaseConfig& other) = delete; + BaseConfig& operator=(BaseConfig&& other) = delete; + BaseConfig& operator=(const BaseConfig& other) = delete; std::shared_future> Request(const std::string& url, - std::chrono::seconds timeout = std::chrono::seconds(4)); + std::chrono::seconds timeout = std::chrono::seconds(4)); private: std::unordered_map>> activeRequests; }; -class RPConfig final : Config +class RPConfig final : BaseConfig { public: - explicit RPConfig(const std::string& configUrl) : configUrl(configUrl) {} + explicit RPConfig(std::string configUrl) : configUrl(std::move(configUrl)) {} static bool ParseGameSettings(const std::string& data, class RocketPlugin* rocketPlugin); static bool ParseRumbleItems(const std::string& data, class CrazyRumble* crazyRumble); @@ -35,11 +35,10 @@ class RPConfig final : Config static void parseBotDifficulties(simdjson::ondemand::document& doc, RocketPlugin::GameSetting& botDifficulties); static void parseAvailableMaps(simdjson::ondemand::document& doc, std::map& maps); static void parseAvailableColors(simdjson::ondemand::document& doc, int& customColorHues, - std::vector& customColors, int& clubColorHues, - std::vector& clubColors, ImVec4& bluePrimaryColor, ImVec4& blueAccentColor, - ImVec4& orangePrimaryColor, ImVec4& orangeAccentColor); + std::vector& customColors, int& clubColorHues, std::vector& clubColors, + ImVec4& bluePrimaryColor, ImVec4& blueAccentColor, ImVec4& orangePrimaryColor, ImVec4& orangeAccentColor); static void parseAvailableMutators(simdjson::ondemand::document& doc, - std::vector& mutators); + std::vector& mutators); std::future requestConfig(); std::string configUrl; diff --git a/source/RocketPlugin/RocketPlugin.cpp b/source/RocketPlugin/RocketPlugin.cpp index bd6e3b1..f79899f 100644 --- a/source/RocketPlugin/RocketPlugin.cpp +++ b/source/RocketPlugin/RocketPlugin.cpp @@ -2,9 +2,9 @@ // A BakkesMod plugin for joining, hosting and manipulating multiplayer games. // // Author: Stanbroek -// Version: 0.6.7 14/07/21 +// Version: 0.6.8 18/09/21 // BMSDK version: 95 -#include "Config.h" +#include "RPConfig.h" #include "RocketPlugin.h" // Game modes @@ -27,88 +27,13 @@ std::filesystem::path BakkesModCrashesFolder; std::filesystem::path RocketPluginDataFolder; std::filesystem::path RocketLeagueExecutableFolder; +std::thread::id GameThreadId; +std::thread::id RenderThreadId; + std::shared_ptr LogLevel; std::shared_ptr GlobalCVarManager; -/* - * File Helpers - */ - -/// Checks if the given file extension is in the list of extensions. -/// File extension -/// List of file extensions -/// Bool with if the file extension is in the list of extensions -bool RocketPlugin::HasExtension(const std::string& fileExtension, const std::vector& extensions) -{ - // Filter out unwanted file extensions. - return std::any_of(extensions.begin(), extensions.end(), [&](const std::string& extension) { - return fileExtension == extension; - }); -} - - -/// Recursively gets files from a certain directory. -/// These files can be filtered by if they end with certain file extensions. -/// Path to the directory to get the files from -/// List of file extensions to filter by -/// Current folder depth -/// Max folder depth to iterate through -/// The files from a certain directory -std::vector RocketPlugin::IterateDirectory(const std::filesystem::path& directory, - const std::vector& extensions, - const int depth, const int maxDepth) -{ - if (depth > maxDepth) { - return std::vector(); - } - - std::vector files; - for (const std::filesystem::directory_entry& file : std::filesystem::directory_iterator(directory)) { - const std::filesystem::path& filePath = file.path(); - if (file.is_directory()) { - std::vector directoryFiles = IterateDirectory( - filePath, extensions, depth + 1, maxDepth); - // Remove if directory is empty. - if (!directoryFiles.empty()) { - files.insert(files.end(), directoryFiles.begin(), directoryFiles.end()); - } - } - else if (HasExtension(filePath.extension().string(), extensions)) { - files.push_back(filePath); - } - } - - return files; -} - - -/// Gets files from a certain directory. -/// These files can be filtered by if they end with certain file extensions. -/// Path to the directory to get the files from -/// Number if filters to filter the files by -/// Multiple file extensions to filter by -/// The files from a certain directory -std::vector RocketPlugin::GetFilesFromDir(const std::filesystem::path& directory, - int numExtension, ...) -{ - if (!exists(directory)) { - return std::vector(); - } - - va_list extensions; - std::vector fileExtensions; - - va_start(extensions, numExtension); - for (int i = 0; i < numExtension; i++) { - fileExtensions.emplace_back(va_arg(extensions, const char*)); - } - va_end(extensions); - - return IterateDirectory(directory, fileExtensions, 0, 1); -} - - /* * Map File Helpers */ @@ -119,8 +44,7 @@ std::vector RocketPlugin::GetFilesFromDir(const std::file /// Map extension to prefer when multiple files are found /// The workshop maps from the given directory std::vector RocketPlugin::getWorkshopMaps(const std::filesystem::path& workshopPath, - const std::vector& extensions, - const std::string& preferredExtension) + const std::vector& extensions, const std::string& preferredExtension) { if (!exists(workshopPath)) { return std::vector(); @@ -128,15 +52,16 @@ std::vector RocketPlugin::getWorkshopMaps(const std::file // Make sure we don't request workshop map names every tick. const bool shouldRequestWorkshopMapNames = publishedFileID.empty(); - std::vector files = IterateDirectory(workshopPath, extensions, 0, 1); + const std::vector files = iterate_directory(workshopPath, extensions, 0, 1); std::filesystem::path bestPath; std::vector workshopMaps; for (const std::filesystem::path& file : files) { if (file.parent_path() != bestPath.parent_path()) { if (!bestPath.empty()) { const uint64_t workshopMapId = std::strtoull(bestPath.parent_path().stem().string().c_str(), nullptr, - 10); - if (shouldRequestWorkshopMapNames && subscribedWorkshopMaps.find(workshopMapId) == subscribedWorkshopMaps.end()) { + 10); + if (shouldRequestWorkshopMapNames && subscribedWorkshopMaps.find(workshopMapId) == + subscribedWorkshopMaps.end()) { publishedFileID.push_back(workshopMapId); } workshopMaps.push_back(bestPath); @@ -150,7 +75,8 @@ std::vector RocketPlugin::getWorkshopMaps(const std::file if (!bestPath.empty()) { const uint64_t workshopMapId = std::strtoull(bestPath.parent_path().stem().string().c_str(), nullptr, 10); - if (shouldRequestWorkshopMapNames && subscribedWorkshopMaps.find(workshopMapId) == subscribedWorkshopMaps.end()) { + if (shouldRequestWorkshopMapNames && subscribedWorkshopMaps.find(workshopMapId) == subscribedWorkshopMaps. + end()) { publishedFileID.push_back(workshopMapId); } workshopMaps.push_back(bestPath); @@ -183,7 +109,7 @@ void PrintCommandOptions(std::string error = "") "\tmutator [mutator] [value]\n" "\trumble [force multiplier] [range multiplier] [duration multiplier]"; - LOG(error); + BM_LOG(error); } @@ -197,7 +123,7 @@ void PrintJoinOptions(std::string error = "") "\tport (optional, default: " + std::to_string(DEFAULT_PORT) + "): port to connect to\n" "\tpassword (optional, default: empty): password the server is protected with"; - LOG(error); + BM_LOG(error); } @@ -212,7 +138,7 @@ void PrintAvailableMutators(const std::vector& mutato error += "\t" + quote(mutator.InternalCategoryName) + " [value]\n"; } - LOG(error.substr(0, error.size() - 1)); + BM_LOG(error.substr(0, error.size() - 1)); } @@ -224,9 +150,10 @@ int FindSanitizedIndexInMutators(const std::vector& m { for (size_t i = 0; i < mutators.size(); i++) { std::string internalMutatorName = mutators[i].InternalCategoryName; - internalMutatorName.erase(std::remove_if(internalMutatorName.begin(), internalMutatorName.end(), [](const char c) { - return !std::isalnum(c); - }), internalMutatorName.end()); + internalMutatorName.erase(std::remove_if(internalMutatorName.begin(), internalMutatorName.end(), + [](const char c) { + return !std::isalnum(c); + }), internalMutatorName.end()); mutatorNameToFind.erase(std::remove_if(mutatorNameToFind.begin(), mutatorNameToFind.end(), [](const char c) { return !std::isalnum(c); }), mutatorNameToFind.end()); @@ -254,7 +181,7 @@ void PrintAvailableMutatorValues(const RocketPlugin::GameSetting& mutator, std:: } } - LOG(error.substr(0, error.size() - 1)); + BM_LOG(error.substr(0, error.size() - 1)); } @@ -269,12 +196,12 @@ int FindSanitizedIndexInMutatorValues(const RocketPlugin::GameSetting& mutator, } for (size_t i = 0; i < mutator.InternalName.size(); i++) { std::string mutatorValue = mutator.InternalName[i]; - mutatorValue.erase(std::remove_if(mutatorValue.begin(), mutatorValue.end(), [](const char c) { + mutatorValue.erase(std::ranges::remove_if(mutatorValue, [](const char c) { return !std::isalnum(c); - }), mutatorValue.end()); - mutatorValueToFind.erase(std::remove_if(mutatorValueToFind.begin(), mutatorValueToFind.end(), [](const char c) { + }).begin(), mutatorValue.end()); + mutatorValueToFind.erase(std::ranges::remove_if(mutatorValueToFind, [](const char c) { return !std::isalnum(c); - }), mutatorValueToFind.end()); + }).begin(), mutatorValueToFind.end()); if (to_lower(mutatorValueToFind) == to_lower(mutatorValue)) { return static_cast(i); @@ -295,14 +222,15 @@ void PrintRumbleOptions(std::string error = "") "\trange multiplier: float to multiply with\n" "\tduration multiplier: float to multiply with"; - LOG(error); + BM_LOG(error); } /// Checks if the given string is a int. /// String to check if it is a int /// Bool with is the string is a int -bool IsInt(const std::string& str) { +bool IsInt(const std::string& str) +{ std::istringstream iss(str); int i; iss >> std::noskipws >> i; // std::noskipws considers leading whitespace invalid. @@ -315,7 +243,8 @@ bool IsInt(const std::string& str) { /// Checks if the given string is a float. /// String to check if it is a float /// Bool with is the string is a float -bool IsFloat(const std::string& str) { +bool IsFloat(const std::string& str) +{ std::istringstream iss(str); float f; iss >> std::noskipws >> f; // std::noskipws considers leading whitespace invalid. @@ -328,8 +257,9 @@ bool IsFloat(const std::string& str) { /// Checks if the given string is a number. /// String to check if it is a number /// Bool with is the string is a number -template::value, bool> = true> -bool IsNumber(const std::string& str) { +template, bool> = true> +bool IsNumber(const std::string& str) +{ std::istringstream iss(str); T num; iss >> std::noskipws >> num; // std::noskipws considers leading whitespace invalid. @@ -402,7 +332,7 @@ void RocketPlugin::parseJoinArguments(const std::vector& arguments) void RocketPlugin::parseHostArguments(const std::vector& arguments) { if (arguments.size() < 3) { - LOG("usage: rp host [map] (preset)"); + BM_LOG("usage: rp host [map] (preset)"); return; } @@ -427,7 +357,7 @@ void PrintAvailableGameModes(const RocketPlugin::GameSetting& gameModes, std::st } } - LOG(error.substr(0, error.size() - 1)); + BM_LOG(error.substr(0, error.size() - 1)); } @@ -439,10 +369,12 @@ void RocketPlugin::parseGameModeArguments(const std::vector& argume } const std::string& gameMode = arguments[2]; - if (const auto& itDisplay = std::find(gameModes.DisplayName.begin(), gameModes.DisplayName.end(), gameMode); itDisplay != gameModes.DisplayName.end()) { + if (const auto& itDisplay = std::ranges::find(gameModes.DisplayName, gameMode); + itDisplay != gameModes.DisplayName.end()) { gameModes.CurrentSelected = std::distance(gameModes.DisplayName.begin(), itDisplay); } - else if (const auto& itInternal = std::find(gameModes.InternalName.begin(), gameModes.InternalName.end(), gameMode); itInternal != gameModes.InternalName.end()) { + else if (const auto& itInternal = std::ranges::find(gameModes.InternalName, gameMode); + itInternal != gameModes.InternalName.end()) { gameModes.CurrentSelected = std::distance(gameModes.InternalName.begin(), itInternal); } else { @@ -452,7 +384,7 @@ void RocketPlugin::parseGameModeArguments(const std::vector& argume if (isHostingLocalGame()) { setMatchSettings(); - LOG("Updated game mode for next match."); + BM_LOG("Updated game mode for next match."); } } @@ -460,7 +392,7 @@ void RocketPlugin::parseGameModeArguments(const std::vector& argume void RocketPlugin::parseMapArguments(const std::vector& arguments) { if (arguments.size() < 3) { - LOG("usage: rp map [map]"); + BM_LOG("usage: rp map [map]"); return; } @@ -481,13 +413,13 @@ void RocketPlugin::parseMapArguments(const std::vector& arguments) currentMap = it->first; } else { - ERROR_LOG("Invalid map {}", quote(arguments[2])); + BM_ERROR_LOG("Invalid map {:s}", quote(arguments[2])); return; } if (isHostingLocalGame()) { setMatchMapName(map.stem().string()); - LOG("Updated map for next match."); + BM_LOG("Updated map for next match."); } } @@ -495,20 +427,20 @@ void RocketPlugin::parseMapArguments(const std::vector& arguments) void RocketPlugin::parsePlayerCountArguments(const std::vector& arguments) { if (arguments.size() < 3) { - LOG("usage: rp players [players]"); + BM_LOG("usage: rp players [players]"); return; } const std::string& players = arguments[2]; if (!IsInt(players)) { - ERROR_LOG("Invalid number of players {}", quote(players)); + BM_ERROR_LOG("Invalid number of players {:s}", quote(players)); return; } playerCount = std::max(2l, std::strtol(players.c_str(), nullptr, 10)); if (isHostingLocalGame()) { - WARNING_LOG("Updating player count may not update while already hosting."); + BM_WARNING_LOG("Updating player count may not update while already hosting."); } } @@ -522,7 +454,7 @@ void setTeamColor(int8_t& teamColor, const int8_t& newTeamColor) void RocketPlugin::parseTeamArguments(const std::vector& arguments) { if (arguments.size() < 6) { - LOG("usage: rp team [teamNum] [teamName*] [primaryColorIdx*] [accentColorIdx*] (clubMatch), *leave empty for default"); + BM_LOG("usage: rp team [teamNum] [teamName*] [primaryColorIdx*] [accentColorIdx*] (clubMatch), *leave empty for default"); return; } @@ -530,7 +462,7 @@ void RocketPlugin::parseTeamArguments(const std::vector& arguments) const std::string& teamNumStr = arguments[2]; const unsigned long& teamNum = std::strtoul(teamNumStr.c_str(), nullptr, 10); if (!IsInt(teamNumStr) || (teamNum != 0 && teamNum != 1)) { - ERROR_LOG("Invalid team number {:s}", quote(teamNumStr)); + BM_ERROR_LOG("Invalid team number {:s}", quote(teamNumStr)); return; } @@ -545,12 +477,12 @@ void RocketPlugin::parseTeamArguments(const std::vector& arguments) // Primary color. const std::string& primaryColorStr = arguments[4]; if (primaryColorStr.empty()) { - setTeamColor(teamNum == 0 ? team1PrimCol : team2PrimCol,-1); + setTeamColor(teamNum == 0 ? team1PrimCol : team2PrimCol, -1); } else { const long primaryColorIdx = std::strtol(primaryColorStr.c_str(), nullptr, 10); if (!IsInt(primaryColorStr) || primaryColorIdx >= clubColors.size()) { - ERROR_LOG("Invalid primary color index {:s}", quote(primaryColorStr)); + BM_ERROR_LOG("Invalid primary color index {:s}", quote(primaryColorStr)); return; } setTeamColor(teamNum == 0 ? team1PrimCol : team2PrimCol, static_cast(primaryColorIdx)); @@ -564,7 +496,7 @@ void RocketPlugin::parseTeamArguments(const std::vector& arguments) else { const long accentColorIdx = std::strtol(accentColorStr.c_str(), nullptr, 10); if (!IsInt(accentColorStr) || accentColorIdx >= customColors.size()) { - ERROR_LOG("Invalid primary color index {:s}", quote(accentColorStr)); + BM_ERROR_LOG("Invalid primary color index {:s}", quote(accentColorStr)); return; } setTeamColor(teamNum == 0 ? team1AccCol : team2AccCol, static_cast(accentColorIdx)); @@ -574,7 +506,7 @@ void RocketPlugin::parseTeamArguments(const std::vector& arguments) if (arguments.size() > 6) { const std::string& clubMatchStr = arguments[6]; if (!IsNumber(clubMatchStr)) { - ERROR_LOG("Invalid club match {:s}", quote(clubMatchStr)); + BM_ERROR_LOG("Invalid club match {:s}", quote(clubMatchStr)); return; } clubMatch = std::strtoul(clubMatchStr.c_str(), nullptr, 10); @@ -582,7 +514,7 @@ void RocketPlugin::parseTeamArguments(const std::vector& arguments) if (isHostingLocalGame()) { setMatchSettings(); - LOG("Updated game mode for next match."); + BM_LOG("Updated game mode for next match."); } } @@ -609,17 +541,17 @@ void RocketPlugin::parseMutatorArguments(const std::vector& argumen const std::string& mutatorValue = arguments[3]; const int j = FindSanitizedIndexInMutatorValues(mutators[i], mutatorValue); if (j == -1) { - PrintAvailableMutatorValues( - mutators[i], "Invalid value '" + mutatorValue + "' for '" + mutators[i].InternalCategoryName + "'\n"); + PrintAvailableMutatorValues(mutators[i], "Invalid value '" + mutatorValue + "' for '" + + mutators[i].InternalCategoryName + "'\n"); return; } mutators[i].CurrentSelected = j; - LOG("Changed {} to {}", quote(mutators[i].InternalCategoryName), quote(mutators[i].InternalName[j])); + BM_LOG("Changed {:s} to {:s}", quote(mutators[i].InternalCategoryName), quote(mutators[i].InternalName[j])); if (isHostingLocalGame()) { setMatchSettings(); - LOG("Updated mutator for next match."); + BM_LOG("Updated mutator for next match."); } } @@ -631,10 +563,10 @@ void RocketPlugin::parseRumbleArguments(const std::vector& argument return; } - const float forceMultiplier = std::strtof(arguments[2].c_str(), nullptr); - const float rangeMultiplier = std::strtof(arguments[3].c_str(), nullptr); + const float forceMultiplier = std::strtof(arguments[2].c_str(), nullptr); + const float rangeMultiplier = std::strtof(arguments[3].c_str(), nullptr); const float durationMultiplier = std::strtof(arguments[4].c_str(), nullptr); - std::shared_ptr crazyRumble = GetCustomGameMode(); + const std::shared_ptr crazyRumble = GetCustomGameMode(); if (crazyRumble != nullptr) { crazyRumble->UpdateItemsValues(forceMultiplier, rangeMultiplier, durationMultiplier); } @@ -647,7 +579,7 @@ void RocketPlugin::parseRumbleArguments(const std::vector& argument /// List of suggestions std::vector RocketPlugin::complete(const std::vector& arguments) { - std::vector suggestions = std::vector(); + std::vector suggestions; if (arguments.size() == 2 && arguments[1].empty()) { suggestions.emplace_back("join ;[ip](:port) (password)"); @@ -664,10 +596,10 @@ std::vector RocketPlugin::complete(const std::vector& } else if (arguments.size() == 3) { if (arguments[2].empty()) { - suggestions.push_back("join " + *joinIP + ":" + std::to_string(*joinPort) + " ;(password)"); + suggestions.push_back(fmt::format("join {:s}:{:d} ;(password)", *joinIP, *joinPort)); } else { - suggestions.push_back("join " + arguments[2] + ":" + std::to_string(*joinPort) + " ;(password)"); + suggestions.push_back(fmt::format("join {:s}:{:d} ;(password)", arguments[2], *joinPort)); } } else if (arguments.size() == 4) { @@ -727,7 +659,7 @@ void RocketPlugin::HostGame(std::string arena) if (arena.empty()) { if (enableWorkshopMaps || enableCustomMaps) { if (!std::filesystem::exists(currentMap)) { - ERROR_LOG("no map selected."); + BM_ERROR_LOG("no map selected."); PushError("Hosting map failed: no map selected"); return; } @@ -746,7 +678,7 @@ void RocketPlugin::HostGame(std::string arena) } else { if (maps.find(currentMap) == maps.end()) { - ERROR_LOG("no map selected."); + BM_ERROR_LOG("no map selected."); PushError("Hosting map failed: no map selected"); return; } @@ -755,15 +687,14 @@ void RocketPlugin::HostGame(std::string arena) } #ifdef _WIN32 /* Cos we as windows want our baguettes the left way. */ - std::replace(arena.begin(), arena.end(), '/', '\\'); + std::ranges::replace(arena, '/', '\\'); #endif const std::string gameMode = gameModes.GetSelected(); std::string gameTags = getGameTags(); // Available PlayerCounts are 2, 4, 6 and 8. gameTags += ",PlayerCount" + std::to_string(std::clamp(playerCount, 2, 8) & ~1); const int numConnections = std::max(10, playerCount); - const std::string networkOptions = "?NumPublicConnections=" + std::to_string(numConnections) + - "?NumOpenPublicConnections=" + std::to_string(numConnections) + "?Lan?Listen"; + const std::string networkOptions = fmt::format("?NumPublicConnections={0:d}?NumOpenPublicConnections={0:d}?Lan?Listen", numConnections); hostingGame = true; if (hostWithParty) { @@ -775,11 +706,11 @@ void RocketPlugin::HostGame(std::string arena) loadingScreenMapName = std::filesystem::path(currentMap).stem(); } else { - loadingScreenMapName = to_wstring(customMapPaths[currentMap]); + loadingScreenMapName = to_wstring(customMapPaths[currentMap]); } loadingScreenMapAuthor = L"unknown"; - const uint64_t workshopMapId = std::strtoll(std::filesystem::path(currentMap).parent_path().stem().string().c_str(), - nullptr, 10); + const uint64_t workshopMapId = std::strtoll( + std::filesystem::path(currentMap).parent_path().stem().string().c_str(), nullptr, 10); if (subscribedWorkshopMaps.find(workshopMapId) != subscribedWorkshopMaps.end()) { const WorkshopMap workshopMap = subscribedWorkshopMaps[workshopMapId]; const std::wstring nickname = getPlayerNickname(workshopMap.Owner); @@ -793,8 +724,9 @@ void RocketPlugin::HostGame(std::string arena) cvarManager->getCvar("cl_soccar_boostcounter").setValue(false); // Delay this so the search status can be send before loading. - const std::string command = "open " + arena + "?Playtest?game=" + gameMode + "?GameTags=" + gameTags + networkOptions; - gameWrapper->SetTimeout([this, command = command](GameWrapper*) { + const std::string command = fmt::format("open {:s}?Playtest?game={:s}?GameTags={:s}{:s}", arena, gameMode, gameTags, + networkOptions); + SetTimeout([this, command = command](GameWrapper*) { gameWrapper->ExecuteUnrealCommand(command); }, 0.1f); } @@ -810,8 +742,8 @@ void RocketPlugin::JoinGame(const char* pswd) loadingScreenMapName = to_wstring(joinableMaps[currentJoinMap]); loadingScreenMapAuthor = L"author"; // Add the owners nickname if we can find them. - const uint64_t workshopMapId = std::strtoll(std::filesystem::path(currentMap).parent_path().stem().string().c_str(), - nullptr, 10); + const uint64_t workshopMapId = std::strtoll( + std::filesystem::path(currentMap).parent_path().stem().string().c_str(), nullptr, 10); if (subscribedWorkshopMaps.find(workshopMapId) != subscribedWorkshopMaps.end()) { const WorkshopMap workshopMap = subscribedWorkshopMaps[workshopMapId]; const std::wstring nickname = getPlayerNickname(workshopMap.Owner); @@ -831,7 +763,7 @@ void RocketPlugin::JoinGame(const char* pswd) } } - gameWrapper->ExecuteUnrealCommand("start " + *joinIP + ":" + std::to_string(*joinPort) + "/?Lan?Password=" + pswd); + gameWrapper->ExecuteUnrealCommand(fmt::format("start {:s}:{:d}/?Lan?Password={:s}", *joinIP, *joinPort, pswd)); } @@ -860,8 +792,8 @@ void RocketPlugin::savePreset(const std::string& presetName) presetFile << "// This preset has been autogenerated by Rocket Plugin\n"; for (const GameSetting& mutator : mutators) { if (mutator.CurrentSelected != 0) { - presetFile << "rp mutator " + quote(mutator.InternalCategoryName) + " " + - quote(mutator.GetSelected()) << std::endl; + presetFile << "rp mutator " + quote(mutator.InternalCategoryName) + " " + quote(mutator.GetSelected()) + << std::endl; } } } @@ -873,7 +805,7 @@ void RocketPlugin::savePreset(const std::string& presetName) void RocketPlugin::loadPreset(const std::filesystem::path& presetPath) { resetMutators(); - TRACE_LOG("loading preset {}", quote(presetPath.u8string())); + BM_TRACE_LOG("loading preset {:s}", quote(presetPath.string())); cvarManager->loadCfg(presetPath.generic_string()); } @@ -900,8 +832,9 @@ void RocketPlugin::copyMap(const std::filesystem::path& map) std::error_code ec; /* Creates parent directory. */ if (!exists(mapDst.parent_path()) && !create_directories(mapDst.parent_path(), ec)) { - PushError("Error Fixing Map\ncheck the console (F6) for more details, for more details and report to the mod author if applicable."); - ERROR_LOG("failed to create directory: {}, {}", quote(mapDst.parent_path().u8string()), quote(ec.message())); + PushError("Error Fixing Map\n" + "check the console (F6) for more details, for more details and report to the mod author if applicable."); + BM_ERROR_LOG("failed to create directory: {:s}, {:s}", quote(mapDst.parent_path().string()), quote(ec.message())); return; } @@ -909,21 +842,22 @@ void RocketPlugin::copyMap(const std::filesystem::path& map) /* Copies file to new directory. */ std::filesystem::copy(mapSrc, mapDst, std::filesystem::copy_options::overwrite_existing, ec); if (ec) { - PushError("Error Fixing Map\ncheck the console (F6) for more details, for more details and report to the mod author if applicable."); - ERROR_LOG("failed to copy file: {} to {}, {}", quote(mapSrc.u8string()), quote(mapDst.u8string()), quote(ec.message())); - INFO_LOG("-------------------------------------------------------"); - INFO_LOG("currentJoinMap = {}", quote(absolute(currentJoinMap).u8string())); + PushError("Error Fixing Map\n" + "check the console (F6) for more details, for more details and report to the mod author if applicable."); + BM_ERROR_LOG("failed to copy file: {:s} to {:s}, {:s}", quote(mapSrc.string()), quote(mapDst.string()), + quote(ec.message())); + BM_INFO_LOG("-------------------------------------------------------"); + BM_INFO_LOG("currentJoinMap = {:s}", quote(absolute(currentJoinMap).string())); int i = 0; for (const auto& [joinableMap, _] : joinableMaps) { - INFO_LOG("[" + std::to_string(i++) + "] = path:" + quote(joinableMap.u8string()) + ", excists: " + - (exists(joinableMap) ? "True" : "False")); + BM_INFO_LOG("[{:d}] = path: {:s}, exists: {:s}", i++, quote(joinableMap.string()), exists(joinableMap)); } - INFO_LOG("-------------------------------------------------------"); + BM_INFO_LOG("-------------------------------------------------------"); return; } - TRACE_LOG("created file successfully."); + BM_TRACE_LOG("created file successfully."); refreshJoinableMaps = true; refreshCustomMapPaths = true; @@ -936,7 +870,7 @@ void RocketPlugin::copyMap(const std::filesystem::path& map) void RocketPlugin::onGameEventInit([[maybe_unused]] const ServerWrapper& server) { // Clear car physics cache. - carPhysics.clear(); + carPhysicsMods.carPhysics.clear(); isJoiningHost = false; if (!hostingGame) { @@ -958,9 +892,9 @@ void RocketPlugin::onGameEventInit([[maybe_unused]] const ServerWrapper& server) if (shouldInviteParty) { shouldInviteParty = false; if (!setSearchStatus(L"Joining")) { - WARNING_LOG("could not set the search status"); + BM_WARNING_LOG("could not set the search status"); } - gameWrapper->SetTimeout([this](GameWrapper*) { + SetTimeout([this](GameWrapper*) { broadcastJoining(); }, 1.41f); } @@ -968,29 +902,9 @@ void RocketPlugin::onGameEventInit([[maybe_unused]] const ServerWrapper& server) /* - * Game Controls + * Modules */ -/// Checks if you are in a game. -/// Bool with if should check online games -/// Whether you are in a game -bool RocketPlugin::IsInGame(const bool allowOnlineGame) const -{ - ServerWrapper localGame = gameWrapper->GetGameEventAsServer(); - if (!localGame.IsNull()) { - return true; - } - if (allowOnlineGame) { - ServerWrapper onlineGame = gameWrapper->GetOnlineGame(); - if (!onlineGame.IsNull()) { - return true; - } - } - - return false; -} - - /// Gets the current game as . /// Bool with if should try to get a online game /// The current game as or NULL is no game is found @@ -1011,1259 +925,219 @@ ServerWrapper RocketPlugin::GetGame(const bool allowOnlineGame) const } -/// Forces overtime in the current game. -void RocketPlugin::ForceOvertime() const +/// Checks if you are in a game. +/// Bool with if should check online games +/// Whether you are in a game +bool RocketPlugin::IsInGame(const bool allowOnlineGame) const { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.ForceOvertime(); + ServerWrapper game = GetGame(allowOnlineGame); + return !game.IsNull(); } -/// Pauses the current game. -void RocketPlugin::PauseServer() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - PlayerControllerWrapper pc = game.GetPauser(); - if (pc.IsNull()) { - cvarManager->executeCommand("mp_pause", false); - } - else { - cvarManager->executeCommand("mp_unpause", false); - } -} - +/* + * BakkesMod plugin overrides + */ -/// Resets the current game. -void RocketPlugin::ResetMatch() const +/// Checks if the GUI window is bound. +/// Name of the GUI window +/// Bool with if the GUI window is bound +bool IsGUIWindowBound(const std::string& windowName) { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; + const std::string bind = "togglemenu " + windowName; + std::ifstream file(BINDS_FILE_PATH); + if (file.is_open()) { + std::string line; + while (getline(file, line)) { + if (line.find(bind) != std::string::npos) { + file.close(); + return true; + } + } + file.close(); } - game.StartNewRound(); + return false; } -/// Ends the current game. -void RocketPlugin::EndMatch() const +/// Registers notifiers and variables to interact with the plugin on load. +void RocketPlugin::OnLoad() { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; + BakkesModConfigFolder = gameWrapper->GetBakkesModPath() / L"cfg"; + BakkesModCrashesFolder = gameWrapper->GetBakkesModPath() / L"crashes"; + if (!exists(BakkesModCrashesFolder)) { + create_directory(BakkesModCrashesFolder); } + RocketPluginDataFolder = gameWrapper->GetDataFolder() / L"RocketPlugin"; + if (!exists(RocketPluginDataFolder)) { + create_directory(RocketPluginDataFolder); + } + RocketLeagueExecutableFolder = std::filesystem::current_path(); - game.EndGame(); -} - + set_game_thread(); -/// Resets the players in the current game. -void RocketPlugin::ResetPlayers() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + // Copy the original cvarManager so we can use it everywhere. + GlobalCVarManager = std::reinterpret_pointer_cast(cvarManager); - game.ResetPlayers(); -} + /* Register CVars */ + registerCVars(); + registerExternalCVars(); + /* Register Notifiers */ + registerNotifiers(); + registerExternalNotifiers(); -/// Resets the balls in the current game. -void RocketPlugin::ResetBalls() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + /* Register Hooks */ + registerHooks(); + registerExternalHooks(); - game.ResetBalls(); -} + // Load RL Constants. + loadRLConstants(); + // Load Constants Config. + ConstantsConfig = std::make_unique(DEFAULT_CONSTANTS_CONFIG_URL); -/* - * Match Settings - */ + /* GUI Settings */ -/// Sets max players in the current game. -/// New number of players -void RocketPlugin::SetMaxPlayers(const int newNumPlayers) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; + // Set the window bind to the default keybind if is not set. + if (!IsGUIWindowBound(GetMenuName())) { + cvarManager->setBind(DEFAULT_GUI_KEYBIND, "togglemenu " + GetMenuName()); + BM_LOG("Set window keybind to {:s}", DEFAULT_GUI_KEYBIND); } - game.SetMaxPlayers(newNumPlayers); -} + // Load the custom mutator presets. + presetPaths = get_files_from_dir(*presetDirPath, 2, ".cfg"); + /* Init Networking */ + upnpClient = std::make_shared(); + p2pHost = std::make_shared(); -/// Gets max players in the current game. -/// Max number of players -int RocketPlugin::GetMaxPlayers() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 16; - } + /* Init Modules */ + RocketPluginModule::rocketPlugin = this; - return game.GetMaxPlayers(); + /* Init Game Modes */ + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); + customGameModes.push_back(std::make_shared()); } -/// Sets max team size in the current game. -/// New team size -void RocketPlugin::SetMaxTeamSize(const int newTeamSize) const +/// Unload the plugin properly. +void RocketPlugin::OnUnload() { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetMaxTeamSize(newTeamSize); + //// Save all CVars to 'config.cfg'. + //cvarManager->backupCfg(CONFIG_FILE_PATH.string()); } -/// Gets max team size in the current game. -/// Max team size -int RocketPlugin::GetMaxTeamSize() const +/// Registers CVars for Rocket Plugin. +void RocketPlugin::registerCVars() { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 3; - } + joinIP = std::make_shared(); + cvarManager->registerCvar("mp_ip", "127.0.0.1", "Default ip for joining local matches").bindTo(joinIP); - return game.GetMaxTeamSize(); -} + joinPort = std::make_shared(DEFAULT_PORT); + cvarManager->registerCvar("mp_port", std::to_string(DEFAULT_PORT), "Default port for joining local matches").bindTo( + joinPort); + presetDirPath = std::make_shared(); + cvarManager->registerCvar("rp_preset_path", PRESETS_PATH.string(), "Default path for the mutator presets directory") + .bindTo(presetDirPath); -/// Sets respawn time in the current game. -/// New respawn time -void RocketPlugin::SetRespawnTime(const int newRespawnTime) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + workshopMapDirPath = std::make_shared(); + cvarManager->registerCvar("rp_workshop_path", WORKSHOP_MAPS_PATH.string(), + "Default path for your workshop maps directory").bindTo(workshopMapDirPath); - game.SetRespawnTime(newRespawnTime); -} + customMapDirPath = std::make_shared(); + cvarManager->registerCvar("rp_custom_path", CUSTOM_MAPS_PATH.string(), + "Default path for your custom maps directory").bindTo(customMapDirPath); + cvarManager->registerCvar("rp_gui_keybind", DEFAULT_GUI_KEYBIND, "Keybind for the gui"); -/// Gets respawn time in the current game. -/// Respawn time -int RocketPlugin::GetRespawnTime() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 3; - } + LogLevel = std::make_shared(0); + cvarManager->registerCvar("rp_log_level", std::to_string(CVarManagerWrapperDebug::level_enum::normal), "Log level", + true, false, 0, false, 0, false).bindTo(LogLevel); - return game.GetRespawnTime(); -} +#ifdef DEBUG + cvarManager->getCvar("rp_log_level").setValue(CVarManagerWrapperDebug::level_enum::all); + showDemoWindow = std::make_shared(false); + cvarManager->registerCvar("rp_show_demo_window", "0", "Shows the Dear ImGui demo window", true, false, 0, false, 0, + false).bindTo(showDemoWindow); -/// Sets the score of the given team in the current game. -/// Team to set the score of -/// New score -void RocketPlugin::SetScore(int team, int newScore) const -{ - switch (team) { - case 0: - return SetScoreBlue(newScore); - case 1: - return SetScoreOrange(newScore); - default: - ERROR_LOG("team #{} not found", team); - } + showMetricsWindow = std::make_shared(false); + cvarManager->registerCvar("rp_show_metrics_window", "0", "Shows the Dear ImGui metrics window", true, false, 0, + false, 0, false).bindTo(showMetricsWindow); +#endif } -/// Gets the score of the given team in the current game. -/// Team to get the score of -/// Teams score -int RocketPlugin::GetScore(int team) const +/// Registers notifiers for Rocket Plugin. +void RocketPlugin::registerNotifiers() { - switch (team) { - case 0: - return GetScoreBlue(); - case 1: - return GetScoreOrange(); - default: - ERROR_LOG("invalid team #{}", team); - return 0; - } -} - + RegisterNotifier("rp", [this](const std::vector& arguments) { + parseArguments(arguments); + }, "Parses commands to interact with Rocket Plugin.", PERMISSION_ALL); -/// Sets blues score in the current game. -/// New score -void RocketPlugin::SetScoreBlue(const int newScore) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + RegisterNotifier("rp_enable_debug_mode", [this](const std::vector&) { + cvarManager->getCvar("rp_log_level").setValue(CVarManagerWrapperDebug::level_enum::all); + }, "Enables debug mode.", PERMISSION_ALL); - ArrayWrapper teams = game.GetTeams(); - if (teams.Count() >= 1) { - TeamWrapper blueTeam = teams.Get(0); - if (!blueTeam.IsNull()) { - blueTeam.SetScore(newScore); + RegisterNotifier("rp_change_keybind", [this](const std::vector& arguments) { + std::string key; + if (arguments.size() >= 2) { + key = arguments[1]; } - } -} - - -/// Gets blues score in the current game. -/// Blues score -int RocketPlugin::GetScoreBlue() const -{ - ServerWrapper game = GetGame(true); - if (game.IsNull()) { - return 0; - } - - ArrayWrapper teams = game.GetTeams(); - if (teams.Count() >= 1) { - TeamWrapper blueTeam = teams.Get(0); - if (!blueTeam.IsNull()) { - return blueTeam.GetScore(); + else { + key = cvarManager->getCvar("rp_gui_keybind").getStringValue(); } - } - return 0; -} + const std::string command = "togglemenu " + GetMenuName(); + cvarManager->setBind(key, command); + BM_LOG("Set {:s} to {:s}", quote(key), quote(command)); + }, "Adds a keybind for " + quote("togglemenu " + GetMenuName()) + " as $rp_gui_keybind or given argument.", + PERMISSION_ALL); + RegisterNotifier("rp_broadcast_game", [this](const std::vector&) { + broadcastJoining(); + }, "Broadcasts a game invite to your party members.", PERMISSION_SOCCAR); -/// Sets oranges score in the current game. -/// New score -void RocketPlugin::SetScoreOrange(const int newScore) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } + RegisterNotifier("rp_clear_car_physics_cache", [this](const std::vector&) { + carPhysicsMods.carPhysics.clear(); + }, "Broadcasts a game invite to your party members.", PERMISSION_SOCCAR); - ArrayWrapper teams = game.GetTeams(); - if (teams.Count() >= 2) { - TeamWrapper orangeTeam = teams.Get(1); - if (!orangeTeam.IsNull()) { - orangeTeam.SetScore(newScore); + RegisterNotifier("rp_add_beta_game_modes", [this](const std::vector&) { + if (GetCustomGameMode() == nullptr) { + customGameModes.push_back(std::make_shared()); + BM_TRACE_LOG("added Small Cars game mode"); } - } -} - - -/// Gets oranges score in the current game. -/// Oranges score -int RocketPlugin::GetScoreOrange() const -{ - ServerWrapper game = GetGame(true); - if (game.IsNull()) { - return 0; - } - - ArrayWrapper teams = game.GetTeams(); - if (teams.Count() >= 2) { - TeamWrapper orangeTeam = teams.Get(1); - if (!orangeTeam.IsNull()) { - return orangeTeam.GetScore(); + else { + BM_WARNING_LOG("Small Cars game mode already added"); } - } - - return 0; -} - - -/// Sets the time remaining in the current game. -/// The new time remaining -void RocketPlugin::SetGameTimeRemaining(const int newGameTimeRemaining) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetGameTimeRemaining(static_cast(newGameTimeRemaining)); -} - - -/// Gets the time remaining in the current game. -/// The time remaining -int RocketPlugin::GetGameTimeRemaining() const -{ - ServerWrapper game = GetGame(true); - if (game.IsNull()) { - return 0; - } - - return static_cast(ceil(game.GetGameTimeRemaining())); -} - - -/// Sets if the goal delay is disabled in the current game. -/// Bool with if the goal delay should be disabled -void RocketPlugin::SetIsGoalDelayDisabled(const bool isGoalDelayDisabled) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetbDisableGoalDelay(isGoalDelayDisabled); -} - - -/// Gets if the goal delay is disabled in the current game. -/// Bool with if the goal delay is disabled -bool RocketPlugin::GetIsGoalDelayDisabled() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return false; - } - - return game.GetbDisableGoalDelay(); -} - - -/// Sets if there is unlimited time in the current game. -/// Bool with if there should be unlimited time -void RocketPlugin::SetIsUnlimitedTime(const bool isUnlimitedTime) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetbUnlimitedTime(isUnlimitedTime); + }, "Adds beta game modes.", PERMISSION_ALL); } -/// Gets if there is unlimited time in the current game. -/// bool with if there is unlimited time -bool RocketPlugin::GetIsUnlimitedTime() const +/// Register hooks for Rocket Plugin. +void RocketPlugin::registerHooks() { - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return false; - } - - return game.GetbUnlimitedTime(); -} - - -/* - * Bots - */ - -/// Sets the number of bots per team in the current game. -/// The new maximum number of bots per team -void RocketPlugin::SetMaxNumBots(const bool newMaxNumBots) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetNumBots(newMaxNumBots); -} - - -/// Gets the maximum number of bots per team in the current game. -/// The maximum number of bots per team -int RocketPlugin::GetMaxNumBots() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 0; - } - - return game.GetNumBots(); -} - - -/// Sets the number of bots per team in the game. -/// The new number of bots per team -void RocketPlugin::SetNumBotsPerTeam(const int newNumBotsPerTeam) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - const int maxTeamSize = game.GetMaxTeamSize(); - const bool isFilledWithAI = game.GetbFillWithAI(); - game.SetMaxTeamSize(newNumBotsPerTeam); - game.SetbFillWithAI(true); - - const int oldMaxNumBotsPerTeam = game.GetNumBots(); - game.SetNumBots(newNumBotsPerTeam); - // UpdateBotCount() only adds/removes one bot at a time. - for (int botsToAdd = std::max(oldMaxNumBotsPerTeam, newNumBotsPerTeam) * 2; botsToAdd > 0; --botsToAdd) { - game.UpdateBotCount(); - } - - game.SetMaxTeamSize(maxTeamSize); - game.SetbFillWithAI(isFilledWithAI); -} - - -/// Gets the number of bots per team in the game. -/// The number of bots per team -int RocketPlugin::GetNumBotsPerTeam() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 0; - } - - return game.GetNumBots(); -} - - -/// Sets if bots are auto filled in the current game. -/// Bool with if bots should be auto filled -void RocketPlugin::SetIsAutoFilledWithBots(const bool isAutoFilledWithBots) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetbFillWithAI(isAutoFilledWithBots); -} - - -/// Gets if bots are auto filled in the current game. -/// Bool with if bots are auto filled -bool RocketPlugin::GetIsAutoFilledWithBots() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return false; - } - - return game.GetbFillWithAI(); -} - - -/// Sets if teams are unfair in the current game. -/// Bool with if teams should be unfair -void RocketPlugin::SetIsUnfairTeams(const bool isUnfairTeams) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetbUnfairTeams(isUnfairTeams); -} - - -/// Gets if teams are unfair in the current game. -/// bool with if teams are unfair -bool RocketPlugin::GetIsUnfairTeams() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return false; - } - - return game.GetbUnfairTeams(); -} - - -/// Freezes or unfreezes all bots. -void RocketPlugin::FreezeBots() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - bool firstBot = true; - bool shouldUnFreeze = false; - for (CarWrapper car : game.GetCars()) { - if (car.IsNull() || car.GetPRI().IsNull() || !car.GetPRI().GetbBot()) { - WARNING_LOG("could not get the car"); - continue; - } - - if (firstBot) { - shouldUnFreeze = car.GetbFrozen(); - firstBot = false; - } - - if (shouldUnFreeze) { - car.SetFrozen(0); - } - else { - car.SetFrozen(1); - } - } -} - - -/* - * Ball Mods - */ - -/// Sets the number of balls in the current game. -/// The new number of balls -void RocketPlugin::SetNumBalls(const int newNumBalls) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - game.SetTotalGameBalls(newNumBalls); - - const float ballScale = GetBallsScale(); - ResetBalls(); - SetBallsScale(ballScale); -} - - -/// Gets the number of balls in the current game. -/// The number of balls -int RocketPlugin::GetNumBalls() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 0; - } - - return game.GetTotalGameBalls(); -} - - -/// Sets the scale of the balls in the current game. -/// The new scale of the balls -void RocketPlugin::SetBallsScale(float newBallsScale) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - /* The game crashes with negative ball scale */ - if (newBallsScale <= 0) { - WARNING_LOG("ball scale out of bounds"); - newBallsScale = 1.0f; - } - - game.ResetBalls(); - for (BallWrapper ball : game.GetGameBalls()) { - if (ball.IsNull()) { - WARNING_LOG("could not get the ball"); - continue; - } - - ball.SetBallScale(newBallsScale); - } -} - - -/// Gets the scale of the balls in the current game. -/// The scale of the balls -float RocketPlugin::GetBallsScale() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 1.0f; - } - - BallWrapper ball = game.GetBall(); - if (ball.IsNull()) { - return 1.0f; - } - - const float ballScale = ball.GetReplicatedBallScale(); - - return ballScale > 0 ? ballScale : 1.0f; -} - - -void RocketPlugin::SetMaxBallVelocity(const float newMaxBallVelocity) const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return; - } - - for (BallWrapper ball : game.GetGameBalls()) { - if (ball.IsNull()) { - WARNING_LOG("could not get the ball"); - continue; - } - - ball.SetMaxLinearSpeed(newMaxBallVelocity); - } -} - - -float RocketPlugin::GetMaxBallVelocity() const -{ - ServerWrapper game = GetGame(); - if (game.IsNull()) { - return 6000.0f; - } - - BallWrapper ball = game.GetBall(); - if (ball.IsNull()) { - return 6000.0f; - } - - return ball.GetMaxLinearSpeed(); -} - - -/* - * Player Mods - */ - -/// Gets the players in the current game. -/// Bool with if the output should include bots -/// Bool with if the output should only include alive players -/// List of players -std::vector RocketPlugin::GetPlayers(const bool includeBots, const bool mustBeAlive) const -{ - std::vector players; - ServerWrapper game = GetGame(); - if (game.IsNull()) { - ERROR_LOG("could not get the game"); - return players; - } - - if (mustBeAlive) { - for (CarWrapper car : game.GetCars()) { - if (car.IsNull() || car.GetPRI().IsNull() || (!includeBots && car.GetPRI().GetbBot())) { - continue; - } - - players.push_back(car.GetPRI()); - } - } - else { - for (PriWrapper pri : game.GetPRIs()) { - if (pri.IsNull() || (!includeBots && pri.GetbBot())) { - continue; - } - - players.push_back(pri); - } - } - - return players; -} - - -/// Gets the player names of the players in the current game. -/// Bool with if the output should include bots -/// Bool with if the output should only include alive players -/// List of players names -std::vector RocketPlugin::GetPlayersNames(const bool includeBots, const bool mustBeAlive) const -{ - return GetPlayersNames(GetPlayers(includeBots, mustBeAlive)); -} - - -/// Gets the player names of the given players. -/// List of players to get the names from -/// List of players names -std::vector RocketPlugin::GetPlayersNames(const std::vector& players) const -{ - std::vector playersNames; - for (PriWrapper player : players) { - playersNames.push_back(player.GetPlayerName().ToString()); - } - - return playersNames; -} - - -/// Sets if the players is admin in the current game. -/// The to update -/// Bool with if the player should be admin -void RocketPlugin::SetIsAdmin(PriWrapper player, const bool isAdmin) const -{ - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return; - } - - player.SetbMatchAdmin(isAdmin); -} - - -/// Gets if the players is admin in the current game. -/// The to check -/// Bool with if the players is admin -bool RocketPlugin::GetIsAdmin(PriWrapper player) const -{ - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return false; - } - - return player.GetbMatchAdmin(); -} - - -/// Sets if the players is hidden in the current game. -/// The to update -/// Bool with if the player should be hidden -void RocketPlugin::SetIsHidden(PriWrapper player, const bool isHidden) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - player.GetCar().SetHidden2(isHidden); - player.GetCar().SetbHiddenSelf(isHidden); -} - - -/// Gets if the players is hidden in the current game. -/// The to check -/// Bool with if the players are hidden -bool RocketPlugin::GetIsHidden(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return false; - } - - return player.GetCar().GetbHidden(); -} - - -/// Demolishes the given player. -/// The to demolish -void RocketPlugin::Demolish(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - player.GetCar().Demolish(); -} - - -/* - * Car Physics mods - */ - -RocketPlugin::CarPhysics::CarPhysics(RocketPlugin* rp, PriWrapper player) -{ - CarScale = rp->GetCarScale(player); - CarHasCollision = rp->GetbCarCollision(player); - CarIsFrozen = rp->GetCarIsFrozen(player); - TorqueRate = rp->GetTorqueRate(player); - MaxCarVelocity = rp->GetMaxCarVelocity(player); - GroundStickyForce = rp->GetGroundStickyForce(player); - WallStickyForce = rp->GetWallStickyForce(player); -} - - -/// Sets the car physics for the player. -/// Gets called on 'TAGame.Car_TA.EventVehicleSetup'. -/// The players car to set the physics of -void RocketPlugin::SetPhysics(CarWrapper car) -{ - if (gameWrapper->GetGameEventAsServer().IsNull()) { - return; - } - if (car.IsNull() || car.GetPRI().IsNull()) { - ERROR_LOG("could not get the cars pri"); - return; - } - const auto& it = carPhysics.find(car.GetPRI().GetUniqueIdWrapper().GetUID()); - if (it == carPhysics.end()) { - return; - } - - const PriWrapper player = car.GetPRI(); - const CarPhysics playerCarPhysics = it->second; - - SetCarScale(player, playerCarPhysics.CarScale); - SetbCarCollision(player, playerCarPhysics.CarHasCollision); - SetCarIsFrozen(player, playerCarPhysics.CarIsFrozen); - SetTorqueRate(player, playerCarPhysics.TorqueRate); - SetMaxCarVelocity(player, playerCarPhysics.MaxCarVelocity); - SetGroundStickyForce(player, playerCarPhysics.GroundStickyForce); - SetWallStickyForce(player, playerCarPhysics.WallStickyForce); -} - - -/// Gets the car physics for the player. -/// The player to get the car physics from -/// The car physics for the player -RocketPlugin::CarPhysics RocketPlugin::GetPhysics(PriWrapper player) -{ - if (player.IsNull()) { - ERROR_LOG("could not get the player"); - return CarPhysics(this, player); - } - - const uint64_t steamID = player.GetUniqueIdWrapper().GetUID(); - const auto& it = carPhysics.find(steamID); - if (it == carPhysics.end()) { - return CarPhysics(this, player); - } - - return it->second; -} - - -/// Gets the car physics for the player and saves them when not found. -/// The player to get the car physics from -/// The car physics for the player -RocketPlugin::CarPhysics& RocketPlugin::GetPhysicsCache(PriWrapper player) -{ - const uint64_t steamID = player.GetUniqueIdWrapper().GetUID(); - return carPhysics.try_emplace(steamID, CarPhysics(this, player)).first->second; -} - - -/// Sets the if the players car has collision in the current game. -/// the player to update the car of -/// Bool with if the players car should have collision -void RocketPlugin::SetbCarCollision(PriWrapper player, const bool carHasCollision) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - GetPhysicsCache(player).CarHasCollision = carHasCollision; - player.GetCar().SetbCollideActors(carHasCollision); -} - - -/// Gets the if the players car has collision in the current game. -/// The player to check the car of -/// Bool with if the players car has collision -bool RocketPlugin::GetbCarCollision(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return true; - } - - return player.GetCar().GetbCollideActors(); -} - - -/// Sets the players car scale in the current game. -/// The player to update the car of -/// The players car scale -/// Bool with if the car should respawn in place -void RocketPlugin::SetCarScale(PriWrapper player, const float newCarScale, const bool shouldRespawn) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - GetPhysicsCache(player).CarScale = newCarScale; - player.GetCar().SetCarScale(newCarScale); - if (shouldRespawn) { - player.GetCar().RespawnInPlace(); - } -} - - -/// Gets the players car scale in the current game. -/// The player to check the car of -/// The players car scale -float RocketPlugin::GetCarScale(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return 1.0f; - } - - const float carScale = player.GetCar().GetReplicatedCarScale(); - - return carScale > 0 ? carScale : 1.0f; -} - - -/// Sets the if the players car should be frozen in the current game. -/// The player to update the car of -/// Bool with if the players car should be frozen -void RocketPlugin::SetCarIsFrozen(PriWrapper player, const bool carIsFrozen) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - GetPhysicsCache(player).CarIsFrozen = carIsFrozen; - player.GetCar().SetFrozen(carIsFrozen); -} - - -/// Gets the if the players car is frozen in the current game. -/// The player to update the car of -/// Bool with if the players car is frozen -bool RocketPlugin::GetCarIsFrozen(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return false; - } - - return player.GetCar().GetbFrozen(); -} - - -/// Sets the players car drive torque in the current game. -/// The player to update the car of -/// The new drive torque of the players car -void RocketPlugin::SetTorqueRate(PriWrapper player, const float torqueRate) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - GetPhysicsCache(player).TorqueRate = torqueRate; - player.GetCar().GetVehicleSim().SetDriveTorque(torqueRate * 100000); -} - - -/// Gets the players car drive torque in the current game. -/// The player to check the car of -/// The drive torque of the players car -float RocketPlugin::GetTorqueRate(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return 2.88f; - } - - return player.GetCar().GetVehicleSim().GetDriveTorque() / 100000; -} - - -/// Sets the players car max velocity in the current game. -/// The player to update the car of -/// The new max velocity of the players car -void RocketPlugin::SetMaxCarVelocity(PriWrapper player, const float maxCarVelocity) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - GetPhysicsCache(player).MaxCarVelocity = maxCarVelocity; - player.GetCar().SetMaxLinearSpeed(maxCarVelocity); -} - - -/// Gets the players car max velocity in the current game. -/// the player to check the car of -/// The max velocity of the players car -float RocketPlugin::GetMaxCarVelocity(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return 2300.0f; - } - - return player.GetCar().GetMaxLinearSpeed(); -} - - -/// Gets the players car sticky force in the current game. -/// The player to get the sticky force of the car of -/// The sticky force of the players car -StickyForceData RocketPlugin::GetStickyForce(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return StickyForceData(); - } - - return player.GetCar().GetStickyForce(); -} - - -/// Sets the players car ground sticky force in the current game. -/// The player to update the car of -/// The new ground sticky force of the players car -void RocketPlugin::SetGroundStickyForce(PriWrapper player, const float groundStickyForce) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - StickyForceData sfd = GetStickyForce(player); - sfd.Ground = groundStickyForce; - - GetPhysicsCache(player).GroundStickyForce = groundStickyForce; - player.GetCar().SetStickyForce(sfd); -} - - -/// Gets the players car ground sticky force in the current game. -/// The player to check the car of -/// The ground sticky force of the players car -float RocketPlugin::GetGroundStickyForce(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return 0.5f; - } - - return player.GetCar().GetStickyForce().Ground; -} - - -/// Sets the players car wall sticky force in the current game. -/// The player to update the car of -/// The new wall sticky force of the players car -void RocketPlugin::SetWallStickyForce(PriWrapper player, const float wallStickyForce) -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return; - } - - StickyForceData sfd = GetStickyForce(player); - sfd.Wall = wallStickyForce; - - GetPhysicsCache(player).WallStickyForce = wallStickyForce; - player.GetCar().SetStickyForce(sfd); -} - - -/// Gets the players car wall sticky force in the current game. -/// The player to check the car of -/// The wall sticky force of the players car -float RocketPlugin::GetWallStickyForce(PriWrapper player) const -{ - if (player.IsNull() || player.GetCar().IsNull()) { - ERROR_LOG("could not get the players car"); - return 1.5f; - } - - return player.GetCar().GetStickyForce().Wall; -} - - -/* - * BakkesMod plugin overrides - */ - -/// Checks if the GUI window is bound. -/// Name of the GUI window -/// Bool with if the GUI window is bound -bool IsGUIWindowBound(const std::string& windowName) -{ - const std::string bind = "togglemenu " + windowName; - std::ifstream file(BINDS_FILE_PATH); - if (file.is_open()) { - std::string line; - while (getline(file, line)) { - if (line.find(bind) != std::string::npos) { - file.close(); - return true; - } - } - file.close(); - } - - return false; -} - - -/// Registers notifiers and variables to interact with the plugin on load. -void RocketPlugin::OnLoad() -{ - BakkesModConfigFolder = gameWrapper->GetBakkesModPath() / L"cfg"; - BakkesModCrashesFolder = gameWrapper->GetBakkesModPath() / L"crashes"; - if (!exists(BakkesModCrashesFolder)) { - std::filesystem::create_directory(BakkesModCrashesFolder); - } - RocketPluginDataFolder = gameWrapper->GetDataFolder() / L"RocketPlugin"; - if (!exists(RocketPluginDataFolder)) { - std::filesystem::create_directory(RocketPluginDataFolder); - } - RocketLeagueExecutableFolder = std::filesystem::current_path(); - - // Copy the original cvarManager so we can use it everywhere. - GlobalCVarManager = std::reinterpret_pointer_cast(cvarManager); - - /* Register CVars */ - joinIP = std::make_shared(); - cvarManager->registerCvar("mp_ip", "127.0.0.1", - "Default ip for joining local matches").bindTo(joinIP); - - joinPort = std::make_shared(DEFAULT_PORT); - cvarManager->registerCvar("mp_port", std::to_string(DEFAULT_PORT), - "Default port for joining local matches").bindTo(joinPort); - - presetDirPath = std::make_shared(); - cvarManager->registerCvar("rp_preset_path", PRESETS_PATH.string(), - "Default path for the mutator presets directory").bindTo(presetDirPath); - - workshopMapDirPath = std::make_shared(); - cvarManager->registerCvar("rp_workshop_path", WORKSHOP_MAPS_PATH.string(), - "Default path for your workshop maps directory").bindTo(workshopMapDirPath); - - customMapDirPath = std::make_shared(); - cvarManager->registerCvar("rp_custom_path", CUSTOM_MAPS_PATH.string(), - "Default path for your custom maps directory").bindTo(customMapDirPath); - - cvarManager->registerCvar("rp_gui_keybind", DEFAULT_GUI_KEYBIND, "Keybind for the gui"); - - LogLevel = std::make_shared(0); - cvarManager->registerCvar("rp_log_level", std::to_string(CVarManagerWrapperDebug::level_enum::normal), - "Log level", true, false, 0, false, 0, false).bindTo(LogLevel); - -#ifdef DEBUG - cvarManager->getCvar("rp_log_level").setValue(CVarManagerWrapperDebug::level_enum::all); - - showDemoWindow = std::make_shared(false); - cvarManager->registerCvar("rp_show_demo_window", "0", - "Shows the Dear ImGui demo window", true, false, 0, false, 0, false).bindTo(showDemoWindow); - - showMetricsWindow = std::make_shared(false); - cvarManager->registerCvar("rp_show_metrics_window", "0", - "Shows the Dear ImGui metrics window", true, false, 0, false, 0, false).bindTo(showMetricsWindow); -#endif - - /* Register Notifiers */ - // TODO, add command completer. - RegisterNotifier("rp", [this](const std::vector& arguments) { - parseArguments(arguments); - }, "Parses commands to interact with Rocket Plugin.", PERMISSION_ALL); - - RegisterNotifier("rp_enable_debug_mode", [this](const std::vector&) { - cvarManager->getCvar("rp_log_level").setValue(CVarManagerWrapperDebug::level_enum::all); - }, "Enables debug mode.", PERMISSION_ALL); - - RegisterNotifier("rp_change_keybind", [this](const std::vector& arguments) { - std::string key; - if (arguments.size() >= 2) { - key = arguments[1]; - } - else { - key = cvarManager->getCvar("rp_gui_keybind").getStringValue(); - } - - const std::string command = "togglemenu " + GetMenuName(); - cvarManager->setBind(key, command); - LOG("Set {} to {}", quote(key), quote(command)); - }, "Adds a keybind for " + quote("togglemenu " + GetMenuName()) + " as $rp_gui_keybind or given argument.", PERMISSION_ALL); - - RegisterNotifier("rp_broadcast_game", [this](const std::vector&) { - broadcastJoining(); - }, "Broadcasts a game invite to your party members.", PERMISSION_SOCCAR); - - RegisterNotifier("rp_add_beta_game_modes", [this](const std::vector&) { - if (GetCustomGameMode() == nullptr) { - customGameModes.push_back(std::make_shared(this)); - TRACE_LOG("added Small Cars game mode"); - } - else { - WARNING_LOG("Small Cars game mode already added"); - } - }, "Adds beta game modes.", PERMISSION_ALL); - - registerExternalNotifiers(); - - /* Register Hooks */ - HookEventWithCaller("Function TAGame.Car_TA.EventVehicleSetup", - [this](const CarWrapper& caller, void*, const std::string&) { - SetPhysics(caller); - }); + HookEventWithCaller("Function TAGame.Car_TA.EventVehicleSetup", + [this](const CarWrapper& caller, void*, const std::string&) { + carPhysicsMods.SetPhysics(caller); + }); HookEventWithCaller("Function TAGame.GameEvent_TA.Init", [this](const ServerWrapper& caller, void*, const std::string&) { onGameEventInit(caller); }); - - registerExternalHooks(); - - // Load RL Constants. - loadRLConstants(); - - // Load Constants Config. - ConstantsConfig = std::make_unique(DEFAULT_CONSTANTS_CONFIG_URL); - - /* GUI Settings */ - - // Set the window bind to the default keybind if is not set. - if (!IsGUIWindowBound(GetMenuName())) { - cvarManager->setBind(DEFAULT_GUI_KEYBIND, "togglemenu " + GetMenuName()); - LOG("Set window keybind to {}", DEFAULT_GUI_KEYBIND); - } - - // Load the custom mutator presets. - presetPaths = GetFilesFromDir(*presetDirPath, 1, ".cfg"); - - /* Init Networking */ - upnpClient = std::make_shared(); - p2pHost = std::make_shared(); - - /* Init Game Modes */ - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); - customGameModes.push_back(std::make_shared(this)); -} - - -/// Unload the plugin properly. -void RocketPlugin::OnUnload() -{ - // Save all CVars to 'config.cfg'. - cvarManager->backupCfg(CONFIG_FILE_PATH.string()); } diff --git a/source/RocketPlugin/RocketPlugin.h b/source/RocketPlugin/RocketPlugin.h index 5e8a725..10c8df6 100644 --- a/source/RocketPlugin/RocketPlugin.h +++ b/source/RocketPlugin/RocketPlugin.h @@ -2,6 +2,14 @@ #include "Version.h" #include "Networking/Networking.h" +#include "Modules/RocketPluginModule.h" +#include "Modules/GameControls.h" +#include "Modules/LocalMatchSettings.h" +#include "Modules/BotSettings.h" +#include "Modules/BallMods.h" +#include "Modules/PlayerMods.h" +#include "Modules/CarPhysicsMods.h" + constexpr const char* PLUGIN_VERSION = VER_FILE_VERSION_STR; constexpr char MARKED_INCOMPLETE = '*'; @@ -33,20 +41,9 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak friend RPConfig; friend RocketGameMode; - /* File Helpers */ -public: - static bool HasExtension(const std::string& fileExtension, const std::vector& extensions); - static std::vector IterateDirectory(const std::filesystem::path& directory, - const std::vector& extensions, - int depth = 0, int maxDepth = 3); - static std::vector GetFilesFromDir(const std::filesystem::path& directory, - int numExtension, ...); -private: - /* Map File Helpers */ public: private: - bool isMapJoinable(const std::filesystem::path& map); std::vector getWorkshopMaps(const std::filesystem::path& workshopPath, const std::vector& extensions = { ".upk", ".udk" }, const std::string& preferredExtension = ".udk"); @@ -75,10 +72,12 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak std::wstring getPlayerNickname(uint64_t uniqueId) const; void getSubscribedWorkshopMapsAsync(bool getSubscribedMaps = false); - struct WorkshopMap { + struct WorkshopMap + { std::string Title; uint64_t Owner = 0; }; + std::vector publishedFileID; // Maps workshop id to workshop info. std::unordered_map subscribedWorkshopMaps; @@ -104,6 +103,8 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak void broadcastJoining(); bool isHostingLocalGame() const; + bool isCurrentMapModded() const; + bool isMapJoinable(const std::filesystem::path& map); bool preLoadMap(const std::filesystem::path& pathName, bool overrideDupe = false, bool warnIfExists = false); void copyMap(const std::filesystem::path& map = ""); void onGameEventInit(const ServerWrapper& server); @@ -113,124 +114,50 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak std::string joiningPartyPswd; bool failedToGetMapPackageFileCache = false; - /* Game Controls */ + /* Modules */ public: - bool IsInGame(bool allowOnlineGame = false) const; ServerWrapper GetGame(bool allowOnlineGame = false) const; - void ForceOvertime() const; - void PauseServer() const; - void ResetMatch() const; - void EndMatch() const; - void ResetPlayers() const; - void ResetBalls() const; -private: - - /* Match Settings */ -public: - void SetMaxPlayers(int newNumPlayers) const; - int GetMaxPlayers() const; - void SetMaxTeamSize(int newTeamSize) const; - int GetMaxTeamSize() const; - void SetRespawnTime(int newRespawnTime) const; - int GetRespawnTime() const; - void SetScore(int team, int newScore) const; - int GetScore(int team) const; - void SetScoreBlue(int newScore) const; - int GetScoreBlue() const; - void SetScoreOrange(int newScore) const; - int GetScoreOrange() const; - void SetGameTimeRemaining(int newGameTimeRemaining) const; - int GetGameTimeRemaining() const; - void SetIsGoalDelayDisabled(bool isGoalDelayDisabled) const; - bool GetIsGoalDelayDisabled() const; - void SetIsUnlimitedTime(bool isUnlimitedTime) const; - bool GetIsUnlimitedTime() const; -private: + bool IsInGame(bool allowOnlineGame = false) const; - /* Bots */ -public: - void SetMaxNumBots(bool newMaxNumBots) const; - int GetMaxNumBots() const; - void SetNumBotsPerTeam(int newNumBotsPerTeam) const; - int GetNumBotsPerTeam() const; - void SetIsAutoFilledWithBots(bool isAutoFilledWithBots) const; - bool GetIsAutoFilledWithBots() const; - void SetIsUnfairTeams(bool isUnfairTeams) const; - bool GetIsUnfairTeams() const; - void FreezeBots() const; + GameControls gameControls; + LocalMatchSettings matchSettings; + BotSettings botSettings; + BallMods ballMods; + PlayerMods playerMods; + CarPhysicsMods carPhysicsMods; private: - /* Ball Mods */ + /* BakkesMod Plugin Overrides */ public: - void SetNumBalls(int newNumBalls) const; - int GetNumBalls() const; - void SetBallsScale(float newBallsScale) const; - float GetBallsScale() const; - void SetMaxBallVelocity(float newMaxBallVelocity) const; - float GetMaxBallVelocity() const; -private: + CATCH_DEFAULT_BM_FUNCTIONS; - /* Player Mods */ -public: - std::vector GetPlayers(bool includeBots = false, bool mustBeAlive = false) const; - std::vector GetPlayersNames(bool includeBots = false, bool mustBeAlive = false) const; - std::vector GetPlayersNames(const std::vector& players) const; - void SetIsAdmin(PriWrapper player, bool isAdmin) const; - bool GetIsAdmin(PriWrapper player) const; - void SetIsHidden(PriWrapper player, bool isHidden) const; - bool GetIsHidden(PriWrapper player) const; - void Demolish(PriWrapper player) const; -private: + void UnhookEvent(const std::string& eventName) const + { + gameWrapper->UnhookEvent(eventName); + } - /* Car Physics mods */ -public: - struct CarPhysics { - CarPhysics(RocketPlugin* rp, PriWrapper player); - - float CarScale; - bool CarHasCollision; - bool CarIsFrozen; - float TorqueRate; - float MaxCarVelocity; - float GroundStickyForce; - float WallStickyForce; - }; - void SetPhysics(CarWrapper car); - CarPhysics GetPhysics(PriWrapper player); - CarPhysics& GetPhysicsCache(PriWrapper player); - void SetbCarCollision(PriWrapper player, bool carHasCollision); - bool GetbCarCollision(PriWrapper player) const; - void SetCarScale(PriWrapper player, float newCarScale, bool shouldRespawn = false); - float GetCarScale(PriWrapper player) const; - void SetCarIsFrozen(PriWrapper player, bool carIsFrozen); - bool GetCarIsFrozen(PriWrapper player) const; - void SetTorqueRate(PriWrapper player, float torqueRate); - float GetTorqueRate(PriWrapper player) const; - void SetMaxCarVelocity(PriWrapper player, float maxCarVelocity); - float GetMaxCarVelocity(PriWrapper player) const; - StickyForceData GetStickyForce(PriWrapper player) const; - void SetGroundStickyForce(PriWrapper player, float groundStickyForce); - float GetGroundStickyForce(PriWrapper player) const; - void SetWallStickyForce(PriWrapper player, float wallStickyForce); - float GetWallStickyForce(PriWrapper player) const; -private: + void UnhookEventPost(const std::string& eventName) const + { + gameWrapper->UnhookEventPost(eventName); + } - /* BakkesMod Plugin Overrides */ -public: - CATCH_DEFAULT_BM_FUNCTIONS; private: + void registerCVars(); + void registerNotifiers(); + void registerHooks(); + void registerExternalCVars(); void registerExternalNotifiers(); void registerExternalHooks(); /* * Rocket Game Mode functions, implementation is in RocketGameMode.h. */ - /* Rocket Game Mode Hooks */ + /* Rocket Game Mode Hooks */ public: protected: - typedef std::function Event; - std::unordered_map> callbacksPre; - std::unordered_map> callbacksPost; + using EventCallback = std::function; + std::unordered_map> callbacksPre; + std::unordered_map> callbacksPost; private: /* @@ -265,18 +192,21 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak void PushError(const std::string& message); private: - void renderMultiplayerTab(); + void refreshGameSettingsConstants(); bool renderCustomMapsSelection(std::map& customMaps, - std::filesystem::path& currentCustomMap, bool& refreshCustomMaps, - bool includeWorkshopMaps = true, bool includeCustomMaps = true); + std::filesystem::path& currentCustomMap, bool& refreshCustomMaps, bool includeWorkshopMaps = true, + bool includeCustomMaps = true); + + void renderMultiplayerTab(); std::queue errors; - bool refreshGameSettingsConstants = true; + bool shouldRefreshGameSettingsConstants = true; std::future> gameSettingsRequest; /* Host Settings */ public: - struct GameSetting { + struct GameSetting + { std::string DisplayCategoryName; std::string InternalCategoryName; size_t CurrentSelected = 0; @@ -289,8 +219,13 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak private: void renderMultiplayerTabHost(); + void renderMultiplayerTabHostTeamSettings(); + void renderMultiplayerTabHostMutatorSettings(); + void renderMultiplayerTabHostAdvancedSettings(); + void renderMultiplayerTabHostAdvancedSettingsUPnPSettings(); + void renderMultiplayerTabHostAdvancedSettingsP2PSettings(); + void loadRLConstants(); - bool isCurrentMapModded() const; bool hostingGame = false; bool shouldInviteParty = false; @@ -371,18 +306,17 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak char IP[64]; bool InvalidIP; }; + std::vector connections; /* In Game Mods */ public: private: void renderInGameModsTab(); - - /* Car Physics Mods */ -public: -private: - size_t selectedPlayer = 0; - std::unordered_map carPhysics; + void renderInGameModsTabGameEventMods(); + void renderInGameModsTabBallMods(); + void renderInGameModsTabPlayerMods(); + void renderInGameModsTabCarPhysicsMods(); /* Game Modes */ public: @@ -397,6 +331,7 @@ class RocketPlugin final : public BakkesMod::Plugin::BakkesModPlugin, public Bak return std::shared_ptr(); } + private: void renderGameModesTab(); diff --git a/source/RocketPlugin/RocketPlugin.rc b/source/RocketPlugin/RocketPlugin.rc index b70a2f8..b616805 100644 --- a/source/RocketPlugin/RocketPlugin.rc +++ b/source/RocketPlugin/RocketPlugin.rc @@ -1,96 +1,96 @@ -// Microsoft Visual C++ generated resource script. -// -#include "Resource.h" -#include "Version.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VER_FILE_VERSION - PRODUCTVERSION VER_PRODUCT_VERSION - FILEFLAGSMASK 0x3fL - FILEFLAGS VER_FILEFLAGS - FILEOS VER_FILEOS - FILETYPE VER_FILETYPE - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", VER_FILE_DESCRIPTION_STR "\0" - VALUE "FileVersion", VER_FILE_VERSION_STR "\0" - VALUE "InternalName", VER_INTERNAL_NAME_STR "\0" - VALUE "LegalCopyright", VER_COPYRIGHT_STR "\0" - VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR "\0" - VALUE "ProductName", VER_PRODUCTNAME_STR "\0" - VALUE "ProductVersion", VER_PRODUCT_VERSION_STR "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +// Microsoft Visual C++ generated resource script. +// +#include "Resource.h" +#include "Version.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VER_FILE_VERSION + PRODUCTVERSION VER_PRODUCT_VERSION + FILEFLAGSMASK 0x3fL + FILEFLAGS VER_FILEFLAGS + FILEOS VER_FILEOS + FILETYPE VER_FILETYPE + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", VER_FILE_DESCRIPTION_STR "\0" + VALUE "FileVersion", VER_FILE_VERSION_STR "\0" + VALUE "InternalName", VER_INTERNAL_NAME_STR "\0" + VALUE "LegalCopyright", VER_COPYRIGHT_STR "\0" + VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR "\0" + VALUE "ProductName", VER_PRODUCTNAME_STR "\0" + VALUE "ProductVersion", VER_PRODUCT_VERSION_STR "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/source/RocketPlugin/RocketPlugin.vcxproj b/source/RocketPlugin/RocketPlugin.vcxproj index ba1ea67..2fc2246 100644 --- a/source/RocketPlugin/RocketPlugin.vcxproj +++ b/source/RocketPlugin/RocketPlugin.vcxproj @@ -1,200 +1,202 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {05FDC018-B60A-4983-AA81-E030820D81BD} - RocketPlugin - 10.0 - - - - DynamicLibrary - false - v142 - true - MultiByte - x64 - - - DynamicLibrary - false - v142 - true - MultiByte - x64 - - - - - - - - - - - - - - - true - $(SolutionDir)Build\$(Platform)\$(Configuration)\ - Build\$(Platform)\$(Configuration)\ - - - true - Build\$(Platform)\$(Configuration)\ - $(SolutionDir)Build\$(Platform)\$(Configuration)\ - - - - Level3 - MaxSpeed - true - true - true - true - stdcpp17 - true - .\;..\External;..\External\BakkesModSDK\include;..\External\BakkesModAdditions\include;..\External\fmt\include;..\External\simdjson\singleheader;%(AdditionalIncludeDirectories) - DEBUG;%(PreprocessorDefinitions) - MultiThreaded - true - Use - pch.h - pch.h - Async - Default - stdc17 - - - true - true - ..\External\BakkesModSDK\lib;%(AdditionalLibraryDirectories) - - - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - stdcpp17 - true - .\;..\External;..\External\BakkesModSDK\include;..\External\BakkesModAdditions\include;..\External\fmt\include;..\External\simdjson\singleheader;%(AdditionalIncludeDirectories) - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - true - Async - stdc17 - Use - pch.h - pch.h - - - true - true - ..\External\BakkesModSDK\lib;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - false - - - - - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {05FDC018-B60A-4983-AA81-E030820D81BD} + RocketPlugin + 10.0 + + + + DynamicLibrary + false + v142 + true + MultiByte + x64 + + + DynamicLibrary + false + v142 + true + MultiByte + x64 + + + + + + + + + + + + + + + true + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + Build\$(Platform)\$(Configuration)\ + + + true + Build\$(Platform)\$(Configuration)\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + + + + Level3 + MaxSpeed + true + true + true + true + stdcpp20 + true + .\;..\External;..\External\BakkesModAdditions\include;..\External\BakkesModSDK\include;..\External\fmt\include;..\External\simdjson\singleheader;%(AdditionalIncludeDirectories) + DEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + Use + pch.h + pch.h + Async + Default + stdc17 + + + true + true + ..\External\BakkesModSDK\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + true + true + stdcpp20 + true + .\;..\External;..\External\BakkesModAdditions\include;..\External\BakkesModSDK\include;..\External\fmt\include;..\External\simdjson\singleheader;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + Async + stdc17 + Use + pch.h + pch.h + + + true + true + ..\External\BakkesModSDK\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/RocketPlugin/RocketPlugin.vcxproj.filters b/source/RocketPlugin/RocketPlugin.vcxproj.filters index 19c7996..28a995f 100644 --- a/source/RocketPlugin/RocketPlugin.vcxproj.filters +++ b/source/RocketPlugin/RocketPlugin.vcxproj.filters @@ -1,214 +1,277 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {18597224-b2ec-4033-901e-1ac0c4df7a77} - - - {99c4a39a-24ec-488b-b1aa-7a4af0df294f} - - - {660cd77f-189d-4380-bb3a-ed560006e353} - - - - - Header Files - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Header Files - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Header Files - - - Header Files - - - Resource Files\GameModes - - - Header Files - - - Header Files - - - Resource Files\GameModes - - - Header Files - - - Resource Files\GameModes - - - Header Files - - - Resource Files\GameModes - - - Resource Files\SIMDJson - - - - - Source Files - - - Source Files - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Source Files - - - Source Files - - - Source Files - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\ImGui - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Resource Files\GameModes - - - Source Files - - - Resource Files\GameModes - - - Source Files - - - Resource Files\GameModes - - - Source Files - - - Resource Files\GameModes - - - Source Files - - - Resource Files\GameModes - - - Resource Files\SIMDJson - - - - - Resource Files - - - Resource Files - - - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {99c4a39a-24ec-488b-b1aa-7a4af0df294f} + + + {fddcbd17-7c2c-4237-b38a-145c2936862e} + + + {f2bc8813-2b8f-441c-b0f6-9a74ca560ba9} + + + {18597224-b2ec-4033-901e-1ac0c4df7a77} + + + {660cd77f-189d-4380-bb3a-ed560006e353} + + + {affac30f-0cca-428c-8bf7-f2f2df4dffa9} + + + {dc472eda-eece-4a76-b01a-f757bf1d82a9} + + + + + Header Files + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + Header Files + + + GameModes + + + GameModes + + + Header Files + + + GameModes + + + Header Files + + + GameModes + + + Modules + + + Resource Files + + + GameModes + + + Networking + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + GameModes + + + External Modules + + + External\SIMDJson + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + + + Source Files + + + Source Files + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + GameModes + + + Source Files + + + GameModes + + + Source Files + + + GameModes + + + Modules + + + GameModes + + + Networking + + + Networking + + + Networking + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + Modules + + + External Modules + + + External\SIMDJson + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External\ImGui + + + External Modules + + + External Modules + + + + + Resource Files + + + Resource Files + + + + + Resource Files + + \ No newline at end of file diff --git a/source/RocketPlugin/RocketPluginGUI.cpp b/source/RocketPlugin/RocketPluginGUI.cpp index 0085e90..c7f8c06 100644 --- a/source/RocketPlugin/RocketPluginGUI.cpp +++ b/source/RocketPlugin/RocketPluginGUI.cpp @@ -1,11 +1,11 @@ // RocketPluginGUI.cpp -// GUI for the RocketPlugin plugin. +// GUI for Rocket Plugin. // // Author: Stanbroek -// Version: 0.6.6 16/04/21 +// Version: 0.6.8 18/09/21 // BMSDK version: 95 -#include "Config.h" +#include "RPConfig.h" #include "RocketPlugin.h" #include "GameModes/RocketGameMode.h" @@ -23,28 +23,9 @@ /// ImGui widgets to rendered every tick. void RocketPlugin::OnRender() { - if (refreshGameSettingsConstants) { - if (!gameSettingsRequest.valid()) { - gameSettingsRequest = ConstantsConfig->RequestGameSettingConstants(); - } - else if (gameSettingsRequest._Is_ready()) { - refreshGameSettingsConstants = false; - const auto& [successful, data] = gameSettingsRequest.get(); - if (!successful || !RPConfig::ParseGameSettings(data, this)) { - Execute([this](GameWrapper*) { - WARNING_LOG("could not load game settings"); - loadRLConstants(); - }); - } -#ifdef DEBUG - else { - Execute([this](GameWrapper*) { - TRACE_LOG("loading game settings from game files."); - loadRLConstants(); - }); - } -#endif - } + set_render_thread_once(); + if (shouldRefreshGameSettingsConstants) { + refreshGameSettingsConstants(); } #ifdef DEBUG @@ -58,8 +39,8 @@ void RocketPlugin::OnRender() #endif ImGui::SetNextWindowSizeConstraints(ImVec2(800, 600), ImVec2(FLT_MAX, FLT_MAX)); - if (ImGui::Begin(menuTitle.c_str(), &isWindowOpen)) { - if (ImGui::BeginTabBar("#TabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_NoTooltip)) { + if (ImGui::Begin((menuTitle + "###RocketPlugin").c_str(), &isWindowOpen)) { + if (ImGui::BeginTabBar("#RPTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton | ImGuiTabBarFlags_NoTooltip)) { renderMultiplayerTab(); renderInGameModsTab(); renderGameModesTab(); @@ -93,8 +74,7 @@ std::string RocketPlugin::GetMenuTitle() /// Sets the ImGui context. void RocketPlugin::SetImGuiContext(const uintptr_t ctx) { - ImGuiContext* context = reinterpret_cast(ctx); - ImGui::SetCurrentContext(context); + ImGui::SetCurrentContext(reinterpret_cast(ctx)); } @@ -134,28 +114,38 @@ void RocketPlugin::OnClose() * General settings */ -/// Pushes an error message to be displayed in the GUI. -/// Message to be displayed in the GUI -void RocketPlugin::PushError(const std::string& message) +/// Refreshes game settings constants. +void RocketPlugin::refreshGameSettingsConstants() { - errors.push(message); + if (!gameSettingsRequest.valid()) { + gameSettingsRequest = ConstantsConfig->RequestGameSettingConstants(); + } + else if (gameSettingsRequest._Is_ready()) { + shouldRefreshGameSettingsConstants = false; + const auto& [successful, data] = gameSettingsRequest.get(); + if (!successful || !RPConfig::ParseGameSettings(data, this)) { + Execute([this](GameWrapper*) { + BM_WARNING_LOG("could not load game settings"); + loadRLConstants(); + }); + } +#ifdef DEBUG + else { + Execute([this](GameWrapper*) { + BM_TRACE_LOG("loading game settings from game files."); + loadRLConstants(); + }); + } +#endif + } } -/// Renders the multiplayer tab. -void RocketPlugin::renderMultiplayerTab() +/// Pushes an error message to be displayed in the GUI. +/// Message to be displayed in the GUI +void RocketPlugin::PushError(const std::string& message) { - if (ImGui::BeginTabItem("Multiplayer")) { - if (!errors.empty()) { - if (ImGui::Banner(errors.front().c_str(), IM_COL32_ERROR_BANNER)) { - errors.pop(); - } - } - renderMultiplayerTabHost(); - ImGui::SameLine(); - renderMultiplayerTabJoin(); - ImGui::EndTabItem(); - } + errors.push(message); } @@ -167,8 +157,8 @@ void RocketPlugin::renderMultiplayerTab() /// Bool with if to include maps from the custom maps directory, default to true /// Bool with if a custom map was selected bool RocketPlugin::renderCustomMapsSelection(std::map& customMaps, - std::filesystem::path& currentCustomMap, bool& refreshCustomMaps, - const bool includeWorkshopMaps, const bool includeCustomMaps) + std::filesystem::path& currentCustomMap, bool& refreshCustomMaps, const bool includeWorkshopMaps, + const bool includeCustomMaps) { if (refreshCustomMaps) { customMaps.clear(); @@ -178,12 +168,12 @@ bool RocketPlugin::renderCustomMapsSelection(std::mapsecond.Title.empty()) { customMaps.insert({ workshopMap, it->second.Title }); } else { - customMaps.insert({ workshopMap, workshopMap.stem().u8string() }); + customMaps.insert({ workshopMap, workshopMap.stem().string() }); } } if (!addedWorkshopMaps) { @@ -193,15 +183,15 @@ bool RocketPlugin::renderCustomMapsSelection(std::mapsecond.Title.empty()) { customMaps.insert({ customMap, it->second.Title }); } else { - customMaps.insert({ customMap, customMap.stem().u8string() }); + customMaps.insert({ customMap, customMap.stem().string() }); } } if (!addedCustomMaps) { @@ -209,9 +199,9 @@ bool RocketPlugin::renderCustomMapsSelection(std::mapRenders the multiplayer tab. +void RocketPlugin::renderMultiplayerTab() +{ + if (ImGui::BeginTabItem("Multiplayer")) { + if (!errors.empty()) { + if (ImGui::Banner(errors.front().c_str(), IM_COL32_ERROR_BANNER)) { + errors.pop(); + } + } + renderMultiplayerTabHost(); + ImGui::SameLine(); + renderMultiplayerTabJoin(); + ImGui::EndTabItem(); + } +} + + /* * Host settings */ @@ -239,7 +246,9 @@ bool RocketPlugin::renderCustomMapsSelection(std::mapRenders the host section in game multiplayer tab. void RocketPlugin::renderMultiplayerTabHost() { - if (ImGui::BeginChild("#HostGame", ImVec2(-ImGui::GetFrameWidthWithSpacing() * 6, -ImGui::GetFrameHeightWithSpacing() + 23), true)) { + const ImVec2 hostGameTabSize = { -ImGui::GetFrameWidthWithSpacing() * 6, + -ImGui::GetFrameHeightWithSpacing() + 23 }; + if (ImGui::BeginChild("#HostGame", hostGameTabSize, true)) { ImGui::Indent(5); ImGui::Spacing(); @@ -267,7 +276,7 @@ void RocketPlugin::renderMultiplayerTabHost() ImGui::BeginWarnBorder(); } if (ImGui::SearchableCombo("##Maps", currentMap, maps, "No maps found", "type to search")) { - gameWrapper->Execute([this](GameWrapper*) { + Execute([this](GameWrapper*) { currentMapIsModded = isCurrentMapModded(); }); } @@ -280,15 +289,16 @@ void RocketPlugin::renderMultiplayerTabHost() } else { std::filesystem::path currentMapPath = currentMap; - if (renderCustomMapsSelection(customMapPaths, currentMapPath, refreshCustomMapPaths, enableWorkshopMaps, enableCustomMaps)) { + if (renderCustomMapsSelection(customMapPaths, currentMapPath, refreshCustomMapPaths, enableWorkshopMaps, + enableCustomMaps)) { currentMap = currentMapPath.string(); const std::filesystem::path config = currentMapPath.replace_extension(L".cfg"); if (exists(config)) { - TRACE_LOG("loading map config"); + BM_TRACE_LOG("loading map config"); loadPreset(config.string()); } else { - TRACE_LOG("could not find map config"); + BM_TRACE_LOG("could not find map config"); } } } @@ -298,412 +308,467 @@ void RocketPlugin::renderMultiplayerTabHost() } ImGui::TextUnformatted(" Bot Difficulty:"); ImGui::SliderArray("##BotDifficulty", &botDifficulties.CurrentSelected, botDifficulties.DisplayName); - if (ImGui::CollapsingHeader("Team Settings")) { - ImGui::TextUnformatted("Team 1"); - ImGui::BeginColumns("Team 1", 2, ImGuiColumnsFlags_NoBorder); - { - ImGui::SetColumnWidth(0, 100); - ImGui::SetCursorPosX(32); - ImGui::TextUnformatted("Team Name:"); - ImGui::NextColumn(); - - ImGui::SetNextItemWidth(100); - ImGui::InputTextWithHint("##Team1Name", "BLUE", &team1Name, ImGuiInputTextFlags_CharsUppercase); - ImGui::NextColumn(); - - ImGui::SetCursorPosX(20); - ImGui::TextUnformatted("Primary Color:"); - ImGui::NextColumn(); - - ImGui::RLColorPicker("##Team1PrimaryColor", &team1PrimCol, clubColors, clubColorHues, defaultBluePrimaryColor, ImVec2(100, 0)); - ImGui::NextColumn(); - - ImGui::SetCursorPosX(28); - ImGui::TextUnformatted("Accent Color:"); - ImGui::NextColumn(); + renderMultiplayerTabHostTeamSettings(); + renderMultiplayerTabHostMutatorSettings(); + renderMultiplayerTabHostAdvancedSettings(); + ImGui::Separator(); - ImGui::RLColorPicker("##Team1AccentColor", &team1AccCol, customColors, customColorHues, defaultBlueAccentColor, ImVec2(100, 0)); + if (isHostingLocalGame()) { + if (ImGui::Button("Host New Match")) { + Execute([this](GameWrapper*) { + HostGame(); + }); } - ImGui::EndColumns(); - ImGui::TextUnformatted("Team 2"); - ImGui::BeginColumns("Team 2", 2, ImGuiColumnsFlags_NoBorder); - { - ImGui::SetColumnWidth(0, 100); - ImGui::SetCursorPosX(32); - ImGui::TextUnformatted("Team Name:"); - ImGui::NextColumn(); + ImGui::SameLine(); + if (ImGui::Button("Update Match Settings")) { + Execute([this](GameWrapper*) { + if (enableWorkshopMaps || enableCustomMaps) { + const std::filesystem::path map = currentMap; + preLoadMap(absolute(map)); + setMatchSettings(map.stem().string()); + } + else { + setMatchSettings(currentMap); + } + BM_TRACE_LOG("updated match settings"); + }); + } + } + else { + if (ImGui::Button("Host")) { + Execute([this](GameWrapper*) { + HostGame(); + }); + } + } + } + ImGui::EndChild(); +} - ImGui::SetNextItemWidth(100); - ImGui::InputTextWithHint("##Team2Name", "ORANGE", &team2Name, ImGuiInputTextFlags_CharsUppercase); - ImGui::NextColumn(); - ImGui::SetCursorPosX(20); - ImGui::TextUnformatted("Primary Color:"); - ImGui::NextColumn(); +/// Renders the team settings in the host section in game multiplayer tab. +void RocketPlugin::renderMultiplayerTabHostTeamSettings() +{ + if (ImGui::CollapsingHeader("Team Settings")) { + ImGui::TextUnformatted("Team 1"); + ImGui::BeginColumns("Team 1", 2, ImGuiColumnsFlags_NoBorder); + { + ImGui::SetColumnWidth(0, 100); + ImGui::SetCursorPosX(32); + ImGui::TextUnformatted("Team Name:"); + ImGui::NextColumn(); + + ImGui::SetNextItemWidth(100); + ImGui::InputTextWithHint("##Team1Name", "BLUE", &team1Name, ImGuiInputTextFlags_CharsUppercase); + ImGui::NextColumn(); + + ImGui::SetCursorPosX(20); + ImGui::TextUnformatted("Primary Color:"); + ImGui::NextColumn(); + + ImGui::RLColorPicker("##Team1PrimaryColor", &team1PrimCol, clubColors, clubColorHues, + defaultBluePrimaryColor, ImVec2(100, 0)); + ImGui::NextColumn(); + + ImGui::SetCursorPosX(28); + ImGui::TextUnformatted("Accent Color:"); + ImGui::NextColumn(); + + ImGui::RLColorPicker("##Team1AccentColor", &team1AccCol, customColors, customColorHues, + defaultBlueAccentColor, ImVec2(100, 0)); + } + ImGui::EndColumns(); + ImGui::TextUnformatted("Team 2"); + ImGui::BeginColumns("Team 2", 2, ImGuiColumnsFlags_NoBorder); + { + ImGui::SetColumnWidth(0, 100); + ImGui::SetCursorPosX(32); + ImGui::TextUnformatted("Team Name:"); + ImGui::NextColumn(); + + ImGui::SetNextItemWidth(100); + ImGui::InputTextWithHint("##Team2Name", "ORANGE", &team2Name, ImGuiInputTextFlags_CharsUppercase); + ImGui::NextColumn(); + + ImGui::SetCursorPosX(20); + ImGui::TextUnformatted("Primary Color:"); + ImGui::NextColumn(); + + ImGui::RLColorPicker("##Team2PrimaryColor", &team2PrimCol, clubColors, clubColorHues, + defaultOrangePrimaryColor, ImVec2(100, 0)); + ImGui::NextColumn(); + + ImGui::SetCursorPosX(28); + ImGui::TextUnformatted("Accent Color:"); + ImGui::NextColumn(); + + ImGui::RLColorPicker("##Team2AccentColor", &team2AccCol, customColors, customColorHues, + defaultOrangeAccentColor, ImVec2(100, 0)); + } + ImGui::EndColumns(); + ImGui::Checkbox("Club Match", &clubMatch); + } +} - ImGui::RLColorPicker("##Team2PrimaryColor", &team2PrimCol, clubColors, clubColorHues, defaultOrangePrimaryColor, ImVec2(100, 0)); - ImGui::NextColumn(); - ImGui::SetCursorPosX(28); - ImGui::TextUnformatted("Accent Color:"); - ImGui::NextColumn(); +/// Renders the mutator settings in the host section in game multiplayer tab. +void RocketPlugin::renderMultiplayerTabHostMutatorSettings() +{ + if (ImGui::CollapsingHeader("Mutators Settings")) { + const ImVec2 MutatorsSettingsWindowSize = { -ImGui::GetFrameWidthWithSpacing() * 4, + static_cast(mutators.size()) * 23.f }; + if (ImGui::BeginChild("#MutatorsSettings", MutatorsSettingsWindowSize, false, ImGuiWindowFlags_NoScrollbar)) { + ImGui::BeginColumns("Mutators", 2, ImGuiColumnsFlags_NoBorder); + { + static float columnWidth = 125; + ImGui::SetColumnWidth(0, columnWidth + ImGui::GetStyle().ItemSpacing.x); + float maxColumnWidth = 0; + for (GameSetting& mutator : mutators) { + const std::string displayName = mutator.DisplayCategoryName + ":"; + const ImVec2 size = ImGui::CalcTextSize(displayName.c_str()); + if (size.x > maxColumnWidth) { + maxColumnWidth = size.x; + } + ImGui::SetCursorPosX(columnWidth - size.x + ImGui::GetStyle().ItemSpacing.x); + ImGui::TextUnformatted(displayName.c_str()); + ImGui::NextColumn(); - ImGui::RLColorPicker("##Team2AccentColor", &team2AccCol, customColors, customColorHues, defaultOrangeAccentColor, ImVec2(100, 0)); + const std::string label = "##" + mutator.InternalCategoryName; + ImGui::PushItemWidth(ImGui::GetWindowWidth() / 3 * 2); + ImGui::SliderArray(label.c_str(), &mutator.CurrentSelected, mutator.DisplayName); + ImGui::NextColumn(); + } + if (maxColumnWidth > columnWidth) { + columnWidth = maxColumnWidth; + } } ImGui::EndColumns(); - ImGui::Checkbox("Club Match", &clubMatch); } - if (ImGui::CollapsingHeader("Mutators Settings")) { - if (ImGui::BeginChild("#MutatorsSettings", ImVec2(-ImGui::GetFrameWidthWithSpacing() * 4, static_cast(mutators.size()) * 23.f), false, ImGuiWindowFlags_NoScrollbar)) { - ImGui::BeginColumns("Mutators", 2, ImGuiColumnsFlags_NoBorder); - { - static float columnWidth = 125; - ImGui::SetColumnWidth(0, columnWidth + ImGui::GetStyle().ItemSpacing.x); - float maxColumnWidth = 0; - for (GameSetting& mutator : mutators) { - const std::string displayName = std::string(mutator.DisplayCategoryName) + ":"; - const ImVec2 size = ImGui::CalcTextSize(displayName.c_str()); - if (size.x > maxColumnWidth) { - maxColumnWidth = size.x; - } - ImGui::SetCursorPosX(columnWidth - size.x + ImGui::GetStyle().ItemSpacing.x); - ImGui::TextUnformatted(displayName.c_str()); - ImGui::NextColumn(); - - const std::string label = "##" + mutator.InternalCategoryName; - ImGui::PushItemWidth(ImGui::GetWindowWidth() / 3 * 2); - ImGui::SliderArray(label.c_str(), &mutator.CurrentSelected, mutator.DisplayName); - ImGui::NextColumn(); - } - if (maxColumnWidth > columnWidth) { - columnWidth = maxColumnWidth; - } - } - ImGui::EndColumns(); - } - ImGui::EndChild(); - ImGui::SameLine(); - if (ImGui::BeginChild("#MutatorsPresets", ImVec2(0.f, static_cast(mutators.size()) * 23.f))) { - ImGui::TextUnformatted(" Presets:"); - ImGui::Separator(); + ImGui::EndChild(); + ImGui::SameLine(); + if (ImGui::BeginChild("#MutatorsPresets", ImVec2(0.f, static_cast(mutators.size()) * 23.f))) { + ImGui::TextUnformatted(" Presets:"); + ImGui::Separator(); - if (ImGui::Button("Default", ImVec2(-5, 0))) { - resetMutators(); - } - for (const std::filesystem::path& presetPath : presetPaths) { - std::string filename = presetPath.filename().string(); - if (ImGui::Button(filename.substr(0, filename.size() - 4).c_str(), ImVec2(-5, 0))) { + if (ImGui::Button("Default", ImVec2(-5, 0))) { + resetMutators(); + } + for (const std::filesystem::path& presetPath : presetPaths) { + std::string filename = presetPath.stem().string(); + if (ImGui::Button(filename.c_str(), ImVec2(-5, 0))) { + Execute([this, presetPath](GameWrapper*) { loadPreset(presetPath); - } - } - if (presetPaths.empty()) { - ImGui::PushItemWidth(-5); - ImGui::TextUnformatted("No presets found."); + }); } - ImGui::Separator(); + } + if (presetPaths.empty()) { + ImGui::PushItemWidth(-5); + ImGui::TextUnformatted("No presets found."); + } + ImGui::Separator(); - if (ImGui::Button("Save preset")) { - ImGui::OpenPopup("Save preset as"); + if (ImGui::Button("Save preset")) { + ImGui::OpenPopup("Save preset as"); + } + if (ImGui::BeginPopup("Save preset as")) { + static char nameBuf[16] = ""; + ImGui::InputText(".cfg", nameBuf, 16); + if (ImGui::Button("Save")) { + savePreset(fmt::format("{:s}.cfg", nameBuf)); + presetPaths = get_files_from_dir(*presetDirPath, 2, ".cfg"); + ImGui::CloseCurrentPopup(); } - if (ImGui::BeginPopup("Save preset as")) { - static char nameBuf[16] = ""; - ImGui::InputText(".cfg", nameBuf, 16); - if (ImGui::Button("Save")) { - savePreset(std::string(nameBuf) + ".cfg"); - presetPaths = GetFilesFromDir(*presetDirPath, 1, ".cfg"); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button("Cancel")) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); + ImGui::SameLine(); + if (ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); } + ImGui::EndPopup(); } - ImGui::EndChild(); } - if (ImGui::CollapsingHeader("Advanced Settings")) { - ImGui::TextUnformatted(" Password: (optional)"); - ImGui::InputText("##pswd_host", &hostPswd, ImGuiInputTextFlags_Password); - ImGui::TextUnformatted((" Internal host port: (default is " + std::to_string(DEFAULT_PORT) + ")").c_str()); - // TODO, Allow changing the internal host port. - ImGui::BeginDisabled(); - const bool invalidHostPortInternal = !Networking::IsValidPort(hostPortInternal); - if (invalidHostPortInternal) { - ImGui::BeginErrorBorder(); - ImGui::InputScalar("##HostPortInternal", ImGuiDataType_U16, &hostPortInternal); - ImGui::EndErrorBorder(); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Invalid port"); - } + ImGui::EndChild(); + } +} + + +/// Renders the advanced settings in the host section in game multiplayer tab. +void RocketPlugin::renderMultiplayerTabHostAdvancedSettings() +{ + if (ImGui::CollapsingHeader("Advanced Settings")) { + ImGui::TextUnformatted(" Password: (optional)"); + ImGui::InputText("##pswd_host", &hostPswd, ImGuiInputTextFlags_Password); + ImGui::TextUnformatted(fmt::format(" Internal host port: (default is {:d})", DEFAULT_PORT).c_str()); + // TODO, Allow changing the internal host port. + ImGui::BeginDisabled(); + const bool invalidHostPortInternal = !Networking::IsValidPort(hostPortInternal); + if (invalidHostPortInternal) { + ImGui::BeginErrorBorder(); + ImGui::InputScalar("##HostPortInternal", ImGuiDataType_U16, &hostPortInternal); + ImGui::EndErrorBorder(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Invalid port"); + } + } + else { + ImGui::InputScalar("##HostPortInternal", ImGuiDataType_U16, &hostPortInternal); + } + ImGui::EndDisabled(); + ImGui::TextUnformatted(" Network options:"); + ImGui::Indent(4); + renderMultiplayerTabHostAdvancedSettingsUPnPSettings(); + renderMultiplayerTabHostAdvancedSettingsP2PSettings(); + ImGui::Unindent(4); + ImGui::Checkbox("Host game with party", &hostWithParty); + ImGui::SameLine(); + ImGui::TextUnformatted("(?)"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Will send a party game invite to everyone in your party.\n" + "This only works when connecting directly to your IP."); + } + } +} + + +/// Renders the UPnP settings in the advanced settings in the host section in game multiplayer tab. +void RocketPlugin::renderMultiplayerTabHostAdvancedSettingsUPnPSettings() +{ + const bool upnpFailed = upnpClient == nullptr; + if (upnpFailed) { + // Disables the collapsing header. + ImGui::BeginDisabled(); + } + if (ImGui::CollapsingHeader("UPnP Settings")) { + ImGui::Indent(10); + ImGui::PushStyleColor(ImGuiCol_Border, static_cast(IM_COL32_WARNING)); + if (ImGui::BeginChild("##UPnPWarning", ImVec2(0, 50), true)) { + ImGui::Dummy(ImVec2(140.0f, 0.0f)); + ImGui::SameLine(); + ImGui::TextUnformatted("WARNING these are advanced settings!"); + ImGui::TextUnformatted("Using these without knowing what your are doing could put your computer and " + "network at risk."); + } + ImGui::EndChild(); + ImGui::PopStyleColor(); + if (ImGui::Button("Search for UPnP devices")) { + if (!upnpClient->DiscoverySearching()) { + Execute([this](GameWrapper*) { + upnpClient->FindDevices(); + }); } else { - ImGui::InputScalar("##HostPortInternal", ImGuiDataType_U16, &hostPortInternal); - } - ImGui::EndDisabled(); - ImGui::TextUnformatted(" Network options:"); - ImGui::Indent(4); - const bool upnpFailed = upnpClient == nullptr; - if (upnpFailed) { - // Disables the collapsing header. - ImGui::BeginDisabled(); - } - if (ImGui::CollapsingHeader("UPnP Settings")) { - ImGui::Indent(10); - ImGui::PushStyleColor(ImGuiCol_Border, static_cast(IM_COL32_WARNING)); - if (ImGui::BeginChild("##UPnPWarning", ImVec2(0, 50), true)) { - ImGui::Dummy(ImVec2(140.0f, 0.0f)); - ImGui::SameLine(); - ImGui::TextUnformatted("WARNING these are advanced settings!"); - ImGui::TextUnformatted("Using these without knowing what your are doing could put your computer and network at risk."); - } - ImGui::EndChild(); - ImGui::PopStyleColor(); - if (ImGui::Button("Search for UPnP devices")) { - if (!upnpClient->DiscoverySearching()) { - Execute([this](GameWrapper*) { - upnpClient->FindDevices(); - }); - } - else { - WARNING_LOG("Already searching for UPnP devices"); - } - } - ImGui::SameLine(); - if (upnpClient->DiscoveryFailed()) { - ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetDiscoveryStatus().c_str()); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Make sure your router supports UPnP \nand has it enabled it the settings."); - } + BM_WARNING_LOG("Already searching for UPnP devices"); + } + } + ImGui::SameLine(); + if (upnpClient->DiscoveryFailed()) { + ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetDiscoveryStatus().c_str()); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Make sure your router supports UPnP \nand has it enabled it the settings."); + } + } + else { + ImGui::TextWrapped(upnpClient->GetDiscoveryStatus()); + } + const bool invalidHostPortExternal = !Networking::IsValidPort(hostPortExternal); + if (upnpClient->DiscoveryFinished()) { + if (ImGui::Button(fmt::format("Forward port {:d}" + (invalidHostPortExternal + ? DEFAULT_PORT + : hostPortExternal)).c_str())) { + if (!upnpClient->ServiceForwardPortActive()) { + Execute([this, invalidHostPortExternal](GameWrapper*) { + upnpClient->ForwardPort(invalidHostPortExternal ? DEFAULT_PORT : hostPortInternal, + invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal, + portLeaseDuration); + }); } else { - ImGui::TextWrapped(upnpClient->GetDiscoveryStatus()); + BM_WARNING_LOG("Already forwarding a port"); } - const bool invalidHostPortExternal = !Networking::IsValidPort(hostPortExternal); - if (upnpClient->DiscoveryFinished()) { - if (ImGui::Button(("Forward port " + (invalidHostPortExternal ? std::to_string(DEFAULT_PORT) : std::to_string(hostPortExternal))).c_str())) { - if (!upnpClient->ServiceForwardPortActive()) { - Execute([this, invalidHostPortExternal](GameWrapper*) { - upnpClient->ForwardPort(invalidHostPortExternal ? DEFAULT_PORT : hostPortInternal, - invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal, portLeaseDuration); + } + if (upnpClient->ServiceForwardPortFailed()) { + ImGui::SameLine(); + ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetForwardPortStatus().c_str()); + } + else if (upnpClient->ServiceForwardPortFinished()) { + ImGui::SameLine(); + ImGui::TextWrapped(upnpClient->GetForwardPortStatus()); + } + } + ImGui::TextUnformatted("External Address:"); + const float itemWidth = std::max(0.f, ImGui::GetCurrentWindowRead()->DC.ItemWidth - ImGui::CalcTextSize(":").x); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, ImGui::GetStyle().ItemSpacing.y)); + ImGui::PushItemWidth(itemWidth / 3 * 2); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + ImGui::InputText("##ExternalIPAddress", upnpClient->GetExternalIpAddressBuffer(), + ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll); + ImGui::PopStyleVar(); + ImGui::PopItemWidth(); + ImGui::SameLine(); + ImGui::TextUnformatted(":"); + ImGui::SameLine(); + ImGui::PushItemWidth(itemWidth / 3); + if (invalidHostPortExternal) { + ImGui::BeginErrorBorder(); + ImGui::InputScalar("##UPnPHostPortExternal", ImGuiDataType_U16, &hostPortExternal); + ImGui::EndErrorBorder(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Invalid port"); + } + } + else { + ImGui::InputScalar("##UPnPHostPortExternal", ImGuiDataType_U16, &hostPortExternal); + } + ImGui::PopItemWidth(); + ImGui::PopStyleVar(); + ImGui::TextUnformatted("Duration to open your port for: (0 means indefinite)"); + constexpr int weekDuration = 60 * 60 * 24 * 7; + ImGui::DragTime(" hour:minutes:seconds##portLeaseDuration", &portLeaseDuration, 60, 0, weekDuration); + if (upnpClient->DiscoveryFinished()) { + ImGui::TextUnformatted("Open ports:"); + ImGui::SameLine(); + if (upnpClient->ServiceClosePortFailed()) { + ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetClosePortStatus().c_str()); + } + else if (upnpClient->ServiceClosePortFinished()) { + ImGui::TextWrapped(upnpClient->GetClosePortStatus()); + } + const std::vector& openPorts = upnpClient->GetOpenPorts(); + if (openPorts.empty()) { + ImGui::TextUnformatted("\tNo open ports found."); + } + else { + for (const unsigned short openPort : openPorts) { + if (ImGui::Button(std::to_string(openPort).c_str())) { + if (!upnpClient->ServiceClosePortActive()) { + Execute([this, openPort](GameWrapper*) { + upnpClient->ClosePort(openPort); }); } else { - WARNING_LOG("Already forwarding a port"); + BM_WARNING_LOG("Already closing a port"); } } - if (upnpClient->ServiceForwardPortFailed()) { - ImGui::SameLine(); - ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetForwardPortStatus().c_str()); - } - else if (upnpClient->ServiceForwardPortFinished()) { - ImGui::SameLine(); - ImGui::TextWrapped(upnpClient->GetForwardPortStatus()); - } - } - ImGui::TextUnformatted("External Address:"); - const float itemWidth = std::max(0.f, ImGui::GetCurrentWindowRead()->DC.ItemWidth - ImGui::CalcTextSize(":").x); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, ImGui::GetStyle().ItemSpacing.y)); - ImGui::PushItemWidth(itemWidth / 3 * 2); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - ImGui::InputText("##ExternalIPAddress", upnpClient->GetExternalIpAddressBuffer(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll); - ImGui::PopStyleVar(); - ImGui::PopItemWidth(); - ImGui::SameLine(); - ImGui::TextUnformatted(":"); - ImGui::SameLine(); - ImGui::PushItemWidth(itemWidth / 3); - if (invalidHostPortExternal) { - ImGui::BeginErrorBorder(); - ImGui::InputScalar("##UPnPHostPortExternal", ImGuiDataType_U16, &hostPortExternal); - ImGui::EndErrorBorder(); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Invalid port"); + ImGui::SetTooltip(fmt::format("Close port {:d}.", openPort)); } - } - else { - ImGui::InputScalar("##UPnPHostPortExternal", ImGuiDataType_U16, &hostPortExternal); - } - ImGui::PopItemWidth(); - ImGui::PopStyleVar(); - ImGui::TextUnformatted("Duration to open your port for: (0 means indefinite)"); - constexpr int weekDuration = 60 * 60 * 24 * 7; - ImGui::DragTime(" hour:minutes:seconds##portLeaseDuration", &portLeaseDuration, 60, 0, weekDuration); - if (upnpClient->DiscoveryFinished()) { - ImGui::TextUnformatted("Open ports:"); ImGui::SameLine(); - if (upnpClient->ServiceClosePortFailed()) { - ImGui::TextColoredWrapped(IM_COL32_ERROR, upnpClient->GetClosePortStatus().c_str()); - } - else if (upnpClient->ServiceClosePortFinished()) { - ImGui::TextWrapped(upnpClient->GetClosePortStatus()); - } - const std::vector& openPorts = upnpClient->GetOpenPorts(); - if (openPorts.empty()) { - ImGui::TextUnformatted("\tNo open ports found."); - } - else { - for (const unsigned short openPort : openPorts) { - if (ImGui::Button(std::to_string(openPort).c_str())) { - if (!upnpClient->ServiceClosePortActive()) { - Execute([this, openPort](GameWrapper*) { - upnpClient->ClosePort(openPort); - }); - } - else { - WARNING_LOG("Already closing a port"); - } - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Close port " + std::to_string(openPort) + "."); - } - ImGui::SameLine(); - } - ImGui::NewLine(); - } } - ImGui::Unindent(10); + ImGui::NewLine(); } - if (upnpFailed) { - ImGui::EndDisabled(); + } + ImGui::Unindent(10); + } + if (upnpFailed) { + ImGui::EndDisabled(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Failed to create networking thread."); + } + } +} + + +/// Renders the P2P settings in the advanced settings in the host section in game multiplayer tab. +void RocketPlugin::renderMultiplayerTabHostAdvancedSettingsP2PSettings() +{ + const bool p2pFailed = p2pHost == nullptr; + if (p2pFailed) { + // Disables the collapsing header. + ImGui::BeginDisabled(); + } + if (ImGui::CollapsingHeader("P2P Settings")) { + ImGui::Indent(10); + ImGui::PushStyleColor(ImGuiCol_Border, static_cast(IM_COL32_WARNING)); + if (ImGui::BeginChild("##P2PWarning", ImVec2(0, 50), true)) { + ImGui::Dummy(ImVec2(140.0f, 0.0f)); + ImGui::SameLine(); + ImGui::TextUnformatted("WARNING these are advanced settings!"); + ImGui::TextUnformatted("Using these without knowing what your are doing could put your computer and " + "network at risk."); + } + ImGui::EndChild(); + ImGui::PopStyleColor(); + if (ImGui::Button("get NAT type")) { + if (p2pHost->GetNATType() != P2PHost::NATType::NAT_SEARCHING) { + Execute([this](GameWrapper*) { + p2pHost->FindNATType(hostPortInternal); + }); + } + else { + BM_WARNING_LOG("Already getting NAT type."); + } + } + ImGui::SameLine(); + ImGui::TextWrapped(p2pHost->GetNATDesc()); + const bool invalidHostPortExternal = !Networking::IsValidPort(hostPortExternal); + if (p2pHost->GetNATType() == P2PHost::NATType::NAT_FULL_CONE || + p2pHost->GetNATType() == P2PHost::NATType::NAT_RESTRICTED_PORT) { + ImGui::TextUnformatted(fmt::format(" External host port: (default is {:d})", DEFAULT_PORT).c_str()); + if (invalidHostPortExternal) { + ImGui::BeginErrorBorder(); + ImGui::InputScalar("##NATHostPortExternal", ImGuiDataType_U16, &hostPortExternal); + ImGui::EndErrorBorder(); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Failed to create networking thread."); + ImGui::SetTooltip("Invalid port"); } } - const bool p2pFailed = p2pHost == nullptr; - if (p2pFailed) { - // Disables the collapsing header. - ImGui::BeginDisabled(); + else { + ImGui::InputScalar("##NATHostPortExternal", ImGuiDataType_U16, &hostPortExternal); } - if (ImGui::CollapsingHeader("P2P Settings")) { - ImGui::Indent(10); - ImGui::PushStyleColor(ImGuiCol_Border, static_cast(IM_COL32_WARNING)); - if (ImGui::BeginChild("##P2PWarning", ImVec2(0, 50), true)) { - ImGui::Dummy(ImVec2(140.0f, 0.0f)); - ImGui::SameLine(); - ImGui::TextUnformatted("WARNING these are advanced settings!"); - ImGui::TextUnformatted("Using these without knowing what your are doing could put your computer and network at risk."); + } + switch (p2pHost->GetNATType()) { + case P2PHost::NATType::NAT_FULL_CONE: + if (ImGui::Button(fmt::format("Punch through port {:d}", + invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal).c_str())) { + Execute([this, invalidHostPortExternal](GameWrapper*) { + p2pHost->PunchPort(NAT_PUNCH_ADDR, invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal); + }); } - ImGui::EndChild(); - ImGui::PopStyleColor(); - if (ImGui::Button("get NAT type")) { - if (p2pHost->GetNATType() != P2PHost::NATType::NAT_SEARCHING) { - Execute([this](GameWrapper*) { - p2pHost->FindNATType(hostPortInternal); - }); - } - else { - WARNING_LOG("Already getting NAT type."); - } + break; + case P2PHost::NATType::NAT_RESTRICTED_PORT: + if (connections.size() > 1 && connections[connections.size() - 1].IP[0] == '\0' && + connections[connections.size() - 2].IP[0] == '\0') { + connections.pop_back(); } - ImGui::SameLine(); - ImGui::TextWrapped(p2pHost->GetNATDesc()); - const bool invalidHostPortExternal = !Networking::IsValidPort(hostPortExternal); - if (p2pHost->GetNATType() == P2PHost::NATType::NAT_FULL_CONE || p2pHost->GetNATType() == P2PHost::NATType::NAT_RESTRICTED_PORT) { - ImGui::TextUnformatted((" External host port: (default is " + std::to_string(DEFAULT_PORT) + ")").c_str()); - if (invalidHostPortExternal) { + if (connections.empty() || connections.back().IP[0] != '\0') { + connections.push_back({ { '\0' }, true }); + } + for (size_t i = 0; i < connections.size(); i++) { + if (connections[i].InvalidIP) { ImGui::BeginErrorBorder(); - ImGui::InputScalar("##NATHostPortExternal", ImGuiDataType_U16, &hostPortExternal); + if (ImGui::InputText(fmt::format("##P2PClientIP_{:d}", i).c_str(), &connections[i].IP[0], + sizeof P2PIP::IP)) { + connections[i].InvalidIP = !Networking::IsValidIPv4(connections[i].IP); + } ImGui::EndErrorBorder(); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Invalid port"); + ImGui::SetTooltip("Invalid ipv4"); } } else { - ImGui::InputScalar("##NATHostPortExternal", ImGuiDataType_U16, &hostPortExternal); + if (ImGui::InputText(fmt::format("##P2PClientIP_{:d}", i).c_str(), &connections[i].IP[0], + sizeof P2PIP::IP)) { + connections[i].InvalidIP = !Networking::IsValidIPv4(connections[i].IP); + } } - } - switch (p2pHost->GetNATType()) { - case P2PHost::NATType::NAT_FULL_CONE: - if (ImGui::Button(("Punch through port " + std::to_string(invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal)).c_str())) { - Execute([this, invalidHostPortExternal](GameWrapper*) { - p2pHost->PunchPort(NAT_PUNCH_ADDR, invalidHostPortExternal ? DEFAULT_PORT : hostPortExternal); + ImGui::SameLine(); + if (ImGui::Button(fmt::format("Start Connection##P2PClientConn_{:d}", i).c_str())) { + p2pHost->PunchPort(connections[i].IP, hostPortExternal); + Execute([this, addr = connections[i].IP](GameWrapper*) { + p2pHost->PunchPort(addr, hostPortExternal); }); } - break; - case P2PHost::NATType::NAT_RESTRICTED_PORT: - if (connections.size() > 1 && connections[connections.size() - 1].IP[0] == '\0' && connections[connections.size() - 2].IP[0] == '\0') { - connections.pop_back(); - } - if (connections.empty() || connections.back().IP[0] != '\0') { - connections.push_back({ { '\0' }, true }); - } - for (size_t i = 0; i < connections.size(); i++) { - if (connections[i].InvalidIP) { - ImGui::BeginErrorBorder(); - if (ImGui::InputText(("##P2PClientIP" + std::to_string(i)).c_str(), &connections[i].IP[0], sizeof P2PIP::IP)) { - connections[i].InvalidIP = !Networking::IsValidIPv4(connections[i].IP); - } - ImGui::EndErrorBorder(); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Invalid ipv4"); - } - } - else { - if (ImGui::InputText(("##P2PClientIP" + std::to_string(i)).c_str(), &connections[i].IP[0], sizeof P2PIP::IP)) { - connections[i].InvalidIP = !Networking::IsValidIPv4(connections[i].IP); - } - } - ImGui::SameLine(); - if (ImGui::Button(("Start Connection##P2PClientConn" + std::to_string(i)).c_str())) { - p2pHost->PunchPort(connections[i].IP, hostPortExternal); - Execute([this, addr = connections[i].IP](GameWrapper*) { - p2pHost->PunchPort(addr, hostPortExternal); - }); - } - } - break; - default: - break; - } - ImGui::Unindent(10); - } - if (p2pFailed) { - ImGui::EndDisabled(); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Failed to create networking thread."); } - } - ImGui::Unindent(4); - ImGui::Checkbox("Host game with party", &hostWithParty); - ImGui::SameLine(); - ImGui::TextUnformatted("(?)"); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Will send a party game invite to everyone in your party.\nThis only works when connecting directly to your IP."); - } + break; + default: + break; } - ImGui::Separator(); - - if (isHostingLocalGame()) { - if (ImGui::Button("Host New Match")) { - Execute([this](GameWrapper*) { - HostGame(); - }); - } - ImGui::SameLine(); - if (ImGui::Button("Update Match Settings")) { - Execute([this](GameWrapper*) { - if (enableWorkshopMaps || enableCustomMaps) { - const std::filesystem::path map = currentMap; - preLoadMap(std::filesystem::absolute(map)); - setMatchSettings(map.stem().string()); - } - else { - setMatchSettings(currentMap); - } - TRACE_LOG("updated match settings"); - }); - } - } - else { - if (ImGui::Button("Host")) { - Execute([this](GameWrapper*) { - HostGame(); - }); - } + ImGui::Unindent(10); + } + if (p2pFailed) { + ImGui::EndDisabled(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Failed to create networking thread."); } } - ImGui::EndChild(); } @@ -720,7 +785,7 @@ void BeginHostStatusBorder(const Networking::DestAddrType addrType, const Networ ImGui::BeginErrorBorder(); } else if (addrType == Networking::DestAddrType::PRIVATE_ADDR || addrType == Networking::DestAddrType::INTERNL_ADDR || - hostStatus == Networking::HostStatus::HOST_TIMEOUT) { + hostStatus == Networking::HostStatus::HOST_TIMEOUT) { ImGui::BeginWarnBorder(); } else if (hostStatus == Networking::HostStatus::HOST_ONLINE) { @@ -761,7 +826,8 @@ void RocketPlugin::renderMultiplayerTabJoin() } } ImGui::EndBorder(); - if (hostOnline == Networking::HostStatus::HOST_UNKNOWN && addressType != Networking::DestAddrType::UNKNOWN_ADDR) { + if (hostOnline == Networking::HostStatus::HOST_UNKNOWN && + addressType != Networking::DestAddrType::UNKNOWN_ADDR) { // Only ping when the user is finished typing. if (ImGui::IsItemActiveLastFrame() && !ImGui::IsItemActive()) { Networking::PingHost(*joinIP, static_cast(*joinPort), &hostOnline, true); @@ -771,8 +837,7 @@ void RocketPlugin::renderMultiplayerTabJoin() ImGui::SetTooltip(Networking::GetHostStatusHint(addressType, hostOnline)); } ImGui::TextUnformatted(" Port:"); - const bool invalidJoinPort = !Networking::IsValidPort(*joinPort); - if (invalidJoinPort) { + if (!Networking::IsValidPort(*joinPort)) { ImGui::BeginErrorBorder(); if (ImGui::InputScalar("##port_join", ImGuiDataType_U16, joinPort.get())) { cvarManager->getCvar("mp_port").setValue(*joinPort); @@ -796,6 +861,7 @@ void RocketPlugin::renderMultiplayerTabJoin() static bool isCurrentMapJoinable = true; if (ImGui::Checkbox("Joining a custom map", &joinCustomMap)) { if (joinCustomMap) { + refreshCustomMapPaths = true; Execute([this](GameWrapper*) { isCurrentMapJoinable = isMapJoinable(currentJoinMap); }); @@ -853,266 +919,307 @@ void RocketPlugin::renderInGameModsTab() { if (ImGui::BeginTabItem("In Game Mods")) { if (ImGui::BeginChild("##InGameMods", ImVec2(0, 0), true)) { - if (ImGui::CollapsingHeader("Game Event Mods")) { - ImGui::Indent(20); - if (ImGui::CollapsingHeader("Game Controls")) { - if (ImGui::Button("Force Overtime")) { - Execute([this](GameWrapper*) { - ForceOvertime(); - }); - } - ImGui::SameLine(); - if (ImGui::Button("Pause Server")) { - Execute([this](GameWrapper*) { - PauseServer(); - }); - } - if (ImGui::Button("Restart Match")) { - Execute([this](GameWrapper*) { - ResetMatch(); - }); - } - ImGui::SameLine(); - if (ImGui::Button("End Match")) { - Execute([this](GameWrapper*) { - EndMatch(); - }); - } - if (ImGui::Button("Reset Players")) { - Execute([this](GameWrapper*) { - ResetPlayers(); - }); - } - ImGui::SameLine(); - if (ImGui::Button("Reset Balls")) { - Execute([this](GameWrapper*) { - ResetBalls(); - }); - } + renderInGameModsTabGameEventMods(); + renderInGameModsTabBallMods(); + renderInGameModsTabPlayerMods(); + renderInGameModsTabCarPhysicsMods(); + } + ImGui::EndChild(); + ImGui::EndTabItem(); + } +} + + +/// Renders the game event mods section in in game mods tab. +void RocketPlugin::renderInGameModsTabGameEventMods() +{ + if (ImGui::CollapsingHeader("Game Event Mods")) { + ImGui::Indent(10); + if (ImGui::CollapsingHeader("Game Controls")) { + ImGui::Indent(10); + if (ImGui::Button("Force Overtime")) { + Execute([this](GameWrapper*) { + gameControls.ForceOvertime(); + }); + } + ImGui::SameLine(); + if (ImGui::Button("Pause Server")) { + Execute([this](GameWrapper*) { + gameControls.PauseServer(); + }); + } + if (ImGui::Button("Restart Match")) { + Execute([this](GameWrapper*) { + gameControls.ResetMatch(); + }); + } + ImGui::SameLine(); + if (ImGui::Button("End Match")) { + Execute([this](GameWrapper*) { + gameControls.EndMatch(); + }); + } + if (ImGui::Button("Reset Players")) { + Execute([this](GameWrapper*) { + gameControls.ResetPlayers(); + }); + } + ImGui::SameLine(); + if (ImGui::Button("Reset Balls")) { + Execute([this](GameWrapper*) { + gameControls.ResetBalls(); + }); + } + ImGui::Unindent(10); + } + if (ImGui::CollapsingHeader("Match Settings")) { + ImGui::Indent(10); + int maxPlayers = matchSettings.GetMaxPlayers(); + if (ImGui::InputInt("Max Players", &maxPlayers)) { + Execute([this, maxPlayers](GameWrapper*) { + matchSettings.SetMaxPlayers(maxPlayers); + }); + } + int maxTeamSize = matchSettings.GetMaxTeamSize(); + if (ImGui::InputInt("Max Team Size", &maxTeamSize)) { + Execute([this, maxTeamSize](GameWrapper*) { + matchSettings.SetMaxTeamSize(maxTeamSize); + }); + } + int respawnTime = matchSettings.GetRespawnTime(); + if (ImGui::InputInt("Respawn Time", &respawnTime)) { + Execute([this, respawnTime](GameWrapper*) { + matchSettings.SetRespawnTime(respawnTime); + }); + } + int blueScore = matchSettings.GetScoreBlue(); + ImGui::PushItemWidth(150); + if (ImGui::InputInt("Blue Score", &blueScore)) { + Execute([this, blueScore](GameWrapper*) { + matchSettings.SetScoreBlue(blueScore); + }); + } + ImGui::SameLine(); + int orangeScore = matchSettings.GetScoreOrange(); + if (ImGui::InputInt("Orange Score", &orangeScore)) { + Execute([this, orangeScore](GameWrapper*) { + matchSettings.SetScoreOrange(orangeScore); + }); + } + ImGui::PopItemWidth(); + int gameTimeRemaining = matchSettings.GetGameTimeRemaining(); + if (ImGui::DragTime("Time Remaining", &gameTimeRemaining)) { + Execute([this, gameTimeRemaining](GameWrapper*) { + matchSettings.SetGameTimeRemaining(gameTimeRemaining); + }); + } + bool isGoalDelayDisabled = matchSettings.GetIsGoalDelayDisabled(); + if (ImGui::Checkbox("Disable Goal Delay", &isGoalDelayDisabled)) { + Execute([this, isGoalDelayDisabled](GameWrapper*) { + matchSettings.SetIsGoalDelayDisabled(isGoalDelayDisabled); + }); + } + bool isUnlimitedTime = matchSettings.GetIsUnlimitedTime(); + if (ImGui::Checkbox("Unlimited Time", &isUnlimitedTime)) { + Execute([this, isUnlimitedTime](GameWrapper*) { + matchSettings.SetIsUnlimitedTime(isUnlimitedTime); + }); + } + ImGui::Unindent(10); + } + if (ImGui::CollapsingHeader("Bots")) { + ImGui::Indent(10); + int numBots = botSettings.GetMaxNumBots(); + if (ImGui::InputInt("Max # bots per team", &numBots)) { + if (!GetGame().IsNull()) { + Execute([this, numBots](GameWrapper*) { + botSettings.SetNumBotsPerTeam(numBots); + }); } - if (ImGui::CollapsingHeader("Match Settings")) { - int maxPlayers = GetMaxPlayers(); - if (ImGui::InputInt("Max Players", &maxPlayers)) { - Execute([this, maxPlayers](GameWrapper*) { - SetMaxPlayers(maxPlayers); - }); - } - int maxTeamSize = GetMaxTeamSize(); - if (ImGui::InputInt("Max Team Size", &maxTeamSize)) { - Execute([this, maxTeamSize](GameWrapper*) { - SetMaxTeamSize(maxTeamSize); - }); - } - int respawnTime = GetRespawnTime(); - if (ImGui::InputInt("Respawn Time", &respawnTime)) { - Execute([this, respawnTime](GameWrapper*) { - SetRespawnTime(respawnTime); - }); - } - int blueScore = GetScoreBlue(); - ImGui::PushItemWidth(150); - if (ImGui::InputInt("Blue Score", &blueScore)) { - Execute([this, blueScore](GameWrapper*) { - SetScoreBlue(blueScore); - }); - } - ImGui::SameLine(); - int orangeScore = GetScoreOrange(); - if (ImGui::InputInt("Orange Score", &orangeScore)) { - Execute([this, orangeScore](GameWrapper*) { - SetScoreOrange(orangeScore); - }); - } - ImGui::PopItemWidth(); - int gameTimeRemaining = GetGameTimeRemaining(); - if (ImGui::DragTime("Time Remaining", &gameTimeRemaining)) { - Execute([this, gameTimeRemaining](GameWrapper*) { - SetGameTimeRemaining(gameTimeRemaining); - }); - } - bool isGoalDelayDisabled = GetIsGoalDelayDisabled(); - if (ImGui::Checkbox("Disable Goal Delay", &isGoalDelayDisabled)) { - Execute([this, isGoalDelayDisabled](GameWrapper*) { - SetIsGoalDelayDisabled(isGoalDelayDisabled); - }); - } - bool isUnlimitedTime = GetIsUnlimitedTime(); - if (ImGui::Checkbox("Unlimited Time", &isUnlimitedTime)) { - Execute([this, isUnlimitedTime](GameWrapper*) { - SetIsUnlimitedTime(isUnlimitedTime); - }); - } + } + bool isAutoFilledWithBots = botSettings.GetIsAutoFilledWithBots(); + if (ImGui::Checkbox("Autofill with bots", &isAutoFilledWithBots)) { + Execute([this, isAutoFilledWithBots](GameWrapper*) { + botSettings.SetIsAutoFilledWithBots(isAutoFilledWithBots); + }); + } + ImGui::SameLine(); + bool isUnfairTeams = botSettings.GetIsUnfairTeams(); + if (ImGui::Checkbox("Unfair Teams", &isUnfairTeams)) { + Execute([this, numBots, isUnfairTeams](GameWrapper*) { + botSettings.SetIsUnfairTeams(isUnfairTeams); + botSettings.SetNumBotsPerTeam(numBots); + }); + } + if (ImGui::Button("Freeze Bots")) { + Execute([this](GameWrapper*) { + botSettings.FreezeBots(); + }); + } + ImGui::Unindent(10); + } + ImGui::Unindent(10); + } +} + + +/// Renders the ball mods section in in game mods tab. +void RocketPlugin::renderInGameModsTabBallMods() +{ + if (ImGui::CollapsingHeader("Ball Mods")) { + ImGui::Indent(10); + int numBalls = ballMods.GetNumBalls(); + if (ImGui::InputInt("# Balls", &numBalls)) { + Execute([this, numBalls](GameWrapper*) { + ballMods.SetNumBalls(numBalls); + }); + } + float ballScale = ballMods.GetBallsScale(); + if (ImGui::SliderFloat("Balls Scale", &ballScale, 0.1f, 10.0f, "%.1fX")) { + Execute([this, ballScale](GameWrapper*) { + ballMods.SetBallsScale(ballScale); + }); + } + float maxBallVelocity = ballMods.GetMaxBallVelocity(); + if (ImGui::DragFloat("Max Ball Velocity", &maxBallVelocity, 1.0f, 0.0f, 0.0f, "%.3f u/s")) { + Execute([this, maxBallVelocity](GameWrapper*) { + ballMods.SetMaxBallVelocity(maxBallVelocity); + }); + } + ImGui::Unindent(10); + } +} + + +/// Renders the player mods section in in game mods tab. +void RocketPlugin::renderInGameModsTabPlayerMods() +{ + if (ImGui::CollapsingHeader("Player Mods")) { + ImGui::Indent(10); + std::vector players; + if (IsInGame()) { + players = playerMods.GetPlayers(true); + } + ImGui::BeginColumns("Mutators", 4); + { + ImGui::SetColumnWidth(0, 110); + ImGui::SetColumnWidth(1, 55); + ImGui::SetColumnWidth(2, 55); + ImGui::TextUnformatted("Player"); + ImGui::NextColumn(); + ImGui::TextUnformatted("Admin"); + ImGui::NextColumn(); + ImGui::TextUnformatted("Hidden"); + ImGui::NextColumn(); + ImGui::NextColumn(); + ImGui::Separator(); + for (PriWrapper& player : players) { + const std::string displayName = player.GetPlayerName().ToString(); + const std::string uniqueName = player.GetUniqueIdWrapper().str(); + if (player.GetbBot()) { + ImGui::Text("(bot) %s", displayName.c_str()); } - if (ImGui::CollapsingHeader("Bots")) { - int numBots = GetMaxNumBots(); - if (ImGui::InputInt("Max # bots per team", &numBots)) { - if (!gameWrapper->GetGameEventAsServer().IsNull()) { - Execute([this, numBots](GameWrapper*) { - SetNumBotsPerTeam(numBots); - }); - } - } - bool isAutoFilledWithBots = GetIsAutoFilledWithBots(); - if (ImGui::Checkbox("Autofill with bots", &isAutoFilledWithBots)) { - Execute([this, isAutoFilledWithBots](GameWrapper*) { - SetIsAutoFilledWithBots(isAutoFilledWithBots); - }); - } - ImGui::SameLine(); - bool isUnfairTeams = GetIsUnfairTeams(); - if (ImGui::Checkbox("Unfair Teams", &isUnfairTeams)) { - Execute([this, isUnfairTeams](GameWrapper*) { - SetIsUnfairTeams(isUnfairTeams); - }); - } - if (ImGui::Button("Freeze Bots")) { - Execute([this](GameWrapper*) { - FreezeBots(); - }); - } + else { + ImGui::TextUnformatted(displayName.c_str()); } - ImGui::Unindent(); - } - if (ImGui::CollapsingHeader("Ball Mods")) { - int numBalls = GetNumBalls(); - if (ImGui::InputInt("# Balls", &numBalls)) { - Execute([this, numBalls](GameWrapper*) { - SetNumBalls(numBalls); + ImGui::NextColumn(); + bool isAdmin = playerMods.GetIsAdmin(player); + if (ImGui::Checkbox(("##Admin_" + uniqueName).c_str(), &isAdmin)) { + Execute([this, player, isAdmin](GameWrapper*) { + playerMods.SetIsAdmin(player, isAdmin); }); } - float ballScale = GetBallsScale(); - if (ImGui::SliderFloat("Balls Scale", &ballScale, 0.1f, 10.0f, "%.1fX")) { - Execute([this, ballScale](GameWrapper*) { - SetBallsScale(ballScale); + ImGui::NextColumn(); + bool isHidden = playerMods.GetIsHidden(player); + if (ImGui::Checkbox(("##Hidden_" + uniqueName).c_str(), &isHidden)) { + Execute([this, player, isHidden](GameWrapper*) { + playerMods.SetIsHidden(player, isHidden); }); } - float maxBallVelocity = GetMaxBallVelocity(); - if (ImGui::DragFloat("Max Ball Velocity", &maxBallVelocity, 1.0f, 0.0f, 0.0f, "%.3f u/s")) { - Execute([this, maxBallVelocity](GameWrapper*) { - SetMaxBallVelocity(maxBallVelocity); + ImGui::NextColumn(); + if (ImGui::Button(("Demolish##_" + uniqueName).c_str())) { + Execute([this, player](GameWrapper*) { + playerMods.Demolish(player); }); } + ImGui::NextColumn(); + ImGui::Separator(); } - if (ImGui::CollapsingHeader("Player Mods")) { - std::vector players; - if (IsInGame()) { - players = GetPlayers(true); - } - ImGui::BeginColumns("Mutators", 4); - { - ImGui::SetColumnWidth(0, 110); - ImGui::SetColumnWidth(1, 55); - ImGui::SetColumnWidth(2, 55); - ImGui::TextUnformatted("Player"); - ImGui::NextColumn(); - ImGui::TextUnformatted("Admin"); - ImGui::NextColumn(); - ImGui::TextUnformatted("Hidden"); - ImGui::NextColumn(); - ImGui::NextColumn(); - ImGui::Separator(); - for (PriWrapper& player : players) { - const std::string displayName = player.GetPlayerName().ToString(); - const std::string uniqueName = player.GetUniqueIdWrapper().str(); - if (player.GetbBot()) { - ImGui::Text("(bot) %s", displayName.c_str()); - } - else { - ImGui::TextUnformatted(displayName.c_str()); - } - ImGui::NextColumn(); - bool isAdmin = GetIsAdmin(player); - if (ImGui::Checkbox(("##Admin_" + uniqueName).c_str(), &isAdmin)) { - Execute([this, player, isAdmin](GameWrapper*) { - SetIsAdmin(player, isAdmin); - }); - } - ImGui::NextColumn(); - bool isHidden = GetIsHidden(player); - if (ImGui::Checkbox(("##Hidden_" + uniqueName).c_str(), &isHidden)) { - Execute([this, player, isHidden](GameWrapper*) { - SetIsHidden(player, isHidden); - }); - } - ImGui::NextColumn(); - if (ImGui::Button(("Demolish##_" + uniqueName).c_str())) { - Execute([this, player](GameWrapper*) { - Demolish(player); - }); - } - ImGui::NextColumn(); - ImGui::Separator(); - } - if (players.empty()) { - ImGui::TextUnformatted("No players found"); - } - } - ImGui::EndColumns(); + if (players.empty()) { + ImGui::TextUnformatted("No players found"); } - if (ImGui::CollapsingHeader("Car Physics Mods")) { - if (!carPhysics.empty()) { - ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled)); - ImGui::TextUnformatted("Car physics mods are active"); - ImGui::PopStyleColor(); - } + } + ImGui::EndColumns(); + ImGui::Unindent(10); + } +} - std::vector players; - std::vector playersNames; - if (IsInGame()) { - players = GetPlayers(true); - playersNames = GetPlayersNames(players); - } - ImGui::TextUnformatted("Modify: "); - ImGui::SameLine(); - ImGui::Combo("##Players", &selectedPlayer, playersNames, "No players found"); - ImGui::Separator(); - if (selectedPlayer < players.size()) { - const PriWrapper player = players[selectedPlayer]; - CarPhysics playerPhysics = GetPhysics(player); - if (ImGui::SliderFloat("Car Scale", &playerPhysics.CarScale, 0.1f, 2.0f, "%.1fX")) { - Execute([this, player, newCarScale = playerPhysics.CarScale](GameWrapper*) { - SetCarScale(player, newCarScale, true); - }); - } - if (ImGui::Checkbox("Car Collision", &playerPhysics.CarHasCollision)) { - Execute([this, player, newCarHasCollision = playerPhysics.CarHasCollision](GameWrapper*) { - SetbCarCollision(player, newCarHasCollision); - }); - } - ImGui::SameLine(); - if (ImGui::Checkbox("Freeze car", &playerPhysics.CarIsFrozen)) { - Execute([this, player, newCarIsFrozen = playerPhysics.CarIsFrozen](GameWrapper*) { - SetCarIsFrozen(player, newCarIsFrozen); - }); - } - ImGui::Separator(); +/// Renders the car physics mods section in in game mods tab. +void RocketPlugin::renderInGameModsTabCarPhysicsMods() +{ + if (ImGui::CollapsingHeader("Car Physics Mods")) { + ImGui::Indent(10); + if (!carPhysicsMods.carPhysics.empty()) { + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled)); + ImGui::TextUnformatted("Car physics mods are active (use 'rp_clear_car_physics_cache' to clear)"); + ImGui::PopStyleColor(); + } - if (ImGui::DragFloat("Torque Rate", &playerPhysics.TorqueRate, 0.1f, 0.0f, 0.0f, "%.3fx10^5 N*m")) { - Execute([this, player, newTorqueRate = playerPhysics.TorqueRate](GameWrapper*) { - SetTorqueRate(player, newTorqueRate); - }); - } - if (ImGui::DragFloat("Max Car Velocity", &playerPhysics.MaxCarVelocity, 1.0f, 0.0f, 0.0f, "%.3f u/s")) { - Execute([this, player, newMaxCarVelocity = playerPhysics.MaxCarVelocity](GameWrapper*) { - SetMaxCarVelocity(player, newMaxCarVelocity); - }); - } - if (ImGui::DragFloat("Ground Sticky Force", &playerPhysics.GroundStickyForce, 1.0f, 0.0f, 0.0f, "%.3f N")) { - Execute([this, player, newGroundStickyForce = playerPhysics.GroundStickyForce](GameWrapper*) { - SetGroundStickyForce(player, newGroundStickyForce); - }); - } - if (ImGui::DragFloat("Wall Sticky Force", &playerPhysics.WallStickyForce, 1.0f, 0.0f, 0.0f, "%.3f N")) { - Execute([this, player, newWallStickyForce = playerPhysics.WallStickyForce](GameWrapper*) { - SetWallStickyForce(player, newWallStickyForce); - }); - } - } + std::vector players; + std::vector playersNames; + if (IsInGame()) { + players = playerMods.GetPlayers(true); + playersNames = playerMods.GetPlayersNames(players); + } + ImGui::TextUnformatted("Modify: "); + ImGui::SameLine(); + ImGui::Combo("##Players", &carPhysicsMods.selectedPlayer, playersNames, "No players found"); + ImGui::Separator(); + + if (carPhysicsMods.selectedPlayer < players.size()) { + const PriWrapper player = players[carPhysicsMods.selectedPlayer]; + CarPhysicsMods::CarPhysics playerPhysics = carPhysicsMods.GetPhysics(player); + if (ImGui::SliderFloat("Car Scale", &playerPhysics.CarScale, 0.1f, 2.0f, "%.1fX")) { + Execute([this, player, newCarScale = playerPhysics.CarScale](GameWrapper*) { + carPhysicsMods.SetCarScale(player, newCarScale, true); + }); + } + if (ImGui::Checkbox("Car Collision", &playerPhysics.CarHasCollision)) { + Execute([this, player, newCarHasCollision = playerPhysics.CarHasCollision](GameWrapper*) { + carPhysicsMods.SetbCarCollision(player, newCarHasCollision); + }); + } + ImGui::SameLine(); + if (ImGui::Checkbox("Freeze car", &playerPhysics.CarIsFrozen)) { + Execute([this, player, newCarIsFrozen = playerPhysics.CarIsFrozen](GameWrapper*) { + carPhysicsMods.SetCarIsFrozen(player, newCarIsFrozen); + }); + } + ImGui::Separator(); + + if (ImGui::DragFloat("Torque Rate", &playerPhysics.TorqueRate, 0.1f, 0.0f, 0.0f, "%.3fx10^5 N*m")) { + Execute([this, player, newTorqueRate = playerPhysics.TorqueRate](GameWrapper*) { + carPhysicsMods.SetTorqueRate(player, newTorqueRate); + }); + } + if (ImGui::DragFloat("Max Car Velocity", &playerPhysics.MaxCarVelocity, 1.0f, 0.0f, 0.0f, "%.3f u/s")) { + Execute([this, player, newMaxCarVelocity = playerPhysics.MaxCarVelocity](GameWrapper*) { + carPhysicsMods.SetMaxCarVelocity(player, newMaxCarVelocity); + }); + } + if (ImGui::DragFloat("Ground Sticky Force", &playerPhysics.GroundStickyForce, 1.0f, 0.0f, 0.0f, "%.3f N")) { + Execute([this, player, newGroundStickyForce = playerPhysics.GroundStickyForce](GameWrapper*) { + carPhysicsMods.SetGroundStickyForce(player, newGroundStickyForce); + }); + } + if (ImGui::DragFloat("Wall Sticky Force", &playerPhysics.WallStickyForce, 1.0f, 0.0f, 0.0f, "%.3f N")) { + Execute([this, player, newWallStickyForce = playerPhysics.WallStickyForce](GameWrapper*) { + carPhysicsMods.SetWallStickyForce(player, newWallStickyForce); + }); } } - ImGui::EndChild(); - ImGui::EndTabItem(); + ImGui::Unindent(10); } } @@ -1140,7 +1247,7 @@ void RocketPlugin::renderGameModesTab() gameModeName = customGameMode->GetGameModeName(); gameModeActive = customGameMode->IsActive(); } - if (ImGui::SwitchCheckbox(("##" + gameModeName + std::to_string(i)).c_str(), &gameModeActive)) { + if (ImGui::SwitchCheckbox(fmt::format("##{:s}_{:d}", gameModeName, i).c_str(), &gameModeActive)) { Execute([this, customGameMode, gameModeActive](GameWrapper*) { customGameMode->Activate(gameModeActive); }); @@ -1164,7 +1271,7 @@ void RocketPlugin::renderGameModesTab() ImGui::SameLine(); if (ImGui::BeginChild("##GameModesOptions", ImVec2(0, 0), true)) { if (customGameModeSelected < customGameModes.size()) { - std::shared_ptr customGameMode = customGameModes[customGameModeSelected]; + const std::shared_ptr customGameMode = customGameModes[customGameModeSelected]; if (customGameMode != nullptr) { ImGui::TextUnformatted(customGameMode->GetGameModeName().c_str()); ImGui::Separator(); diff --git a/source/RocketPlugin/RocketPluginServer.cpp b/source/RocketPlugin/RocketPluginServer.cpp deleted file mode 100644 index 678e79f..0000000 --- a/source/RocketPlugin/RocketPluginServer.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// RocketPluginServer.cpp -// Custom server for the RocketPlugin plugin. -// -// Author: Stanbroek -// Version: 0.6.5 05/02/21 - -#include "RocketPluginServer.h" - -#include - -void RocketPluginServer::Start() const -{ - [[maybe_unused]] const char* gameDir = "rocketleague"; - [[maybe_unused]] const uint32 ip = INADDR_ANY; - [[maybe_unused]] const uint16 masterServerUpdaterPort = MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE; - [[maybe_unused]] const EServerMode mode = eServerModeNoAuthentication; // Don't authenticate user logins and don't list on the server list - //const EServerMode mode = eServerModeAuthentication; // Authenticate users, list on the server list, don't run VAC on clients that connect - - if (SteamGameServer() == nullptr) { - TRACE_LOG("initializing Steam game server interface"); - - if (!SteamGameServer_Init(ip, 8766, 27815, 27816, mode, "0.0.2")) { - ERROR_LOG("SteamGameServer_Init call failed"); - } - if (SteamGameServer() == nullptr) { - ERROR_LOG("Steam game server interface interface is invalid"); - return; - } - } - else { - TRACE_LOG("Steam game server interface is already Initialized"); - } - - if (!SteamGameServer()->BLoggedOn()) { - TRACE_LOG("logging in Steam game server"); - SteamGameServer()->SetModDir(gameDir); - SteamGameServer()->SetProduct("252950"); - SteamGameServer()->SetGameDescription("Rocket League"); - SteamGameServer()->LogOnAnonymous(); - SteamGameServer()->EnableHeartbeats(true); - } - else { - TRACE_LOG("Steam game server is already logged on"); - } -} - - -void RocketPluginServer::Stop() const -{ - if (connectedToSteam) { - TRACE_LOG("logging off Steam game server"); - SteamGameServer()->LogOff(); - } - - //SteamGameServer_Shutdown(); -} - - -void RocketPluginServer::SetSettings() const -{ - if (SteamGameServer() != nullptr) { - SteamGameServer()->SetMaxPlayerCount(maxPlayerCount); - SteamGameServer()->SetPasswordProtected(passwordProtected); - SteamGameServer()->SetServerName(serverName.c_str()); - SteamGameServer()->SetMapName(mapName.c_str()); - SteamGameServer()->SetGameTags(gameTags.c_str()); - TRACE_LOG("set Steam game server settings"); - } -} - - -void RocketPluginServer::SetRichPresence() const -{ - if (SteamGameServer() && SteamUser() && SteamFriends()) { - const u_long addr = htonl(SteamGameServer()->GetPublicIP()); - const std::string value = fmt::format("-SteamConnectID={} -SteamConnectIP={}", - SteamUser()->GetSteamID().ConvertToUint64(), Networking::IPv4ToString(&addr)); - if (SteamFriends()->SetRichPresence("connect", value.c_str())) { - TRACE_LOG("set rich presence to connect:{}", quote(value)); - } - else { - TRACE_LOG("failed to set rich presence to connect:{}", quote(value)); - } - } -} - - -void RocketPluginServer::LogStatus() const -{ - - TRACE_LOG("Connected to Steam: {}\n", connectedToSteam); - TRACE_LOG("Logged in to Steam: {}\n", loggedInToSteam); - ISteamGameServer* steamGameServer = SteamGameServer(); - if (steamGameServer != nullptr) { - TRACE_LOG("Logged On: {}\n", steamGameServer->BLoggedOn()); - TRACE_LOG("Secure: {}\n", steamGameServer->BSecure()); - TRACE_LOG("Steam ID: {}\n", steamGameServer->GetSteamID().ConvertToUint64()); - const u_long addr = htonl(steamGameServer->GetPublicIP()); - TRACE_LOG("public IP: {}", Networking::IPv4ToString(&addr)); - } - else { - TRACE_LOG("Error, could not get Steam game server"); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: called when a connections to the Steam back-end has been established -// this means the Steam client now has a working connection to the Steam servers -// usually this will have occurred before the game has launched, and should -// only be seen if the user has dropped connection due to a networking issue -// or a Steam server update -//----------------------------------------------------------------------------- -void RocketPluginServer::OnSteamServersConnected([[maybe_unused]] SteamServersConnected_t* pLogonSuccess) -{ - TRACE_LOG("succesfully"); - connectedToSteam = true; - SetSettings(); -} - - -//----------------------------------------------------------------------------- -// Purpose: called when a connection attempt has failed -// this will occur periodically if the Steam client is not connected, -// and has failed in it's retry to establish a connection -//----------------------------------------------------------------------------- -void RocketPluginServer::OnSteamServersConnectFailure([[maybe_unused]] SteamServerConnectFailure_t* pConnectFailure) -{ - TRACE_LOG("Result: {:X}, Still Retrying: {}", pConnectFailure->m_eResult, pConnectFailure->m_bStillRetrying); - connectedToSteam = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: called if the client has lost connection to the Steam servers -// real-time services will be disabled until a matching SteamServersConnected_t has been posted -//----------------------------------------------------------------------------- -void RocketPluginServer::OnSteamServersDisconnected([[maybe_unused]] SteamServersDisconnected_t* pLoggedOff) -{ - TRACE_LOG("Result: {:X}", pLoggedOff->m_eResult); - connectedToSteam = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: received when the game server requests to be displayed as secure (VAC protected) -// m_bSecure is true if the game server should display itself as secure to users, false otherwise -//----------------------------------------------------------------------------- -void RocketPluginServer::OnPolicyResponse([[maybe_unused]] GSPolicyResponse_t* pPolicyResponse) -{ - TRACE_LOG("Secure: {}", static_cast(pPolicyResponse->m_bSecure)); - loggedInToSteam = true; -} - - -//----------------------------------------------------------------------------- -// callback for BeginAuthSession -//----------------------------------------------------------------------------- -void RocketPluginServer::OnValidateAuthTicketResponse(ValidateAuthTicketResponse_t* pResponse) -{ - TRACE_LOG("from {}", pResponse->m_SteamID.ConvertToUint64()); - if (pResponse->m_eAuthSessionResponse == k_EAuthSessionResponseOK) { - INFO_LOG("authenticated"); - //SteamGameServerNetworking()->SendP2PPacket(pResponse->m_SteamID, nullptr, NULL, k_EP2PSendUnreliable); - } - else { - INFO_LOG("failed to authenticate, {:X}", pResponse->m_eAuthSessionResponse); - //SteamGameServerNetworking()->SendP2PPacket(pResponse->m_SteamID, nullptr, NULL, k_EP2PSendReliable); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: callback notification - a user wants to talk to us over the P2P channel via the SendP2PPacket() API -// in response, a call to AcceptP2PPacketsFromUser() needs to be made, if you want to talk with them -//----------------------------------------------------------------------------- -void RocketPluginServer::OnP2PSessionRequest(P2PSessionRequest_t* pCallback) -{ - TRACE_LOG("from {}", pCallback->m_steamIDRemote.ConvertToUint64()); - // We'll accept a connection from anyone. - SteamGameServerNetworking()->AcceptP2PSessionWithUser(pCallback->m_steamIDRemote); -} - - -//----------------------------------------------------------------------------- -// Purpose: callback notification - packets can't get through to the specified user via the SendP2PPacket() API -// all packets queued packets unsent at this point will be dropped -// further attempts to send will retry making the connection (but will be dropped if we fail again) -//----------------------------------------------------------------------------- -void RocketPluginServer::OnP2PSessionConnectFail([[maybe_unused]] P2PSessionConnectFail_t* pCallback) -{ - TRACE_LOG("from {}", pCallback->m_steamIDRemote.ConvertToUint64()); - INFO_LOG("dropped connection"); -} \ No newline at end of file diff --git a/source/RocketPlugin/RocketPluginServer.h b/source/RocketPlugin/RocketPluginServer.h deleted file mode 100644 index 660485a..0000000 --- a/source/RocketPlugin/RocketPluginServer.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once -#include "RocketPlugin.h" - -#define STEAM_API_NODLL -#include "SteamWorksWrapper/steam_gameserver.h" - - -class RocketPluginServer -{ -public: - RocketPluginServer() = default; - ~RocketPluginServer() { Stop(); } - RocketPluginServer(const RocketPluginServer&) = delete; - RocketPluginServer(RocketPluginServer&&) = delete; - RocketPluginServer& operator=(const RocketPluginServer&) = delete; - RocketPluginServer& operator=(RocketPluginServer&&) = delete; - - void Start() const; - void Stop() const; - - void SetSettings() const; - void SetRichPresence() const; - void LogStatus() const; - - bool connectedToSteam = false; - bool loggedInToSteam = false; - - int maxPlayerCount = 8; - bool passwordProtected = false; - std::string serverName = "Such Server Many Wow"; - std::string mapName = "Galleon"; - std::string gameTags = "RocketPluginServer"; - -private: - // BUG, Log: Don't use 'IsSteamSocketsServer' on non-listen-server clients; crashing - - /* - * Various callback functions that Steam will call to let us know about events related to our - * connection to the Steam servers for authentication purposes. - */ - - // Tells us when we have successfully connected to Steam - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnSteamServersConnected, SteamServersConnected_t); - - // Tells us when there was a failure to connect to Steam - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnSteamServersConnectFailure, SteamServerConnectFailure_t); - - // Tells us when we have been logged out of Steam - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnSteamServersDisconnected, SteamServersDisconnected_t); - - // Tells us that Steam has set our security policy (VAC on or off) - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnPolicyResponse, GSPolicyResponse_t); - - /* - * Various callback functions that Steam will call to let us know about whether we should - * allow clients to play or we should kick/deny them. - */ - - // Tells us a client has been authenticated and approved to play by Steam (passes auth, license check, VAC status, etc...) - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnValidateAuthTicketResponse, ValidateAuthTicketResponse_t); - - // client connection state - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnP2PSessionRequest, P2PSessionRequest_t); - STEAM_GAMESERVER_CALLBACK(RocketPluginServer, OnP2PSessionConnectFail, P2PSessionConnectFail_t); - - -//#define STEAM_GAMESERVER_CALLBACK_STUB(thisclass, param) \ -// STEAM_GAMESERVER_CALLBACK(thisclass, OnGS ## param, param) { pParam; TRACE_LOG("steam gameserver callback stub"); } -//#define STEAM_CALLBACK_STUB(thisclass, param) \ -// STEAM_CALLBACK(thisclass, On ## param, param) { pParam; TRACE_LOG("steam callback stub"); } -//#define CALLBACK_STUB(thisclass, param) \ -// STEAM_CALLBACK_STUB(thisclass, param) \ -// STEAM_GAMESERVER_CALLBACK_STUB(thisclass, param) -// -// /// isteammatchmakingservers.h callbacks: -// CALLBACK_STUB(RocketPluginServer, FavoritesListChanged_t) -// CALLBACK_STUB(RocketPluginServer, LobbyInvite_t) -// CALLBACK_STUB(RocketPluginServer, LobbyEnter_t) -// CALLBACK_STUB(RocketPluginServer, LobbyDataUpdate_t) -// CALLBACK_STUB(RocketPluginServer, LobbyChatUpdate_t) -// CALLBACK_STUB(RocketPluginServer, LobbyChatMsg_t) -// CALLBACK_STUB(RocketPluginServer, LobbyGameCreated_t) -// CALLBACK_STUB(RocketPluginServer, LobbyMatchList_t) -// CALLBACK_STUB(RocketPluginServer, LobbyKicked_t) -// CALLBACK_STUB(RocketPluginServer, LobbyCreated_t) -// CALLBACK_STUB(RocketPluginServer, PSNGameBootInviteResult_t) -// CALLBACK_STUB(RocketPluginServer, FavoritesListAccountsUpdated_t) -// -// /// isteamfriends.h callbacks: -// CALLBACK_STUB(RocketPluginServer, GameRichPresenceJoinRequested_t) -// -// /// isteamclient.h callbacks: -// CALLBACK_STUB(RocketPluginServer, SteamServersConnected_t) -// CALLBACK_STUB(RocketPluginServer, SteamServerConnectFailure_t) -// CALLBACK_STUB(RocketPluginServer, SteamServersDisconnected_t) -// CALLBACK_STUB(RocketPluginServer, ClientGameServerDeny_t) -// CALLBACK_STUB(RocketPluginServer, IPCFailure_t) -// CALLBACK_STUB(RocketPluginServer, LicensesUpdated_t) -// CALLBACK_STUB(RocketPluginServer, ValidateAuthTicketResponse_t) -// CALLBACK_STUB(RocketPluginServer, MicroTxnAuthorizationResponse_t) -// CALLBACK_STUB(RocketPluginServer, EncryptedAppTicketResponse_t) -// CALLBACK_STUB(RocketPluginServer, GetAuthSessionTicketResponse_t) -// CALLBACK_STUB(RocketPluginServer, GameWebCallback_t) -// CALLBACK_STUB(RocketPluginServer, StoreAuthURLResponse_t) -// -// /// isteamgameserver.h callbacks -// CALLBACK_STUB(RocketPluginServer, GSClientApprove_t) -// CALLBACK_STUB(RocketPluginServer, GSClientDeny_t) -// CALLBACK_STUB(RocketPluginServer, GSClientKick_t) -// CALLBACK_STUB(RocketPluginServer, GSClientAchievementStatus_t) -// CALLBACK_STUB(RocketPluginServer, GSPolicyResponse_t) -// CALLBACK_STUB(RocketPluginServer, GSGameplayStats_t) -// CALLBACK_STUB(RocketPluginServer, GSClientGroupStatus_t) -// CALLBACK_STUB(RocketPluginServer, GSReputation_t) -// CALLBACK_STUB(RocketPluginServer, AssociateWithClanResult_t) -// CALLBACK_STUB(RocketPluginServer, ComputeNewPlayerCompatibilityResult_t) -// -// /// isteamnetworking.h callbacks -// CALLBACK_STUB(RocketPluginServer, P2PSessionRequest_t) -// CALLBACK_STUB(RocketPluginServer, P2PSessionConnectFail_t) -// CALLBACK_STUB(RocketPluginServer, SocketStatusCallback_t) -}; diff --git a/source/RocketPlugin/Version.h b/source/RocketPlugin/Version.h index e32dbb1..4dfa976 100644 --- a/source/RocketPlugin/Version.h +++ b/source/RocketPlugin/Version.h @@ -1,11 +1,11 @@ #pragma once -#define __STRINGIZE(s) #s -#define STRINGIZE(s) __STRINGIZE(s) +#define STRINGIZE2(s) #s +#define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_REVISION 7 -#define VERSION_BUILD 56 +#define VERSION_REVISION 8 +#define VERSION_BUILD 2 #define VER_FILE_DESCRIPTION_STR "Rocket Plugin" #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD diff --git a/source/RocketPlugin/pch.h b/source/RocketPlugin/pch.h index 8deb561..8e7495c 100644 --- a/source/RocketPlugin/pch.h +++ b/source/RocketPlugin/pch.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -50,14 +51,16 @@ #include "utils/exception_safety.h" #include "utils/parser_w.h" -enum { +enum +{ PLUGINTYPE_ALL = 0x00 }; // General Utils -#include "utils/xorstr.h" +#include "utils/timer.h" #include "utils/stringify.h" #include "utils/threading.h" +#include "utils/filesystem.h" #include "utils/exception_safety.h" // Dear ImGui @@ -66,6 +69,7 @@ enum { #include "ImGui/imgui_searchablecombo.h" #include "ImGui/imgui_rangeslider.h" #include "ImGui/imgui_additions.h" +//#include "ImGui/imgui_stdlib.h" // SIMDJson #pragma warning(push, 0) @@ -78,6 +82,7 @@ enum { #include "fmt/ostream.h" #include "fmt/chrono.h" #include "fmt/ranges.h" +#include "fmt/xchar.h" #include "fmt/os.h" #endif //PCH_H