| Commit message (Collapse) | Author | Age | Files | Lines |
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
This reverts commit 41a336cc8e53ba062ab791ffd6dc9b90d2c72899.
|
| | |
|
| | |
|
| |\
| |
| | |
add support for user-configured font
|
| | | |
|
| | | |
|
| |/ |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Multi-area sync against the upstream MO2 2.5.3 beta line. Roughly three
logical sections share the diff:
Catch-up (Betas 3-11):
- nxmaccessmanager: drop "supporter" from validRoles so non-premium
supporters get the right download path (Beta 10)
- mainwindow: disable tutorial triggers at the trigger sites; Qt 6.11
lockup on child windows (Beta 4)
- basic_games: add Kingdom Come Deliverance 2, Slay the Spire 2
(Betas 11, 6)
- uibase: add NXM collections parsing fields/accessors + (?:nxm|modl)
scheme support in NXMUrl (Beta 9)
- Starfield: blueprintPrefix() on IPluginGame; plugins.txt write
suppression for blueprint plugins; hasInvalidBlueprint /
hasUnpairedBlueprint diagnoses; Title-keyed content catalog
consolidation (Betas 3-5)
- downloadmanager + systemtraymanager + organizercore + iuserinterface
+ settings: add Beta 11 "show notifications when downloads complete
or fail" toggle and the showNotification plumbing
- nxmaccessmanager: restore upstream re-entry guard for OAuth refresh
and the styled OAuth response page (Beta 11)
- organizer_en.ts and game-bethesda *_en.ts: pull upstream HEAD strings
Workarounds tab removed:
- Delete settingsdialogworkarounds.{h,cpp}; drop the tab in
settingsdialog.ui; move "Enable archives parsing" into General
- Hardcode GameSettings::forceEnableCoreFiles() to true so the
primary-master toggle-off bug (DLCs unchecked on tab refresh) can't
recur; setter becomes a no-op
- No-op stubs for offlineMode, useProxy, useCustomBrowser, Steam
appID/credentials, executablesBlacklist, skipFileSuffixes,
skipDirectories — UI gone, accessors keep call sites green
- settingsdialognexus drops the custom-browser wiring; spawn drops the
"Change the blacklist" Retry path
Beta 9 download manager port:
- fileID-first match in nxmFilesAvailable and
nxmFileInfoFromMd5Available; filename remains the fallback
- NexusInterface::isActiveFileStatus() helper; rewrite of
nxmUpdatesAvailable to use pickNewestVersion /
findUpdateChainSuccessors / resolveInstalledFileId. ARCHIVED_HIDDEN
now correctly treated as inactive
- std::optional<unsigned int> reservedID on DownloadInfo factories and
on the three addDownload overloads; startDownloadURLs and
startDownloadURLWithMeta return the canonical DownloadID instead of
m_ActiveDownloads.size()-1 (which was the index, not an ID)
- QHash<unsigned int, DownloadInfo*> m_ByID maintained alongside
m_ActiveDownloads at every mutation site; downloadInfoByID is now
O(1) via m_ByID.value(id, nullptr)
LOOT remains intentionally stripped (lootcli build cruft cleaned up
separately). BSA wide-path skipped — Linux UTF-8 paths already work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Steam build of Ready or Not ships its main executable as
ReadyOrNotSteam-Win64-Shipping.exe; the non-Steam build (Epic / GOG)
ships plain ReadyOrNot-Win64-Shipping.exe. The shipped plugin only
listed the latter, so Steam users hit "game directory not valid"
and couldn't open the instance.
Override looksValid() to accept either binary so detection works
out of the box for both stores. GameBinary defaults to the Steam
variant since Fluorine is Steam/Proton-oriented; the override
makes the non-Steam binary equally valid for instance opening.
Bump plugin version to 0.0.0.2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
User feedback: the only way to clean up old backups was to hand-edit
the profile directory, since the "Choose backup to restore" dialog
exposed select-or-cancel and no delete affordance.
Add an addChoice overload on SelectionDialog that takes a per-row
delete callback. Each row is rendered as a horizontal layout —
QCommandLinkButton (stretched) plus a small auto-raised QToolButton
with a trash icon (user-trash → edit-delete → SP_TrashIcon
fallback chain). Clicking the trash prompts for confirmation,
invokes the callback, and hides the row on success; the QCommandLink
remains live for restore. numChoices() now counts visible rows
under scrollAreaWidgetContents so the "no backups" check stays
correct as rows disappear.
MainWindow::queryRestore wires the callback to delete the matching
Plugins.txt.<ts>, loadorder.txt.<ts>, and lockedorder.txt.<ts>
triplet via QFile::remove.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
"plugin failed to initialize" with no name and no exception text is
the canonical first-line indicator for a Python plugin that didn't
register — but it tells the user nothing about *which* plugin or
*why*. Encountered while diagnosing a flaky first-launch failure
where a Python plugin's init() silently returned False on cold
boot and succeeded on the next run, plus a Ready or Not instance
that wouldn't open.
Wrap the IPlugin::init trampoline in pyplugins.h manually instead
of relying on PYBIND11_OVERRIDE_PURE so we can:
- log the plugin's name and the surrounding hint when init()
returns False (typically a plugin swallowing an exception in
its own try/except);
- catch pybind11::error_already_set and log the Python exception
text + traceback before returning False to the C++ caller.
plugincontainer.cpp's "plugin failed to initialize" line now also
prints the plugin name so the proxied-candidate context is clear.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two complementary changes against ENOTCONN — "Transport endpoint is
not connected" — from a wedged FUSE mount left by a previous crashed
or unclean session.
MOApplication::notify already caught filesystem_error and called
FuseConnector::tryCleanupStaleMount on the affected path, but it
still went on to show the user a hard error dialog about the
exception. If we've already cleared the wedged mount the workflow
that triggered the iterator (refresh, restore backup, etc.) just
needs to be retried — the dialog is noise on a state we just
recovered from. Probe stat() after cleanup; if the path is no
longer wedged, log + swallow.
OrganizerCore::afterRun's post-game chmod loop used the throwing
recursive_directory_iterator constructor with no error_code, so a
single ENOTCONN under the game dir unwound out of afterRun and
left the rest of the post-run sync (save/INI/plugin sync-back,
load-order refresh, FinishedRun callback) un-run. Switch to
error_code-based iteration; on ENOTCONN, call
tryCleanupStaleMount on the game dir and continue cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
invalidateNodeCache's docstring promised "Clear all node_cache entries
whose path starts with the given prefix" but the implementation only
cleared the exact path's entry and its parent. removeFromTree on a
directory destroys every descendant VfsNode via cascading unique_ptr
destruction; every descendant inode still cached in node_cache became
a dangling pointer.
Next time Wine called getattr on a cached descendant ino,
resolveByInode returned the dangling pointer and snapshotFromNode
read freed memory — depending on what reused the allocation, this
manifested as either std::bad_alloc (corrupted string length in
real_path triggers a huge allocation request) or outright SIGSEGV.
ENOMEM bubbled up to Wine's NT loader as ERROR_MOD_NOT_FOUND (0x7E),
which is exactly the F4SE "couldn't load plugin (0000007E)" pattern
reported in #210 after mod-state transitions.
Rewrite invalidateNodeCache to actually walk node_cache and erase
every entry whose path is the target or a descendant under target/.
Lock order is tree_mutex (exclusive, caller) → inode_mutex (shared)
→ node_cache_mutex (exclusive), consistent with existing sites.
Top-level mutations also invalidate root (inode 1) since its
children map changed.
Also enrich the FUSE wrap_* exception macro to log the inode being
processed alongside the exception text. Future "[VFS] getattr(ino=N):
caught exception: ..." entries point straight at the path that
triggered cache/tree corruption.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|