Storing data sounds very easy on the surface. Just take whatever you want stored, choose a format you want to store it in and write it to a data store of your choice. This can be a well-structured database or your average text file. And reading the data is just doing the same process in reverse, right? Load the data from wherever it’s stored, convert it into the format you need and use it. So far, so easy.
Except that this initial look is deceptive. Earlier or later, you’re going to want to update your application to introduce a new feature, fix an age-old bug or something else that requires you to add, remove or modify something about the data stored. What you’re left with now is having to build something that can read the old format as well as the new format. This is also easy enough to do for simple cases but gets really tedious over time.
With more complicated scenarios, like let’s say switching everything from a system based on numerical data to something that is text-based, it’s easy to screw this up. This is something that Minecraft went through, starting in 1.7 and being finalized in 1.13 (called “the flattening”). What happens if this update process goes wrong is something that can be seen especially when taking a look at the classic map below the lobby: Doors that are facing the wrong way, stairs that are oriented strangely, fences that don’t connect properly, etc.
Another example of this can be seen with our current shop system, where sometimes users experience their shop randomly seeming to “forget” what item it was supposed to be selling. This is an artifact of the same issue. Data that’s being stored in some format along with data that is on a whole different version and a shop plugin that is left trying to understand a myriad of formats at once while trying to cope with the situation.
And that is also the reason we wanted to write this blog post in the first place. This week, we’ve been working on how the new shop plugin that we are developing for the next map stores data. So, what is the answer to the predicament above, you might ask? It is called data versioning. What you do is, you take a number that is baked into your application and every time you write data, you first write that number and then the data.
That way, when reading data, your program can immediately see what format it has in front of it and doesn’t have to guess by the way the data is formatted. The only thing left to do then is to write a part of your application that says, “okay, so I know this data is formatted in this way, so I’m going to convert it over to the new format”. An added bonus is that you can chain these update routines together and leave the old ones in your program. That way, when a very old version is found, it triggers a type of chain reaction, slowly updating the data through the different versions one by one. This is also the method our new shop plugin will be using.
So, what about Mojang? Did they figure out how to do it? They did! Starting with Minecraft 1.9 (Snapshot 15w32a), they introduced a data version that they increment for every release: https://minecraft.fandom.com/wiki/Data_version They even went as far as writing a programming tool (library) to make writing the individual update routines easier, called “DataFixerUpper”.
Except that this initial look is deceptive. Earlier or later, you’re going to want to update your application to introduce a new feature, fix an age-old bug or something else that requires you to add, remove or modify something about the data stored. What you’re left with now is having to build something that can read the old format as well as the new format. This is also easy enough to do for simple cases but gets really tedious over time.
With more complicated scenarios, like let’s say switching everything from a system based on numerical data to something that is text-based, it’s easy to screw this up. This is something that Minecraft went through, starting in 1.7 and being finalized in 1.13 (called “the flattening”). What happens if this update process goes wrong is something that can be seen especially when taking a look at the classic map below the lobby: Doors that are facing the wrong way, stairs that are oriented strangely, fences that don’t connect properly, etc.
Another example of this can be seen with our current shop system, where sometimes users experience their shop randomly seeming to “forget” what item it was supposed to be selling. This is an artifact of the same issue. Data that’s being stored in some format along with data that is on a whole different version and a shop plugin that is left trying to understand a myriad of formats at once while trying to cope with the situation.
And that is also the reason we wanted to write this blog post in the first place. This week, we’ve been working on how the new shop plugin that we are developing for the next map stores data. So, what is the answer to the predicament above, you might ask? It is called data versioning. What you do is, you take a number that is baked into your application and every time you write data, you first write that number and then the data.
That way, when reading data, your program can immediately see what format it has in front of it and doesn’t have to guess by the way the data is formatted. The only thing left to do then is to write a part of your application that says, “okay, so I know this data is formatted in this way, so I’m going to convert it over to the new format”. An added bonus is that you can chain these update routines together and leave the old ones in your program. That way, when a very old version is found, it triggers a type of chain reaction, slowly updating the data through the different versions one by one. This is also the method our new shop plugin will be using.
So, what about Mojang? Did they figure out how to do it? They did! Starting with Minecraft 1.9 (Snapshot 15w32a), they introduced a data version that they increment for every release: https://minecraft.fandom.com/wiki/Data_version They even went as far as writing a programming tool (library) to make writing the individual update routines easier, called “DataFixerUpper”.