Json function parsing?
This commit is contained in:
parent
bf458c2921
commit
b02477fc1a
build.gradle.kts
src/main/kotlin/ru/dbotthepony/kstarbound
@ -17,7 +17,7 @@ repositories {
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
url = uri("https://maven.dbotthepony.ru")
|
||||
url = uri("https://maven.dbotthepony.ru/")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ const val METRES_IN_STARBOUND_UNITf = 0.5f
|
||||
const val PIXELS_IN_STARBOUND_UNIT = 8.0
|
||||
const val PIXELS_IN_STARBOUND_UNITf = 8.0f
|
||||
|
||||
class TileDefLoadingException(message: String, cause: Throwable? = null) : IllegalStateException(message, cause)
|
||||
class ProjectileDefLoadingException(message: String, cause: Throwable? = null) : IllegalStateException(message, cause)
|
||||
// class TileDefLoadingException(message: String, cause: Throwable? = null) : IllegalStateException(message, cause)
|
||||
// class ProjectileDefLoadingException(message: String, cause: Throwable? = null) : IllegalStateException(message, cause)
|
||||
|
||||
object Starbound : IVFS {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
@ -40,10 +40,12 @@ object Starbound : IVFS {
|
||||
private val tiles = HashMap<String, TileDefinition>()
|
||||
private val projectiles = HashMap<String, ConfiguredProjectile>()
|
||||
private val parallax = HashMap<String, Parallax>()
|
||||
private val functions = HashMap<String, JsonFunction>()
|
||||
|
||||
val tilesAccess: Map<String, TileDefinition> = Collections.unmodifiableMap(tiles)
|
||||
val projectilesAccess: Map<String, ConfiguredProjectile> = Collections.unmodifiableMap(projectiles)
|
||||
val parallaxAccess: Map<String, Parallax> = Collections.unmodifiableMap(parallax)
|
||||
val functionsAccess: Map<String, JsonFunction> = Collections.unmodifiableMap(functions)
|
||||
|
||||
val gson: Gson = GsonBuilder()
|
||||
.enableComplexMapKeySerialization()
|
||||
@ -65,6 +67,7 @@ object Starbound : IVFS {
|
||||
.also(SkyParameters::registerGson)
|
||||
.also(DungeonWorldDef::registerGson)
|
||||
.also(Parallax::registerGson)
|
||||
.also(JsonFunction::registerGson)
|
||||
|
||||
.registerTypeAdapter(DamageType::class.java, CustomEnumTypeAdapter(DamageType.values()).nullSafe())
|
||||
|
||||
@ -149,6 +152,7 @@ object Starbound : IVFS {
|
||||
}
|
||||
}
|
||||
|
||||
loadStage(callback, this::loadFunctions, "functions")
|
||||
loadStage(callback, this::loadTileMaterials, "materials")
|
||||
loadStage(callback, this::loadProjectiles, "projectiles")
|
||||
loadStage(callback, this::loadParallax, "parallax definitions")
|
||||
@ -229,7 +233,8 @@ object Starbound : IVFS {
|
||||
check(tiles[tileDef.materialName] == null) { "Already has material with ID ${tileDef.materialName} loaded!" }
|
||||
tiles[tileDef.materialName] = tileDef
|
||||
} catch (err: Throwable) {
|
||||
throw TileDefLoadingException("Loading tile file $listedFile", err)
|
||||
//throw TileDefLoadingException("Loading tile file $listedFile", err)
|
||||
LOGGER.error("Loading tile file $listedFile", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,18 +243,35 @@ object Starbound : IVFS {
|
||||
|
||||
private fun loadProjectiles(callback: (String) -> Unit) {
|
||||
for (fs in fileSystems) {
|
||||
for (listedFile in fs.listAllFiles("projectiles")) {
|
||||
if (listedFile.endsWith(".projectile")) {
|
||||
try {
|
||||
callback("Loading $listedFile")
|
||||
for (listedFile in fs.listAllFilesWithExtension("projectile")) {
|
||||
try {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
val def = gson.fromJson(getReader(listedFile), ConfigurableProjectile::class.java).configure(getPathFolder(listedFile))
|
||||
check(projectiles[def.projectileName] == null) { "Already has projectile with ID ${def.projectileName} loaded!" }
|
||||
projectiles[def.projectileName] = def
|
||||
} catch(err: Throwable) {
|
||||
//throw ProjectileDefLoadingException("Loading projectile file $listedFile", err)
|
||||
LOGGER.error("Loading projectile file $listedFile", err)
|
||||
val def = gson.fromJson(getReader(listedFile), ConfigurableProjectile::class.java).configure(getPathFolder(listedFile))
|
||||
check(projectiles[def.projectileName] == null) { "Already has projectile with ID ${def.projectileName} loaded!" }
|
||||
projectiles[def.projectileName] = def
|
||||
} catch(err: Throwable) {
|
||||
//throw ProjectileDefLoadingException("Loading projectile file $listedFile", err)
|
||||
LOGGER.error("Loading projectile file $listedFile", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadFunctions(callback: (String) -> Unit) {
|
||||
for (fs in fileSystems) {
|
||||
for (listedFile in fs.listAllFilesWithExtension("functions")) {
|
||||
try {
|
||||
callback("Loading $listedFile")
|
||||
|
||||
val readObject = loadJson(listedFile) as JsonObject
|
||||
|
||||
for (key in readObject.keySet()) {
|
||||
val def = gson.fromJson(readObject[key], JsonFunction::class.java)
|
||||
functions[key] = def
|
||||
}
|
||||
} catch(err: Throwable) {
|
||||
LOGGER.error("Loading function file $listedFile", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,19 @@ interface IVFS {
|
||||
return ArrayList<String>(a.size + b.size).also { it.addAll(a); it.addAll(b) }
|
||||
}
|
||||
|
||||
fun listAllFilesWithExtension(extension: String): Collection<String> {
|
||||
val listing = ArrayList<String>()
|
||||
val ext = ".$extension"
|
||||
|
||||
for (listedFile in listAllFiles("")) {
|
||||
if (listedFile.endsWith(ext)) {
|
||||
listing.add(listedFile)
|
||||
}
|
||||
}
|
||||
|
||||
return listing
|
||||
}
|
||||
|
||||
fun listAllFiles(path: String): Collection<String> {
|
||||
val lists = mutableListOf<Collection<String>>()
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
package ru.dbotthepony.kstarbound.defs
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonArray
|
||||
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 ru.dbotthepony.kstarbound.io.CustomEnumTypeAdapter
|
||||
import ru.dbotthepony.kstarbound.io.IStringSerializable
|
||||
import ru.dbotthepony.kstarbound.io.Vector2dTypeAdapter
|
||||
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
||||
|
||||
enum class JsonFunctionInterpolation(vararg aliases: String) : IStringSerializable {
|
||||
LINEAR;
|
||||
|
||||
private val aliases: Array<String> = Array(aliases.size) { aliases[it].uppercase() }
|
||||
|
||||
override fun match(name: String): Boolean {
|
||||
for (alias in aliases)
|
||||
if (name == alias)
|
||||
return true
|
||||
|
||||
return name == this.name
|
||||
}
|
||||
|
||||
override fun write(out: JsonWriter) {
|
||||
out.value(this.name)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ADAPTER: TypeAdapter<JsonFunctionInterpolation> = CustomEnumTypeAdapter(values()).nullSafe()
|
||||
}
|
||||
}
|
||||
|
||||
enum class JsonFunctionConstraint(vararg aliases: String) : IStringSerializable {
|
||||
CLAMP;
|
||||
|
||||
private val aliases: Array<String> = Array(aliases.size) { aliases[it].uppercase() }
|
||||
|
||||
override fun match(name: String): Boolean {
|
||||
for (alias in aliases)
|
||||
if (name == alias)
|
||||
return true
|
||||
|
||||
return name == this.name
|
||||
}
|
||||
|
||||
override fun write(out: JsonWriter) {
|
||||
out.value(this.name)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ADAPTER: TypeAdapter<JsonFunctionConstraint> = CustomEnumTypeAdapter(values()).nullSafe()
|
||||
}
|
||||
}
|
||||
|
||||
class JsonFunction(
|
||||
val interpolation: JsonFunctionInterpolation,
|
||||
val constraint: JsonFunctionConstraint,
|
||||
val ranges: List<Vector2d>
|
||||
) {
|
||||
companion object : TypeAdapter<JsonFunction>() {
|
||||
override fun write(out: JsonWriter, value: JsonFunction) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun read(reader: JsonReader): JsonFunction {
|
||||
reader.beginArray()
|
||||
|
||||
val interpolation = JsonFunctionInterpolation.ADAPTER.read(reader)
|
||||
val constraint = JsonFunctionConstraint.ADAPTER.read(reader)
|
||||
|
||||
val ranges = ArrayList<Vector2d>()
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||
ranges.add(Vector2dTypeAdapter.read(reader))
|
||||
}
|
||||
|
||||
reader.endArray()
|
||||
|
||||
return JsonFunction(interpolation, constraint, ImmutableList.copyOf(ranges))
|
||||
}
|
||||
|
||||
fun registerGson(gsonBuilder: GsonBuilder) {
|
||||
gsonBuilder.registerTypeAdapter(JsonFunctionConstraint::class.java, JsonFunctionConstraint.ADAPTER)
|
||||
gsonBuilder.registerTypeAdapter(JsonFunctionInterpolation::class.java, JsonFunctionInterpolation.ADAPTER)
|
||||
gsonBuilder.registerTypeAdapter(JsonFunction::class.java, this)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
package ru.dbotthepony.kstarbound.io
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import ru.dbotthepony.kstarbound.api.IVFS
|
||||
import java.io.*
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.Channels
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
private fun readHeader(reader: RandomAccessFile, required: Int) {
|
||||
@ -124,6 +127,8 @@ class StarboundPakDirectory(val name: String, val parent: StarboundPakDirectory?
|
||||
|
||||
class StarboundPak(val path: File, callback: (finished: Boolean, status: String) -> Unit = { _, _ -> }) : Closeable, IVFS {
|
||||
val reader = RandomAccessFile(path, "r")
|
||||
private val filesByExtension = Object2ObjectArrayMap<String, ArrayList<StarboundPakFile>>()
|
||||
private val filesByExtensionPath = Object2ObjectArrayMap<String, ArrayList<String>>()
|
||||
|
||||
init {
|
||||
readHeader(reader, 0x53) // S
|
||||
@ -184,6 +189,13 @@ class StarboundPak(val path: File, callback: (finished: Boolean, status: String)
|
||||
|
||||
indexNodes[read.name] = read
|
||||
root.resolve(read.directoryHiearchy).writeFile(read)
|
||||
|
||||
val last = read.name.substringAfterLast('/').substringAfterLast('.', "")
|
||||
|
||||
if (last != "") {
|
||||
filesByExtension.computeIfAbsent(last, Object2ObjectFunction { ArrayList() }).add(read)
|
||||
filesByExtensionPath.computeIfAbsent(last, Object2ObjectFunction { ArrayList() }).add(read.name)
|
||||
}
|
||||
} catch (err: Throwable) {
|
||||
throw IOException("Reading index node at $i", err)
|
||||
}
|
||||
@ -212,4 +224,8 @@ class StarboundPak(val path: File, callback: (finished: Boolean, status: String)
|
||||
override fun close() {
|
||||
reader.close()
|
||||
}
|
||||
|
||||
override fun listAllFilesWithExtension(extension: String): Collection<String> {
|
||||
return filesByExtensionPath[extension]?.let(Collections::unmodifiableList) ?: listOf()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user