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.io.json.builder.EnumAdapter
|
||||
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.util.WriteOnce
|
||||
import ru.dbotthepony.kstarbound.world.ITileGetter
|
||||
@ -268,6 +269,8 @@ data class RenderTemplate(
|
||||
.mapAsObject(RenderTemplate::rules, RenderRuleList::class.java)
|
||||
.build()
|
||||
|
||||
val CACHE = ADAPTER.asReference()
|
||||
|
||||
fun registerGson(gsonBuilder: GsonBuilder) {
|
||||
gsonBuilder.registerTypeAdapter(RenderPiece.ADAPTER)
|
||||
gsonBuilder.registerTypeAdapter(RenderRuleList.ADAPTER)
|
||||
@ -282,32 +285,5 @@ data class RenderTemplate(
|
||||
|
||||
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