From 4449fa4f0e6461d8773d22b9e11c7c334c083b01 Mon Sep 17 00:00:00 2001 From: vickydotbat Date: Thu, 14 May 2026 11:43:52 +0200 Subject: [PATCH] Fix override precedence --- internal/topdata/native.go | 6 +-- internal/topdata/topdata_test.go | 78 ++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/internal/topdata/native.go b/internal/topdata/native.go index 94eb2c8..114bb74 100644 --- a/internal/topdata/native.go +++ b/internal/topdata/native.go @@ -1117,14 +1117,14 @@ func pruneLockDataToActiveRows(lockData map[string]int, rows []map[string]any, r } pruned := 0 for key := range lockData { + if _, ok := activeKeys[key]; ok { + continue + } if _, retired := retiredKeys[key]; retired { delete(lockData, key) pruned++ continue } - if _, ok := activeKeys[key]; ok { - continue - } if _, ok := referencedKeys[key]; ok { continue } diff --git a/internal/topdata/topdata_test.go b/internal/topdata/topdata_test.go index 52882ed..72b75c8 100644 --- a/internal/topdata/topdata_test.go +++ b/internal/topdata/topdata_test.go @@ -8410,6 +8410,84 @@ func TestBuildSkillsKeyNullRemovesIdentityWithoutNullingRow(t *testing.T) { } } +func TestBuildSpellsAllowsDuplicateBaseKeyToBeSplitAcrossTwoOverrideRenames(t *testing.T) { + root := testProjectRoot(t) + mkdirAll(t, filepath.Join(root, "topdata", "data", "spells", "modules")) + writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n") + writeFile(t, filepath.Join(root, "topdata", "data", "spells", "base.json"), `{ + "output": "spells.2da", + "columns": ["Label", "Name", "SpellDesc"], + "rows": [ + {"id": 443, "key": "spells:etherealness", "Label": "GreaterSanctuary", "Name": "2364", "SpellDesc": "2371"}, + {"id": 724, "key": "spells:etherealness_83893", "Label": "Etherealness", "Name": "83893", "SpellDesc": "****"} + ] +}`+"\n") + writeFile(t, filepath.Join(root, "topdata", "data", "spells", "lock.json"), "{}\n") + writeFile(t, filepath.Join(root, "topdata", "data", "spells", "modules", "ovr_fixduplicates.json"), `{ + "overrides": [ + { + "id": 443, + "key": "spells:greater_sanctuary" + }, + { + "id": 724, + "key": "spells:etherealness" + } + ] +}`+"\n") + mkdirAll(t, filepath.Join(root, "reference")) + writeFile(t, filepath.Join(root, "reference", "build.py"), "print('ok')\n") + + datasets, err := discoverNativeDatasets(filepath.Join(root, "topdata", "data")) + if err != nil { + t.Fatalf("discoverNativeDatasets failed: %v", err) + } + if len(datasets) != 1 { + t.Fatalf("expected one dataset, got %d", len(datasets)) + } + collectedDataset, err := collectNativeDataset(datasets[0]) + if err != nil { + t.Fatalf("collectNativeDataset failed: %v", err) + } + if collectedDataset.LockData["spells:greater_sanctuary"] != 443 { + t.Fatalf("expected collected greater_sanctuary lock entry, got %#v", collectedDataset.LockData) + } + if collectedDataset.LockData["spells:etherealness"] != 724 { + t.Fatalf("expected collected etherealness to be remapped to row 724, got lock=%#v rows=%#v", collectedDataset.LockData, collectedDataset.Rows) + } + if _, ok := collectedDataset.LockData["spells:etherealness_83893"]; ok { + t.Fatalf("expected collected etherealness_83893 to be retired, got %#v", collectedDataset.LockData) + } + + result, err := BuildNative(testProject(root), nil) + if err != nil { + t.Fatalf("BuildNative failed: %v", err) + } + lockRaw, err := os.ReadFile(filepath.Join(root, "topdata", "data", "spells", "lock.json")) + if err != nil { + t.Fatalf("read spells lock: %v", err) + } + lockText := string(lockRaw) + if !strings.Contains(lockText, `"spells:greater_sanctuary": 443`) { + t.Fatalf("expected greater_sanctuary lock entry, got:\n%s", lockText) + } + if !strings.Contains(lockText, `"spells:etherealness": 724`) { + t.Fatalf("expected etherealness to be remapped to row 724, got:\n%s", lockText) + } + if strings.Contains(lockText, `"spells:etherealness_83893"`) { + t.Fatalf("expected etherealness_83893 to be retired, got:\n%s", lockText) + } + + got, err := os.ReadFile(filepath.Join(result.Output2DADir, "spells.2da")) + if err != nil { + t.Fatalf("read spells.2da: %v", err) + } + text := string(got) + if !strings.Contains(text, "GreaterSanctuary") || !strings.Contains(text, "Etherealness") { + t.Fatalf("expected both renamed rows to remain present, got:\n%s", text) + } +} + func TestBuildSkillsIgnoresStaleBaseSpanLockDuringInitialLoad(t *testing.T) { root := testProjectRoot(t) mkdirAll(t, filepath.Join(root, "topdata", "data", "skills", "modules"))