хз, всё равно надо что то другое

This commit is contained in:
DBotThePony 2023-02-08 14:51:15 +07:00
parent c3756b259a
commit bd690ee56c
Signed by: DBot
GPG Key ID: DCC23B5715498507
28 changed files with 273 additions and 582 deletions

View File

@ -162,8 +162,6 @@ class Starbound : ISBFileLocator {
registerTypeAdapter(JsonFunction.Companion)
// Общее
registerTypeAdapterFactory(LeveledStatusEffect.ADAPTER)
registerTypeAdapter(MaterialReference.Companion)
registerTypeAdapterFactory(ThingDescription.Factory(stringInterner))
registerTypeAdapter(EnumAdapter(DamageType::class, default = DamageType.NORMAL))
@ -172,7 +170,7 @@ class Starbound : ISBFileLocator {
registerTypeAdapter(spriteRegistry)
registerTypeAdapterFactory(IItemDefinition.InventoryIcon.Factory(pathStack, spriteRegistry))
registerTypeAdapterFactory(IArmorItemDefinition.ArmorFrames.Factory(pathStack, this@Starbound::atlasRegistry))
registerTypeAdapterFactory(IArmorItemDefinition.Frames.Factory(pathStack, this@Starbound::atlasRegistry))
registerTypeAdapterFactory(DirectAssetReferenceFactory(pathStack))
registerTypeAdapter(ImageReference.Adapter(pathStack, this@Starbound::atlasRegistry))

View File

@ -0,0 +1,107 @@
package ru.dbotthepony.kstarbound.defs
import ru.dbotthepony.kstarbound.io.json.builder.JsonIgnoreProperty
import ru.dbotthepony.kstarbound.util.INotNullDelegate
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
abstract class DefinitionBuilder {
interface IProperty {
fun checkAndThrow()
}
inner class Nullable<V>(private var value: V? = null) : ReadWriteProperty<Any?, V?>, IProperty {
override fun getValue(thisRef: Any?, property: KProperty<*>): V? {
return value
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: V?) {
if (isFrozen) throw IllegalStateException("$thisRef is frozen!")
this.value = value
}
override fun checkAndThrow() {
// no op
}
override fun equals(other: Any?): Boolean {
return other is Nullable<*> && other.value == value
}
override fun hashCode(): Int {
return value?.hashCode() ?: 0
}
override fun toString(): String {
return "Nullable[$value]"
}
}
inner class NotNull<V : Any>(private var value: V? = null) : ReadWriteProperty<Any?, V>, IProperty, INotNullDelegate {
override val isPresent: Boolean
get() = value != null
fun getNullable(): V? {
return value
}
override fun getValue(thisRef: Any?, property: KProperty<*>): V {
return checkNotNull(value) {"${property.name} was not initialized"}
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
if (isFrozen) throw IllegalStateException("$thisRef is frozen!")
this.value = value
}
override fun checkAndThrow() {
if (value == null) {
throw NullPointerException("Value was not initialized")
}
}
override fun equals(other: Any?): Boolean {
return other is NotNull<*> && other.value == value
}
override fun hashCode(): Int {
return value?.hashCode() ?: 0
}
override fun toString(): String {
return "NotNull[$value]"
}
}
@JsonIgnoreProperty
var isFrozen = false
private set
@JsonIgnoreProperty
private val properties = ArrayList<IProperty>()
override fun equals(other: Any?): Boolean {
if (other is DefinitionBuilder && other.javaClass === this.javaClass)
return other.properties == properties
return false
}
override fun hashCode(): Int {
return properties.hashCode()
}
override fun toString(): String {
return "${this::class.simpleName}[frozen=$isFrozen,values={${properties.joinToString(",")}}]"
}
protected open fun onFreeze() {
}
fun freeze() {
if (isFrozen) return
onFreeze()
isFrozen = true
}
}

View File

@ -8,6 +8,11 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kstarbound.util.PathStack
/**
* Путь как указан в JSON + Абсолютный путь
*
* @see DirectAssetReference
*/
class DirectAssetReferenceFactory(val remapper: PathStack) : TypeAdapterFactory {
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
if (type.rawType == DirectAssetReference::class.java) {
@ -33,4 +38,7 @@ class DirectAssetReferenceFactory(val remapper: PathStack) : TypeAdapterFactory
}
}
/**
* Путь как указан в JSON + Абсолютный путь
*/
data class DirectAssetReference(val path: String, val fullPath: String)

View File

@ -1,36 +0,0 @@
package ru.dbotthepony.kstarbound.defs
import com.google.gson.JsonSyntaxException
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
data class MaterialReference(
val id: Int?,
val name: String?
) {
init {
require(id != null || name != null) { "At least ID or material string ID should be not null" }
}
companion object : TypeAdapter<MaterialReference>() {
override fun write(out: JsonWriter, value: MaterialReference) {
if (value.id != null) {
out.value(value.id)
} else {
out.value(value.name!!)
}
}
override fun read(`in`: JsonReader): MaterialReference {
if (`in`.peek() == JsonToken.NUMBER) {
return MaterialReference(id = `in`.nextInt(), name = null)
} else if (`in`.peek() == JsonToken.STRING) {
return MaterialReference(id = null, name = `in`.nextString())
} else {
throw JsonSyntaxException("Invalid material reference: ${`in`.peek()} (must be either an Integer or String), near ${`in`.path}")
}
}
}
}

View File

@ -1,35 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.DirectAssetReference
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
data class ArmorItemDefinition(
override val itemName: String,
override val price: Long,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: List<IItemDefinition.IInventoryIcon>?,
override val itemTags: List<String>,
override val learnBlueprintsOnPickup: List<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: List<String>,
override val scripts: List<DirectAssetReference>,
override val scriptDelta: Int,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: List<String>,
override val fuelAmount: Long?,
override val colorOptions: List<Map<String, String>>,
override val maleFrames: IArmorItemDefinition.IArmorFrames,
override val femaleFrames: IArmorItemDefinition.IArmorFrames,
override val level: Double,
override val leveledStatusEffects: List<ILeveledStatusEffect>,
override val armorType: ArmorPieceType,
val descriptionData: ThingDescription,
) : IArmorItemDefinition, IThingWithDescription by descriptionData

View File

@ -2,85 +2,45 @@ package ru.dbotthepony.kstarbound.defs.item
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.DirectAssetReference
import ru.dbotthepony.kstarbound.defs.util.enrollMap
import ru.dbotthepony.kstarbound.io.json.builder.JsonBuilder
import ru.dbotthepony.kstarbound.io.json.builder.JsonIgnoreProperty
import ru.dbotthepony.kstarbound.util.NotNullVar
@JsonBuilder
open class ArmorItemPrototype : ItemPrototype(), IArmorItemDefinition {
override var colorOptions: ImmutableList<Map<String, String>> = ImmutableList.of()
override var maleFrames: IArmorItemDefinition.ArmorFrames by NotNullVar()
override var femaleFrames: IArmorItemDefinition.ArmorFrames by NotNullVar()
override var level: Double = 1.0
override var leveledStatusEffects: ImmutableList<LeveledStatusEffect> = ImmutableList.of()
abstract class ArmorItemPrototype : ItemPrototype(), IArmorItemDefinition {
override var colorOptions: ImmutableList<Map<String, String>> by NotNull(ImmutableList.of())
override var maleFrames: IArmorItemDefinition.Frames by NotNull()
override var femaleFrames: IArmorItemDefinition.Frames by NotNull()
override var level: Double by NotNull(1.0)
override var leveledStatusEffects: ImmutableList<LeveledStatusEffect> by NotNull(ImmutableList.of())
override var scripts: ImmutableList<DirectAssetReference> = ImmutableList.of()
override var scriptDelta: Int = 1
@JsonIgnoreProperty
override var armorType: ArmorPieceType by NotNullVar()
override var scripts: ImmutableList<DirectAssetReference> by NotNull(ImmutableList.of())
override var scriptDelta: Int by NotNull(1)
init {
maxStack = 1L
}
override fun assemble(): IItemDefinition {
return ArmorItemDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
scripts = scripts,
scriptDelta = scriptDelta,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
colorOptions = colorOptions,
maleFrames = maleFrames,
femaleFrames = femaleFrames,
level = level,
leveledStatusEffects = leveledStatusEffects,
armorType = armorType,
)
}
}
@JsonBuilder
class HeadArmorItemPrototype : ArmorItemPrototype() {
init {
armorType = ArmorPieceType.HEAD
}
@JsonIgnoreProperty
override val armorType: ArmorPieceType = ArmorPieceType.HEAD
}
@JsonBuilder
class ChestArmorItemPrototype : ArmorItemPrototype() {
init {
armorType = ArmorPieceType.CHEST
}
@JsonIgnoreProperty
override val armorType: ArmorPieceType = ArmorPieceType.CHEST
}
@JsonBuilder
class LegsArmorItemPrototype : ArmorItemPrototype() {
init {
armorType = ArmorPieceType.LEGS
}
@JsonIgnoreProperty
override val armorType: ArmorPieceType = ArmorPieceType.LEGS
}
@JsonBuilder
class BackArmorItemPrototype : ArmorItemPrototype() {
init {
armorType = ArmorPieceType.BACK
}
@JsonIgnoreProperty
override val armorType: ArmorPieceType = ArmorPieceType.BACK
}

View File

@ -1,32 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
data class CurrencyItemDefinition(
override val itemName: String,
override val price: Long,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: List<IItemDefinition.IInventoryIcon>?,
override val itemTags: List<String>,
override val learnBlueprintsOnPickup: List<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: List<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: List<String>,
override val fuelAmount: Long?,
override val pickupSoundsSmall: List<String>,
override val pickupSoundsMedium: List<String>,
override val pickupSoundsLarge: List<String>,
override val smallStackLimit: Long,
override val mediumStackLimit: Long,
override val currency: String,
override val value: Long,
val descriptionData: ThingDescription,
) : ICurrencyItemDefinition, IThingWithDescription by descriptionData

View File

@ -8,44 +8,10 @@ import ru.dbotthepony.kstarbound.util.NotNullVar
@JsonBuilder
class CurrencyItemPrototype : ItemPrototype(), ICurrencyItemDefinition {
override var pickupSoundsSmall: ImmutableList<String> = ImmutableList.of()
override var pickupSoundsMedium: ImmutableList<String> = ImmutableList.of()
override var pickupSoundsLarge: ImmutableList<String> = ImmutableList.of()
override var smallStackLimit: Long by NotNullVar()
override var mediumStackLimit: Long by NotNullVar()
override var currency: String by NotNullVar()
override var value: Long by NotNullVar()
override var currency: String by NotNull()
override var value: Long by NotNull()
init {
maxStack = 16777216L
}
override fun assemble(): IItemDefinition {
return CurrencyItemDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
pickupSoundsSmall = pickupSoundsSmall,
pickupSoundsMedium = pickupSoundsMedium,
pickupSoundsLarge = pickupSoundsLarge,
smallStackLimit = smallStackLimit,
mediumStackLimit = mediumStackLimit,
currency = currency,
value = value,
)
}
}

View File

@ -1,33 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kvector.vector.Color
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
data class FlashlightDefinition(
override val itemName: String,
override val price: Long,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: ImmutableList<out IItemDefinition.IInventoryIcon>?,
override val itemTags: ImmutableList<String>,
override val learnBlueprintsOnPickup: ImmutableList<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: ImmutableList<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: ImmutableList<String>,
override val fuelAmount: Long?,
override val lightPosition: Vector2d,
override val lightColor: Color,
override val beamLevel: Int,
override val beamAmbience: Double,
override val handPosition: Vector2d,
val descriptionData: ThingDescription,
) : IFlashlightDefinition, IThingWithDescription by descriptionData

View File

@ -8,40 +8,13 @@ import ru.dbotthepony.kvector.vector.ndouble.Vector2d
@JsonBuilder
class FlashlightPrototype : ItemPrototype(), IFlashlightDefinition {
override var lightPosition: Vector2d by NotNullVar()
override var lightColor: Color by NotNullVar()
override var beamLevel: Int by NotNullVar()
override var beamAmbience: Double by NotNullVar()
override var handPosition: Vector2d by NotNullVar()
override var lightPosition: Vector2d by NotNull()
override var lightColor: Color by NotNull()
override var beamLevel: Int by NotNull()
override var beamAmbience: Double by NotNull()
override var handPosition: Vector2d by NotNull()
init {
maxStack = 1L
}
override fun assemble(): IItemDefinition {
return FlashlightDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
lightPosition = lightPosition,
lightColor = lightColor,
beamLevel = beamLevel,
beamAmbience = beamAmbience,
handPosition = handPosition,
)
}
}

View File

@ -1,36 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
data class HarvestingToolDefinition(
override val itemName: String,
override val price: Long = 4L,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: ImmutableList<out IItemDefinition.IInventoryIcon>?,
override val itemTags: ImmutableList<String>,
override val learnBlueprintsOnPickup: ImmutableList<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: ImmutableList<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: ImmutableList<String>,
override val fuelAmount: Long?,
override val frames: Int,
override val animationCycle: Double,
override val blockRadius: Int,
override val altBlockRadius: Int,
override val idleSound: ImmutableList<String>,
override val strikeSounds: ImmutableList<String>,
override val handPosition: Vector2d,
override val fireTime: Double,
val descriptionData: ThingDescription,
) : IHarvestingToolDefinition, IThingWithDescription by descriptionData

View File

@ -8,46 +8,16 @@ import ru.dbotthepony.kvector.vector.ndouble.Vector2d
@JsonBuilder
class HarvestingToolPrototype : ItemPrototype(), IHarvestingToolDefinition {
override var frames: Int by NotNullVar()
override var animationCycle: Double by NotNullVar()
override var blockRadius: Int by NotNullVar()
override var altBlockRadius: Int = 0
override var idleSound: ImmutableList<String> = ImmutableList.of()
override var strikeSounds: ImmutableList<String> = ImmutableList.of()
override var handPosition: Vector2d by NotNullVar()
override var fireTime: Double by NotNullVar()
override var frames: Int by NotNull()
override var animationCycle: Double by NotNull()
override var blockRadius: Int by NotNull()
override var altBlockRadius: Int by NotNull(0)
override var idleSound: ImmutableList<String> by NotNull(ImmutableList.of())
override var strikeSounds: ImmutableList<String> by NotNull(ImmutableList.of())
override var handPosition: Vector2d by NotNull()
override var fireTime: Double by NotNull()
init {
maxStack = 1L
}
override fun assemble(): IItemDefinition {
return HarvestingToolDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
frames = frames,
animationCycle = animationCycle,
blockRadius = blockRadius,
altBlockRadius = altBlockRadius,
idleSound = idleSound,
strikeSounds = strikeSounds,
handPosition = handPosition,
fireTime = fireTime,
)
}
}

View File

@ -27,50 +27,50 @@ interface IArmorItemDefinition : ILeveledItemDefinition, IScriptableItemDefiniti
/**
* Визуальные кадры анимации, когда надето на гуманоида мужского пола
*/
val maleFrames: IArmorFrames
val maleFrames: IFrames
/**
* Визуальные кадры анимации, когда надето на гуманоида женского пола
*/
val femaleFrames: IArmorFrames
val femaleFrames: IFrames
@JsonImplementation(ArmorFrames::class)
interface IArmorFrames {
@JsonImplementation(Frames::class)
interface IFrames {
val body: ImageReference
val backSleeve: ImageReference?
val frontSleeve: ImageReference?
}
data class ArmorFrames(
data class Frames(
override val body: ImageReference,
override val backSleeve: ImageReference? = null,
override val frontSleeve: ImageReference? = null,
) : IArmorFrames {
) : IFrames {
class Factory(private val remapper: PathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapterFactory {
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
if (type.rawType == ArmorFrames::class.java) {
return object : TypeAdapter<ArmorFrames>() {
if (type.rawType == Frames::class.java) {
return object : TypeAdapter<Frames>() {
private val adapter = FactoryAdapter.Builder(
ArmorFrames::class,
ArmorFrames::body,
ArmorFrames::backSleeve,
ArmorFrames::frontSleeve,
Frames::class,
Frames::body,
Frames::backSleeve,
Frames::frontSleeve,
).build(gson)
override fun write(out: JsonWriter, value: ArmorFrames?) {
override fun write(out: JsonWriter, value: Frames?) {
if (value == null)
out.nullValue()
else
adapter.write(out, value)
}
override fun read(`in`: JsonReader): ArmorFrames? {
override fun read(`in`: JsonReader): Frames? {
if (`in`.peek() == JsonToken.NULL)
return null
if (`in`.peek() == JsonToken.STRING) {
val path = remapper.remap(`in`.nextString())
return ArmorFrames(ImageReference(path, atlasRegistry.invoke().get(path)), null, null)
return Frames(ImageReference(path, atlasRegistry.invoke().get(path)), null, null)
}
return adapter.read(`in`)

View File

@ -1,31 +1,6 @@
package ru.dbotthepony.kstarbound.defs.item
interface ICurrencyItemDefinition : IItemDefinition {
/**
* Звуки при поднятии "малого" количества предметов. Не имеет никакого смысла без [smallStackLimit]
*/
val pickupSoundsSmall: List<String>
/**
* Звуки при поднятии "среднего" количества предметов. Не имеет никакого смысла без [mediumStackLimit]
*/
val pickupSoundsMedium: List<String>
/**
* Звуки при поднятии "большого" количества предметов. Не имеет никакого смысла без [smallStackLimit] и без [mediumStackLimit]
*/
val pickupSoundsLarge: List<String>
/**
* Количество предметов ниже или равному данному значению проиграет звук [pickupSoundsSmall]
*/
val smallStackLimit: Long
/**
* Количество предметов ниже или равному данному значению (но не меньше [smallStackLimit]) проиграет звук [pickupSoundsMedium]
*/
val mediumStackLimit: Long
/**
* ID валюты
*/

View File

@ -8,6 +8,7 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.RegistryReference
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
@ -90,7 +91,7 @@ interface IItemDefinition : IThingWithDescription {
/**
* При подборе предмета мгновенно заставляет игрока изучить эти рецепты крафта
*/
val learnBlueprintsOnPickup: List<String>
val learnBlueprintsOnPickup: List<RegistryReference<IItemDefinition>>
/**
* Максимальное количество предмета в стопке
@ -133,4 +134,29 @@ interface IItemDefinition : IThingWithDescription {
* Топливо корабля
*/
val fuelAmount: Long?
/**
* Звуки при поднятии "малого" количества предметов. Не имеет никакого смысла без [smallStackLimit]
*/
val pickupSoundsSmall: List<String>
/**
* Звуки при поднятии "среднего" количества предметов. Не имеет никакого смысла без [mediumStackLimit]
*/
val pickupSoundsMedium: List<String>
/**
* Звуки при поднятии "большого" количества предметов. Не имеет никакого смысла без [smallStackLimit] и без [mediumStackLimit]
*/
val pickupSoundsLarge: List<String>
/**
* Количество предметов ниже или равному данному значению проиграет звук [pickupSoundsSmall]
*/
val smallStackLimit: Long?
/**
* Количество предметов ниже или равному данному значению (но не меньше [smallStackLimit]) проиграет звук [pickupSoundsMedium]
*/
val mediumStackLimit: Long?
}

View File

@ -1,7 +1,9 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
@JsonImplementation(LeveledStatusEffect::class)
interface ILeveledStatusEffect {
val levelFunction: String
val stat: String
@ -9,17 +11,10 @@ interface ILeveledStatusEffect {
val amount: Double
}
@JsonFactory
data class LeveledStatusEffect(
override val levelFunction: String,
override val stat: String,
override val baseMultiplier: Double = 1.0,
override val amount: Double = 0.0,
) : ILeveledStatusEffect {
companion object {
val ADAPTER = FactoryAdapter.Builder(LeveledStatusEffect::class,
LeveledStatusEffect::levelFunction,
LeveledStatusEffect::stat,
LeveledStatusEffect::baseMultiplier,
LeveledStatusEffect::amount)
}
}
) : ILeveledStatusEffect

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.util.Either
interface ILiquidItem : IItemDefinition {
/**
* То, какую жидкость из себя представляет данный предмет
*/
val liquid: MaterialReference
val liquid: Either<Int, String>
}

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.util.Either
interface IMaterialItem : IItemDefinition {
/**
* То, какой материал (блок) из себя представляет данный предмет
*/
val material: MaterialReference
val material: Either<Int, String>
}

View File

@ -1,27 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.io.json.builder.JsonPropertyConfig
data class ItemDefinition(
override val itemName: String,
override val price: Long = 4L,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: ImmutableList<out IItemDefinition.IInventoryIcon>?,
override val itemTags: ImmutableList<String>,
override val learnBlueprintsOnPickup: ImmutableList<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: ImmutableList<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: ImmutableList<String>,
override val fuelAmount: Long?,
val descriptionData: ThingDescription,
) : IItemDefinition, IThingWithDescription by descriptionData

View File

@ -1,6 +1,8 @@
package ru.dbotthepony.kstarbound.defs.item
import com.google.common.collect.ImmutableList
import ru.dbotthepony.kstarbound.defs.DefinitionBuilder
import ru.dbotthepony.kstarbound.defs.RegistryReference
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kstarbound.defs.util.enrollMap
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter
@ -11,49 +13,45 @@ import ru.dbotthepony.kstarbound.io.json.builder.JsonIgnoreProperty
import ru.dbotthepony.kstarbound.util.NotNullVar
@JsonBuilder
open class ItemPrototype : IItemDefinition {
open class ItemPrototype : DefinitionBuilder(), IItemDefinition {
@JsonIgnoreProperty
final override var shortdescription: String = "..."
@JsonIgnoreProperty
final override var description: String = "..."
final override val shortdescription: String
get() = descriptionData.shortdescription
final override var itemName: String by NotNullVar()
final override var price: Long = 0L
final override var rarity: ItemRarity = ItemRarity.COMMON
final override var category: String? = null
final override var inventoryIcon: ImmutableList<IItemDefinition.InventoryIcon>? = null
final override var itemTags: ImmutableList<String> = ImmutableList.of()
final override var learnBlueprintsOnPickup: ImmutableList<String> = ImmutableList.of()
final override var maxStack: Long = 9999L
final override var eventCategory: String? = null
final override var consumeOnPickup: Boolean = false
final override var pickupQuestTemplates: ImmutableList<String> = ImmutableList.of()
final override var tooltipKind: String = "normal"
final override var twoHanded: Boolean = false
final override var radioMessagesOnPickup: ImmutableList<String> = ImmutableList.of()
final override var fuelAmount: Long? = null
@JsonIgnoreProperty
final override val description: String
get() = descriptionData.description
@JsonIgnoreProperty
final override val racialDescription: Map<String, String>
get() = descriptionData.racialDescription
@JsonIgnoreProperty
final override val racialShortDescription: Map<String, String>
get() = descriptionData.racialShortDescription
@JsonPropertyConfig(isFlat = true)
var descriptionData: ThingDescription by NotNullVar()
open fun assemble(): IItemDefinition {
return ItemDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
)
}
final override var itemName: String by NotNull()
final override var price: Long by NotNull(0L)
final override var rarity: ItemRarity by NotNull(ItemRarity.COMMON)
final override var category: String? by Nullable()
final override var inventoryIcon: ImmutableList<IItemDefinition.InventoryIcon>? by Nullable()
final override var itemTags: ImmutableList<String> by NotNull(ImmutableList.of())
final override var learnBlueprintsOnPickup: ImmutableList<RegistryReference<IItemDefinition>> by NotNull(ImmutableList.of())
final override var maxStack: Long by NotNull(9999L)
final override var eventCategory: String? by Nullable()
final override var consumeOnPickup: Boolean by NotNull(false)
final override var pickupQuestTemplates: ImmutableList<String> by NotNull(ImmutableList.of())
final override var tooltipKind: String by NotNull("normal")
final override var twoHanded: Boolean by NotNull(false)
final override var radioMessagesOnPickup: ImmutableList<String> by NotNull(ImmutableList.of())
final override var fuelAmount: Long? by Nullable()
final override var pickupSoundsSmall: ImmutableList<String> by NotNull(ImmutableList.of())
final override var pickupSoundsMedium: ImmutableList<String> by NotNull(ImmutableList.of())
final override var pickupSoundsLarge: ImmutableList<String> by NotNull(ImmutableList.of())
final override var smallStackLimit: Long? by Nullable()
final override var mediumStackLimit: Long? by Nullable()
}

View File

@ -1,27 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.defs.ThingDescription
data class LiquidItemDefinition(
override val itemName: String,
override val price: Long,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: List<IItemDefinition.IInventoryIcon>?,
override val itemTags: List<String>,
override val learnBlueprintsOnPickup: List<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: List<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: List<String>,
override val fuelAmount: Long?,
override val liquid: MaterialReference,
val descriptionData: ThingDescription,
) : ILiquidItem, IThingWithDescription by descriptionData

View File

@ -1,45 +1,24 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.defs.util.enrollMap
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter
import ru.dbotthepony.kstarbound.io.json.builder.JsonBuilder
import ru.dbotthepony.kstarbound.util.Either
@JsonBuilder
class LiquidItemPrototype : ItemPrototype() {
var liquid: MaterialReference? = null
class LiquidItemPrototype : ItemPrototype(), ILiquidItem {
private val liquidDelegate = NotNull<Either<Int, String>>()
override var liquid: Either<Int, String> by liquidDelegate
var liquidId: Int?
get() = liquid?.id
set(value) {
if (liquid == null)
liquid = MaterialReference(id = value, name = null)
}
get() = liquidDelegate.getNullable()?.left
set(value) { if (liquidDelegate.getNullable() == null) liquid = Either.left(value!!) }
var liquidName: String?
get() = liquid?.name
set(value) { liquid = MaterialReference(name = value, id = null) }
get() = liquidDelegate.getNullable()?.right
set(value) { liquid = Either.right(value!!) }
override fun assemble(): IItemDefinition {
return LiquidItemDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
liquid = checkNotNull(liquid) { "Liquid is null (either 'liquidId' or 'liquidName' should be present, or 'liquid' itself)" },
)
override fun onFreeze() {
if (liquidDelegate.getNullable() == null) {
throw NullPointerException("no liquidId nor liquidName was defined")
}
}
}

View File

@ -1,27 +0,0 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.IThingWithDescription
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.defs.ThingDescription
data class MaterialItemDefinition(
override val itemName: String,
override val price: Long,
override val rarity: ItemRarity,
override val category: String?,
override val inventoryIcon: List<IItemDefinition.IInventoryIcon>?,
override val itemTags: List<String>,
override val learnBlueprintsOnPickup: List<String>,
override val maxStack: Long,
override val eventCategory: String?,
override val consumeOnPickup: Boolean,
override val pickupQuestTemplates: List<String>,
override val tooltipKind: String,
override val twoHanded: Boolean,
override val radioMessagesOnPickup: List<String>,
override val fuelAmount: Long?,
override val material: MaterialReference,
val descriptionData: ThingDescription,
) : IMaterialItem, IThingWithDescription by descriptionData

View File

@ -1,45 +1,24 @@
package ru.dbotthepony.kstarbound.defs.item
import ru.dbotthepony.kstarbound.defs.MaterialReference
import ru.dbotthepony.kstarbound.defs.util.enrollMap
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter
import ru.dbotthepony.kstarbound.io.json.builder.JsonBuilder
import ru.dbotthepony.kstarbound.util.Either
@JsonBuilder
class MaterialItemPrototype : ItemPrototype() {
var material: MaterialReference? = null
class MaterialItemPrototype : ItemPrototype(), IMaterialItem {
private val materialDelegate = NotNull<Either<Int, String>>()
override var material: Either<Int, String> by materialDelegate
var materialId: Int?
get() = material?.id
set(value) {
if (material == null)
material = MaterialReference(id = value, name = null)
}
get() = materialDelegate.getNullable()?.left
set(value) { if (materialDelegate.getNullable() == null) material = Either.left(value!!) }
var materialName: String?
get() = material?.name
set(value) { material = MaterialReference(name = value, id = null) }
get() = materialDelegate.getNullable()?.right
set(value) { material = Either.right(value!!) }
override fun assemble(): IItemDefinition {
return MaterialItemDefinition(
descriptionData = descriptionData,
itemName = itemName,
price = price,
rarity = rarity,
category = category,
inventoryIcon = inventoryIcon,
itemTags = itemTags,
learnBlueprintsOnPickup = learnBlueprintsOnPickup,
maxStack = maxStack,
eventCategory = eventCategory,
consumeOnPickup = consumeOnPickup,
pickupQuestTemplates = pickupQuestTemplates,
tooltipKind = tooltipKind,
twoHanded = twoHanded,
radioMessagesOnPickup = radioMessagesOnPickup,
fuelAmount = fuelAmount,
material = checkNotNull(material) { "Material is null (either 'materialId' or 'materialName' should be present, or 'material' itself)" },
)
override fun onFreeze() {
if (material == null) {
throw NullPointerException("no materialId nor materialName was defined")
}
}
}

View File

@ -19,8 +19,10 @@ import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kstarbound.defs.DefinitionBuilder
import ru.dbotthepony.kstarbound.defs.util.flattenJsonElement
import ru.dbotthepony.kstarbound.io.json.builder.BuilderAdapter.Builder
import ru.dbotthepony.kstarbound.util.INotNullDelegate
import ru.dbotthepony.kstarbound.util.NotNullVar
import kotlin.properties.Delegates
import kotlin.reflect.KClass
@ -173,7 +175,7 @@ class BuilderAdapter<T : Any> private constructor(
val delegate = property.property.getDelegate(instance)
if (delegate is NotNullVar<*> && !delegate.isInitialized) {
if (delegate is INotNullDelegate && !delegate.isPresent) {
throw JsonSyntaxException("${property.name} in ${instance::class.qualifiedName} can not be null, but it is missing from JSON structure")
} else {
try {
@ -185,6 +187,10 @@ class BuilderAdapter<T : Any> private constructor(
}
}
if (instance is DefinitionBuilder) {
instance.freeze()
}
return instance
}

View File

@ -0,0 +1,5 @@
package ru.dbotthepony.kstarbound.util
interface INotNullDelegate {
val isPresent: Boolean
}

View File

@ -7,13 +7,13 @@ import kotlin.properties.Delegates
/**
* Аналог [Delegates.notNull], но со свойством [isInitialized]
*/
class NotNullVar<V : Any> : ReadWriteProperty<Any?, V> {
class NotNullVar<V : Any> : ReadWriteProperty<Any?, V>, INotNullDelegate {
private var value: V? = null
/**
* Имеет ли данный делегат не-null значение
*/
val isInitialized: Boolean
override val isPresent: Boolean
get() = value != null
override fun getValue(thisRef: Any?, property: KProperty<*>): V {

View File

@ -6,7 +6,6 @@ import ru.dbotthepony.kbox2d.api.Manifold
import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape
import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
import ru.dbotthepony.kstarbound.defs.item.ItemDefinition
import ru.dbotthepony.kstarbound.world.World
class ItemEntity(world: World<*, *>, val def: IItemDefinition) : Entity(world) {