Essentially the idea here is not to muck about with diffs or event / command based sourcing.<p>Just store each internal state you might want to recover, in full. Except use compression to store the states you want to recover. In this article, the compression is done based on the 'initial state'. I imagine there is flexibility on maybe 'checkpointing' some states once the difference becomes to big. Maybe do the compression not with a prefix of the 'initial' state but with a prefix of the entire undo history.<p>All this requires is halfway efficient serialization / deserialization implementation, and access to Zstandard (I guess other compression algorithms also work).<p>I think the key trick here is that, if you can serialize to bytes, you can just use compression methods as a replacement for storing diffs or other complicated methods for de-duplicating data. This could be a really powerful method to really easily keep a state history without high performance cost.
From the developer p.o.v. its like you have each previous state at your fingertips. Whilst in reality the compression ensures it is stored efficiently.
It is interesting to compare this to Jonathan Blow's talk on the rewind system in Braid [1].<p>This stores complete game states using a compression library to keep memory under control, whereas Braid stored a combination of keyframes, and diffs from those keyframes, to avoid using a compression library.<p>[1] <a href="https://www.youtube.com/watch?v=8dinUbg2h70" rel="nofollow">https://www.youtube.com/watch?v=8dinUbg2h70</a>
This is the design I also usually use for undo/redo. Actually for small interactive editors I like to go further and make it so that anytime you do anything the program serializes its state and loads it back in. This is sometimes too costly but has unexpected reliability benefits. It makes sure your serialization code is well exercised, it ensures most of your program states are linkable/nameable, and also it's sort of like every time you do anything you're restarting the program. There's much less implicit state that can cause problems. And as a fallback if you do get the program into a bad state you can just hit undo and you're back into a good state.
This is cool, but I don't understand the justification for why a more traditional "just store a sequence of events" undo system wasn't possible. As the author says in the post on the scripting system, the game scripts access virtual interfaces. Those could just record the methods called before forwarding them on - doesn't matter that the scripts make arbitrary method calls. It seems to me that there's nothing inherent to "the level script is arbitrary code rather than a list of commands as data" that makes that style of undo impossible.