aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-28 20:11:14 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-28 20:11:14 -0500
commitfbfdd7b1171e692a663bf221075abfe0e0ef0ab9 (patch)
tree941e0d6e576cc53542b4bb8d1165887351972a79 /libs
parent817524ce9e1146cfad05b7a2e7d41495bcde537b (diff)
Native port of SKSELogRedirector plugin family (sysdmp), default off
Three FileMapper variants — Steam SSE, GOG, VR — that redirect <docs>/My Games/<X> onto a sibling folder so SKSE writes logs to the right place. Only one applies per game; all default off so the user opts in to the matching variant. Layout mirrors game_bethesda: shared static lib in src/common/ with the QObject base (init/author/version/settings/enabledByDefault/mappings), three plugin .so subdirs each adding Q_PLUGIN_METADATA + their own name/description and destFolderName override. Q_PLUGIN_METADATA can only appear once per .so, hence the split. Paths preserved verbatim from the upstream .py — including the SSE variant's "Skyrim.INI" sibling folder, which is intentional: a Skyrim bug sometimes creates a directory of that name and the redirect makes SKSE find logs in SSE's docs folder. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'libs')
-rw-r--r--libs/skse_log_redirector/CMakeLists.txt5
-rw-r--r--libs/skse_log_redirector/src/CMakeLists.txt6
-rw-r--r--libs/skse_log_redirector/src/common/CMakeLists.txt26
-rw-r--r--libs/skse_log_redirector/src/common/skseLogRedirectorBase.cpp62
-rw-r--r--libs/skse_log_redirector/src/common/skseLogRedirectorBase.h48
-rw-r--r--libs/skse_log_redirector/src/gog/CMakeLists.txt13
-rw-r--r--libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.cpp22
-rw-r--r--libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.h17
-rw-r--r--libs/skse_log_redirector/src/sse/CMakeLists.txt13
-rw-r--r--libs/skse_log_redirector/src/sse/skseLogRedirector.cpp24
-rw-r--r--libs/skse_log_redirector/src/sse/skseLogRedirector.h17
-rw-r--r--libs/skse_log_redirector/src/vr/CMakeLists.txt13
-rw-r--r--libs/skse_log_redirector/src/vr/skseLogRedirectorVR.cpp22
-rw-r--r--libs/skse_log_redirector/src/vr/skseLogRedirectorVR.h17
-rw-r--r--libs/skse_log_redirector/vcpkg.json15
15 files changed, 320 insertions, 0 deletions
diff --git a/libs/skse_log_redirector/CMakeLists.txt b/libs/skse_log_redirector/CMakeLists.txt
new file mode 100644
index 0000000..3e10a97
--- /dev/null
+++ b/libs/skse_log_redirector/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(skse_log_redirector)
+
+add_subdirectory(src)
diff --git a/libs/skse_log_redirector/src/CMakeLists.txt b/libs/skse_log_redirector/src/CMakeLists.txt
new file mode 100644
index 0000000..5ab9468
--- /dev/null
+++ b/libs/skse_log_redirector/src/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.16)
+
+add_subdirectory(common)
+add_subdirectory(sse)
+add_subdirectory(gog)
+add_subdirectory(vr)
diff --git a/libs/skse_log_redirector/src/common/CMakeLists.txt b/libs/skse_log_redirector/src/common/CMakeLists.txt
new file mode 100644
index 0000000..7aefbda
--- /dev/null
+++ b/libs/skse_log_redirector/src/common/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.16)
+
+add_library(skse_log_redirector_common STATIC
+ skseLogRedirectorBase.cpp
+ skseLogRedirectorBase.h
+)
+
+set_target_properties(skse_log_redirector_common PROPERTIES
+ AUTOMOC ON
+ CXX_STANDARD 23
+ CXX_STANDARD_REQUIRED ON
+ POSITION_INDEPENDENT_CODE ON
+)
+
+target_include_directories(skse_log_redirector_common
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_compile_options(skse_log_redirector_common PRIVATE
+ "-idirafter" "${CMAKE_SOURCE_DIR}/libs/uibase/include/uibase"
+)
+set_property(TARGET skse_log_redirector_common APPEND PROPERTY AUTOMOC_MOC_OPTIONS
+ "-I${CMAKE_SOURCE_DIR}/libs/uibase/include/uibase"
+)
+
+target_link_libraries(skse_log_redirector_common PUBLIC mo2::uibase)
diff --git a/libs/skse_log_redirector/src/common/skseLogRedirectorBase.cpp b/libs/skse_log_redirector/src/common/skseLogRedirectorBase.cpp
new file mode 100644
index 0000000..8b35201
--- /dev/null
+++ b/libs/skse_log_redirector/src/common/skseLogRedirectorBase.cpp
@@ -0,0 +1,62 @@
+#include "skseLogRedirectorBase.h"
+
+#include <uibase/imoinfo.h>
+#include <uibase/iplugingame.h>
+#include <uibase/pluginsetting.h>
+#include <uibase/versioninfo.h>
+
+#include <QDir>
+
+using namespace MOBase;
+
+bool SkseLogRedirectorBase::init(IOrganizer* moInfo)
+{
+ m_organizer = moInfo;
+ return true;
+}
+
+QString SkseLogRedirectorBase::author() const
+{
+ return "sysdmp";
+}
+
+VersionInfo SkseLogRedirectorBase::version() const
+{
+ return VersionInfo(0, 0, 1);
+}
+
+QList<PluginSetting> SkseLogRedirectorBase::settings() const
+{
+ return {};
+}
+
+bool SkseLogRedirectorBase::enabledByDefault() const
+{
+ return false;
+}
+
+MappingType SkseLogRedirectorBase::mappings() const
+{
+ MappingType result;
+ if (m_organizer == nullptr) {
+ return result;
+ }
+ const IPluginGame* game = m_organizer->managedGame();
+ if (game == nullptr) {
+ return result;
+ }
+
+ const QString docsPath = game->documentsDirectory().absolutePath();
+ // Sibling folder under "My Games" — e.g. <docs>/../Skyrim. QDir::cleanPath
+ // collapses the "..", matching pathlib.Path.resolve() in the upstream .py.
+ const QString siblingPath =
+ QDir::cleanPath(docsPath + QStringLiteral("/../") + destFolderName());
+
+ Mapping m;
+ m.source = docsPath;
+ m.destination = siblingPath;
+ m.isDirectory = true;
+ m.createTarget = true;
+ result.push_back(std::move(m));
+ return result;
+}
diff --git a/libs/skse_log_redirector/src/common/skseLogRedirectorBase.h b/libs/skse_log_redirector/src/common/skseLogRedirectorBase.h
new file mode 100644
index 0000000..ec2399e
--- /dev/null
+++ b/libs/skse_log_redirector/src/common/skseLogRedirectorBase.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <uibase/filemapping.h>
+#include <uibase/iplugin.h>
+#include <uibase/ipluginfilemapper.h>
+
+#include <QList>
+#include <QObject>
+#include <QString>
+
+namespace MOBase
+{
+struct PluginSetting;
+class IOrganizer;
+} // namespace MOBase
+
+// Shared base for the SKSELogRedirector plugin family (sysdmp). Each variant
+// (Steam SSE, GOG, VR) only differs in the destination folder name under
+// "My Games" — everything else is identical, so the variants subclass this
+// base and override destFolderName().
+//
+// All variants are off by default: only one is applicable per game and the
+// user opts into the matching one.
+class SkseLogRedirectorBase : public QObject,
+ public MOBase::IPlugin,
+ public MOBase::IPluginFileMapper
+{
+ Q_OBJECT
+ Q_INTERFACES(MOBase::IPlugin MOBase::IPluginFileMapper)
+
+public:
+ // IPlugin
+ bool init(MOBase::IOrganizer* moInfo) override;
+ QString author() const override;
+ MOBase::VersionInfo version() const override;
+ QList<MOBase::PluginSetting> settings() const override;
+ bool enabledByDefault() const override;
+
+ // IPluginFileMapper
+ MappingType mappings() const override;
+
+protected:
+ // Sibling folder name under "My Games" — e.g. "Skyrim", "Skyrim VR",
+ // "Skyrim Special Edition", "Skyrim.INI".
+ virtual QString destFolderName() const = 0;
+
+ MOBase::IOrganizer* m_organizer = nullptr;
+};
diff --git a/libs/skse_log_redirector/src/gog/CMakeLists.txt b/libs/skse_log_redirector/src/gog/CMakeLists.txt
new file mode 100644
index 0000000..ef78d3e
--- /dev/null
+++ b/libs/skse_log_redirector/src/gog/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.16)
+
+add_library(skse_log_redirector_gog SHARED
+ skseLogRedirectorGOG.cpp
+ skseLogRedirectorGOG.h
+)
+mo2_configure_plugin(skse_log_redirector_gog NO_SOURCES WARNINGS OFF)
+target_link_libraries(skse_log_redirector_gog PRIVATE
+ mo2::uibase
+ skse_log_redirector_common
+)
+
+mo2_install_plugin(skse_log_redirector_gog)
diff --git a/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.cpp b/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.cpp
new file mode 100644
index 0000000..c1da77b
--- /dev/null
+++ b/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.cpp
@@ -0,0 +1,22 @@
+#include "skseLogRedirectorGOG.h"
+
+QString SkseLogRedirectorGOG::name() const
+{
+ return "SKSE Log Redirector GOG";
+}
+
+QString SkseLogRedirectorGOG::localizedName() const
+{
+ return tr("SKSE Log Redirector GOG");
+}
+
+QString SkseLogRedirectorGOG::description() const
+{
+ return tr("Redirects \"\\Documents\\My Games\\Skyrim Special Edition\" to "
+ "\"\\Documents\\My Games\\Skyrim Special Edition GOG\" via VFS.");
+}
+
+QString SkseLogRedirectorGOG::destFolderName() const
+{
+ return QStringLiteral("Skyrim Special Edition");
+}
diff --git a/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.h b/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.h
new file mode 100644
index 0000000..683bf31
--- /dev/null
+++ b/libs/skse_log_redirector/src/gog/skseLogRedirectorGOG.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "skseLogRedirectorBase.h"
+
+class SkseLogRedirectorGOG : public SkseLogRedirectorBase
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.sysdmp.SKSELogRedirectorGOG")
+
+public:
+ QString name() const override;
+ QString localizedName() const override;
+ QString description() const override;
+
+protected:
+ QString destFolderName() const override;
+};
diff --git a/libs/skse_log_redirector/src/sse/CMakeLists.txt b/libs/skse_log_redirector/src/sse/CMakeLists.txt
new file mode 100644
index 0000000..36a06ec
--- /dev/null
+++ b/libs/skse_log_redirector/src/sse/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.16)
+
+add_library(skse_log_redirector SHARED
+ skseLogRedirector.cpp
+ skseLogRedirector.h
+)
+mo2_configure_plugin(skse_log_redirector NO_SOURCES WARNINGS OFF)
+target_link_libraries(skse_log_redirector PRIVATE
+ mo2::uibase
+ skse_log_redirector_common
+)
+
+mo2_install_plugin(skse_log_redirector)
diff --git a/libs/skse_log_redirector/src/sse/skseLogRedirector.cpp b/libs/skse_log_redirector/src/sse/skseLogRedirector.cpp
new file mode 100644
index 0000000..20cc44c
--- /dev/null
+++ b/libs/skse_log_redirector/src/sse/skseLogRedirector.cpp
@@ -0,0 +1,24 @@
+#include "skseLogRedirector.h"
+
+QString SkseLogRedirector::name() const
+{
+ return "SKSE Log Redirector";
+}
+
+QString SkseLogRedirector::localizedName() const
+{
+ return tr("SKSE Log Redirector");
+}
+
+QString SkseLogRedirector::description() const
+{
+ return tr("Redirects \"\\Documents\\My Games\\SKYRIM.INI\" to "
+ "\"\\Documents\\My Games\\Skyrim Special Edition\" via VFS.");
+}
+
+QString SkseLogRedirector::destFolderName() const
+{
+ // Verbatim from upstream .py: "Skyrim.INI" can be a directory created by a
+ // Skyrim bug; redirecting it makes SKSE find logs in the SSE docs.
+ return QStringLiteral("Skyrim.INI");
+}
diff --git a/libs/skse_log_redirector/src/sse/skseLogRedirector.h b/libs/skse_log_redirector/src/sse/skseLogRedirector.h
new file mode 100644
index 0000000..5074550
--- /dev/null
+++ b/libs/skse_log_redirector/src/sse/skseLogRedirector.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "skseLogRedirectorBase.h"
+
+class SkseLogRedirector : public SkseLogRedirectorBase
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.sysdmp.SKSELogRedirector")
+
+public:
+ QString name() const override;
+ QString localizedName() const override;
+ QString description() const override;
+
+protected:
+ QString destFolderName() const override;
+};
diff --git a/libs/skse_log_redirector/src/vr/CMakeLists.txt b/libs/skse_log_redirector/src/vr/CMakeLists.txt
new file mode 100644
index 0000000..00e5ac2
--- /dev/null
+++ b/libs/skse_log_redirector/src/vr/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.16)
+
+add_library(skse_log_redirector_vr SHARED
+ skseLogRedirectorVR.cpp
+ skseLogRedirectorVR.h
+)
+mo2_configure_plugin(skse_log_redirector_vr NO_SOURCES WARNINGS OFF)
+target_link_libraries(skse_log_redirector_vr PRIVATE
+ mo2::uibase
+ skse_log_redirector_common
+)
+
+mo2_install_plugin(skse_log_redirector_vr)
diff --git a/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.cpp b/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.cpp
new file mode 100644
index 0000000..caf9d86
--- /dev/null
+++ b/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.cpp
@@ -0,0 +1,22 @@
+#include "skseLogRedirectorVR.h"
+
+QString SkseLogRedirectorVR::name() const
+{
+ return "SKSE Log Redirector (test build with VR workaround)";
+}
+
+QString SkseLogRedirectorVR::localizedName() const
+{
+ return tr("SKSE Log Redirector (test build with VR workaround)");
+}
+
+QString SkseLogRedirectorVR::description() const
+{
+ return tr("Redirects \"\\Documents\\My Games\\Skyrim VR\" to "
+ "\"\\Documents\\My Games\\Skyrim Special Edition\" via VFS.");
+}
+
+QString SkseLogRedirectorVR::destFolderName() const
+{
+ return QStringLiteral("Skyrim VR");
+}
diff --git a/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.h b/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.h
new file mode 100644
index 0000000..bce099f
--- /dev/null
+++ b/libs/skse_log_redirector/src/vr/skseLogRedirectorVR.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "skseLogRedirectorBase.h"
+
+class SkseLogRedirectorVR : public SkseLogRedirectorBase
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.sysdmp.SKSELogRedirectorVR")
+
+public:
+ QString name() const override;
+ QString localizedName() const override;
+ QString description() const override;
+
+protected:
+ QString destFolderName() const override;
+};
diff --git a/libs/skse_log_redirector/vcpkg.json b/libs/skse_log_redirector/vcpkg.json
new file mode 100644
index 0000000..a639ce6
--- /dev/null
+++ b/libs/skse_log_redirector/vcpkg.json
@@ -0,0 +1,15 @@
+{
+ "features": {
+ "standalone": {
+ "description": "Build Standalone.",
+ "dependencies": ["mo2-cmake"]
+ }
+ },
+ "vcpkg-configuration": {
+ "default-registry": {
+ "kind": "git",
+ "repository": "https://github.com/ModOrganizer2/vcpkg-registry",
+ "baseline": "8beb2e0efa9c17dd6d17bb05288dd1e40727f673"
+ }
+ }
+}