Skip to content

Serialization

Simon edited this page Aug 10, 2023 · 14 revisions

Serialization and Deserialization in Fleks can be achieved via the snapshot functionality of the world.

LibGDX

LibGDX has a built-in way of reading and writing JSON. However, there are a few things to note:

  • keys in JSON are always stored as a string
  • serializing/deserializing collections requires to pass additional information to the JSON writer/reader

The first point can be solved easily by converting an Entity to its id. That way we only store the int value in the json instead of the string representation. In the example code below this is done via world.snapshot().mapKeys { it.key.id }:

  • int = 0
  • string = Entity(id=0)

The second point is also not difficult. We simply tell the fromJson method that we want to load a map and that the values are lists. If we don't pass the list information then LibGDX will load the components as GdxArray implementations. Since we converted entities to their ids before, we also need to convert them back. The example below does that via jsonSnapshot.mapKeys { Entity(it.key.toInt()) }.

Here is the code:

import com.badlogic.gdx.utils.Json
import com.github.quillraven.fleks.Component
import com.github.quillraven.fleks.ComponentType
import com.github.quillraven.fleks.Entity
import com.github.quillraven.fleks.configureWorld

data class Position(val x: Int = 0, val y: Int = 0) : Component<Position> {
    override fun type(): ComponentType<Position> = Position

    companion object : ComponentType<Position>()
}

data class Speed(val value: Float = 1f) : Component<Speed> {
    override fun type(): ComponentType<Speed> = Speed

    companion object : ComponentType<Speed>()
}

fun main() {
    val world = configureWorld { }

    // create two entities with components
    world.entity {
        it += Position(3, 3)
        it += Speed()
    }
    world.entity {
        it += Position(1, 2)
        it += Speed(2.5f)
    }

    // serialize world snapshot
    var snapshot = world.snapshot().mapKeys { it.key.id }
    val json = Json().toJson(snapshot)
    println(json) // prints: {0:[{class:com.gdx.test.Speed},{class:com.gdx.test.Position,x:3,y:3}],1:[{class:com.gdx.test.Speed,value:2.5},{class:com.gdx.test.Position,x:1,y:2}]}

    // clear the world
    world.removeAll(clearRecycled = true)
    println(world.numEntities) // prints: 0

    // deserialize world snapshot
    val jsonSnapshot = Json().fromJson(HashMap::class.java, List::class.java, json) as Map<String, List<Component<*>>>
    world.loadSnapshot(jsonSnapshot.mapKeys { Entity(it.key.toInt()) })
    println(world.numEntities) // prints: 2
    snapshot = world.snapshot().mapKeys { it.key.id }
    println(Json().toJson(snapshot)) // prints: {0:[{class:com.gdx.test.Speed},{class:com.gdx.test.Position,x:3,y:3}],1:[{class:com.gdx.test.Speed,value:2.5},{class:com.gdx.test.Position,x:1,y:2}]}
}

Here is a link that describes how to serialize/deserialize the components of a single entity.

KorGE

Here is an link to an example on how to do it in KorGE.

Clone this wiki locally