nte-exporter/docs/packet-format.md
Golumpa 20b2086299 Anchor scans to page 1; export stable prefixes
Anchor page-run selection to start at page 1 (select_continuous_run_from_page_1) instead of picking the longest run, so newest pages are preserved and the newest timestamp ordinal 0 is always captured. Change boundary logic to always assign stable UIDs and export the captured prefix of an oldest timestamp group even when it may be an unfinished 10-pull, emitting informational warnings (INCOMPLETE_TIMESTAMP_GROUP_EXPORTED / INCOMPLETE_ARC_10_PULL_EXPORTED) instead of dropping rows. Apply the same policy to Arc groups and update arc group annotation and warnings accordingly. Add a new console module for improved CLI output and update cli, live_capture, adapters, and session code to use the new run selection and console helpers. Update docs, mappings, and tests to reflect the new boundary/export behavior and messaging.
2026-06-11 12:22:34 +01:00

3.5 KiB

Packet Format Notes

This prototype supports separate Monopoly and Arc/Gashapon history decoders.

Monopoly

  • History is fetched over the UDP game connection.
  • Client history-page requests are 45 bytes.
  • History request constant: 4220 / 0x107c.
  • Request selector 4: Lottery_Permanent.
  • Request selector 8: Lottery_LimitedCharacter.
  • Request page cursor: page_number * 4.
  • Normal server responses contain 5 history records.
  • The final page may contain fewer than 5 records.

Decoded fields:

  • roll_result = first u32 / 4
  • roll_result = 0 means Points Gift
  • Some page-first records have a short prefix before the record body. For these, a hidden signed source flag immediately after the visible dice field overrides the visible dice:
    • source_flag = 0 means Points Gift
    • source_flag = -4 means Chase Reward
  • Timestamp is an 8-byte little-endian value
  • unix_seconds = little_endian_u64(timestamp_raw) / 40000000 - 62135596800
  • Reward keys are the reward id string encoded one character per byte as ASCII * 4 with carry chaining into the next byte. The final byte is the pending carry (00 or 01) acting as a terminator, or is omitted. Examples: 98bdc9ad7dd9a5b99501 decodes to fork_vine, 10a58d9539bdc9b585b101 to DiceNormal, c4c0cccc00 to character id 1033. Arc/Gashapon history uses the same scheme at ASCII * 2.
  • The decoder decodes the key to its id string and looks up display metadata in mappings/arcs.json, mappings/characters.json, and mappings/items.json. Unknown rewards still export their decoded id with empty name/rank.

Page and row numbers are research metadata only. They must not be used for permanent dedupe because they shift when new history appears.

Timestamp groups keep all records with the same raw timestamp together for UID ordinal generation. For boundary/group-size detection, only result_type = dice rows count as pull-set members; Points Gift and Chase Reward rows stay in the group but do not increase the dice-only group count.

Pages are anchored to the continuous run starting at page 1 (history always loads page 1 first), so the newest timestamp group's ordinal 0 is always captured. Ordinals are assigned in scan order (newest first), so ordinal 0 of a timestamp group is its newest record and any unseen continuation rows can only append after the captured ones with higher ordinals. Every exported UID is therefore stable. The oldest captured group is the only nuance: if the capture did not reach the true end of history (final page full) and the dice-only count is not a positive multiple of 10, it may be an unfinished 10-pull continuing onto an uncaptured page; its captured prefix is still ordinal-stable, so it is exported and flagged INCOMPLETE_TIMESTAMP_GROUP_EXPORTED so the user knows to scroll further. If page 1 itself was not captured, the run falls back to the longest continuous block and emits DID_NOT_START_AT_PAGE_1.

Arc / Gashapon

  • Arc history uses a separate 34-byte request.
  • Request constant: 2060 / 0x080c.
  • Cursor step: 2.
  • Pool: Arc_MiracleBox.
  • Each response page normally contains 5 records.
  • Arc timestamps use unix_seconds = little_endian_u64(timestamp_raw) / 20000000 - 62135596800.
  • Arc pulls are treated as 10-pull timestamp groups. Like Monopoly, the oldest captured group is exported even if it is a 10-pull the scan stopped mid-way (its captured prefix is ordinal-stable) and flagged INCOMPLETE_ARC_10_PULL_EXPORTED.
  • Arc rows use the same reward_type, reward_id, reward_name, reward_rank, and reward_key_hex fields as Monopoly rows.