diff --git a/openfut-adapter-fifa17/src/fut/non_economy.rs b/openfut-adapter-fifa17/src/fut/non_economy.rs index 5c75324..b484500 100644 --- a/openfut-adapter-fifa17/src/fut/non_economy.rs +++ b/openfut-adapter-fifa17/src/fut/non_economy.rs @@ -24,9 +24,48 @@ pub fn accountinfo_body() -> Value { json!({}) } -/// `GET …/settings` — production oracle returns an empty config list. +/// `GET …/settings` — the FUT client applies this `configs` array via the applier +/// `FUN_18011dc50`, the ONLY writer of the `IS_*` UI gate bytes (each +/// `byte = (field == 1)`). A flag never sent is a gate never opened — which is why +/// Single-Player Seasons/Draft refuse to open while issuing ZERO server requests +/// (`friendlySeasonsEnabled` → slot `[0x16]` → model byte `0x1fd3a` +/// `IS_FRIENDLY_SEASON_ENABLED`; RE-confirmed via pyghidra on CardsDLL). +/// +/// Default (`OPENFUT_FUT_SETTINGS` unset/`off`) is the historical empty baseline. +/// `OPENFUT_FUT_SETTINGS=gates` populates the array. SAFETY: populating it is what +/// makes the applier RUN, and it then writes EVERY gate byte, so the already-live +/// store flags MUST be re-asserted here or enabling Seasons would clear the working +/// Store (those reach the client today via the Blaze FUT_RS4_CONFIG store, not +/// here). Mirrors the audited list in `utas_server.py` `_SETTINGS_KEEP`/`_GATES`. pub fn settings_body() -> Value { - json!({ "configs": [] }) + if std::env::var("OPENFUT_FUT_SETTINGS").as_deref() != Ok("gates") { + return json!({ "configs": [] }); + } + // Already-live store flags re-asserted (pinned to their working state). + const KEEP: &[&str] = &[ + "storeEnabled", + "storeEnabled_JP", + "coinEnabled", + "coinEnabled_JP", + "cardPackStoreEnabled", + "cardPackStoreEnabled_JP", + "pointsPackStoreEnabled", + "tradingEnabled", + ]; + // Mode gates that nothing has ever populated (the point of the change). + const GATES: &[&str] = &[ + "friendlySeasonsEnabled", + "enableDraftMode", + "enableSinglePlayerDraftMode", + "enableOfflineDraftMode", + "tournamentQuitEnabled", + ]; + let configs: Vec = KEEP + .iter() + .chain(GATES.iter()) + .map(|k| json!({ "type": k, "value": 1 })) + .collect(); + json!({ "configs": configs }) } /// `GET …/leaderboards/options` — production oracle (FUT_MODES off) returns an