diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt index 9d7c2583c..26875fc30 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt @@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.nbt.set import java.util.function.Supplier +import kotlin.jvm.optionals.getOrNull import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty0 @@ -174,8 +175,8 @@ class Savetables : INBTSerializable { fun codecNullable(prop: Delegate, codec: Codec, name: String): Stateless { return Stateless(prop, name, Tag::class.java) - .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow() { throw IllegalStateException("Failed to write NBT data for $name: $it") } } } - .withDeserializer { codec.decode(NbtOps.INSTANCE, it).getOrThrow() { throw IllegalStateException("Failed to read NBT data for $name: $it") }.first } + .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write save data for '$name': $it") } } } + .withDeserializer { codec.decode(NbtOps.INSTANCE, it).resultOrPartial { throw IllegalStateException("Failed to read save data for '$name'", RuntimeException(it)) }.getOrNull()?.first } } fun codecNullable(prop: KMutableProperty0, codec: Codec, name: String = prop.name): Stateless { @@ -184,8 +185,8 @@ class Savetables : INBTSerializable { fun codecNullable(prop: Delegate, codec: Codec, name: String, default: T?): Stateless { return Stateless(prop, name, Tag::class.java) - .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write NBT data for $name: $it") } } } - .withDeserializer { codec.decode(NbtOps.INSTANCE, it).mapOrElse({ it.first }, { LOGGER.error("Failed to read NBT data for $name", RuntimeException(it.message())); default }) } + .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write save data for '$name': $it") } } } + .withDeserializer { codec.decode(NbtOps.INSTANCE, it).resultOrPartial { LOGGER.error("Failed to read save data for '$name'", RuntimeException(it)) }.map { it.first }.orElse(default) } .withDefault { default } } @@ -195,14 +196,27 @@ class Savetables : INBTSerializable { fun codec(prop: Delegate, codec: Codec, name: String): Stateless { return Stateless(prop, name, Tag::class.java) - .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write NBT data for $name: $it") } } - .withDeserializer { codec.decode(NbtOps.INSTANCE, it).getOrThrow() { throw IllegalStateException("Failed to read NBT data for $name: $it") }.first } + .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write save data for '$name': $it") } } + .withDeserializer { + codec.decode(NbtOps.INSTANCE, it).let { res -> + res + .resultOrPartial { LOGGER.error("Failed to read save data for '$name'", RuntimeException(it)) } + .map { it.first } + .orElseThrow { throw RuntimeException("Failed to read save data for '$name': ${res.error().get().message()}") } + } + } } fun codec(prop: Delegate, codec: Codec, name: String, default: T): Stateless { return Stateless(prop, name, Tag::class.java) - .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write NBT data for $name: $it") } } - .withDeserializer { codec.decode(NbtOps.INSTANCE, it).mapOrElse({ it.first }, { LOGGER.error("Failed to read NBT data for $name", RuntimeException(it.message())); default }) } + .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow { throw IllegalStateException("Failed to write save data for '$name': $it") } } + .withDeserializer { + codec + .decode(NbtOps.INSTANCE, it) + .resultOrPartial { LOGGER.error("Failed to read save data for '$name'", RuntimeException(it)) } + .map { it.first } + .orElse(default) + } .withDefault { default } }