package ru.dbotthepony.kstarbound.item import com.google.gson.JsonNull import com.google.gson.JsonObject import ru.dbotthepony.kommons.io.koptional import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.defs.DamageSource import ru.dbotthepony.kstarbound.defs.PhysicsForceRegion import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition import ru.dbotthepony.kstarbound.defs.item.ItemDescriptor import ru.dbotthepony.kstarbound.json.mergeJson import ru.dbotthepony.kstarbound.network.syncher.InternedStringCodec import ru.dbotthepony.kstarbound.network.syncher.JsonElementCodec import ru.dbotthepony.kstarbound.network.syncher.NetworkedGroup import ru.dbotthepony.kstarbound.network.syncher.NetworkedList import ru.dbotthepony.kstarbound.network.syncher.NetworkedMap import ru.dbotthepony.kstarbound.network.syncher.NetworkedStatefulItemStack import ru.dbotthepony.kstarbound.network.syncher.networkedBoolean import ru.dbotthepony.kstarbound.network.syncher.networkedData import ru.dbotthepony.kstarbound.network.syncher.networkedFixedPoint2 import ru.dbotthepony.kstarbound.util.AssetPathStack import ru.dbotthepony.kstarbound.world.Direction import ru.dbotthepony.kstarbound.world.entities.Animator import ru.dbotthepony.kstarbound.world.physics.Poly class ActiveItemStack(entry: ItemRegistry.Entry, config: JsonObject, parameters: JsonObject, size: Long) : ItemStack(entry, config, parameters, size), NetworkedStatefulItemStack.Stateful { override val networkElement = NetworkedGroup() val animator: Animator init { var animationConfig = Starbound.loadJsonAsset(lookupProperty("animation"), entry.directory) ?: JsonNull.INSTANCE val animationCustom = lookupProperty("animationCustom") if (!animationCustom.isJsonNull) { animationConfig = mergeJson(animationConfig.deepCopy(), animationCustom) } try { if (animationConfig.isJsonNull) { animator = Animator() } else { animator = Animator(Starbound.gson.fromJson(animationConfig, AnimationDefinition::class.java)) } } catch (err: Throwable) { throw RuntimeException("Unable to instance animator for ${entry.name} (animation config: ${lookupProperty("animation")})", err) } networkElement.add(animator.networkGroup) } var holdingItem by networkedBoolean(true).also { networkElement.add(it) } var backArmFrame by networkedData(KOptional(), InternedStringCodec.koptional()).also { networkElement.add(it) } var frontArmFrame by networkedData(KOptional(), InternedStringCodec.koptional()).also { networkElement.add(it) } var twoHandedGrip by networkedBoolean().also { networkElement.add(it) } var recoil by networkedBoolean().also { networkElement.add(it) } var outsideOfHand by networkedBoolean().also { networkElement.add(it) } var armAngle by networkedFixedPoint2(0.01).also { networkElement.add(it) } var facingDirection by networkedData(KOptional(), Direction.CODEC.koptional()).also { networkElement.add(it) } val damageSources = NetworkedList(DamageSource.CODEC, DamageSource.LEGACY_CODEC).also { networkElement.add(it) } val itemDamageSources = NetworkedList(DamageSource.CODEC, DamageSource.LEGACY_CODEC).also { networkElement.add(it) } val shieldPolys = NetworkedList(Poly.CODEC, Poly.LEGACY_CODEC).also { networkElement.add(it) } val itemShieldPolys = NetworkedList(Poly.CODEC, Poly.LEGACY_CODEC).also { networkElement.add(it) } val forceRegions = NetworkedList(PhysicsForceRegion.CODEC, PhysicsForceRegion.LEGACY_CODEC).also { networkElement.add(it) } val itemForceRegions = NetworkedList(PhysicsForceRegion.CODEC, PhysicsForceRegion.LEGACY_CODEC).also { networkElement.add(it) } val scriptedAnimationParameters = NetworkedMap(InternedStringCodec, JsonElementCodec).also { networkElement.add(it, false) } init { for ((k, v) in lookupProperty("animationParts", JsonObject()).asJsonObject.entrySet()) { animator.setPartTag(k, "partImage", v.asString) } val scriptedAnimationParameters = lookupProperty("scriptedAnimationParameters") if (scriptedAnimationParameters is JsonObject) { for ((k, v) in scriptedAnimationParameters.entrySet()) { this.scriptedAnimationParameters[k] = v.deepCopy() } } } override fun copy(size: Long): ItemStack { if (isEmpty) return EMPTY return ActiveItemStack(entry, config, parameters.deepCopy(), size) } }