Fix Darkest Dungeon Workshop mod handling#1500
Conversation
📝 WalkthroughWalkthroughWorkshopManager adds workshop payload validation, multi-stage steam_settings cleanup, payload-aware metadata generation, and enhanced DLL discovery with path normalization and symlink safety. Items with corrupted/suspicious payloads are now deleted and forced to re-download; mods metadata derives file selection from actual payload files; symlink configuration includes app ID override extension and stale directory cleanup. ChangesPayload Validation and Metadata Refinement
Symlink Configuration and DLL Discovery Refinement
Sequence DiagramsequenceDiagram
participant SyncFlow as getItemsNeedingSync
participant Validate as PayloadValidator
participant Cleanup as CleanupHelpers
participant Metadata as buildModsJson
participant Symlink as configureModSymlinks
participant Discovery as DLLDiscovery
SyncFlow->>Cleanup: cleanupGeneratedSteamSettingsInWorkshopContent
SyncFlow->>Validate: invalidWorkshopPayloadReason (per item)
alt Invalid Payload
Validate->>Cleanup: deleteDirectoryTreeNoFollow (invalidate)
Cleanup-->>SyncFlow: Item marked for re-download
else Valid Payload
Validate-->>SyncFlow: Item ready for sync
end
Metadata->>Validate: getPayloadFiles (detect primary file & sizes)
Validate-->>Metadata: primary filename + total size
Symlink->>Cleanup: cleanupGeneratedSteamSettingsInWorkshopContent
Symlink->>Discovery: Walk gameRootDir with path filtering
Discovery->>Discovery: shouldSkipDllDiscoveryPath (prune workshop/metadata)
Discovery->>Cleanup: cleanupStaleGeneratedGameSteamSettings(validPaths)
Cleanup-->>Symlink: Stale directories removed
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
0487b59 to
47e25a2
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src/main/java/app/gamenative/workshop/WorkshopManager.kt`:
- Around line 1513-1515: The current payload detection in isWorkshopPayloadFile
(which uses pathKey(file) and hasSteamSettingsSegment) incorrectly treats
preview.* files as mod payload; update isWorkshopPayloadFile to also exclude
files whose names match the generated preview pattern (e.g., names starting with
"preview." or matching "preview.*") so preview images are not counted as
payload, and then ensure any logic that sets primary_filename (the code that
derives primary_filename from the recursive payload set) computes it from the
filtered payload list returned by isWorkshopPayloadFile rather than from the
unfiltered file list so primary_filename can never point to a preview artifact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a7d89f16-1a03-4da4-bff6-b5ec4f11776b
📒 Files selected for processing (1)
app/src/main/java/app/gamenative/workshop/WorkshopManager.kt
There was a problem hiding this comment.
1 issue found across 1 file
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
47e25a2 to
e06b895
Compare
| private fun pathKey(path: Path): String = | ||
| path.normalize().toAbsolutePath().toString() | ||
| .replace('\\', '/') | ||
| .trimEnd('/') | ||
| .lowercase() |
There was a problem hiding this comment.
Might be worth pulling or re-using some of these from fileUtils.kt
There was a problem hiding this comment.
Good thought but I checked FileUtils and didn’t see a clean direct reuse. These helpers are pretty specific to the Workshop cleanup path, especially the steam_settings/workshop-content filtering and no-follow delete behavior.
The only reusable bits would maybe be path normalization / same-child checks, but since they’re only used here right now I kept them local for now.
What are your thoughts?
| // _metadata format that doesn't work when symlinked into mods/. | ||
| // Force ISteamUGC path regardless of detection. | ||
| val forceStandardAppIds = setOf(211820,1468810) // Starbound,TaleofImmortal | ||
| val forceStandardAppIds = setOf(211820, 1468810, 262060) // Starbound, Tale of Immortal, Darkest Dungeon |
There was a problem hiding this comment.
I think it's worth us pulling these out into a different file like a workshopOverrideIds.kt where we can more easily track this.
There was a problem hiding this comment.
Good idea, latest commit adds a WorkshopOverrideIds.kt as requested :)
|
A few suggestions, otherwise looks pretty good. Have you also tested that the changes are backwards compatible with other titles? Would also be good for a quick recording of the change that allows DD to work |
e06b895 to
1e38ab6
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/workshop/WorkshopOverrideIds.kt (1)
4-7: 💤 Low valueConsider enhancing the documentation with rationale.
The KDoc explains what the override does but could benefit from explaining why these specific games need this treatment. Consider adding a note about the common characteristic they share (e.g., "Games with a mods/ directory that shouldn't trigger filesystem-based mod detection").
This would help future maintainers understand when to add new App IDs to this set.
📝 Suggested documentation enhancement
/** * Games that should use the standard ISteamUGC/mods.json path even when * mod directory detection finds a high-confidence filesystem mod folder. + * + * These games have a mods/ directory in their installation but rely on + * Workshop metadata rather than direct filesystem access for mod loading. */🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/src/main/java/app/gamenative/workshop/WorkshopOverrideIds.kt` around lines 4 - 7, The KDoc on WorkshopOverrideIds should be expanded to include the rationale for the override: explain that the listed App IDs (in WorkshopOverrideIds) are games that have a mods/ (or similar) directory which would otherwise trigger high-confidence filesystem-based mod detection, but should instead use the standard ISteamUGC/mods.json path; add a short note describing this common characteristic and guidance for when to add new App IDs (e.g., "add when a game has a mods/ folder that should not be treated as a filesystem mod folder").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@app/src/main/java/app/gamenative/workshop/WorkshopOverrideIds.kt`:
- Around line 4-7: The KDoc on WorkshopOverrideIds should be expanded to include
the rationale for the override: explain that the listed App IDs (in
WorkshopOverrideIds) are games that have a mods/ (or similar) directory which
would otherwise trigger high-confidence filesystem-based mod detection, but
should instead use the standard ISteamUGC/mods.json path; add a short note
describing this common characteristic and guidance for when to add new App IDs
(e.g., "add when a game has a mods/ folder that should not be treated as a
filesystem mod folder").
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 93865dad-199a-4aa3-8f69-72ede32cfaa0
📒 Files selected for processing (2)
app/src/main/java/app/gamenative/workshop/WorkshopManager.ktapp/src/main/java/app/gamenative/workshop/WorkshopOverrideIds.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- app/src/main/java/app/gamenative/workshop/WorkshopManager.kt
I've tested a handful of games already and they still work. There shouldn't be any regressions since if another game had broken generated steam_settings it likely already didn't work anyway. Although I wouldn't be completely surprised if there's some weird edge case where a game could have been “working” despite stale generated files, and this PR may now clean them. Video added as well. |
Added comments to clarify the purpose of forceStandardAppIds.
|
Thank you, merged. Can you get the nightly to the person who brought it up @Nightwalker743? I'm flying for the next 24 hours |
|
@utkarshdalal I've sent the nightly over to them! Thanks, have a safe flight! |
Description
This is a requested bug fix from here: https://discord.com/channels/1378308569287622737/1506727093122240632
Fixes Darkest Dungeon workshop mods only partially appearing in-game on GameNative.
The game was being treated as a filesystem-managed mod title because it has a high-confidence
mods/directory, which caused Workshop items to be symlinked instead of exposed through the standard ISteamUGC/gbe_fork Workshop metadata path. This made only a subset of subscribed Workshop mods appear in-game.This change forces Darkest Dungeon (
262060) through the standard Workshop path, prevents generatedsteam_settingsand Workshop symlink trees from being rediscovered as game Steam API locations, excludes generated metadata from Workshop payload sizing, and invalidates stale completed downloads whose usable payload is missing or implausibly incomplete.Recording
I downloaded a mod that removes the circus icon in the bottom left corner just to show off mods working easily. Image here is before the mod, circus icon in the bottom left:

Video showing the mod working (and other mods enabled and no crashing):
https://github.com/user-attachments/assets/59101681-004d-4731-a68d-44a2023f24d2
Type of Change
Checklist
#code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.CONTRIBUTING.md.Summary by cubic
Fixes Darkest Dungeon (app 262060) Workshop mods only partially appearing by routing the game through standard Steam Workshop handling and tightening validation/cleanup. All subscribed Workshop mods now load correctly and broken or partial downloads are auto-repaired.
WorkshopOverrideIds(instead of filesystem mod detection).steam_settings, hidden files, and preview images from payload scans; computeprimary_filename,primary_filesize, andtotal_files_sizesfrom filtered files only.steam_settings, anywhere under/workshop/content/, and symlinks pointing into it to avoid false Steam API locations.steam_settingsfrom Workshop content and stale ones in the game tree; keep only dirs next to real Steam DLLs and write the correctsteam_appid.txtbeside each.Written for commit 2db27e7. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
Chores