a2bd048ace
PHASE A settled the token from the CLIENT ITSELF, so this is not a guessed enum.
vocab_dump.py (new; static, read-only, VA->offset through the real PE section table)
dumps CardsDLL's NULL-terminated {const char*, int} vocabularies. The tradeState
table at 0x180229e40 reads exactly:
'active' = 1 'inactive' = 2 'expired' = 3 'closed' = 4
The sibling tables (type/zone/lev/pos) match the corpus verbatim, which validates the
dumper. So "inactive" is a token the client's own parser decodes.
PHASE B, bounded as instructed. `OPENFUT_FIFA17_UNLISTED_PROBE=<wire id>` exposes
EXACTLY ONE unlisted trade-pile item on /tradePile as a non-active record; unset,
behaviour is byte-identical to before. The other stranded pile items are untouched --
no bulk migration.
Why this shape is forced rather than chosen: the route table has exactly one
trade-pile route, it carries only twelve-atom auction records, `pile` (0x226) has no
deserializer arm so membership comes from the owning list, and of those atoms only
tradeState expresses lifecycle. The row carries tradeState "inactive" with
expires/prices/bid all zero so it cannot render a countdown or a price, and reuses the
item's stable tradeId because the client keys its record store on tradeId and
re-parents itemData -- so listing the item later UPDATES the row instead of leaving a
duplicate ghost.
Both preconditions are re-checked at response time: the item must actually be in the
`trade` pile, and it must not already own a listing. Two tests cover exactly those.
counts semantics deliberately unchanged -- the inactive row is not counted.
340 tests pass, 0 failed, clippy clean. Deployed; the wire now carries all three
lifecycle states at once (expired 1000000097, active 1000000155, inactive 1000000059)
and that body is preserved as a fixture.
191 lines
4.0 KiB
JSON
191 lines
4.0 KiB
JSON
{
|
|
"auctionInfo": [
|
|
{
|
|
"bidState": "none",
|
|
"buyNowPrice": 15000,
|
|
"coinsProcessed": 0,
|
|
"currentBid": 0,
|
|
"expires": 0,
|
|
"itemData": {
|
|
"assetId": 20801,
|
|
"attributeList": [
|
|
{
|
|
"index": 0,
|
|
"value": 92
|
|
},
|
|
{
|
|
"index": 1,
|
|
"value": 92
|
|
},
|
|
{
|
|
"index": 2,
|
|
"value": 81
|
|
},
|
|
{
|
|
"index": 3,
|
|
"value": 91
|
|
},
|
|
{
|
|
"index": 4,
|
|
"value": 33
|
|
},
|
|
{
|
|
"index": 5,
|
|
"value": 80
|
|
}
|
|
],
|
|
"cardassetid": 20801,
|
|
"cardsubtypeid": 0,
|
|
"contract": 7,
|
|
"definitionId": 20801,
|
|
"discardValue": 1500,
|
|
"fitness": 99,
|
|
"id": 100000097,
|
|
"itemState": "listFS",
|
|
"itemType": "player",
|
|
"leagueId": 53,
|
|
"nation": 38,
|
|
"owners": 1,
|
|
"playStyle": 250,
|
|
"preferredPosition": "LW",
|
|
"rareflag": 1,
|
|
"rating": 94,
|
|
"resourceId": 20801,
|
|
"teamid": 243,
|
|
"untradeable": false
|
|
},
|
|
"sellerEstablished": 1,
|
|
"sellerName": "CAGE",
|
|
"startingBid": 150,
|
|
"tradeId": 1000000097,
|
|
"tradeState": "expired",
|
|
"watched": false
|
|
},
|
|
{
|
|
"bidState": "none",
|
|
"buyNowPrice": 15000,
|
|
"coinsProcessed": 0,
|
|
"currentBid": 0,
|
|
"expires": 2996,
|
|
"itemData": {
|
|
"assetId": 158023,
|
|
"attributeList": [
|
|
{
|
|
"index": 0,
|
|
"value": 89
|
|
},
|
|
{
|
|
"index": 1,
|
|
"value": 90
|
|
},
|
|
{
|
|
"index": 2,
|
|
"value": 86
|
|
},
|
|
{
|
|
"index": 3,
|
|
"value": 96
|
|
},
|
|
{
|
|
"index": 4,
|
|
"value": 26
|
|
},
|
|
{
|
|
"index": 5,
|
|
"value": 61
|
|
}
|
|
],
|
|
"cardassetid": 158023,
|
|
"cardsubtypeid": 0,
|
|
"contract": 7,
|
|
"definitionId": 158023,
|
|
"discardValue": 1500,
|
|
"fitness": 99,
|
|
"id": 100000155,
|
|
"itemState": "listFS",
|
|
"itemType": "player",
|
|
"leagueId": 53,
|
|
"nation": 52,
|
|
"owners": 1,
|
|
"playStyle": 250,
|
|
"preferredPosition": "RW",
|
|
"rareflag": 1,
|
|
"rating": 93,
|
|
"resourceId": 158023,
|
|
"teamid": 241,
|
|
"untradeable": false
|
|
},
|
|
"sellerEstablished": 1,
|
|
"sellerName": "CAGE",
|
|
"startingBid": 150,
|
|
"tradeId": 1000000155,
|
|
"tradeState": "active",
|
|
"watched": false
|
|
},
|
|
{
|
|
"bidState": "none",
|
|
"buyNowPrice": 0,
|
|
"coinsProcessed": 0,
|
|
"currentBid": 0,
|
|
"expires": 0,
|
|
"itemData": {
|
|
"assetId": 158023,
|
|
"attributeList": [
|
|
{
|
|
"index": 0,
|
|
"value": 89
|
|
},
|
|
{
|
|
"index": 1,
|
|
"value": 90
|
|
},
|
|
{
|
|
"index": 2,
|
|
"value": 86
|
|
},
|
|
{
|
|
"index": 3,
|
|
"value": 96
|
|
},
|
|
{
|
|
"index": 4,
|
|
"value": 26
|
|
},
|
|
{
|
|
"index": 5,
|
|
"value": 61
|
|
}
|
|
],
|
|
"cardassetid": 158023,
|
|
"cardsubtypeid": 0,
|
|
"contract": 7,
|
|
"definitionId": 158023,
|
|
"discardValue": 1500,
|
|
"fitness": 99,
|
|
"id": 100000059,
|
|
"itemState": "free",
|
|
"itemType": "player",
|
|
"leagueId": 53,
|
|
"nation": 52,
|
|
"owners": 1,
|
|
"playStyle": 250,
|
|
"preferredPosition": "RW",
|
|
"rareflag": 1,
|
|
"rating": 93,
|
|
"resourceId": 158023,
|
|
"teamid": 241,
|
|
"untradeable": false
|
|
},
|
|
"sellerEstablished": 1,
|
|
"sellerName": "CAGE",
|
|
"startingBid": 0,
|
|
"tradeId": 1000000059,
|
|
"tradeState": "inactive",
|
|
"watched": false
|
|
}
|
|
],
|
|
"credits": 29843976,
|
|
"duplicateItemIdList": [],
|
|
"total": 3
|
|
}
|