From 629813b58030a86f935a5b5d3f7d1bbdb9edd2df Mon Sep 17 00:00:00 2001 From: funman300 Date: Sun, 2 Aug 2026 17:15:41 -0700 Subject: [PATCH] fifa17-recon: transfer market read routes (empty-but-valid) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add auctionhouse/trade/tradePile/watchList/marketdata routes per ENDPOINT_MAP market §. All share the reversed IS-list body {auctionInfo:[], credits, total, duplicateItemIdList} (shared deser 0x18013e7f0). Served EMPTY (no live listings yet) -- empty arrays never desync the SAX reader, so freeze-safe; unlocks the market screens vs the prior catch-all {}. GET auctionhouse merges the FutGetAuctionCount ints (extra keys skip). POST auctionhouse = FutISStart new tradeId; PUT relist / watch add-remove / delete = acks. tradePile precedes /trade (prefix collision). Populating real auctions deferred to in-game test. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o --- fifa17-recon/tools/utas_server.py | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/fifa17-recon/tools/utas_server.py b/fifa17-recon/tools/utas_server.py index 25cf9b0..59909ca 100755 --- a/fifa17-recon/tools/utas_server.py +++ b/fifa17-recon/tools/utas_server.py @@ -183,6 +183,15 @@ ROUTES = [ # STEP 1 (wf_0bc80ab3): zero-resolve squad in MASSINFO; club stays {}. (re.compile(G + r"/userMassInfo"), lambda m, h: (200, MASSINFO)), (re.compile(G + r"/season"), lambda m, h: (200, {})), + # ---- transfer market / auction house (empty-but-valid; ENDPOINT_MAP market §) + # tradePile MUST precede /trade ("/tradePile" contains the "/trade" prefix). + (re.compile(G + r"/tradePile"), lambda m, h: tradepile_route(h)), + (re.compile(G + r"/trade"), lambda m, h: trade_route(h)), + (re.compile(G + r"/watchList"), lambda m, h: watchlist_route(h)), + (re.compile(G + r"/auctionhouse"), lambda m, h: auctionhouse_route(h)), + (re.compile(G + r"/marketdata"), lambda m, h: (200, {"minPrice": 150, "maxPrice": 15000})), + (re.compile(r"/ut/delete/game/[^/]+/trade"), lambda m, h: (200, {})), + (re.compile(r"/ut/delete/game/[^/]+/watchList"), lambda m, h: (200, {})), (re.compile(G + r"/club"), lambda m, h: (200, {"itemData": STORE.items()})), ] @@ -301,6 +310,50 @@ def credits_route(h): } +# ---- TRANSFER MARKET / AUCTION HOUSE (ENDPOINT_MAP market §) ---------------- +# Every list response shares one body: {auctionInfo:[record], credits, total, +# duplicateItemIdList} (shared deser 0x18013e7f0). auctionInfo + dupIdList MUST be +# ARRAYS and each record.itemData MUST be a card OBJECT, or the SAX reader desyncs +# -> busy-loop freeze at 0x1801c7f1a. We serve an EMPTY-but-valid market (no live +# listings yet): empty arrays never desync, so this is freeze-safe. Populating real +# auctions needs an in-game test pass. Extra keys are SKIP'd, so one merged body +# safely satisfies both the search parser and the auction-count parser. +def _market_body(): + return {"auctionInfo": [], "credits": STORE.coins(), "total": 0, + "duplicateItemIdList": []} + + +def auctionhouse_route(h): + # GET = search (empty results) OR count -> merged body (extra keys skip) + # POST = FutISStart (list item for sale) -> {"id": new tradeId} + # PUT = .../relist (relist all expired) -> ack {} + if h.command == "POST": + return 200, {"id": STORE.new_item_id()} + if h.command == "PUT": + return 200, {} + body = _market_body() + body.update({"count": 0, "maxAuctionsAllowed": 100, + "offered": 0, "selling": 0, "sold": 0}) # FutGetAuctionCount ints + return 200, body + + +def trade_route(h): + # GET view one auction / POST place bid -> {auctionInfo:[record], credits} + return 200, {"auctionInfo": [], "credits": STORE.coins()} + + +def tradepile_route(h): + b = _market_body(); b.pop("duplicateItemIdList", None) + return 200, b # {auctionInfo, credits, total} + + +def watchlist_route(h): + if h.command in ("PUT", "POST", "DELETE"): + return 200, {} # add/remove watch -> ack + b = _market_body(); b.pop("duplicateItemIdList", None) + return 200, b + + class H(http.server.BaseHTTPRequestHandler): protocol_version = "HTTP/1.1"