ReferenceAdapter
This commit is contained in:
parent
6fafcd6185
commit
6f8de045e1
@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager
|
|||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.EnumAdapter
|
import ru.dbotthepony.kstarbound.io.json.builder.EnumAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
||||||
|
import ru.dbotthepony.kstarbound.io.json.util.asReference
|
||||||
import ru.dbotthepony.kstarbound.registerTypeAdapter
|
import ru.dbotthepony.kstarbound.registerTypeAdapter
|
||||||
import ru.dbotthepony.kstarbound.util.WriteOnce
|
import ru.dbotthepony.kstarbound.util.WriteOnce
|
||||||
import ru.dbotthepony.kstarbound.world.ITileGetter
|
import ru.dbotthepony.kstarbound.world.ITileGetter
|
||||||
@ -268,6 +269,8 @@ data class RenderTemplate(
|
|||||||
.mapAsObject(RenderTemplate::rules, RenderRuleList::class.java)
|
.mapAsObject(RenderTemplate::rules, RenderRuleList::class.java)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
val CACHE = ADAPTER.asReference()
|
||||||
|
|
||||||
fun registerGson(gsonBuilder: GsonBuilder) {
|
fun registerGson(gsonBuilder: GsonBuilder) {
|
||||||
gsonBuilder.registerTypeAdapter(RenderPiece.ADAPTER)
|
gsonBuilder.registerTypeAdapter(RenderPiece.ADAPTER)
|
||||||
gsonBuilder.registerTypeAdapter(RenderRuleList.ADAPTER)
|
gsonBuilder.registerTypeAdapter(RenderRuleList.ADAPTER)
|
||||||
@ -282,32 +285,5 @@ data class RenderTemplate(
|
|||||||
|
|
||||||
gsonBuilder.registerTypeAdapter(EnumAdapter(RenderRuleList.Combination::class.java))
|
gsonBuilder.registerTypeAdapter(EnumAdapter(RenderRuleList.Combination::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cache = ConcurrentHashMap<String, RenderTemplate>()
|
|
||||||
|
|
||||||
val CACHE = object : TypeAdapter<RenderTemplate>() {
|
|
||||||
override fun write(out: JsonWriter, value: RenderTemplate) {
|
|
||||||
ADAPTER.write(out, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(reader: JsonReader): RenderTemplate {
|
|
||||||
if (reader.peek() != JsonToken.STRING) {
|
|
||||||
throw JsonSyntaxException("Expected string as input for render template cache retriever")
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = reader.nextString()
|
|
||||||
|
|
||||||
if (path[0] != '/') {
|
|
||||||
// относительный путь
|
|
||||||
|
|
||||||
val readingFolder = Starbound.assetFolder ?: throw NullPointerException("Currently read folder is not specified")
|
|
||||||
path = "$readingFolder/$path"
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.computeIfAbsent(path) {
|
|
||||||
return@computeIfAbsent Starbound.GSON.fromJson(Starbound.locate(it).reader(), RenderTemplate::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.util
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Данный [TypeAdapter] реализует возможности чтения данных по "ссылке" на файл.
|
||||||
|
*
|
||||||
|
* К примеру, если в оригинальной структуре может (или обычно) встречаться такое:
|
||||||
|
*
|
||||||
|
* ```json
|
||||||
|
* {
|
||||||
|
* "thing": { ... },
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* и такое:
|
||||||
|
*
|
||||||
|
* ```json
|
||||||
|
* {
|
||||||
|
* "thing": "/path/to/thing.config"
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* То второй вариант будет прочитан из указанного пути и закеширован внутри [ReferenceAdapter]
|
||||||
|
*/
|
||||||
|
class ReferenceAdapter<T>(val parent: TypeAdapter<T>) : TypeAdapter<T>() {
|
||||||
|
private val cache = ConcurrentHashMap<String, T>()
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: T) {
|
||||||
|
parent.write(out, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): T {
|
||||||
|
if (reader.peek() != JsonToken.STRING) {
|
||||||
|
return parent.read(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = reader.nextString()
|
||||||
|
|
||||||
|
if (path[0] != '/') {
|
||||||
|
// относительный путь
|
||||||
|
|
||||||
|
val readingFolder = Starbound.assetFolder ?: throw NullPointerException("Currently read folder is not specified")
|
||||||
|
path = "$readingFolder/$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache.computeIfAbsent(path) {
|
||||||
|
return@computeIfAbsent parent.read(JsonReader(Starbound.locate(it).reader()).also { it.isLenient = true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> TypeAdapter<T>.asReference(): TypeAdapter<T> {
|
||||||
|
return ReferenceAdapter(this)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user