two results this round, both negative and both useful.
the account ids are right end to end, so isOwnedByBottomPlayer picks the
branch it should. and every character row carries the export names it
needs - knight, goblin and barbarian all have a filename, a blue and a
red prefix and UseAnimator set - so neither "empty prefix" nor "wrong
row" survives. Debugger::error is __noreturn, and the client does not
abort, so Character::Character is not failing to build animations
either: reached, it works.
with the checksum agreeing byte for byte, the objects in the client are
identical to ours. that leaves only the sprite never being made, or
being made and torn down again - and every push re-runs decode, which
destroys whatever it cannot match. five times a second nothing would
ever be seen. SCROLL_SNAPSHOT_INTERVAL_TICKS widens the gap so one run
can tell.