ммм
This commit is contained in:
parent
2d7681628d
commit
2d8e3a7ff5
@ -1,10 +1,13 @@
|
|||||||
package ru.dbotthepony.kstarbound
|
package ru.dbotthepony.kstarbound
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import org.lwjgl.Version
|
import org.lwjgl.Version
|
||||||
import org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose
|
import org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose
|
||||||
import ru.dbotthepony.kstarbound.client.StarboundClient
|
import ru.dbotthepony.kstarbound.client.StarboundClient
|
||||||
import ru.dbotthepony.kstarbound.io.*
|
import ru.dbotthepony.kstarbound.io.*
|
||||||
|
import ru.dbotthepony.kstarbound.io.json.factory.ImmutableCollectionAdapterFactory
|
||||||
import ru.dbotthepony.kstarbound.world.ChunkPos
|
import ru.dbotthepony.kstarbound.world.ChunkPos
|
||||||
import ru.dbotthepony.kstarbound.world.entities.ItemEntity
|
import ru.dbotthepony.kstarbound.world.entities.ItemEntity
|
||||||
import ru.dbotthepony.kstarbound.world.entities.PlayerEntity
|
import ru.dbotthepony.kstarbound.world.entities.PlayerEntity
|
||||||
|
@ -46,6 +46,7 @@ import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter
|
|||||||
import ru.dbotthepony.kstarbound.io.json.Vector2fTypeAdapter
|
import ru.dbotthepony.kstarbound.io.json.Vector2fTypeAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.json.Vector2iTypeAdapter
|
import ru.dbotthepony.kstarbound.io.json.Vector2iTypeAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.json.Vector4iTypeAdapter
|
import ru.dbotthepony.kstarbound.io.json.Vector4iTypeAdapter
|
||||||
|
import ru.dbotthepony.kstarbound.io.json.factory.ImmutableCollectionAdapterFactory
|
||||||
import ru.dbotthepony.kstarbound.math.*
|
import ru.dbotthepony.kstarbound.math.*
|
||||||
import ru.dbotthepony.kvector.vector.Color
|
import ru.dbotthepony.kvector.vector.Color
|
||||||
import java.io.*
|
import java.io.*
|
||||||
@ -145,7 +146,9 @@ object Starbound {
|
|||||||
.setDateFormat(DateFormat.LONG)
|
.setDateFormat(DateFormat.LONG)
|
||||||
.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
|
.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
|
||||||
.setPrettyPrinting()
|
.setPrettyPrinting()
|
||||||
.registerTypeAdapter(Color::class.java, ColorTypeAdapter.nullSafe())
|
.registerTypeAdapter(ColorTypeAdapter.nullSafe())
|
||||||
|
|
||||||
|
.registerTypeAdapterFactory(ImmutableCollectionAdapterFactory)
|
||||||
|
|
||||||
// чтоб строки всегда intern'ились
|
// чтоб строки всегда intern'ились
|
||||||
.registerTypeAdapter(NULLABLE_STRING_ADAPTER)
|
.registerTypeAdapter(NULLABLE_STRING_ADAPTER)
|
||||||
|
@ -2,11 +2,14 @@ package ru.dbotthepony.kstarbound.io.json.builder
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonSyntaxException
|
import com.google.gson.JsonSyntaxException
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.TypeAdapterFactory
|
||||||
import com.google.gson.internal.bind.JsonTreeReader
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
import com.google.gson.internal.bind.TypeAdapters
|
import com.google.gson.internal.bind.TypeAdapters
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonToken
|
import com.google.gson.stream.JsonToken
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
@ -241,13 +244,17 @@ class BuilderAdapter<T : Any> private constructor(
|
|||||||
var mustBePresent: Boolean? = null
|
var mustBePresent: Boolean? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class Builder<T : Any>(val factory: () -> T, vararg fields: KMutableProperty1<T, *>) {
|
class Builder<T : Any>(val factory: () -> T, vararg fields: KMutableProperty1<T, *>) : TypeAdapterFactory {
|
||||||
private val properties = ArrayList<WrappedProperty<T, *>>()
|
private val properties = ArrayList<WrappedProperty<T, *>>()
|
||||||
private val flatProperties = ArrayList<WrappedProperty<T, *>>()
|
private val flatProperties = ArrayList<WrappedProperty<T, *>>()
|
||||||
private val ignoreKeys = ObjectArraySet<String>()
|
private val ignoreKeys = ObjectArraySet<String>()
|
||||||
var extraPropertiesAreFatal = false
|
var extraPropertiesAreFatal = false
|
||||||
var logMisses: Boolean? = null
|
var logMisses: Boolean? = null
|
||||||
|
|
||||||
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Являются ли "лишние" ключи в JSON структуре ошибкой.
|
* Являются ли "лишние" ключи в JSON структуре ошибкой.
|
||||||
*
|
*
|
||||||
|
@ -2,13 +2,16 @@ package ru.dbotthepony.kstarbound.io.json.builder
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParseException
|
import com.google.gson.JsonParseException
|
||||||
import com.google.gson.JsonSyntaxException
|
import com.google.gson.JsonSyntaxException
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.TypeAdapterFactory
|
||||||
import com.google.gson.internal.bind.JsonTreeReader
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
import com.google.gson.internal.bind.TypeAdapters
|
import com.google.gson.internal.bind.TypeAdapters
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonToken
|
import com.google.gson.stream.JsonToken
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
@ -382,7 +385,7 @@ class FactoryAdapter<T : Any> private constructor(
|
|||||||
/**
|
/**
|
||||||
* Позволяет построить класс [FactoryAdapter] на основе заданных параметров
|
* Позволяет построить класс [FactoryAdapter] на основе заданных параметров
|
||||||
*/
|
*/
|
||||||
class Builder<T : Any>(val clazz: KClass<T>) {
|
class Builder<T : Any>(val clazz: KClass<T>) : TypeAdapterFactory {
|
||||||
constructor(clazz: KClass<T>, vararg fields: KProperty1<T, *>) : this(clazz) {
|
constructor(clazz: KClass<T>, vararg fields: KProperty1<T, *>) : this(clazz) {
|
||||||
for (field in fields) {
|
for (field in fields) {
|
||||||
auto(field)
|
auto(field)
|
||||||
@ -391,6 +394,14 @@ class FactoryAdapter<T : Any> private constructor(
|
|||||||
|
|
||||||
private val types = ArrayList<PackedProperty<T, *>>()
|
private val types = ArrayList<PackedProperty<T, *>>()
|
||||||
|
|
||||||
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
|
if (type.rawType == clazz.java) {
|
||||||
|
return build() as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Принимает ли класс *последним* аргументом JSON структуру
|
* Принимает ли класс *последним* аргументом JSON структуру
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.factory
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
|
||||||
|
class ImmutableArrayMapTypeAdapter<K, V>(val keyAdapter: TypeAdapter<K>, val elementAdapter: TypeAdapter<V>) : TypeAdapter<ImmutableMap<K, V>>() {
|
||||||
|
override fun write(out: JsonWriter, value: ImmutableMap<K, V>) {
|
||||||
|
out.beginArray()
|
||||||
|
|
||||||
|
for ((k, v) in value) {
|
||||||
|
keyAdapter.write(out, k)
|
||||||
|
elementAdapter.write(out, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): ImmutableMap<K, V> {
|
||||||
|
reader.beginArray()
|
||||||
|
|
||||||
|
val builder = ImmutableMap.Builder<K, V>()
|
||||||
|
|
||||||
|
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||||
|
builder.put(
|
||||||
|
keyAdapter.read(reader) ?: throw JsonSyntaxException("Nulls as keys are not allowed, near ${reader.path}"),
|
||||||
|
elementAdapter.read(reader) ?: throw JsonSyntaxException("Nulls as values are not allowed, near ${reader.path}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endArray()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.factory
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.TypeAdapterFactory
|
||||||
|
import com.google.gson.internal.`$Gson$Types`
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
|
object ImmutableCollectionAdapterFactory : TypeAdapterFactory {
|
||||||
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
|
when (type.rawType) {
|
||||||
|
ImmutableList::class.java -> {
|
||||||
|
val elementType = `$Gson$Types`.getCollectionElementType(type.type, type.rawType)
|
||||||
|
return ImmutableListTypeAdapter(gson.getAdapter(TypeToken.get(elementType))) as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet::class.java -> {
|
||||||
|
val elementType = `$Gson$Types`.getCollectionElementType(type.type, type.rawType)
|
||||||
|
return ImmutableSetTypeAdapter(gson.getAdapter(TypeToken.get(elementType))) as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableMap::class.java -> {
|
||||||
|
val (elementType0, elementType1) = `$Gson$Types`.getMapKeyAndValueTypes(type.type, type.rawType)
|
||||||
|
|
||||||
|
if (`$Gson$Types`.getRawType(elementType0) == String::class.java) {
|
||||||
|
return ImmutableMapTypeAdapter(gson.getAdapter(TypeToken.get(elementType1))) as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImmutableArrayMapTypeAdapter(
|
||||||
|
gson.getAdapter(TypeToken.get(elementType0)),
|
||||||
|
gson.getAdapter(TypeToken.get(elementType1))
|
||||||
|
) as TypeAdapter<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.factory
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
|
||||||
|
class ImmutableListTypeAdapter<E>(val elementAdapter: TypeAdapter<E>) : TypeAdapter<ImmutableList<E>>() {
|
||||||
|
override fun write(out: JsonWriter, value: ImmutableList<E>) {
|
||||||
|
if (value.size == 1) {
|
||||||
|
elementAdapter.write(out, value[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out.beginArray()
|
||||||
|
|
||||||
|
for (v in value) {
|
||||||
|
elementAdapter.write(out, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): ImmutableList<E> {
|
||||||
|
if (reader.peek() != JsonToken.BEGIN_ARRAY) {
|
||||||
|
// не массив, возможно упрощение структуры "a": [value] -> "a": value
|
||||||
|
return ImmutableList.of(elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls"))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.beginArray()
|
||||||
|
|
||||||
|
val builder = ImmutableList.Builder<E>()
|
||||||
|
|
||||||
|
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||||
|
val readObject = elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
||||||
|
builder.add(readObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endArray()
|
||||||
|
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.factory
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
|
||||||
|
class ImmutableMapTypeAdapter<V>(val elementAdapter: TypeAdapter<V>) : TypeAdapter<ImmutableMap<String, V>>() {
|
||||||
|
override fun write(out: JsonWriter, value: ImmutableMap<String, V>) {
|
||||||
|
out.beginObject()
|
||||||
|
|
||||||
|
for ((k, v) in value) {
|
||||||
|
out.name(k)
|
||||||
|
elementAdapter.write(out, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endObject()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): ImmutableMap<String, V> {
|
||||||
|
reader.beginObject()
|
||||||
|
|
||||||
|
val builder = ImmutableMap.Builder<String, V>()
|
||||||
|
|
||||||
|
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||||
|
builder.put(reader.nextName(), elementAdapter.read(reader) ?: throw JsonSyntaxException("Nulls are not allowed, near ${reader.path}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.factory
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
|
||||||
|
class ImmutableSetTypeAdapter<E>(val elementAdapter: TypeAdapter<E>) : TypeAdapter<ImmutableSet<E>>() {
|
||||||
|
override fun write(out: JsonWriter, value: ImmutableSet<E>) {
|
||||||
|
if (value.size == 1) {
|
||||||
|
elementAdapter.write(out, value.first())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out.beginArray()
|
||||||
|
|
||||||
|
for (v in value) {
|
||||||
|
elementAdapter.write(out, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): ImmutableSet<E> {
|
||||||
|
if (reader.peek() != JsonToken.BEGIN_ARRAY) {
|
||||||
|
// не массив, возможно упрощение структуры "a": [value] -> "a": value
|
||||||
|
return ImmutableSet.of(elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls"))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.beginArray()
|
||||||
|
|
||||||
|
val builder = ImmutableSet.Builder<E>()
|
||||||
|
|
||||||
|
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||||
|
val readObject = elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
||||||
|
builder.add(readObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endArray()
|
||||||
|
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,8 @@ import com.google.gson.stream.JsonReader
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
|
||||||
class LazyTypeProvider<T : Any?>(private val bound: Class<T>) : TypeAdapter<T>() {
|
class LazyTypeProvider<T : Any?>(private val bound: Class<T>, private val resolver: (Class<T>) -> TypeAdapter<T> = Starbound::getTypeAdapter) : TypeAdapter<T>() {
|
||||||
private val resolved by lazy { Starbound.getTypeAdapter(bound) }
|
private val resolved by lazy { resolver(bound) }
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: T) {
|
override fun write(out: JsonWriter, value: T) {
|
||||||
resolved.write(out, value)
|
resolved.write(out, value)
|
||||||
|
Loading…
Reference in New Issue
Block a user