Schéma replay záznamu

Replay záznam je celá hra jako JSON (průměr ~90 kB). Klient ho sestaví z Player.log MTG Areny (build_replay_record) a pošle jako událost replay_record. Přehrává ho replay_match engine, aby ověřil, že engine reprodukuje skutečnou hru tah po tahu.

Kořen: schema_version, match_id, game_number, turns[]. Každý tah má me a opp (strana hráče), checkpoint (stav po tahu) a counter_events.

Historie verzí

Všechna nová pole jsou aditivní (#[serde(default)]); verze se zvedá při každém novém poli, aby šlo měření podmínit na schema_version >= N (era gate na pole).

Verze Datum Novinka Proč
3 – spell_targets je {kouzlo: [cíle]} Kouzlo s více cíli se zhroutilo na první.
4 23. 9. 2026 attack_ids, id blokerů, spell_mode_choices Seznam jmen neřekne, jestli dva blokeři blokují jednoho útočníka.
5 23. 9. 2026 Play::arrival Jak karta dorazila na bojiště (cast × put × return). cause_object_id to nerozliší.
6 23. 9. 2026 Play::phase Kdy se hrálo (instant po boji, tvor po boji).
7 23. 9. 2026 spell_x_mana, Activation::more_targets X kouzla se hrála s X=0; druhý cíl se hádal.
8 24. 9. 2026 Play::seq, spell_cost_counters Pořadí akcí mezi oběma hráči; volitelná blight cena.
9 26. 9. 2026 Play::step Krok uvnitř fáze (instant po vyhlášení útočníků, ne na začátku boje).
10 4. 10. 2026 spell_mana_sources Čím se platilo za kouzlo (Treasure, mana tvor, pain land). Surové annotation se od 31. 8. do cloudu neposílají, takže replay nevěděl, že soupeř rozbil Treasure místo tapnutí země.

Součástí v9 je také controller u událostí card_played/spell_cast: hru zapíše ke hráči, který kartu ovládá, ne majiteli (soupeř zahrál mou kartu přes Outrageous Robbery).

Co znamenají klíčová pole Play

  • name – karta.
  • arrival – {category, from_zone, affector}: PlayLand, Resolve, Put, Return… a odkud/čím.
  • phase – Phase_Main1, Phase_Combat, Phase_Main2, Phase_Ending…
  • step (v9) – Step_DeclareAttack, Step_DeclareBlock, Step_EndStep… Hlavní fáze krok nemají.
  • seq (v8) – pořadí v celé hře, sdílené oběma hráči.
  • cause_object_id – první zaznamenaný přesun karty za celý její život (není „kdo ji zahrál").

Co záznam neobsahuje

  • Cíl útoku (hráč × planeswalker). Útok na planeswalkera se přehraje jako útok na hráče.
  • Cíle kouzel mířících na hráče – spell_targets uvádí jen permanenty; kouzlo bez cíle znamená hráče.
  • Některé nepoužité platby (např. „pay 1 life" u některých zemí).

Chování starých záznamů

Záznamy se nepřepisují. Přehrávač musí umět všechny verze a nechat pole, která tam nejsou, na výchozích hodnotách. Proto je u měření potřeba vždy říct, z jaké populace verzí číslo pochází.