я даже не знаю что сказать про динамические прототипы...
This commit is contained in:
parent
df4937f1df
commit
ebdf0aa642
@ -1,9 +1,12 @@
|
|||||||
package ru.dbotthepony.kstarbound
|
package ru.dbotthepony.kstarbound
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonPrimitive
|
||||||
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.defs.item.DynamicItemDefinition
|
||||||
import ru.dbotthepony.kstarbound.io.BTreeDB
|
import ru.dbotthepony.kstarbound.io.BTreeDB
|
||||||
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
|
||||||
@ -86,7 +89,7 @@ fun main() {
|
|||||||
val getMat = starbound.tilesByID[materialID]
|
val getMat = starbound.tilesByID[materialID]
|
||||||
|
|
||||||
if (getMat != null) {
|
if (getMat != null) {
|
||||||
chunk.foreground[x, y].material = getMat
|
chunk.foreground[x, y].material = getMat.value
|
||||||
hitTile = true
|
hitTile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +105,7 @@ fun main() {
|
|||||||
chunk.foreground[x, y].setHueShift(colorShift)
|
chunk.foreground[x, y].setHueShift(colorShift)
|
||||||
|
|
||||||
if (getModifier != null && getMat != null) {
|
if (getModifier != null && getMat != null) {
|
||||||
chunk.foreground[x, y].modifier = getModifier
|
chunk.foreground[x, y].modifier = getModifier.value
|
||||||
}
|
}
|
||||||
|
|
||||||
val modifierHueShift = reader.readUnsignedByte()
|
val modifierHueShift = reader.readUnsignedByte()
|
||||||
@ -113,7 +116,7 @@ fun main() {
|
|||||||
val getMat2 = starbound.tilesByID[materialID2]
|
val getMat2 = starbound.tilesByID[materialID2]
|
||||||
|
|
||||||
if (getMat2 != null) {
|
if (getMat2 != null) {
|
||||||
chunk.background[x, y].material = getMat2
|
chunk.background[x, y].material = getMat2.value
|
||||||
hitTile = true
|
hitTile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +130,7 @@ fun main() {
|
|||||||
val getModifier2 = starbound.tileModifiersByID[modifier2]
|
val getModifier2 = starbound.tileModifiersByID[modifier2]
|
||||||
|
|
||||||
if (getModifier2 != null && getMat2 != null) {
|
if (getModifier2 != null && getMat2 != null) {
|
||||||
chunk.background[x, y].modifier = getModifier2
|
chunk.background[x, y].modifier = getModifier2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.background[x, y].color = colorVariant2
|
chunk.background[x, y].color = colorVariant2
|
||||||
@ -151,7 +154,7 @@ fun main() {
|
|||||||
val getLiquid = starbound.liquidByID[liquid]
|
val getLiquid = starbound.liquidByID[liquid]
|
||||||
|
|
||||||
if (getLiquid != null) {
|
if (getLiquid != null) {
|
||||||
val state = chunk.setLiquid(x, y, getLiquid)!!
|
val state = chunk.setLiquid(x, y, getLiquid.value)!!
|
||||||
|
|
||||||
state.isInfinite = liquidIsInfinite
|
state.isInfinite = liquidIsInfinite
|
||||||
state.pressure = liquidPressure
|
state.pressure = liquidPressure
|
||||||
@ -178,7 +181,7 @@ fun main() {
|
|||||||
val rand = java.util.Random()
|
val rand = java.util.Random()
|
||||||
|
|
||||||
for (i in 0 .. 10) {
|
for (i in 0 .. 10) {
|
||||||
val item = ItemEntity(client.world!!, item)
|
val item = ItemEntity(client.world!!, item.value)
|
||||||
|
|
||||||
item.position = Vector2d(600.0 + 16.0 + i, 721.0 + 48.0)
|
item.position = Vector2d(600.0 + 16.0 + i, 721.0 + 48.0)
|
||||||
item.spawn()
|
item.spawn()
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package ru.dbotthepony.kstarbound
|
package ru.dbotthepony.kstarbound
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
import it.unimi.dsi.fastutil.ints.IntCollection
|
import it.unimi.dsi.fastutil.ints.IntCollection
|
||||||
@ -10,35 +13,57 @@ import it.unimi.dsi.fastutil.objects.ObjectCollection
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectIterator
|
import it.unimi.dsi.fastutil.objects.ObjectIterator
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectSet
|
import it.unimi.dsi.fastutil.objects.ObjectSet
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
|
import ru.dbotthepony.kstarbound.api.IStarboundFile
|
||||||
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class ObjectRegistry<T>(val name: String, val key: (T) -> String, val intKey: ((T) -> Int)? = null) {
|
inline fun <reified T : Any> ObjectRegistry(name: String, noinline key: (T) -> String, noinline intKey: ((T) -> Int)? = null): ObjectRegistry<T> {
|
||||||
private val objects = Object2ObjectOpenHashMap<String, T>()
|
return ObjectRegistry(T::class, name, key, intKey)
|
||||||
private val intObjects = Int2ObjectOpenHashMap<T>()
|
}
|
||||||
|
|
||||||
private val origins = Object2ObjectOpenHashMap<String, Any>()
|
class RegistryObject<T : Any>(val value: T, private val json: JsonObject, val file: IStarboundFile, val gson: Gson, val pathStack: PathStack) {
|
||||||
private val intOrigins = Int2ObjectOpenHashMap<Any>()
|
fun copy(): JsonObject {
|
||||||
|
return json.deepCopy()
|
||||||
|
}
|
||||||
|
|
||||||
val view: Map<String, T> = Collections.unmodifiableMap(objects)
|
override fun equals(other: Any?): Boolean {
|
||||||
val intView = object : Int2ObjectMap<T> {
|
return other is RegistryObject<*> && other.value == value && other.json == json
|
||||||
override fun get(key: Int): T? = intObjects[key]
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return value.hashCode().rotateRight(13) xor json.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "RegistryObject[$value from $file]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectRegistry<T : Any>(val clazz: KClass<T>, val name: String, val key: (T) -> String, val intKey: ((T) -> Int)? = null) {
|
||||||
|
private val objects = Object2ObjectOpenHashMap<String, RegistryObject<T>>()
|
||||||
|
private val intObjects = Int2ObjectOpenHashMap<RegistryObject<T>>()
|
||||||
|
|
||||||
|
val view: Map<String, RegistryObject<T>> = Collections.unmodifiableMap(objects)
|
||||||
|
val intView = object : Int2ObjectMap<RegistryObject<T>> {
|
||||||
|
override fun get(key: Int): RegistryObject<T>? = intObjects[key]
|
||||||
override fun containsKey(key: Int) = intObjects.containsKey(key)
|
override fun containsKey(key: Int) = intObjects.containsKey(key)
|
||||||
override fun defaultReturnValue(rv: T) = throw UnsupportedOperationException()
|
override fun defaultReturnValue(rv: RegistryObject<T>) = throw UnsupportedOperationException()
|
||||||
override fun defaultReturnValue(): T = throw UnsupportedOperationException()
|
override fun defaultReturnValue(): RegistryObject<T> = throw UnsupportedOperationException()
|
||||||
override fun containsValue(value: T) = intObjects.containsValue(value)
|
override fun containsValue(value: RegistryObject<T>) = intObjects.containsValue(value)
|
||||||
override fun isEmpty() = intObjects.isEmpty()
|
override fun isEmpty() = intObjects.isEmpty()
|
||||||
override fun putAll(from: Map<out Int, T>) = throw UnsupportedOperationException()
|
override fun putAll(from: Map<out Int, RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private val int2ObjectEntrySet: ObjectSet<Int2ObjectMap.Entry<T>> = object : ObjectSet<Int2ObjectMap.Entry<T>> {
|
private val int2ObjectEntrySet: ObjectSet<Int2ObjectMap.Entry<RegistryObject<T>>> = object : ObjectSet<Int2ObjectMap.Entry<RegistryObject<T>>> {
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = intObjects.int2ObjectEntrySet().size
|
get() = intObjects.int2ObjectEntrySet().size
|
||||||
|
|
||||||
override fun add(element: Int2ObjectMap.Entry<T>) = throw UnsupportedOperationException()
|
override fun add(element: Int2ObjectMap.Entry<RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
override fun addAll(elements: Collection<Int2ObjectMap.Entry<T>>) = throw UnsupportedOperationException()
|
override fun addAll(elements: Collection<Int2ObjectMap.Entry<RegistryObject<T>>>) = throw UnsupportedOperationException()
|
||||||
override fun clear() = throw UnsupportedOperationException()
|
override fun clear() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun iterator(): ObjectIterator<Int2ObjectMap.Entry<T>> {
|
override fun iterator(): ObjectIterator<Int2ObjectMap.Entry<RegistryObject<T>>> {
|
||||||
return object : ObjectIterator<Int2ObjectMap.Entry<T>> {
|
return object : ObjectIterator<Int2ObjectMap.Entry<RegistryObject<T>>> {
|
||||||
val iterator = intObjects.int2ObjectEntrySet().iterator()
|
val iterator = intObjects.int2ObjectEntrySet().iterator()
|
||||||
override fun hasNext() = iterator.hasNext()
|
override fun hasNext() = iterator.hasNext()
|
||||||
override fun remove() = throw UnsupportedOperationException()
|
override fun remove() = throw UnsupportedOperationException()
|
||||||
@ -46,15 +71,15 @@ class ObjectRegistry<T>(val name: String, val key: (T) -> String, val intKey: ((
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contains(element: Int2ObjectMap.Entry<T>) = intObjects.int2ObjectEntrySet().contains(element)
|
override fun contains(element: Int2ObjectMap.Entry<RegistryObject<T>>) = intObjects.int2ObjectEntrySet().contains(element)
|
||||||
override fun containsAll(elements: Collection<Int2ObjectMap.Entry<T>>) = intObjects.int2ObjectEntrySet().containsAll(elements)
|
override fun containsAll(elements: Collection<Int2ObjectMap.Entry<RegistryObject<T>>>) = intObjects.int2ObjectEntrySet().containsAll(elements)
|
||||||
override fun isEmpty() = intObjects.int2ObjectEntrySet().isEmpty()
|
override fun isEmpty() = intObjects.int2ObjectEntrySet().isEmpty()
|
||||||
override fun remove(element: Int2ObjectMap.Entry<T>) = throw UnsupportedOperationException()
|
override fun remove(element: Int2ObjectMap.Entry<RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
override fun removeAll(elements: Collection<Int2ObjectMap.Entry<T>>) = throw UnsupportedOperationException()
|
override fun removeAll(elements: Collection<Int2ObjectMap.Entry<RegistryObject<T>>>) = throw UnsupportedOperationException()
|
||||||
override fun retainAll(elements: Collection<Int2ObjectMap.Entry<T>>) = throw UnsupportedOperationException()
|
override fun retainAll(elements: Collection<Int2ObjectMap.Entry<RegistryObject<T>>>) = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun int2ObjectEntrySet(): ObjectSet<Int2ObjectMap.Entry<T>> {
|
override fun int2ObjectEntrySet(): ObjectSet<Int2ObjectMap.Entry<RegistryObject<T>>> {
|
||||||
return int2ObjectEntrySet
|
return int2ObjectEntrySet
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,82 +114,69 @@ class ObjectRegistry<T>(val name: String, val key: (T) -> String, val intKey: ((
|
|||||||
get() = intObjects.keys.size
|
get() = intObjects.keys.size
|
||||||
}
|
}
|
||||||
|
|
||||||
override val values: ObjectCollection<T> = object : ObjectCollection<T> {
|
override val values: ObjectCollection<RegistryObject<T>> = object : ObjectCollection<RegistryObject<T>> {
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = intObjects.values.size
|
get() = intObjects.values.size
|
||||||
|
|
||||||
override fun add(element: T) = throw UnsupportedOperationException()
|
override fun add(element: RegistryObject<T>) = throw UnsupportedOperationException()
|
||||||
override fun addAll(elements: Collection<T>) = throw UnsupportedOperationException()
|
override fun addAll(elements: Collection<RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
override fun clear() = throw UnsupportedOperationException()
|
override fun clear() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun iterator(): ObjectIterator<T> {
|
override fun iterator(): ObjectIterator<RegistryObject<T>> {
|
||||||
return object : ObjectIterator<T> {
|
return object : ObjectIterator<RegistryObject<T>> {
|
||||||
val iterator = intObjects.values.iterator()
|
val iterator = intObjects.values.iterator()
|
||||||
override fun hasNext() = iterator.hasNext()
|
override fun hasNext() = iterator.hasNext()
|
||||||
override fun next(): T = iterator.next()
|
override fun next(): RegistryObject<T> = iterator.next()
|
||||||
override fun remove() = throw UnsupportedOperationException()
|
override fun remove() = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contains(element: T) = intObjects.values.contains(element)
|
override fun contains(element: RegistryObject<T>) = intObjects.values.contains(element)
|
||||||
override fun containsAll(elements: Collection<T>) = intObjects.values.containsAll(elements)
|
override fun containsAll(elements: Collection<RegistryObject<T>>) = intObjects.values.containsAll(elements)
|
||||||
override fun isEmpty() = intObjects.values.isEmpty()
|
override fun isEmpty() = intObjects.values.isEmpty()
|
||||||
override fun remove(element: T) = throw UnsupportedOperationException()
|
override fun remove(element: RegistryObject<T>) = throw UnsupportedOperationException()
|
||||||
override fun removeAll(elements: Collection<T>) = throw UnsupportedOperationException()
|
override fun removeAll(elements: Collection<RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
override fun retainAll(elements: Collection<T>) = throw UnsupportedOperationException()
|
override fun retainAll(elements: Collection<RegistryObject<T>>) = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = intObjects.size
|
get() = intObjects.size
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearOrigins() {
|
|
||||||
origins.clear()
|
|
||||||
intOrigins.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
clearOrigins()
|
|
||||||
objects.clear()
|
objects.clear()
|
||||||
intObjects.clear()
|
intObjects.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(value: T, origin: Any? = null): Boolean {
|
fun add(gson: Gson, file: IStarboundFile, pathStack: PathStack): Boolean {
|
||||||
val key = this.key.invoke(value)
|
return pathStack(file.computeDirectory()) {
|
||||||
|
val elem = gson.fromJson(file.reader(), JsonObject::class.java)
|
||||||
|
val value = gson.fromJson<T>(JsonTreeReader(elem), clazz.java)
|
||||||
|
add(RegistryObject(value, elem, file, gson, pathStack))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(value: T, json: JsonObject, file: IStarboundFile, gson: Gson, pathStack: PathStack): Boolean {
|
||||||
|
return add(RegistryObject(value, json, file, gson, pathStack))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun add(value: RegistryObject<T>): Boolean {
|
||||||
|
val key = this.key.invoke(value.value)
|
||||||
|
|
||||||
val existing = objects.put(key, value)
|
val existing = objects.put(key, value)
|
||||||
|
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
val oldOrigin = origins[key]
|
LOGGER.warn("Registry $name already has object with key $key! Overwriting. (old originated from ${existing.file}, new originate from ${value.file}).")
|
||||||
|
|
||||||
if (origin == null && oldOrigin == null)
|
|
||||||
LOGGER.warn("Registry $name already has object with key $key! Overwriting.")
|
|
||||||
else if (origin == null)
|
|
||||||
LOGGER.warn("Registry $name already has object with key $key! Overwriting. (old originated from $oldOrigin)")
|
|
||||||
else
|
|
||||||
LOGGER.warn("Registry $name already has object with key $key! Overwriting. (old originated from $oldOrigin, new originate from $origin).")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin == null)
|
|
||||||
origins.remove(key)
|
|
||||||
else
|
|
||||||
origins[key] = origin
|
|
||||||
|
|
||||||
if (this.intKey == null)
|
if (this.intKey == null)
|
||||||
return existing != null
|
return existing != null
|
||||||
|
|
||||||
val intKey = this.intKey.invoke(value)
|
val intKey = this.intKey.invoke(value.value)
|
||||||
val intExisting = intObjects.put(intKey, value)
|
val intExisting = intObjects.put(intKey, value)
|
||||||
|
|
||||||
if (intExisting != null) {
|
if (intExisting != null) {
|
||||||
val oldOrigin = intOrigins[intKey]
|
LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${this.key.invoke(intExisting.value)})! Overwriting. (old originated from ${intExisting.file}, new originate from ${value.file}).")
|
||||||
|
|
||||||
if (origin == null && oldOrigin == null)
|
|
||||||
LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${this.key.invoke(intExisting)})! Overwriting.")
|
|
||||||
else if (origin == null)
|
|
||||||
LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${this.key.invoke(intExisting)})! Overwriting. (old originated from $oldOrigin)")
|
|
||||||
else
|
|
||||||
LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${this.key.invoke(intExisting)})! Overwriting. (old originated from $oldOrigin, new originate from $origin).")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return existing != null || intExisting != null
|
return existing != null || intExisting != null
|
||||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.kstarbound
|
|||||||
import com.google.common.collect.Interner
|
import com.google.common.collect.Interner
|
||||||
import com.google.common.collect.Interners
|
import com.google.common.collect.Interners
|
||||||
import com.google.gson.*
|
import com.google.gson.*
|
||||||
|
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.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
@ -53,7 +54,7 @@ import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementationTypeFactory
|
|||||||
import ru.dbotthepony.kstarbound.io.json.factory.ArrayListAdapterFactory
|
import ru.dbotthepony.kstarbound.io.json.factory.ArrayListAdapterFactory
|
||||||
import ru.dbotthepony.kstarbound.io.json.factory.ImmutableCollectionAdapterFactory
|
import ru.dbotthepony.kstarbound.io.json.factory.ImmutableCollectionAdapterFactory
|
||||||
import ru.dbotthepony.kstarbound.math.*
|
import ru.dbotthepony.kstarbound.math.*
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
import ru.dbotthepony.kstarbound.util.WriteOnce
|
import ru.dbotthepony.kstarbound.util.WriteOnce
|
||||||
import java.io.*
|
import java.io.*
|
||||||
@ -70,7 +71,7 @@ class Starbound : ISBFileLocator {
|
|||||||
private val logger = LogManager.getLogger()
|
private val logger = LogManager.getLogger()
|
||||||
|
|
||||||
val stringInterner: Interner<String> = Interners.newWeakInterner()
|
val stringInterner: Interner<String> = Interners.newWeakInterner()
|
||||||
val pathStack = AssetPathStack(stringInterner)
|
val pathStack = PathStack(stringInterner)
|
||||||
|
|
||||||
private val _tiles = ObjectRegistry("tiles", TileDefinition::materialName, TileDefinition::materialId)
|
private val _tiles = ObjectRegistry("tiles", TileDefinition::materialName, TileDefinition::materialId)
|
||||||
val tiles = _tiles.view
|
val tiles = _tiles.view
|
||||||
@ -296,9 +297,8 @@ class Starbound : ISBFileLocator {
|
|||||||
logger.info("Loaded $name in ${System.currentTimeMillis() - time}ms")
|
logger.info("Loaded $name in ${System.currentTimeMillis() - time}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> loadStage(
|
private fun <T : Any> loadStage(
|
||||||
callback: (Boolean, Boolean, String) -> Unit,
|
callback: (Boolean, Boolean, String) -> Unit,
|
||||||
clazz: Class<T>,
|
|
||||||
registry: ObjectRegistry<T>,
|
registry: ObjectRegistry<T>,
|
||||||
files: List<IStarboundFile>,
|
files: List<IStarboundFile>,
|
||||||
) {
|
) {
|
||||||
@ -306,8 +306,7 @@ class Starbound : ISBFileLocator {
|
|||||||
for (listedFile in files) {
|
for (listedFile in files) {
|
||||||
try {
|
try {
|
||||||
it("Loading $listedFile")
|
it("Loading $listedFile")
|
||||||
val def = pathStack(listedFile.computeDirectory()) { gson.fromJson(listedFile.reader(), clazz) }
|
registry.add(gson, listedFile, pathStack)
|
||||||
registry.add(def, listedFile)
|
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
logger.error("Loading ${registry.name} definition file $listedFile", err)
|
logger.error("Loading ${registry.name} definition file $listedFile", err)
|
||||||
}
|
}
|
||||||
@ -391,12 +390,12 @@ class Starbound : ISBFileLocator {
|
|||||||
|
|
||||||
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
loadStage(callback, this::loadItemDefinitions, "item definitions")
|
||||||
|
|
||||||
loadStage(callback, TileDefinition::class.java, _tiles, ext2files["material"] ?: listOf())
|
loadStage(callback, _tiles, ext2files["material"] ?: listOf())
|
||||||
loadStage(callback, MaterialModifier::class.java, _tileModifiers, ext2files["matmod"] ?: listOf())
|
loadStage(callback, _tileModifiers, ext2files["matmod"] ?: listOf())
|
||||||
loadStage(callback, LiquidDefinition::class.java, _liquid, ext2files["liquid"] ?: listOf())
|
loadStage(callback, _liquid, ext2files["liquid"] ?: listOf())
|
||||||
loadStage(callback, StatusEffectDefinition::class.java, _statusEffects, ext2files["statuseffect"] ?: listOf())
|
loadStage(callback, _statusEffects, ext2files["statuseffect"] ?: listOf())
|
||||||
loadStage(callback, Species::class.java, _species, ext2files["species"] ?: listOf())
|
loadStage(callback, _species, ext2files["species"] ?: listOf())
|
||||||
loadStage(callback, ParticleDefinition::class.java, _particles, ext2files["particle"] ?: listOf())
|
loadStage(callback, _particles, ext2files["particle"] ?: listOf())
|
||||||
|
|
||||||
pathStack.block("/") {
|
pathStack.block("/") {
|
||||||
playerDefinition = gson.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
playerDefinition = gson.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
||||||
@ -456,8 +455,9 @@ class Starbound : ISBFileLocator {
|
|||||||
for (listedFile in fs.explore().filter { it.isFile }.filter { f -> files.keys.any { f.name.endsWith(it) } }) {
|
for (listedFile in fs.explore().filter { it.isFile }.filter { f -> files.keys.any { f.name.endsWith(it) } }) {
|
||||||
try {
|
try {
|
||||||
callback("Loading $listedFile")
|
callback("Loading $listedFile")
|
||||||
val def: ItemPrototype = pathStack(listedFile.computeDirectory()) { gson.fromJson(listedFile.reader(), files.entries.first { listedFile.name.endsWith(it.key) }.value) }
|
val json = gson.fromJson(listedFile.reader(), JsonObject::class.java)
|
||||||
_items.add(def, listedFile)
|
val def: ItemPrototype = pathStack(listedFile.computeDirectory()) { gson.fromJson(JsonTreeReader(json), files.entries.first { listedFile.name.endsWith(it.key) }.value) }
|
||||||
|
_items.add(def, json, listedFile, gson, pathStack)
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
logger.error("Loading item definition file $listedFile", err)
|
logger.error("Loading item definition file $listedFile", err)
|
||||||
}
|
}
|
||||||
|
@ -72,14 +72,14 @@ class TileRenderers(val client: StarboundClient) {
|
|||||||
fun getTileRenderer(defName: String): TileRenderer {
|
fun getTileRenderer(defName: String): TileRenderer {
|
||||||
return tileRenderersCache.computeIfAbsent(defName) {
|
return tileRenderersCache.computeIfAbsent(defName) {
|
||||||
val def = client.starbound.tiles[defName] // TODO: Пустой рендерер
|
val def = client.starbound.tiles[defName] // TODO: Пустой рендерер
|
||||||
return@computeIfAbsent TileRenderer(this, def!!)
|
return@computeIfAbsent TileRenderer(this, def!!.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getModifierRenderer(defName: String): TileRenderer {
|
fun getModifierRenderer(defName: String): TileRenderer {
|
||||||
return modifierRenderersCache.computeIfAbsent(defName) {
|
return modifierRenderersCache.computeIfAbsent(defName) {
|
||||||
val def = client.starbound.tileModifiers[defName] // TODO: Пустой рендерер
|
val def = client.starbound.tileModifiers[defName] // TODO: Пустой рендерер
|
||||||
return@computeIfAbsent TileRenderer(this, def!!)
|
return@computeIfAbsent TileRenderer(this, def!!.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@ import com.google.gson.stream.JsonToken
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
import ru.dbotthepony.kstarbound.api.ISBFileLocator
|
import ru.dbotthepony.kstarbound.api.ISBFileLocator
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import java.io.Reader
|
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@ -20,7 +19,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
*
|
*
|
||||||
* Созданный [TypeAdapter] имеет встроенный кеш.
|
* Созданный [TypeAdapter] имеет встроенный кеш.
|
||||||
*/
|
*/
|
||||||
class AssetReferenceFactory(val remapper: AssetPathStack, val locator: ISBFileLocator) : TypeAdapterFactory {
|
class AssetReferenceFactory(val remapper: PathStack, val locator: ISBFileLocator) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == AssetReference::class.java) {
|
if (type.rawType == AssetReference::class.java) {
|
||||||
val param = type.type as? ParameterizedType ?: return null
|
val param = type.type as? ParameterizedType ?: return null
|
||||||
|
@ -6,9 +6,9 @@ import com.google.gson.TypeAdapterFactory
|
|||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
|
|
||||||
class DirectAssetReferenceFactory(val remapper: AssetPathStack) : TypeAdapterFactory {
|
class DirectAssetReferenceFactory(val remapper: PathStack) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == DirectAssetReference::class.java) {
|
if (type.rawType == DirectAssetReference::class.java) {
|
||||||
return object : TypeAdapter<DirectAssetReference>() {
|
return object : TypeAdapter<DirectAssetReference>() {
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.defs
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import ru.dbotthepony.kstarbound.RegistryObject
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
|
private fun merge(destination: JsonObject, source: JsonObject) {
|
||||||
|
for ((k, v) in source.entrySet()) {
|
||||||
|
if (v is JsonObject) {
|
||||||
|
val original = destination[k]
|
||||||
|
|
||||||
|
if (original is JsonObject) {
|
||||||
|
merge(original, v)
|
||||||
|
} else {
|
||||||
|
destination.add(k, v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
destination.add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DynamicDefinition<Def : Any>(val original: RegistryObject<Def>) {
|
||||||
|
private var isDirty = false
|
||||||
|
private var dynamicData = JsonObject()
|
||||||
|
|
||||||
|
fun markDirty() {
|
||||||
|
isDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var def: Def = original.value
|
||||||
|
get() {
|
||||||
|
if (isDirty) {
|
||||||
|
synchronized(this) {
|
||||||
|
if (!isDirty) return field
|
||||||
|
|
||||||
|
val copy = original.copy()
|
||||||
|
merge(copy, dynamicData)
|
||||||
|
|
||||||
|
original.pathStack(original.file.computeDirectory()) {
|
||||||
|
field = original.gson.fromJson(JsonTreeReader(copy), field::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
isDirty = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun setJson(saveInput: JsonObject) {
|
||||||
|
if (saveInput == dynamicData) return
|
||||||
|
sanitize(saveInput)
|
||||||
|
if (saveInput == dynamicData) return
|
||||||
|
isDirty = true
|
||||||
|
dynamicData = saveInput
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun sanitize(saveInput: JsonObject)
|
||||||
|
}
|
@ -10,6 +10,7 @@ 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
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap
|
||||||
|
import ru.dbotthepony.kstarbound.RegistryObject
|
||||||
import java.lang.ref.Reference
|
import java.lang.ref.Reference
|
||||||
import java.lang.ref.ReferenceQueue
|
import java.lang.ref.ReferenceQueue
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
@ -18,7 +19,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
class RegistryReferenceFactory : TypeAdapterFactory {
|
class RegistryReferenceFactory : TypeAdapterFactory {
|
||||||
private val types = Reference2ObjectArrayMap<Class<*>, (String) -> Nothing?>()
|
private val types = Reference2ObjectArrayMap<Class<*>, (String) -> RegistryObject<Nothing>?>()
|
||||||
private var isLenient = false
|
private var isLenient = false
|
||||||
|
|
||||||
fun lenient(): RegistryReferenceFactory {
|
fun lenient(): RegistryReferenceFactory {
|
||||||
@ -26,12 +27,12 @@ class RegistryReferenceFactory : TypeAdapterFactory {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> add(clazz: Class<T>, resolver: (String) -> T?): RegistryReferenceFactory {
|
fun <T : Any> add(clazz: Class<T>, resolver: (String) -> RegistryObject<T>?): RegistryReferenceFactory {
|
||||||
check(types.put(clazz, resolver as (String) -> Nothing?) == null) { "Already has resolver for class $clazz!" }
|
check(types.put(clazz, resolver as (String) -> RegistryObject<Nothing>?) == null) { "Already has resolver for class $clazz!" }
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> add(noinline resolver: (String) -> T?) = add(T::class.java, resolver)
|
inline fun <reified T: Any> add(noinline resolver: (String) -> RegistryObject<T>?) = add(T::class.java, resolver)
|
||||||
|
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == RegistryReference::class.java) {
|
if (type.rawType == RegistryReference::class.java) {
|
||||||
@ -45,7 +46,7 @@ class RegistryReferenceFactory : TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegistryReferenceTypeAdapter<T>(val resolver: (String) -> T?, val strings: TypeAdapter<String>) : TypeAdapter<RegistryReference<T>>() {
|
class RegistryReferenceTypeAdapter<T : Any>(val resolver: (String) -> RegistryObject<T>?, val strings: TypeAdapter<String>) : TypeAdapter<RegistryReference<T>>() {
|
||||||
override fun write(out: JsonWriter, value: RegistryReference<T>?) {
|
override fun write(out: JsonWriter, value: RegistryReference<T>?) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
out.nullValue()
|
out.nullValue()
|
||||||
@ -65,21 +66,21 @@ class RegistryReferenceTypeAdapter<T>(val resolver: (String) -> T?, val strings:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RegistryReference<T>(val name: String, val resolver: (String) -> T?) : Supplier<T?>, () -> T?, Lazy<T?> {
|
data class RegistryReference<T : Any>(val name: String, val resolver: (String) -> RegistryObject<T>?) : Supplier<RegistryObject<T>?>, () -> RegistryObject<T>?, Lazy<RegistryObject<T>?> {
|
||||||
private val lazy = lazy { resolver.invoke(name) }
|
private val lazy = lazy { resolver.invoke(name) }
|
||||||
|
|
||||||
override fun get(): T? {
|
override fun get(): RegistryObject<T>? {
|
||||||
return lazy.value
|
return lazy.value
|
||||||
}
|
}
|
||||||
|
|
||||||
override val value: T?
|
override val value: RegistryObject<T>?
|
||||||
get() = lazy.value
|
get() = lazy.value
|
||||||
|
|
||||||
override fun isInitialized(): Boolean {
|
override fun isInitialized(): Boolean {
|
||||||
return lazy.isInitialized()
|
return lazy.isInitialized()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(): T? {
|
override fun invoke(): RegistryObject<T>? {
|
||||||
return lazy.value
|
return lazy.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,26 +3,16 @@ package ru.dbotthepony.kstarbound.defs.image
|
|||||||
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.Gson
|
||||||
import com.google.gson.GsonBuilder
|
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
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.TypeAdapterFactory
|
|
||||||
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.JsonWriter
|
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
|
||||||
import ru.dbotthepony.kstarbound.api.ISBFileLocator
|
import ru.dbotthepony.kstarbound.api.ISBFileLocator
|
||||||
import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
|
import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
|
||||||
import ru.dbotthepony.kstarbound.io.json.stream
|
import ru.dbotthepony.kstarbound.io.json.stream
|
||||||
import ru.dbotthepony.kstarbound.io.json.transform
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import ru.dbotthepony.kstarbound.registerTypeAdapter
|
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
|
||||||
import ru.dbotthepony.kstarbound.util.WriteOnce
|
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
||||||
import ru.dbotthepony.kvector.vector.nint.Vector4i
|
import ru.dbotthepony.kvector.vector.nint.Vector4i
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@ -169,7 +159,7 @@ class AtlasConfiguration private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Registry(val locator: ISBFileLocator, val remapper: AssetPathStack, val gson: Gson) {
|
class Registry(val locator: ISBFileLocator, val remapper: PathStack, val gson: Gson) {
|
||||||
private val cache = ConcurrentHashMap<String, AtlasConfiguration>()
|
private val cache = ConcurrentHashMap<String, AtlasConfiguration>()
|
||||||
|
|
||||||
private fun generateFakeNames(dimensions: Vector2i): JsonArray {
|
private fun generateFakeNames(dimensions: Vector2i): JsonArray {
|
||||||
|
@ -5,8 +5,7 @@ import com.google.gson.TypeAdapter
|
|||||||
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
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Хранит данные (пару) вида "/example/animated.png" у которого, вероятнее всего, есть "/example/animated.frames"
|
* Хранит данные (пару) вида "/example/animated.png" у которого, вероятнее всего, есть "/example/animated.frames"
|
||||||
@ -17,7 +16,7 @@ data class ImageReference(
|
|||||||
val image: String,
|
val image: String,
|
||||||
val config: AtlasConfiguration,
|
val config: AtlasConfiguration,
|
||||||
) {
|
) {
|
||||||
class Adapter(private val remapper: AssetPathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapter<ImageReference>() {
|
class Adapter(private val remapper: PathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapter<ImageReference>() {
|
||||||
override fun write(out: JsonWriter, value: ImageReference?) {
|
override fun write(out: JsonWriter, value: ImageReference?) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
out.nullValue()
|
out.nullValue()
|
||||||
|
@ -3,8 +3,7 @@ package ru.dbotthepony.kstarbound.defs.image
|
|||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
import com.google.gson.stream.JsonReader
|
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.util.PathStack
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +21,7 @@ data class SpriteReference(
|
|||||||
return atlas[resolved] ?: atlas.any()
|
return atlas[resolved] ?: atlas.any()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Adapter(private val remapper: AssetPathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapter<SpriteReference>() {
|
class Adapter(private val remapper: PathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapter<SpriteReference>() {
|
||||||
override fun write(out: JsonWriter, value: SpriteReference?) {
|
override fun write(out: JsonWriter, value: SpriteReference?) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
out.nullValue()
|
out.nullValue()
|
||||||
|
@ -32,6 +32,4 @@ data class ArmorItemDefinition(
|
|||||||
override val armorType: ArmorPieceType,
|
override val armorType: ArmorPieceType,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>,
|
|
||||||
) : IArmorItemDefinition, IThingWithDescription by descriptionData
|
) : IArmorItemDefinition, IThingWithDescription by descriptionData
|
||||||
|
@ -46,8 +46,6 @@ open class ArmorItemPrototype : ItemPrototype(), IArmorItemDefinition {
|
|||||||
radioMessagesOnPickup = radioMessagesOnPickup,
|
radioMessagesOnPickup = radioMessagesOnPickup,
|
||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
|
|
||||||
colorOptions = colorOptions,
|
colorOptions = colorOptions,
|
||||||
maleFrames = maleFrames,
|
maleFrames = maleFrames,
|
||||||
femaleFrames = femaleFrames,
|
femaleFrames = femaleFrames,
|
||||||
|
@ -29,6 +29,4 @@ data class CurrencyItemDefinition(
|
|||||||
override val value: Long,
|
override val value: Long,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>,
|
|
||||||
) : ICurrencyItemDefinition, IThingWithDescription by descriptionData
|
) : ICurrencyItemDefinition, IThingWithDescription by descriptionData
|
||||||
|
@ -39,8 +39,6 @@ class CurrencyItemPrototype : ItemPrototype(), ICurrencyItemDefinition {
|
|||||||
radioMessagesOnPickup = radioMessagesOnPickup,
|
radioMessagesOnPickup = radioMessagesOnPickup,
|
||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
|
|
||||||
pickupSoundsSmall = pickupSoundsSmall,
|
pickupSoundsSmall = pickupSoundsSmall,
|
||||||
pickupSoundsMedium = pickupSoundsMedium,
|
pickupSoundsMedium = pickupSoundsMedium,
|
||||||
pickupSoundsLarge = pickupSoundsLarge,
|
pickupSoundsLarge = pickupSoundsLarge,
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.defs.item
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import ru.dbotthepony.kstarbound.RegistryObject
|
||||||
|
import ru.dbotthepony.kstarbound.defs.DynamicDefinition
|
||||||
|
|
||||||
|
class DynamicItemDefinition(def: RegistryObject<IItemDefinition>) : DynamicDefinition<IItemDefinition>(def) {
|
||||||
|
override fun sanitize(saveInput: JsonObject) {
|
||||||
|
saveInput.remove("itemName")
|
||||||
|
saveInput.remove("pickupQuestTemplates")
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,4 @@ data class FlashlightDefinition(
|
|||||||
override val handPosition: Vector2d,
|
override val handPosition: Vector2d,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>
|
|
||||||
) : IFlashlightDefinition, IThingWithDescription by descriptionData
|
) : IFlashlightDefinition, IThingWithDescription by descriptionData
|
||||||
|
@ -37,8 +37,6 @@ class FlashlightPrototype : ItemPrototype(), IFlashlightDefinition {
|
|||||||
radioMessagesOnPickup = radioMessagesOnPickup,
|
radioMessagesOnPickup = radioMessagesOnPickup,
|
||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
|
|
||||||
lightPosition = lightPosition,
|
lightPosition = lightPosition,
|
||||||
lightColor = lightColor,
|
lightColor = lightColor,
|
||||||
beamLevel = beamLevel,
|
beamLevel = beamLevel,
|
||||||
|
@ -33,6 +33,4 @@ data class HarvestingToolDefinition(
|
|||||||
override val fireTime: Double,
|
override val fireTime: Double,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>
|
|
||||||
) : IHarvestingToolDefinition, IThingWithDescription by descriptionData
|
) : IHarvestingToolDefinition, IThingWithDescription by descriptionData
|
||||||
|
@ -40,8 +40,6 @@ class HarvestingToolPrototype : ItemPrototype(), IHarvestingToolDefinition {
|
|||||||
radioMessagesOnPickup = radioMessagesOnPickup,
|
radioMessagesOnPickup = radioMessagesOnPickup,
|
||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
|
|
||||||
frames = frames,
|
frames = frames,
|
||||||
animationCycle = animationCycle,
|
animationCycle = animationCycle,
|
||||||
blockRadius = blockRadius,
|
blockRadius = blockRadius,
|
||||||
|
@ -11,7 +11,7 @@ import ru.dbotthepony.kstarbound.defs.image.AtlasConfiguration
|
|||||||
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
|
|
||||||
interface IArmorItemDefinition : ILeveledItemDefinition, IScriptableItemDefinition {
|
interface IArmorItemDefinition : ILeveledItemDefinition, IScriptableItemDefinition {
|
||||||
/**
|
/**
|
||||||
@ -46,7 +46,7 @@ interface IArmorItemDefinition : ILeveledItemDefinition, IScriptableItemDefiniti
|
|||||||
override val backSleeve: ImageReference? = null,
|
override val backSleeve: ImageReference? = null,
|
||||||
override val frontSleeve: ImageReference? = null,
|
override val frontSleeve: ImageReference? = null,
|
||||||
) : IArmorFrames {
|
) : IArmorFrames {
|
||||||
class Factory(private val remapper: AssetPathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapterFactory {
|
class Factory(private val remapper: PathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == ArmorFrames::class.java) {
|
if (type.rawType == ArmorFrames::class.java) {
|
||||||
return object : TypeAdapter<ArmorFrames>() {
|
return object : TypeAdapter<ArmorFrames>() {
|
||||||
|
@ -7,13 +7,11 @@ 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
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
|
||||||
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
|
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
||||||
import ru.dbotthepony.kstarbound.io.json.ifString
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
|
||||||
|
|
||||||
interface IItemDefinition : IThingWithDescription {
|
interface IItemDefinition : IThingWithDescription {
|
||||||
/**
|
/**
|
||||||
@ -53,7 +51,7 @@ interface IItemDefinition : IThingWithDescription {
|
|||||||
data class InventoryIcon(
|
data class InventoryIcon(
|
||||||
override val image: SpriteReference
|
override val image: SpriteReference
|
||||||
) : IInventoryIcon {
|
) : IInventoryIcon {
|
||||||
class Factory(val remapper: AssetPathStack, val spriteRegistry: SpriteReference.Adapter) : TypeAdapterFactory {
|
class Factory(val remapper: PathStack, val spriteRegistry: SpriteReference.Adapter) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == InventoryIcon::class.java) {
|
if (type.rawType == InventoryIcon::class.java) {
|
||||||
return object : TypeAdapter<InventoryIcon>() {
|
return object : TypeAdapter<InventoryIcon>() {
|
||||||
|
@ -24,6 +24,4 @@ data class ItemDefinition(
|
|||||||
override val fuelAmount: Long?,
|
override val fuelAmount: Long?,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>
|
|
||||||
) : IItemDefinition, IThingWithDescription by descriptionData
|
) : IItemDefinition, IThingWithDescription by descriptionData
|
||||||
|
@ -11,7 +11,7 @@ import ru.dbotthepony.kstarbound.io.json.builder.JsonIgnoreProperty
|
|||||||
import ru.dbotthepony.kstarbound.util.NotNullVar
|
import ru.dbotthepony.kstarbound.util.NotNullVar
|
||||||
|
|
||||||
@JsonBuilder
|
@JsonBuilder
|
||||||
open class ItemPrototype : IItemDefinition, INativeJsonHolder {
|
open class ItemPrototype : IItemDefinition {
|
||||||
@JsonIgnoreProperty
|
@JsonIgnoreProperty
|
||||||
final override var shortdescription: String = "..."
|
final override var shortdescription: String = "..."
|
||||||
@JsonIgnoreProperty
|
@JsonIgnoreProperty
|
||||||
@ -36,13 +36,6 @@ open class ItemPrototype : IItemDefinition, INativeJsonHolder {
|
|||||||
@JsonPropertyConfig(isFlat = true)
|
@JsonPropertyConfig(isFlat = true)
|
||||||
var descriptionData: ThingDescription by NotNullVar()
|
var descriptionData: ThingDescription by NotNullVar()
|
||||||
|
|
||||||
@JsonIgnoreProperty
|
|
||||||
var json: Map<String, Any> = mapOf()
|
|
||||||
|
|
||||||
final override fun acceptJson(json: MutableMap<String, Any>) {
|
|
||||||
this.json = json
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun assemble(): IItemDefinition {
|
open fun assemble(): IItemDefinition {
|
||||||
return ItemDefinition(
|
return ItemDefinition(
|
||||||
descriptionData = descriptionData,
|
descriptionData = descriptionData,
|
||||||
@ -61,8 +54,6 @@ open class ItemPrototype : IItemDefinition, INativeJsonHolder {
|
|||||||
twoHanded = twoHanded,
|
twoHanded = twoHanded,
|
||||||
radioMessagesOnPickup = radioMessagesOnPickup,
|
radioMessagesOnPickup = radioMessagesOnPickup,
|
||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,4 @@ data class LiquidItemDefinition(
|
|||||||
override val liquid: MaterialReference,
|
override val liquid: MaterialReference,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>
|
|
||||||
) : ILiquidItem, IThingWithDescription by descriptionData
|
) : ILiquidItem, IThingWithDescription by descriptionData
|
||||||
|
@ -40,8 +40,6 @@ class LiquidItemPrototype : ItemPrototype() {
|
|||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
liquid = checkNotNull(liquid) { "Liquid is null (either 'liquidId' or 'liquidName' should be present, or 'liquid' itself)" },
|
liquid = checkNotNull(liquid) { "Liquid is null (either 'liquidId' or 'liquidName' should be present, or 'liquid' itself)" },
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,4 @@ data class MaterialItemDefinition(
|
|||||||
override val material: MaterialReference,
|
override val material: MaterialReference,
|
||||||
|
|
||||||
val descriptionData: ThingDescription,
|
val descriptionData: ThingDescription,
|
||||||
|
|
||||||
val json: Map<String, Any>
|
|
||||||
) : IMaterialItem, IThingWithDescription by descriptionData
|
) : IMaterialItem, IThingWithDescription by descriptionData
|
||||||
|
@ -40,8 +40,6 @@ class MaterialItemPrototype : ItemPrototype() {
|
|||||||
fuelAmount = fuelAmount,
|
fuelAmount = fuelAmount,
|
||||||
|
|
||||||
material = checkNotNull(material) { "Material is null (either 'materialId' or 'materialName' should be present, or 'material' itself)" },
|
material = checkNotNull(material) { "Material is null (either 'materialId' or 'materialName' should be present, or 'material' itself)" },
|
||||||
|
|
||||||
json = enrollMap(json),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,8 @@ annotation class JsonIgnoreProperty
|
|||||||
annotation class JsonPropertyConfig(
|
annotation class JsonPropertyConfig(
|
||||||
val isFlat: Boolean = false,
|
val isFlat: Boolean = false,
|
||||||
|
|
||||||
|
val write: Boolean = true,
|
||||||
|
|
||||||
val mustBePresent: Int = 0,
|
val mustBePresent: Int = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
|
||||||
import ru.dbotthepony.kstarbound.defs.util.flattenJsonElement
|
import ru.dbotthepony.kstarbound.defs.util.flattenJsonElement
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter.Builder
|
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter.Builder
|
||||||
import ru.dbotthepony.kstarbound.util.NotNullVar
|
import ru.dbotthepony.kstarbound.util.NotNullVar
|
||||||
@ -29,40 +28,6 @@ import kotlin.reflect.KMutableProperty1
|
|||||||
import kotlin.reflect.full.declaredMembers
|
import kotlin.reflect.full.declaredMembers
|
||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
/**
|
|
||||||
* Данный интерфейс имеет один единственный метод: [acceptJson]
|
|
||||||
*
|
|
||||||
* Используется в связке с [BuilderAdapter] для классов, которым необходимо хранить оригинальную JSON структуру
|
|
||||||
*/
|
|
||||||
interface IJsonHolder {
|
|
||||||
/**
|
|
||||||
* Выставляет [JsonObject], который является источником данных для данной структуры
|
|
||||||
*/
|
|
||||||
fun acceptJson(json: JsonObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Для классов, которые хотят принимать Java'вские [Map] напрямую, как оригинальную JSON структуру
|
|
||||||
*/
|
|
||||||
interface INativeJsonHolder : IJsonHolder {
|
|
||||||
override fun acceptJson(json: JsonObject) {
|
|
||||||
acceptJson(flattenJsonElement(json))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun acceptJson(json: MutableMap<String, Any>)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
fun <T : Any> BuilderAdapter(factory: () -> T, vararg fields: KMutableProperty1<T, *>): TypeAdapterFactory {
|
|
||||||
val builder = BuilderAdapter.Builder(factory)
|
|
||||||
|
|
||||||
for (field in fields) {
|
|
||||||
builder.auto(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [TypeAdapter] для классов, которые создаются "без всего", а после наполняются данными (паттерн builder).
|
* [TypeAdapter] для классов, которые создаются "без всего", а после наполняются данными (паттерн builder).
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.builder
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Данный интерфейс имеет один единственный метод: [acceptJson]
|
||||||
|
*
|
||||||
|
* Используется в связке с [BuilderAdapter] для классов, которым необходимо хранить оригинальную JSON структуру
|
||||||
|
*/
|
||||||
|
interface IJsonHolder {
|
||||||
|
/**
|
||||||
|
* Выставляет [JsonObject], который является источником данных для данной структуры
|
||||||
|
*/
|
||||||
|
fun acceptJson(json: JsonObject)
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json.builder
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import ru.dbotthepony.kstarbound.defs.util.flattenJsonElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Для классов, которые хотят принимать Java'вские [Map] напрямую, как оригинальную JSON структуру
|
||||||
|
*/
|
||||||
|
interface INativeJsonHolder : IJsonHolder {
|
||||||
|
override fun acceptJson(json: JsonObject) {
|
||||||
|
acceptJson(flattenJsonElement(json))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun acceptJson(json: MutableMap<String, Any>)
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.lua
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||||
|
annotation class LuaExposed
|
||||||
|
|
||||||
|
interface ILuaIndex {
|
||||||
|
fun luaIndex(index: Any?): Any?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILuaNewIndex {
|
||||||
|
fun luaIndex(index: Any?, value: Any?)
|
||||||
|
}
|
||||||
|
|
||||||
|
class JVM2LuaWrapper<R : Any>(val value: R) {
|
||||||
|
private abstract class LuaBinding<in R : Any> {
|
||||||
|
abstract fun invoke(receiver: R, values: Array<Any?>): Any?
|
||||||
|
abstract fun read(receiver: R): Any?
|
||||||
|
abstract fun write(receiver: R, value: Any?)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LuaFunctionBinding<in R : Any>(private val func: (R, Array<Any?>) -> Any?) : LuaBinding<R>() {
|
||||||
|
override fun invoke(receiver: R, values: Array<Any?>): Any? {
|
||||||
|
return func.invoke(receiver, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(receiver: R) {
|
||||||
|
throw UnsupportedOperationException("attempt to index a function value")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(receiver: R, value: Any?) {
|
||||||
|
throw UnsupportedOperationException("attempt to new index a function value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LuaPropertyBinding<in R : Any>(private val read: (R) -> Any?, private val write: ((R, Any?) -> Unit)?) : LuaBinding<R>() {
|
||||||
|
override fun invoke(receiver: R, values: Array<Any?>): Any? {
|
||||||
|
throw UnsupportedOperationException("attempt to call a value")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(receiver: R): Any? {
|
||||||
|
return read.invoke(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(receiver: R, value: Any?) {
|
||||||
|
if (write == null)
|
||||||
|
throw UnsupportedOperationException("attempt to new index a read-only value")
|
||||||
|
|
||||||
|
write.invoke(receiver, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
//private val decls =
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.util
|
|||||||
import com.google.common.collect.Interner
|
import com.google.common.collect.Interner
|
||||||
import kotlin.concurrent.getOrSet
|
import kotlin.concurrent.getOrSet
|
||||||
|
|
||||||
class AssetPathStack(private val interner: Interner<String>? = null) {
|
class PathStack(private val interner: Interner<String>? = null) {
|
||||||
private val _stack = ThreadLocal<ArrayDeque<String>>()
|
private val _stack = ThreadLocal<ArrayDeque<String>>()
|
||||||
private val stack: ArrayDeque<String> get() = _stack.getOrSet { ArrayDeque() }
|
private val stack: ArrayDeque<String> get() = _stack.getOrSet { ArrayDeque() }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user