diff --git a/DL2GameOverhaulScript/DL2GameOverhaulScript.vcxproj b/DL2GameOverhaulScript/DL2GameOverhaulScript.vcxproj
index f84411a..3d39862 100644
--- a/DL2GameOverhaulScript/DL2GameOverhaulScript.vcxproj
+++ b/DL2GameOverhaulScript/DL2GameOverhaulScript.vcxproj
@@ -246,7 +246,7 @@
Level3
true
- _DEBUG;DL2GameOverhaulScript_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;_DEBUG;DL2GameOverhaulScript_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
Use
pch.h
@@ -256,19 +256,19 @@
- pch;source\ImGui\freetype\include;source\ImGui;source\MinHook;
+ pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;
$(IntDir)$(TargetName)_$(PlatformTarget).pch
Windows
true
false
- freetype-mtd.lib;libMinHook-x64-v141-mtd.lib;%(AdditionalDependencies)
+ spdlog-mtd.lib;freetype-mtd.lib;libMinHook-x64-v141-mtd.lib;%(AdditionalDependencies)
- source\ImGui\freetype\lib;source\MinHook\lib;
+ source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;
copy /Y "$(SolutionDir)Extra Files\Default Config\EGameTools.ini" "$(SolutionDir)$(PlatformShortName)\$(Configuration)\EGameTools.ini"
@@ -281,12 +281,12 @@
true
true
true
- _WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
true
Use
pch.h
stdcpplatest
- pch;source\ImGui\freetype\include;source\ImGui;source\MinHook;%(AdditionalIncludeDirectories)
+ pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;%(AdditionalIncludeDirectories)
None
false
$(IntDir)$(TargetName)_$(PlatformTarget).pch
@@ -297,8 +297,8 @@
true
false
false
- source\ImGui\freetype\lib;source\MinHook\lib;%(AdditionalLibraryDirectories)
- freetype-mt.lib;libMinHook-x64-v141-mt.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)
+ source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;%(AdditionalLibraryDirectories)
+ spdlog-mt.lib;freetype-mt.lib;libMinHook-x64-v141-mt.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)
/NOIMPLIB /NOEXP %(AdditionalOptions)
diff --git a/DL2GameOverhaulScript/pch/pch.h b/DL2GameOverhaulScript/pch/pch.h
index 80530a8..e532735 100644
--- a/DL2GameOverhaulScript/pch/pch.h
+++ b/DL2GameOverhaulScript/pch/pch.h
@@ -43,6 +43,8 @@
#include
#define IMGUI_DEFINE_MATH_OPERATORS
+#include
+#include
#include
#include
#include
diff --git a/DL2GameOverhaulScript/source/ImGui/imguiex.cpp b/DL2GameOverhaulScript/source/ImGui/imguiex.cpp
index c584ceb..7903b85 100644
--- a/DL2GameOverhaulScript/source/ImGui/imguiex.cpp
+++ b/DL2GameOverhaulScript/source/ImGui/imguiex.cpp
@@ -104,11 +104,11 @@ namespace ImGui {
}
static const float CalculateIndentation(const float window_width, const float text_width, const float min_indentation) {
const float indentation = (window_width - text_width) * 0.5f;
- return indentation > min_indentation ? indentation : min_indentation;
+ return (indentation > min_indentation ? indentation : min_indentation);
}
void TextCentered(const char* text, const bool calculateWithScrollbar) {
const float min_indentation = 20.0f;
- const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? ImGui::GetStyle().ScrollbarSize : 0.0f);
+ const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
const float wrap_pos = window_width - min_indentation;
std::istringstream iss(text);
@@ -136,7 +136,7 @@ namespace ImGui {
}
void TextCenteredColored(const char* text, const ImU32 col, const bool calculateWithScrollbar) {
const float min_indentation = 20.0f;
- const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? ImGui::GetStyle().ScrollbarSize : 0.0f);
+ const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
const float wrap_pos = window_width - min_indentation;
std::istringstream iss(text);
diff --git a/DL2GameOverhaulScript/source/changelog.h b/DL2GameOverhaulScript/source/changelog.h
index bfeac3a..ffeab59 100644
--- a/DL2GameOverhaulScript/source/changelog.h
+++ b/DL2GameOverhaulScript/source/changelog.h
@@ -7,7 +7,7 @@ namespace Changelog {
{ "v1.1.0",
R"(- You can now load custom mod files from "EGameTools\UserModFiles"! Please read the new "Welcome" screen which explains how to use this feature and how to use the rest of the mod menu
- By using the directory mentioned earlier for mod files, you can reload most of them by just reloading the savegame!
-- Mod menu UI revamp
+- Mod menu UI/UX revamp
- Added "Reload Jump Params", using the directory mentioned earlier (Player)
- Added "One-handed Mode" (Player)
@@ -17,9 +17,12 @@ R"(- You can now load custom mod files from "EGameTools\UserModFiles"! Please re
- Added "Game Speed" slider (World)
- Added "Slow Motion", default button is "4" (World)
- Added a "Debug" menu tab (mainly used for troubleshooting)
+- Added logging to file (mainly used for troubleshooting)
- Changed "Menu Transparency" to "Menu Opacity"
- Fixed having a weird offset of the entire map view when FreeCam is enabled
-- Fixed player dying from switching FreeCam off after flying to high altitudes/through walls with “Teleport Player to Camera” option)" }
+- Fixed player dying from switching FreeCam off after flying to high altitudes/through walls with "Teleport Player to Camera" option
+
+That's it for this update! The next few updates will include some more bug fixes rather than new, big features, so stay tuned!)" }
};
}
\ No newline at end of file
diff --git a/DL2GameOverhaulScript/source/config/config.cpp b/DL2GameOverhaulScript/source/config/config.cpp
index 1afc65d..838bcaf 100644
--- a/DL2GameOverhaulScript/source/config/config.cpp
+++ b/DL2GameOverhaulScript/source/config/config.cpp
@@ -4063,12 +4063,10 @@ namespace Config {
{ "World:Time", "SlowMotionTransitionTime", 1.0f, &Menu::World::slowMotionTransitionTime, Float }
});
std::vector configVariables(configVariablesDefault.begin(), configVariablesDefault.end());
- static const char* configFileName = "EGameTools.ini";
+ static constexpr const char* configFileName = "EGameTools.ini";
static std::filesystem::file_time_type configPreviousWriteTime{};
static std::filesystem::file_time_type configLastWriteTime{};
- std::string configStatus{};
- std::string configError{};
static bool savedConfig = false;
static inih::INIReader reader{};
@@ -4131,15 +4129,14 @@ namespace Config {
inih::INIWriter writer{};
writer.write(configFileName, reader);
} catch (const std::runtime_error& e) {
- configError = Utils::PrintError("Error writing file %s: %s", configFileName, e.what());
+ Utils::PrintError("Error writing file {}: {}", configFileName, e.what());
}
}
static bool ConfigExists() {
return std::filesystem::exists(configFileName);
}
static void CreateConfig() {
- configStatus = Utils::PrintWarning("%s does not exist (will create now); using default config values", configFileName);
-
+ Utils::PrintWarning("{} does not exist (will create now); using default config values", configFileName);
LoadAndWriteDefaultConfig();
}
static void ReadConfig(const bool configUpdate = false) {
@@ -4199,10 +4196,9 @@ namespace Config {
}
}
- configStatus = Utils::PrintSuccess(configUpdate ? "Successfully read updated config!" : "Successfully read config!");
+ Utils::PrintInfo(configUpdate ? "Successfully read updated config!" : "Successfully read config!");
} catch (const std::runtime_error& e) {
- configError = Utils::PrintSuccess("Error writing file %s; using default config values: %s", configFileName, e.what());
-
+ Utils::PrintError("Error writing file {}; using default config values: {}", configFileName, e.what());
LoadDefaultConfig();
}
}
@@ -4238,7 +4234,7 @@ namespace Config {
savedConfig = true;
} catch (const std::runtime_error& e) {
- configError = Utils::PrintError("Error saving to file %s: %s", configFileName, e.what());
+ Utils::PrintError("Error saving to file {}: {}", configFileName, e.what());
}
}
void InitConfig() {
diff --git a/DL2GameOverhaulScript/source/core.cpp b/DL2GameOverhaulScript/source/core.cpp
index d6c037f..8bff7f3 100644
--- a/DL2GameOverhaulScript/source/core.cpp
+++ b/DL2GameOverhaulScript/source/core.cpp
@@ -78,6 +78,20 @@ namespace Core {
}
Utils::PrintWarning("Creating game shortcut for \"EGameTools\"");
std::filesystem::create_directory_symlink(Utils::Files::GetCurrentProcDirectory() + "\\EGameTools", "..\\..\\data\\EGameTools");
+ Utils::PrintInfo("Game shortcut created");
+ }
+
+ static void InitLogger() {
+ constexpr size_t maxSize = static_cast(1048576) * 100;
+ constexpr size_t maxFiles = 10;
+
+ static std::vector sinks{};
+ sinks.push_back(std::make_shared("EGameTools\\log.txt", maxSize, maxFiles, true));
+ sinks.push_back(std::make_shared());
+ std::shared_ptr combined_logger = std::make_shared("EGameTools", std::begin(sinks), std::end(sinks));
+ combined_logger->flush_on(spdlog::level::trace);
+
+ spdlog::set_default_logger(combined_logger);
}
void OnPostUpdate() {
@@ -96,27 +110,30 @@ namespace Core {
}
DWORD64 WINAPI MainThread(HMODULE hModule) {
EnableConsole();
+ InitLogger();
- Utils::PrintInfo("Initializing config");
+ Utils::PrintWarning("Initializing config");
Config::InitConfig();
CreateSymlinkForLoadingFiles();
- Utils::PrintInfo("Sorting Player Variables");
+ Utils::PrintWarning("Sorting Player Variables");
GamePH::PlayerVariables::SortPlayerVars();
+ Utils::PrintInfo("Player Variables sorted");
- Utils::PrintInfo("Initializing MinHook");
+ Utils::PrintWarning("Initializing MinHook");
MH_Initialize();
+ Utils::PrintInfo("Initialized MinHook");
- Utils::PrintInfo("Hooking DX11/DX12 renderer");
+ Utils::PrintWarning("Hooking DX11/DX12 renderer");
std::thread([]() {
LoopHookRenderer();
- Utils::PrintSuccess("Hooked DX11/DX12 renderer!");
+ Utils::PrintInfo("Hooked \"DX11/DX12 renderer\"!");
}).detach();
for (auto& hook : *Utils::Hook::HookBase::GetInstances()) {
- Utils::PrintInfo("Hooking %s", hook->name.data());
+ Utils::PrintWarning("Hooking \"{}\"", hook->name.data());
std::thread([&hook]() {
hook->HookLoop();
- Utils::PrintSuccess("Hooked %s!", hook->name.data());
+ Utils::PrintInfo("Hooked \"{}\"!", hook->name.data());
}).detach();
}
@@ -129,12 +146,14 @@ namespace Core {
void Cleanup() {
exiting = true;
- Utils::PrintInfo("Game requested exit, running cleanup");
- Utils::PrintInfo("Saving config to file");
+ Utils::PrintWarning("Game requested exit, running cleanup");
+ Utils::PrintWarning("Saving config to file");
Config::SaveConfig();
+ Utils::PrintInfo("Config saved to file");
- Utils::PrintInfo("Unhooking everything");
+ Utils::PrintWarning("Unhooking everything");
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
+ Utils::PrintInfo("Unhooked everything");
}
}
\ No newline at end of file
diff --git a/DL2GameOverhaulScript/source/core.h b/DL2GameOverhaulScript/source/core.h
index bdc9387..b411b24 100644
--- a/DL2GameOverhaulScript/source/core.h
+++ b/DL2GameOverhaulScript/source/core.h
@@ -5,7 +5,6 @@
#include
#include "..\utils\values.h"
-
#ifndef VK_NONE
#ifdef _DEBUG
diff --git a/DL2GameOverhaulScript/source/game/Engine/engine_hooks.cpp b/DL2GameOverhaulScript/source/game/Engine/engine_hooks.cpp
index 3490bfe..da4106d 100644
--- a/DL2GameOverhaulScript/source/game/Engine/engine_hooks.cpp
+++ b/DL2GameOverhaulScript/source/game/Engine/engine_hooks.cpp
@@ -75,7 +75,7 @@ namespace Engine {
static std::vector cachedUserModDirs{};
static void CacheUserModDirs() {
- Utils::PrintInfo("Recaching user mod directories");
+ Utils::PrintWarning("Recaching user mod directories");
if (!cachedUserModDirs.empty())
cachedUserModDirs.clear();
@@ -110,7 +110,7 @@ namespace Engine {
continue;
const char* filePath2 = finalPath.c_str();
- Utils::PrintWarning("Loading user mod file \"%s\"", filePath2);
+ Utils::PrintWarning("Loading user mod file \"{}\"", filePath2);
return FsOpenHook.pOriginal(firstByte != 0x0 ? (reinterpret_cast(filePath2) | (firstByte << 56)) : reinterpret_cast(filePath2), a2, a3); // restores first byte of addr if first byte was not 0
}
diff --git a/DL2GameOverhaulScript/source/menu/debug.cpp b/DL2GameOverhaulScript/source/menu/debug.cpp
index e2bc5ef..c04a3c1 100644
--- a/DL2GameOverhaulScript/source/menu/debug.cpp
+++ b/DL2GameOverhaulScript/source/menu/debug.cpp
@@ -63,7 +63,7 @@ namespace Menu {
};
static void RenderClassAddrPair(const std::pair* pair) {
- static float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
+ const float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
static std::string labelID{};
labelID = "##DebugAddrInputText" + std::string(pair->first);
diff --git a/DL2GameOverhaulScript/source/menu/init.cpp b/DL2GameOverhaulScript/source/menu/init.cpp
index 5fb9c2d..31fc93a 100644
--- a/DL2GameOverhaulScript/source/menu/init.cpp
+++ b/DL2GameOverhaulScript/source/menu/init.cpp
@@ -4,14 +4,14 @@
#include "menu.h"
namespace Menu {
- static const std::string welcomeTitle = std::string(title + " - Welcome!");
- static const std::string changelogTitle = std::string(title + " - Update Changelog");
+ static std::string welcomeTitle{};
+ static std::string changelogTitle{};
static constexpr ImGuiWindowFlags welcomeWindowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove;
- static constexpr ImVec2 minChangelogWndSize = ImVec2(400.0f, 0.0f);
- static constexpr ImVec2 defMaxChangelogWndSize = ImVec2(400.0f, 700.0f);
- static constexpr ImVec2 minWelcomeWndSize = ImVec2(800.0f, 0.0f);
- static constexpr ImVec2 defMaxWelcomeWndSize = ImVec2(800.0f, 700.0f);
+ static constexpr ImVec2 defMinWndSize = ImVec2(800.0f, 0.0f);
+ static ImVec2 minWndSize = defMinWndSize;
+ static constexpr ImVec2 defMaxWndSize = ImVec2(800.0f, 700.0f);
+ static ImVec2 maxWndSize = defMaxWndSize;
static Utils::Time::Timer timePassedFromWelcomeScreen{};
@@ -39,7 +39,7 @@ namespace Menu {
static void RenderWelcomeScreen() {
ImGui::SetNextWindowBgAlpha(1.0f);
- ImGui::SetNextWindowSizeConstraints(minWelcomeWndSize, defMaxWelcomeWndSize);
+ ImGui::SetNextWindowSizeConstraints(minWndSize, maxWndSize);
if (ImGui::BeginPopupModal(welcomeTitle.c_str(), nullptr, welcomeWindowFlags)) {
ImGui::TextCenteredColored("PLEASE read the following text!", IM_COL32(230, 0, 0, 255));
ImGui::Spacing(ImVec2(0.0f, 5.0f));
@@ -114,6 +114,10 @@ namespace Menu {
ImGui::TextCentered("You DO NOT NEED to restart the game for the changes in the config to be applied!");
ImGui::TextCentered("If you want to regenerate the config file, delete it and it will automatically be regenerated.");
+ ImGui::SeparatorTextColored("Logging", IM_COL32(200, 0, 0, 255));
+ ImGui::NewLine();
+ ImGui::TextCentered("Log files will be stored in the EGameTools folder as \"log.x.txt\", x being the number of the previous log file. The most recent log file will be called \"log.txt\".");
+
ImGui::Separator();
ImGui::NewLine();
ImGui::TextCentered("Finally, if you've got any issue, no matter how small, please make sure to report it! I will try my best to fix it. I want this mod to be polished and enjoyable to use!");
@@ -123,7 +127,7 @@ namespace Menu {
ImGui::BeginDisabled(!timePassedFromWelcomeScreen.DidTimePass());
{
const std::string btnText = "Let me play!" + (!timePassedFromWelcomeScreen.DidTimePass() ? (" (" + std::to_string(10 - (timePassedFromWelcomeScreen.GetTimePassed() / 1000)) + ")") : "");
- if (ImGui::ButtonCentered(btnText.c_str(), ImVec2(0.0f, 30.0f))) {
+ if (ImGui::ButtonCentered(btnText.c_str(), ImVec2(0.0f, 30.0f) * scale)) {
ImGui::CloseCurrentPopup();
firstTimeRunning.Set(false);
if (hasSeenChangelog.GetValue())
@@ -136,7 +140,7 @@ namespace Menu {
}
static void RenderChangelog() {
ImGui::SetNextWindowBgAlpha(1.0f);
- ImGui::SetNextWindowSizeConstraints(minChangelogWndSize, defMaxChangelogWndSize);
+ ImGui::SetNextWindowSizeConstraints(minWndSize, maxWndSize);
if (ImGui::BeginPopupModal(changelogTitle.c_str(), nullptr, welcomeWindowFlags)) {
const std::string subTitle = "This is what the " + std::string(MOD_VERSION_STR) + " update brings:";
ImGui::TextCenteredColored(subTitle.c_str(), IM_COL32(230, 0, 0, 255), false);
@@ -152,7 +156,7 @@ namespace Menu {
ImGui::TextCentered(line.c_str(), false);
}
- if (ImGui::ButtonCentered("Close", ImVec2(0.0f, 30.0f))) {
+ if (ImGui::ButtonCentered("Close", ImVec2(0.0f, 30.0f) * scale)) {
ImGui::CloseCurrentPopup();
menuToggle.SetChangesAreDisabled(false);
hasSeenChangelog.Set(true);
@@ -172,11 +176,19 @@ namespace Menu {
return;
}
+ ImGui::StyleScaleAllSizes(&ImGui::GetStyle(), scale, &defStyle);
+ ImGui::GetIO().FontGlobalScale = scale;
+ minWndSize = defMinWndSize * scale;
+ maxWndSize = defMaxWndSize * scale;
+
if (firstTimeRunningFunc) {
firstTimeRunningFunc = false;
timePassedFromWelcomeScreen = Utils::Time::Timer(10000);
menuToggle.SetChangesAreDisabled(true);
+ welcomeTitle = std::string(title + " - Welcome!");
+ changelogTitle = std::string(title + " - Update Changelog");
+
if (firstTimeRunning.GetValue())
ImGui::OpenPopup(welcomeTitle.c_str());
else if (!hasSeenChangelog.GetValue())
diff --git a/DL2GameOverhaulScript/source/menu/menu.cpp b/DL2GameOverhaulScript/source/menu/menu.cpp
index e9d77d4..d7d76eb 100644
--- a/DL2GameOverhaulScript/source/menu/menu.cpp
+++ b/DL2GameOverhaulScript/source/menu/menu.cpp
@@ -5,9 +5,12 @@ namespace Menu {
const std::string title = "EGameTools (" + std::string(MOD_VERSION_STR) + ")";
ImGuiStyle defStyle{};
ImTextureID EGTLogoTexture{};
+ static constexpr ImVec2 defEGTLogoSize = ImVec2(278.0f, 100.0f);
+ static ImVec2 EGTLogoSize = defEGTLogoSize;
static constexpr ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar;
- static constexpr ImVec2 minWndSize = ImVec2(425.0f, 725.0f);
+ static constexpr ImVec2 defMinWndSize = ImVec2(425.0f, 725.0f);
+ static ImVec2 minWndSize = defMinWndSize;
static constexpr ImVec2 defMaxWndSize = ImVec2(900.0f, 725.0f);
static ImVec2 maxWndSize = defMaxWndSize;
@@ -19,12 +22,17 @@ namespace Menu {
Option hasSeenChangelog{};
void Render() {
+ ImGui::StyleScaleAllSizes(&ImGui::GetStyle(), scale, &defStyle);
+ ImGui::GetIO().FontGlobalScale = scale;
+ minWndSize = defMinWndSize * scale;
maxWndSize = defMaxWndSize * scale;
+ EGTLogoSize = defEGTLogoSize * scale;
+
ImGui::SetNextWindowBgAlpha(static_cast(opacity) / 100.0f);
ImGui::SetNextWindowSizeConstraints(minWndSize, maxWndSize);
ImGui::Begin(title.c_str(), &menuToggle.value, windowFlags); {
- ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.0f) - 278.0f / 2.0f);
- ImGui::Image(EGTLogoTexture, ImVec2(278.0f * scale, 100.0f * scale));
+ ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.0f) - (EGTLogoSize.x / 2.0f));
+ ImGui::Image(EGTLogoTexture, EGTLogoSize);
const float footerHeight = ImGui::GetFrameHeightWithSpacing() * 3.0f + GImGui->Style.WindowPadding.y * 2.0f + GImGui->Style.FramePadding.y * 2.0f;
const float remainingHeight = ImGui::GetContentRegionAvail().y - footerHeight;
@@ -50,10 +58,7 @@ namespace Menu {
ImGui::Hotkey("Menu Toggle Key", &menuToggle);
ImGui::SliderFloat("Menu Opacity", &opacity, 0.0f, 100.0f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp);
- if (ImGui::SliderFloat("Menu Scale", &scale, 1.0f, 2.5f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp)) {
- ImGui::StyleScaleAllSizes(&ImGui::GetStyle(), scale, &defStyle);
- ImGui::GetIO().FontGlobalScale = scale;
- }
+ ImGui::SliderFloat("Menu Scale", &scale, 1.0f, 2.5f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp);
ImGui::End();
}
}
diff --git a/DL2GameOverhaulScript/source/menu/misc.cpp b/DL2GameOverhaulScript/source/menu/misc.cpp
index c555b41..0e23a64 100644
--- a/DL2GameOverhaulScript/source/menu/misc.cpp
+++ b/DL2GameOverhaulScript/source/menu/misc.cpp
@@ -5,8 +5,8 @@
namespace Menu {
namespace Misc {
- KeyBindOption disableHUD{ VK_F8 };
KeyBindOption disableGamePauseWhileAFK{ VK_NONE };
+ KeyBindOption disableHUD{ VK_F8 };
static void UpdateDisabledOptions() {
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
@@ -39,12 +39,11 @@ namespace Menu {
}
void Tab::Render() {
ImGui::SeparatorText("Misc##Misc");
+ ImGui::CheckboxHotkey("Disable Game Pause While AFK", &disableGamePauseWhileAFK);
ImGui::BeginDisabled(disableHUD.GetChangesAreDisabled()); {
ImGui::CheckboxHotkey("Disable HUD", &disableHUD);
ImGui::EndDisabled();
}
- ImGui::SameLine();
- ImGui::CheckboxHotkey("Disable Game Pause While AFK", &disableGamePauseWhileAFK);
}
}
}
\ No newline at end of file
diff --git a/DL2GameOverhaulScript/source/menu/misc.h b/DL2GameOverhaulScript/source/menu/misc.h
index d55c585..815f8a1 100644
--- a/DL2GameOverhaulScript/source/menu/misc.h
+++ b/DL2GameOverhaulScript/source/menu/misc.h
@@ -3,8 +3,8 @@
namespace Menu {
namespace Misc {
- extern KeyBindOption disableHUD;
extern KeyBindOption disableGamePauseWhileAFK;
+ extern KeyBindOption disableHUD;
class Tab : MenuTab {
public:
diff --git a/DL2GameOverhaulScript/source/menu/player.cpp b/DL2GameOverhaulScript/source/menu/player.cpp
index 9ec211f..eb9251c 100644
--- a/DL2GameOverhaulScript/source/menu/player.cpp
+++ b/DL2GameOverhaulScript/source/menu/player.cpp
@@ -6325,7 +6325,7 @@ namespace Menu {
if (ImGui::Button(restoreBtnName.c_str()))
RestoreVariableToDefault(key);
if (debugEnabled) {
- static float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
+ const float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
static std::string labelID{};
labelID = "##DebugAddrInputText" + std::string(key);
const DWORD64 finalAddr = floatVarAddr ? reinterpret_cast(floatVarAddr) : reinterpret_cast(boolVarAddr);
diff --git a/DL2GameOverhaulScript/source/spdlog/LICENSE b/DL2GameOverhaulScript/source/spdlog/LICENSE
new file mode 100644
index 0000000..6546da0
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/LICENSE
@@ -0,0 +1,26 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Gabi Melman.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+-- NOTE: Third party dependency used by this software --
+This software depends on the fmt lib (MIT License),
+and users must comply to its license: https://raw.githubusercontent.com/fmtlib/fmt/master/LICENSE
+
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/async.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async.h
new file mode 100644
index 0000000..e96abd1
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async.h
@@ -0,0 +1,100 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+//
+// Async logging using global thread pool
+// All loggers created here share same global thread pool.
+// Each log message is pushed to a queue along with a shared pointer to the
+// logger.
+// If a logger deleted while having pending messages in the queue, it's actual
+// destruction will defer
+// until all its messages are processed by the thread pool.
+// This is because each message in the queue holds a shared_ptr to the
+// originating logger.
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+namespace spdlog {
+
+namespace details {
+static const size_t default_async_q_size = 8192;
+}
+
+// async logger factory - creates async loggers backed with thread pool.
+// if a global thread pool doesn't already exist, create it with default queue
+// size of 8192 items and single thread.
+template
+struct async_factory_impl {
+ template
+ static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) {
+ auto ®istry_inst = details::registry::instance();
+
+ // create global thread pool if not already exists..
+
+ auto &mutex = registry_inst.tp_mutex();
+ std::lock_guard tp_lock(mutex);
+ auto tp = registry_inst.get_tp();
+ if (tp == nullptr) {
+ tp = std::make_shared(details::default_async_q_size, 1U);
+ registry_inst.set_tp(tp);
+ }
+
+ auto sink = std::make_shared(std::forward(args)...);
+ auto new_logger = std::make_shared(std::move(logger_name), std::move(sink),
+ std::move(tp), OverflowPolicy);
+ registry_inst.initialize_logger(new_logger);
+ return new_logger;
+ }
+};
+
+using async_factory = async_factory_impl;
+using async_factory_nonblock = async_factory_impl;
+
+template
+inline std::shared_ptr create_async(std::string logger_name,
+ SinkArgs &&...sink_args) {
+ return async_factory::create(std::move(logger_name),
+ std::forward(sink_args)...);
+}
+
+template
+inline std::shared_ptr create_async_nb(std::string logger_name,
+ SinkArgs &&...sink_args) {
+ return async_factory_nonblock::create(std::move(logger_name),
+ std::forward(sink_args)...);
+}
+
+// set global thread pool.
+inline void init_thread_pool(size_t q_size,
+ size_t thread_count,
+ std::function on_thread_start,
+ std::function on_thread_stop) {
+ auto tp = std::make_shared(q_size, thread_count, on_thread_start,
+ on_thread_stop);
+ details::registry::instance().set_tp(std::move(tp));
+}
+
+inline void init_thread_pool(size_t q_size,
+ size_t thread_count,
+ std::function on_thread_start) {
+ init_thread_pool(q_size, thread_count, on_thread_start, [] {});
+}
+
+inline void init_thread_pool(size_t q_size, size_t thread_count) {
+ init_thread_pool(
+ q_size, thread_count, [] {}, [] {});
+}
+
+// get the global thread pool.
+inline std::shared_ptr thread_pool() {
+ return details::registry::instance().get_tp();
+}
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger-inl.h
new file mode 100644
index 0000000..1e79479
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger-inl.h
@@ -0,0 +1,84 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+#include
+#include
+
+#include
+#include
+
+SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name,
+ sinks_init_list sinks_list,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy)
+ : async_logger(std::move(logger_name),
+ sinks_list.begin(),
+ sinks_list.end(),
+ std::move(tp),
+ overflow_policy) {}
+
+SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name,
+ sink_ptr single_sink,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy)
+ : async_logger(
+ std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) {}
+
+// send the log message to the thread pool
+SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg){
+ SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){
+ pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
+}
+else {
+ throw_spdlog_ex("async log: thread pool doesn't exist anymore");
+}
+}
+SPDLOG_LOGGER_CATCH(msg.source)
+}
+
+// send flush request to the thread pool
+SPDLOG_INLINE void spdlog::async_logger::flush_(){
+ SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){
+ pool_ptr->post_flush(shared_from_this(), overflow_policy_);
+}
+else {
+ throw_spdlog_ex("async flush: thread pool doesn't exist anymore");
+}
+}
+SPDLOG_LOGGER_CATCH(source_loc())
+}
+
+//
+// backend functions - called from the thread pool to do the actual job
+//
+SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) {
+ for (auto &sink : sinks_) {
+ if (sink->should_log(msg.level)) {
+ SPDLOG_TRY { sink->log(msg); }
+ SPDLOG_LOGGER_CATCH(msg.source)
+ }
+ }
+
+ if (should_flush_(msg)) {
+ backend_flush_();
+ }
+}
+
+SPDLOG_INLINE void spdlog::async_logger::backend_flush_() {
+ for (auto &sink : sinks_) {
+ SPDLOG_TRY { sink->flush(); }
+ SPDLOG_LOGGER_CATCH(source_loc())
+ }
+}
+
+SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) {
+ auto cloned = std::make_shared(*this);
+ cloned->name_ = std::move(new_name);
+ return cloned;
+}
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger.h
new file mode 100644
index 0000000..846c4c6
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/async_logger.h
@@ -0,0 +1,74 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+// Fast asynchronous logger.
+// Uses pre allocated queue.
+// Creates a single back thread to pop messages from the queue and log them.
+//
+// Upon each log write the logger:
+// 1. Checks if its log level is enough to log the message
+// 2. Push a new copy of the message to a queue (or block the caller until
+// space is available in the queue)
+// Upon destruction, logs all remaining messages in the queue before
+// destructing..
+
+#include
+
+namespace spdlog {
+
+// Async overflow policy - block by default.
+enum class async_overflow_policy {
+ block, // Block until message can be enqueued
+ overrun_oldest, // Discard oldest message in the queue if full when trying to
+ // add new item.
+ discard_new // Discard new message if the queue is full when trying to add new item.
+};
+
+namespace details {
+class thread_pool;
+}
+
+class SPDLOG_API async_logger final : public std::enable_shared_from_this,
+ public logger {
+ friend class details::thread_pool;
+
+public:
+ template
+ async_logger(std::string logger_name,
+ It begin,
+ It end,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block)
+ : logger(std::move(logger_name), begin, end),
+ thread_pool_(std::move(tp)),
+ overflow_policy_(overflow_policy) {}
+
+ async_logger(std::string logger_name,
+ sinks_init_list sinks_list,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block);
+
+ async_logger(std::string logger_name,
+ sink_ptr single_sink,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block);
+
+ std::shared_ptr clone(std::string new_name) override;
+
+protected:
+ void sink_it_(const details::log_msg &msg) override;
+ void flush_() override;
+ void backend_sink_it_(const details::log_msg &incoming_log_msg);
+ void backend_flush_();
+
+private:
+ std::weak_ptr thread_pool_;
+ async_overflow_policy overflow_policy_;
+};
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "async_logger-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/argv.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/argv.h
new file mode 100644
index 0000000..7de2f83
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/argv.h
@@ -0,0 +1,40 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+#include
+#include
+
+//
+// Init log levels using each argv entry that starts with "SPDLOG_LEVEL="
+//
+// set all loggers to debug level:
+// example.exe "SPDLOG_LEVEL=debug"
+
+// set logger1 to trace level
+// example.exe "SPDLOG_LEVEL=logger1=trace"
+
+// turn off all logging except for logger1 and logger2:
+// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info"
+
+namespace spdlog {
+namespace cfg {
+
+// search for SPDLOG_LEVEL= in the args and use it to init the levels
+inline void load_argv_levels(int argc, const char **argv) {
+ const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
+ for (int i = 1; i < argc; i++) {
+ std::string arg = argv[i];
+ if (arg.find(spdlog_level_prefix) == 0) {
+ auto levels_string = arg.substr(spdlog_level_prefix.size());
+ helpers::load_levels(levels_string);
+ }
+ }
+}
+
+inline void load_argv_levels(int argc, char **argv) {
+ load_argv_levels(argc, const_cast(argv));
+}
+
+} // namespace cfg
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/env.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/env.h
new file mode 100644
index 0000000..6e55414
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/env.h
@@ -0,0 +1,36 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+#include
+#include
+#include
+
+//
+// Init levels and patterns from env variables SPDLOG_LEVEL
+// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger).
+// Note - fallback to "info" level on unrecognized levels
+//
+// Examples:
+//
+// set global level to debug:
+// export SPDLOG_LEVEL=debug
+//
+// turn off all logging except for logger1:
+// export SPDLOG_LEVEL="*=off,logger1=debug"
+//
+
+// turn off all logging except for logger1 and logger2:
+// export SPDLOG_LEVEL="off,logger1=debug,logger2=info"
+
+namespace spdlog {
+namespace cfg {
+inline void load_env_levels() {
+ auto env_val = details::os::getenv("SPDLOG_LEVEL");
+ if (!env_val.empty()) {
+ helpers::load_levels(env_val);
+ }
+}
+
+} // namespace cfg
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers-inl.h
new file mode 100644
index 0000000..93650a2
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers-inl.h
@@ -0,0 +1,107 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace spdlog {
+namespace cfg {
+namespace helpers {
+
+// inplace convert to lowercase
+inline std::string &to_lower_(std::string &str) {
+ std::transform(str.begin(), str.end(), str.begin(), [](char ch) {
+ return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch);
+ });
+ return str;
+}
+
+// inplace trim spaces
+inline std::string &trim_(std::string &str) {
+ const char *spaces = " \n\r\t";
+ str.erase(str.find_last_not_of(spaces) + 1);
+ str.erase(0, str.find_first_not_of(spaces));
+ return str;
+}
+
+// return (name,value) trimmed pair from given "name=value" string.
+// return empty string on missing parts
+// "key=val" => ("key", "val")
+// " key = val " => ("key", "val")
+// "key=" => ("key", "")
+// "val" => ("", "val")
+
+inline std::pair extract_kv_(char sep, const std::string &str) {
+ auto n = str.find(sep);
+ std::string k, v;
+ if (n == std::string::npos) {
+ v = str;
+ } else {
+ k = str.substr(0, n);
+ v = str.substr(n + 1);
+ }
+ return std::make_pair(trim_(k), trim_(v));
+}
+
+// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.."
+// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
+inline std::unordered_map extract_key_vals_(const std::string &str) {
+ std::string token;
+ std::istringstream token_stream(str);
+ std::unordered_map rv{};
+ while (std::getline(token_stream, token, ',')) {
+ if (token.empty()) {
+ continue;
+ }
+ auto kv = extract_kv_('=', token);
+ rv[kv.first] = kv.second;
+ }
+ return rv;
+}
+
+SPDLOG_INLINE void load_levels(const std::string &input) {
+ if (input.empty() || input.size() > 512) {
+ return;
+ }
+
+ auto key_vals = extract_key_vals_(input);
+ std::unordered_map levels;
+ level::level_enum global_level = level::info;
+ bool global_level_found = false;
+
+ for (auto &name_level : key_vals) {
+ auto &logger_name = name_level.first;
+ auto level_name = to_lower_(name_level.second);
+ auto level = level::from_str(level_name);
+ // ignore unrecognized level names
+ if (level == level::off && level_name != "off") {
+ continue;
+ }
+ if (logger_name.empty()) // no logger name indicate global level
+ {
+ global_level_found = true;
+ global_level = level;
+ } else {
+ levels[logger_name] = level;
+ }
+ }
+
+ details::registry::instance().set_levels(std::move(levels),
+ global_level_found ? &global_level : nullptr);
+}
+
+} // namespace helpers
+} // namespace cfg
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers.h
new file mode 100644
index 0000000..c023818
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/cfg/helpers.h
@@ -0,0 +1,29 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+namespace spdlog {
+namespace cfg {
+namespace helpers {
+//
+// Init levels from given string
+//
+// Examples:
+//
+// set global level to debug: "debug"
+// turn off all logging except for logger1: "off,logger1=debug"
+// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info"
+//
+SPDLOG_API void load_levels(const std::string &txt);
+} // namespace helpers
+
+} // namespace cfg
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "helpers-inl.h"
+#endif // SPDLOG_HEADER_ONLY
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/common-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/common-inl.h
new file mode 100644
index 0000000..a8a0453
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/common-inl.h
@@ -0,0 +1,68 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+#include
+#include
+
+namespace spdlog {
+namespace level {
+
+#if __cplusplus >= 201703L
+constexpr
+#endif
+ static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
+
+static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
+
+SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT {
+ return level_string_views[l];
+}
+
+SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT {
+ return short_level_names[l];
+}
+
+SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT {
+ auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name);
+ if (it != std::end(level_string_views))
+ return static_cast(std::distance(std::begin(level_string_views), it));
+
+ // check also for "warn" and "err" before giving up..
+ if (name == "warn") {
+ return level::warn;
+ }
+ if (name == "err") {
+ return level::err;
+ }
+ return level::off;
+}
+} // namespace level
+
+SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg)
+ : msg_(std::move(msg)) {}
+
+SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) {
+#ifdef SPDLOG_USE_STD_FORMAT
+ msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what();
+#else
+ memory_buf_t outbuf;
+ fmt::format_system_error(outbuf, last_errno, msg.c_str());
+ msg_ = fmt::to_string(outbuf);
+#endif
+}
+
+SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT { return msg_.c_str(); }
+
+SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) {
+ SPDLOG_THROW(spdlog_ex(msg, last_errno));
+}
+
+SPDLOG_INLINE void throw_spdlog_ex(std::string msg) { SPDLOG_THROW(spdlog_ex(std::move(msg))); }
+
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/common.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/common.h
new file mode 100644
index 0000000..1269c14
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/common.h
@@ -0,0 +1,411 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef SPDLOG_USE_STD_FORMAT
+ #include
+ #if __cpp_lib_format >= 202207L
+ #include
+ #else
+ #include
+ #endif
+#endif
+
+#ifdef SPDLOG_COMPILED_LIB
+ #undef SPDLOG_HEADER_ONLY
+ #if defined(SPDLOG_SHARED_LIB)
+ #if defined(_WIN32)
+ #ifdef spdlog_EXPORTS
+ #define SPDLOG_API __declspec(dllexport)
+ #else // !spdlog_EXPORTS
+ #define SPDLOG_API __declspec(dllimport)
+ #endif
+ #else // !defined(_WIN32)
+ #define SPDLOG_API __attribute__((visibility("default")))
+ #endif
+ #else // !defined(SPDLOG_SHARED_LIB)
+ #define SPDLOG_API
+ #endif
+ #define SPDLOG_INLINE
+#else // !defined(SPDLOG_COMPILED_LIB)
+ #define SPDLOG_API
+ #define SPDLOG_HEADER_ONLY
+ #define SPDLOG_INLINE inline
+#endif // #ifdef SPDLOG_COMPILED_LIB
+
+#include
+
+#if !defined(SPDLOG_USE_STD_FORMAT) && \
+ FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8
+ #define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string)
+ #define SPDLOG_FMT_STRING(format_string) FMT_STRING(format_string)
+ #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
+ #include
+ #endif
+#else
+ #define SPDLOG_FMT_RUNTIME(format_string) format_string
+ #define SPDLOG_FMT_STRING(format_string) format_string
+#endif
+
+// visual studio up to 2013 does not support noexcept nor constexpr
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ #define SPDLOG_NOEXCEPT _NOEXCEPT
+ #define SPDLOG_CONSTEXPR
+#else
+ #define SPDLOG_NOEXCEPT noexcept
+ #define SPDLOG_CONSTEXPR constexpr
+#endif
+
+// If building with std::format, can just use constexpr, otherwise if building with fmt
+// SPDLOG_CONSTEXPR_FUNC needs to be set the same as FMT_CONSTEXPR to avoid situations where
+// a constexpr function in spdlog could end up calling a non-constexpr function in fmt
+// depending on the compiler
+// If fmt determines it can't use constexpr, we should inline the function instead
+#ifdef SPDLOG_USE_STD_FORMAT
+ #define SPDLOG_CONSTEXPR_FUNC constexpr
+#else // Being built with fmt
+ #if FMT_USE_CONSTEXPR
+ #define SPDLOG_CONSTEXPR_FUNC FMT_CONSTEXPR
+ #else
+ #define SPDLOG_CONSTEXPR_FUNC inline
+ #endif
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+ #define SPDLOG_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+ #define SPDLOG_DEPRECATED __declspec(deprecated)
+#else
+ #define SPDLOG_DEPRECATED
+#endif
+
+// disable thread local on msvc 2013
+#ifndef SPDLOG_NO_TLS
+ #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt)
+ #define SPDLOG_NO_TLS 1
+ #endif
+#endif
+
+#ifndef SPDLOG_FUNCTION
+ #define SPDLOG_FUNCTION static_cast(__FUNCTION__)
+#endif
+
+#ifdef SPDLOG_NO_EXCEPTIONS
+ #define SPDLOG_TRY
+ #define SPDLOG_THROW(ex) \
+ do { \
+ printf("spdlog fatal error: %s\n", ex.what()); \
+ std::abort(); \
+ } while (0)
+ #define SPDLOG_CATCH_STD
+#else
+ #define SPDLOG_TRY try
+ #define SPDLOG_THROW(ex) throw(ex)
+ #define SPDLOG_CATCH_STD \
+ catch (const std::exception &) { \
+ }
+#endif
+
+namespace spdlog {
+
+class formatter;
+
+namespace sinks {
+class sink;
+}
+
+#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
+using filename_t = std::wstring;
+ // allow macro expansion to occur in SPDLOG_FILENAME_T
+ #define SPDLOG_FILENAME_T_INNER(s) L##s
+ #define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)
+#else
+using filename_t = std::string;
+ #define SPDLOG_FILENAME_T(s) s
+#endif
+
+using log_clock = std::chrono::system_clock;
+using sink_ptr = std::shared_ptr;
+using sinks_init_list = std::initializer_list;
+using err_handler = std::function;
+#ifdef SPDLOG_USE_STD_FORMAT
+namespace fmt_lib = std;
+
+using string_view_t = std::string_view;
+using memory_buf_t = std::string;
+
+template
+ #if __cpp_lib_format >= 202207L
+using format_string_t = std::format_string;
+ #else
+using format_string_t = std::string_view;
+ #endif
+
+template
+struct is_convertible_to_basic_format_string
+ : std::integral_constant>::value> {};
+
+ #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
+using wstring_view_t = std::wstring_view;
+using wmemory_buf_t = std::wstring;
+
+template
+ #if __cpp_lib_format >= 202207L
+using wformat_string_t = std::wformat_string;
+ #else
+using wformat_string_t = std::wstring_view;
+ #endif
+ #endif
+ #define SPDLOG_BUF_TO_STRING(x) x
+#else // use fmt lib instead of std::format
+namespace fmt_lib = fmt;
+
+using string_view_t = fmt::basic_string_view;
+using memory_buf_t = fmt::basic_memory_buffer;
+
+template
+using format_string_t = fmt::format_string;
+
+template
+using remove_cvref_t = typename std::remove_cv::type>::type;
+
+template
+ #if FMT_VERSION >= 90101
+using fmt_runtime_string = fmt::runtime_format_string;
+ #else
+using fmt_runtime_string = fmt::basic_runtime;
+ #endif
+
+// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the
+// condition from basic_format_string here, in addition, fmt::basic_runtime is only
+// convertible to basic_format_string but not basic_string_view
+template
+struct is_convertible_to_basic_format_string
+ : std::integral_constant>::value ||
+ std::is_same, fmt_runtime_string>::value> {
+};
+
+ #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
+using wstring_view_t = fmt::basic_string_view;
+using wmemory_buf_t = fmt::basic_memory_buffer;
+
+template
+using wformat_string_t = fmt::wformat_string;
+ #endif
+ #define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x)
+#endif
+
+#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
+ #ifndef _WIN32
+ #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows
+ #endif // _WIN32
+#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
+
+template
+struct is_convertible_to_any_format_string
+ : std::integral_constant::value ||
+ is_convertible_to_basic_format_string::value> {};
+
+#if defined(SPDLOG_NO_ATOMIC_LEVELS)
+using level_t = details::null_atomic_int;
+#else
+using level_t = std::atomic;
+#endif
+
+#define SPDLOG_LEVEL_TRACE 0
+#define SPDLOG_LEVEL_DEBUG 1
+#define SPDLOG_LEVEL_INFO 2
+#define SPDLOG_LEVEL_WARN 3
+#define SPDLOG_LEVEL_ERROR 4
+#define SPDLOG_LEVEL_CRITICAL 5
+#define SPDLOG_LEVEL_OFF 6
+
+#if !defined(SPDLOG_ACTIVE_LEVEL)
+ #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
+#endif
+
+// Log level enum
+namespace level {
+enum level_enum : int {
+ trace = SPDLOG_LEVEL_TRACE,
+ debug = SPDLOG_LEVEL_DEBUG,
+ info = SPDLOG_LEVEL_INFO,
+ warn = SPDLOG_LEVEL_WARN,
+ err = SPDLOG_LEVEL_ERROR,
+ critical = SPDLOG_LEVEL_CRITICAL,
+ off = SPDLOG_LEVEL_OFF,
+ n_levels
+};
+
+#define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t("trace", 5)
+#define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t("debug", 5)
+#define SPDLOG_LEVEL_NAME_INFO spdlog::string_view_t("info", 4)
+#define SPDLOG_LEVEL_NAME_WARNING spdlog::string_view_t("warning", 7)
+#define SPDLOG_LEVEL_NAME_ERROR spdlog::string_view_t("error", 5)
+#define SPDLOG_LEVEL_NAME_CRITICAL spdlog::string_view_t("critical", 8)
+#define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t("off", 3)
+
+#if !defined(SPDLOG_LEVEL_NAMES)
+ #define SPDLOG_LEVEL_NAMES \
+ { \
+ SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \
+ SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \
+ SPDLOG_LEVEL_NAME_OFF \
+ }
+#endif
+
+#if !defined(SPDLOG_SHORT_LEVEL_NAMES)
+
+ #define SPDLOG_SHORT_LEVEL_NAMES \
+ { "T", "D", "I", "W", "E", "C", "O" }
+#endif
+
+SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
+SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
+SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
+
+} // namespace level
+
+//
+// Color mode used by sinks with color support.
+//
+enum class color_mode { always, automatic, never };
+
+//
+// Pattern time - specific time getting to use for pattern_formatter.
+// local time by default
+//
+enum class pattern_time_type {
+ local, // log localtime
+ utc // log utc
+};
+
+//
+// Log exception
+//
+class SPDLOG_API spdlog_ex : public std::exception {
+public:
+ explicit spdlog_ex(std::string msg);
+ spdlog_ex(const std::string &msg, int last_errno);
+ const char *what() const SPDLOG_NOEXCEPT override;
+
+private:
+ std::string msg_;
+};
+
+[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
+[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
+
+struct source_loc {
+ SPDLOG_CONSTEXPR source_loc() = default;
+ SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in)
+ : filename{filename_in},
+ line{line_in},
+ funcname{funcname_in} {}
+
+ SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line == 0; }
+ const char *filename{nullptr};
+ int line{0};
+ const char *funcname{nullptr};
+};
+
+struct file_event_handlers {
+ file_event_handlers()
+ : before_open(nullptr),
+ after_open(nullptr),
+ before_close(nullptr),
+ after_close(nullptr) {}
+
+ std::function before_open;
+ std::function after_open;
+ std::function before_close;
+ std::function after_close;
+};
+
+namespace details {
+
+// to_string_view
+
+SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf)
+ SPDLOG_NOEXCEPT {
+ return spdlog::string_view_t{buf.data(), buf.size()};
+}
+
+SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str)
+ SPDLOG_NOEXCEPT {
+ return str;
+}
+
+#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
+SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf)
+ SPDLOG_NOEXCEPT {
+ return spdlog::wstring_view_t{buf.data(), buf.size()};
+}
+
+SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str)
+ SPDLOG_NOEXCEPT {
+ return str;
+}
+#endif
+
+#ifndef SPDLOG_USE_STD_FORMAT
+template
+inline fmt::basic_string_view to_string_view(fmt::basic_format_string fmt) {
+ return fmt;
+}
+#elif __cpp_lib_format >= 202207L
+template
+SPDLOG_CONSTEXPR_FUNC std::basic_string_view to_string_view(
+ std::basic_format_string fmt) SPDLOG_NOEXCEPT {
+ return fmt.get();
+}
+#endif
+
+// make_unique support for pre c++14
+#if __cplusplus >= 201402L // C++14 and beyond
+using std::enable_if_t;
+using std::make_unique;
+#else
+template
+using enable_if_t = typename std::enable_if::type;
+
+template
+std::unique_ptr make_unique(Args &&...args) {
+ static_assert(!std::is_array::value, "arrays not supported");
+ return std::unique_ptr(new T(std::forward(args)...));
+}
+#endif
+
+// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
+template ::value, int> = 0>
+constexpr T conditional_static_cast(U value) {
+ return static_cast(value);
+}
+
+template ::value, int> = 0>
+constexpr T conditional_static_cast(U value) {
+ return value;
+}
+
+} // namespace details
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "common-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer-inl.h
new file mode 100644
index 0000000..43d1002
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer-inl.h
@@ -0,0 +1,63 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+namespace spdlog {
+namespace details {
+SPDLOG_INLINE backtracer::backtracer(const backtracer &other) {
+ std::lock_guard lock(other.mutex_);
+ enabled_ = other.enabled();
+ messages_ = other.messages_;
+}
+
+SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT {
+ std::lock_guard lock(other.mutex_);
+ enabled_ = other.enabled();
+ messages_ = std::move(other.messages_);
+}
+
+SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) {
+ std::lock_guard lock(mutex_);
+ enabled_ = other.enabled();
+ messages_ = std::move(other.messages_);
+ return *this;
+}
+
+SPDLOG_INLINE void backtracer::enable(size_t size) {
+ std::lock_guard lock{mutex_};
+ enabled_.store(true, std::memory_order_relaxed);
+ messages_ = circular_q{size};
+}
+
+SPDLOG_INLINE void backtracer::disable() {
+ std::lock_guard lock{mutex_};
+ enabled_.store(false, std::memory_order_relaxed);
+}
+
+SPDLOG_INLINE bool backtracer::enabled() const { return enabled_.load(std::memory_order_relaxed); }
+
+SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) {
+ std::lock_guard lock{mutex_};
+ messages_.push_back(log_msg_buffer{msg});
+}
+
+SPDLOG_INLINE bool backtracer::empty() const {
+ std::lock_guard lock{mutex_};
+ return messages_.empty();
+}
+
+// pop all items in the q and apply the given fun on each of them.
+SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) {
+ std::lock_guard lock{mutex_};
+ while (!messages_.empty()) {
+ auto &front_msg = messages_.front();
+ fun(front_msg);
+ messages_.pop_front();
+ }
+}
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer.h
new file mode 100644
index 0000000..541339c
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/backtracer.h
@@ -0,0 +1,45 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+#include
+
+// Store log messages in circular buffer.
+// Useful for storing debug data in case of error/warning happens.
+
+namespace spdlog {
+namespace details {
+class SPDLOG_API backtracer {
+ mutable std::mutex mutex_;
+ std::atomic enabled_{false};
+ circular_q messages_;
+
+public:
+ backtracer() = default;
+ backtracer(const backtracer &other);
+
+ backtracer(backtracer &&other) SPDLOG_NOEXCEPT;
+ backtracer &operator=(backtracer other);
+
+ void enable(size_t size);
+ void disable();
+ bool enabled() const;
+ void push_back(const log_msg &msg);
+ bool empty() const;
+
+ // pop all items in the q and apply the given fun on each of them.
+ void foreach_pop(std::function fun);
+};
+
+} // namespace details
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "backtracer-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/circular_q.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/circular_q.h
new file mode 100644
index 0000000..ab068df
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/circular_q.h
@@ -0,0 +1,113 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+// circular q view of std::vector.
+#pragma once
+
+#include
+#include
+
+namespace spdlog {
+namespace details {
+template
+class circular_q {
+ size_t max_items_ = 0;
+ typename std::vector::size_type head_ = 0;
+ typename std::vector::size_type tail_ = 0;
+ size_t overrun_counter_ = 0;
+ std::vector v_;
+
+public:
+ using value_type = T;
+
+ // empty ctor - create a disabled queue with no elements allocated at all
+ circular_q() = default;
+
+ explicit circular_q(size_t max_items)
+ : max_items_(max_items + 1) // one item is reserved as marker for full q
+ ,
+ v_(max_items_) {}
+
+ circular_q(const circular_q &) = default;
+ circular_q &operator=(const circular_q &) = default;
+
+ // move cannot be default,
+ // since we need to reset head_, tail_, etc to zero in the moved object
+ circular_q(circular_q &&other) SPDLOG_NOEXCEPT { copy_moveable(std::move(other)); }
+
+ circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT {
+ copy_moveable(std::move(other));
+ return *this;
+ }
+
+ // push back, overrun (oldest) item if no room left
+ void push_back(T &&item) {
+ if (max_items_ > 0) {
+ v_[tail_] = std::move(item);
+ tail_ = (tail_ + 1) % max_items_;
+
+ if (tail_ == head_) // overrun last item if full
+ {
+ head_ = (head_ + 1) % max_items_;
+ ++overrun_counter_;
+ }
+ }
+ }
+
+ // Return reference to the front item.
+ // If there are no elements in the container, the behavior is undefined.
+ const T &front() const { return v_[head_]; }
+
+ T &front() { return v_[head_]; }
+
+ // Return number of elements actually stored
+ size_t size() const {
+ if (tail_ >= head_) {
+ return tail_ - head_;
+ } else {
+ return max_items_ - (head_ - tail_);
+ }
+ }
+
+ // Return const reference to item by index.
+ // If index is out of range 0…size()-1, the behavior is undefined.
+ const T &at(size_t i) const {
+ assert(i < size());
+ return v_[(head_ + i) % max_items_];
+ }
+
+ // Pop item from front.
+ // If there are no elements in the container, the behavior is undefined.
+ void pop_front() { head_ = (head_ + 1) % max_items_; }
+
+ bool empty() const { return tail_ == head_; }
+
+ bool full() const {
+ // head is ahead of the tail by 1
+ if (max_items_ > 0) {
+ return ((tail_ + 1) % max_items_) == head_;
+ }
+ return false;
+ }
+
+ size_t overrun_counter() const { return overrun_counter_; }
+
+ void reset_overrun_counter() { overrun_counter_ = 0; }
+
+private:
+ // copy from other&& and reset it to disabled state
+ void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT {
+ max_items_ = other.max_items_;
+ head_ = other.head_;
+ tail_ = other.tail_;
+ overrun_counter_ = other.overrun_counter_;
+ v_ = std::move(other.v_);
+
+ // put &&other in disabled, but valid state
+ other.max_items_ = 0;
+ other.head_ = other.tail_ = 0;
+ other.overrun_counter_ = 0;
+ }
+};
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/console_globals.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/console_globals.h
new file mode 100644
index 0000000..9c55210
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/console_globals.h
@@ -0,0 +1,28 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+namespace spdlog {
+namespace details {
+
+struct console_mutex {
+ using mutex_t = std::mutex;
+ static mutex_t &mutex() {
+ static mutex_t s_mutex;
+ return s_mutex;
+ }
+};
+
+struct console_nullmutex {
+ using mutex_t = null_mutex;
+ static mutex_t &mutex() {
+ static mutex_t s_mutex;
+ return s_mutex;
+ }
+};
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper-inl.h
new file mode 100644
index 0000000..69af9b6
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper-inl.h
@@ -0,0 +1,152 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace spdlog {
+namespace details {
+
+SPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers)
+ : event_handlers_(event_handlers) {}
+
+SPDLOG_INLINE file_helper::~file_helper() { close(); }
+
+SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) {
+ close();
+ filename_ = fname;
+
+ auto *mode = SPDLOG_FILENAME_T("ab");
+ auto *trunc_mode = SPDLOG_FILENAME_T("wb");
+
+ if (event_handlers_.before_open) {
+ event_handlers_.before_open(filename_);
+ }
+ for (int tries = 0; tries < open_tries_; ++tries) {
+ // create containing folder if not exists already.
+ os::create_dir(os::dir_name(fname));
+ if (truncate) {
+ // Truncate by opening-and-closing a tmp file in "wb" mode, always
+ // opening the actual log-we-write-to in "ab" mode, since that
+ // interacts more politely with eternal processes that might
+ // rotate/truncate the file underneath us.
+ std::FILE *tmp;
+ if (os::fopen_s(&tmp, fname, trunc_mode)) {
+ continue;
+ }
+ std::fclose(tmp);
+ }
+ if (!os::fopen_s(&fd_, fname, mode)) {
+ if (event_handlers_.after_open) {
+ event_handlers_.after_open(filename_, fd_);
+ }
+ return;
+ }
+
+ details::os::sleep_for_millis(open_interval_);
+ }
+
+ throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing",
+ errno);
+}
+
+SPDLOG_INLINE void file_helper::reopen(bool truncate) {
+ if (filename_.empty()) {
+ throw_spdlog_ex("Failed re opening file - was not opened before");
+ }
+ this->open(filename_, truncate);
+}
+
+SPDLOG_INLINE void file_helper::flush() {
+ if (std::fflush(fd_) != 0) {
+ throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno);
+ }
+}
+
+SPDLOG_INLINE void file_helper::sync() {
+ if (!os::fsync(fd_)) {
+ throw_spdlog_ex("Failed to fsync file " + os::filename_to_str(filename_), errno);
+ }
+}
+
+SPDLOG_INLINE void file_helper::close() {
+ if (fd_ != nullptr) {
+ if (event_handlers_.before_close) {
+ event_handlers_.before_close(filename_, fd_);
+ }
+
+ std::fclose(fd_);
+ fd_ = nullptr;
+
+ if (event_handlers_.after_close) {
+ event_handlers_.after_close(filename_);
+ }
+ }
+}
+
+SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) {
+ if(fd_ == nullptr) return;
+ size_t msg_size = buf.size();
+ auto data = buf.data();
+ if (std::fwrite(data, 1, msg_size, fd_) != msg_size) {
+ throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno);
+ }
+}
+
+SPDLOG_INLINE size_t file_helper::size() const {
+ if (fd_ == nullptr) {
+ throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_));
+ }
+ return os::filesize(fd_);
+}
+
+SPDLOG_INLINE const filename_t &file_helper::filename() const { return filename_; }
+
+//
+// return file path and its extension:
+//
+// "mylog.txt" => ("mylog", ".txt")
+// "mylog" => ("mylog", "")
+// "mylog." => ("mylog.", "")
+// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
+//
+// the starting dot in filenames is ignored (hidden files):
+//
+// ".mylog" => (".mylog". "")
+// "my_folder/.mylog" => ("my_folder/.mylog", "")
+// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
+SPDLOG_INLINE std::tuple file_helper::split_by_extension(
+ const filename_t &fname) {
+ auto ext_index = fname.rfind('.');
+
+ // no valid extension found - return whole path and empty string as
+ // extension
+ if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) {
+ return std::make_tuple(fname, filename_t());
+ }
+
+ // treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
+ auto folder_index = fname.find_last_of(details::os::folder_seps_filename);
+ if (folder_index != filename_t::npos && folder_index >= ext_index - 1) {
+ return std::make_tuple(fname, filename_t());
+ }
+
+ // finally - return a valid base and extension tuple
+ return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
+}
+
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper.h
new file mode 100644
index 0000000..f0e5d18
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/file_helper.h
@@ -0,0 +1,61 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+namespace spdlog {
+namespace details {
+
+// Helper class for file sinks.
+// When failing to open a file, retry several times(5) with a delay interval(10 ms).
+// Throw spdlog_ex exception on errors.
+
+class SPDLOG_API file_helper {
+public:
+ file_helper() = default;
+ explicit file_helper(const file_event_handlers &event_handlers);
+
+ file_helper(const file_helper &) = delete;
+ file_helper &operator=(const file_helper &) = delete;
+ ~file_helper();
+
+ void open(const filename_t &fname, bool truncate = false);
+ void reopen(bool truncate);
+ void flush();
+ void sync();
+ void close();
+ void write(const memory_buf_t &buf);
+ size_t size() const;
+ const filename_t &filename() const;
+
+ //
+ // return file path and its extension:
+ //
+ // "mylog.txt" => ("mylog", ".txt")
+ // "mylog" => ("mylog", "")
+ // "mylog." => ("mylog.", "")
+ // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
+ //
+ // the starting dot in filenames is ignored (hidden files):
+ //
+ // ".mylog" => (".mylog". "")
+ // "my_folder/.mylog" => ("my_folder/.mylog", "")
+ // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
+ static std::tuple split_by_extension(const filename_t &fname);
+
+private:
+ const int open_tries_ = 5;
+ const unsigned int open_interval_ = 10;
+ std::FILE *fd_{nullptr};
+ filename_t filename_;
+ file_event_handlers event_handlers_;
+};
+} // namespace details
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "file_helper-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/fmt_helper.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/fmt_helper.h
new file mode 100644
index 0000000..6130600
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/fmt_helper.h
@@ -0,0 +1,141 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef SPDLOG_USE_STD_FORMAT
+ #include
+ #include
+#endif
+
+// Some fmt helpers to efficiently format and pad ints and strings
+namespace spdlog {
+namespace details {
+namespace fmt_helper {
+
+inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest) {
+ auto *buf_ptr = view.data();
+ dest.append(buf_ptr, buf_ptr + view.size());
+}
+
+#ifdef SPDLOG_USE_STD_FORMAT
+template
+inline void append_int(T n, memory_buf_t &dest) {
+ // Buffer should be large enough to hold all digits (digits10 + 1) and a sign
+ SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits::digits10 + 2;
+ char buf[BUF_SIZE];
+
+ auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10);
+ if (ec == std::errc()) {
+ dest.append(buf, ptr);
+ } else {
+ throw_spdlog_ex("Failed to format int", static_cast(ec));
+ }
+}
+#else
+template
+inline void append_int(T n, memory_buf_t &dest) {
+ fmt::format_int i(n);
+ dest.append(i.data(), i.data() + i.size());
+}
+#endif
+
+template
+SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n) {
+ // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912
+ unsigned int count = 1;
+ for (;;) {
+ // Integer division is slow so do it for a group of four digits instead
+ // of for every digit. The idea comes from the talk by Alexandrescu
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
+ if (n < 10) return count;
+ if (n < 100) return count + 1;
+ if (n < 1000) return count + 2;
+ if (n < 10000) return count + 3;
+ n /= 10000u;
+ count += 4;
+ }
+}
+
+template
+inline unsigned int count_digits(T n) {
+ using count_type =
+ typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
+#ifdef SPDLOG_USE_STD_FORMAT
+ return count_digits_fallback(static_cast(n));
+#else
+ return static_cast(fmt::
+ // fmt 7.0.0 renamed the internal namespace to detail.
+ // See: https://github.com/fmtlib/fmt/issues/1538
+ #if FMT_VERSION < 70000
+ internal
+ #else
+ detail
+ #endif
+ ::count_digits(static_cast(n)));
+#endif
+}
+
+inline void pad2(int n, memory_buf_t &dest) {
+ if (n >= 0 && n < 100) // 0-99
+ {
+ dest.push_back(static_cast('0' + n / 10));
+ dest.push_back(static_cast('0' + n % 10));
+ } else // unlikely, but just in case, let fmt deal with it
+ {
+ fmt_lib::format_to(std::back_inserter(dest), SPDLOG_FMT_STRING("{:02}"), n);
+ }
+}
+
+template
+inline void pad_uint(T n, unsigned int width, memory_buf_t &dest) {
+ static_assert(std::is_unsigned::value, "pad_uint must get unsigned T");
+ for (auto digits = count_digits(n); digits < width; digits++) {
+ dest.push_back('0');
+ }
+ append_int(n, dest);
+}
+
+template
+inline void pad3(T n, memory_buf_t &dest) {
+ static_assert(std::is_unsigned::value, "pad3 must get unsigned T");
+ if (n < 1000) {
+ dest.push_back(static_cast(n / 100 + '0'));
+ n = n % 100;
+ dest.push_back(static_cast((n / 10) + '0'));
+ dest.push_back(static_cast((n % 10) + '0'));
+ } else {
+ append_int(n, dest);
+ }
+}
+
+template
+inline void pad6(T n, memory_buf_t &dest) {
+ pad_uint(n, 6, dest);
+}
+
+template
+inline void pad9(T n, memory_buf_t &dest) {
+ pad_uint(n, 9, dest);
+}
+
+// return fraction of a second of the given time_point.
+// e.g.
+// fraction(tp) -> will return the millis part of the second
+template
+inline ToDuration time_fraction(log_clock::time_point tp) {
+ using std::chrono::duration_cast;
+ using std::chrono::seconds;
+ auto duration = tp.time_since_epoch();
+ auto secs = duration_cast(duration);
+ return duration_cast(duration) - duration_cast(secs);
+}
+
+} // namespace fmt_helper
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg-inl.h
new file mode 100644
index 0000000..aa3a957
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg-inl.h
@@ -0,0 +1,44 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+#include
+
+namespace spdlog {
+namespace details {
+
+SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time,
+ spdlog::source_loc loc,
+ string_view_t a_logger_name,
+ spdlog::level::level_enum lvl,
+ spdlog::string_view_t msg)
+ : logger_name(a_logger_name),
+ level(lvl),
+ time(log_time)
+#ifndef SPDLOG_NO_THREAD_ID
+ ,
+ thread_id(os::thread_id())
+#endif
+ ,
+ source(loc),
+ payload(msg) {
+}
+
+SPDLOG_INLINE log_msg::log_msg(spdlog::source_loc loc,
+ string_view_t a_logger_name,
+ spdlog::level::level_enum lvl,
+ spdlog::string_view_t msg)
+ : log_msg(os::now(), loc, a_logger_name, lvl, msg) {}
+
+SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name,
+ spdlog::level::level_enum lvl,
+ spdlog::string_view_t msg)
+ : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) {}
+
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg.h
new file mode 100644
index 0000000..87df1e8
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg.h
@@ -0,0 +1,40 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+#include
+
+namespace spdlog {
+namespace details {
+struct SPDLOG_API log_msg {
+ log_msg() = default;
+ log_msg(log_clock::time_point log_time,
+ source_loc loc,
+ string_view_t logger_name,
+ level::level_enum lvl,
+ string_view_t msg);
+ log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg);
+ log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg);
+ log_msg(const log_msg &other) = default;
+ log_msg &operator=(const log_msg &other) = default;
+
+ string_view_t logger_name;
+ level::level_enum level{level::off};
+ log_clock::time_point time;
+ size_t thread_id{0};
+
+ // wrapping the formatted text with color (updated by pattern_formatter).
+ mutable size_t color_range_start{0};
+ mutable size_t color_range_end{0};
+
+ source_loc source;
+ string_view_t payload;
+};
+} // namespace details
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "log_msg-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer-inl.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer-inl.h
new file mode 100644
index 0000000..2eb2428
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer-inl.h
@@ -0,0 +1,54 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#ifndef SPDLOG_HEADER_ONLY
+ #include
+#endif
+
+namespace spdlog {
+namespace details {
+
+SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg)
+ : log_msg{orig_msg} {
+ buffer.append(logger_name.begin(), logger_name.end());
+ buffer.append(payload.begin(), payload.end());
+ update_string_views();
+}
+
+SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)
+ : log_msg{other} {
+ buffer.append(logger_name.begin(), logger_name.end());
+ buffer.append(payload.begin(), payload.end());
+ update_string_views();
+}
+
+SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT
+ : log_msg{other},
+ buffer{std::move(other.buffer)} {
+ update_string_views();
+}
+
+SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) {
+ log_msg::operator=(other);
+ buffer.clear();
+ buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size());
+ update_string_views();
+ return *this;
+}
+
+SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT {
+ log_msg::operator=(other);
+ buffer = std::move(other.buffer);
+ update_string_views();
+ return *this;
+}
+
+SPDLOG_INLINE void log_msg_buffer::update_string_views() {
+ logger_name = string_view_t{buffer.data(), logger_name.size()};
+ payload = string_view_t{buffer.data() + logger_name.size(), payload.size()};
+}
+
+} // namespace details
+} // namespace spdlog
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer.h
new file mode 100644
index 0000000..1143b3b
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/log_msg_buffer.h
@@ -0,0 +1,32 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+#include
+
+namespace spdlog {
+namespace details {
+
+// Extend log_msg with internal buffer to store its payload.
+// This is needed since log_msg holds string_views that points to stack data.
+
+class SPDLOG_API log_msg_buffer : public log_msg {
+ memory_buf_t buffer;
+ void update_string_views();
+
+public:
+ log_msg_buffer() = default;
+ explicit log_msg_buffer(const log_msg &orig_msg);
+ log_msg_buffer(const log_msg_buffer &other);
+ log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
+ log_msg_buffer &operator=(const log_msg_buffer &other);
+ log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT;
+};
+
+} // namespace details
+} // namespace spdlog
+
+#ifdef SPDLOG_HEADER_ONLY
+ #include "log_msg_buffer-inl.h"
+#endif
diff --git a/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/mpmc_blocking_q.h b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/mpmc_blocking_q.h
new file mode 100644
index 0000000..5a474bf
--- /dev/null
+++ b/DL2GameOverhaulScript/source/spdlog/include/spdlog/details/mpmc_blocking_q.h
@@ -0,0 +1,177 @@
+// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+
+#pragma once
+
+// multi producer-multi consumer blocking queue.
+// enqueue(..) - will block until room found to put the new message.
+// enqueue_nowait(..) - will return immediately with false if no room left in
+// the queue.
+// dequeue_for(..) - will block until the queue is not empty or timeout have
+// passed.
+
+#include
+
+#include
+#include
+#include
+
+namespace spdlog {
+namespace details {
+
+template
+class mpmc_blocking_queue {
+public:
+ using item_type = T;
+ explicit mpmc_blocking_queue(size_t max_items)
+ : q_(max_items) {}
+
+#ifndef __MINGW32__
+ // try to enqueue and block if no room left
+ void enqueue(T &&item) {
+ {
+ std::unique_lock lock(queue_mutex_);
+ pop_cv_.wait(lock, [this] { return !this->q_.full(); });
+ q_.push_back(std::move(item));
+ }
+ push_cv_.notify_one();
+ }
+
+ // enqueue immediately. overrun oldest message in the queue if no room left.
+ void enqueue_nowait(T &&item) {
+ {
+ std::unique_lock lock(queue_mutex_);
+ q_.push_back(std::move(item));
+ }
+ push_cv_.notify_one();
+ }
+
+ void enqueue_if_have_room(T &&item) {
+ bool pushed = false;
+ {
+ std::unique_lock lock(queue_mutex_);
+ if (!q_.full()) {
+ q_.push_back(std::move(item));
+ pushed = true;
+ }
+ }
+
+ if (pushed) {
+ push_cv_.notify_one();
+ } else {
+ ++discard_counter_;
+ }
+ }
+
+ // dequeue with a timeout.
+ // Return true, if succeeded dequeue item, false otherwise
+ bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) {
+ {
+ std::unique_lock lock(queue_mutex_);
+ if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) {
+ return false;
+ }
+ popped_item = std::move(q_.front());
+ q_.pop_front();
+ }
+ pop_cv_.notify_one();
+ return true;
+ }
+
+ // blocking dequeue without a timeout.
+ void dequeue(T &popped_item) {
+ {
+ std::unique_lock lock(queue_mutex_);
+ push_cv_.wait(lock, [this] { return !this->q_.empty(); });
+ popped_item = std::move(q_.front());
+ q_.pop_front();
+ }
+ pop_cv_.notify_one();
+ }
+
+#else
+ // apparently mingw deadlocks if the mutex is released before cv.notify_one(),
+ // so release the mutex at the very end each function.
+
+ // try to enqueue and block if no room left
+ void enqueue(T &&item) {
+ std::unique_lock lock(queue_mutex_);
+ pop_cv_.wait(lock, [this] { return !this->q_.full(); });
+ q_.push_back(std::move(item));
+ push_cv_.notify_one();
+ }
+
+ // enqueue immediately. overrun oldest message in the queue if no room left.
+ void enqueue_nowait(T &&item) {
+ std::unique_lock lock(queue_mutex_);
+ q_.push_back(std::move(item));
+ push_cv_.notify_one();
+ }
+
+ void enqueue_if_have_room(T &&item) {
+ bool pushed = false;
+ std::unique_lock lock(queue_mutex_);
+ if (!q_.full()) {
+ q_.push_back(std::move(item));
+ pushed = true;
+ }
+
+ if (pushed) {
+ push_cv_.notify_one();
+ } else {
+ ++discard_counter_;
+ }
+ }
+
+ // dequeue with a timeout.
+ // Return true, if succeeded dequeue item, false otherwise
+ bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) {
+ std::unique_lock