-
-
Notifications
You must be signed in to change notification settings - Fork 24
Serialization
Serialization and Deserialization in Fleks can be achieved via the snapshot functionality of the world. A Snapshot is a container for the components and tags of an entity.
data class Snapshot(
val components: List<Component<*>>,
val tags: List<UniqueId<*>>,
)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 Snapshot instances.
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(), 0u) }.
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.github.quillraven.fleks.Snapshot,components:[{class:com.gdx.test.Speed},{class:com.gdx.test.Position,x:3,y:3}]},1:{class:com.github.quillraven.fleks.Snapshot,components:[{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, Snapshot::class.java, json) as Map<String, Snapshot>
world.loadSnapshot(jsonSnapshot.mapKeys { Entity(it.key.toInt(), 0u) })
println(world.numEntities) // prints: 2
snapshot = world.snapshot().mapKeys { it.key.id }
println(Json().toJson(snapshot)) // prints: {0:{class:com.github.quillraven.fleks.Snapshot,components:[{class:com.gdx.test.Speed},{class:com.gdx.test.Position,x:3,y:3}]},1:{class:com.github.quillraven.fleks.Snapshot,components:[{class:com.gdx.test.Speed,value:2.5},{class:com.gdx.test.Position,x:1,y:2}]}}
}The example above ignores the entity version information, which might be sufficient for your game, but in case you need it as well then here is the updated code snippet. For more details about entity version, check out the entity wiki.
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()
val json = Json().toJson(snapshot)
println(json) // prints: {Entity(id=0, version=0):{class:com.github.quillraven.fleks.Snapshot,components:[{class:om.gdx.test.Speed},{class:om.gdx.test.Position,x:3,y:3}]},Entity(id=1, version=0):{class:com.github.quillraven.fleks.Snapshot,components:[{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, Snapshot::class.java, json) as Map<String, Snapshot>
world.loadSnapshot(jsonSnapshot.mapKeys {
Entity(
it.key.substringAfter("id=").substringBefore(", ").toInt(),
it.key.substringAfter("version=").substringBefore(")").toUInt()
)
})
println(world.numEntities) // prints: 2
snapshot = world.snapshot()
println(Json().toJson(snapshot)) // prints: {Entity(id=0, version=0):{class:com.github.quillraven.fleks.Snapshot,components:[{class:om.gdx.test.Speed},{class:om.gdx.test.Position,x:3,y:3}]},Entity(id=1, version=0):{class:com.github.quillraven.fleks.Snapshot,components:[{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.
Here is a link to an example on how to do it in KorGE.