Posted October 04, 2024 by JamesKiddx
This isn't a mandated dev update, but thought I'd post a bit about the loading and saving of the worlds mobiles and items.
TODO add code snippets
I went thru a few iterations here as I was trying to get out of it without writing a whole pile of code, and keep it maintainable. At least with my skilll level we cant get everything we want.
First up, a bit of background, the world essentially stores all mobiles and items in a List<>, no matter where they are, be in a container, logged off players, everything.
Now Mobiles like a Player have an inventory aka a backpack item.
So the item has a Parent property set to the PlayerMobile, and the PlayerMobile has a reference to the backpack as well.
Any items in the backpack would have their parent be the backpack item.
Mobiles can have Target's which of course are other Mobiles with targets etc.
This sort of circular reference and long chains breaks pretty much all out of the box serializers, JSON, protobuffers, messagepack etc all cant support this out of the box. While Ceras which i played with sort of works, as it can handle saving/loading it doesn't quite get us there, as each reference to an Item or Mobile is serialised as a new ref.
So for me the easiest fix was "borrowing" more concepts from Runuo/Servuo.
Each Item/Mobile has Serialize/Deserialize method, where we manually write each property we want saved/loaded. We can also write out a version code in the save method, and read it in the load and then if/else accordingly.
This is alot of manual work, and updating two methods every time you add a new property to an object and you want it saved/loaded.
I've reduced this by writing a rosyln source generator that creates the Deserialize method for any object with a Serialize, It reads each Write method called in the Serialize method and generates a corresponding read in the generated Deserialize. I've even got support for parsing if blocks to allow for forward/backward compatibility.
Overall I'm pretty happy with this setup, I only have to add property's to a single method manually to handle saving/loading.
The only downside with all this is the world must be paused while saving, at a small scale it's no problem ( 45ms currently ), but at scale it would become an annoying few second stutter.