KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/defs/object/ObjectDefinition.kt

238 lines
9.4 KiB
Kotlin

package ru.dbotthepony.kstarbound.defs.`object`
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSet
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSyntaxException
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetPath
import ru.dbotthepony.kstarbound.defs.ItemReference
import ru.dbotthepony.kstarbound.defs.JsonReference
import ru.dbotthepony.kstarbound.defs.StatModifier
import ru.dbotthepony.kstarbound.defs.item.TreasurePoolDefinition
import ru.dbotthepony.kstarbound.defs.tile.TileDamageConfig
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.json.consumeNull
import ru.dbotthepony.kstarbound.json.listAdapter
import ru.dbotthepony.kstarbound.json.stream
import ru.dbotthepony.kstarbound.math.PeriodicFunction
import ru.dbotthepony.kstarbound.util.Either
import ru.dbotthepony.kstarbound.json.contains
import ru.dbotthepony.kstarbound.json.get
import ru.dbotthepony.kstarbound.json.getArray
import ru.dbotthepony.kstarbound.json.set
import ru.dbotthepony.kvector.vector.RGBAColor
data class ObjectDefinition(
val objectName: String,
val objectType: ObjectType = ObjectType.OBJECT,
val race: String = "generic",
val category: String = "other",
val colonyTags: ImmutableSet<String> = ImmutableSet.of(),
val scripts: ImmutableSet<AssetPath> = ImmutableSet.of(),
val animationScripts: ImmutableSet<AssetPath> = ImmutableSet.of(),
val hasObjectItem: Boolean = true,
val scannable: Boolean = true,
val retainObjectParametersInItem: Boolean = false,
val breakDropPool: Registry.Ref<TreasurePoolDefinition>? = null,
// null - not specified, empty list - always drop nothing
val breakDropOptions: ImmutableList<ImmutableList<ItemReference>>? = null,
val smashDropPool: Registry.Ref<TreasurePoolDefinition>? = null,
val smashDropOptions: ImmutableList<ImmutableList<ItemReference>> = ImmutableList.of(),
//val animation: AssetReference<AnimationDefinition>? = null,
val animation: AssetPath? = null,
val smashSounds: ImmutableSet<AssetPath> = ImmutableSet.of(),
val smashParticles: JsonArray? = null,
val smashable: Boolean = false,
val unbreakable: Boolean = false,
val damageShakeMagnitude: Double = 0.2,
val damageMaterialKind: String = "solid",
val damageTeam: DamageTeam = DamageTeam(),
val lightColor: RGBAColor? = null,
val lightColors: ImmutableMap<String, RGBAColor> = ImmutableMap.of(),
val pointLight: Boolean = false,
val pointBeam: Double = 0.0,
val beamAmbience: Double = 0.0,
val soundEffect: AssetPath? = null,
val soundEffectRangeMultiplier: Double = 1.0,
val price: Long = 1L,
val statusEffects: ImmutableList<Either<String, StatModifier>> = ImmutableList.of(),
val touchDamage: JsonReference.Object = JsonReference.Object(null, null, null),
val minimumLiquidLevel: Float? = null,
val maximumLiquidLevel: Float? = null,
val liquidCheckInterval: Float = 0.5f,
val health: Double = 1.0,
val rooting: Boolean = false,
val biomePlaced: Boolean = false,
val printable: Boolean = false,
val smashOnBreak: Boolean = false,
val damageConfig: TileDamageConfig,
val flickerPeriod: PeriodicFunction? = null,
val orientations: ImmutableList<ObjectOrientation>,
) {
companion object {
}
class Adapter(gson: Gson) : TypeAdapter<ObjectDefinition>() {
@JsonFactory(logMisses = false)
class PlainData(
val objectName: String,
val objectType: ObjectType = ObjectType.OBJECT,
val race: String = "generic",
val category: String = "other",
val colonyTags: ImmutableSet<String> = ImmutableSet.of(),
val scripts: ImmutableSet<AssetPath> = ImmutableSet.of(),
val animationScripts: ImmutableSet<AssetPath> = ImmutableSet.of(),
val hasObjectItem: Boolean = true,
val scannable: Boolean = true,
val retainObjectParametersInItem: Boolean = false,
val breakDropPool: Registry.Ref<TreasurePoolDefinition>? = null,
// null - not specified, empty list - always drop nothing
val breakDropOptions: ImmutableList<ImmutableList<ItemReference>>? = null,
val smashDropPool: Registry.Ref<TreasurePoolDefinition>? = null,
val smashDropOptions: ImmutableList<ImmutableList<ItemReference>> = ImmutableList.of(),
//val animation: AssetReference<AnimationDefinition>? = null,
val animation: AssetPath? = null,
val smashSounds: ImmutableSet<AssetPath> = ImmutableSet.of(),
val smashParticles: JsonArray? = null,
val smashable: Boolean = false,
val unbreakable: Boolean = false,
val damageShakeMagnitude: Double = 0.2,
val damageMaterialKind: String = "solid",
val damageTeam: DamageTeam = DamageTeam(),
val lightColor: RGBAColor? = null,
val lightColors: ImmutableMap<String, RGBAColor> = ImmutableMap.of(),
val pointLight: Boolean = false,
val pointBeam: Double = 0.0,
val beamAmbience: Double = 0.0,
val soundEffect: AssetPath? = null,
val soundEffectRangeMultiplier: Double = 1.0,
val price: Long = 1L,
val statusEffects: ImmutableList<Either<String, StatModifier>> = ImmutableList.of(),
//val touchDamage: TouchDamage,
val touchDamage: JsonReference.Object = JsonReference.Object(null, null, null),
val minimumLiquidLevel: Float? = null,
val maximumLiquidLevel: Float? = null,
val liquidCheckInterval: Float = 0.5f,
val health: Double = 1.0,
val rooting: Boolean = false,
val biomePlaced: Boolean = false,
)
private val objects = gson.getAdapter(JsonObject::class.java)
private val objectRef = gson.getAdapter(JsonReference.Object::class.java)
private val basic = gson.getAdapter(PlainData::class.java)
private val damageConfig = gson.getAdapter(TileDamageConfig::class.java)
private val damageTeam = gson.getAdapter(DamageTeam::class.java)
private val orientations = gson.getAdapter(ObjectOrientation::class.java)
private val emitter = gson.getAdapter(ParticleEmissionEntry::class.java)
private val emitters = gson.listAdapter<ParticleEmissionEntry>()
override fun write(out: JsonWriter, value: ObjectDefinition?) {
if (value == null) {
out.nullValue()
} else {
TODO()
}
}
override fun read(`in`: JsonReader): ObjectDefinition? {
if (`in`.consumeNull())
return null
val read = objects.read(`in`)
val basic = basic.fromJsonTree(read)
val printable = basic.hasObjectItem && read.get("printable", basic.scannable)
val smashOnBreak = read.get("smashOnBreak", basic.smashable)
val getDamageParams = objectRef.fromJsonTree(read.get("damageTable", JsonPrimitive("/objects/defaultParameters.config:damageTable")))
getDamageParams?.value ?: throw JsonSyntaxException("No valid damageTable specified")
getDamageParams.value["health"] = read["health"]
getDamageParams.value["harvestLevel"] = read["harvestLevel"]
val damageConfig = damageConfig.fromJsonTree(getDamageParams.value)
val flickerPeriod = if ("flickerPeriod" in read) {
PeriodicFunction(
read.get("flickerPeriod", 0.0),
read.get("flickerMinIntensity", 0.0),
read.get("flickerMaxIntensity", 0.0),
read.get("flickerPeriodVariance", 0.0),
read.get("flickerIntensityVariance", 0.0),
)
} else {
null
}
val orientations = ObjectOrientation.preprocess(read.getArray("orientations"))
.stream()
.map { orientations.fromJsonTree(it) }
.collect(ImmutableList.toImmutableList())
if ("particleEmitter" in read) {
orientations.forEach { it.particleEmitters.add(emitter.fromJsonTree(read["particleEmitter"])) }
}
if ("particleEmitters" in read) {
orientations.forEach { it.particleEmitters.addAll(emitters.fromJsonTree(read["particleEmitters"])) }
}
return ObjectDefinition(
objectName = basic.objectName,
objectType = basic.objectType,
race = basic.race,
category = basic.category,
colonyTags = basic.colonyTags,
scripts = basic.scripts,
animationScripts = basic.animationScripts,
hasObjectItem = basic.hasObjectItem,
scannable = basic.scannable,
retainObjectParametersInItem = basic.retainObjectParametersInItem,
breakDropPool = basic.breakDropPool,
breakDropOptions = basic.breakDropOptions,
smashDropPool = basic.smashDropPool,
smashDropOptions = basic.smashDropOptions,
animation = basic.animation,
smashSounds = basic.smashSounds,
smashParticles = basic.smashParticles,
smashable = basic.smashable,
unbreakable = basic.unbreakable,
damageShakeMagnitude = basic.damageShakeMagnitude,
damageMaterialKind = basic.damageMaterialKind,
damageTeam = basic.damageTeam,
lightColor = basic.lightColor,
lightColors = basic.lightColors,
pointLight = basic.pointLight,
pointBeam = basic.pointBeam,
beamAmbience = basic.beamAmbience,
soundEffect = basic.soundEffect,
soundEffectRangeMultiplier = basic.soundEffectRangeMultiplier,
price = basic.price,
statusEffects = basic.statusEffects,
touchDamage = basic.touchDamage,
minimumLiquidLevel = basic.minimumLiquidLevel,
maximumLiquidLevel = basic.maximumLiquidLevel,
liquidCheckInterval = basic.liquidCheckInterval,
health = basic.health,
rooting = basic.rooting,
biomePlaced = basic.biomePlaced,
printable = printable,
smashOnBreak = smashOnBreak,
damageConfig = damageConfig,
flickerPeriod = flickerPeriod,
orientations = orientations,
)
}
}
}