Fix NPE when restoring a snapshot taken before a card was created - #11416
Fix NPE when restoring a snapshot taken before a card was created#11416cuinhellcat wants to merge 1 commit into
Conversation
GameSnapshot.copyGameState() puts the snapshot's cards back into the running game, but never removes cards the running game has and the snapshot does not: tokens, copies and effect cards that came into being after the snapshot was taken. The loop restoring attachments then walks the battlefield, looks every card up in the snapshot via findById, and dereferences the null it gets back for those cards. Rolling back a cancelled cast does not hit this, because it creates no new objects, but any restore reaching back past the creation of a token or a copy throws. Remove those cards from the game while restoring, which is what going back to a state in which they did not exist means. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Hallo 👋 FYI there's already a PR related to your experiment: #10294 |
I have no problem in being just a bill payer (I have this subscription and I can use some of my contingent for this project.) As long as copy pasting helps, I will do it. But I totally understand your point. I will switch to testing, what claude code did and only post here, if tests work on my end... If I cause trouble, I will immediately step back. Just tell me to stop, I will do so. |
Problem
GameSnapshot.copyGameState()copies the snapshot's cards back into the running game, but it never removes cards that the running game has and the snapshot does not — tokens, copies and effect cards that were created after the snapshot was taken.The loop that restores attachments afterwards iterates the current battlefield and looks every card up in the snapshot:
For a card the snapshot does not know,
findByIdreturnsnulland the next line throws.Interestingly
assignGameStatealready anticipates such cards a few lines further down — it prints"Missing card " + cand continues — but by thencopyGameStatehas already thrown.When it shows up
Not in the current use of snapshots: rolling back a cancelled cast (
GameActionUtil.rollbackAbility) creates no new objects, so every card on the battlefield is also in the snapshot. Any restore that reaches back past the creation of a token or a copy throws instead — which is what happens as soon as snapshots are used to step further back than the action in progress.Fix
Remove those cards from the game as part of the restore. Returning to a state in which they did not exist is exactly what a restore means, and it also gives the
"Missing card"branch below nothing left to report.Notes
master;forge-gamecompiles clean.AI disclosure
Written with Claude Code (Claude Opus 5), as requested in CONTRIBUTING; the agent is also recorded as co-author on the commit.