Action Plan 1: Level Loading and Saving

The following page describes an action plan describing upcoming changes to the loading and saving of levels.

Currently, SML loads and saves levels in a JSON-formatted document that recurses through the internal structures of a level and converts them into JSON. The library used to work with JSON is JSON.Net by James Newton-King. This works decently well for saving levels to a file, but improvements can be made.

Saving a level, or "serialization", is done through three methods in all serializable objects -,  , and. returns an anonymously-typed object containing the vital elements of the level to be saved. Serialize calls  and has it converted into a JSON string, which can then be written to any file. receives a JSON file and recreates the level based on the JSON file's contents.

The structure of the serialized level is as follows: There are some problems with this design that this action plan will address. Primarily, the bulk of the JSON file is tile instance data - and it's a lot of bulk, with the test level in the current commits clocking in at almost 13,000 lines for the tiles alone. However, there are only about seven distinct kinds of tile in current commits, and their properties are all identical - except for their position. If we only store the positions of a group of otherwise identical tiles, we may be able to greatly cut down in file size.
 * Level
 * Level Exits
 * Sections
 * Layers
 * Layer Tiles
 * Sprites
 * Paths
 * Event Scripts

ILevelSerializer and LevelLoadManager
First, though, we need to separate our concerns into separate classes which will allow SML to load and save levels according to any given serializer version. Enter the ILevelSerializer interface, an interface that defines methods to load and save level files. Individual serializer versions will implement this interface.

The LevelLoadManager static class will handle the loading and saving of level files instead of having level files instantiate ILevelSerializer-implementing classes. On loading a level file, the JSON is converted into a JObject. This JObject will contain, as one of the root elements, a serializer version string that instructs LevelLoadManager on which serializer to use. The serializer is then instantiated and the JObject is passed to it, where it returns a fully-constructed Level instance. On saving a level file, LevelLoadManager is provided with a Level instance and a string or enum specifying which serializer version to use. Once more, LevelLoadManager will instantiate the proper serializer instance and then use it to write and save a JSON file.

Notice: Older, non-current serializer versions may be made obsolete or removed from the code at any time with little or no warning. The code to read such files should remain, but the ability to write such files may be removed in the interest of not creating level files that are poorly made.

Serializer Version 0.02
A new serializer version, Version 0.02, will be specified. This new version will mostly change the structure of tiles being saved. This new version will only write "unique" tiles (tiles which vary from others anything other than position) once and use an ID for each "unique" tile. Then, tile groups - essentially an ID to a "unique" tile followed by a list of positions - will be written after the "unique" tiles. All other structure should, more or less, remain the same.

This new version will be mostly similar to Version 0.01, except that the collection "Layer Tile" will be replaced by two collections - "Unique Layer Tiles" and "Layer Tile Groups". The structure is below. The position blob is a group of semicolon-delimited Vector2s where each component is delimited by commas. The final Vector2 shall not have a semicolon succeeding it. There are no newlines or other characters except for any characters resulting from System.Single.ToString. For instance: positionBlob: "0,0;100,100;200,200;300,300;400,400"
 * Unique Layer Tile
 * Qualified Type Name
 * File-Unique ID
 * Tile Collision Type
 * Tile Name
 * Graphics Resource Name
 * Initial State
 * Custom Tile Data (varies by tile)
 * Layer Tile Group
 * File-Unique ID
 * Position Blob