Split FriendlyStreams
This commit is contained in:
parent
ea42b19e21
commit
03403eb54d
129
src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BinaryJson.kt
Normal file
129
src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BinaryJson.kt
Normal file
@ -0,0 +1,129 @@
|
||||
package ru.dbotthepony.mc.otm.core.util
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import net.minecraft.nbt.NbtAccounter
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
private const val TYPE_NULL = 0x01
|
||||
private const val TYPE_DOUBLE = 0x02
|
||||
private const val TYPE_BOOLEAN = 0x03
|
||||
private const val TYPE_INT = 0x04
|
||||
private const val TYPE_STRING = 0x05
|
||||
private const val TYPE_ARRAY = 0x06
|
||||
private const val TYPE_OBJECT = 0x07
|
||||
|
||||
/**
|
||||
* Writes binary json to stream in Starbound Object Notation format
|
||||
*
|
||||
* just copy pasted this code from my another project because i was lazy
|
||||
*/
|
||||
fun OutputStream.writeBinaryJson(element: JsonElement) {
|
||||
if (element is JsonObject) {
|
||||
write(TYPE_OBJECT)
|
||||
writeVarIntLE(element.size())
|
||||
|
||||
for ((k, v) in element.entrySet()) {
|
||||
writeBinaryString(k)
|
||||
writeBinaryJson(v)
|
||||
}
|
||||
} else if (element is JsonArray) {
|
||||
write(TYPE_ARRAY)
|
||||
writeVarIntLE(element.size())
|
||||
|
||||
for (v in element) {
|
||||
writeBinaryJson(v)
|
||||
}
|
||||
} else if (element is JsonPrimitive) {
|
||||
if (element.isNumber) {
|
||||
val num = element.asNumber
|
||||
|
||||
if (num is Int || num is Long || num is Short || num is Byte) {
|
||||
write(TYPE_INT)
|
||||
writeVarLongLE(num.toLong())
|
||||
} else if (num is Float || num is Double) {
|
||||
write(TYPE_DOUBLE)
|
||||
writeDouble(num.toDouble())
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown number type: ${num::class.qualifiedName}")
|
||||
}
|
||||
} else if (element.isString) {
|
||||
write(TYPE_STRING)
|
||||
writeBinaryString(element.asString)
|
||||
} else if (element.isBoolean) {
|
||||
write(TYPE_BOOLEAN)
|
||||
write(if (element.asBoolean) 1 else 0)
|
||||
} else {
|
||||
write(TYPE_NULL)
|
||||
}
|
||||
} else if (element is JsonNull) {
|
||||
write(TYPE_NULL)
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown element type: ${element::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads binary json from stream in Starbound Object Notation format
|
||||
*
|
||||
* just copy pasted this code from my another project because i was lazy
|
||||
*/
|
||||
fun InputStream.readBinaryJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): JsonElement {
|
||||
sizeLimit.accountBytes(1L)
|
||||
|
||||
return when (val id = read()) {
|
||||
TYPE_NULL -> JsonNull.INSTANCE
|
||||
TYPE_DOUBLE -> {
|
||||
sizeLimit.accountBytes(8L)
|
||||
JsonPrimitive(readDouble())
|
||||
}
|
||||
TYPE_BOOLEAN -> {
|
||||
sizeLimit.accountBytes(1L)
|
||||
JsonPrimitive(read() > 1)
|
||||
}
|
||||
TYPE_INT -> JsonPrimitive(readVarLongLE(sizeLimit))
|
||||
TYPE_STRING -> JsonPrimitive(readBinaryString(sizeLimit))
|
||||
TYPE_ARRAY -> {
|
||||
val values = readVarIntLE(sizeLimit)
|
||||
|
||||
if (values == 0) return JsonArray()
|
||||
if (values < 0) throw JsonSyntaxException("Tried to read json array with $values elements in it")
|
||||
|
||||
val build = JsonArray(values)
|
||||
for (i in 0 until values) build.add(readBinaryJson(sizeLimit))
|
||||
return build
|
||||
}
|
||||
TYPE_OBJECT -> {
|
||||
val values = readVarIntLE(sizeLimit)
|
||||
if (values == 0) return JsonObject()
|
||||
if (values < 0) throw JsonSyntaxException("Tried to read json object with $values elements in it")
|
||||
|
||||
val build = JsonObject()
|
||||
|
||||
for (i in 0 until values) {
|
||||
val key: String
|
||||
|
||||
try {
|
||||
key = readBinaryString(sizeLimit)
|
||||
} catch(err: Throwable) {
|
||||
throw JsonSyntaxException("Reading json object at $i", err)
|
||||
}
|
||||
|
||||
try {
|
||||
build.add(key, readBinaryJson(sizeLimit))
|
||||
} catch(err: Throwable) {
|
||||
throw JsonSyntaxException("Reading json object at $i with name $key", err)
|
||||
}
|
||||
}
|
||||
|
||||
return build
|
||||
}
|
||||
else -> throw JsonParseException("Unknown element type $id")
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package ru.dbotthepony.mc.otm.core.util
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import io.netty.buffer.ByteBufInputStream
|
||||
import io.netty.buffer.ByteBufOutputStream
|
||||
import io.netty.handler.codec.DecoderException
|
||||
import io.netty.handler.codec.EncoderException
|
||||
import net.minecraft.nbt.NbtAccounter
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
fun FriendlyByteBuf.readBinaryJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): JsonElement {
|
||||
return ByteBufInputStream(this).readBinaryJson(sizeLimit)
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.writeBinaryJson(value: JsonElement) {
|
||||
ByteBufOutputStream(this).writeBinaryJson(value)
|
||||
}
|
||||
|
||||
fun <S> FriendlyByteBuf.writeBinaryJsonWithCodec(codec: Codec<S>, value: S) {
|
||||
writeBinaryJson(codec.encode(value, JsonOps.INSTANCE, JsonOps.INSTANCE.empty())
|
||||
.get().map({ it }, { throw EncoderException("Failed to encode input data: ${it.message()}") }))
|
||||
}
|
||||
|
||||
fun <S> FriendlyByteBuf.readBinaryJsonWithCodec(codec: Codec<S>, sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): S {
|
||||
return codec.decode(JsonOps.INSTANCE, readBinaryJson(sizeLimit))
|
||||
.get().map({ it.first }, { throw DecoderException("Failed to decode data from network: ${it.message()}") })
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.readBinaryComponent(): Component {
|
||||
return Component.Serializer.fromJson(readBinaryJson()) ?: throw NullPointerException("Received null component")
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.writeBinaryComponent(component: Component) {
|
||||
writeBinaryJson(Component.Serializer.toJsonTree(component))
|
||||
}
|
||||
|
||||
// обратный порядок аргументов у лямбда выражения
|
||||
fun <T> FriendlyByteBuf.writeCollection(collection: Collection<T>, writer: (T, FriendlyByteBuf) -> Unit) {
|
||||
writeCollection(collection) { a, b -> writer.invoke(b, a) }
|
||||
}
|
@ -1,22 +1,9 @@
|
||||
package ru.dbotthepony.mc.otm.core.util
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import io.netty.buffer.ByteBufInputStream
|
||||
import io.netty.buffer.ByteBufOutputStream
|
||||
import io.netty.handler.codec.DecoderException
|
||||
import io.netty.handler.codec.EncoderException
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.NbtAccounter
|
||||
import net.minecraft.nbt.NbtIo
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -143,123 +130,6 @@ fun InputStream.readBigDecimal(sizeLimit: NbtAccounter = NbtAccounter(512L)): Bi
|
||||
return BigDecimal(BigInteger(bytes), scale)
|
||||
}
|
||||
|
||||
private const val TYPE_NULL = 0x01
|
||||
private const val TYPE_DOUBLE = 0x02
|
||||
private const val TYPE_BOOLEAN = 0x03
|
||||
private const val TYPE_INT = 0x04
|
||||
private const val TYPE_STRING = 0x05
|
||||
private const val TYPE_ARRAY = 0x06
|
||||
private const val TYPE_OBJECT = 0x07
|
||||
|
||||
/**
|
||||
* Writes binary json to stream in Starbound Object Notation format
|
||||
*
|
||||
* just copy pasted this code from my another project because i was lazy
|
||||
*/
|
||||
fun OutputStream.writeBinaryJson(element: JsonElement) {
|
||||
if (element is JsonObject) {
|
||||
write(TYPE_OBJECT)
|
||||
writeVarIntLE(element.size())
|
||||
|
||||
for ((k, v) in element.entrySet()) {
|
||||
writeBinaryString(k)
|
||||
writeBinaryJson(v)
|
||||
}
|
||||
} else if (element is JsonArray) {
|
||||
write(TYPE_ARRAY)
|
||||
writeVarIntLE(element.size())
|
||||
|
||||
for (v in element) {
|
||||
writeBinaryJson(v)
|
||||
}
|
||||
} else if (element is JsonPrimitive) {
|
||||
if (element.isNumber) {
|
||||
val num = element.asNumber
|
||||
|
||||
if (num is Int || num is Long || num is Short || num is Byte) {
|
||||
write(TYPE_INT)
|
||||
writeVarLongLE(num.toLong())
|
||||
} else if (num is Float || num is Double) {
|
||||
write(TYPE_DOUBLE)
|
||||
writeDouble(num.toDouble())
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown number type: ${num::class.qualifiedName}")
|
||||
}
|
||||
} else if (element.isString) {
|
||||
write(TYPE_STRING)
|
||||
writeBinaryString(element.asString)
|
||||
} else if (element.isBoolean) {
|
||||
write(TYPE_BOOLEAN)
|
||||
write(if (element.asBoolean) 1 else 0)
|
||||
} else {
|
||||
write(TYPE_NULL)
|
||||
}
|
||||
} else if (element is JsonNull) {
|
||||
write(TYPE_NULL)
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown element type: ${element::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads binary json from stream in Starbound Object Notation format
|
||||
*
|
||||
* just copy pasted this code from my another project because i was lazy
|
||||
*/
|
||||
fun InputStream.readBinaryJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): JsonElement {
|
||||
sizeLimit.accountBytes(1L)
|
||||
|
||||
return when (val id = read()) {
|
||||
TYPE_NULL -> JsonNull.INSTANCE
|
||||
TYPE_DOUBLE -> {
|
||||
sizeLimit.accountBytes(8L)
|
||||
JsonPrimitive(readDouble())
|
||||
}
|
||||
TYPE_BOOLEAN -> {
|
||||
sizeLimit.accountBytes(1L)
|
||||
JsonPrimitive(read() > 1)
|
||||
}
|
||||
TYPE_INT -> JsonPrimitive(readVarLongLE(sizeLimit))
|
||||
TYPE_STRING -> JsonPrimitive(readBinaryString(sizeLimit))
|
||||
TYPE_ARRAY -> {
|
||||
val values = readVarIntLE(sizeLimit)
|
||||
|
||||
if (values == 0) return JsonArray()
|
||||
if (values < 0) throw JsonSyntaxException("Tried to read json array with $values elements in it")
|
||||
|
||||
val build = JsonArray(values)
|
||||
for (i in 0 until values) build.add(readBinaryJson(sizeLimit))
|
||||
return build
|
||||
}
|
||||
TYPE_OBJECT -> {
|
||||
val values = readVarIntLE(sizeLimit)
|
||||
if (values == 0) return JsonObject()
|
||||
if (values < 0) throw JsonSyntaxException("Tried to read json object with $values elements in it")
|
||||
|
||||
val build = JsonObject()
|
||||
|
||||
for (i in 0 until values) {
|
||||
val key: String
|
||||
|
||||
try {
|
||||
key = readBinaryString(sizeLimit)
|
||||
} catch(err: Throwable) {
|
||||
throw JsonSyntaxException("Reading json object at $i", err)
|
||||
}
|
||||
|
||||
try {
|
||||
build.add(key, readBinaryJson(sizeLimit))
|
||||
} catch(err: Throwable) {
|
||||
throw JsonSyntaxException("Reading json object at $i with name $key", err)
|
||||
}
|
||||
}
|
||||
|
||||
return build
|
||||
}
|
||||
else -> throw JsonParseException("Unknown element type $id")
|
||||
}
|
||||
}
|
||||
|
||||
fun InputStream.readBinaryComponent(): Component? {
|
||||
return Component.Serializer.fromJson(readBinaryJson())
|
||||
}
|
||||
@ -268,37 +138,6 @@ fun OutputStream.writeBinaryComponent(component: Component) {
|
||||
writeBinaryJson(Component.Serializer.toJsonTree(component))
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.readBinaryJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): JsonElement {
|
||||
return ByteBufInputStream(this).readBinaryJson(sizeLimit)
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.writeBinaryJson(value: JsonElement) {
|
||||
ByteBufOutputStream(this).writeBinaryJson(value)
|
||||
}
|
||||
|
||||
fun <S> FriendlyByteBuf.writeBinaryJsonWithCodec(codec: Codec<S>, value: S) {
|
||||
writeBinaryJson(codec.encode(value, JsonOps.INSTANCE, JsonOps.INSTANCE.empty())
|
||||
.get().map({ it }, { throw EncoderException("Failed to encode input data: ${it.message()}") }))
|
||||
}
|
||||
|
||||
fun <S> FriendlyByteBuf.readBinaryJsonWithCodec(codec: Codec<S>, sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): S {
|
||||
return codec.decode(JsonOps.INSTANCE, readBinaryJson(sizeLimit))
|
||||
.get().map({ it.first }, { throw DecoderException("Failed to decode data from network: ${it.message()}") })
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.readBinaryComponent(): Component {
|
||||
return Component.Serializer.fromJson(readBinaryJson()) ?: throw NullPointerException("Received null component")
|
||||
}
|
||||
|
||||
fun FriendlyByteBuf.writeBinaryComponent(component: Component) {
|
||||
writeBinaryJson(Component.Serializer.toJsonTree(component))
|
||||
}
|
||||
|
||||
// обратный порядок аргументов у лямбда выражения
|
||||
fun <T> FriendlyByteBuf.writeCollection(collection: Collection<T>, writer: (T, FriendlyByteBuf) -> Unit) {
|
||||
writeCollection(collection) { a, b -> writer.invoke(b, a) }
|
||||
}
|
||||
|
||||
fun <S : OutputStream, V> S.writeCollection(collection: Collection<V>, writer: S.(V) -> Unit) {
|
||||
writeVarIntLE(collection.size)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user