{"id":122,"date":"2016-04-17T11:05:18","date_gmt":"2016-04-17T11:05:18","guid":{"rendered":"http:\/\/blog.qubekwest.com\/?p=122"},"modified":"2018-01-16T12:22:01","modified_gmt":"2018-01-16T12:22:01","slug":"serialization-round-four","status":"publish","type":"post","link":"https:\/\/blog.qubekwest.com\/?p=122","title":{"rendered":"Serialization Round Four"},"content":{"rendered":"<p>Serialization is the conversion of an object into a magical stream of data that can be deserialized later back into an object. \u00a0At first glance you could probably be convinced that this is a totally unnecessary thing for objects to be able to do. \u00a0For most simple projects this sort of thing never even comes up, so you&#8217;d be right if you figured they&#8217;re useless. \u00a0For QubeKwest however, they aren&#8217;t just needed, they&#8217;re needed a lot.<\/p>\n<p>Consider for a moment all the data in QubeKwest. \u00a0Everything from the world you are walking around in to chat messages between players is just data at the end of the day.\u00a0 If\u00a0the objects in the game can be easily converted to data and then can be easily restored, you suddenly have lots of fun new options for how they can be used. \u00a0Pure data versions can be shuttled down a network wire or stored away in files on the disk. \u00a0Later when you need the objects again they can be easily loaded from the disk or reconstructed by the client on the other end of the network.<\/p>\n<p>There are loads of different ways to serialize data. \u00a0Some are crazy flexible, some are practically automatic, some involve elaborate frameworks, and others are hard coded. \u00a0Some make serialized data that is large and fluffy and others are small and concise. \u00a0Due to the vastness of the worlds I&#8217;m trying to build with QubeKwest, it makes sense to make sure my serializer makes as little data as possible. \u00a0That loses me some flexibility, but it means I can store larger worlds in less space and that I can use less bandwidth when you&#8217;re playing.<\/p>\n<p>I set out to make my own serialization patterns and to say it&#8217;s been an evolutionary process isn&#8217;t giving it proper credit. \u00a0My first idea involved saving things into 32-bit integers. \u00a0I built a collection of functions for aligning data into the integers and started making the basic patterns of how my serialization would work. \u00a0Almost immediately I realized that serializing things into integers was a<span style=\"line-height: 1.6471;\">\u00a0total pain in the butt, and really not worth the trouble. \u00a0With that, version 1 died a horrible death.<\/span><\/p>\n<p><span style=\"line-height: 1.6471;\">Later, while learning the finer points of NIO and LWJGL, I realized that both of those make rather heavy use of ByteBuffers. \u00a0My integer pattern could be adapted fairly easily to use bytes and that allowed me to throw away all the issues with aligning data in integers and all the masking and shifting that involves. \u00a0Even more conveniently, ByteBuffers already have methods for storing and retrieving every type of data I could possibly need. \u00a0They even let you add other ByteBuffers to them so objects that have other serializable objects in them are easier to deal with. \u00a0<\/span><span style=\"line-height: 1.6471;\">This was version 2 and it died when I tried to deserialize things without any direct knowledge of what I was deserializing. \u00a0<\/span><\/p>\n<p>The next version added the idea of a header to the serialized data. \u00a0I could use that to identify what type of data it is I&#8217;m looking at when it&#8217;s still in its serialized form. \u00a0The header data itself was only defined by a collection of constants and the way several helper methods dealt with it. \u00a0This wasn&#8217;t a great solution, but it lined up with the mess I&#8217;d been crafting. \u00a0This version also started to add the idea of variable sized data objects. \u00a0I freely admit that it was wishful thinking to pretend that everything could be a fixed size, but I knew that variable sized things were going to add a lot of complexity.<\/p>\n<p>Before long, I realized that I would probably need multiple versions of a particular type of object over time. \u00a0I know I saw this coming, but for some reason I didn&#8217;t include this feature into the header data I was using. \u00a0The problem is that if I can&#8217;t identify which version I&#8217;d serialized, I wouldn&#8217;t be able to load it properly. \u00a0With that, version 3 also passed on.<\/p>\n<p>The evolution continued when I realized I didn&#8217;t just want versions, but also that I&#8217;d created an honest to goodness mess of things for serialization. \u00a0My interface had static methods on it to avoid creating dummy objects just for the sake of asking them questions about serialization. \u00a0The problem with that, is that the static methods were literally on the interface and while they could be overridden they were not enforceable. \u00a0Every time I implemented a new object, I had to remember to create those too. \u00a0As mentioned before, my header data was a twisted jumble of constants and helper methods. \u00a0To fix that I created actual serialization header classes. \u00a0That meant a bunch of my helper methods now had a proper place to live and all the constants that told where things go could just be removed.<\/p>\n<p>Attempt number 4 was born as I cleaned up all of the serialization patterns that were broken and sad. \u00a0It was a total refactor. \u00a0To make the use of the serialization more logical in other packages, I also pulled it into its own package. \u00a0All these changes were just the tip of a pretty serious ice burg because after I started the refactor, all of the objects that I had already created the serialization functions for had to be revised to follow the new patterns I&#8217;d just established. \u00a0Now two days later, I think I&#8217;ve finally finished and I&#8217;m actually really happy with how it all works. \u00a0Hopefully this version will be the last one, but if I&#8217;m being honest, I sort of doubt it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Serialization is the conversion of an object into a magical stream of data that can be deserialized later back into an object. \u00a0At first glance you could probably be convinced that this is a totally unnecessary thing for objects to be able to do. \u00a0For most simple projects this sort of thing never even comes &hellip; <a href=\"https:\/\/blog.qubekwest.com\/?p=122\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Serialization Round Four<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-122","post","type-post","status-publish","format-standard","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/posts\/122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=122"}],"version-history":[{"count":8,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/posts\/122\/revisions"}],"predecessor-version":[{"id":312,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=\/wp\/v2\/posts\/122\/revisions\/312"}],"wp:attachment":[{"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.qubekwest.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}