Some improvement to asset loading and feedback
This commit is contained in:
parent
0854baa986
commit
4c959b82a9
@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableList
|
|||||||
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.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
import kotlinx.coroutines.future.asCompletableFuture
|
import kotlinx.coroutines.future.asCompletableFuture
|
||||||
import kotlinx.coroutines.future.await
|
import kotlinx.coroutines.future.await
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -147,7 +149,7 @@ object Globals {
|
|||||||
LOGGER.fatal("$path does not exist or is not a file, expect bad things to happen!")
|
LOGGER.fatal("$path does not exist or is not a file, expect bad things to happen!")
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
AssetPathStack("/") {
|
AssetPathStack(path) {
|
||||||
accept.set(adapter.value.fromJsonTree(file))
|
accept.set(adapter.value.fromJsonTree(file))
|
||||||
}
|
}
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
@ -161,6 +163,38 @@ object Globals {
|
|||||||
return Starbound.GLOBAL_SCOPE.launch { load(path, accept, lazy(LazyThreadSafetyMode.NONE) { Starbound.gson.getAdapter(T::class.java) }) }.asCompletableFuture()
|
return Starbound.GLOBAL_SCOPE.launch { load(path, accept, lazy(LazyThreadSafetyMode.NONE) { Starbound.gson.getAdapter(T::class.java) }) }.asCompletableFuture()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : Any> mapAdapter(filename: String): Lazy<TypeAdapter<ImmutableMap<String, T>>> {
|
||||||
|
val parent by lazy { Starbound.gson.getAdapter(T::class.java) }
|
||||||
|
|
||||||
|
return lazy(LazyThreadSafetyMode.NONE) {
|
||||||
|
object : TypeAdapter<ImmutableMap<String, T>>() {
|
||||||
|
override fun write(out: JsonWriter, value: ImmutableMap<String, T>) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): ImmutableMap<String, T> {
|
||||||
|
`in`.beginObject()
|
||||||
|
|
||||||
|
val builder = ImmutableMap.Builder<String, T>()
|
||||||
|
|
||||||
|
while (`in`.hasNext()) {
|
||||||
|
val name = `in`.nextName()
|
||||||
|
val element = Starbound.ELEMENTS_ADAPTER.read(`in`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
builder.put(name, parent.fromJsonTree(element))
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
LOGGER.error("Exception reading element at $name from $filename; it will not be loaded", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
`in`.endObject()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun load(): List<Future<*>> {
|
fun load(): List<Future<*>> {
|
||||||
val tasks = ArrayList<CompletableFuture<*>>()
|
val tasks = ArrayList<CompletableFuture<*>>()
|
||||||
|
|
||||||
@ -186,10 +220,10 @@ object Globals {
|
|||||||
tasks.add(load("/plants/bushDamage.config", ::bushDamage))
|
tasks.add(load("/plants/bushDamage.config", ::bushDamage))
|
||||||
tasks.add(load("/tiles/defaultDamage.config", ::tileDamage))
|
tasks.add(load("/tiles/defaultDamage.config", ::tileDamage))
|
||||||
|
|
||||||
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/dungeon_worlds.config", ::dungeonWorlds, lazy { Starbound.gson.mapAdapter() }) }.asCompletableFuture())
|
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/dungeon_worlds.config", ::dungeonWorlds, mapAdapter("/dungeon_worlds.config")) }.asCompletableFuture())
|
||||||
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/currencies.config", ::currencies, lazy { Starbound.gson.mapAdapter() }) }.asCompletableFuture())
|
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/currencies.config", ::currencies, mapAdapter("/currencies.config")) }.asCompletableFuture())
|
||||||
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/system_objects.config", ::systemObjects, lazy { Starbound.gson.mapAdapter() }) }.asCompletableFuture())
|
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/system_objects.config", ::systemObjects, mapAdapter("/system_objects.config")) }.asCompletableFuture())
|
||||||
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/instance_worlds.config", ::instanceWorlds, lazy { Starbound.gson.mapAdapter() }) }.asCompletableFuture())
|
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/instance_worlds.config", ::instanceWorlds, mapAdapter("/instance_worlds.config")) }.asCompletableFuture())
|
||||||
|
|
||||||
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/names/profanityfilter.config", ::profanityFilterInternal, lazy { Starbound.gson.listAdapter() }) }.asCompletableFuture())
|
tasks.add(Starbound.GLOBAL_SCOPE.launch { load("/names/profanityfilter.config", ::profanityFilterInternal, lazy { Starbound.gson.listAdapter() }) }.asCompletableFuture())
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ object Registries {
|
|||||||
try {
|
try {
|
||||||
val elem = JsonPatch.applyAsync(Starbound.ELEMENTS_ADAPTER.read(listedFile.asyncJsonReader().await()), patches[listedFile.computeFullPath()])
|
val elem = JsonPatch.applyAsync(Starbound.ELEMENTS_ADAPTER.read(listedFile.asyncJsonReader().await()), patches[listedFile.computeFullPath()])
|
||||||
|
|
||||||
AssetPathStack(listedFile.computeDirectory()) {
|
AssetPathStack(listedFile.computeFullPath()) {
|
||||||
val read = adapter.fromJsonTree(elem)
|
val read = adapter.fromJsonTree(elem)
|
||||||
val keys = keyProvider(read)
|
val keys = keyProvider(read)
|
||||||
|
|
||||||
|
@ -98,9 +98,13 @@ class AssetReference<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val value = json.thenApplyAsync({ j ->
|
val value = json.thenApplyAsync({ j ->
|
||||||
AssetPathStack(fullPath.substringBefore(':').substringBeforeLast('/')) {
|
if (j == null) {
|
||||||
adapter.fromJsonTree(j)
|
null
|
||||||
}
|
} else {
|
||||||
|
AssetPathStack(fullPath.substringBefore(':').substringBefore('?')) {
|
||||||
|
adapter.fromJsonTree(j)
|
||||||
|
}
|
||||||
|
}
|
||||||
}, Starbound.EXECUTOR)
|
}, Starbound.EXECUTOR)
|
||||||
|
|
||||||
value.exceptionally {
|
value.exceptionally {
|
||||||
|
@ -10,6 +10,7 @@ import ru.dbotthepony.kstarbound.io.writeStruct2d
|
|||||||
import ru.dbotthepony.kstarbound.json.builder.DispatchingAdapter
|
import ru.dbotthepony.kstarbound.json.builder.DispatchingAdapter
|
||||||
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
|
import ru.dbotthepony.kstarbound.json.builder.JsonFlat
|
||||||
import ru.dbotthepony.kstarbound.math.Line2d
|
import ru.dbotthepony.kstarbound.math.Line2d
|
||||||
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
||||||
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
|
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
|
||||||
@ -38,6 +39,7 @@ sealed class PhysicsForceRegion {
|
|||||||
val xTargetVelocity: Double?,
|
val xTargetVelocity: Double?,
|
||||||
val yTargetVelocity: Double?,
|
val yTargetVelocity: Double?,
|
||||||
val controlForce: Double,
|
val controlForce: Double,
|
||||||
|
@JsonFlat
|
||||||
override val filter: PhysicsCategoryFilter,
|
override val filter: PhysicsCategoryFilter,
|
||||||
override val enabled: Boolean = true
|
override val enabled: Boolean = true
|
||||||
) : PhysicsForceRegion() {
|
) : PhysicsForceRegion() {
|
||||||
@ -69,6 +71,7 @@ sealed class PhysicsForceRegion {
|
|||||||
val innerRadius: Double,
|
val innerRadius: Double,
|
||||||
val targetRadialVelocity: Double,
|
val targetRadialVelocity: Double,
|
||||||
val controlForce: Double,
|
val controlForce: Double,
|
||||||
|
@JsonFlat
|
||||||
override val filter: PhysicsCategoryFilter,
|
override val filter: PhysicsCategoryFilter,
|
||||||
override val enabled: Boolean = true
|
override val enabled: Boolean = true
|
||||||
) : PhysicsForceRegion() {
|
) : PhysicsForceRegion() {
|
||||||
@ -101,6 +104,7 @@ sealed class PhysicsForceRegion {
|
|||||||
val gradient: Line2d,
|
val gradient: Line2d,
|
||||||
val baseTargetVelocity: Double,
|
val baseTargetVelocity: Double,
|
||||||
val baseControlForce: Double,
|
val baseControlForce: Double,
|
||||||
|
@JsonFlat
|
||||||
override val filter: PhysicsCategoryFilter,
|
override val filter: PhysicsCategoryFilter,
|
||||||
override val enabled: Boolean = true
|
override val enabled: Boolean = true
|
||||||
) : PhysicsForceRegion() {
|
) : PhysicsForceRegion() {
|
||||||
|
@ -72,10 +72,10 @@ data class DungeonDefinition(
|
|||||||
tiles.spewWarnings(name)
|
tiles.spewWarnings(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val directory = AssetPathStack.last()
|
private val file = AssetPathStack.lastFile()
|
||||||
|
|
||||||
val actualParts: ImmutableList<DungeonPart> by lazy {
|
val actualParts: ImmutableList<DungeonPart> by lazy {
|
||||||
AssetPathStack(directory) {
|
AssetPathStack(file) {
|
||||||
val build = parts.stream().map { Starbound.gson.fromJson(it, DungeonPart::class.java) }.collect(ImmutableList.toImmutableList())
|
val build = parts.stream().map { Starbound.gson.fromJson(it, DungeonPart::class.java) }.collect(ImmutableList.toImmutableList())
|
||||||
build.forEach { it.bind(this) }
|
build.forEach { it.bind(this) }
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ import ru.dbotthepony.kommons.gson.get
|
|||||||
import ru.dbotthepony.kommons.gson.getObject
|
import ru.dbotthepony.kommons.gson.getObject
|
||||||
import ru.dbotthepony.kstarbound.json.JsonPatch
|
import ru.dbotthepony.kstarbound.json.JsonPatch
|
||||||
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
import ru.dbotthepony.kstarbound.math.vector.Vector2d
|
||||||
|
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.lang.ref.Reference
|
import java.lang.ref.Reference
|
||||||
@ -378,11 +379,27 @@ class Image private constructor(
|
|||||||
val file = Starbound.locate(it)
|
val file = Starbound.locate(it)
|
||||||
|
|
||||||
if (!file.exists) {
|
if (!file.exists) {
|
||||||
throw FileNotFoundException("No such file $it")
|
val asset = AssetPathStack.lastFile()
|
||||||
|
|
||||||
|
if (asset == "/") {
|
||||||
|
logger.error("No such file $it")
|
||||||
|
} else {
|
||||||
|
logger.error("No such file $it (referenced in $asset)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return@computeIfAbsent Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.isFile) {
|
if (!file.isFile) {
|
||||||
throw FileNotFoundException("File $it is a directory")
|
val asset = AssetPathStack.lastFile()
|
||||||
|
|
||||||
|
if (asset == "/") {
|
||||||
|
logger.error("$it is a directory")
|
||||||
|
} else {
|
||||||
|
logger.error("$it is a directory (referenced in $asset)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return@computeIfAbsent Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
val getWidth = intArrayOf(0)
|
val getWidth = intArrayOf(0)
|
||||||
@ -400,7 +417,7 @@ class Image private constructor(
|
|||||||
MemoryUtil.memPutByte(buf + i, readBuf[i])
|
MemoryUtil.memPutByte(buf + i, readBuf[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return@STBIReadCallbackI read
|
return@STBIReadCallbackI read.coerceAtLeast(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
val skipCallback = STBISkipCallback.create { _, n -> stream.skip(n.toLong()) }
|
val skipCallback = STBISkipCallback.create { _, n -> stream.skip(n.toLong()) }
|
||||||
@ -425,10 +442,18 @@ class Image private constructor(
|
|||||||
eofCallback.free()
|
eofCallback.free()
|
||||||
callback.free()
|
callback.free()
|
||||||
|
|
||||||
if (!status)
|
if (!status) {
|
||||||
throw IllegalArgumentException("File $file is not an image or it is corrupted")
|
val asset = AssetPathStack.lastFile()
|
||||||
|
|
||||||
Optional.of(Image(file, it, getWidth[0], getHeight[0], getConfig(it)))
|
if (asset == "/") {
|
||||||
|
logger.error("$file is not an image or it is corrupted")
|
||||||
|
} else {
|
||||||
|
logger.error("$file is not an image or it is corrupted (referenced in $asset)")
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional.empty()
|
||||||
|
} else
|
||||||
|
Optional.of(Image(file, it, getWidth[0], getHeight[0], getConfig(it)))
|
||||||
} catch (err: Exception) {
|
} catch (err: Exception) {
|
||||||
logger.error("Failed to load image at path $it", err)
|
logger.error("Failed to load image at path $it", err)
|
||||||
Optional.empty()
|
Optional.empty()
|
||||||
|
@ -9,27 +9,23 @@ import com.google.gson.JsonElement
|
|||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.JsonSyntaxException
|
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
import com.google.gson.annotations.JsonAdapter
|
import com.google.gson.annotations.JsonAdapter
|
||||||
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 kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.future.asCompletableFuture
|
import kotlinx.coroutines.future.asCompletableFuture
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.kommons.util.Either
|
import ru.dbotthepony.kommons.util.Either
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
import ru.dbotthepony.kstarbound.Registry
|
import ru.dbotthepony.kstarbound.Registry
|
||||||
import ru.dbotthepony.kstarbound.defs.AssetPath
|
import ru.dbotthepony.kstarbound.defs.AssetPath
|
||||||
import ru.dbotthepony.kstarbound.defs.JsonReference
|
|
||||||
import ru.dbotthepony.kstarbound.defs.actor.StatModifier
|
import ru.dbotthepony.kstarbound.defs.actor.StatModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.item.TreasurePoolDefinition
|
import ru.dbotthepony.kstarbound.defs.item.TreasurePoolDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDamageParameters
|
import ru.dbotthepony.kstarbound.defs.tile.TileDamageParameters
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kommons.gson.consumeNull
|
import ru.dbotthepony.kommons.gson.consumeNull
|
||||||
import ru.dbotthepony.kstarbound.json.listAdapter
|
import ru.dbotthepony.kstarbound.json.listAdapter
|
||||||
import ru.dbotthepony.kstarbound.json.stream
|
|
||||||
import ru.dbotthepony.kstarbound.util.PeriodicFunction
|
import ru.dbotthepony.kstarbound.util.PeriodicFunction
|
||||||
import ru.dbotthepony.kommons.gson.contains
|
import ru.dbotthepony.kommons.gson.contains
|
||||||
import ru.dbotthepony.kommons.gson.get
|
import ru.dbotthepony.kommons.gson.get
|
||||||
@ -219,7 +215,7 @@ data class ObjectDefinition(
|
|||||||
|
|
||||||
val orientations = ImmutableList.Builder<Supplier<ObjectOrientation>>()
|
val orientations = ImmutableList.Builder<Supplier<ObjectOrientation>>()
|
||||||
|
|
||||||
val path = AssetPathStack.last()
|
val path = AssetPathStack.lastFile()
|
||||||
|
|
||||||
for (v in ObjectOrientation.preprocess(read.getArray("orientations"))) {
|
for (v in ObjectOrientation.preprocess(read.getArray("orientations"))) {
|
||||||
val future = Starbound.GLOBAL_SCOPE.async { this@Adapter.orientations.read(v as JsonObject, path) }.asCompletableFuture()
|
val future = Starbound.GLOBAL_SCOPE.async { this@Adapter.orientations.read(v as JsonObject, path) }.asCompletableFuture()
|
||||||
@ -275,7 +271,7 @@ data class ObjectDefinition(
|
|||||||
soundEffectRangeMultiplier = basic.soundEffectRangeMultiplier,
|
soundEffectRangeMultiplier = basic.soundEffectRangeMultiplier,
|
||||||
price = basic.price,
|
price = basic.price,
|
||||||
statusEffects = basic.statusEffects,
|
statusEffects = basic.statusEffects,
|
||||||
touchDamage = Starbound.loadJsonAsset(basic.touchDamage, AssetPathStack.last()),
|
touchDamage = Starbound.loadJsonAsset(basic.touchDamage, AssetPathStack.lastFolder()),
|
||||||
minimumLiquidLevel = basic.minimumLiquidLevel,
|
minimumLiquidLevel = basic.minimumLiquidLevel,
|
||||||
maximumLiquidLevel = basic.maximumLiquidLevel,
|
maximumLiquidLevel = basic.maximumLiquidLevel,
|
||||||
liquidCheckInterval = basic.liquidCheckInterval,
|
liquidCheckInterval = basic.liquidCheckInterval,
|
||||||
|
@ -9,10 +9,7 @@ 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.TypeAdapter
|
||||||
import com.google.gson.annotations.JsonAdapter
|
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import kotlinx.coroutines.future.await
|
import kotlinx.coroutines.future.await
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.kommons.gson.clear
|
import ru.dbotthepony.kommons.gson.clear
|
||||||
@ -24,9 +21,7 @@ import ru.dbotthepony.kstarbound.math.vector.Vector2i
|
|||||||
import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf
|
import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf
|
||||||
import ru.dbotthepony.kstarbound.client.render.RenderLayer
|
import ru.dbotthepony.kstarbound.client.render.RenderLayer
|
||||||
import ru.dbotthepony.kstarbound.defs.Drawable
|
import ru.dbotthepony.kstarbound.defs.Drawable
|
||||||
import ru.dbotthepony.kstarbound.defs.JsonReference
|
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
||||||
import ru.dbotthepony.kommons.gson.consumeNull
|
|
||||||
import ru.dbotthepony.kstarbound.json.listAdapter
|
import ru.dbotthepony.kstarbound.json.listAdapter
|
||||||
import ru.dbotthepony.kstarbound.json.setAdapter
|
import ru.dbotthepony.kstarbound.json.setAdapter
|
||||||
import ru.dbotthepony.kommons.gson.contains
|
import ru.dbotthepony.kommons.gson.contains
|
||||||
@ -37,11 +32,9 @@ import ru.dbotthepony.kstarbound.Registry
|
|||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.isEmptyTile
|
import ru.dbotthepony.kstarbound.defs.tile.isEmptyTile
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.isNotEmptyTile
|
|
||||||
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
||||||
import ru.dbotthepony.kstarbound.world.Direction
|
import ru.dbotthepony.kstarbound.world.Direction
|
||||||
import ru.dbotthepony.kstarbound.world.World
|
import ru.dbotthepony.kstarbound.world.World
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
data class ObjectOrientation(
|
data class ObjectOrientation(
|
||||||
@ -154,12 +147,12 @@ data class ObjectOrientation(
|
|||||||
private val spaces = gson.setAdapter<Vector2i>()
|
private val spaces = gson.setAdapter<Vector2i>()
|
||||||
private val materialSpaces = gson.getAdapter(TypeToken.getParameterized(ImmutableList::class.java, TypeToken.getParameterized(Pair::class.java, Vector2i::class.java, String::class.java).type)) as TypeAdapter<ImmutableList<Pair<Vector2i, String>>>
|
private val materialSpaces = gson.getAdapter(TypeToken.getParameterized(ImmutableList::class.java, TypeToken.getParameterized(Pair::class.java, Vector2i::class.java, String::class.java).type)) as TypeAdapter<ImmutableList<Pair<Vector2i, String>>>
|
||||||
|
|
||||||
suspend fun read(obj: JsonObject, folder: String): ObjectOrientation {
|
suspend fun read(obj: JsonObject, file: String): ObjectOrientation {
|
||||||
val drawables = ArrayList<Drawable>()
|
val drawables = ArrayList<Drawable>()
|
||||||
val flipImages = obj.get("flipImages", false)
|
val flipImages = obj.get("flipImages", false)
|
||||||
val renderLayer = RenderLayer.parse(obj.get("renderLayer", "Object"))
|
val renderLayer = RenderLayer.parse(obj.get("renderLayer", "Object"))
|
||||||
|
|
||||||
AssetPathStack(folder) {
|
AssetPathStack(file) {
|
||||||
if ("imageLayers" in obj) {
|
if ("imageLayers" in obj) {
|
||||||
for (value in obj["imageLayers"].asJsonArray) {
|
for (value in obj["imageLayers"].asJsonArray) {
|
||||||
var result = this.drawables.fromJsonTree(value)
|
var result = this.drawables.fromJsonTree(value)
|
||||||
@ -273,7 +266,7 @@ data class ObjectOrientation(
|
|||||||
val lightPosition = obj["lightPosition"]?.let { vectorsi.fromJsonTree(it) } ?: Vector2i.ZERO
|
val lightPosition = obj["lightPosition"]?.let { vectorsi.fromJsonTree(it) } ?: Vector2i.ZERO
|
||||||
val beamAngle = obj.get("beamAngle", 0.0) / 180.0 * PI
|
val beamAngle = obj.get("beamAngle", 0.0) / 180.0 * PI
|
||||||
val statusEffectArea = obj["statusEffectArea"]?.let { vectorsd.fromJsonTree(it) }
|
val statusEffectArea = obj["statusEffectArea"]?.let { vectorsd.fromJsonTree(it) }
|
||||||
val touchDamage = Starbound.loadJsonAsset(obj["touchDamage"] ?: JsonNull.INSTANCE, AssetPathStack.last()).await()
|
val touchDamage = Starbound.loadJsonAsset(obj["touchDamage"] ?: JsonNull.INSTANCE, AssetPathStack.lastFolder()).await()
|
||||||
|
|
||||||
val emitters = ArrayList<ParticleEmissionEntry>()
|
val emitters = ArrayList<ParticleEmissionEntry>()
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package ru.dbotthepony.kstarbound.util
|
package ru.dbotthepony.kstarbound.util
|
||||||
|
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
object AssetPathStack {
|
object AssetPathStack {
|
||||||
private val _stack = object : ThreadLocal<ArrayDeque<String>>() {
|
private val _stack = object : ThreadLocal<ArrayDeque<String>>() {
|
||||||
@ -10,20 +9,35 @@ object AssetPathStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val stack: ArrayDeque<String> get() = _stack.get()
|
private val _fileStack = object : ThreadLocal<ArrayDeque<String>>() {
|
||||||
|
override fun initialValue(): ArrayDeque<String> {
|
||||||
|
return ArrayDeque()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val folderStack: ArrayDeque<String> get() = _stack.get()
|
||||||
|
private val fileStack: ArrayDeque<String> get() = _fileStack.get()
|
||||||
|
|
||||||
fun push(value: String) {
|
fun push(value: String) {
|
||||||
stack.addLast(value)
|
if (value.last() == '/') {
|
||||||
|
// already folder, we don't have filename
|
||||||
|
folderStack.addLast(value)
|
||||||
|
fileStack.addLast(value)
|
||||||
|
} else {
|
||||||
|
folderStack.addLast(value.substringBeforeLast('/') + "/")
|
||||||
|
fileStack.addLast(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pushFilename(value: String) {
|
fun lastFolder() = folderStack.lastOrNull() ?: "/"
|
||||||
push(value.substringBefore(':').substringBeforeLast('/'))
|
fun lastFile() = fileStack.lastOrNull() ?: "/"
|
||||||
|
|
||||||
|
fun pop() {
|
||||||
|
folderStack.removeLast()
|
||||||
|
fileStack.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun last() = stack.lastOrNull() ?: "/"
|
inline operator fun <T> invoke(path: String, block: (String) -> T): T {
|
||||||
fun pop() = stack.removeLast()
|
|
||||||
|
|
||||||
inline fun <T> block(path: String, block: (String) -> T): T {
|
|
||||||
try {
|
try {
|
||||||
push(path)
|
push(path)
|
||||||
return block.invoke(path)
|
return block.invoke(path)
|
||||||
@ -32,23 +46,12 @@ object AssetPathStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator fun <T> invoke(path: String, block: (String) -> T) = block(path, block)
|
|
||||||
|
|
||||||
private fun remap(a: String, b: String): String {
|
|
||||||
if (b.isEmpty())
|
|
||||||
return a
|
|
||||||
if (b[0] == '/')
|
|
||||||
return b
|
|
||||||
|
|
||||||
return Starbound.STRINGS.intern("$a/$b")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun remap(path: String): String {
|
fun remap(path: String): String {
|
||||||
return remap(last(), path)
|
return relativeTo(lastFolder(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remapSafe(path: String): String {
|
fun remapSafe(path: String): String {
|
||||||
return remap(last(), path)
|
return relativeTo(lastFolder(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun relativeTo(base: String, path: String): String {
|
fun relativeTo(base: String, path: String): String {
|
||||||
|
@ -8,7 +8,7 @@ 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 it.unimi.dsi.fastutil.objects.ObjectArrayList
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
import org.apache.logging.log4j.LogManager
|
||||||
import org.lwjgl.opengl.GL11.GL_LINES
|
import org.lwjgl.opengl.GL11.GL_LINES
|
||||||
import ru.dbotthepony.kommons.util.IStruct2d
|
import ru.dbotthepony.kommons.util.IStruct2d
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
@ -30,6 +30,7 @@ import ru.dbotthepony.kstarbound.json.listAdapter
|
|||||||
import ru.dbotthepony.kstarbound.math.Line2d
|
import ru.dbotthepony.kstarbound.math.Line2d
|
||||||
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
|
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
|
||||||
import ru.dbotthepony.kstarbound.network.syncher.nativeCodec
|
import ru.dbotthepony.kstarbound.network.syncher.nativeCodec
|
||||||
|
import ru.dbotthepony.kstarbound.util.AssetPathStack
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
import java.io.DataOutputStream
|
import java.io.DataOutputStream
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
@ -417,6 +418,7 @@ class Poly private constructor(val edges: ImmutableList<Line2d>, val vertices: I
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object : TypeAdapterFactory {
|
companion object : TypeAdapterFactory {
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
val CODEC = nativeCodec(::read, Poly::write)
|
val CODEC = nativeCodec(::read, Poly::write)
|
||||||
val LEGACY_CODEC = legacyCodec(::read, Poly::write)
|
val LEGACY_CODEC = legacyCodec(::read, Poly::write)
|
||||||
|
|
||||||
@ -447,8 +449,13 @@ class Poly private constructor(val edges: ImmutableList<Line2d>, val vertices: I
|
|||||||
else {
|
else {
|
||||||
val list = list.read(`in`)
|
val list = list.read(`in`)
|
||||||
|
|
||||||
if (list.isEmpty())
|
if (list.isEmpty()) {
|
||||||
|
// LOGGER.warn("Accepting empty poly from asset ${AssetPathStack.lastFile()} to match original engine behavior")
|
||||||
return EMPTY
|
return EMPTY
|
||||||
|
} else if (list.size == 1) {
|
||||||
|
LOGGER.warn("Accepting degenerate poly with 1 points from asset ${AssetPathStack.lastFile()} to match original engine behavior")
|
||||||
|
return Poly(listOf(list[0], list[0], list[0], list[0]))
|
||||||
|
}
|
||||||
|
|
||||||
return Poly(list)
|
return Poly(list)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user