Fix base parts not generating
This commit is contained in:
@@ -182,7 +182,6 @@ generated_assets:
|
|||||||
kind: trailing_numeric_suffix
|
kind: trailing_numeric_suffix
|
||||||
group_from: first_path_segment
|
group_from: first_path_segment
|
||||||
parts_rows:
|
parts_rows:
|
||||||
null_undiscovered_rows: true
|
|
||||||
row_defaults:
|
row_defaults:
|
||||||
COSTMODIFIER: "0"
|
COSTMODIFIER: "0"
|
||||||
acbonus:
|
acbonus:
|
||||||
@@ -274,11 +273,11 @@ ACBONUS values before module overrides are applied. The
|
|||||||
IDs so higher part rows can sort before lower rows in the toolset; the legacy
|
IDs so higher part rows can sort before lower rows in the toolset; the legacy
|
||||||
`descending_row_id_sort_key` strategy remains available for repositories that
|
`descending_row_id_sort_key` strategy remains available for repositories that
|
||||||
already depend on it. Per-dataset policies such as `chest: fixed 0.00` can
|
already depend on it. Per-dataset policies such as `chest: fixed 0.00` can
|
||||||
override the default. When `null_undiscovered_rows` is true, authored part rows
|
override the default. Authored source ACBONUS values are not authoritative when
|
||||||
without discovered model IDs are omitted from the collected row set so dense
|
this policy is configured, except that authored `****` values remain null
|
||||||
2DA output writes them as `****` null rows. Authored source ACBONUS values are
|
unless model discovery activates the row. Dense gaps without authored rows or
|
||||||
not authoritative when this policy is configured; files under `parts/modules`
|
discovered part models are emitted as `****` null rows. Files under
|
||||||
remain the final override layer.
|
`parts/modules` remain the final override layer.
|
||||||
|
|
||||||
Extraction is deliberately guarded because it writes source files from binary
|
Extraction is deliberately guarded because it writes source files from binary
|
||||||
archives. `extract.archives` is a list of glob patterns relative to
|
archives. `extract.archives` is a list of glob patterns relative to
|
||||||
|
|||||||
@@ -2248,7 +2248,6 @@ func TestBuildHAKsGeneratesParts2DAAssetsFromLocalModels(t *testing.T) {
|
|||||||
"group_from": "first_path_segment"
|
"group_from": "first_path_segment"
|
||||||
},
|
},
|
||||||
"parts_rows": {
|
"parts_rows": {
|
||||||
"null_undiscovered_rows": true,
|
|
||||||
"row_defaults": {"COSTMODIFIER": "0"},
|
"row_defaults": {"COSTMODIFIER": "0"},
|
||||||
"acbonus": {
|
"acbonus": {
|
||||||
"default": {
|
"default": {
|
||||||
@@ -2285,6 +2284,7 @@ func TestBuildHAKsGeneratesParts2DAAssetsFromLocalModels(t *testing.T) {
|
|||||||
"rows": [
|
"rows": [
|
||||||
{"id": 0, "COSTMODIFIER": 1, "ACBONUS": "0.25"},
|
{"id": 0, "COSTMODIFIER": 1, "ACBONUS": "0.25"},
|
||||||
{"id": 17, "COSTMODIFIER": 0, "ACBONUS": "0.90"},
|
{"id": 17, "COSTMODIFIER": 0, "ACBONUS": "0.90"},
|
||||||
|
{"id": 19, "COSTMODIFIER": 0, "ACBONUS": "****"},
|
||||||
{"id": 117, "COSTMODIFIER": 0, "ACBONUS": "****"}
|
{"id": 117, "COSTMODIFIER": 0, "ACBONUS": "****"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -2327,7 +2327,13 @@ func TestBuildHAKsGeneratesParts2DAAssetsFromLocalModels(t *testing.T) {
|
|||||||
t.Fatalf("read generated parts 2da: %v", err)
|
t.Fatalf("read generated parts 2da: %v", err)
|
||||||
}
|
}
|
||||||
partsText := string(partsRaw)
|
partsText := string(partsRaw)
|
||||||
for _, want := range []string{"0\t****\t****", "17\t****\t****", "18\t0\t0.75", "117\t0\t1.17"} {
|
for _, want := range []string{
|
||||||
|
"0\t1\t0.00",
|
||||||
|
"17\t0\t0.17",
|
||||||
|
"18\t0\t0.75",
|
||||||
|
"19\t****\t****",
|
||||||
|
"117\t0\t1.17",
|
||||||
|
} {
|
||||||
if !strings.Contains(partsText, want) {
|
if !strings.Contains(partsText, want) {
|
||||||
t.Fatalf("expected generated parts 2da to contain %q after normalization and overrides, got:\n%s", want, partsText)
|
t.Fatalf("expected generated parts 2da to contain %q after normalization and overrides, got:\n%s", want, partsText)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,10 +297,9 @@ type AutogenConsumerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PartsRowsConfig struct {
|
type PartsRowsConfig struct {
|
||||||
NullUndiscoveredRows bool `json:"null_undiscovered_rows" yaml:"null_undiscovered_rows"`
|
RowDefaults map[string]string `json:"row_defaults" yaml:"row_defaults"`
|
||||||
RowDefaults map[string]string `json:"row_defaults" yaml:"row_defaults"`
|
ACBonus PartsRowsACBonusConfig `json:"acbonus" yaml:"acbonus"`
|
||||||
ACBonus PartsRowsACBonusConfig `json:"acbonus" yaml:"acbonus"`
|
Datasets map[string]PartsRowsDatasetConfig `json:"datasets" yaml:"datasets"`
|
||||||
Datasets map[string]PartsRowsDatasetConfig `json:"datasets" yaml:"datasets"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartsRowsDatasetConfig struct {
|
type PartsRowsDatasetConfig struct {
|
||||||
@@ -1396,9 +1395,6 @@ func validateGeneratedConfig(cfg GeneratedConfig) []error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func partsRowsConfigConfigured(cfg PartsRowsConfig) bool {
|
func partsRowsConfigConfigured(cfg PartsRowsConfig) bool {
|
||||||
if cfg.NullUndiscoveredRows {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if len(cfg.RowDefaults) > 0 {
|
if len(cfg.RowDefaults) > 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,44 +907,6 @@ func TestValidateLayoutAcceptsGeneratedTopData2DAConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateLayoutAcceptsGeneratedPartsRowsNullUndiscoveredWithoutACBonusPolicy(t *testing.T) {
|
|
||||||
root := t.TempDir()
|
|
||||||
mkdirAll(t, filepath.Join(root, "assets"))
|
|
||||||
mkdirAll(t, filepath.Join(root, "build"))
|
|
||||||
proj := Project{
|
|
||||||
Root: root,
|
|
||||||
Config: Config{
|
|
||||||
Module: ModuleConfig{Name: "Test", ResRef: "testmod"},
|
|
||||||
Paths: PathConfig{Assets: "assets"},
|
|
||||||
Generated: GeneratedConfig{
|
|
||||||
TopData2DA: []GeneratedTopData2DAConfig{
|
|
||||||
{
|
|
||||||
ID: "parts",
|
|
||||||
Source: "topdata",
|
|
||||||
Output: "{paths.cache}/generated-assets/parts-2da",
|
|
||||||
IncludeDatasets: []string{"parts/**"},
|
|
||||||
PackageRoot: "part",
|
|
||||||
Autogen: AutogenConsumerConfig{
|
|
||||||
ID: "parts",
|
|
||||||
Mode: "parts_rows",
|
|
||||||
Root: "part",
|
|
||||||
Include: []string{"**/*.mdl"},
|
|
||||||
Derive: AutogenDeriveConfig{Kind: "trailing_numeric_suffix", GroupFrom: "first_path_segment"},
|
|
||||||
PartsRows: PartsRowsConfig{
|
|
||||||
NullUndiscoveredRows: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := proj.ValidateLayout(); err != nil {
|
|
||||||
t.Fatalf("ValidateLayout returned error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateLayoutRejectsEscapingGeneratedTopData2DAConfig(t *testing.T) {
|
func TestValidateLayoutRejectsEscapingGeneratedTopData2DAConfig(t *testing.T) {
|
||||||
root := t.TempDir()
|
root := t.TempDir()
|
||||||
mkdirAll(t, filepath.Join(root, "assets"))
|
mkdirAll(t, filepath.Join(root, "assets"))
|
||||||
|
|||||||
@@ -136,11 +136,13 @@ The superseded implementation was correct only if all of the following were true
|
|||||||
- `COSTMODIFIER = 0`
|
- `COSTMODIFIER = 0`
|
||||||
- `ACBONUS = 0.00`
|
- `ACBONUS = 0.00`
|
||||||
|
|
||||||
6. When configured, rows without discovered models are emitted as dense null
|
6. Authored base rows remain exposed. Authored `ACBONUS = ****` rows remain
|
||||||
|
null unless model discovery activates the row.
|
||||||
|
7. Dense gaps without authored rows or discovered models are emitted as null
|
||||||
rows with `COSTMODIFIER = ****` and `ACBONUS = ****`.
|
rows with `COSTMODIFIER = ****` and `ACBONUS = ****`.
|
||||||
7. File overrides are applied after discovery and take precedence.
|
8. File overrides are applied after discovery and take precedence.
|
||||||
8. The final output includes all eligible existing models present in the manifest.
|
9. The final output includes all eligible existing models present in the manifest.
|
||||||
9. Discovery does not require a sibling local `sow-assets` checkout or a Git clone.
|
10. Discovery does not require a sibling local `sow-assets` checkout or a Git clone.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -474,7 +474,9 @@ func normalizePartsRowsACBonus(collected []nativeCollectedDataset, cfg project.P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rowID, ok := cloned["id"].(int)
|
rowID, ok := cloned["id"].(int)
|
||||||
if ok {
|
if isUnsetPartValue(cloned["ACBONUS"]) {
|
||||||
|
cloned["COSTMODIFIER"] = nullValue
|
||||||
|
} else if ok {
|
||||||
if value, configured := configuredPartsRowsACBonusValue(rowID, dataset.Dataset.Name, cfg); configured {
|
if value, configured := configuredPartsRowsACBonusValue(rowID, dataset.Dataset.Name, cfg); configured {
|
||||||
cloned["ACBONUS"] = value
|
cloned["ACBONUS"] = value
|
||||||
}
|
}
|
||||||
@@ -663,15 +665,7 @@ func augmentWithAutogeneratedPartsWithConfig(collected []nativeCollectedDataset,
|
|||||||
|
|
||||||
// Add rows for discovered IDs that don't already exist.
|
// Add rows for discovered IDs that don't already exist.
|
||||||
newRows := make([]map[string]any, 0, len(dataset.Rows))
|
newRows := make([]map[string]any, 0, len(dataset.Rows))
|
||||||
for _, row := range dataset.Rows {
|
newRows = append(newRows, dataset.Rows...)
|
||||||
rowID, ok := row["id"].(int)
|
|
||||||
if cfg.NullUndiscoveredRows && ok {
|
|
||||||
if _, discovered := ids[rowID]; !discovered {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newRows = append(newRows, row)
|
|
||||||
}
|
|
||||||
|
|
||||||
for rowID := range ids {
|
for rowID := range ids {
|
||||||
if row, exists := existingRows[rowID]; exists {
|
if row, exists := existingRows[rowID]; exists {
|
||||||
|
|||||||
@@ -10533,6 +10533,7 @@ func TestNormalizePartsRowsACBonusUsesConfiguredPolicyBeforeOverrides(t *testing
|
|||||||
Rows: []map[string]any{
|
Rows: []map[string]any{
|
||||||
{"id": 1, "COSTMODIFIER": "5", "ACBONUS": "0.90"},
|
{"id": 1, "COSTMODIFIER": "5", "ACBONUS": "0.90"},
|
||||||
{"id": 999, "COSTMODIFIER": "0", "ACBONUS": "****"},
|
{"id": 999, "COSTMODIFIER": "0", "ACBONUS": "****"},
|
||||||
|
{"id": 1000, "COSTMODIFIER": "0", "ACBONUS": "0.00"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -10569,8 +10570,11 @@ func TestNormalizePartsRowsACBonusUsesConfiguredPolicyBeforeOverrides(t *testing
|
|||||||
if got := beltRows[1]["ACBONUS"]; got != "9.98" {
|
if got := beltRows[1]["ACBONUS"]; got != "9.98" {
|
||||||
t.Fatalf("expected authored belt ACBONUS to be replaced with computed sort key 9.98, got %v", got)
|
t.Fatalf("expected authored belt ACBONUS to be replaced with computed sort key 9.98, got %v", got)
|
||||||
}
|
}
|
||||||
if got := beltRows[999]["ACBONUS"]; got != "0.00" {
|
if got := beltRows[999]["ACBONUS"]; got != "****" {
|
||||||
t.Fatalf("expected highest belt row to sort at 0.00, got %v", got)
|
t.Fatalf("expected authored null belt row to remain ****, got %v", got)
|
||||||
|
}
|
||||||
|
if got := beltRows[1000]["ACBONUS"]; got != "-0.01" {
|
||||||
|
t.Fatalf("expected non-null high belt row to use computed sort key, got %v", got)
|
||||||
}
|
}
|
||||||
chestRows := rowsByID(got[1].Rows)
|
chestRows := rowsByID(got[1].Rows)
|
||||||
if got := chestRows[14]["ACBONUS"]; got != "0.00" {
|
if got := chestRows[14]["ACBONUS"]; got != "0.00" {
|
||||||
@@ -10588,8 +10592,9 @@ func TestNormalizePartsRowsACBonusSupportsAscendingRowIDSortKey(t *testing.T) {
|
|||||||
Dataset: nativeDataset{Name: "parts/belt", OutputName: "parts_belt.2da"},
|
Dataset: nativeDataset{Name: "parts/belt", OutputName: "parts_belt.2da"},
|
||||||
Columns: []string{"COSTMODIFIER", "ACBONUS"},
|
Columns: []string{"COSTMODIFIER", "ACBONUS"},
|
||||||
Rows: []map[string]any{
|
Rows: []map[string]any{
|
||||||
{"id": 1, "COSTMODIFIER": "0", "ACBONUS": "****"},
|
{"id": 1, "COSTMODIFIER": "0", "ACBONUS": "0.00"},
|
||||||
{"id": 117, "COSTMODIFIER": "0", "ACBONUS": "****"},
|
{"id": 117, "COSTMODIFIER": "0", "ACBONUS": "0.00"},
|
||||||
|
{"id": 118, "COSTMODIFIER": "0", "ACBONUS": "****"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -10611,6 +10616,9 @@ func TestNormalizePartsRowsACBonusSupportsAscendingRowIDSortKey(t *testing.T) {
|
|||||||
if got := beltRows[117]["ACBONUS"]; got != "1.17" {
|
if got := beltRows[117]["ACBONUS"]; got != "1.17" {
|
||||||
t.Fatalf("expected high belt row to get higher sort key 1.17, got %v", got)
|
t.Fatalf("expected high belt row to get higher sort key 1.17, got %v", got)
|
||||||
}
|
}
|
||||||
|
if got := beltRows[118]["ACBONUS"]; got != "****" {
|
||||||
|
t.Fatalf("expected authored null belt row to remain ****, got %v", got)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rowsByID(rows []map[string]any) map[int]map[string]any {
|
func rowsByID(rows []map[string]any) map[int]map[string]any {
|
||||||
|
|||||||
Reference in New Issue
Block a user