From 1bf602fce69951627e1d348019577d372c6d15e9 Mon Sep 17 00:00:00 2001 From: Seggan Date: Fri, 9 Feb 2024 16:22:54 -0500 Subject: [PATCH] More BlockStorage --- .../serial/CollectionBlockStorageDataType.kt | 71 +++++++++++++++++++ .../serial/MiscBlockStorageDataType.kt | 34 +++++++++ .../galactifun/util/RandomUtils.kt | 29 ++++++++ 3 files changed, 134 insertions(+) create mode 100644 src/main/kotlin/io/github/addoncommunity/galactifun/serial/CollectionBlockStorageDataType.kt create mode 100644 src/main/kotlin/io/github/addoncommunity/galactifun/serial/MiscBlockStorageDataType.kt diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/serial/CollectionBlockStorageDataType.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/serial/CollectionBlockStorageDataType.kt new file mode 100644 index 0000000..9695a86 --- /dev/null +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/serial/CollectionBlockStorageDataType.kt @@ -0,0 +1,71 @@ +package io.github.addoncommunity.galactifun.serial + +import io.github.addoncommunity.galactifun.util.decodeBase +import io.github.addoncommunity.galactifun.util.encodeBase +import io.github.seggan.kfun.serial.BlockStorageDataType + +abstract class CollectionBlockStorageDataType>( + private val contentSerializer: BlockStorageDataType +) : BlockStorageDataType { + + override fun serialize(value: C): String { + val sb = StringBuilder() + sb.append(value.size.encodeBase(126)) + sb.append('\u007F') + for (element in value) { + val serialized = contentSerializer.serialize(element) + sb.append(serialized.length.encodeBase(126)) + sb.append('\u007F') + sb.append(serialized) + } + return sb.toString() + } + + override fun deserialize(value: String): C? { + val parts = value.split('\u007F', limit = 2) + if (parts.size != 2) return null + val size = parts[0].decodeBase(126) + val coll = provideCollection(size) + var rest = parts[1] + for (i in 0 until size) { + val nextParts = rest.split('\u007F', limit = 2) + if (nextParts.size != 2) return null + val length = nextParts[0].decodeBase(126) + val serialized = nextParts[1].substring(0, length) + coll.add(contentSerializer.deserialize(serialized) ?: return null) + rest = nextParts[1].substring(length) + } + if (rest.isNotEmpty()) return null + + // You better not break on me + @Suppress("UNCHECKED_CAST") + return coll as C + } + + protected abstract fun provideCollection(size: Int): MutableCollection +} + +class ListBlockStorageDataType(contentSerializer: BlockStorageDataType) : + CollectionBlockStorageDataType>(contentSerializer) { + override fun provideCollection(size: Int): MutableList = ArrayList(size) +} + +class SetBlockStorageDataType(contentSerializer: BlockStorageDataType) : + CollectionBlockStorageDataType>(contentSerializer) { + override fun provideCollection(size: Int): MutableSet = LinkedHashSet(size) +} + +class MapBlockStorageDataType( + keySerializer: BlockStorageDataType, + valueSerializer: BlockStorageDataType +) : BlockStorageDataType> { + + private val internalSerializer = ListBlockStorageDataType( + PairBlockStorageDataType(keySerializer, valueSerializer) + ) + + override fun serialize(value: Map): String = + internalSerializer.serialize(value.toList()) + + override fun deserialize(value: String): Map? = internalSerializer.deserialize(value)?.toMap() +} diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/serial/MiscBlockStorageDataType.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/serial/MiscBlockStorageDataType.kt new file mode 100644 index 0000000..29a4ee5 --- /dev/null +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/serial/MiscBlockStorageDataType.kt @@ -0,0 +1,34 @@ +package io.github.addoncommunity.galactifun.serial + +import io.github.addoncommunity.galactifun.util.decodeBase +import io.github.addoncommunity.galactifun.util.encodeBase +import io.github.seggan.kfun.serial.BlockStorageDataType + +class PairBlockStorageDataType( + private val serializerA: BlockStorageDataType, + private val serializerB: BlockStorageDataType +) : BlockStorageDataType> { + + override fun serialize(value: Pair): String { + val sb = StringBuilder() + val a = serializerA.serialize(value.first) + sb.append(a.length.encodeBase(126)) + sb.append('\u007F') + sb.append(a) + sb.append(serializerB.serialize(value.second)) + return sb.toString() + } + + override fun deserialize(value: String): Pair? { + val parts = value.split('\u007F', limit = 2) + if (parts.size != 2) return null + val length = parts[0].decodeBase(126) + val a = parts[1].substring(0, length) + val b = parts[1].substring(length) + return serializerA.deserialize(a)?.let { da -> + serializerB.deserialize(b)?.let { db -> + da to db + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/util/RandomUtils.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/util/RandomUtils.kt index e2d8e01..65fed84 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/util/RandomUtils.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/util/RandomUtils.kt @@ -42,8 +42,16 @@ inline fun > enumSetOf(vararg elements: E): EnumSet { return set } +inline fun , V> enumMapOf(vararg pairs: Pair): EnumMap { + val map: EnumMap = EnumMap(K::class.java) + map.putAll(pairs) + return map +} + inline fun > enumSetOf(): EnumSet = EnumSet.noneOf(E::class.java) +inline fun , V> enumMapOf(): EnumMap = EnumMap(K::class.java) + inline fun BlockTicker(sync: Boolean, crossinline tick: (Block) -> Unit) = object : BlockTicker() { override fun isSynchronized() = sync override fun tick(b: Block, item: SlimefunItem, data: Config) = tick(b) @@ -65,4 +73,25 @@ fun Entity.galactifunTeleport( removeMetadata("galactifun.teleporting", pluginInstance) it } +} + +fun Int.encodeBase(base: Int): String { + if (this == 0) return "\u0000" + val sb = StringBuilder() + var n = this + while (n > 0) { + sb.append((n % base).toChar()) + n /= base + } + sb.reverse() + return sb.toString() +} + +fun String.decodeBase(base: Int): Int { + var num = 0 + for (i in lastIndex downTo 0) { + num *= base + num += get(i).code + } + return num } \ No newline at end of file