//! # openfut-adapter-fifa17 //! //! The FIFA 17 game adapter: everything that is true of *FIFA 17 specifically* //! and must therefore stay out of OpenFUT Core and out of the generic protocol //! crates. //! //! ## Layering //! //! ```text //! openfut-protocol-blaze generic Blaze: Fire2 framing, Heat2/TDF codec //! ▲ //! openfut-adapter-fifa17 THIS: FIFA 17 command tables, response bodies, //! ▲ dispatch ordering, session identity //! OpenFUT Core game-independent FUT domain (not yet wired) //! ``` //! //! A second title gets its own adapter crate and reuses the protocol layer //! underneath. Nothing here is written to be shared with one; if something in //! this crate turns out to be title-independent, it belongs one layer down. //! //! ## Modules //! //! * [`blaze`] — the Blaze/Fire2 RPC surface. Implemented, runtime validated. //! * [`redirector`] — the first hop's `` response. //! Implemented; runtime validated against the retail client. //! * [`roster`] — the FUT roster-update response, the last gate before the hub. //! Implemented; not yet runtime validated. //! * [`fut`] — FUT/RS4 (UTAS) wire → Core semantic mappings; currently the //! owned-player ("My Squad") search: query parse + FIFA-id→name resolution + //! semantic filter/pagination. Pure mapping; no Rust UTAS host yet. //! //! Still served only by the Python backend: LSX/Origin (`:4216`), UTAS/RS4 //! (`:8099`) and POW/EASFC (`:8094`). Roster XML (`:8081`) has an adapter here //! but no Rust host yet. //! //! **Nucleus (`:42131`) is deliberately not ported.** Instrumentation across //! every live session showed the client never dials it: the listener is bound, //! the handler logs unconditionally on connect, the client fetches the //! `OSDK_NUCLEUS` config that carries the URL — and makes zero requests. It is //! dead code on the observed path, so porting it would add an untested //! component for no parity gain. See the vault's Protocol Findings. //! //! ## Provenance //! //! Ported from `fifa17-recon/tools/blaze_responder_v3b.py`, the implementation //! that drove a retail FIFA 17 client from Origin login to an opened FUT pack. //! Parity is tested, not asserted: `fixtures/blaze_transactions.jsonl` records //! real request→response(s) transactions produced by the Python dispatcher, and //! `tests/oracle_parity.rs` replays them byte-for-byte. //! //! ## Not a server //! //! This crate answers frames. It opens no socket, terminates no TLS and owns no //! runtime. Hosting it is a separate, later decision — the Python backend //! remains the live runtime and nothing here is wired into it. //! //! ``` //! use openfut_adapter_fifa17::blaze::{Adapter, AdapterConfig, Session}; //! use openfut_protocol_blaze::fire2::{Header, MsgType}; //! use openfut_protocol_blaze::heat2::Struct; //! //! let adapter = Adapter::new(AdapterConfig::loopback()); //! let mut session = Session::new("session-key", 0x656E5553); //! //! // Util::ping //! let request = Header::new(0x0009, 0x0002, 1, MsgType::Message); //! let out = adapter.dispatch(&request, &Struct::new(), &mut session, 1_754_870_400); //! //! assert_eq!(out.len(), 1); //! assert_eq!(out[0].header.msg_type, MsgType::Reply); //! ``` pub mod blaze; pub mod fut; pub mod redirector; pub mod roster; pub mod tls; pub use blaze::{Adapter, AdapterConfig, Session};