Fix alignment/id encoding

This commit is contained in:
2026-05-26 14:18:04 +02:00
parent 22e3fabbbb
commit 28d487565a
3 changed files with 93 additions and 0 deletions
+5
View File
@@ -148,6 +148,11 @@ toolkit defaults, YAML values, legacy status, active environment overrides, and
provenance. Sensitive override values such as tokens are reported as set without provenance. Sensitive override values such as tokens are reported as set without
printing the secret. printing the secret.
Topdata value encodings under `topdata.value_encodings` are matched by dataset
and column. Set `dataset: "*"` to apply an encoding to the same column name in
any native topdata dataset; an exact dataset rule takes precedence over the
wildcard rule for that column.
Common configurable defaults: Common configurable defaults:
```yaml ```yaml
+10
View File
@@ -420,6 +420,16 @@ func applyTopDataValueEncodings(datasets []nativeDataset, encodings []project.To
} }
out := append([]nativeDataset(nil), datasets...) out := append([]nativeDataset(nil), datasets...)
for index := range out { for index := range out {
for _, encoding := range encodings {
dataset := filepath.ToSlash(strings.TrimSpace(encoding.Dataset))
if dataset != "*" {
continue
}
if out[index].ValueEncodings == nil {
out[index].ValueEncodings = map[string]project.TopDataValueEncodingConfig{}
}
out[index].ValueEncodings[strings.ToLower(strings.TrimSpace(encoding.Column))] = encoding
}
for _, encoding := range encodings { for _, encoding := range encodings {
if filepath.ToSlash(strings.TrimSpace(encoding.Dataset)) != out[index].Name { if filepath.ToSlash(strings.TrimSpace(encoding.Dataset)) != out[index].Name {
continue continue
+78
View File
@@ -348,6 +348,84 @@ func TestBuildNativeEncodesConfiguredIDHexLists(t *testing.T) {
} }
} }
func TestBuildNativeAppliesWildcardConfiguredValueEncodings(t *testing.T) {
root := testProjectRoot(t)
mkdirAll(t, filepath.Join(root, "topdata", "data", "feat"))
mkdirAll(t, filepath.Join(root, "topdata", "data", "classes", "core", "modules"))
mkdirAll(t, filepath.Join(root, "topdata", "data", "baseitems", "modules"))
writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "base.json"), `{
"output": "feat.2da",
"columns": ["LABEL"],
"rows": [
{"id": 2, "key": "feat:weapon_proficiency_simple", "LABEL": "WeaponProfSimple"},
{"id": 9, "key": "feat:weapon_proficiency_martial", "LABEL": "WeaponProfMartial"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "lock.json"), `{
"feat:weapon_proficiency_simple": 2,
"feat:weapon_proficiency_martial": 9
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "classes", "core", "base.json"), `{
"output": "classes.2da",
"columns": ["Label", "PreferredAlignments"],
"rows": [
{"id": 0, "key": "classes:barbarian", "Label": "Barbarian"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "classes", "core", "lock.json"), `{"classes:barbarian":0}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "classes", "core", "modules", "10_barbarian.json"), `{
"overrides": [
{
"key": "classes:barbarian",
"PreferredAlignments": {"alignments": ["ng", "cg", "tn", "cn", "ne", "ce"]}
}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "base.json"), `{
"output": "baseitems.2da",
"columns": ["Label", "ProficiencyFeats"],
"rows": [
{"id": 42, "key": "baseitems:testclub", "Label": "Test Club"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "lock.json"), `{"baseitems:testclub":42}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "modules", "10_testclub.json"), `{
"overrides": [
{
"key": "baseitems:testclub",
"ProficiencyFeats": {"ids": ["feat:weapon_proficiency_simple", "feat:weapon_proficiency_martial"]}
}
]
}`+"\n")
proj := testProject(root)
proj.Config.TopData.ValueEncodings = []project.TopDataValueEncodingConfig{
{Dataset: "classes/core", Column: "PreferredAlignments", Mode: "alignment_hex_list", Min: 0, Max: 31, HexWidth: 3},
{Dataset: "*", Column: "PreferredAlignments", Mode: "alignment_hex_list", Min: 0, Max: 31, HexWidth: 2},
{Dataset: "*", Column: "ProficiencyFeats", Mode: "id_hex_list", Min: 0, Max: 65535, HexWidth: 4},
}
result, err := BuildNativeWithOptions(proj, NativeBuildOptions{BuildWiki: false}, nil)
if err != nil {
t.Fatalf("BuildNativeWithOptions failed: %v", err)
}
classesRaw, err := os.ReadFile(filepath.Join(result.Output2DADir, "classes.2da"))
if err != nil {
t.Fatalf("read classes.2da: %v", err)
}
if got := string(classesRaw); !strings.Contains(got, "0x00900C001005011014") {
t.Fatalf("expected wildcard alignment encoding in classes.2da, got:\n%s", got)
}
baseitemsRaw, err := os.ReadFile(filepath.Join(result.Output2DADir, "baseitems.2da"))
if err != nil {
t.Fatalf("read baseitems.2da: %v", err)
}
if got := string(baseitemsRaw); !strings.Contains(got, "0x00020009") {
t.Fatalf("expected wildcard id encoding in baseitems.2da, got:\n%s", got)
}
}
func TestBuildNativeAppliesConfiguredValueDefaults(t *testing.T) { func TestBuildNativeAppliesConfiguredValueDefaults(t *testing.T) {
root := testProjectRoot(t) root := testProjectRoot(t)
mkdirAll(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "modules")) mkdirAll(t, filepath.Join(root, "topdata", "data", "racialtypes", "core", "modules"))