4d2b8b9be3
Implements the FIFA17 economy WRITER cluster on top of the landed Core
economy authority + host CoreEconomy client + identity/item-shaper infra.
Handlers are pub, unit-tested, and NOT yet routed: classify() and
ROUTE_AUTHORITY are untouched — the classifier barrier is a later single
coherent flip. No stubs; real Core-backed behavior; fail-closed on CoreError.
Pack generator (adapter fut/pack_content.rs):
generate_pack_contents(&PackDef, &mut impl Rng, &[GeneratedCandidate])
-> Vec<GeneratedCard>. Pure, seeded (deterministic), gold-tier split +
special_chance gate as documented OPENFUT PLACEHOLDER policy (Python
open_pack/_pack_body parity note inline). Fail-closed empty on empty pool.
Store/item writers (host economy_store.rs), matching oracle wire shapes:
- handle_store_buy PUT /store/transaction -> purchase_items (debit+mint N)
-> createPackResponse; cancel/unknown/owned_only -> 200 {}; insufficient
-> 461 {reason,credits}; CoreError -> 503.
- handle_pack_open POST /purchased -> owned_only consumes the unopened
entitlement (redeem_entitlement, consume-once); normal packs debit+mint.
- handle_quick_sell{_path,_body} DELETE .../item/<id> + POST /ut/delete/.../item
-> reverse-resolve wire->Core id (SquadWireResolver) -> sell_item ->
{items:[{id}],totalCredits}; not-owned skipped.
Production OwnedItemLookup = CoreItemLookup over CoreAccess.
Market (host market_store.rs / pile_store.rs / market.rs), synthetic-seller:
- MarketStore over sqlx SQLite (WAL-once + busy_timeout=5s + BEGIN IMMEDIATE
for writes, mirroring openfut-core::db). listings(active/reserved/sold/
cancelled), owner-checked cancel, CAS reserve/complete_sale/rollback.
Typed errors NotFound/Sold/Cancelled/WrongOwner/Conflict.
- PileStore: durable pile/location metadata keyed by Core item id.
- handle_market_{list,query,cancel,buy} + handle_move_items. Buy-now =
reserve (CAS) -> balance precheck (461) -> Core purchase_item (mint+debit)
-> complete_sale; any Core failure rolls the reservation back active.
Two concurrent buyers -> exactly one sale + one debit.
Deps (additive): rand 0.8 (adapter+host), sqlx 0.7 sqlite/runtime-tokio (host).
Tests: adapter +7 (pack_content), host +43 (economy_store 20, market/store 23
incl two_reservers_exactly_one_wins, two_buyers_exactly_one_sale_one_debit,
state_survives_reopen, move_persists_across_reopen). All green; clippy
-D warnings clean; rustfmt clean.
25 lines
1.0 KiB
TOML
25 lines
1.0 KiB
TOML
[package]
|
|
name = "openfut-adapter-fifa17"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
license = "MIT"
|
|
description = "FIFA 17 game adapter: Blaze command tables, response bodies and dispatch"
|
|
publish = false
|
|
|
|
[dependencies]
|
|
openfut-protocol-blaze = { path = "../openfut-protocol-blaze" }
|
|
# Reads the bundled fetchClientConfig table (227-243 rows per CFID), which is
|
|
# generated from the Python oracle rather than transcribed by hand. Unlike the
|
|
# protocol crate below it, this crate is ordinary server-side code, so a real
|
|
# JSON parser is the right call — hand-rolling one to preserve a zero-dependency
|
|
# streak would be reinventing a solved problem in the riskiest possible place.
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
# Seeded RNG for the Store pack-content generator (`fut::pack_content`). The
|
|
# generator is pure over an injected `rand::Rng`, so packs are deterministic
|
|
# under a seeded `StdRng` in tests and reproducible in production.
|
|
rand = "0.8"
|
|
|
|
[dev-dependencies]
|
|
# Differential fixtures are JSONL; the runtime dependency already covers it.
|