From 12a3becc1b5ee374ad810f6474690ae4aad5ca34 Mon Sep 17 00:00:00 2001 From: SettingDust Date: Tue, 27 Sep 2022 12:04:05 +0800 Subject: [PATCH 1/6] feat(core): add `Vector3d` and `Triple` extensions --- .../silk/core/math/vector/VectorOperations.kt | 73 +++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt index bbc351dd..b13ca172 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt @@ -1,5 +1,6 @@ package net.silkmc.silk.core.math.vector +import com.mojang.math.Vector3d import com.mojang.math.Vector3f import net.minecraft.core.Vec3i import net.minecraft.world.phys.Vec3 @@ -18,6 +19,9 @@ operator fun Vec3.times(vec: Vec3): Vec3 = multiply(vec) operator fun Vec3.div(vec: Vec3): Vec3 = Vec3(x / vec.x, y / vec.y, z / vec.z) operator fun Vec3.compareTo(vec: Vec3) = lengthSqr().compareTo(vec.lengthSqr()) +fun Vec3.triple() = Triple(x, y, z) +fun Vec3(x: Number, y: Number, z: Number) = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) + operator fun Vec3.component1() = x operator fun Vec3.component2() = y operator fun Vec3.component3() = z @@ -25,9 +29,15 @@ operator fun Vec3.component3() = z operator fun Vector3f.not(): Vector3f = times(-1f) -operator fun Vector3f.plus(n: Number): Vector3f = copy().apply { n.toFloat().let { nFloat -> add(nFloat, nFloat, nFloat) } } -operator fun Vector3f.minus(n: Number): Vector3f = copy().apply { n.toFloat().let { nFloat -> sub(Vector3f(nFloat, nFloat, nFloat)) } } -operator fun Vector3f.times(n: Number): Vector3f = n.toFloat().let { nFloat -> Vector3f(x() * nFloat, y() * nFloat, z() * nFloat) } +operator fun Vector3f.plus(n: Number): Vector3f = + copy().apply { n.toFloat().let { nFloat -> add(nFloat, nFloat, nFloat) } } + +operator fun Vector3f.minus(n: Number): Vector3f = + copy().apply { n.toFloat().let { nFloat -> sub(Vector3f(nFloat, nFloat, nFloat)) } } + +operator fun Vector3f.times(n: Number): Vector3f = + n.toFloat().let { nFloat -> Vector3f(x() * nFloat, y() * nFloat, z() * nFloat) } + operator fun Vector3f.div(n: Number): Vector3f = times(1.0 / n.toDouble()) operator fun Vector3f.compareTo(n: Number) = Vec3(this).length().compareTo(n.toDouble()) @@ -37,6 +47,16 @@ operator fun Vector3f.times(vec: Vector3f): Vector3f = Vector3f(x() * vec.x(), y operator fun Vector3f.div(vec: Vector3f): Vector3f = Vector3f(x() / vec.x(), y() / vec.y(), z() / vec.z()) operator fun Vector3f.compareTo(vec: Vector3f) = Vec3(this).lengthSqr().compareTo(Vec3(vec).lengthSqr()) +fun Vector3f.triple() = Triple(x, y, z) +fun Vector3f(x: Number, y: Number, z: Number) = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) + +val Vector3f.x: Float + get() = x() +val Vector3f.y: Float + get() = y() +val Vector3f.z: Float + get() = z() + operator fun Vector3f.component1() = x() operator fun Vector3f.component2() = y() operator fun Vector3f.component3() = z() @@ -45,17 +65,58 @@ operator fun Vector3f.component3() = z() operator fun Vec3i.not(): Vec3i = times(-1) inline operator fun T.plus(n: Number): T = n.toInt().let { nInt -> offset(nInt, nInt, nInt) } as T -inline operator fun T.minus(n: Number): T = (-n.toInt()).let { nInt -> offset(nInt, nInt, nInt) } as T +inline operator fun T.minus(n: Number): T = + (-n.toInt()).let { nInt -> offset(nInt, nInt, nInt) } as T + operator fun Vec3i.times(n: Number): Vec3i = multiply(n.toInt()) operator fun Vec3i.div(n: Number) = (1.0 / n.toDouble()).let { nDouble -> Vec3i(x * nDouble, y * nDouble, z * nDouble) } -operator fun Vec3i.compareTo(n: Number) = Vec3(x.toDouble(), y.toDouble(), z.toDouble()).length().compareTo(n.toDouble()) +operator fun Vec3i.compareTo(n: Number) = + Vec3(x.toDouble(), y.toDouble(), z.toDouble()).length().compareTo(n.toDouble()) inline operator fun T.plus(vec: Vec3i): T = offset(vec) as T inline operator fun T.minus(vec: Vec3i): T = offset(!vec) as T operator fun Vec3i.times(vec: Vec3i): Vec3i = Vec3i(x * vec.x, y * vec.y, z * vec.z) operator fun Vec3i.div(vec: Vec3i): Vec3i = Vec3i(x / vec.x, y / vec.y, z / vec.z) -operator fun Vec3i.compareTo(vec: Vec3i) = Vec3(x.toDouble(), y.toDouble(), z.toDouble()).lengthSqr().compareTo(Vec3(vec.x.toDouble(), vec.y.toDouble(), vec.z.toDouble()).lengthSqr()) +operator fun Vec3i.compareTo(vec: Vec3i) = + Vec3(x.toDouble(), y.toDouble(), z.toDouble()).lengthSqr() + .compareTo(Vec3(vec.x.toDouble(), vec.y.toDouble(), vec.z.toDouble()).lengthSqr()) + +fun Vec3i.triple() = Triple(x, y, z) +fun Vec3i(x: Number, y: Number, z: Number) = Vec3i(x.toDouble(), y.toDouble(), z.toDouble()) operator fun Vec3i.component1() = x operator fun Vec3i.component2() = y operator fun Vec3i.component3() = z + +operator fun Vector3d.not(): Vector3d = times(-1f) + +operator fun Vector3d.plus(n: Number): Vector3d = + copy().apply { n.toDouble().let { set(it + x, it + y, it + z) } } + +operator fun Vector3d.minus(n: Number): Vector3d = + copy().apply { n.toDouble().let { set(x - it, y - it, z - it) } } + +operator fun Vector3d.times(n: Number): Vector3d = copy().apply { n.toDouble().let { times -> scale(times) } } +operator fun Vector3d.div(n: Number): Vector3d = times(1.0 / n.toDouble()) +operator fun Vector3d.compareTo(n: Number) = Vec3(x, y, z).length().compareTo(n.toDouble()) + +operator fun Vector3d.plus(vec: Vector3d): Vector3d = copy().apply { add(vec) } +operator fun Vector3d.minus(vec: Vector3d): Vector3d = Vector3d(x - vec.x, y - vec.y, z - vec.z) +operator fun Vector3d.times(vec: Vector3d): Vector3d = Vector3d(x * vec.x, y * vec.y, z * vec.z) +operator fun Vector3d.div(vec: Vector3d): Vector3d = Vector3d(x / vec.x, y / vec.y, z / vec.z) +operator fun Vector3d.compareTo(vec: Vector3d) = + Vec3(x, y, z).lengthSqr().compareTo(Vec3(vec.x, vec.y, vec.z).lengthSqr()) + +fun Vector3d.copy() = Vector3d(x, y, z) +fun Vector3d.triple() = Triple(x, y, z) +fun Vector3d(x: Number, y: Number, z: Number) = Vector3d(x.toDouble(), y.toDouble(), z.toDouble()) + +operator fun Vector3d.component1() = x +operator fun Vector3d.component2() = y +operator fun Vector3d.component3() = z + + +fun Triple.vector3() = Vec3(first, second, third) +fun Triple.vector3i() = Vec3i(first, second, third) +fun Triple.vector3f() = Vector3f(first, second, third) +fun Triple.vector3d() = Vector3d(first, second, third) \ No newline at end of file From 85ee6c6d5e5f339ce49008da72a3bd4012b8b95e Mon Sep 17 00:00:00 2001 From: SettingDust Date: Tue, 27 Sep 2022 12:18:39 +0800 Subject: [PATCH 2/6] feat(core): add serializers for vectors --- .../silk/core/math/vector/VectorOperations.kt | 12 +- .../serializers/BlockPosSerializer.kt | 22 ++++ .../serializers/VectorSerializer.kt | 106 ++++++++++++++++++ 3 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/BlockPosSerializer.kt create mode 100644 silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt index b13ca172..b92fafbe 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt @@ -33,7 +33,7 @@ operator fun Vector3f.plus(n: Number): Vector3f = copy().apply { n.toFloat().let { nFloat -> add(nFloat, nFloat, nFloat) } } operator fun Vector3f.minus(n: Number): Vector3f = - copy().apply { n.toFloat().let { nFloat -> sub(Vector3f(nFloat, nFloat, nFloat)) } } + copy().apply { sub(Vector3f(n, n, n)) } operator fun Vector3f.times(n: Number): Vector3f = n.toFloat().let { nFloat -> Vector3f(x() * nFloat, y() * nFloat, z() * nFloat) } @@ -70,16 +70,14 @@ inline operator fun T.minus(n: Number): T = operator fun Vec3i.times(n: Number): Vec3i = multiply(n.toInt()) operator fun Vec3i.div(n: Number) = (1.0 / n.toDouble()).let { nDouble -> Vec3i(x * nDouble, y * nDouble, z * nDouble) } -operator fun Vec3i.compareTo(n: Number) = - Vec3(x.toDouble(), y.toDouble(), z.toDouble()).length().compareTo(n.toDouble()) +operator fun Vec3i.compareTo(n: Number) = Vec3(x, y, z).length().compareTo(n.toDouble()) inline operator fun T.plus(vec: Vec3i): T = offset(vec) as T inline operator fun T.minus(vec: Vec3i): T = offset(!vec) as T operator fun Vec3i.times(vec: Vec3i): Vec3i = Vec3i(x * vec.x, y * vec.y, z * vec.z) operator fun Vec3i.div(vec: Vec3i): Vec3i = Vec3i(x / vec.x, y / vec.y, z / vec.z) operator fun Vec3i.compareTo(vec: Vec3i) = - Vec3(x.toDouble(), y.toDouble(), z.toDouble()).lengthSqr() - .compareTo(Vec3(vec.x.toDouble(), vec.y.toDouble(), vec.z.toDouble()).lengthSqr()) + Vec3(x, y, z).lengthSqr().compareTo(Vec3(vec.x, vec.y, vec.z).lengthSqr()) fun Vec3i.triple() = Triple(x, y, z) fun Vec3i(x: Number, y: Number, z: Number) = Vec3i(x.toDouble(), y.toDouble(), z.toDouble()) @@ -116,7 +114,7 @@ operator fun Vector3d.component2() = y operator fun Vector3d.component3() = z -fun Triple.vector3() = Vec3(first, second, third) -fun Triple.vector3i() = Vec3i(first, second, third) +fun Triple.vec3() = Vec3(first, second, third) +fun Triple.vec3i() = Vec3i(first, second, third) fun Triple.vector3f() = Vector3f(first, second, third) fun Triple.vector3d() = Vector3d(first, second, third) \ No newline at end of file diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/BlockPosSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/BlockPosSerializer.kt new file mode 100644 index 00000000..e4300356 --- /dev/null +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/BlockPosSerializer.kt @@ -0,0 +1,22 @@ +package net.silkmc.silk.core.serialization.serializers + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.minecraft.core.Vec3i +import net.minecraft.core.BlockPos +import net.silkmc.silk.core.serialization.SilkSerializer + +/** + * Use vector serializers for structure. [BlockPos] is a [Vec3i] + */ +@ExperimentalSerializationApi +object BlockPosSerializer : SilkSerializer() { + override val descriptor = PrimitiveSerialDescriptor(descriptorName, PrimitiveKind.LONG) + + override fun deserialize(decoder: Decoder) = BlockPos.of(decoder.decodeLong())!! + + override fun serialize(encoder: Encoder, value: BlockPos) = encoder.encodeLong(value.asLong()) +} \ No newline at end of file diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt new file mode 100644 index 00000000..a9e8c111 --- /dev/null +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt @@ -0,0 +1,106 @@ +package net.silkmc.silk.core.serialization.serializers + +import com.mojang.math.Vector3d +import com.mojang.math.Vector3f +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.encoding.CompositeDecoder +import kotlinx.serialization.encoding.CompositeEncoder +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.minecraft.core.Vec3i +import net.silkmc.silk.core.math.vector.triple +import net.silkmc.silk.core.serialization.SilkSerializer + +private const val XIndex = 0; +private const val YIndex = 1; +private const val ZIndex = 2; + +private inline fun SilkSerializer<*>.descriptor(serializer: KSerializer) = + buildClassSerialDescriptor(descriptorName) { + element("x", serializer.descriptor) + element("y", serializer.descriptor) + element("z", serializer.descriptor) + } + +@ExperimentalSerializationApi +private inline fun CompositeDecoder.decodeVector( + descriptor: SerialDescriptor, + serializer: DeserializationStrategy, + constructor: (T, T, T) -> U +) = run { + if (decodeSequentially()) { + constructor( + decodeSerializableElement(descriptor, XIndex, serializer), + decodeSerializableElement(descriptor, YIndex, serializer), + decodeSerializableElement(descriptor, ZIndex, serializer) + ) + } else { + var x: T? = null + var y: T? = null + var z: T? = null + while (true) { + when (val i = decodeElementIndex(Vec3iSerializer.descriptor)) { + CompositeDecoder.DECODE_DONE -> break + XIndex -> x = decodeSerializableElement(descriptor, i, serializer) + YIndex -> y = decodeSerializableElement(descriptor, i, serializer) + ZIndex -> z = decodeSerializableElement(descriptor, i, serializer) + } + } + constructor(x!!, y!!, z!!) + } +} + +private fun CompositeEncoder.encodeVector( + descriptor: SerialDescriptor, + serializer: SerializationStrategy, + triple: Triple +) = apply { + encodeSerializableElement(descriptor, XIndex, serializer, triple.first) + encodeSerializableElement(descriptor, YIndex, serializer, triple.second) + encodeSerializableElement(descriptor, ZIndex, serializer, triple.third) +} + +@ExperimentalSerializationApi +object Vec3iSerializer : SilkSerializer() { + private val serializer = Int.serializer() + + override val descriptor = descriptor(serializer) + + override fun deserialize(decoder: Decoder) = + decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vec3i)) + + override fun serialize(encoder: Encoder, value: Vec3i) = + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) +} + +@ExperimentalSerializationApi +object Vector3fSerializer : SilkSerializer() { + private val serializer = Float.serializer() + + override val descriptor = descriptor(serializer) + + override fun deserialize(decoder: Decoder) = + decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3f)) + + override fun serialize(encoder: Encoder, value: Vector3f) = + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) +} + +@ExperimentalSerializationApi +object Vector3dSerializer : SilkSerializer() { + private val serializer = Double.serializer() + + override val descriptor = descriptor(serializer) + + override fun deserialize(decoder: Decoder) = + decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3d)) + + override fun serialize(encoder: Encoder, value: Vector3d) = + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) +} \ No newline at end of file From e5c6db71f109b6963e3c1140d08d22be245e901a Mon Sep 17 00:00:00 2001 From: SettingDust Date: Tue, 11 Oct 2022 10:56:15 +0800 Subject: [PATCH 3/6] chore(core): typo --- .../silk/core/math/vector/VectorOperations.kt | 8 +++---- .../serializers/VectorSerializer.kt | 24 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt index b92fafbe..4123bbfd 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt @@ -114,7 +114,7 @@ operator fun Vector3d.component2() = y operator fun Vector3d.component3() = z -fun Triple.vec3() = Vec3(first, second, third) -fun Triple.vec3i() = Vec3i(first, second, third) -fun Triple.vector3f() = Vector3f(first, second, third) -fun Triple.vector3d() = Vector3d(first, second, third) \ No newline at end of file +fun Triple.toVec3() = Vec3(first, second, third) +fun Triple.toVec3i() = Vec3i(first, second, third) +fun Triple.toVector3f() = Vector3f(first, second, third) +fun Triple.toVector3d() = Vector3d(first, second, third) \ No newline at end of file diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt index a9e8c111..0121d393 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt @@ -17,9 +17,9 @@ import net.minecraft.core.Vec3i import net.silkmc.silk.core.math.vector.triple import net.silkmc.silk.core.serialization.SilkSerializer -private const val XIndex = 0; -private const val YIndex = 1; -private const val ZIndex = 2; +private const val xIndex = 0 +private const val yIndex = 1 +private const val zIndex = 2 private inline fun SilkSerializer<*>.descriptor(serializer: KSerializer) = buildClassSerialDescriptor(descriptorName) { @@ -36,9 +36,9 @@ private inline fun CompositeDecoder.decodeVector( ) = run { if (decodeSequentially()) { constructor( - decodeSerializableElement(descriptor, XIndex, serializer), - decodeSerializableElement(descriptor, YIndex, serializer), - decodeSerializableElement(descriptor, ZIndex, serializer) + decodeSerializableElement(descriptor, xIndex, serializer), + decodeSerializableElement(descriptor, yIndex, serializer), + decodeSerializableElement(descriptor, zIndex, serializer) ) } else { var x: T? = null @@ -47,9 +47,9 @@ private inline fun CompositeDecoder.decodeVector( while (true) { when (val i = decodeElementIndex(Vec3iSerializer.descriptor)) { CompositeDecoder.DECODE_DONE -> break - XIndex -> x = decodeSerializableElement(descriptor, i, serializer) - YIndex -> y = decodeSerializableElement(descriptor, i, serializer) - ZIndex -> z = decodeSerializableElement(descriptor, i, serializer) + xIndex -> x = decodeSerializableElement(descriptor, i, serializer) + yIndex -> y = decodeSerializableElement(descriptor, i, serializer) + zIndex -> z = decodeSerializableElement(descriptor, i, serializer) } } constructor(x!!, y!!, z!!) @@ -61,9 +61,9 @@ private fun CompositeEncoder.encodeVector( serializer: SerializationStrategy, triple: Triple ) = apply { - encodeSerializableElement(descriptor, XIndex, serializer, triple.first) - encodeSerializableElement(descriptor, YIndex, serializer, triple.second) - encodeSerializableElement(descriptor, ZIndex, serializer, triple.third) + encodeSerializableElement(descriptor, xIndex, serializer, triple.first) + encodeSerializableElement(descriptor, yIndex, serializer, triple.second) + encodeSerializableElement(descriptor, zIndex, serializer, triple.third) } @ExperimentalSerializationApi From b5be983db1581596f04b8b245282e113d18e6200 Mon Sep 17 00:00:00 2001 From: Jakob K Date: Wed, 12 Oct 2022 00:08:54 +0200 Subject: [PATCH 4/6] Rename `triple()` to `toTriple()` in vector operations --- .../net/silkmc/silk/core/math/vector/VectorOperations.kt | 8 ++++---- .../core/serialization/serializers/VectorSerializer.kt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt index 4123bbfd..6c037ef4 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/math/vector/VectorOperations.kt @@ -19,7 +19,7 @@ operator fun Vec3.times(vec: Vec3): Vec3 = multiply(vec) operator fun Vec3.div(vec: Vec3): Vec3 = Vec3(x / vec.x, y / vec.y, z / vec.z) operator fun Vec3.compareTo(vec: Vec3) = lengthSqr().compareTo(vec.lengthSqr()) -fun Vec3.triple() = Triple(x, y, z) +fun Vec3.toTriple() = Triple(x, y, z) fun Vec3(x: Number, y: Number, z: Number) = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) operator fun Vec3.component1() = x @@ -47,7 +47,7 @@ operator fun Vector3f.times(vec: Vector3f): Vector3f = Vector3f(x() * vec.x(), y operator fun Vector3f.div(vec: Vector3f): Vector3f = Vector3f(x() / vec.x(), y() / vec.y(), z() / vec.z()) operator fun Vector3f.compareTo(vec: Vector3f) = Vec3(this).lengthSqr().compareTo(Vec3(vec).lengthSqr()) -fun Vector3f.triple() = Triple(x, y, z) +fun Vector3f.toTriple() = Triple(x, y, z) fun Vector3f(x: Number, y: Number, z: Number) = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) val Vector3f.x: Float @@ -79,7 +79,7 @@ operator fun Vec3i.div(vec: Vec3i): Vec3i = Vec3i(x / vec.x, y / vec.y, z / vec. operator fun Vec3i.compareTo(vec: Vec3i) = Vec3(x, y, z).lengthSqr().compareTo(Vec3(vec.x, vec.y, vec.z).lengthSqr()) -fun Vec3i.triple() = Triple(x, y, z) +fun Vec3i.toTriple() = Triple(x, y, z) fun Vec3i(x: Number, y: Number, z: Number) = Vec3i(x.toDouble(), y.toDouble(), z.toDouble()) operator fun Vec3i.component1() = x @@ -106,7 +106,7 @@ operator fun Vector3d.compareTo(vec: Vector3d) = Vec3(x, y, z).lengthSqr().compareTo(Vec3(vec.x, vec.y, vec.z).lengthSqr()) fun Vector3d.copy() = Vector3d(x, y, z) -fun Vector3d.triple() = Triple(x, y, z) +fun Vector3d.toTriple() = Triple(x, y, z) fun Vector3d(x: Number, y: Number, z: Number) = Vector3d(x.toDouble(), y.toDouble(), z.toDouble()) operator fun Vector3d.component1() = x diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt index 0121d393..3ca531cc 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt @@ -14,7 +14,7 @@ import kotlinx.serialization.encoding.CompositeEncoder import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import net.minecraft.core.Vec3i -import net.silkmc.silk.core.math.vector.triple +import net.silkmc.silk.core.math.vector.toTriple import net.silkmc.silk.core.serialization.SilkSerializer private const val xIndex = 0 @@ -76,7 +76,7 @@ object Vec3iSerializer : SilkSerializer() { decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vec3i)) override fun serialize(encoder: Encoder, value: Vec3i) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) } @ExperimentalSerializationApi @@ -89,7 +89,7 @@ object Vector3fSerializer : SilkSerializer() { decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3f)) override fun serialize(encoder: Encoder, value: Vector3f) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) } @ExperimentalSerializationApi @@ -102,5 +102,5 @@ object Vector3dSerializer : SilkSerializer() { decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3d)) override fun serialize(encoder: Encoder, value: Vector3d) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.triple()).endStructure(descriptor) + encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) } \ No newline at end of file From 5b20c22090b9f4891d6c5cee51b87ba5951b5f1c Mon Sep 17 00:00:00 2001 From: Jakob K Date: Sat, 26 Nov 2022 18:07:03 +0100 Subject: [PATCH 5/6] feat(core): add delegate serializer class --- .../serialization/SilkDelegateSerializer.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkDelegateSerializer.kt diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkDelegateSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkDelegateSerializer.kt new file mode 100644 index 00000000..3f7a8693 --- /dev/null +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkDelegateSerializer.kt @@ -0,0 +1,24 @@ +package net.silkmc.silk.core.serialization + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +abstract class SilkDelegateSerializer( + private val delegateSerializer: KSerializer, + private val convertTo: T.() -> D, + private val convertFrom: D.() -> T, +) : KSerializer { + + override val descriptor: SerialDescriptor + get() = delegateSerializer.descriptor + + override fun deserialize(decoder: Decoder): T { + return decoder.decodeSerializableValue(delegateSerializer).convertFrom() + } + + override fun serialize(encoder: Encoder, value: T) { + encoder.encodeSerializableValue(delegateSerializer, value.convertTo()) + } +} From e86a0609b5567588552ff50845e279fbdd8bc910 Mon Sep 17 00:00:00 2001 From: Jakob K Date: Sat, 26 Nov 2022 18:07:55 +0100 Subject: [PATCH 6/6] refactor(core): serializer vectors by delegating to pos --- .../serialization/SilkSerializersModule.kt | 25 ++++ .../serializers/VectorSerializer.kt | 108 ++---------------- .../silk/core/world/pos/BasicPositions.kt | 6 + .../test/serialization/VectorSerialization.kt | 17 +++ 4 files changed, 58 insertions(+), 98 deletions(-) create mode 100644 silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkSerializersModule.kt create mode 100644 silk-core/src/test/kotlin/net/silkmc/silk/core/test/serialization/VectorSerialization.kt diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkSerializersModule.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkSerializersModule.kt new file mode 100644 index 00000000..b5f6b829 --- /dev/null +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/SilkSerializersModule.kt @@ -0,0 +1,25 @@ +package net.silkmc.silk.core.serialization + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.cbor.Cbor +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.contextual +import net.silkmc.silk.core.serialization.serializers.Vec3iSerializer +import net.silkmc.silk.core.serialization.serializers.Vector3dSerializer +import net.silkmc.silk.core.serialization.serializers.Vector3fSerializer + +val silkSerializersModule = SerializersModule { + contextual(Vec3iSerializer) + contextual(Vector3fSerializer) + contextual(Vector3dSerializer) +} + +val SilkJson = Json { + serializersModule = silkSerializersModule +} + +@OptIn(ExperimentalSerializationApi::class) +val SilkCbor = Cbor { + serializersModule = silkSerializersModule +} diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt index 3ca531cc..6b71c8ae 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/serialization/serializers/VectorSerializer.kt @@ -2,105 +2,17 @@ package net.silkmc.silk.core.serialization.serializers import com.mojang.math.Vector3d import com.mojang.math.Vector3f -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerializationStrategy -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.descriptors.buildClassSerialDescriptor -import kotlinx.serialization.encoding.CompositeDecoder -import kotlinx.serialization.encoding.CompositeEncoder -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder import net.minecraft.core.Vec3i -import net.silkmc.silk.core.math.vector.toTriple -import net.silkmc.silk.core.serialization.SilkSerializer +import net.silkmc.silk.core.serialization.SilkDelegateSerializer +import net.silkmc.silk.core.world.pos.Pos3d +import net.silkmc.silk.core.world.pos.Pos3f +import net.silkmc.silk.core.world.pos.Pos3i -private const val xIndex = 0 -private const val yIndex = 1 -private const val zIndex = 2 +object Vec3iSerializer : + SilkDelegateSerializer(Pos3i.serializer(), ::Pos3i, Pos3i::toMcVec3i) -private inline fun SilkSerializer<*>.descriptor(serializer: KSerializer) = - buildClassSerialDescriptor(descriptorName) { - element("x", serializer.descriptor) - element("y", serializer.descriptor) - element("z", serializer.descriptor) - } +object Vector3fSerializer : + SilkDelegateSerializer(Pos3f.serializer(), ::Pos3f, Pos3f::toMcVector3f) -@ExperimentalSerializationApi -private inline fun CompositeDecoder.decodeVector( - descriptor: SerialDescriptor, - serializer: DeserializationStrategy, - constructor: (T, T, T) -> U -) = run { - if (decodeSequentially()) { - constructor( - decodeSerializableElement(descriptor, xIndex, serializer), - decodeSerializableElement(descriptor, yIndex, serializer), - decodeSerializableElement(descriptor, zIndex, serializer) - ) - } else { - var x: T? = null - var y: T? = null - var z: T? = null - while (true) { - when (val i = decodeElementIndex(Vec3iSerializer.descriptor)) { - CompositeDecoder.DECODE_DONE -> break - xIndex -> x = decodeSerializableElement(descriptor, i, serializer) - yIndex -> y = decodeSerializableElement(descriptor, i, serializer) - zIndex -> z = decodeSerializableElement(descriptor, i, serializer) - } - } - constructor(x!!, y!!, z!!) - } -} - -private fun CompositeEncoder.encodeVector( - descriptor: SerialDescriptor, - serializer: SerializationStrategy, - triple: Triple -) = apply { - encodeSerializableElement(descriptor, xIndex, serializer, triple.first) - encodeSerializableElement(descriptor, yIndex, serializer, triple.second) - encodeSerializableElement(descriptor, zIndex, serializer, triple.third) -} - -@ExperimentalSerializationApi -object Vec3iSerializer : SilkSerializer() { - private val serializer = Int.serializer() - - override val descriptor = descriptor(serializer) - - override fun deserialize(decoder: Decoder) = - decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vec3i)) - - override fun serialize(encoder: Encoder, value: Vec3i) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) -} - -@ExperimentalSerializationApi -object Vector3fSerializer : SilkSerializer() { - private val serializer = Float.serializer() - - override val descriptor = descriptor(serializer) - - override fun deserialize(decoder: Decoder) = - decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3f)) - - override fun serialize(encoder: Encoder, value: Vector3f) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) -} - -@ExperimentalSerializationApi -object Vector3dSerializer : SilkSerializer() { - private val serializer = Double.serializer() - - override val descriptor = descriptor(serializer) - - override fun deserialize(decoder: Decoder) = - decoder.beginStructure(descriptor).decodeVector(descriptor, serializer, (::Vector3d)) - - override fun serialize(encoder: Encoder, value: Vector3d) = - encoder.beginStructure(descriptor).encodeVector(descriptor, serializer, value.toTriple()).endStructure(descriptor) -} \ No newline at end of file +object Vector3dSerializer : + SilkDelegateSerializer(Pos3d.serializer(), ::Pos3d, Pos3d::toMcVector3d) diff --git a/silk-core/src/main/kotlin/net/silkmc/silk/core/world/pos/BasicPositions.kt b/silk-core/src/main/kotlin/net/silkmc/silk/core/world/pos/BasicPositions.kt index 2ccd7e3c..00caaab5 100644 --- a/silk-core/src/main/kotlin/net/silkmc/silk/core/world/pos/BasicPositions.kt +++ b/silk-core/src/main/kotlin/net/silkmc/silk/core/world/pos/BasicPositions.kt @@ -150,6 +150,8 @@ data class Pos2d(override val x: Double, override val z: Double) : Pos2Dimension @Serializable @SerialName("pos3i") data class Pos3i(override val x: Int, override val y: Int, override val z: Int) : Pos3DimensionalConvertible { + constructor(vec3i: Vec3i) : this(vec3i.x, vec3i.y, vec3i.z) + override fun atY(y: Int) = Pos3i(x, y, z) override fun withoutHeight() = Pos2i(x, z) } @@ -161,6 +163,8 @@ data class Pos3i(override val x: Int, override val y: Int, override val z: Int) @Serializable @SerialName("pos3f") data class Pos3f(override val x: Float, override val y: Float, override val z: Float) : Pos3DimensionalConvertible { + constructor(vector3f: Vector3f) : this(vector3f.x(), vector3f.y(), vector3f.z()) + override fun atY(y: Float) = Pos3f(x, y, z) override fun withoutHeight() = Pos2f(x, z) } @@ -172,6 +176,8 @@ data class Pos3f(override val x: Float, override val y: Float, override val z: F @Serializable @SerialName("pos3d") data class Pos3d(override val x: Double, override val y: Double, override val z: Double) : Pos3DimensionalConvertible { + constructor(vector3d: Vector3d) : this(vector3d.x, vector3d.y, vector3d.z) + override fun atY(y: Double) = Pos3d(x, y, z) override fun withoutHeight() = Pos2d(x, z) } diff --git a/silk-core/src/test/kotlin/net/silkmc/silk/core/test/serialization/VectorSerialization.kt b/silk-core/src/test/kotlin/net/silkmc/silk/core/test/serialization/VectorSerialization.kt new file mode 100644 index 00000000..e7e48d9e --- /dev/null +++ b/silk-core/src/test/kotlin/net/silkmc/silk/core/test/serialization/VectorSerialization.kt @@ -0,0 +1,17 @@ +package net.silkmc.silk.core.test.serialization + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe +import kotlinx.serialization.encodeToString +import net.silkmc.silk.core.math.vector.Vec3i +import net.silkmc.silk.core.serialization.SilkJson + +class VectorSerialization : FunSpec({ + val json = SilkJson + + context("serialize 3d vectors") { + test("blockpos") { + json.encodeToString(Vec3i(1, 2, 3)) shouldBe """{"x":1,"y":2,"z":3}""" + } + } +})