fifa17-recon: correct tradePile/counts shape, and narrow the marketdata array fix
Two follow-ups on the working transfer market.
1. GET /tradePile/counts now returns the FutGetAuctionCount shape
({count, maxAuctionsAllowed, offered, selling, sold}, all scalar ints, atoms
0xbc/0x1bf/0x1e5/0x2b8/0x2c9) via a dedicated route ordered before /tradePile.
Previously it fell through to tradepile_route and got the auction-LIST body, which
the counts deser skips, leaving every tally at its constructor default. Survivable
but wrong; the doc flags the loaded byte at +0x28 as gating a completion-handler
branch. selling reflects real STORE.listings().
2. Narrowed the marketdata bare-array fix to /pricelimits only. The client sends TWO
marketdata requests: /marketdata/pricelimits (GetSuggestedPricing, a bare array,
the thing that froze) and plain /marketdata?defId=N (price comparison, an OBJECT).
The prior commit returned the array for both, which the contract suite caught
(test_market_bodies: 'list' has no attribute get) -- plain /marketdata wants
{minPrice,maxPrice} and was never the freeze. Returning the array for it would be
the same desync in reverse. Now: pricelimits -> array, plain marketdata -> object.
The contract suite catching my over-broadened fix before it reached the game is the
suite doing its job. 439 contract checks pass, market unit suite passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -673,7 +673,15 @@ def marketdata_route(h):
|
||||
pricing is a later refinement, not a freeze concern.
|
||||
"""
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
q = parse_qs(urlparse(h.path).query)
|
||||
parsed = urlparse(h.path)
|
||||
# ONLY /marketdata/pricelimits is the bare-array GetSuggestedPricing. Plain
|
||||
# /marketdata?defId=N is a DIFFERENT endpoint (price comparison) that takes an
|
||||
# OBJECT: it was served {minPrice,maxPrice} in the frozen session and did NOT
|
||||
# freeze, so it wants an object, not the array. Returning the array for it would
|
||||
# be the same object-vs-array desync in reverse. Keep them distinct.
|
||||
if not parsed.path.endswith("/pricelimits"):
|
||||
return 200, {"minPrice": 150, "maxPrice": 15000}
|
||||
q = parse_qs(parsed.query)
|
||||
raw = q.get("defId", [""])[0]
|
||||
ids = [int(x) for x in raw.split(",") if x.strip().isdigit()]
|
||||
return 200, [{"defId": d, "minPrice": 150, "maxPrice": 15000} for d in ids]
|
||||
@@ -1147,6 +1155,9 @@ ROUTES = [
|
||||
(re.compile(G + r"/activeMessage"), lambda m, h: (200, {})),
|
||||
# ---- transfer market / auction house (empty-but-valid; ENDPOINT_MAP market §)
|
||||
# tradePile MUST precede /trade ("/tradePile" contains the "/trade" prefix).
|
||||
# /tradePile/counts (GetAuctionCount) MUST precede /tradePile: the latter's regex
|
||||
# also matches the /counts path, and the two responses are different shapes.
|
||||
(re.compile(G + r"/tradePile/counts"), lambda m, h: auction_counts_route(h)),
|
||||
(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)),
|
||||
@@ -2959,6 +2970,22 @@ def watchlist_route(h):
|
||||
return 200, {"auctionInfo": [], "credits": STORE.coins(), "total": 0}
|
||||
|
||||
|
||||
def auction_counts_route(h):
|
||||
"""GET tradePile/counts -- FutGetAuctionCount (deser 0x180163770). Distinct from
|
||||
/tradePile: this is the auction TALLY, not the listing list. Until now it fell
|
||||
through to tradepile_route and got {auctionInfo,...}, which the counts deser skips,
|
||||
leaving every count at its constructor default. Survivable but wrong.
|
||||
|
||||
All five fields are scalar ints (count 0xbc, maxAuctionsAllowed 0x1bf, offered
|
||||
0x1e5, selling 0x2b8, sold 0x2c9), so there is no container-type freeze risk.
|
||||
They are the only inputs to IS_MAX_AUCTIONS (FUN_1800377c0 = !(max<0 || cur<max));
|
||||
maxAuctionsAllowed 100 with selling < 100 keeps the cap open.
|
||||
"""
|
||||
n = len(STORE.listings())
|
||||
return 200, {"count": n, "maxAuctionsAllowed": 100,
|
||||
"offered": 0, "selling": n, "sold": 0}
|
||||
|
||||
|
||||
class H(http.server.BaseHTTPRequestHandler):
|
||||
protocol_version = "HTTP/1.1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user