feat(fifa17): gated kits-only club?type=equippables, to test the locked-kit cause
A live kit_trace run on the retail client showed the kit clone driver only ever sees PLAYERS - about 19 records, all cardtype 1 / itemState 1 / +0x60 = 1 - and never a kit, with no KIT_DBCLONE line at all. So the locked-kit failure is UPSTREAM of the item+0x60 == 4 gate that this arm's comment blamed. In the same session the client asked for ?type=kit six times, which we answer and which feeds the items browser, and ?type=equippables twice, which we answer empty. If the equippable view is what populates the collection FUN_1800d73d0 scans to build the active-kit triple, an empty answer explains precisely why the triple stays zero and the engine falls back to its own catalogue kit. The arm now selects ContentKind::Kit behind OPENFUT_FIFA17_EQUIPPABLES=1, so it answers with TWO items rather than the thirty across five families that crashed the client on 2026-08-05. Default OFF: that crash is real and reproducible, and the narrow body is a hypothesis under test rather than an established safe response. Reverting is an env change plus a restart, no rebuild.
This commit is contained in:
@@ -2316,12 +2316,30 @@ fn club_type_filter(token: Option<&str>) -> Option<ClubTypeFilter> {
|
||||
label: "equippables",
|
||||
// The combined customisation view, and the one response that has ever
|
||||
// crashed this client: 30 items across five families at once
|
||||
// (2026-08-05). A single-family answer here is not available either —
|
||||
// the view is by definition multi-family — and the kit swap it feeds
|
||||
// needs `item+0x60 == 4`, which a server can never produce (it can
|
||||
// only ever produce 1 = club and 6 = purchased). So this stays empty
|
||||
// until that is a client-side change, not a wire one.
|
||||
selector: ClubSelector::Withheld("multi_family_crash_2026_08_05"),
|
||||
// (2026-08-05).
|
||||
//
|
||||
// 2026-08-24: this is also the prime suspect for the LOCKED kit. A
|
||||
// live `kit_trace` run showed the kit clone driver only ever sees
|
||||
// PLAYERS (~19 records, cardtype 1 / itemState 1 / `+0x60` 1) and
|
||||
// never a kit, with no `KIT_DBCLONE` at all — so the failure is
|
||||
// upstream of the `item+0x60 == 4` gate. In the same session the
|
||||
// client asked for `?type=kit` (6x, which we answer and which feeds
|
||||
// the items BROWSER) and `?type=equippables` (2x, which we answer
|
||||
// empty). If the equippable view is what populates the collection
|
||||
// `FUN_1800d73d0` scans for the active-kit triple, an empty answer
|
||||
// is exactly why the triple stays zero and the engine falls back to
|
||||
// its own catalogue kit.
|
||||
//
|
||||
// So the arm is now selectable behind `OPENFUT_FIFA17_EQUIPPABLES=1`
|
||||
// and answers with KITS ONLY — two items, not the thirty across five
|
||||
// families that crashed the client. Default OFF: the crash is real
|
||||
// and reproducible, and this narrower body is a hypothesis under
|
||||
// test, not an established safe response.
|
||||
selector: if equippables_enabled() {
|
||||
ClubSelector::Kind(ContentKind::Kit)
|
||||
} else {
|
||||
ClubSelector::Withheld("multi_family_crash_2026_08_05")
|
||||
},
|
||||
},
|
||||
Some("leaguelogos") => ClubTypeFilter {
|
||||
label: "leaguelogos",
|
||||
@@ -5571,6 +5589,18 @@ fn discard_table_enabled() -> bool {
|
||||
*ENABLED.get_or_init(|| std::env::var("OPENFUT_FIFA17_DISCARD_TABLE").as_deref() == Ok("1"))
|
||||
}
|
||||
|
||||
/// Answer `club?type=equippables` with a KITS-ONLY body.
|
||||
///
|
||||
/// Default OFF. The multi-family form of this response crashed the client on
|
||||
/// 2026-08-05, so serving it at all is an experiment: the narrow two-kit body is
|
||||
/// a hypothesis about why the pre-match kit selector reports every kit locked,
|
||||
/// not a response we have established as safe. Flip the env var off to revert
|
||||
/// with a restart and no rebuild.
|
||||
fn equippables_enabled() -> bool {
|
||||
static ENABLED: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
|
||||
*ENABLED.get_or_init(|| std::env::var("OPENFUT_FIFA17_EQUIPPABLES").as_deref() == Ok("1"))
|
||||
}
|
||||
|
||||
/// A JSON response with an explicit status.
|
||||
fn json_status(status: u16, v: &Value) -> WireResponse {
|
||||
let body = serde_json::to_vec(v).unwrap_or_default();
|
||||
|
||||
Reference in New Issue
Block a user