Skip to content

Commit

Permalink
Use map syntax for prefab file definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
0ffz committed Dec 24, 2023
1 parent f1c54d5 commit 02550bd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package com.mineinabyss.geary.prefabs
import co.touchlab.kermit.Severity
import com.benasher44.uuid.Uuid
import com.mineinabyss.geary.components.relations.NoInherit
import com.mineinabyss.geary.datatypes.Component
import com.mineinabyss.geary.datatypes.Entity
import com.mineinabyss.geary.helpers.entity
import com.mineinabyss.geary.modules.geary
import com.mineinabyss.geary.prefabs.configuration.components.Prefab
import com.mineinabyss.geary.prefabs.helpers.inheritPrefabs
import com.mineinabyss.geary.prefabs.serializers.ComponentListAsMapSerializer
import com.mineinabyss.geary.serialization.dsl.serializableComponents
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.builtins.ListSerializer
import okio.Path

class PrefabLoader {
Expand Down Expand Up @@ -60,7 +58,7 @@ class PrefabLoader {
/** Registers an entity with components defined in a [path], adding a [Prefab] component. */
fun loadFromPath(namespace: String, path: Path, writeTo: Entity? = null): Result<Entity> {
return runCatching {
val serializer = ListSerializer(PolymorphicSerializer(Component::class))
val serializer = ComponentListAsMapSerializer()
val ext = path.name.substringAfterLast('.')
val decoded = formats[ext]?.decodeFromFile(serializer, path)
?: throw IllegalArgumentException("Unknown file format $ext")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.mineinabyss.geary.prefabs.serializers

import com.mineinabyss.geary.datatypes.GearyComponent
import com.mineinabyss.geary.serialization.dsl.serializableComponents
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.PolymorphicKind
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildSerialDescriptor
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder


class GearyComponentSerializer : KSerializer<GearyComponent> {
@OptIn(InternalSerializationApi::class)
override val descriptor: SerialDescriptor =
buildSerialDescriptor("GearyComponentSerializer", PolymorphicKind.SEALED)

override fun deserialize(decoder: Decoder): GearyComponent {
TODO("Not yet implemented")
}

override fun serialize(encoder: Encoder, value: GearyComponent) {
TODO("Not yet implemented")
}

}

class ComponentListAsMapSerializer : KSerializer<List<GearyComponent>> {
val keySerializer = String.serializer()
val valueSerializer = GearyComponentSerializer()

override val descriptor: SerialDescriptor
get() = MapSerializer(keySerializer, valueSerializer).descriptor

override fun deserialize(decoder: Decoder): List<GearyComponent> {
val components = mutableSetOf<GearyComponent>()
val compositeDecoder = decoder.beginStructure(descriptor)
while (true) {
val index = compositeDecoder.decodeElementIndex(descriptor)
if (index == CompositeDecoder.DECODE_DONE) break

val startIndex = components.size * 2
val key: String = compositeDecoder.decodeSerializableElement(descriptor, startIndex + index, keySerializer)
val foundValueSerializer =
serializableComponents.serializers.getSerializerFor(key, GearyComponent::class) as? KSerializer<Any>
?: error("No component serializer registered for $key")
val newDescriptor = MapSerializer(keySerializer, foundValueSerializer).descriptor
val newIndex = compositeDecoder.decodeElementIndex(newDescriptor)
val decodedValue = compositeDecoder.decodeSerializableElement<Any>(
descriptor = newDescriptor,
index = newIndex,
deserializer = foundValueSerializer,
)
components += decodedValue
}
compositeDecoder.endStructure(descriptor)
return components.toList()
}

override fun serialize(encoder: Encoder, value: List<GearyComponent>) {
TODO("Not implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface ComponentSerializers {
fun <T : Component> getSerializerFor(
key: String,
baseClass: KClass<in T>
): DeserializationStrategy<out T>?
): DeserializationStrategy<T>?

fun <T : Component> getSerializerFor(kClass: KClass<in T>): DeserializationStrategy<out T>?
fun getSerialNameFor(kClass: KClass<out Component>): String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SerializersByMap(
key: String,
baseClass: KClass<in T>
): DeserializationStrategy<out T>? =
module.getPolymorphic(baseClass = baseClass, serializedClassName = key)
module.getPolymorphic(baseClass = baseClass, serializedClassName = key.prefixNamespaceIfNotPrefixed())

override fun <T : Component> getSerializerFor(kClass: KClass<in T>): DeserializationStrategy<out T>? {
val serialName = getSerialNameFor(kClass) ?: return null
Expand All @@ -32,4 +32,9 @@ class SerializersByMap(

override fun getSerialNameFor(kClass: KClass<out Component>): String? =
component2serialName[kClass]

private fun String.prefixNamespaceIfNotPrefixed(): String =
if (!contains(":"))
"geary:${this}"
else this
}

0 comments on commit 02550bd

Please sign in to comment.