FIFA's updateActiveSquad PUT stores each slot as itemData={id:<clubItemId>}
(a reference), not the full player. We saved the bare references, so the
squad reloaded empty ("active squad resets"). Add Store.reconstruct_squad()
to re-embed the full club item by id on GET /squad/0, so the saved squad
reloads with its real players.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
store/transaction receives {"state":"TRANSACTIONCANCEL"} (cancel/close)
and {"packId":N} (pack-details fetch on store load) -- neither is a
confirmed purchase. The handler treated packId as a buy and even
defaulted to opening a Gold Pack on cancels, silently spending coins.
Make store_buy a safe no-op that logs every body, so the real
purchase-CONFIRM signal can be identified from a deliberate in-game buy
and open_pack() gated on exactly that. Save restored on next fresh run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
Add a first-cut FUT store on top of the persistent profile:
- fut_store: PACK_CATALOG (Bronze/Gold/Premium), a curated real-player
PACK_POOL, and open_pack() (deduct coins -> generate items -> add to
club -> persist).
- utas_server routes: GET store/purchasegroup/all (catalog), PUT
(v2) store/transaction (buy + open, returns awarded itemData +
updated coins), GET purchased (last pack). Matches both /ut/game and
/ut/v2/game prefixes.
Verified via curl: buy Gold Pack -> 7 real players awarded, coins
15000->10000, club 10->17, persisted. Wire format is a best-guess
grounded in the CardsDLL store keys (packId/price/itemData/coins);
iterate against the in-game store next. Pool is curated for now --
replace with a full dbdata.dll extract later.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
Add fut_store.py: a JSON-backed profile store (coins, owned club items,
saved squads, record). First run grants a starter pack -- 15000 coins +
a 10-player starter club (real assetIds; identity resolves locally
in-game per docs/CARD_SYSTEM.md).
Wire utas_server to the store: /user/credits -> persisted coins,
/club -> persisted owned items, PUT /squad -> persists the squad the
user builds so it survives relaunches. Profile save file is gitignored.
Foundation for pack-opening (store/purchasegroup + transaction) next.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
Milestone: FIFA 17 Ultimate Team boots end-to-end on our offline backend
past every EA gate into the hub and a live Squads editor (correct 4-4-2,
5-star squad, no freezes).
Key findings this session:
- userMassInfo MUST stay {} (any content desyncs the massinfo parser
0x180174630 -> tokenizer busy-loop freeze). Deliver the squad via
GET /squad/0 (fetched on Squads-tab entry) instead.
- Player cards render generic because the card view-model (0x1800d7920)
reads identity/rating/face from a resolved record at item+0x10, filled
by a lookup (0x18011cca0) in the FUT item-definition std::map at
CardsDb+0x160c0 -- which is EMPTY offline -> default blank record.
- Version advertising (itemDbVersion/checkServerDbVersion) is proven inert
(JSON fields routed to the skip handler). Owned items don't auto-trigger
a definition fetch. In-place map overwrite is dead (map stays empty).
- Definition-serving endpoints (item/resource, defid, item?idList) built +
ready; the fetch trigger lives in the packed FIFA17.exe.
New: docs/CARD_SYSTEM.md (findings + ordered next-steps plan for real
player cards: patch-POC, dbdata extractor, drive FIFA17.exe fetch, or
live-memory store injection). Plus tools: fut_seed.py (squad ladder +
definition serving), fifadrive.sh, vgamepad.py, and the login-RE toolset.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
Emulates FIFA 17's full online + Ultimate Team stack against an offline,
clean-room backend (no EA servers). Proven end-to-end 2026-08-01:
Origin login -> Blaze login -> device-trust -> the FUT hub.
Package:
- tools/openfut-fut.sh one-command orchestrator (start/stop/status/restart)
- tools/root_arm.sh idempotent host arm (sysctls, DNAT, /etc/hosts easw)
- tools/{lsx_responder_v2,blaze_responder_v3b,roster_server,utas_server,autopatch}.py
the 5 servers (Origin LSX :4216, Blaze :42127/42130/42131, roster :8081,
FUT/UTAS :8099) + heat2.py (Fire2/Heat2 TDF codec)
- FUT-RUNBOOK.md runbook + gate-ladder troubleshooting
- docs/, tools/login_dump/*.md the reverse-engineering write-ups
All findings are clean-room, from binaries we own; nothing from any leak.
The wire protocol maps 1:1 to FIFA 23.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o