Regarding rollback, there's an interesting technique that I stumbled upon:
Instead of serializing individual objects, you serialize all the memory relevant to the gameplay by using a custom memory allocator whenever the gameplay related code runs. This custom memory allocator is designed to allow taking fast memory snapshots, and supports restoring memory snapshots.
This allows rollbacking any code, including in my case rollbacking user-submitted Lua scripts.
I wrote about it at https://www.jfgeyelin.com/2021/02/a-general-state-rollback-t...