134 lines
3.6 KiB
Kotlin
134 lines
3.6 KiB
Kotlin
package ru.dbotthepony.kstarbound.world
|
|
|
|
import com.google.gson.Gson
|
|
import com.google.gson.JsonObject
|
|
import com.google.gson.JsonSyntaxException
|
|
import com.google.gson.TypeAdapter
|
|
import com.google.gson.TypeAdapterFactory
|
|
import com.google.gson.reflect.TypeToken
|
|
import com.google.gson.stream.JsonReader
|
|
import com.google.gson.stream.JsonToken
|
|
import com.google.gson.stream.JsonWriter
|
|
import ru.dbotthepony.kommons.gson.get
|
|
import ru.dbotthepony.kommons.vector.Vector3i
|
|
import ru.dbotthepony.kommons.gson.consumeNull
|
|
|
|
data class UniversePos(val location: Vector3i = Vector3i.ZERO, val planetOrbit: Int = 0, val satelliteOrbit: Int = 0) {
|
|
val isSystem: Boolean
|
|
get() = planetOrbit == 0
|
|
|
|
val isPlanet: Boolean
|
|
get() = planetOrbit != 0 && satelliteOrbit == 0
|
|
|
|
val isSatellite: Boolean
|
|
get() = planetOrbit != 0 && satelliteOrbit == 0
|
|
|
|
val orbitNumber: Int
|
|
get() = if (isSatellite) satelliteOrbit else if (isPlanet) planetOrbit else 0
|
|
|
|
fun system(): UniversePos {
|
|
if (planetOrbit == 0 && satelliteOrbit == 0)
|
|
return this
|
|
|
|
return UniversePos(location)
|
|
}
|
|
|
|
fun planet(): UniversePos {
|
|
if (satelliteOrbit == 0)
|
|
return this
|
|
|
|
return UniversePos(location, planetOrbit)
|
|
}
|
|
|
|
fun satellite(): UniversePos {
|
|
return this
|
|
}
|
|
|
|
fun parent(): UniversePos {
|
|
if (isSatellite)
|
|
return planet()
|
|
else if (isPlanet)
|
|
return system()
|
|
else
|
|
return this
|
|
}
|
|
|
|
companion object : TypeAdapterFactory {
|
|
private val splitter = Regex("[ _:]")
|
|
val ZERO = UniversePos()
|
|
|
|
override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
|
if (type.rawType == UniversePos::class.java) {
|
|
val vectors = gson.getAdapter(Vector3i::class.java)
|
|
val objects = gson.getAdapter(JsonObject::class.java)
|
|
|
|
return object : TypeAdapter<UniversePos>() {
|
|
override fun write(out: JsonWriter, value: UniversePos?) {
|
|
if (value == null)
|
|
out.nullValue()
|
|
else {
|
|
out.beginObject()
|
|
|
|
out.name("location")
|
|
vectors.write(out, value.location)
|
|
|
|
out.name("planet")
|
|
out.value(value.planetOrbit)
|
|
|
|
out.name("satellite")
|
|
out.value(value.satelliteOrbit)
|
|
|
|
out.endObject()
|
|
}
|
|
}
|
|
|
|
override fun read(`in`: JsonReader): UniversePos? {
|
|
if (`in`.consumeNull())
|
|
return null
|
|
|
|
if (`in`.peek() == JsonToken.BEGIN_OBJECT) {
|
|
val values = objects.read(`in`)!!
|
|
val location = values.get("location", vectors)
|
|
val planet = values.get("planet", 0)
|
|
val orbit = values.get("orbit", 0)
|
|
return UniversePos(location, planet, orbit)
|
|
}
|
|
|
|
if (`in`.peek() == JsonToken.STRING) {
|
|
val read = `in`.nextString().trim()
|
|
|
|
if (read == "" || read.lowercase() == "")
|
|
return ZERO
|
|
else {
|
|
try {
|
|
val split = read.split(splitter)
|
|
val x = split[0].toInt()
|
|
val y = split[1].toInt()
|
|
val z = split[2].toInt()
|
|
|
|
val planet = if (split.size > 3) split[3].toInt() else 0
|
|
val orbit = if (split.size > 4) split[4].toInt() else 0
|
|
|
|
if (planet <= 0) // TODO: ??? Determine, if this is a bug in original code
|
|
throw IndexOutOfBoundsException("Planetary orbit: $planet")
|
|
|
|
if (orbit < 0)
|
|
throw IndexOutOfBoundsException("Satellite orbit: $orbit")
|
|
|
|
return UniversePos(Vector3i(x, y, z), planet, orbit)
|
|
} catch (err: Throwable) {
|
|
throw JsonSyntaxException("Error parsing UniversePos from string", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
throw JsonSyntaxException("Invalid data type for UniversePos: ${`in`.peek()}")
|
|
}
|
|
} as TypeAdapter<T>
|
|
}
|
|
|
|
return null
|
|
}
|
|
}
|
|
}
|