//! # 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. //! //! Still served only by the Python backend, each a separate future module: //! the redirector (HTTPS + XML `getServerInstance`), the Nucleus OAuth stub, //! LSX/Origin (`:4216`), roster XML (`:8081`), UTAS/RS4 (`:8099`) and POW/EASFC //! (`:8094`). //! //! ## 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::default()); //! 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 use blaze::{Adapter, AdapterConfig, Session};