fix(fifa17): preserve versioned resourceId on the wire (no special->base collapse)
shape_item emitted resourceId/definitionId = asset_id (base), collapsing every versioned (special) card onto its base definition on the /club and squad wire. The dev 32-card fixture is base-only (version 0), so Slice 7 never exposed it; the real profile (1531 versioned cards) did. Fifa17Identity now carries resource_id (= (version<<24)|asset_id, == asset_id for a base card). shape_item emits resourceId/definitionId from resource_id and assetId/cardassetid from asset_id — versioned and base stay distinct. The host resolver populates resource_id from the catalog's reconstructed resource_id (the catalog already parsed version; it was dropped before shaping). Regression test: versioned 117617092 (v7 of asset 176580) shapes resourceId/ definitionId=117617092, assetId/cardassetid=176580. Verified on the real staged /club: 1949 items, wire-id set exact, 0 wire->resourceId mismatches, 0 duplicate-multiplicity mismatches vs the source manifest. adapter 111 + host 24 tests green; clippy -D warnings clean.
This commit is contained in:
@@ -88,6 +88,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000001,
|
item_id: 100000001,
|
||||||
asset_id: 20801,
|
asset_id: 20801,
|
||||||
|
resource_id: 20801,
|
||||||
},
|
},
|
||||||
)]));
|
)]));
|
||||||
let items = vec![item(
|
let items = vec![item(
|
||||||
@@ -155,6 +156,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000002,
|
item_id: 100000002,
|
||||||
asset_id: 158023,
|
asset_id: 158023,
|
||||||
|
resource_id: 158023,
|
||||||
},
|
},
|
||||||
)]));
|
)]));
|
||||||
// Synthetic club "Northgate United" has no FIFA team id.
|
// Synthetic club "Northgate United" has no FIFA team id.
|
||||||
|
|||||||
@@ -52,7 +52,13 @@ pub struct CoreOwnedItem {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Fifa17Identity {
|
pub struct Fifa17Identity {
|
||||||
pub item_id: u32,
|
pub item_id: u32,
|
||||||
|
/// Base FIFA player asset (low 24 bits the client resolves art/name from).
|
||||||
pub asset_id: u32,
|
pub asset_id: u32,
|
||||||
|
/// Full versioned resource id = `(version << 24) | asset_id`. Equals
|
||||||
|
/// `asset_id` for a version-0 base card. This is the wire
|
||||||
|
/// `resourceId`/`definitionId`, kept DISTINCT from `asset_id` so a versioned
|
||||||
|
/// (special) card never collapses onto its base on the wire.
|
||||||
|
pub resource_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supplies the FIFA numeric identity for a Core item. Returning `None` means
|
/// Supplies the FIFA numeric identity for a Core item. Returning `None` means
|
||||||
@@ -80,7 +86,10 @@ fn discard_value(rating: u8) -> i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build one FIFA `_item` object (version byte 0x00 → `resourceId == assetId`).
|
/// Build one FIFA `_item` object. `resourceId`/`definitionId` carry the full
|
||||||
|
/// versioned resource id; `assetId`/`cardassetid` carry the base asset. For a
|
||||||
|
/// version-0 base card these coincide; for a special they differ and MUST NOT
|
||||||
|
/// be collapsed.
|
||||||
///
|
///
|
||||||
/// This is the single source of truth for a player item's on-wire shape; the
|
/// This is the single source of truth for a player item's on-wire shape; the
|
||||||
/// `/club` envelope and squad projection both call it, so their items are
|
/// `/club` envelope and squad projection both call it, so their items are
|
||||||
@@ -104,10 +113,10 @@ pub fn shape_item(
|
|||||||
.collect();
|
.collect();
|
||||||
json!({
|
json!({
|
||||||
"id": id.item_id,
|
"id": id.item_id,
|
||||||
"resourceId": asset,
|
"resourceId": id.resource_id,
|
||||||
"assetId": asset,
|
"assetId": asset,
|
||||||
"cardassetid": asset,
|
"cardassetid": asset,
|
||||||
"definitionId": asset,
|
"definitionId": id.resource_id,
|
||||||
"cardsubtypeid": 0,
|
"cardsubtypeid": 0,
|
||||||
"itemType": "player",
|
"itemType": "player",
|
||||||
"rareflag": 1,
|
"rareflag": 1,
|
||||||
@@ -162,6 +171,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000001,
|
item_id: 100000001,
|
||||||
asset_id: 20801,
|
asset_id: 20801,
|
||||||
|
resource_id: 20801,
|
||||||
},
|
},
|
||||||
&ent,
|
&ent,
|
||||||
);
|
);
|
||||||
@@ -193,6 +203,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000030,
|
item_id: 100000030,
|
||||||
asset_id: 101490,
|
asset_id: 101490,
|
||||||
|
resource_id: 101490,
|
||||||
},
|
},
|
||||||
&ent,
|
&ent,
|
||||||
);
|
);
|
||||||
@@ -201,6 +212,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000031,
|
item_id: 100000031,
|
||||||
asset_id: 101490,
|
asset_id: 101490,
|
||||||
|
resource_id: 101490,
|
||||||
},
|
},
|
||||||
&ent,
|
&ent,
|
||||||
);
|
);
|
||||||
@@ -215,4 +227,25 @@ mod tests {
|
|||||||
assert_eq!(a["id"], 100000030);
|
assert_eq!(a["id"], 100000030);
|
||||||
assert_eq!(b["id"], 100000031);
|
assert_eq!(b["id"], 100000031);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn versioned_special_keeps_resourceid_distinct_from_assetid() {
|
||||||
|
// A versioned (special) card: resourceId/definitionId carry the full
|
||||||
|
// versioned id; assetId/cardassetid stay the base asset. They MUST NOT
|
||||||
|
// collapse. (resource 117617092 = version 7 of asset 176580.)
|
||||||
|
let ent = entities();
|
||||||
|
let it = shape_item(
|
||||||
|
&item("oc-v", "fifa17_117617092", 92, "ST"),
|
||||||
|
Fifa17Identity {
|
||||||
|
item_id: 100000384,
|
||||||
|
asset_id: 176580,
|
||||||
|
resource_id: 117617092,
|
||||||
|
},
|
||||||
|
&ent,
|
||||||
|
);
|
||||||
|
assert_eq!(it["resourceId"], 117617092, "versioned resource id on the wire");
|
||||||
|
assert_eq!(it["definitionId"], 117617092);
|
||||||
|
assert_eq!(it["assetId"], 176580, "base asset id preserved");
|
||||||
|
assert_eq!(it["cardassetid"], 176580);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000042,
|
item_id: 100000042,
|
||||||
asset_id: 20801,
|
asset_id: 20801,
|
||||||
|
resource_id: 20801,
|
||||||
},
|
},
|
||||||
)]));
|
)]));
|
||||||
let input = one_slot_input(&owned, SquadExtInput::Fresh(fresh_ext()));
|
let input = one_slot_input(&owned, SquadExtInput::Fresh(fresh_ext()));
|
||||||
@@ -359,6 +360,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000030,
|
item_id: 100000030,
|
||||||
asset_id: 101490,
|
asset_id: 101490,
|
||||||
|
resource_id: 101490,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@@ -366,6 +368,7 @@ mod tests {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: 100000031,
|
item_id: 100000031,
|
||||||
asset_id: 101490,
|
asset_id: 101490,
|
||||||
|
resource_id: 101490,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]));
|
]));
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ fn oracle_tables() -> (HashMap<String, CoreOwnedItem>, TableIdentity) {
|
|||||||
Fifa17Identity {
|
Fifa17Identity {
|
||||||
item_id: wire as u32,
|
item_id: wire as u32,
|
||||||
asset_id: asset,
|
asset_id: asset,
|
||||||
|
resource_id: asset,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,6 +551,7 @@ impl ItemIdentityResolver for Fifa17IdentityResolver {
|
|||||||
// Wire ids live in 1e8..9e8 (policy) — well within u32.
|
// Wire ids live in 1e8..9e8 (policy) — well within u32.
|
||||||
item_id: wire as u32,
|
item_id: wire as u32,
|
||||||
asset_id: ident.asset_id,
|
asset_id: ident.asset_id,
|
||||||
|
resource_id: ident.resource_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user