Skip to content

fix(dmm-import): stop treating unknown mods as already managed - #424

Merged
Slush97 merged 1 commit into
mainfrom
fix/dmm-import-identity
Oct 6, 2026
Merged

Slush97 merged 1 commit into
mainfrom
fix/dmm-import-identity

Conversation

@Slush97

@Slush97 Slush97 commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Problem

The DMM import that runs as the first step of Fix Unknown has quietly done almost nothing since #296 (2026-07-24) on the default DMM setup, where DMM shares citadel/addons with Grimoire.

  • Startup (backfillMissingMetadataHashes) gives every unknown VPK a metadata row with its sha256, and enrich adds globalType and, for hero skins, an inferred lockerHero.
  • migrateDmmInstall put every row with a sha256 into managedHashes, so DMM's own files were skipped as "an identical file is already managed by Grimoire".
  • isGrimoireManaged counted any lockerHero, so hero skins would be refused even once the hash check was fixed.

Fix

  • hasModIdentity(meta) in metadata.ts: a row counts as managed only if it has a GameBanana id, a name, a Grimoire-built VPK (merged, Locker builds, soul/urn imports, sound swaps, forge installs) or a user choice (manual hero, local variant group, priority mod). Hashes and inferred hero/global type do not count.
  • dmmMigration.ts uses it for the "already managed" hash set and for the in-place ownership check (replacing isGrimoireManaged).
  • When DMM's file sits outside Grimoire's folders but Grimoire already lists the same bytes as an unknown mod, that file is tagged instead of copying a second one (keeps the old "no duplicate copies" behavior).

@grimoire/social-types, IPC and i18n are untouched.

Testing

  • 3 new guard tests (dmmMigration.guards.test.ts) seed the rows startup actually writes. Two of them fail on main; the manual-hero one checks protection is kept.
  • tsc -b, eslint, vitest (2651 passed), ui:check, i18n check and manifest check all pass.
  • Real data: a DMM library built by DMM main (b626d504) through its real UI with 7 real GameBanana mods (hero skin, particle skin, sound, HUD, multi-file, disabled, downloaded-only), reshaped to DMM 1.1.0's on-disk format, imported through dmm-migrate:scan/execute in a throwaway Grimoire:
    • main: 1 adopted, 6 skipped, 6 left unknown.
    • this branch: 7 adopted with the right identity (bytes match DMM's records), hero skins included, 0 unknown left; a second run adopts nothing and changes no files.

Known, not changed here

DMM 2.0 parks a downloaded-but-never-enabled mod as <id>_<name>_dir.vpk in the addons root. This import copies it to .disabled (never moving DMM files), and Grimoire's scan then drops the identical .disabled copy, so the root file ends up identified but listed as enabled. Same behavior as before #296; #417's importer handles this case by moving the file.

Related: #417 replaces this flow with the interchange importer and has the same two checks in importer.ts; it should reuse hasModIdentity after rebasing.

Since the startup sha256 backfill (#296), every unknown VPK gets a metadata
row with a hash, and enrich adds an inferred lockerHero to hero skins. The
DMM import counted any hashed row as managed and any lockerHero as owned, so
on a shared addons folder it skipped nearly every DMM mod and never adopted
a hero skin.

Add hasModIdentity() in metadata.ts (GameBanana id, name, a Grimoire-built
VPK or a user choice such as a manual hero) and use it for both checks. When
DMM's file sits outside Grimoire's folders but Grimoire already lists the
same bytes as an unknown mod, tag that file instead of copying a duplicate.
@Slush97
Slush97 merged commit a886e8a into main Oct 6, 2026
1 check passed
@Skeptic-systems

Copy link
Copy Markdown
Contributor

@Slush97 Should be fixed now, worked fine in my tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants