diff --git a/.github/workflows/backup.yml b/.github/workflows/backup.yml
new file mode 100644
index 000000000..366f4682b
--- /dev/null
+++ b/.github/workflows/backup.yml
@@ -0,0 +1,32 @@
+name: Back up code to other forges
+
+on:
+ schedule:
+ - cron: '0 2 * * *' # Run every day at 2 AM
+ workflow_dispatch: # Allow manual trigger
+
+jobs:
+ push-to-forges:
+ runs-on: ubuntu-latest
+ if: github.repository == 'goatcorp/Dalamud'
+
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd #v0.9.1
+ with:
+ ssh-private-key: |
+ ${{ secrets.MIRROR_GITLAB_SYNC_KEY }}
+ ${{ secrets.MIRROR_CODEBERG_SYNC_KEY }}
+
+ - name: Add remotes & push
+ env:
+ GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=accept-new"
+ run: |
+ git remote add gitlab git@gitlab.com:goatcorp/Dalamud.git
+ git push gitlab --all --force
+ git remote add codeberg git@codeberg.org:goatcorp/Dalamud.git
+ git push codeberg --all --force
diff --git a/Dalamud.Boot/Dalamud.Boot.rc b/Dalamud.Boot/Dalamud.Boot.rc
index b46e81caf..655df27e1 100644
--- a/Dalamud.Boot/Dalamud.Boot.rc
+++ b/Dalamud.Boot/Dalamud.Boot.rc
@@ -26,6 +26,38 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
RT_MANIFEST_THEMES RT_MANIFEST "themes.manifest"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_APPNAME "Dalamud Boot"
+ IDS_MSVCRT_ACTION_OPENDOWNLOAD
+ "Download Microsoft Visual C++ Redistributable 2022\nExit the game and download the latest setup file from Microsoft."
+ IDS_MSVCRT_ACTION_IGNORE
+ "Ignore and Continue\nAttempt to continue with the currently installed version.\nDalamud or plugins may fail to load."
+ IDS_MSVCRT_DIALOG_MAININSTRUCTION
+ "Outdated Microsoft Visual C++ Redistributable"
+ IDS_MSVCRT_DIALOG_CONTENT
+ "The Microsoft Visual C++ Redistributable version detected on this computer (v{0}.{1}.{2}.{3}) is out of date and may not work with Dalamud."
+ IDS_MSVCRT_DOWNLOADURL "https://aka.ms/vs/17/release/vc_redist.x64.exe"
+ IDS_INITIALIZEFAIL_ACTION_ABORT "Abort\nExit the game."
+ IDS_INITIALIZEFAIL_ACTION_CONTINUE
+ "Load game without Dalamud\nThe game will launch without Dalamud enabled."
+ IDS_INITIALIZEFAIL_DIALOG_MAININSTRUCTION "Failed to load Dalamud."
+ IDS_INITIALIZEFAIL_DIALOG_CONTENT
+ "An error is preventing Dalamud from being loaded along with the game."
+END
+
+STRINGTABLE
+BEGIN
+ IDS_INITIALIZEFAIL_DIALOG_FOOTER
+ "Last operation: {0}\nHRESULT: 0x{1:08X}\nDescription: {2}"
+END
+
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/Dalamud.Boot/Dalamud.Boot.vcxproj b/Dalamud.Boot/Dalamud.Boot.vcxproj
index a15601af4..0a4a9c563 100644
--- a/Dalamud.Boot/Dalamud.Boot.vcxproj
+++ b/Dalamud.Boot/Dalamud.Boot.vcxproj
@@ -48,7 +48,7 @@
Level3
true
true
- stdcpp20
+ stdcpp23
pch.h
ProgramDatabase
CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
@@ -65,7 +65,7 @@
true
false
- MultiThreadedDebugDLL
+ MultiThreadedDebugDLL
_DEBUG;%(PreprocessorDefinitions)
Use
26812
@@ -80,7 +80,7 @@
true
true
- MultiThreadedDLL
+ MultiThreadedDLL
NDEBUG;%(PreprocessorDefinitions)
Use
26812
@@ -133,6 +133,10 @@
NotUsing
+
+ NotUsing
+ NotUsing
+
NotUsing
@@ -176,6 +180,7 @@
+
@@ -206,4 +211,4 @@
-
+
\ No newline at end of file
diff --git a/Dalamud.Boot/Dalamud.Boot.vcxproj.filters b/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
index 7c26b28ff..15e3eb8b3 100644
--- a/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
+++ b/Dalamud.Boot/Dalamud.Boot.vcxproj.filters
@@ -76,6 +76,9 @@
Dalamud.Boot DLL
+
+ Common Boot
+
@@ -146,6 +149,9 @@
Dalamud.Boot DLL
+
+ Common Boot
+
diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp
index 5e73962ec..80a16f89a 100644
--- a/Dalamud.Boot/dllmain.cpp
+++ b/Dalamud.Boot/dllmain.cpp
@@ -9,10 +9,125 @@
#include "utils.h"
#include "veh.h"
#include "xivfixes.h"
+#include "resource.h"
HMODULE g_hModule;
HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr);
+static void CheckMsvcrtVersion() {
+ // Commit introducing inline mutex ctor: tagged vs-2022-17.14 (2024-06-18)
+ // - https://github.com/microsoft/STL/commit/22a88260db4d754bbc067e2002430144d6ec5391
+ // MSVC Redist versions:
+ // - https://github.com/abbodi1406/vcredist/blob/master/source_links/README.md
+ // - 14.40.33810.0 dsig 2024-04-28
+ // - 14.40.33816.0 dsig 2024-09-11
+
+ constexpr WORD RequiredMsvcrtVersionComponents[] = {14, 40, 33816, 0};
+ constexpr auto RequiredMsvcrtVersion = 0ULL
+ | (static_cast(RequiredMsvcrtVersionComponents[0]) << 48)
+ | (static_cast(RequiredMsvcrtVersionComponents[1]) << 32)
+ | (static_cast(RequiredMsvcrtVersionComponents[2]) << 16)
+ | (static_cast(RequiredMsvcrtVersionComponents[3]) << 0);
+
+ constexpr const wchar_t* RuntimeDllNames[] = {
+#ifdef _DEBUG
+ L"msvcp140d.dll",
+ L"vcruntime140d.dll",
+ L"vcruntime140_1d.dll",
+#else
+ L"msvcp140.dll",
+ L"vcruntime140.dll",
+ L"vcruntime140_1.dll",
+#endif
+ };
+
+ uint64_t lowestVersion = 0;
+ for (const auto& runtimeDllName : RuntimeDllNames) {
+ const utils::loaded_module mod(GetModuleHandleW(runtimeDllName));
+ if (!mod) {
+ logging::E("MSVCRT DLL not found: {}", runtimeDllName);
+ continue;
+ }
+
+ const auto path = mod.path()
+ .transform([](const auto& p) { return p.wstring(); })
+ .value_or(runtimeDllName);
+
+ if (const auto versionResult = mod.get_file_version()) {
+ const auto& versionFull = versionResult->get();
+ logging::I("MSVCRT DLL {} has version {}.", path, utils::format_file_version(versionFull));
+
+ const auto version = 0ULL |
+ (static_cast(versionFull.dwFileVersionMS) << 32) |
+ (static_cast(versionFull.dwFileVersionLS) << 0);
+
+ if (version < RequiredMsvcrtVersion && (lowestVersion == 0 || lowestVersion > version))
+ lowestVersion = version;
+ } else {
+ logging::E("Failed to detect MSVCRT DLL version for {}: {}", path, versionResult.error().describe());
+ }
+ }
+
+ if (!lowestVersion)
+ return;
+
+ enum IdTaskDialogAction {
+ IdTaskDialogActionOpenDownload = 101,
+ IdTaskDialogActionIgnore,
+ };
+
+ const TASKDIALOG_BUTTON buttons[]{
+ {IdTaskDialogActionOpenDownload, MAKEINTRESOURCEW(IDS_MSVCRT_ACTION_OPENDOWNLOAD)},
+ {IdTaskDialogActionIgnore, MAKEINTRESOURCEW(IDS_MSVCRT_ACTION_IGNORE)},
+ };
+
+ const WORD lowestVersionComponents[]{
+ static_cast(lowestVersion >> 48),
+ static_cast(lowestVersion >> 32),
+ static_cast(lowestVersion >> 16),
+ static_cast(lowestVersion >> 0),
+ };
+
+ const auto dialogContent = std::vformat(
+ utils::get_string_resource(IDS_MSVCRT_DIALOG_CONTENT),
+ std::make_wformat_args(
+ lowestVersionComponents[0],
+ lowestVersionComponents[1],
+ lowestVersionComponents[2],
+ lowestVersionComponents[3]));
+
+ const TASKDIALOGCONFIG config{
+ .cbSize = sizeof config,
+ .hInstance = g_hModule,
+ .dwFlags = TDF_CAN_BE_MINIMIZED | TDF_ALLOW_DIALOG_CANCELLATION | TDF_USE_COMMAND_LINKS,
+ .pszWindowTitle = MAKEINTRESOURCEW(IDS_APPNAME),
+ .pszMainIcon = MAKEINTRESOURCEW(IDI_ICON1),
+ .pszMainInstruction = MAKEINTRESOURCEW(IDS_MSVCRT_DIALOG_MAININSTRUCTION),
+ .pszContent = dialogContent.c_str(),
+ .cButtons = _countof(buttons),
+ .pButtons = buttons,
+ .nDefaultButton = IdTaskDialogActionOpenDownload,
+ };
+
+ int buttonPressed;
+ if (utils::scoped_dpi_awareness_context ctx;
+ FAILED(TaskDialogIndirect(&config, &buttonPressed, nullptr, nullptr)))
+ buttonPressed = IdTaskDialogActionOpenDownload;
+
+ switch (buttonPressed) {
+ case IdTaskDialogActionOpenDownload:
+ ShellExecuteW(
+ nullptr,
+ L"open",
+ utils::get_string_resource(IDS_MSVCRT_DOWNLOADURL).c_str(),
+ nullptr,
+ nullptr,
+ SW_SHOW);
+ ExitProcess(0);
+ break;
+ }
+}
+
HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
g_startInfo.from_envvars();
@@ -24,7 +139,7 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
}
if (g_startInfo.BootShowConsole)
- ConsoleSetup(L"Dalamud Boot");
+ ConsoleSetup(utils::get_string_resource(IDS_APPNAME).c_str());
logging::update_dll_load_status(true);
@@ -94,6 +209,8 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
if ((g_startInfo.BootWaitMessageBox & DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize) != DalamudStartInfo::WaitMessageboxFlags::None)
MessageBoxW(nullptr, L"Press OK to continue (BeforeInitialize)", L"Dalamud Boot", MB_OK);
+ CheckMsvcrtVersion();
+
if (g_startInfo.BootDebugDirectX) {
logging::I("Enabling DirectX Debugging.");
@@ -159,7 +276,7 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
if (minHookLoaded) {
logging::I("Applying fixes...");
- xivfixes::apply_all(true);
+ std::thread([] { xivfixes::apply_all(true); }).join();
logging::I("Fixes OK");
} else {
logging::W("Skipping fixes, as MinHook has failed to load.");
@@ -170,11 +287,14 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
while (!IsDebuggerPresent())
Sleep(100);
logging::I("Debugger attached.");
+ __debugbreak();
}
- const auto fs_module_path = utils::get_module_path(g_hModule);
- const auto runtimeconfig_path = std::filesystem::path(fs_module_path).replace_filename(L"Dalamud.runtimeconfig.json").wstring();
- const auto module_path = std::filesystem::path(fs_module_path).replace_filename(L"Dalamud.dll").wstring();
+ const auto fs_module_path = utils::loaded_module(g_hModule).path();
+ if (!fs_module_path)
+ return fs_module_path.error();
+ const auto runtimeconfig_path = std::filesystem::path(*fs_module_path).replace_filename(L"Dalamud.runtimeconfig.json").wstring();
+ const auto module_path = std::filesystem::path(*fs_module_path).replace_filename(L"Dalamud.dll").wstring();
// ============================== CLR ========================================= //
diff --git a/Dalamud.Boot/error_info.cpp b/Dalamud.Boot/error_info.cpp
new file mode 100644
index 000000000..02356b730
--- /dev/null
+++ b/Dalamud.Boot/error_info.cpp
@@ -0,0 +1,26 @@
+#include "error_info.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include
+
+DalamudBootError::DalamudBootError(DalamudBootErrorDescription dalamudErrorDescription, long hresult) noexcept
+ : m_dalamudErrorDescription(dalamudErrorDescription)
+ , m_hresult(hresult) {
+}
+
+DalamudBootError::DalamudBootError(DalamudBootErrorDescription dalamudErrorDescription) noexcept
+ : DalamudBootError(dalamudErrorDescription, E_FAIL) {
+}
+
+const char* DalamudBootError::describe() const {
+ switch (m_dalamudErrorDescription) {
+ case DalamudBootErrorDescription::ModuleResourceLoadFail:
+ return "Failed to load resource.";
+ case DalamudBootErrorDescription::ModuleResourceVersionReadFail:
+ return "Failed to query version information.";
+ case DalamudBootErrorDescription::ModuleResourceVersionSignatureFail:
+ return "Invalid version info found.";
+ default:
+ return "(unavailable)";
+ }
+}
diff --git a/Dalamud.Boot/error_info.h b/Dalamud.Boot/error_info.h
new file mode 100644
index 000000000..b5862d0dd
--- /dev/null
+++ b/Dalamud.Boot/error_info.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include
+#include
+
+typedef unsigned long DWORD;
+typedef _Return_type_success_(return >= 0) long HRESULT;
+
+enum class DalamudBootErrorDescription {
+ None,
+ ModulePathResolutionFail,
+ ModuleResourceLoadFail,
+ ModuleResourceVersionReadFail,
+ ModuleResourceVersionSignatureFail,
+};
+
+class DalamudBootError {
+ DalamudBootErrorDescription m_dalamudErrorDescription;
+ long m_hresult;
+
+public:
+ DalamudBootError(DalamudBootErrorDescription dalamudErrorDescription, long hresult) noexcept;
+ DalamudBootError(DalamudBootErrorDescription dalamudErrorDescription) noexcept;
+
+ const char* describe() const;
+
+ operator HRESULT() const {
+ return m_hresult;
+ }
+};
+
+template
+using DalamudExpected = std::expected<
+ std::conditional_t<
+ std::is_reference_v,
+ std::reference_wrapper>,
+ T
+ >,
+ DalamudBootError
+>;
+
+using DalamudUnexpected = std::unexpected;
diff --git a/Dalamud.Boot/hooks.cpp b/Dalamud.Boot/hooks.cpp
index 295d427ae..3443a5f8a 100644
--- a/Dalamud.Boot/hooks.cpp
+++ b/Dalamud.Boot/hooks.cpp
@@ -84,19 +84,13 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
const auto dllName = unicode::convert(pData->Loaded.FullDllName->Buffer);
utils::loaded_module mod(pData->Loaded.DllBase);
- std::wstring version, description;
- try {
- version = utils::format_file_version(mod.get_file_version());
- } catch (...) {
- version = L"";
- }
-
- try {
- description = mod.get_description();
- } catch (...) {
- description = L"";
- }
-
+ const auto version = mod.get_file_version()
+ .transform([](const auto& v) { return utils::format_file_version(v.get()); })
+ .value_or(L"");
+
+ const auto description = mod.get_description()
+ .value_or(L"");
+
logging::I(R"({} "{}" ("{}" ver {}) has been loaded at 0x{:X} ~ 0x{:X} (0x{:X}); finding import table items to hook.)",
LogTag, dllName, description, version,
reinterpret_cast(pData->Loaded.DllBase),
@@ -125,7 +119,9 @@ void hooks::getprocaddress_singleton_import_hook::hook_module(const utils::loade
if (mod.is_current_process())
return;
- const auto path = unicode::convert(mod.path().wstring());
+ const auto path = mod.path()
+ .transform([](const auto& p) { return unicode::convert(p.wstring()); })
+ .value_or("");
for (const auto& [hModule, targetFns] : m_targetFns) {
for (const auto& [targetFn, pfnThunk] : targetFns) {
@@ -133,7 +129,7 @@ void hooks::getprocaddress_singleton_import_hook::hook_module(const utils::loade
if (void* pGetProcAddressImport; mod.find_imported_function_pointer(dllName.c_str(), targetFn.c_str(), 0, pGetProcAddressImport)) {
auto& hook = m_hooks[hModule][targetFn][mod];
if (!hook) {
- logging::I("{} Hooking {}!{} imported by {}", LogTag, dllName, targetFn, unicode::convert(mod.path().wstring()));
+ logging::I("{} Hooking {}!{} imported by {}", LogTag, dllName, targetFn, path);
hook.emplace(std::format("getprocaddress_singleton_import_hook::hook_module({}!{})", dllName, targetFn), static_cast(pGetProcAddressImport), pfnThunk);
}
diff --git a/Dalamud.Boot/pch.h b/Dalamud.Boot/pch.h
index c2194c157..ac1394e57 100644
--- a/Dalamud.Boot/pch.h
+++ b/Dalamud.Boot/pch.h
@@ -11,6 +11,9 @@
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
+// https://developercommunity.visualstudio.com/t/Access-violation-with-std::mutex::lock-a/10664660
+#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
+
// Windows Header Files (1)
#include
@@ -21,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -51,6 +55,7 @@
#include
#include
#include
+#include
#include
// https://www.akenotsuki.com/misc/srell/en/
diff --git a/Dalamud.Boot/resource.h b/Dalamud.Boot/resource.h
index 51acf37df..2a1cde6e2 100644
--- a/Dalamud.Boot/resource.h
+++ b/Dalamud.Boot/resource.h
@@ -3,12 +3,23 @@
// Used by Dalamud.Boot.rc
//
#define IDI_ICON1 101
+#define IDS_APPNAME 102
+#define IDS_MSVCRT_ACTION_OPENDOWNLOAD 103
+#define IDS_MSVCRT_ACTION_IGNORE 104
+#define IDS_MSVCRT_DIALOG_MAININSTRUCTION 105
+#define IDS_MSVCRT_DIALOG_CONTENT 106
+#define IDS_MSVCRT_DOWNLOADURL 107
+#define IDS_INITIALIZEFAIL_ACTION_ABORT 108
+#define IDS_INITIALIZEFAIL_ACTION_CONTINUE 109
+#define IDS_INITIALIZEFAIL_DIALOG_MAININSTRUCTION 110
+#define IDS_INITIALIZEFAIL_DIALOG_CONTENT 111
+#define IDS_INITIALIZEFAIL_DIALOG_FOOTER 112
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
diff --git a/Dalamud.Boot/rewrite_entrypoint.cpp b/Dalamud.Boot/rewrite_entrypoint.cpp
index 3a1672af7..69a4ec818 100644
--- a/Dalamud.Boot/rewrite_entrypoint.cpp
+++ b/Dalamud.Boot/rewrite_entrypoint.cpp
@@ -2,6 +2,7 @@
#include "logging.h"
#include "utils.h"
+#include "resource.h"
HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue);
@@ -379,12 +380,50 @@ extern "C" void WINAPI RewrittenEntryPoint_AdjustedStack(RewrittenEntryPointPara
auto desc = err.Description();
if (desc.length() == 0)
desc = err.ErrorMessage();
- if (MessageBoxW(nullptr, std::format(
- L"Failed to load Dalamud. Load game without Dalamud(yes) or abort(no)?\n\n{}\n{}",
- last_operation,
- desc.GetBSTR()).c_str(),
- L"Dalamud.Boot", MB_OK | MB_YESNO) == IDNO)
- ExitProcess(-1);
+
+ enum IdTaskDialogAction {
+ IdTaskDialogActionAbort = 101,
+ IdTaskDialogActionContinue,
+ };
+
+ const TASKDIALOG_BUTTON buttons[]{
+ {IdTaskDialogActionAbort, MAKEINTRESOURCEW(IDS_INITIALIZEFAIL_ACTION_ABORT)},
+ {IdTaskDialogActionContinue, MAKEINTRESOURCEW(IDS_INITIALIZEFAIL_ACTION_CONTINUE)},
+ };
+
+ const auto hru32 = static_cast(hr);
+ const auto footer = std::vformat(
+ utils::get_string_resource(IDS_INITIALIZEFAIL_DIALOG_FOOTER),
+ std::make_wformat_args(
+ last_operation,
+ hru32,
+ desc.GetBSTR()));
+
+ const TASKDIALOGCONFIG config{
+ .cbSize = sizeof config,
+ .hInstance = g_hModule,
+ .dwFlags = TDF_CAN_BE_MINIMIZED | TDF_ALLOW_DIALOG_CANCELLATION | TDF_USE_COMMAND_LINKS | TDF_EXPAND_FOOTER_AREA,
+ .pszWindowTitle = MAKEINTRESOURCEW(IDS_APPNAME),
+ .pszMainIcon = MAKEINTRESOURCEW(IDI_ICON1),
+ .pszMainInstruction = MAKEINTRESOURCEW(IDS_INITIALIZEFAIL_DIALOG_MAININSTRUCTION),
+ .pszContent = MAKEINTRESOURCEW(IDS_INITIALIZEFAIL_DIALOG_CONTENT),
+ .cButtons = _countof(buttons),
+ .pButtons = buttons,
+ .nDefaultButton = IdTaskDialogActionAbort,
+ .pszFooter = footer.c_str(),
+ };
+
+ int buttonPressed;
+ if (utils::scoped_dpi_awareness_context ctx;
+ FAILED(TaskDialogIndirect(&config, &buttonPressed, nullptr, nullptr)))
+ buttonPressed = IdTaskDialogActionAbort;
+
+ switch (buttonPressed) {
+ case IdTaskDialogActionAbort:
+ ExitProcess(-1);
+ break;
+ }
+
if (hMainThreadContinue) {
CloseHandle(hMainThreadContinue);
hMainThreadContinue = nullptr;
diff --git a/Dalamud.Boot/utils.cpp b/Dalamud.Boot/utils.cpp
index dbfcf39ee..9820e5b7f 100644
--- a/Dalamud.Boot/utils.cpp
+++ b/Dalamud.Boot/utils.cpp
@@ -3,22 +3,27 @@
#include "utils.h"
-std::filesystem::path utils::loaded_module::path() const {
- std::wstring buf(MAX_PATH, L'\0');
- for (;;) {
- if (const auto len = GetModuleFileNameExW(GetCurrentProcess(), m_hModule, &buf[0], static_cast(buf.size())); len != buf.size()) {
- if (buf.empty())
- throw std::runtime_error(std::format("Failed to resolve module path: Win32 error {}", GetLastError()));
+DalamudExpected utils::loaded_module::path() const {
+ for (std::wstring buf(MAX_PATH, L'\0');; buf.resize(buf.size() * 2)) {
+ if (const auto len = GetModuleFileNameW(m_hModule, &buf[0], static_cast(buf.size()));
+ len != buf.size()) {
+ if (!len) {
+ return DalamudUnexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModulePathResolutionFail,
+ HRESULT_FROM_WIN32(GetLastError()));
+ }
+
buf.resize(len);
return buf;
}
- if (buf.size() * 2 < PATHCCH_MAX_CCH)
- buf.resize(buf.size() * 2);
- else if (auto p = std::filesystem::path(buf); exists(p))
- return p;
- else
- throw std::runtime_error("Failed to resolve module path: no amount of buffer size would fit the data");
+ if (buf.size() > PATHCCH_MAX_CCH) {
+ return DalamudUnexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModulePathResolutionFail,
+ E_OUTOFMEMORY);
+ }
}
}
@@ -144,66 +149,90 @@ void* utils::loaded_module::get_imported_function_pointer(const char* pcszDllNam
throw std::runtime_error(std::format("Failed to find import for {}!{} ({}).", pcszDllName, pcszFunctionName ? pcszFunctionName : "", hintOrOrdinal));
}
-std::unique_ptr, decltype(&FreeResource)> utils::loaded_module::get_resource(LPCWSTR lpName, LPCWSTR lpType) const {
+DalamudExpected, decltype(&FreeResource)>> utils::loaded_module::get_resource(LPCWSTR lpName, LPCWSTR lpType) const {
const auto hres = FindResourceW(m_hModule, lpName, lpType);
if (!hres)
- throw std::runtime_error("No such resource");
-
+ return DalamudUnexpected(std::in_place, DalamudBootErrorDescription::ModuleResourceLoadFail, GetLastError());
+
const auto hRes = LoadResource(m_hModule, hres);
if (!hRes)
- throw std::runtime_error("LoadResource failure");
+ return DalamudUnexpected(std::in_place, DalamudBootErrorDescription::ModuleResourceLoadFail, GetLastError());
- return {hRes, &FreeResource};
+ return std::unique_ptr, decltype(&FreeResource)>(hRes, &FreeResource);
}
-std::wstring utils::loaded_module::get_description() const {
- const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
- const auto pBlock = LockResource(rsrc.get());
-
+DalamudExpected utils::loaded_module::get_description() const {
+ auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
+ if (!rsrc)
+ return DalamudUnexpected(std::move(rsrc.error()));
+
+ const auto pBlock = LockResource(rsrc->get());
+
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} * lpTranslate;
UINT cbTranslate;
if (!VerQueryValueW(pBlock,
- TEXT("\\VarFileInfo\\Translation"),
+ L"\\VarFileInfo\\Translation",
reinterpret_cast(&lpTranslate),
&cbTranslate)) {
- throw std::runtime_error("Invalid version information (1)");
+ return DalamudUnexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModuleResourceVersionReadFail,
+ HRESULT_FROM_WIN32(GetLastError()));
}
for (size_t i = 0; i < (cbTranslate / sizeof(LANGANDCODEPAGE)); i++) {
+ wchar_t subblockNameBuf[64];
+ *std::format_to_n(
+ subblockNameBuf,
+ _countof(subblockNameBuf),
+ L"\\StringFileInfo\\{:04x}{:04x}\\FileDescription",
+ lpTranslate[i].wLanguage,
+ lpTranslate[i].wCodePage).out = 0;;
+
wchar_t* buf = nullptr;
UINT size = 0;
- if (!VerQueryValueW(pBlock,
- std::format(L"\\StringFileInfo\\{:04x}{:04x}\\FileDescription",
- lpTranslate[i].wLanguage,
- lpTranslate[i].wCodePage).c_str(),
- reinterpret_cast(&buf),
- &size)) {
+ if (!VerQueryValueW(pBlock, subblockNameBuf, reinterpret_cast(&buf), &size))
continue;
- }
+
auto currName = std::wstring_view(buf, size);
- while (!currName.empty() && currName.back() == L'\0')
- currName = currName.substr(0, currName.size() - 1);
+ if (const auto p = currName.find(L'\0'); p != std::string::npos)
+ currName = currName.substr(0, p);
if (currName.empty())
continue;
return std::wstring(currName);
}
-
- throw std::runtime_error("Invalid version information (2)");
+
+ return DalamudUnexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModuleResourceVersionReadFail,
+ HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
}
-VS_FIXEDFILEINFO utils::loaded_module::get_file_version() const {
- const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
- const auto pBlock = LockResource(rsrc.get());
+std::expected, DalamudBootError> utils::loaded_module::get_file_version() const {
+ auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
+ if (!rsrc)
+ return DalamudUnexpected(std::move(rsrc.error()));
+
+ const auto pBlock = LockResource(rsrc->get());
UINT size = 0;
LPVOID lpBuffer = nullptr;
- if (!VerQueryValueW(pBlock, L"\\", &lpBuffer, &size))
- throw std::runtime_error("Failed to query version information.");
+ if (!VerQueryValueW(pBlock, L"\\", &lpBuffer, &size)) {
+ return std::unexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModuleResourceVersionReadFail,
+ HRESULT_FROM_WIN32(GetLastError()));
+ }
+
const VS_FIXEDFILEINFO& versionInfo = *static_cast(lpBuffer);
- if (versionInfo.dwSignature != 0xfeef04bd)
- throw std::runtime_error("Invalid version info found.");
+ if (versionInfo.dwSignature != 0xfeef04bd) {
+ return std::unexpected(
+ std::in_place,
+ DalamudBootErrorDescription::ModuleResourceVersionSignatureFail);
+ }
+
return versionInfo;
}
@@ -353,7 +382,7 @@ const char* utils::signature_finder::result::resolve_jump_target(size_t instruct
nmd_x86_instruction instruction{};
if (!nmd_x86_decode(&Match[instructionOffset], NMD_X86_MAXIMUM_INSTRUCTION_LENGTH, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL))
throw std::runtime_error("Matched address does not have a valid assembly instruction");
-
+
size_t numExplicitOperands = 0;
for (size_t i = 0; i < instruction.num_operands; i++)
numExplicitOperands += instruction.operands[i].is_implicit ? 0 : 1;
@@ -589,17 +618,10 @@ bool utils::is_running_on_wine() {
return g_startInfo.Platform != "WINDOWS";
}
-std::filesystem::path utils::get_module_path(HMODULE hModule) {
- std::wstring buf(MAX_PATH, L'\0');
- while (true) {
- if (const auto res = GetModuleFileNameW(hModule, &buf[0], static_cast(buf.size())); !res)
- throw std::runtime_error(std::format("GetModuleFileName failure: 0x{:X}", GetLastError()));
- else if (res < buf.size()) {
- buf.resize(res);
- return buf;
- } else
- buf.resize(buf.size() * 2);
- }
+std::wstring utils::get_string_resource(uint32_t resId) {
+ LPCWSTR pstr;
+ const auto len = LoadStringW(g_hModule, resId, reinterpret_cast(&pstr), 0);
+ return std::wstring(pstr, len);
}
HWND utils::try_find_game_window() {
@@ -625,7 +647,7 @@ void utils::wait_for_game_window() {
std::wstring utils::escape_shell_arg(const std::wstring& arg) {
// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
-
+
std::wstring res;
if (!arg.empty() && arg.find_first_of(L" \t\n\v\"") == std::wstring::npos) {
res.append(arg);
@@ -677,3 +699,22 @@ std::wstring utils::format_win32_error(DWORD err) {
return std::format(L"Win32 error ({}=0x{:X})", err, err);
}
+
+utils::scoped_dpi_awareness_context::scoped_dpi_awareness_context()
+ : scoped_dpi_awareness_context(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
+}
+
+utils::scoped_dpi_awareness_context::scoped_dpi_awareness_context(DPI_AWARENESS_CONTEXT context) {
+ const auto user32 = GetModuleHandleW(L"user32.dll");
+ m_setThreadDpiAwarenessContext =
+ user32
+ ? reinterpret_cast(
+ GetProcAddress(user32, "SetThreadDpiAwarenessContext"))
+ : nullptr;
+ m_old = m_setThreadDpiAwarenessContext ? m_setThreadDpiAwarenessContext(context) : DPI_AWARENESS_CONTEXT_UNAWARE;
+}
+
+utils::scoped_dpi_awareness_context::~scoped_dpi_awareness_context() {
+ if (m_setThreadDpiAwarenessContext)
+ m_setThreadDpiAwarenessContext(m_old);
+}
diff --git a/Dalamud.Boot/utils.h b/Dalamud.Boot/utils.h
index 2cdaf60a7..c5833722b 100644
--- a/Dalamud.Boot/utils.h
+++ b/Dalamud.Boot/utils.h
@@ -1,5 +1,6 @@
#pragma once
+#include
#include
#include
#include
@@ -7,6 +8,7 @@
#include
#include
+#include "error_info.h"
#include "unicode.h"
namespace utils {
@@ -18,14 +20,13 @@ namespace utils {
loaded_module(void* hModule) : m_hModule(reinterpret_cast(hModule)) {}
loaded_module(size_t hModule) : m_hModule(reinterpret_cast(hModule)) {}
- std::filesystem::path path() const;
+ DalamudExpected path() const;
bool is_current_process() const { return m_hModule == GetModuleHandleW(nullptr); }
bool owns_address(const void* pAddress) const;
- operator HMODULE() const {
- return m_hModule;
- }
+ operator HMODULE() const { return m_hModule; }
+ operator bool() const { return m_hModule; }
size_t address_int() const { return reinterpret_cast(m_hModule); }
size_t image_size() const { return is_pe64() ? nt_header64().OptionalHeader.SizeOfImage : nt_header32().OptionalHeader.SizeOfImage; }
@@ -58,9 +59,9 @@ namespace utils {
void* get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) const;
template TFn** get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) { return reinterpret_cast(get_imported_function_pointer(pcszDllName, pcszFunctionName, hintOrOrdinal)); }
- [[nodiscard]] std::unique_ptr, decltype(&FreeResource)> get_resource(LPCWSTR lpName, LPCWSTR lpType) const;
- [[nodiscard]] std::wstring get_description() const;
- [[nodiscard]] VS_FIXEDFILEINFO get_file_version() const;
+ [[nodiscard]] DalamudExpected, decltype(&FreeResource)>> get_resource(LPCWSTR lpName, LPCWSTR lpType) const;
+ [[nodiscard]] DalamudExpected get_description() const;
+ [[nodiscard]] DalamudExpected get_file_version() const;
static loaded_module current_process();
static std::vector all_modules();
@@ -269,7 +270,7 @@ namespace utils {
bool is_running_on_wine();
- std::filesystem::path get_module_path(HMODULE hModule);
+ std::wstring get_string_resource(uint32_t resId);
/// @brief Find the game main window.
/// @return Handle to the game main window, or nullptr if it doesn't exist (yet).
@@ -280,4 +281,18 @@ namespace utils {
std::wstring escape_shell_arg(const std::wstring& arg);
std::wstring format_win32_error(DWORD err);
+
+ class scoped_dpi_awareness_context {
+ DPI_AWARENESS_CONTEXT m_old;
+ decltype(&SetThreadDpiAwarenessContext) m_setThreadDpiAwarenessContext;
+
+ public:
+ scoped_dpi_awareness_context();
+ scoped_dpi_awareness_context(DPI_AWARENESS_CONTEXT);
+ ~scoped_dpi_awareness_context();
+ scoped_dpi_awareness_context(const scoped_dpi_awareness_context&) = delete;
+ scoped_dpi_awareness_context(scoped_dpi_awareness_context&&) = delete;
+ scoped_dpi_awareness_context& operator=(const scoped_dpi_awareness_context&) = delete;
+ scoped_dpi_awareness_context& operator=(scoped_dpi_awareness_context&&) = delete;
+ };
}
diff --git a/Dalamud.Boot/veh.cpp b/Dalamud.Boot/veh.cpp
index 85d58eb9d..b0ec1cefa 100644
--- a/Dalamud.Boot/veh.cpp
+++ b/Dalamud.Boot/veh.cpp
@@ -102,9 +102,13 @@ bool is_ffxiv_address(const wchar_t* module_name, const DWORD64 address)
return false;
}
-static void append_injector_launch_args(std::vector& args)
+static DalamudExpected append_injector_launch_args(std::vector& args)
{
- args.emplace_back(L"--game=\"" + utils::loaded_module::current_process().path().wstring() + L"\"");
+ if (auto path = utils::loaded_module::current_process().path())
+ args.emplace_back(L"--game=\"" + path->wstring() + L"\"");
+ else
+ return DalamudUnexpected(std::in_place, std::move(path.error()));
+
switch (g_startInfo.DalamudLoadMethod) {
case DalamudStartInfo::LoadMethod::Entrypoint:
args.emplace_back(L"--mode=entrypoint");
@@ -155,6 +159,8 @@ static void append_injector_launch_args(std::vector& args)
args.emplace_back(szArgList[i]);
LocalFree(szArgList);
}
+
+ return {};
}
LONG exception_handler(EXCEPTION_POINTERS* ex)
@@ -358,11 +364,20 @@ bool veh::add_handler(bool doFullDump, const std::string& workingDirectory)
args.emplace_back(std::format(L"--process-handle={}", reinterpret_cast(hInheritableCurrentProcess)));
args.emplace_back(std::format(L"--exception-info-pipe-read-handle={}", reinterpret_cast(hReadPipeInheritable->get())));
args.emplace_back(std::format(L"--asset-directory={}", unicode::convert(g_startInfo.AssetDirectory)));
- args.emplace_back(std::format(L"--log-directory={}", g_startInfo.BootLogPath.empty()
- ? utils::loaded_module(g_hModule).path().parent_path().wstring()
- : std::filesystem::path(unicode::convert(g_startInfo.BootLogPath)).parent_path().wstring()));
+ if (const auto path = utils::loaded_module(g_hModule).path()) {
+ args.emplace_back(std::format(L"--log-directory={}", g_startInfo.BootLogPath.empty()
+ ? path->parent_path().wstring()
+ : std::filesystem::path(unicode::convert(g_startInfo.BootLogPath)).parent_path().wstring()));
+ } else {
+ logging::W("Failed to read path of the Dalamud Boot module: {}", path.error().describe());
+ return false;
+ }
+
args.emplace_back(L"--");
- append_injector_launch_args(args);
+ if (auto r = append_injector_launch_args(args); !r) {
+ logging::W("Failed to generate injector launch args: {}", r.error().describe());
+ return false;
+ }
for (const auto& arg : args)
{
diff --git a/Dalamud.Boot/xivfixes.cpp b/Dalamud.Boot/xivfixes.cpp
index eb0f7df56..7f9e92225 100644
--- a/Dalamud.Boot/xivfixes.cpp
+++ b/Dalamud.Boot/xivfixes.cpp
@@ -8,12 +8,6 @@
#include "ntdll.h"
#include "utils.h"
-template
-static std::span assume_nonempty_span(std::span t, const char* descr) {
- if (t.empty())
- throw std::runtime_error(std::format("Unexpected empty span found: {}", descr));
- return t;
-}
void xivfixes::unhook_dll(bool bApply) {
static const auto LogTag = "[xivfixes:unhook_dll]";
static const auto LogTagW = L"[xivfixes:unhook_dll]";
@@ -23,77 +17,90 @@ void xivfixes::unhook_dll(bool bApply) {
const auto mods = utils::loaded_module::all_modules();
- const auto test_module = [&](size_t i, const utils::loaded_module & mod) {
- std::filesystem::path path;
- try {
- path = mod.path();
- std::wstring version, description;
- try {
- version = utils::format_file_version(mod.get_file_version());
- } catch (...) {
- version = L"";
- }
-
- try {
- description = mod.get_description();
- } catch (...) {
- description = L"";
- }
-
- logging::I(R"({} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): "{}" ("{}" ver {}))", LogTagW, i + 1, mods.size(), mod.address_int(), mod.address_int() + mod.image_size(), mod.image_size(), path.wstring(), description, version);
- } catch (const std::exception& e) {
- logging::W("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what());
+ for (size_t i = 0; i < mods.size(); i++) {
+ const auto& mod = mods[i];
+ const auto path = mod.path();
+ if (!path) {
+ logging::W(
+ "{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}",
+ LogTag,
+ i + 1,
+ mods.size(),
+ mod.address_int(),
+ path.error().describe());
return;
}
- const auto moduleName = unicode::convert(path.filename().wstring());
+ const auto version = mod.get_file_version()
+ .transform([](const auto& v) { return utils::format_file_version(v.get()); })
+ .value_or(L"");
- std::vector buf;
- std::string formatBuf;
+ const auto description = mod.get_description()
+ .value_or(L"");
+
+ logging::I(
+ R"({} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): "{}" ("{}" ver {}))",
+ LogTagW,
+ i + 1,
+ mods.size(),
+ mod.address_int(),
+ mod.address_int() + mod.image_size(),
+ mod.image_size(),
+ path->wstring(),
+ description,
+ version);
+
+ const auto moduleName = unicode::convert(path->filename().wstring());
+
+ const auto& sectionHeader = mod.section_header(".text");
+ const auto section = mod.span_as(sectionHeader.VirtualAddress, sectionHeader.Misc.VirtualSize);
+ if (section.empty()) {
+ logging::W("{} Error: .text[VA:VA + VS] is empty", LogTag);
+ return;
+ }
+
+ auto hFsDllRaw = CreateFileW(path->c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
+ if (hFsDllRaw == INVALID_HANDLE_VALUE) {
+ logging::W("{} Module loaded in current process but could not open file: Win32 error {}", LogTag, GetLastError());
+ return;
+ }
+
+ auto hFsDll = std::unique_ptr(hFsDllRaw, &CloseHandle);
+ std::vector buf(section.size());
+ SetFilePointer(hFsDll.get(), sectionHeader.PointerToRawData, nullptr, FILE_CURRENT);
+ if (DWORD read{}; ReadFile(hFsDll.get(), &buf[0], static_cast(buf.size()), &read, nullptr)) {
+ if (read < section.size_bytes()) {
+ logging::W("{} ReadFile: read {} bytes < requested {} bytes", LogTagW, read, section.size_bytes());
+ return;
+ }
+ } else {
+ logging::I("{} ReadFile: Win32 error {}", LogTagW, GetLastError());
+ return;
+ }
+
+ const auto doRestore = g_startInfo.BootUnhookDlls.contains(unicode::convert(path->filename().u8string()));
try {
- const auto& sectionHeader = mod.section_header(".text");
- const auto section = assume_nonempty_span(mod.span_as(sectionHeader.VirtualAddress, sectionHeader.Misc.VirtualSize), ".text[VA:VA+VS]");
- auto hFsDllRaw = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
- if (hFsDllRaw == INVALID_HANDLE_VALUE) {
- logging::W("{} Module loaded in current process but could not open file: Win32 error {}", LogTag, GetLastError());
- return;
- }
- auto hFsDll = std::unique_ptr(hFsDllRaw, &CloseHandle);
-
- buf.resize(section.size());
- SetFilePointer(hFsDll.get(), sectionHeader.PointerToRawData, nullptr, FILE_CURRENT);
- if (DWORD read{}; ReadFile(hFsDll.get(), &buf[0], static_cast(buf.size()), &read, nullptr)) {
- if (read < section.size_bytes()) {
- logging::W("{} ReadFile: read {} bytes < requested {} bytes", LogTagW, read, section.size_bytes());
- return;
- }
- } else {
- logging::I("{} ReadFile: Win32 error {}", LogTagW, GetLastError());
- return;
- }
-
- const auto doRestore = g_startInfo.BootUnhookDlls.contains(unicode::convert(path.filename().u8string()));
-
std::optional tenderizer;
- for (size_t i = 0, instructionLength = 1, printed = 0; i < buf.size(); i += instructionLength) {
- if (section[i] == buf[i]) {
+ std::string formatBuf;
+ for (size_t inst = 0, instructionLength = 1, printed = 0; inst < buf.size(); inst += instructionLength) {
+ if (section[inst] == buf[inst]) {
instructionLength = 1;
continue;
}
- const auto rva = sectionHeader.VirtualAddress + i;
+ const auto rva = sectionHeader.VirtualAddress + inst;
nmd_x86_instruction instruction{};
- if (!nmd_x86_decode(§ion[i], section.size() - i, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL)) {
+ if (!nmd_x86_decode(§ion[inst], section.size() - inst, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL)) {
instructionLength = 1;
if (printed < 64) {
- logging::W("{} {}+0x{:0X}: dd {:02X}", LogTag, moduleName, rva, static_cast(section[i]));
+ logging::W("{} {}+0x{:0X}: dd {:02X}", LogTag, moduleName, rva, static_cast(section[inst]));
printed++;
}
} else {
instructionLength = instruction.length;
if (printed < 64) {
formatBuf.resize(128);
- nmd_x86_format(&instruction, &formatBuf[0], reinterpret_cast(§ion[i]), NMD_X86_FORMAT_FLAGS_DEFAULT | NMD_X86_FORMAT_FLAGS_BYTES);
+ nmd_x86_format(&instruction, &formatBuf[0], reinterpret_cast(§ion[inst]), NMD_X86_FORMAT_FLAGS_DEFAULT | NMD_X86_FORMAT_FLAGS_BYTES);
formatBuf.resize(strnlen(&formatBuf[0], formatBuf.size()));
const auto& directory = mod.data_directory(IMAGE_DIRECTORY_ENTRY_EXPORT);
@@ -103,25 +110,25 @@ void xivfixes::unhook_dll(bool bApply) {
const auto functions = mod.span_as(exportDirectory.AddressOfFunctions, exportDirectory.NumberOfFunctions);
std::string resolvedExportName;
- for (size_t j = 0; j < names.size(); ++j) {
+ for (size_t nameIndex = 0; nameIndex < names.size(); ++nameIndex) {
std::string_view name;
- if (const char* pcszName = mod.address_as(names[j]); pcszName < mod.address() || pcszName >= mod.address() + mod.image_size()) {
+ if (const char* pcszName = mod.address_as(names[nameIndex]); pcszName < mod.address() || pcszName >= mod.address() + mod.image_size()) {
if (IsBadReadPtr(pcszName, 256)) {
- logging::W("{} Name #{} points to an invalid address outside the executable. Skipping.", LogTag, j);
+ logging::W("{} Name #{} points to an invalid address outside the executable. Skipping.", LogTag, nameIndex);
continue;
}
name = std::string_view(pcszName, strnlen(pcszName, 256));
- logging::W("{} Name #{} points to a seemingly valid address outside the executable: {}", LogTag, j, name);
+ logging::W("{} Name #{} points to a seemingly valid address outside the executable: {}", LogTag, nameIndex, name);
}
- if (ordinals[j] >= functions.size()) {
- logging::W("{} Ordinal #{} points to function index #{} >= #{}. Skipping.", LogTag, j, ordinals[j], functions.size());
+ if (ordinals[nameIndex] >= functions.size()) {
+ logging::W("{} Ordinal #{} points to function index #{} >= #{}. Skipping.", LogTag, nameIndex, ordinals[nameIndex], functions.size());
continue;
}
- const auto rva = functions[ordinals[j]];
- if (rva == §ion[i] - mod.address()) {
+ const auto rva = functions[ordinals[nameIndex]];
+ if (rva == §ion[inst] - mod.address()) {
resolvedExportName = std::format("[export:{}]", name);
break;
}
@@ -135,7 +142,7 @@ void xivfixes::unhook_dll(bool bApply) {
if (doRestore) {
if (!tenderizer)
tenderizer.emplace(section, PAGE_EXECUTE_READWRITE);
- memcpy(§ion[i], &buf[i], instructionLength);
+ memcpy(§ion[inst], &buf[inst], instructionLength);
}
}
@@ -147,21 +154,7 @@ void xivfixes::unhook_dll(bool bApply) {
} catch (const std::exception& e) {
logging::W("{} Error: {}", LogTag, e.what());
}
- };
-
- // This is needed since try and __try cannot be used in the same function. Lambdas circumvent the limitation.
- const auto windows_exception_handler = [&]() {
- for (size_t i = 0; i < mods.size(); i++) {
- const auto& mod = mods[i];
- __try {
- test_module(i, mod);
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- logging::W("{} Error: Access Violation", LogTag);
- }
- }
- };
-
- windows_exception_handler();
+ }
}
using TFnGetInputDeviceManager = void* ();
@@ -294,13 +287,11 @@ static bool is_xivalex(const std::filesystem::path& dllPath) {
static bool is_openprocess_already_dealt_with() {
static const auto s_value = [] {
for (const auto& mod : utils::loaded_module::all_modules()) {
- try {
- if (is_xivalex(mod.path()))
- return true;
-
- } catch (...) {
- // pass
- }
+ const auto path = mod.path().value_or({});
+ if (path.empty())
+ continue;
+ if (is_xivalex(path))
+ return true;
}
return false;
}();
@@ -650,43 +641,22 @@ void xivfixes::symbol_load_patches(bool bApply) {
void xivfixes::disable_game_debugging_protection(bool bApply) {
static const char* LogTag = "[xivfixes:disable_game_debugging_protection]";
- static const std::vector patchBytes = {
- 0x31, 0xC0, // XOR EAX, EAX
- 0x90, // NOP
- 0x90, // NOP
- 0x90, // NOP
- 0x90 // NOP
- };
+ static std::optional> s_hookIsDebuggerPresent;
- if (!bApply)
- return;
+ if (bApply) {
+ if (!g_startInfo.BootEnabledGameFixes.contains("disable_game_debugging_protection")) {
+ logging::I("{} Turned off via environment variable.", LogTag);
+ return;
+ }
- if (!g_startInfo.BootEnabledGameFixes.contains("disable_game_debugging_protection")) {
- logging::I("{} Turned off via environment variable.", LogTag);
- return;
- }
-
- // Find IsDebuggerPresent in Framework.Tick()
- const char* matchPtr = utils::signature_finder()
- .look_in(utils::loaded_module(g_hGameInstance), ".text")
- .look_for_hex("FF 15 ?? ?? ?? ?? 85 C0 74 13 41")
- .find_one()
- .Match.data();
-
- if (!matchPtr) {
- logging::E("{} Failed to find signature.", LogTag);
- return;
- }
-
- void* address = const_cast(static_cast(matchPtr));
-
- DWORD oldProtect;
- if (VirtualProtect(address, patchBytes.size(), PAGE_EXECUTE_READWRITE, &oldProtect)) {
- memcpy(address, patchBytes.data(), patchBytes.size());
- VirtualProtect(address, patchBytes.size(), oldProtect, &oldProtect);
- logging::I("{} Patch applied at address 0x{:X}.", LogTag, reinterpret_cast(address));
+ s_hookIsDebuggerPresent.emplace("kernel32.dll!IsDebuggerPresent", "kernel32.dll", "IsDebuggerPresent", 0);
+ s_hookIsDebuggerPresent->set_detour([]() { return false; });
+ logging::I("{} Enable", LogTag);
} else {
- logging::E("{} Failed to change memory protection.", LogTag);
+ if (s_hookIsDebuggerPresent) {
+ logging::I("{} Disable", LogTag);
+ s_hookIsDebuggerPresent.reset();
+ }
}
}
diff --git a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
index 1c89f4ff7..7f8de3843 100644
--- a/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
+++ b/Dalamud.Injector.Boot/Dalamud.Injector.Boot.vcxproj
@@ -38,7 +38,7 @@
Level3
true
true
- stdcpplatest
+ stdcpp23
pch.h
ProgramDatabase
CPPDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
@@ -55,7 +55,7 @@
true
false
- MultiThreadedDebugDLL
+ MultiThreadedDebugDLL
_DEBUG;%(PreprocessorDefinitions)
@@ -67,7 +67,7 @@
true
true
- MultiThreadedDLL
+ MultiThreadedDLL
NDEBUG;%(PreprocessorDefinitions)
@@ -108,4 +108,4 @@
-
+
\ No newline at end of file
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 76e84e779..01eb1a2ec 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -6,7 +6,7 @@
XIV Launcher addon framework
- 13.0.0.0
+ 13.0.0.3
$(DalamudVersion)
$(DalamudVersion)
$(DalamudVersion)
@@ -68,7 +68,7 @@
-
+
all
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs
index 8a97f5cc2..c008db08f 100644
--- a/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs
+++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs
@@ -38,7 +38,7 @@ public abstract unsafe class AddonArgs
///
/// The name to check.
/// Whether it is the case.
- internal bool IsAddon(ReadOnlySpan name)
+ internal bool IsAddon(string name)
{
if (this.Addon.IsNull)
return false;
@@ -46,12 +46,10 @@ public abstract unsafe class AddonArgs
if (name.Length is 0 or > 32)
return false;
- var addonName = this.Addon.Name;
-
- if (string.IsNullOrEmpty(addonName))
+ if (string.IsNullOrEmpty(this.Addon.Name))
return false;
- return name == addonName;
+ return name == this.Addon.Name;
}
///
diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs
index 4c32873c6..407b54060 100644
--- a/Dalamud/Game/ClientState/ClientState.cs
+++ b/Dalamud/Game/ClientState/ClientState.cs
@@ -38,7 +38,7 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
private readonly ClientStateAddressResolver address;
private readonly Hook setupTerritoryTypeHook;
private readonly Hook uiModuleHandlePacketHook;
- private readonly Hook onLogoutHook;
+ private Hook onLogoutHook;
[ServiceManager.ServiceDependency]
private readonly Framework framework = Service.Get();
@@ -64,14 +64,14 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
this.setupTerritoryTypeHook = Hook.FromAddress(setTerritoryTypeAddr, this.SetupTerritoryTypeDetour);
this.uiModuleHandlePacketHook = Hook.FromAddress((nint)UIModule.StaticVirtualTablePointer->HandlePacket, this.UIModuleHandlePacketDetour);
- this.onLogoutHook = Hook.FromAddress((nint)LogoutCallbackInterface.StaticVirtualTablePointer->OnLogout, this.OnLogoutDetour);
this.framework.Update += this.FrameworkOnOnUpdateEvent;
this.networkHandlers.CfPop += this.NetworkHandlersOnCfPop;
this.setupTerritoryTypeHook.Enable();
this.uiModuleHandlePacketHook.Enable();
- this.onLogoutHook.Enable();
+
+ this.framework.RunOnTick(this.Setup);
}
private unsafe delegate void ProcessPacketPlayerSetupDelegate(nint a1, nint packet);
@@ -180,8 +180,25 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
this.networkHandlers.CfPop -= this.NetworkHandlersOnCfPop;
}
+ private unsafe void Setup()
+ {
+ this.onLogoutHook = Hook.FromAddress((nint)AgentLobby.Instance()->LogoutCallbackInterface.VirtualTable->OnLogout, this.OnLogoutDetour);
+ this.onLogoutHook.Enable();
+
+ this.TerritoryType = (ushort)GameMain.Instance()->CurrentTerritoryTypeId;
+ }
+
private unsafe void SetupTerritoryTypeDetour(EventFramework* eventFramework, ushort territoryType)
{
+ this.SetTerritoryType(territoryType);
+ this.setupTerritoryTypeHook.Original(eventFramework, territoryType);
+ }
+
+ private unsafe void SetTerritoryType(ushort territoryType)
+ {
+ if (this.TerritoryType == territoryType)
+ return;
+
Log.Debug("TerritoryType changed: {0}", territoryType);
this.TerritoryType = territoryType;
@@ -207,8 +224,6 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
}
}
}
-
- this.setupTerritoryTypeHook.Original(eventFramework, territoryType);
}
private unsafe void UIModuleHandlePacketDetour(
diff --git a/Dalamud/Game/Config/SystemConfigOption.cs b/Dalamud/Game/Config/SystemConfigOption.cs
index 154992637..dcfe16751 100644
--- a/Dalamud/Game/Config/SystemConfigOption.cs
+++ b/Dalamud/Game/Config/SystemConfigOption.cs
@@ -1031,6 +1031,13 @@ public enum SystemConfigOption
[GameConfigOption("TitleScreenType", ConfigType.UInt)]
TitleScreenType,
+ ///
+ /// System option with the internal name DisplayObjectLimitType2.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("DisplayObjectLimitType2", ConfigType.UInt)]
+ DisplayObjectLimitType2,
+
///
/// System option with the internal name AccessibilitySoundVisualEnable.
/// This option is a UInt.
@@ -1115,6 +1122,13 @@ public enum SystemConfigOption
[GameConfigOption("CameraZoom", ConfigType.UInt)]
CameraZoom,
+ ///
+ /// System option with the internal name DynamicAroundRangeMode.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("DynamicAroundRangeMode", ConfigType.UInt)]
+ DynamicAroundRangeMode,
+
///
/// System option with the internal name DynamicRezoType.
/// This option is a UInt.
diff --git a/Dalamud/Game/Config/UiConfigOption.cs b/Dalamud/Game/Config/UiConfigOption.cs
index 1a59b8945..f6a9aaa21 100644
--- a/Dalamud/Game/Config/UiConfigOption.cs
+++ b/Dalamud/Game/Config/UiConfigOption.cs
@@ -2032,6 +2032,13 @@ public enum UiConfigOption
[GameConfigOption("NamePlateDispJobIconInInstanceOther", ConfigType.UInt)]
NamePlateDispJobIconInInstanceOther,
+ ///
+ /// UiConfig option with the internal name LogNamePlateDispEnemyCast.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogNamePlateDispEnemyCast", ConfigType.UInt)]
+ LogNamePlateDispEnemyCast,
+
///
/// UiConfig option with the internal name ActiveInfo.
/// This option is a UInt.
@@ -2690,6 +2697,594 @@ public enum UiConfigOption
[GameConfigOption("LogColorOtherClass", ConfigType.UInt)]
LogColorOtherClass,
+ ///
+ /// UiConfig option with the internal name LogChatBubbleEnableChatBubble.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleEnableChatBubble", ConfigType.UInt)]
+ LogChatBubbleEnableChatBubble,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShowMax.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShowMax", ConfigType.UInt)]
+ LogChatBubbleShowMax,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShowOwnMessage.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShowOwnMessage", ConfigType.UInt)]
+ LogChatBubbleShowOwnMessage,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShowDuringBattle.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShowDuringBattle", ConfigType.UInt)]
+ LogChatBubbleShowDuringBattle,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleSizeType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleSizeType", ConfigType.UInt)]
+ LogChatBubbleSizeType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShowLargePvP.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShowLargePvP", ConfigType.UInt)]
+ LogChatBubbleShowLargePvP,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShowQuickChat.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShowQuickChat", ConfigType.UInt)]
+ LogChatBubbleShowQuickChat,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleDispRowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleDispRowType", ConfigType.UInt)]
+ LogChatBubbleDispRowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleSayShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleSayShowType", ConfigType.UInt)]
+ LogChatBubbleSayShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleSayFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleSayFontColor", ConfigType.UInt)]
+ LogChatBubbleSayFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleSayWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleSayWindowColor", ConfigType.UInt)]
+ LogChatBubbleSayWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleYellShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleYellShowType", ConfigType.UInt)]
+ LogChatBubbleYellShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleYellFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleYellFontColor", ConfigType.UInt)]
+ LogChatBubbleYellFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleYellWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleYellWindowColor", ConfigType.UInt)]
+ LogChatBubbleYellWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShoutShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShoutShowType", ConfigType.UInt)]
+ LogChatBubbleShoutShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShoutFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShoutFontColor", ConfigType.UInt)]
+ LogChatBubbleShoutFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleShoutWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleShoutWindowColor", ConfigType.UInt)]
+ LogChatBubbleShoutWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleTellShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleTellShowType", ConfigType.UInt)]
+ LogChatBubbleTellShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleTellFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleTellFontColor", ConfigType.UInt)]
+ LogChatBubbleTellFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleTellWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleTellWindowColor", ConfigType.UInt)]
+ LogChatBubbleTellWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePartyShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePartyShowType", ConfigType.UInt)]
+ LogChatBubblePartyShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePartyFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePartyFontColor", ConfigType.UInt)]
+ LogChatBubblePartyFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePartyWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePartyWindowColor", ConfigType.UInt)]
+ LogChatBubblePartyWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleAllianceShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleAllianceShowType", ConfigType.UInt)]
+ LogChatBubbleAllianceShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleAllianceFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleAllianceFontColor", ConfigType.UInt)]
+ LogChatBubbleAllianceFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleAllianceWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleAllianceWindowColor", ConfigType.UInt)]
+ LogChatBubbleAllianceWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleFcShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleFcShowType", ConfigType.UInt)]
+ LogChatBubbleFcShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleFcFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleFcFontColor", ConfigType.UInt)]
+ LogChatBubbleFcFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleFcWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleFcWindowColor", ConfigType.UInt)]
+ LogChatBubbleFcWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleBeginnerShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleBeginnerShowType", ConfigType.UInt)]
+ LogChatBubbleBeginnerShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleBeginnerFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleBeginnerFontColor", ConfigType.UInt)]
+ LogChatBubbleBeginnerFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleBeginnerWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleBeginnerWindowColor", ConfigType.UInt)]
+ LogChatBubbleBeginnerWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePvpteamShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePvpteamShowType", ConfigType.UInt)]
+ LogChatBubblePvpteamShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePvpteamFontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePvpteamFontColor", ConfigType.UInt)]
+ LogChatBubblePvpteamFontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubblePvpteamWindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubblePvpteamWindowColor", ConfigType.UInt)]
+ LogChatBubblePvpteamWindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs1ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs1ShowType", ConfigType.UInt)]
+ LogChatBubbleLs1ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs1FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs1FontColor", ConfigType.UInt)]
+ LogChatBubbleLs1FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs1WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs1WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs1WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs2ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs2ShowType", ConfigType.UInt)]
+ LogChatBubbleLs2ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs2FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs2FontColor", ConfigType.UInt)]
+ LogChatBubbleLs2FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs2WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs2WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs2WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs3ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs3ShowType", ConfigType.UInt)]
+ LogChatBubbleLs3ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs3FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs3FontColor", ConfigType.UInt)]
+ LogChatBubbleLs3FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs3WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs3WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs3WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs4ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs4ShowType", ConfigType.UInt)]
+ LogChatBubbleLs4ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs4FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs4FontColor", ConfigType.UInt)]
+ LogChatBubbleLs4FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs4WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs4WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs4WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs5ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs5ShowType", ConfigType.UInt)]
+ LogChatBubbleLs5ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs5FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs5FontColor", ConfigType.UInt)]
+ LogChatBubbleLs5FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs5WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs5WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs5WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs6ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs6ShowType", ConfigType.UInt)]
+ LogChatBubbleLs6ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs6FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs6FontColor", ConfigType.UInt)]
+ LogChatBubbleLs6FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs6WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs6WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs6WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs7ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs7ShowType", ConfigType.UInt)]
+ LogChatBubbleLs7ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs7FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs7FontColor", ConfigType.UInt)]
+ LogChatBubbleLs7FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs7WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs7WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs7WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs8ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs8ShowType", ConfigType.UInt)]
+ LogChatBubbleLs8ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs8FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs8FontColor", ConfigType.UInt)]
+ LogChatBubbleLs8FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleLs8WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleLs8WindowColor", ConfigType.UInt)]
+ LogChatBubbleLs8WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls1ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls1ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls1ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls1FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls1FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls1FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls1WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls1WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls1WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls2ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls2ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls2ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls2FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls2FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls2FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls2WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls2WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls2WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls3ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls3ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls3ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls3FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls3FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls3FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls3WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls3WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls3WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls4ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls4ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls4ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls4FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls4FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls4FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls4WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls4WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls4WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls5ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls5ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls5ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls5FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls5FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls5FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls5WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls5WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls5WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls6ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls6ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls6ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls6FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls6FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls6FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls6WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls6WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls6WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls7ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls7ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls7ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls7FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls7FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls7FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls7WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls7WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls7WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls8ShowType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls8ShowType", ConfigType.UInt)]
+ LogChatBubbleCwls8ShowType,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls8FontColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls8FontColor", ConfigType.UInt)]
+ LogChatBubbleCwls8FontColor,
+
+ ///
+ /// UiConfig option with the internal name LogChatBubbleCwls8WindowColor.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogChatBubbleCwls8WindowColor", ConfigType.UInt)]
+ LogChatBubbleCwls8WindowColor,
+
+ ///
+ /// UiConfig option with the internal name LogPermeationRateInput.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("LogPermeationRateInput", ConfigType.UInt)]
+ LogPermeationRateInput,
+
///
/// UiConfig option with the internal name ChatType.
/// This option is a UInt.
@@ -3453,6 +4048,27 @@ public enum UiConfigOption
[GameConfigOption("GPoseMotionFilterAction", ConfigType.UInt)]
GPoseMotionFilterAction,
+ ///
+ /// UiConfig option with the internal name GPoseRollRotationCameraCorrection.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("GPoseRollRotationCameraCorrection", ConfigType.UInt)]
+ GPoseRollRotationCameraCorrection,
+
+ ///
+ /// UiConfig option with the internal name GPoseInitCameraFocus.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("GPoseInitCameraFocus", ConfigType.UInt)]
+ GPoseInitCameraFocus,
+
+ ///
+ /// UiConfig option with the internal name GposePortraitRotateType.
+ /// This option is a UInt.
+ ///
+ [GameConfigOption("GposePortraitRotateType", ConfigType.UInt)]
+ GposePortraitRotateType,
+
///
/// UiConfig option with the internal name LsListSortPriority.
/// This option is a UInt.
diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs
index 6de4e3c3f..d7303c4ce 100644
--- a/Dalamud/Game/Gui/ChatGui.cs
+++ b/Dalamud/Game/Gui/ChatGui.cs
@@ -41,7 +41,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
private static readonly ModuleLog Log = new("ChatGui");
private readonly Queue chatQueue = new();
- private readonly Dictionary<(string PluginName, Guid CommandId), Action> dalamudLinkHandlers = new();
+ private readonly Dictionary<(string PluginName, uint CommandId), Action> dalamudLinkHandlers = new();
private readonly Hook printMessageHook;
private readonly Hook inventoryItemCopyHook;
@@ -50,7 +50,8 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
[ServiceManager.ServiceDependency]
private readonly DalamudConfiguration configuration = Service.Get();
- private ImmutableDictionary<(string PluginName, Guid CommandId), Action>? dalamudLinkHandlersCopy;
+ private ImmutableDictionary<(string PluginName, uint CommandId), Action>? dalamudLinkHandlersCopy;
+ private uint dalamudChatHandlerId = 1000;
[ServiceManager.ServiceConstructor]
private ChatGui()
@@ -86,7 +87,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
public byte LastLinkedItemFlags { get; private set; }
///
- public IReadOnlyDictionary<(string PluginName, Guid CommandId), Action> RegisteredLinkHandlers
+ public IReadOnlyDictionary<(string PluginName, uint CommandId), Action> RegisteredLinkHandlers
{
get
{
@@ -164,19 +165,33 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
#region Chat Links
- ///
- public DalamudLinkPayload AddChatLinkHandler(Action commandAction)
+ ///
+ /// Register a chat link handler.
+ ///
+ /// Internal use only.
+ /// The action to be executed.
+ /// Returns an SeString payload for the link.
+ public DalamudLinkPayload AddChatLinkHandler(Action commandAction)
{
- return this.AddChatLinkHandler("Dalamud", commandAction);
+ return this.AddChatLinkHandler("Dalamud", this.dalamudChatHandlerId++, commandAction);
}
///
- public void RemoveChatLinkHandler(Guid commandId)
+ /// Internal use only.
+ public DalamudLinkPayload AddChatLinkHandler(uint commandId, Action commandAction)
+ {
+ return this.AddChatLinkHandler("Dalamud", commandId, commandAction);
+ }
+
+ ///
+ /// Internal use only.
+ public void RemoveChatLinkHandler(uint commandId)
{
this.RemoveChatLinkHandler("Dalamud", commandId);
}
///
+ /// Internal use only.
public void RemoveChatLinkHandler()
{
this.RemoveChatLinkHandler("Dalamud");
@@ -240,11 +255,11 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
/// Create a link handler.
///
/// The name of the plugin handling the link.
+ /// The ID of the command to run.
/// The command action itself.
/// A payload for handling.
- internal DalamudLinkPayload AddChatLinkHandler(string pluginName, Action commandAction)
+ internal DalamudLinkPayload AddChatLinkHandler(string pluginName, uint commandId, Action commandAction)
{
- var commandId = Guid.CreateVersion7();
var payload = new DalamudLinkPayload { Plugin = pluginName, CommandId = commandId };
lock (this.dalamudLinkHandlers)
{
@@ -277,7 +292,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
///
/// The name of the plugin handling the link.
/// The ID of the command to be removed.
- internal void RemoveChatLinkHandler(string pluginName, Guid commandId)
+ internal void RemoveChatLinkHandler(string pluginName, uint commandId)
{
lock (this.dalamudLinkHandlers)
{
@@ -400,13 +415,13 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
if (!terminatedSender.SequenceEqual(possiblyModifiedSenderData))
{
- Log.Verbose($"HandlePrintMessageDetour Sender modified: {SeString.Parse(terminatedSender)} -> {parsedSender}");
+ Log.Verbose($"HandlePrintMessageDetour Sender modified: {new ReadOnlySeStringSpan(terminatedSender).ToMacroString()} -> {new ReadOnlySeStringSpan(possiblyModifiedSenderData).ToMacroString()}");
sender->SetString(possiblyModifiedSenderData);
}
if (!terminatedMessage.SequenceEqual(possiblyModifiedMessageData))
{
- Log.Verbose($"HandlePrintMessageDetour Message modified: {SeString.Parse(terminatedMessage)} -> {parsedMessage}");
+ Log.Verbose($"HandlePrintMessageDetour Message modified: {new ReadOnlySeStringSpan(terminatedMessage).ToMacroString()} -> {new ReadOnlySeStringSpan(possiblyModifiedMessageData).ToMacroString()}");
message->SetString(possiblyModifiedMessageData);
}
@@ -534,7 +549,7 @@ internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui
public byte LastLinkedItemFlags => this.chatGuiService.LastLinkedItemFlags;
///
- public IReadOnlyDictionary<(string PluginName, Guid CommandId), Action> RegisteredLinkHandlers => this.chatGuiService.RegisteredLinkHandlers;
+ public IReadOnlyDictionary<(string PluginName, uint CommandId), Action> RegisteredLinkHandlers => this.chatGuiService.RegisteredLinkHandlers;
///
void IInternalDisposableService.DisposeService()
@@ -551,11 +566,11 @@ internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui
}
///
- public DalamudLinkPayload AddChatLinkHandler(Action commandAction)
- => this.chatGuiService.AddChatLinkHandler(this.plugin.InternalName, commandAction);
+ public DalamudLinkPayload AddChatLinkHandler(uint commandId, Action commandAction)
+ => this.chatGuiService.AddChatLinkHandler(this.plugin.InternalName, commandId, commandAction);
///
- public void RemoveChatLinkHandler(Guid commandId)
+ public void RemoveChatLinkHandler(uint commandId)
=> this.chatGuiService.RemoveChatLinkHandler(this.plugin.InternalName, commandId);
///
diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs
index 8a8a4787a..bd8d8e1d7 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBar.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs
@@ -586,8 +586,7 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar
newTextNode->LineSpacing = 12;
newTextNode->AlignmentFontType = 5;
newTextNode->FontSize = 14;
- newTextNode->TextFlags = (byte)TextFlags.Edge;
- newTextNode->TextFlags2 = 0;
+ newTextNode->TextFlags = TextFlags.Edge;
if (this.emptyString == null)
this.emptyString = Utf8String.FromString(" ");
@@ -642,7 +641,7 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar
break;
case AddonEventType.MouseClick:
- dtrBarEntry.OnClick?.Invoke(new AddonMouseEventData(eventData));
+ dtrBarEntry.OnClick?.Invoke(DtrInteractionEvent.FromMouseEvent(new AddonMouseEventData(eventData)));
break;
}
}
diff --git a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
index 54847705d..6fdc504ca 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
@@ -43,6 +43,11 @@ public interface IReadOnlyDtrBarEntry
/// Gets a value indicating whether the user has hidden this entry from view through the Dalamud settings.
///
public bool UserHidden { get; }
+
+ ///
+ /// Gets an action to be invoked when the user clicks on the dtr entry.
+ ///
+ public Action? OnClick { get; }
}
///
@@ -68,7 +73,7 @@ public interface IDtrBarEntry : IReadOnlyDtrBarEntry
///
/// Gets or sets an action to be invoked when the user clicks on the dtr entry.
///
- public Action? OnClick { get; set; }
+ public new Action? OnClick { get; set; }
///
/// Remove this entry from the bar.
@@ -118,7 +123,7 @@ internal sealed unsafe class DtrBarEntry : IDisposable, IDtrBarEntry
public SeString? Tooltip { get; set; }
///
- public Action? OnClick { get; set; }
+ public Action? OnClick { get; set; }
///
public bool HasClickAction => this.OnClick != null;
diff --git a/Dalamud/Game/Gui/Dtr/DtrInteractionEvent.cs b/Dalamud/Game/Gui/Dtr/DtrInteractionEvent.cs
new file mode 100644
index 000000000..8b2bd8a7d
--- /dev/null
+++ b/Dalamud/Game/Gui/Dtr/DtrInteractionEvent.cs
@@ -0,0 +1,59 @@
+using System.Numerics;
+
+using Dalamud.Game.Addon.Events.EventDataTypes;
+
+namespace Dalamud.Game.Gui.Dtr;
+
+///
+/// Represents an interaction event from the DTR system.
+///
+public class DtrInteractionEvent
+{
+ ///
+ /// Gets the type of mouse click (left or right).
+ ///
+ public MouseClickType ClickType { get; init; }
+
+ ///
+ /// Gets the modifier keys that were held during the click.
+ ///
+ public ClickModifierKeys ModifierKeys { get; init; }
+
+ ///
+ /// Gets the scroll direction of the mouse wheel, if applicable.
+ ///
+ public MouseScrollDirection ScrollDirection { get; init; }
+
+ ///
+ /// Gets lower-level mouse data, if this event came from native UI.
+ ///
+ /// Can only be set by Dalamud. If null, this event was manually created.
+ ///
+ public AddonMouseEventData? AtkEventSource { get; private init; }
+
+ ///
+ /// Gets the position of the mouse cursor when the event occurred.
+ ///
+ public Vector2 Position { get; init; }
+
+ ///
+ /// Helper to create a from an .
+ ///
+ /// The event.
+ /// A better event.
+ public static DtrInteractionEvent FromMouseEvent(AddonMouseEventData ev)
+ {
+ return new DtrInteractionEvent
+ {
+ AtkEventSource = ev,
+ ClickType = ev.IsLeftClick ? MouseClickType.Left : MouseClickType.Right,
+ ModifierKeys = (ev.IsAltHeld ? ClickModifierKeys.Alt : 0) |
+ (ev.IsControlHeld ? ClickModifierKeys.Ctrl : 0) |
+ (ev.IsShiftHeld ? ClickModifierKeys.Shift : 0),
+ ScrollDirection = ev.IsScrollUp ? MouseScrollDirection.Up :
+ ev.IsScrollDown ? MouseScrollDirection.Down :
+ MouseScrollDirection.None,
+ Position = ev.Position,
+ };
+ }
+}
diff --git a/Dalamud/Game/Gui/Dtr/DtrInteractionTypes.cs b/Dalamud/Game/Gui/Dtr/DtrInteractionTypes.cs
new file mode 100644
index 000000000..7c498dc94
--- /dev/null
+++ b/Dalamud/Game/Gui/Dtr/DtrInteractionTypes.cs
@@ -0,0 +1,65 @@
+namespace Dalamud.Game.Gui.Dtr;
+
+///
+/// An enum representing the mouse click types.
+///
+public enum MouseClickType
+{
+ ///
+ /// A left click.
+ ///
+ Left,
+
+ ///
+ /// A right click.
+ ///
+ Right,
+}
+
+///
+/// Modifier keys that can be held during a mouse click event.
+///
+[Flags]
+public enum ClickModifierKeys
+{
+ ///
+ /// No modifiers were present.
+ ///
+ None = 0,
+
+ ///
+ /// The CTRL key was held.
+ ///
+ Ctrl = 1 << 0,
+
+ ///
+ /// The ALT key was held.
+ ///
+ Alt = 1 << 1,
+
+ ///
+ /// The SHIFT key was held.
+ ///
+ Shift = 1 << 2,
+}
+
+///
+/// Possible directions for scroll wheel events.
+///
+public enum MouseScrollDirection
+{
+ ///
+ /// No scrolling.
+ ///
+ None = 0,
+
+ ///
+ /// A scroll up event.
+ ///
+ Up = 1,
+
+ ///
+ /// A scroll down event.
+ ///
+ Down = -1,
+}
diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs
index dc1e54e77..67f4f563e 100644
--- a/Dalamud/Game/SigScanner.cs
+++ b/Dalamud/Game/SigScanner.cs
@@ -343,11 +343,11 @@ public class SigScanner : IDisposable, ISigScanner
break;
var scanRet = mBase + index;
+ mBase = scanRet + 1;
if (this.IsCopy)
scanRet -= this.moduleCopyOffset;
yield return scanRet;
- mBase = scanRet + 1;
}
}
diff --git a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs
index 9e2466df4..8b6a2bed8 100644
--- a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs
+++ b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs
@@ -121,6 +121,15 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator
return this.Evaluate(ReadOnlySeString.FromMacroString(macroString).AsSpan(), localParameters, language);
}
+ ///
+ public ReadOnlySeString EvaluateMacroString(
+ ReadOnlySpan macroString,
+ Span localParameters = default,
+ ClientLanguage? language = null)
+ {
+ return this.Evaluate(ReadOnlySeString.FromMacroString(macroString).AsSpan(), localParameters, language);
+ }
+
///
public ReadOnlySeString EvaluateFromAddon(
uint addonId,
@@ -247,6 +256,9 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator
case MacroCode.Switch:
return this.TryResolveSwitch(in context, payload);
+ case MacroCode.SwitchPlatform:
+ return this.TryResolveSwitchPlatform(in context, payload);
+
case MacroCode.PcName:
return this.TryResolvePcName(in context, payload);
@@ -450,6 +462,29 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator
return false;
}
+ private bool TryResolveSwitchPlatform(in SeStringContext context, in ReadOnlySePayloadSpan payload)
+ {
+ if (!payload.TryGetExpression(out var expr1))
+ return false;
+
+ if (!expr1.TryGetInt(out var intVal))
+ return false;
+
+ // Our version of the game uses IsMacClient() here and the
+ // Xbox version seems to always return 7 for the platform.
+ var platform = Util.IsWine() ? 5 : 3;
+
+ // The sheet is seeminly split into first 20 rows for wired controllers
+ // and the last 20 rows for wireless controllers.
+ var rowId = (uint)((20 * ((intVal - 1) / 20)) + (platform - 4 < 2 ? 2 : 1));
+
+ if (!this.dataManager.GetExcelSheet().TryGetRow(rowId, out var platformRow))
+ return false;
+
+ context.Builder.Append(platformRow.Name);
+ return true;
+ }
+
private unsafe bool TryResolvePcName(in SeStringContext context, in ReadOnlySePayloadSpan payload)
{
if (!payload.TryGetExpression(out var eEntityId))
diff --git a/Dalamud/Game/Text/Evaluator/SeStringParameter.cs b/Dalamud/Game/Text/Evaluator/SeStringParameter.cs
index 7201179ea..1c6dd96cb 100644
--- a/Dalamud/Game/Text/Evaluator/SeStringParameter.cs
+++ b/Dalamud/Game/Text/Evaluator/SeStringParameter.cs
@@ -77,4 +77,6 @@ public readonly struct SeStringParameter
public static implicit operator SeStringParameter(DSeString value) => new(new ReadOnlySeString(value.Encode()));
public static implicit operator SeStringParameter(string value) => new(value);
+
+ public static implicit operator SeStringParameter(ReadOnlySpan value) => new(value);
}
diff --git a/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs b/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs
index ee06172b4..8b020b111 100644
--- a/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs
+++ b/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs
@@ -16,7 +16,7 @@ public class DalamudLinkPayload : Payload
public override PayloadType Type => PayloadType.DalamudLink;
/// Gets the plugin command ID to be linked.
- public Guid CommandId { get; internal set; }
+ public uint CommandId { get; internal set; }
/// Gets an optional extra integer value 1.
public int Extra1 { get; internal set; }
@@ -40,7 +40,7 @@ public class DalamudLinkPayload : Payload
var ssb = Lumina.Text.SeStringBuilder.SharedPool.Get();
var res = ssb.BeginMacro(MacroCode.Link)
.AppendIntExpression((int)EmbeddedInfoType.DalamudLink - 1)
- .AppendStringExpression(this.CommandId.ToString())
+ .AppendUIntExpression(this.CommandId)
.AppendIntExpression(this.Extra1)
.AppendIntExpression(this.Extra2)
.BeginStringExpression()
@@ -72,15 +72,15 @@ public class DalamudLinkPayload : Payload
if (!pluginExpression.TryGetString(out var pluginString))
return;
- if (!commandIdExpression.TryGetString(out var commandId))
+ if (!commandIdExpression.TryGetUInt(out var commandId))
return;
this.Plugin = pluginString.ExtractText();
- this.CommandId = Guid.Parse(commandId.ExtractText());
+ this.CommandId = commandId;
}
else
{
- if (!commandIdExpression.TryGetString(out var commandId))
+ if (!commandIdExpression.TryGetUInt(out var commandId))
return;
if (!extra1Expression.TryGetInt(out var extra1))
@@ -102,7 +102,7 @@ public class DalamudLinkPayload : Payload
return;
}
- this.CommandId = Guid.Parse(commandId.ExtractText());
+ this.CommandId = commandId;
this.Extra1 = extra1;
this.Extra2 = extra2;
this.Plugin = extraData[0];
diff --git a/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiBuildUiDelegate.cs b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiBuildUiDelegate.cs
new file mode 100644
index 000000000..6ebab55c6
--- /dev/null
+++ b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiBuildUiDelegate.cs
@@ -0,0 +1,4 @@
+namespace Dalamud.Interface.ImGuiBackend.Delegates;
+
+/// Delegate to be called when ImGui should be used to layout now.
+public delegate void ImGuiBuildUiDelegate();
diff --git a/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewInputFrameDelegate.cs b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewInputFrameDelegate.cs
new file mode 100644
index 000000000..7397d8d7f
--- /dev/null
+++ b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewInputFrameDelegate.cs
@@ -0,0 +1,4 @@
+namespace Dalamud.Interface.ImGuiBackend.Delegates;
+
+/// Delegate to be called on new input frame.
+public delegate void ImGuiNewInputFrameDelegate();
diff --git a/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewRenderFrameDelegate.cs b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewRenderFrameDelegate.cs
new file mode 100644
index 000000000..4a4b38b71
--- /dev/null
+++ b/Dalamud/Interface/ImGuiBackend/Delegates/ImGuiNewRenderFrameDelegate.cs
@@ -0,0 +1,4 @@
+namespace Dalamud.Interface.ImGuiBackend.Delegates;
+
+/// Delegate to be called on new render frame.
+public delegate void ImGuiNewRenderFrameDelegate();
diff --git a/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs b/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs
index ebb8e67e2..ea609828d 100644
--- a/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs
+++ b/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs
@@ -8,6 +8,7 @@ using System.Runtime.InteropServices;
using Dalamud.Bindings.ImGui;
using Dalamud.Bindings.ImGuizmo;
using Dalamud.Bindings.ImPlot;
+using Dalamud.Interface.ImGuiBackend.Delegates;
using Dalamud.Interface.ImGuiBackend.Helpers;
using Dalamud.Interface.ImGuiBackend.InputHandler;
using Dalamud.Interface.ImGuiBackend.Renderers;
@@ -93,13 +94,13 @@ internal sealed unsafe class Dx11Win32Backend : IWin32Backend
~Dx11Win32Backend() => this.ReleaseUnmanagedResources();
///
- public event IImGuiBackend.BuildUiDelegate? BuildUi;
+ public event ImGuiBuildUiDelegate? BuildUi;
///
- public event IImGuiBackend.NewInputFrameDelegate? NewInputFrame;
+ public event ImGuiNewInputFrameDelegate? NewInputFrame;
///
- public event IImGuiBackend.NewRenderFrameDelegate? NewRenderFrame;
+ public event ImGuiNewRenderFrameDelegate? NewRenderFrame;
///
public bool UpdateCursor
diff --git a/Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs b/Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs
index 9248b4b5a..4a41191b5 100644
--- a/Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs
+++ b/Dalamud/Interface/ImGuiBackend/IImGuiBackend.cs
@@ -1,4 +1,5 @@
-using Dalamud.Interface.ImGuiBackend.InputHandler;
+using Dalamud.Interface.ImGuiBackend.Delegates;
+using Dalamud.Interface.ImGuiBackend.InputHandler;
using Dalamud.Interface.ImGuiBackend.Renderers;
namespace Dalamud.Interface.ImGuiBackend;
@@ -6,23 +7,14 @@ namespace Dalamud.Interface.ImGuiBackend;
/// Backend for ImGui.
internal interface IImGuiBackend : IDisposable
{
- /// Delegate to be called when ImGui should be used to layout now.
- public delegate void BuildUiDelegate();
-
- /// Delegate to be called on new input frame.
- public delegate void NewInputFrameDelegate();
-
- /// Delegaet to be called on new render frame.
- public delegate void NewRenderFrameDelegate();
-
/// User methods invoked every ImGui frame to construct custom UIs.
- event BuildUiDelegate? BuildUi;
+ event ImGuiBuildUiDelegate? BuildUi;
/// User methods invoked every ImGui frame on handling inputs.
- event NewInputFrameDelegate? NewInputFrame;
+ event ImGuiNewInputFrameDelegate? NewInputFrame;
/// User methods invoked every ImGui frame on handling renders.
- event NewRenderFrameDelegate? NewRenderFrame;
+ event ImGuiNewRenderFrameDelegate? NewRenderFrame;
/// Gets or sets a value indicating whether the cursor should be overridden with the ImGui cursor.
///
@@ -36,7 +28,7 @@ internal interface IImGuiBackend : IDisposable
/// Gets the input handler.
IImGuiInputHandler InputHandler { get; }
-
+
/// Gets the renderer.
IImGuiRenderer Renderer { get; }
@@ -45,7 +37,7 @@ internal interface IImGuiBackend : IDisposable
/// Handles stuff before resizing happens.
void OnPreResize();
-
+
/// Handles stuff after resizing happens.
/// The new width.
/// The new height.
diff --git a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs
index 1842028e2..596df4c67 100644
--- a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs
+++ b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs
@@ -1,19 +1,18 @@
-using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Dalamud.Bindings.ImGui;
+using Dalamud.Memory;
using Serilog;
using TerraFX.Interop.Windows;
-using static Dalamud.Interface.ImGuiBackend.Helpers.ImGuiViewportHelpers;
-
using static TerraFX.Interop.Windows.Windows;
using ERROR = TerraFX.Interop.Windows.ERROR;
@@ -245,6 +244,9 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
return default(LRESULT);
}
+ if (!ImGui.IsWindowHovered(ImGuiHoveredFlags.AnyWindow))
+ ImGui.ClearWindowFocus();
+
break;
}
@@ -371,6 +373,14 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
case WM.WM_DISPLAYCHANGE:
this.viewportHandler.UpdateMonitors();
break;
+
+ case WM.WM_KILLFOCUS when hWndCurrent == this.hWnd:
+ if (!ImGui.IsAnyMouseDown() && GetCapture() == hWndCurrent)
+ ReleaseCapture();
+
+ ImGui.GetIO().WantCaptureMouse = false;
+ ImGui.ClearWindowFocus();
+ break;
}
return null;
@@ -531,7 +541,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
// We still want to return MA_NOACTIVATE
// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mouseactivate
- return 0x3;
+ return MA.MA_NOACTIVATE;
case WM.WM_NCHITTEST:
// Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
@@ -539,8 +549,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
if (viewport.Flags.HasFlag(ImGuiViewportFlags.NoInputs))
{
- // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest
- return -1;
+ return HTTRANSPARENT;
}
break;
@@ -575,51 +584,50 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
private struct ViewportHandler : IDisposable
{
- [SuppressMessage("ReSharper", "CollectionNeverQueried.Local", Justification = "Keeping references alive")]
- private readonly List
public IFontSpec DefaultFontSpec => Service.Get().DefaultFontSpec;
+ ///
+ public float FontDefaultSizePt => Service.Get().DefaultFontSpec.SizePt;
+
+ ///
+ public float FontDefaultSizePx => Service.Get().DefaultFontSpec.SizePx;
+
+ ///
+ public ImFontPtr FontDefault => InterfaceManager.DefaultFont;
+
+ ///
+ public ImFontPtr FontIcon => InterfaceManager.IconFont;
+
+ ///
+ public ImFontPtr FontMono => InterfaceManager.MonoFont;
+
///
/// Gets the handle to the default Dalamud font - supporting all game languages and icons.
///
@@ -541,15 +584,6 @@ public sealed class UiBuilder : IDisposable, IUiBuilder
internal static bool DoStats { get; set; } = false;
#endif
- private void OnDefaultStyleChanged()
- => this.DefaultStyleChanged.InvokeSafely();
-
- private void OnDefaultGlobalScaleChanged()
- => this.DefaultGlobalScaleChanged.InvokeSafely();
-
- private void OnDefaultFontChanged()
- => this.DefaultFontChanged.InvokeSafely();
-
///
/// Gets a value indicating whether this UiBuilder has a configuration UI registered.
///
@@ -796,6 +830,15 @@ public sealed class UiBuilder : IDisposable, IUiBuilder
this.ResizeBuffers?.InvokeSafely();
}
+ private void OnDefaultStyleChanged()
+ => this.DefaultStyleChanged.InvokeSafely();
+
+ private void OnDefaultGlobalScaleChanged()
+ => this.DefaultGlobalScaleChanged.InvokeSafely();
+
+ private void OnDefaultFontChanged()
+ => this.DefaultFontChanged.InvokeSafely();
+
private class FontHandleWrapper : IFontHandle
{
private IFontHandle? wrapped;
diff --git a/Dalamud/Interface/Utility/ImGuiHelpers.cs b/Dalamud/Interface/Utility/ImGuiHelpers.cs
index 27cb3596c..87f258250 100644
--- a/Dalamud/Interface/Utility/ImGuiHelpers.cs
+++ b/Dalamud/Interface/Utility/ImGuiHelpers.cs
@@ -203,8 +203,8 @@ public static partial class ImGuiHelpers
ImGui.SetClipboardText(textCopy.IsNull ? text.Span : textCopy.Span);
}
- text.Dispose();
- textCopy.Dispose();
+ text.Recycle();
+ textCopy.Recycle();
}
/// Draws a SeString.
diff --git a/Dalamud/Plugin/ActivePluginsChangedEventArgs.cs b/Dalamud/Plugin/ActivePluginsChangedEventArgs.cs
index 0c857be79..7a3991dcd 100644
--- a/Dalamud/Plugin/ActivePluginsChangedEventArgs.cs
+++ b/Dalamud/Plugin/ActivePluginsChangedEventArgs.cs
@@ -2,10 +2,8 @@ using System.Collections.Generic;
namespace Dalamud.Plugin;
-///
-/// Contains data about changes to the list of active plugins.
-///
-public class ActivePluginsChangedEventArgs : EventArgs
+///
+public class ActivePluginsChangedEventArgs : EventArgs, IActivePluginsChangedEventArgs
{
///
/// Initializes a new instance of the class
@@ -19,13 +17,9 @@ public class ActivePluginsChangedEventArgs : EventArgs
this.AffectedInternalNames = affectedInternalNames;
}
- ///
- /// Gets the invalidation kind that caused this event to be fired.
- ///
+ ///
public PluginListInvalidationKind Kind { get; }
- ///
- /// Gets the InternalNames of affected plugins.
- ///
+ ///
public IEnumerable AffectedInternalNames { get; }
}
diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs
index 25c998a42..541071b63 100644
--- a/Dalamud/Plugin/DalamudPluginInterface.cs
+++ b/Dalamud/Plugin/DalamudPluginInterface.cs
@@ -489,7 +489,7 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa
/// Dispatch the active plugins changed event.
///
/// The event arguments containing information about the change.
- internal void NotifyActivePluginsChanged(ActivePluginsChangedEventArgs args)
+ internal void NotifyActivePluginsChanged(IActivePluginsChangedEventArgs args)
{
foreach (var action in Delegate.EnumerateInvocationList(this.ActivePluginsChanged))
{
diff --git a/Dalamud/Plugin/IActivePluginsChangedEventArgs.cs b/Dalamud/Plugin/IActivePluginsChangedEventArgs.cs
new file mode 100644
index 000000000..17c4347c7
--- /dev/null
+++ b/Dalamud/Plugin/IActivePluginsChangedEventArgs.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+
+namespace Dalamud.Plugin;
+
+///
+/// Contains data about changes to the list of active plugins.
+///
+public interface IActivePluginsChangedEventArgs
+{
+ ///
+ /// Gets the invalidation kind that caused this event to be fired.
+ ///
+ PluginListInvalidationKind Kind { get; }
+
+ ///
+ /// Gets the InternalNames of affected plugins.
+ ///
+ IEnumerable AffectedInternalNames { get; }
+}
diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs
index 1a1a47403..e98398a16 100644
--- a/Dalamud/Plugin/IDalamudPluginInterface.cs
+++ b/Dalamud/Plugin/IDalamudPluginInterface.cs
@@ -33,7 +33,7 @@ public interface IDalamudPluginInterface
/// Delegate for events that listen to changes to the list of active plugins.
///
/// The event arguments containing information about the change.
- public delegate void ActivePluginsChangedDelegate(ActivePluginsChangedEventArgs args);
+ public delegate void ActivePluginsChangedDelegate(IActivePluginsChangedEventArgs args);
///
/// Event that gets fired when loc is changed
diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs
index a4aa3919b..db803caa8 100644
--- a/Dalamud/Plugin/Internal/PluginManager.cs
+++ b/Dalamud/Plugin/Internal/PluginManager.cs
@@ -1240,7 +1240,7 @@ internal class PluginManager : IInternalDisposableService
}
return this.bannedPlugins.Any(ban => (ban.Name == manifest.InternalName || ban.Name == Hash.GetStringSha256Hash(manifest.InternalName))
- && ban.AssemblyVersion >= versionToCheck);
+ && (ban.AssemblyVersion == null || ban.AssemblyVersion >= versionToCheck));
}
///
diff --git a/Dalamud/Plugin/Internal/Types/BannedPlugin.cs b/Dalamud/Plugin/Internal/Types/BannedPlugin.cs
index a21bbf02b..384318a56 100644
--- a/Dalamud/Plugin/Internal/Types/BannedPlugin.cs
+++ b/Dalamud/Plugin/Internal/Types/BannedPlugin.cs
@@ -17,7 +17,7 @@ internal struct BannedPlugin
/// Gets plugin assembly version.
///
[JsonProperty]
- public Version AssemblyVersion { get; private set; }
+ public Version? AssemblyVersion { get; private set; }
///
/// Gets reason for the ban.
diff --git a/Dalamud/Plugin/Services/IChatGui.cs b/Dalamud/Plugin/Services/IChatGui.cs
index ab595dc3f..c474ca386 100644
--- a/Dalamud/Plugin/Services/IChatGui.cs
+++ b/Dalamud/Plugin/Services/IChatGui.cs
@@ -83,20 +83,21 @@ public interface IChatGui
///
/// Gets the dictionary of Dalamud Link Handlers.
///
- public IReadOnlyDictionary<(string PluginName, Guid CommandId), Action> RegisteredLinkHandlers { get; }
+ public IReadOnlyDictionary<(string PluginName, uint CommandId), Action> RegisteredLinkHandlers { get; }
///
/// Register a chat link handler.
///
+ /// The ID of the command.
/// The action to be executed.
/// Returns an SeString payload for the link.
- public DalamudLinkPayload AddChatLinkHandler(Action commandAction);
+ public DalamudLinkPayload AddChatLinkHandler(uint commandId, Action commandAction);
///
/// Remove a chat link handler.
///
/// The ID of the command.
- public void RemoveChatLinkHandler(Guid commandId);
+ public void RemoveChatLinkHandler(uint commandId);
///
/// Removes all chat link handlers registered by the plugin.
diff --git a/Dalamud/Plugin/Services/ISeStringEvaluator.cs b/Dalamud/Plugin/Services/ISeStringEvaluator.cs
index 65932652e..4efc29e3e 100644
--- a/Dalamud/Plugin/Services/ISeStringEvaluator.cs
+++ b/Dalamud/Plugin/Services/ISeStringEvaluator.cs
@@ -38,6 +38,15 @@ public interface ISeStringEvaluator
/// An evaluated .
ReadOnlySeString EvaluateMacroString(string macroString, Span localParameters = default, ClientLanguage? language = null);
+ ///
+ /// Evaluates macros in a macro string.
+ ///
+ /// The macro string.
+ /// An optional list of local parameters.
+ /// An optional language override.
+ /// An evaluated .
+ ReadOnlySeString EvaluateMacroString(ReadOnlySpan macroString, Span localParameters = default, ClientLanguage? language = null);
+
///
/// Evaluates macros in text from the Addon sheet.
///
diff --git a/Dalamud/Support/BugBait.cs b/Dalamud/Support/BugBait.cs
index 8dbf2e429..7ce96208c 100644
--- a/Dalamud/Support/BugBait.cs
+++ b/Dalamud/Support/BugBait.cs
@@ -36,6 +36,7 @@ internal static class BugBait
Reporter = reporter,
Name = plugin.InternalName,
Version = isTesting ? plugin.TestingAssemblyVersion?.ToString() : plugin.AssemblyVersion.ToString(),
+ Platform = Util.GetHostPlatform().ToString(),
DalamudHash = Util.GetScmVersion(),
};
@@ -66,6 +67,9 @@ internal static class BugBait
[JsonProperty("version")]
public string? Version { get; set; }
+ [JsonProperty("platform")]
+ public string? Platform { get; set; }
+
[JsonProperty("reporter")]
public string? Reporter { get; set; }
diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs
index a95f3ed66..a1c2eb6b2 100644
--- a/Dalamud/Utility/Util.cs
+++ b/Dalamud/Utility/Util.cs
@@ -9,6 +9,7 @@ using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using Dalamud.Bindings.ImGui;
@@ -27,6 +28,8 @@ using Windows.Win32.System.Memory;
using Windows.Win32.System.Ole;
using Windows.Win32.UI.WindowsAndMessaging;
+using Dalamud.Interface.Internal;
+
using FLASHWINFO = Windows.Win32.UI.WindowsAndMessaging.FLASHWINFO;
using HWND = Windows.Win32.Foundation.HWND;
using MEMORY_BASIC_INFORMATION = Windows.Win32.System.Memory.MEMORY_BASIC_INFORMATION;
@@ -522,17 +525,36 @@ public static partial class Util
public static bool IsWindows11() => Environment.OSVersion.Version.Build >= 22000;
///
- /// Open a link in the default browser.
+ /// Open a link in the default browser, and attempts to focus the newly launched application.
///
/// The link to open.
- public static void OpenLink(string url)
- {
- var process = new ProcessStartInfo(url)
+ public static void OpenLink(string url) => new Thread(
+ static url =>
{
- UseShellExecute = true,
- };
- Process.Start(process);
- }
+ try
+ {
+ var psi = new ProcessStartInfo((string)url!)
+ {
+ UseShellExecute = true,
+ ErrorDialogParentHandle = Service.GetNullable() is { } im
+ ? im.GameWindowHandle
+ : 0,
+ Verb = "open",
+ };
+ if (Process.Start(psi) is not { } process)
+ return;
+
+ if (process.Id != 0)
+ TerraFX.Interop.Windows.Windows.AllowSetForegroundWindow((uint)process.Id);
+ process.WaitForInputIdle();
+ TerraFX.Interop.Windows.Windows.SetForegroundWindow(
+ (TerraFX.Interop.Windows.HWND)process.MainWindowHandle);
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "{fn}: failed to open {url}", nameof(OpenLink), url);
+ }
+ }).Start(url);
///
/// Perform a "zipper merge" (A, 1, B, 2, C, 3) of multiple enumerables, allowing for lists to end early.
diff --git a/DalamudCrashHandler/DalamudCrashHandler.cpp b/DalamudCrashHandler/DalamudCrashHandler.cpp
index 62ccdd20a..ec7115ffd 100644
--- a/DalamudCrashHandler/DalamudCrashHandler.cpp
+++ b/DalamudCrashHandler/DalamudCrashHandler.cpp
@@ -463,12 +463,14 @@ void open_folder_and_select_items(HWND hwndOpener, const std::wstring& path) {
void export_tspack(HWND hWndParent, const std::filesystem::path& logDir, const std::string& crashLog, const std::string& troubleshootingPackData) {
static const char* SourceLogFiles[] = {
- "output.log",
+ "output.log", // XIVLauncher for Windows
+ "launcher.log", // XIVLauncher.Core for [mostly] Linux
"patcher.log",
"dalamud.log",
"dalamud.injector.log",
"dalamud.boot.log",
"aria.log",
+ "wine.log"
};
static constexpr auto MaxSizePerLog = 1 * 1024 * 1024;
static constexpr std::array OutputFileTypeFilterSpec{{
diff --git a/Directory.Build.props b/Directory.Build.props
index 224b610b6..b5330709f 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -10,7 +10,7 @@
- 6.3.0
+ 6.5.1
13.0.3
diff --git a/filter_imgui_bindings.ps1 b/filter_imgui_bindings.ps1
index e2ca0d7ba..55f02599d 100644
--- a/filter_imgui_bindings.ps1
+++ b/filter_imgui_bindings.ps1
@@ -21,7 +21,7 @@ $sourcePaths = (
# replace "ImGuiKey.GamepadStart"
$tmp = Get-Content -Path "$PSScriptRoot\imgui\Dalamud.Bindings.ImGui\Generated\Enums\ImGuiKeyPrivate.cs" -Raw
$tmp = $tmp.Replace("unchecked((int)GamepadStart)", "unchecked((int)ImGuiKey.GamepadStart)").Trim()
-$tmp | Set-Content -Path "$PSScriptRoot\imgui\Dalamud.Bindings.ImGui\Generated\Enums\ImGuiKeyPrivate.cs" -Encoding ascii
+$tmp.Trim() | Set-Content -Path "$PSScriptRoot\imgui\Dalamud.Bindings.ImGui\Generated\Enums\ImGuiKeyPrivate.cs" -Encoding ascii
try
{
@@ -141,7 +141,9 @@ foreach ($sourcePath in $sourcePaths)
$husks = $husks.Replace("public unsafe struct", "public unsafe partial struct")
$husks = $referNativeFunctionQualified.Replace($husks, '$1Native.$2')
$husks = "// `r`n`r`nusing $([string]::Join(";`r`nusing ", $imports) );`r`n`r`n$husks"
- $husks | Set-Content -Path "$targetPath.gen.cs" -Encoding ascii
+ $husks = $husks -ireplace 'nuint (ActiveIdUsingKeyInputMask)', 'ImBitArrayImGuiKeyNamedKeyCOUNTLessImGuiKeyNamedKeyBEGIN $1'
+ $husks = $husks.Replace('ref Unsafe.AsRef(&Handle->ActiveIdUsingKeyInputMask)', 'ref Unsafe.AsRef(&Handle->ActiveIdUsingKeyInputMask)')
+ $husks.Trim() | Set-Content -Path "$targetPath.gen.cs" -Encoding ascii
}
$husks = "// `r`n`r`nusing $([string]::Join(";`r`nusing ", $imports) );`r`n`r`nnamespace $namespace;`r`n`r`n"
@@ -286,6 +288,6 @@ foreach ($sourcePath in $sourcePaths)
$null = $sb.Append("// DISCARDED: $methodName`r`n")
}
- $sb.ToString() | Set-Content -Path "$targetPath/$className.gen.cs" -Encoding ascii
+ $sb.ToString().Trim() | Set-Content -Path "$targetPath/$className.gen.cs" -Encoding ascii
}
}
diff --git a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGui.gen.cs b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGui.gen.cs
index 3574ab21f..8db9fb7de 100644
--- a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGui.gen.cs
+++ b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGui.gen.cs
@@ -8896,4 +8896,3 @@ public unsafe partial class ImGui
// DISCARDED: internal static byte VSliderFloatNative(byte* label, Vector2 size, float* v, float vMin, float vMax, byte* format, ImGuiSliderFlags flags)
// DISCARDED: internal static byte VSliderIntNative(byte* label, Vector2 size, int* v, int vMin, int vMax, byte* format, ImGuiSliderFlags flags)
// DISCARDED: internal static byte VSliderScalarNative(byte* label, Vector2 size, ImGuiDataType dataType, void* pData, void* pMin, void* pMax, byte* format, ImGuiSliderFlags flags)
-
diff --git a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGuiNative.gen.cs b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGuiNative.gen.cs
index 22386e992..5e2fd7fa2 100644
--- a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGuiNative.gen.cs
+++ b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Functions/ImGuiNative.gen.cs
@@ -4828,4 +4828,3 @@ public unsafe partial class ImGuiNative
}
}
-
diff --git a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Structs.gen.cs b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Structs.gen.cs
index f853f5402..2fe66de88 100644
--- a/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Structs.gen.cs
+++ b/imgui/Dalamud.Bindings.ImGui/Custom/Generated/Generated/Structs.gen.cs
@@ -2250,7 +2250,7 @@ namespace Dalamud.Bindings.ImGui
public byte ActiveIdUsingMouseWheel;
public uint ActiveIdUsingNavDirMask;
public uint ActiveIdUsingNavInputMask;
- public nuint ActiveIdUsingKeyInputMask;
+ public ImBitArrayImGuiKeyNamedKeyCOUNTLessImGuiKeyNamedKeyBEGIN ActiveIdUsingKeyInputMask;
public ImGuiItemFlags CurrentItemFlags;
public ImGuiNextItemData NextItemData;
public ImGuiLastItemData LastItemData;
@@ -2546,7 +2546,7 @@ namespace Dalamud.Bindings.ImGui
public int WantCaptureKeyboardNextFrame;
public int WantTextInputNextFrame;
public ImVector TempBuffer;
- public unsafe ImGuiContext(bool initialized = default, bool fontAtlasOwnedByContext = default, ImGuiIO io = default, ImGuiPlatformIO platformIo = default, ImVector inputEventsQueue = default, ImVector inputEventsTrail = default, ImGuiStyle style = default, ImGuiConfigFlags configFlagsCurrFrame = default, ImGuiConfigFlags configFlagsLastFrame = default, ImFontPtr font = default, float fontSize = default, float fontBaseSize = default, ImDrawListSharedData drawListSharedData = default, double time = default, int frameCount = default, int frameCountEnded = default, int frameCountPlatformEnded = default, int frameCountRendered = default, bool withinFrameScope = default, bool withinFrameScopeWithImplicitWindow = default, bool withinEndChild = default, bool gcCompactAll = default, bool testEngineHookItems = default, void* testEngine = default, ImVector windows = default, ImVector windowsFocusOrder = default, ImVector windowsTempSortBuffer = default, ImVector currentWindowStack = default, ImGuiStorage windowsById = default, int windowsActiveCount = default, Vector2 windowsHoverPadding = default, ImGuiWindow* currentWindow = default, ImGuiWindow* hoveredWindow = default, ImGuiWindow* hoveredWindowUnderMovingWindow = default, ImGuiDockNode* hoveredDockNode = default, ImGuiWindow* movingWindow = default, ImGuiWindow* wheelingWindow = default, Vector2 wheelingWindowRefMousePos = default, float wheelingWindowTimer = default, uint debugHookIdInfo = default, uint hoveredId = default, uint hoveredIdPreviousFrame = default, bool hoveredIdAllowOverlap = default, bool hoveredIdUsingMouseWheel = default, bool hoveredIdPreviousFrameUsingMouseWheel = default, bool hoveredIdDisabled = default, float hoveredIdTimer = default, float hoveredIdNotActiveTimer = default, uint activeId = default, uint activeIdIsAlive = default, float activeIdTimer = default, bool activeIdIsJustActivated = default, bool activeIdAllowOverlap = default, bool activeIdNoClearOnFocusLoss = default, bool activeIdHasBeenPressedBefore = default, bool activeIdHasBeenEditedBefore = default, bool activeIdHasBeenEditedThisFrame = default, Vector2 activeIdClickOffset = default, ImGuiWindow* activeIdWindow = default, ImGuiInputSource activeIdSource = default, int activeIdMouseButton = default, uint activeIdPreviousFrame = default, bool activeIdPreviousFrameIsAlive = default, bool activeIdPreviousFrameHasBeenEditedBefore = default, ImGuiWindow* activeIdPreviousFrameWindow = default, uint lastActiveId = default, float lastActiveIdTimer = default, bool activeIdUsingMouseWheel = default, uint activeIdUsingNavDirMask = default, uint activeIdUsingNavInputMask = default, nuint activeIdUsingKeyInputMask = default, ImGuiItemFlags currentItemFlags = default, ImGuiNextItemData nextItemData = default, ImGuiLastItemData lastItemData = default, ImGuiNextWindowData nextWindowData = default, ImVector colorStack = default, ImVector styleVarStack = default, ImVector fontStack = default, ImVector focusScopeStack = default, ImVector itemFlagsStack = default, ImVector groupStack = default, ImVector openPopupStack = default, ImVector beginPopupStack = default, int beginMenuCount = default, ImVector viewports = default, float currentDpiScale = default, ImGuiViewportP* currentViewport = default, ImGuiViewportP* mouseViewport = default, ImGuiViewportP* mouseLastHoveredViewport = default, uint platformLastFocusedViewportId = default, ImGuiPlatformMonitor fallbackMonitor = default, int viewportFrontMostStampCount = default, ImGuiWindow* navWindow = default, uint navId = default, uint navFocusScopeId = default, uint navActivateId = default, uint navActivateDownId = default, uint navActivatePressedId = default, uint navActivateInputId = default, ImGuiActivateFlags navActivateFlags = default, uint navJustMovedToId = default, uint navJustMovedToFocusScopeId = default, ImGuiModFlags navJustMovedToKeyMods = default, uint navNextActivateId = default, ImGuiActivateFlags navNextActivateFlags = default, ImGuiInputSource navInputSource = default, ImGuiNavLayer navLayer = default, bool navIdIsAlive = default, bool navMousePosDirty = default, bool navDisableHighlight = default, bool navDisableMouseHover = default, bool navAnyRequest = default, bool navInitRequest = default, bool navInitRequestFromMove = default, uint navInitResultId = default, ImRect navInitResultRectRel = default, bool navMoveSubmitted = default, bool navMoveScoringItems = default, bool navMoveForwardToNextFrame = default, ImGuiNavMoveFlags navMoveFlags = default, ImGuiScrollFlags navMoveScrollFlags = default, ImGuiModFlags navMoveKeyMods = default, ImGuiDir navMoveDir = default, ImGuiDir navMoveDirForDebug = default, ImGuiDir navMoveClipDir = default, ImRect navScoringRect = default, ImRect navScoringNoClipRect = default, int navScoringDebugCount = default, int navTabbingDir = default, int navTabbingCounter = default, ImGuiNavItemData navMoveResultLocal = default, ImGuiNavItemData navMoveResultLocalVisible = default, ImGuiNavItemData navMoveResultOther = default, ImGuiNavItemData navTabbingResultFirst = default, ImGuiWindow* navWindowingTarget = default, ImGuiWindow* navWindowingTargetAnim = default, ImGuiWindow* navWindowingListWindow = default, float navWindowingTimer = default, float navWindowingHighlightAlpha = default, bool navWindowingToggleLayer = default, float dimBgRatio = default, ImGuiMouseCursor mouseCursor = default, bool dragDropActive = default, bool dragDropWithinSource = default, bool dragDropWithinTarget = default, ImGuiDragDropFlags dragDropSourceFlags = default, int dragDropSourceFrameCount = default, int dragDropMouseButton = default, ImGuiPayload dragDropPayload = default, ImRect dragDropTargetRect = default, uint dragDropTargetId = default, ImGuiDragDropFlags dragDropAcceptFlags = default, float dragDropAcceptIdCurrRectSurface = default, uint dragDropAcceptIdCurr = default, uint dragDropAcceptIdPrev = default, int dragDropAcceptFrameCount = default, uint dragDropHoldJustPressedId = default, ImVector dragDropPayloadBufHeap = default, byte* dragDropPayloadBufLocal = default, int clipperTempDataStacked = default, ImVector clipperTempData = default, ImGuiTable* currentTable = default, int tablesTempDataStacked = default, ImVector tablesTempData = default, ImPoolImGuiTable tables = default, ImVector tablesLastTimeActive = default, ImVector drawChannelsTempMergeBuffer = default, ImGuiTabBar* currentTabBar = default, ImPoolImGuiTabBar tabBars = default, ImVector currentTabBarStack = default, ImVector shrinkWidthBuffer = default, Vector2 mouseLastValidPos = default, ImGuiInputTextState inputTextState = default, ImFont inputTextPasswordFont = default, uint tempInputId = default, ImGuiColorEditFlags colorEditOptions = default, float colorEditLastHue = default, float colorEditLastSat = default, uint colorEditLastColor = default, Vector4 colorPickerRef = default, ImGuiComboPreviewData comboPreviewData = default, float sliderGrabClickOffset = default, float sliderCurrentAccum = default, bool sliderCurrentAccumDirty = default, bool dragCurrentAccumDirty = default, float dragCurrentAccum = default, float dragSpeedDefaultRatio = default, float scrollbarClickDeltaToGrabCenter = default, float disabledAlphaBackup = default, short disabledStackSize = default, short tooltipOverrideCount = default, float tooltipSlowDelay = default, ImVector clipboardHandlerData = default, ImVector menusIdSubmittedThisFrame = default, ImGuiPlatformImeData platformImeData = default, ImGuiPlatformImeData platformImeDataPrev = default, uint platformImeViewport = default, byte platformLocaleDecimalPoint = default, ImGuiDockContext dockContext = default, bool settingsLoaded = default, float settingsDirtyTimer = default, ImGuiTextBuffer settingsIniData = default, ImVector settingsHandlers = default, ImChunkStreamImGuiWindowSettings settingsWindows = default, ImChunkStreamImGuiTableSettings settingsTables = default, ImVector hooks = default, uint hookIdNext = default, bool logEnabled = default, ImGuiLogType logType = default, ImFileHandle logFile = default, ImGuiTextBuffer logBuffer = default, byte* logNextPrefix = default, byte* logNextSuffix = default, float logLinePosY = default, bool logLineFirstItem = default, int logDepthRef = default, int logDepthToExpand = default, int logDepthToExpandDefault = default, ImGuiDebugLogFlags debugLogFlags = default, ImGuiTextBuffer debugLogBuf = default, bool debugItemPickerActive = default, uint debugItemPickerBreakId = default, ImGuiMetricsConfig debugMetricsConfig = default, ImGuiStackTool debugStackTool = default, float* framerateSecPerFrame = default, int framerateSecPerFrameIdx = default, int framerateSecPerFrameCount = default, float framerateSecPerFrameAccum = default, int wantCaptureMouseNextFrame = default, int wantCaptureKeyboardNextFrame = default, int wantTextInputNextFrame = default, ImVector tempBuffer = default)
+ public unsafe ImGuiContext(bool initialized = default, bool fontAtlasOwnedByContext = default, ImGuiIO io = default, ImGuiPlatformIO platformIo = default, ImVector inputEventsQueue = default, ImVector inputEventsTrail = default, ImGuiStyle style = default, ImGuiConfigFlags configFlagsCurrFrame = default, ImGuiConfigFlags configFlagsLastFrame = default, ImFontPtr font = default, float fontSize = default, float fontBaseSize = default, ImDrawListSharedData drawListSharedData = default, double time = default, int frameCount = default, int frameCountEnded = default, int frameCountPlatformEnded = default, int frameCountRendered = default, bool withinFrameScope = default, bool withinFrameScopeWithImplicitWindow = default, bool withinEndChild = default, bool gcCompactAll = default, bool testEngineHookItems = default, void* testEngine = default, ImVector windows = default, ImVector windowsFocusOrder = default, ImVector windowsTempSortBuffer = default, ImVector currentWindowStack = default, ImGuiStorage windowsById = default, int windowsActiveCount = default, Vector2 windowsHoverPadding = default, ImGuiWindow* currentWindow = default, ImGuiWindow* hoveredWindow = default, ImGuiWindow* hoveredWindowUnderMovingWindow = default, ImGuiDockNode* hoveredDockNode = default, ImGuiWindow* movingWindow = default, ImGuiWindow* wheelingWindow = default, Vector2 wheelingWindowRefMousePos = default, float wheelingWindowTimer = default, uint debugHookIdInfo = default, uint hoveredId = default, uint hoveredIdPreviousFrame = default, bool hoveredIdAllowOverlap = default, bool hoveredIdUsingMouseWheel = default, bool hoveredIdPreviousFrameUsingMouseWheel = default, bool hoveredIdDisabled = default, float hoveredIdTimer = default, float hoveredIdNotActiveTimer = default, uint activeId = default, uint activeIdIsAlive = default, float activeIdTimer = default, bool activeIdIsJustActivated = default, bool activeIdAllowOverlap = default, bool activeIdNoClearOnFocusLoss = default, bool activeIdHasBeenPressedBefore = default, bool activeIdHasBeenEditedBefore = default, bool activeIdHasBeenEditedThisFrame = default, Vector2 activeIdClickOffset = default, ImGuiWindow* activeIdWindow = default, ImGuiInputSource activeIdSource = default, int activeIdMouseButton = default, uint activeIdPreviousFrame = default, bool activeIdPreviousFrameIsAlive = default, bool activeIdPreviousFrameHasBeenEditedBefore = default, ImGuiWindow* activeIdPreviousFrameWindow = default, uint lastActiveId = default, float lastActiveIdTimer = default, bool activeIdUsingMouseWheel = default, uint activeIdUsingNavDirMask = default, uint activeIdUsingNavInputMask = default, ImBitArrayImGuiKeyNamedKeyCOUNTLessImGuiKeyNamedKeyBEGIN activeIdUsingKeyInputMask = default, ImGuiItemFlags currentItemFlags = default, ImGuiNextItemData nextItemData = default, ImGuiLastItemData lastItemData = default, ImGuiNextWindowData nextWindowData = default, ImVector colorStack = default, ImVector styleVarStack = default, ImVector fontStack = default, ImVector focusScopeStack = default, ImVector itemFlagsStack = default, ImVector groupStack = default, ImVector openPopupStack = default, ImVector beginPopupStack = default, int beginMenuCount = default, ImVector viewports = default, float currentDpiScale = default, ImGuiViewportP* currentViewport = default, ImGuiViewportP* mouseViewport = default, ImGuiViewportP* mouseLastHoveredViewport = default, uint platformLastFocusedViewportId = default, ImGuiPlatformMonitor fallbackMonitor = default, int viewportFrontMostStampCount = default, ImGuiWindow* navWindow = default, uint navId = default, uint navFocusScopeId = default, uint navActivateId = default, uint navActivateDownId = default, uint navActivatePressedId = default, uint navActivateInputId = default, ImGuiActivateFlags navActivateFlags = default, uint navJustMovedToId = default, uint navJustMovedToFocusScopeId = default, ImGuiModFlags navJustMovedToKeyMods = default, uint navNextActivateId = default, ImGuiActivateFlags navNextActivateFlags = default, ImGuiInputSource navInputSource = default, ImGuiNavLayer navLayer = default, bool navIdIsAlive = default, bool navMousePosDirty = default, bool navDisableHighlight = default, bool navDisableMouseHover = default, bool navAnyRequest = default, bool navInitRequest = default, bool navInitRequestFromMove = default, uint navInitResultId = default, ImRect navInitResultRectRel = default, bool navMoveSubmitted = default, bool navMoveScoringItems = default, bool navMoveForwardToNextFrame = default, ImGuiNavMoveFlags navMoveFlags = default, ImGuiScrollFlags navMoveScrollFlags = default, ImGuiModFlags navMoveKeyMods = default, ImGuiDir navMoveDir = default, ImGuiDir navMoveDirForDebug = default, ImGuiDir navMoveClipDir = default, ImRect navScoringRect = default, ImRect navScoringNoClipRect = default, int navScoringDebugCount = default, int navTabbingDir = default, int navTabbingCounter = default, ImGuiNavItemData navMoveResultLocal = default, ImGuiNavItemData navMoveResultLocalVisible = default, ImGuiNavItemData navMoveResultOther = default, ImGuiNavItemData navTabbingResultFirst = default, ImGuiWindow* navWindowingTarget = default, ImGuiWindow* navWindowingTargetAnim = default, ImGuiWindow* navWindowingListWindow = default, float navWindowingTimer = default, float navWindowingHighlightAlpha = default, bool navWindowingToggleLayer = default, float dimBgRatio = default, ImGuiMouseCursor mouseCursor = default, bool dragDropActive = default, bool dragDropWithinSource = default, bool dragDropWithinTarget = default, ImGuiDragDropFlags dragDropSourceFlags = default, int dragDropSourceFrameCount = default, int dragDropMouseButton = default, ImGuiPayload dragDropPayload = default, ImRect dragDropTargetRect = default, uint dragDropTargetId = default, ImGuiDragDropFlags dragDropAcceptFlags = default, float dragDropAcceptIdCurrRectSurface = default, uint dragDropAcceptIdCurr = default, uint dragDropAcceptIdPrev = default, int dragDropAcceptFrameCount = default, uint dragDropHoldJustPressedId = default, ImVector dragDropPayloadBufHeap = default, byte* dragDropPayloadBufLocal = default, int clipperTempDataStacked = default, ImVector clipperTempData = default, ImGuiTable* currentTable = default, int tablesTempDataStacked = default, ImVector tablesTempData = default, ImPoolImGuiTable tables = default, ImVector tablesLastTimeActive = default, ImVector drawChannelsTempMergeBuffer = default, ImGuiTabBar* currentTabBar = default, ImPoolImGuiTabBar tabBars = default, ImVector currentTabBarStack = default, ImVector shrinkWidthBuffer = default, Vector2 mouseLastValidPos = default, ImGuiInputTextState inputTextState = default, ImFont inputTextPasswordFont = default, uint tempInputId = default, ImGuiColorEditFlags colorEditOptions = default, float colorEditLastHue = default, float colorEditLastSat = default, uint colorEditLastColor = default, Vector4 colorPickerRef = default, ImGuiComboPreviewData comboPreviewData = default, float sliderGrabClickOffset = default, float sliderCurrentAccum = default, bool sliderCurrentAccumDirty = default, bool dragCurrentAccumDirty = default, float dragCurrentAccum = default, float dragSpeedDefaultRatio = default, float scrollbarClickDeltaToGrabCenter = default, float disabledAlphaBackup = default, short disabledStackSize = default, short tooltipOverrideCount = default, float tooltipSlowDelay = default, ImVector clipboardHandlerData = default, ImVector menusIdSubmittedThisFrame = default, ImGuiPlatformImeData platformImeData = default, ImGuiPlatformImeData platformImeDataPrev = default, uint platformImeViewport = default, byte platformLocaleDecimalPoint = default, ImGuiDockContext dockContext = default, bool settingsLoaded = default, float settingsDirtyTimer = default, ImGuiTextBuffer settingsIniData = default, ImVector settingsHandlers = default, ImChunkStreamImGuiWindowSettings settingsWindows = default, ImChunkStreamImGuiTableSettings settingsTables = default, ImVector hooks = default, uint hookIdNext = default, bool logEnabled = default, ImGuiLogType logType = default, ImFileHandle logFile = default, ImGuiTextBuffer logBuffer = default, byte* logNextPrefix = default, byte* logNextSuffix = default, float logLinePosY = default, bool logLineFirstItem = default, int logDepthRef = default, int logDepthToExpand = default, int logDepthToExpandDefault = default, ImGuiDebugLogFlags debugLogFlags = default, ImGuiTextBuffer debugLogBuf = default, bool debugItemPickerActive = default, uint debugItemPickerBreakId = default, ImGuiMetricsConfig debugMetricsConfig = default, ImGuiStackTool debugStackTool = default, float* framerateSecPerFrame = default, int framerateSecPerFrameIdx = default, int framerateSecPerFrameCount = default, float framerateSecPerFrameAccum = default, int wantCaptureMouseNextFrame = default, int wantCaptureKeyboardNextFrame = default, int wantTextInputNextFrame = default, ImVector tempBuffer = default)
{
Initialized = initialized ? (byte)1 : (byte)0;
FontAtlasOwnedByContext = fontAtlasOwnedByContext ? (byte)1 : (byte)0;
@@ -2921,7 +2921,7 @@ namespace Dalamud.Bindings.ImGui
WantTextInputNextFrame = wantTextInputNextFrame;
TempBuffer = tempBuffer;
}
- public unsafe ImGuiContext(bool initialized = default, bool fontAtlasOwnedByContext = default, ImGuiIO io = default, ImGuiPlatformIO platformIo = default, ImVector inputEventsQueue = default, ImVector inputEventsTrail = default, ImGuiStyle style = default, ImGuiConfigFlags configFlagsCurrFrame = default, ImGuiConfigFlags configFlagsLastFrame = default, ImFontPtr font = default, float fontSize = default, float fontBaseSize = default, ImDrawListSharedData drawListSharedData = default, double time = default, int frameCount = default, int frameCountEnded = default, int frameCountPlatformEnded = default, int frameCountRendered = default, bool withinFrameScope = default, bool withinFrameScopeWithImplicitWindow = default, bool withinEndChild = default, bool gcCompactAll = default, bool testEngineHookItems = default, void* testEngine = default, ImVector windows = default, ImVector windowsFocusOrder = default, ImVector windowsTempSortBuffer = default, ImVector currentWindowStack = default, ImGuiStorage windowsById = default, int windowsActiveCount = default, Vector2 windowsHoverPadding = default, ImGuiWindow* currentWindow = default, ImGuiWindow* hoveredWindow = default, ImGuiWindow* hoveredWindowUnderMovingWindow = default, ImGuiDockNode* hoveredDockNode = default, ImGuiWindow* movingWindow = default, ImGuiWindow* wheelingWindow = default, Vector2 wheelingWindowRefMousePos = default, float wheelingWindowTimer = default, uint debugHookIdInfo = default, uint hoveredId = default, uint hoveredIdPreviousFrame = default, bool hoveredIdAllowOverlap = default, bool hoveredIdUsingMouseWheel = default, bool hoveredIdPreviousFrameUsingMouseWheel = default, bool hoveredIdDisabled = default, float hoveredIdTimer = default, float hoveredIdNotActiveTimer = default, uint activeId = default, uint activeIdIsAlive = default, float activeIdTimer = default, bool activeIdIsJustActivated = default, bool activeIdAllowOverlap = default, bool activeIdNoClearOnFocusLoss = default, bool activeIdHasBeenPressedBefore = default, bool activeIdHasBeenEditedBefore = default, bool activeIdHasBeenEditedThisFrame = default, Vector2 activeIdClickOffset = default, ImGuiWindow* activeIdWindow = default, ImGuiInputSource activeIdSource = default, int activeIdMouseButton = default, uint activeIdPreviousFrame = default, bool activeIdPreviousFrameIsAlive = default, bool activeIdPreviousFrameHasBeenEditedBefore = default, ImGuiWindow* activeIdPreviousFrameWindow = default, uint lastActiveId = default, float lastActiveIdTimer = default, bool activeIdUsingMouseWheel = default, uint activeIdUsingNavDirMask = default, uint activeIdUsingNavInputMask = default, nuint activeIdUsingKeyInputMask = default, ImGuiItemFlags currentItemFlags = default, ImGuiNextItemData nextItemData = default, ImGuiLastItemData lastItemData = default, ImGuiNextWindowData nextWindowData = default, ImVector colorStack = default, ImVector styleVarStack = default, ImVector fontStack = default, ImVector focusScopeStack = default, ImVector itemFlagsStack = default, ImVector groupStack = default, ImVector openPopupStack = default, ImVector beginPopupStack = default, int beginMenuCount = default, ImVector viewports = default, float currentDpiScale = default, ImGuiViewportP* currentViewport = default, ImGuiViewportP* mouseViewport = default, ImGuiViewportP* mouseLastHoveredViewport = default, uint platformLastFocusedViewportId = default, ImGuiPlatformMonitor fallbackMonitor = default, int viewportFrontMostStampCount = default, ImGuiWindow* navWindow = default, uint navId = default, uint navFocusScopeId = default, uint navActivateId = default, uint navActivateDownId = default, uint navActivatePressedId = default, uint navActivateInputId = default, ImGuiActivateFlags navActivateFlags = default, uint navJustMovedToId = default, uint navJustMovedToFocusScopeId = default, ImGuiModFlags navJustMovedToKeyMods = default, uint navNextActivateId = default, ImGuiActivateFlags navNextActivateFlags = default, ImGuiInputSource navInputSource = default, ImGuiNavLayer navLayer = default, bool navIdIsAlive = default, bool navMousePosDirty = default, bool navDisableHighlight = default, bool navDisableMouseHover = default, bool navAnyRequest = default, bool navInitRequest = default, bool navInitRequestFromMove = default, uint navInitResultId = default, ImRect navInitResultRectRel = default, bool navMoveSubmitted = default, bool navMoveScoringItems = default, bool navMoveForwardToNextFrame = default, ImGuiNavMoveFlags navMoveFlags = default, ImGuiScrollFlags navMoveScrollFlags = default, ImGuiModFlags navMoveKeyMods = default, ImGuiDir navMoveDir = default, ImGuiDir navMoveDirForDebug = default, ImGuiDir navMoveClipDir = default, ImRect navScoringRect = default, ImRect navScoringNoClipRect = default, int navScoringDebugCount = default, int navTabbingDir = default, int navTabbingCounter = default, ImGuiNavItemData navMoveResultLocal = default, ImGuiNavItemData navMoveResultLocalVisible = default, ImGuiNavItemData navMoveResultOther = default, ImGuiNavItemData navTabbingResultFirst = default, ImGuiWindow* navWindowingTarget = default, ImGuiWindow* navWindowingTargetAnim = default, ImGuiWindow* navWindowingListWindow = default, float navWindowingTimer = default, float navWindowingHighlightAlpha = default, bool navWindowingToggleLayer = default, float dimBgRatio = default, ImGuiMouseCursor mouseCursor = default, bool dragDropActive = default, bool dragDropWithinSource = default, bool dragDropWithinTarget = default, ImGuiDragDropFlags dragDropSourceFlags = default, int dragDropSourceFrameCount = default, int dragDropMouseButton = default, ImGuiPayload dragDropPayload = default, ImRect dragDropTargetRect = default, uint dragDropTargetId = default, ImGuiDragDropFlags dragDropAcceptFlags = default, float dragDropAcceptIdCurrRectSurface = default, uint dragDropAcceptIdCurr = default, uint dragDropAcceptIdPrev = default, int dragDropAcceptFrameCount = default, uint dragDropHoldJustPressedId = default, ImVector dragDropPayloadBufHeap = default, Span dragDropPayloadBufLocal = default, int clipperTempDataStacked = default, ImVector clipperTempData = default, ImGuiTable* currentTable = default, int tablesTempDataStacked = default, ImVector tablesTempData = default, ImPoolImGuiTable tables = default, ImVector tablesLastTimeActive = default, ImVector drawChannelsTempMergeBuffer = default, ImGuiTabBar* currentTabBar = default, ImPoolImGuiTabBar tabBars = default, ImVector currentTabBarStack = default, ImVector shrinkWidthBuffer = default, Vector2 mouseLastValidPos = default, ImGuiInputTextState inputTextState = default, ImFont inputTextPasswordFont = default, uint tempInputId = default, ImGuiColorEditFlags colorEditOptions = default, float colorEditLastHue = default, float colorEditLastSat = default, uint colorEditLastColor = default, Vector4 colorPickerRef = default, ImGuiComboPreviewData comboPreviewData = default, float sliderGrabClickOffset = default, float sliderCurrentAccum = default, bool sliderCurrentAccumDirty = default, bool dragCurrentAccumDirty = default, float dragCurrentAccum = default, float dragSpeedDefaultRatio = default, float scrollbarClickDeltaToGrabCenter = default, float disabledAlphaBackup = default, short disabledStackSize = default, short tooltipOverrideCount = default, float tooltipSlowDelay = default, ImVector clipboardHandlerData = default, ImVector menusIdSubmittedThisFrame = default, ImGuiPlatformImeData platformImeData = default, ImGuiPlatformImeData platformImeDataPrev = default, uint platformImeViewport = default, byte platformLocaleDecimalPoint = default, ImGuiDockContext dockContext = default, bool settingsLoaded = default, float settingsDirtyTimer = default, ImGuiTextBuffer settingsIniData = default, ImVector settingsHandlers = default, ImChunkStreamImGuiWindowSettings settingsWindows = default, ImChunkStreamImGuiTableSettings settingsTables = default, ImVector hooks = default, uint hookIdNext = default, bool logEnabled = default, ImGuiLogType logType = default, ImFileHandle logFile = default, ImGuiTextBuffer logBuffer = default, byte* logNextPrefix = default, byte* logNextSuffix = default, float logLinePosY = default, bool logLineFirstItem = default, int logDepthRef = default, int logDepthToExpand = default, int logDepthToExpandDefault = default, ImGuiDebugLogFlags debugLogFlags = default, ImGuiTextBuffer debugLogBuf = default, bool debugItemPickerActive = default, uint debugItemPickerBreakId = default, ImGuiMetricsConfig debugMetricsConfig = default, ImGuiStackTool debugStackTool = default, Span framerateSecPerFrame = default, int framerateSecPerFrameIdx = default, int framerateSecPerFrameCount = default, float framerateSecPerFrameAccum = default, int wantCaptureMouseNextFrame = default, int wantCaptureKeyboardNextFrame = default, int wantTextInputNextFrame = default, ImVector tempBuffer = default)
+ public unsafe ImGuiContext(bool initialized = default, bool fontAtlasOwnedByContext = default, ImGuiIO io = default, ImGuiPlatformIO platformIo = default, ImVector inputEventsQueue = default, ImVector inputEventsTrail = default, ImGuiStyle style = default, ImGuiConfigFlags configFlagsCurrFrame = default, ImGuiConfigFlags configFlagsLastFrame = default, ImFontPtr font = default, float fontSize = default, float fontBaseSize = default, ImDrawListSharedData drawListSharedData = default, double time = default, int frameCount = default, int frameCountEnded = default, int frameCountPlatformEnded = default, int frameCountRendered = default, bool withinFrameScope = default, bool withinFrameScopeWithImplicitWindow = default, bool withinEndChild = default, bool gcCompactAll = default, bool testEngineHookItems = default, void* testEngine = default, ImVector windows = default, ImVector windowsFocusOrder = default, ImVector windowsTempSortBuffer = default, ImVector currentWindowStack = default, ImGuiStorage windowsById = default, int windowsActiveCount = default, Vector2 windowsHoverPadding = default, ImGuiWindow* currentWindow = default, ImGuiWindow* hoveredWindow = default, ImGuiWindow* hoveredWindowUnderMovingWindow = default, ImGuiDockNode* hoveredDockNode = default, ImGuiWindow* movingWindow = default, ImGuiWindow* wheelingWindow = default, Vector2 wheelingWindowRefMousePos = default, float wheelingWindowTimer = default, uint debugHookIdInfo = default, uint hoveredId = default, uint hoveredIdPreviousFrame = default, bool hoveredIdAllowOverlap = default, bool hoveredIdUsingMouseWheel = default, bool hoveredIdPreviousFrameUsingMouseWheel = default, bool hoveredIdDisabled = default, float hoveredIdTimer = default, float hoveredIdNotActiveTimer = default, uint activeId = default, uint activeIdIsAlive = default, float activeIdTimer = default, bool activeIdIsJustActivated = default, bool activeIdAllowOverlap = default, bool activeIdNoClearOnFocusLoss = default, bool activeIdHasBeenPressedBefore = default, bool activeIdHasBeenEditedBefore = default, bool activeIdHasBeenEditedThisFrame = default, Vector2 activeIdClickOffset = default, ImGuiWindow* activeIdWindow = default, ImGuiInputSource activeIdSource = default, int activeIdMouseButton = default, uint activeIdPreviousFrame = default, bool activeIdPreviousFrameIsAlive = default, bool activeIdPreviousFrameHasBeenEditedBefore = default, ImGuiWindow* activeIdPreviousFrameWindow = default, uint lastActiveId = default, float lastActiveIdTimer = default, bool activeIdUsingMouseWheel = default, uint activeIdUsingNavDirMask = default, uint activeIdUsingNavInputMask = default, ImBitArrayImGuiKeyNamedKeyCOUNTLessImGuiKeyNamedKeyBEGIN activeIdUsingKeyInputMask = default, ImGuiItemFlags currentItemFlags = default, ImGuiNextItemData nextItemData = default, ImGuiLastItemData lastItemData = default, ImGuiNextWindowData nextWindowData = default, ImVector colorStack = default, ImVector styleVarStack = default, ImVector fontStack = default, ImVector focusScopeStack = default, ImVector itemFlagsStack = default, ImVector groupStack = default, ImVector openPopupStack = default, ImVector beginPopupStack = default, int beginMenuCount = default, ImVector viewports = default, float currentDpiScale = default, ImGuiViewportP* currentViewport = default, ImGuiViewportP* mouseViewport = default, ImGuiViewportP* mouseLastHoveredViewport = default, uint platformLastFocusedViewportId = default, ImGuiPlatformMonitor fallbackMonitor = default, int viewportFrontMostStampCount = default, ImGuiWindow* navWindow = default, uint navId = default, uint navFocusScopeId = default, uint navActivateId = default, uint navActivateDownId = default, uint navActivatePressedId = default, uint navActivateInputId = default, ImGuiActivateFlags navActivateFlags = default, uint navJustMovedToId = default, uint navJustMovedToFocusScopeId = default, ImGuiModFlags navJustMovedToKeyMods = default, uint navNextActivateId = default, ImGuiActivateFlags navNextActivateFlags = default, ImGuiInputSource navInputSource = default, ImGuiNavLayer navLayer = default, bool navIdIsAlive = default, bool navMousePosDirty = default, bool navDisableHighlight = default, bool navDisableMouseHover = default, bool navAnyRequest = default, bool navInitRequest = default, bool navInitRequestFromMove = default, uint navInitResultId = default, ImRect navInitResultRectRel = default, bool navMoveSubmitted = default, bool navMoveScoringItems = default, bool navMoveForwardToNextFrame = default, ImGuiNavMoveFlags navMoveFlags = default, ImGuiScrollFlags navMoveScrollFlags = default, ImGuiModFlags navMoveKeyMods = default, ImGuiDir navMoveDir = default, ImGuiDir navMoveDirForDebug = default, ImGuiDir navMoveClipDir = default, ImRect navScoringRect = default, ImRect navScoringNoClipRect = default, int navScoringDebugCount = default, int navTabbingDir = default, int navTabbingCounter = default, ImGuiNavItemData navMoveResultLocal = default, ImGuiNavItemData navMoveResultLocalVisible = default, ImGuiNavItemData navMoveResultOther = default, ImGuiNavItemData navTabbingResultFirst = default, ImGuiWindow* navWindowingTarget = default, ImGuiWindow* navWindowingTargetAnim = default, ImGuiWindow* navWindowingListWindow = default, float navWindowingTimer = default, float navWindowingHighlightAlpha = default, bool navWindowingToggleLayer = default, float dimBgRatio = default, ImGuiMouseCursor mouseCursor = default, bool dragDropActive = default, bool dragDropWithinSource = default, bool dragDropWithinTarget = default, ImGuiDragDropFlags dragDropSourceFlags = default, int dragDropSourceFrameCount = default, int dragDropMouseButton = default, ImGuiPayload dragDropPayload = default, ImRect dragDropTargetRect = default, uint dragDropTargetId = default, ImGuiDragDropFlags dragDropAcceptFlags = default, float dragDropAcceptIdCurrRectSurface = default, uint dragDropAcceptIdCurr = default, uint dragDropAcceptIdPrev = default, int dragDropAcceptFrameCount = default, uint dragDropHoldJustPressedId = default, ImVector dragDropPayloadBufHeap = default, Span dragDropPayloadBufLocal = default, int clipperTempDataStacked = default, ImVector clipperTempData = default, ImGuiTable* currentTable = default, int tablesTempDataStacked = default, ImVector tablesTempData = default, ImPoolImGuiTable tables = default, ImVector