Skip to content

Commit

Permalink
More BlockStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Feb 9, 2024
1 parent 4cdc367 commit 1bf602f
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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<E, C : Collection<E>>(
private val contentSerializer: BlockStorageDataType<E>
) : BlockStorageDataType<C> {

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<E>
}

class ListBlockStorageDataType<E>(contentSerializer: BlockStorageDataType<E>) :
CollectionBlockStorageDataType<E, List<E>>(contentSerializer) {
override fun provideCollection(size: Int): MutableList<E> = ArrayList(size)
}

class SetBlockStorageDataType<E>(contentSerializer: BlockStorageDataType<E>) :
CollectionBlockStorageDataType<E, Set<E>>(contentSerializer) {
override fun provideCollection(size: Int): MutableSet<E> = LinkedHashSet(size)
}

class MapBlockStorageDataType<K, V>(
keySerializer: BlockStorageDataType<K>,
valueSerializer: BlockStorageDataType<V>
) : BlockStorageDataType<Map<K, V>> {

private val internalSerializer = ListBlockStorageDataType(
PairBlockStorageDataType(keySerializer, valueSerializer)
)

override fun serialize(value: Map<K, V>): String =
internalSerializer.serialize(value.toList())

override fun deserialize(value: String): Map<K, V>? = internalSerializer.deserialize(value)?.toMap()
}
Original file line number Diff line number Diff line change
@@ -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<A, B>(
private val serializerA: BlockStorageDataType<A>,
private val serializerB: BlockStorageDataType<B>
) : BlockStorageDataType<Pair<A, B>> {

override fun serialize(value: Pair<A, B>): 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<A, B>? {
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
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,16 @@ inline fun <reified E : Enum<E>> enumSetOf(vararg elements: E): EnumSet<E> {
return set
}

inline fun <reified K : Enum<K>, V> enumMapOf(vararg pairs: Pair<K, V>): EnumMap<K, V> {
val map: EnumMap<K, V> = EnumMap(K::class.java)
map.putAll(pairs)
return map
}

inline fun <reified E : Enum<E>> enumSetOf(): EnumSet<E> = EnumSet.noneOf(E::class.java)

inline fun <reified K : Enum<K>, V> enumMapOf(): EnumMap<K, V> = 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)
Expand All @@ -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
}

0 comments on commit 1bf602f

Please sign in to comment.