diff --git a/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeDelegate.kt b/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeDelegate.kt new file mode 100644 index 0000000000..9c9e20e7be --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeDelegate.kt @@ -0,0 +1,24 @@ +package gg.rsmod.game.model.attr + +import gg.rsmod.game.model.entity.Pawn +import kotlin.reflect.KProperty + +/** + * A delegate class meant for delegating [Pawn] extension properties to. + * + * @property [attributeKey] The [AttributeKey] being delegated to + * + * @property [defaultValue] The default value when [getValue] is called but [Pawn.attr] fails to return a [T] + * + * @author Curtis Woodard + */ +class AttributeDelegate(val attributeKey: AttributeKey, private val defaultValue: T) { + constructor(persistenceKey: String? = null, resetOnDeath: Boolean = false, defaultValue: T): this( + attributeKey = AttributeKey(persistenceKey, resetOnDeath), + defaultValue = defaultValue + ) + + operator fun getValue(pawn: Pawn, prop: KProperty<*>): T = pawn.attr[attributeKey] ?: defaultValue + + operator fun setValue(pawn: Pawn, prop: KProperty<*>, newValue: T) { pawn.attr[attributeKey] = newValue } +} diff --git a/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeKey.kt b/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeKey.kt index 6ebd4c1322..59b3497263 100644 --- a/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeKey.kt +++ b/game/src/main/kotlin/gg/rsmod/game/model/attr/AttributeKey.kt @@ -1,11 +1,15 @@ package gg.rsmod.game.model.attr import com.google.common.base.MoreObjects +import gg.rsmod.game.model.entity.Pawn +import kotlin.reflect.KProperty /** * An [AttributeKey] is a flexible key that can be used to represent any type of * value. * + * Can also be used as a delegate for a [Pawn] extension property + * * @param T * The type of the value that this attribute will store. * @@ -26,6 +30,15 @@ import com.google.common.base.MoreObjects */ class AttributeKey(val persistenceKey: String? = null, val resetOnDeath: Boolean = false) { + operator fun getValue(ref: Pawn, prop: KProperty<*>): T = ref.attr[this] as T + + operator fun setValue(ref: Pawn, prop: KProperty<*>, value: T) { ref.attr[this] = value } + + /** + * For when you want to delegate to this key but also want a default value just in case. + */ + operator fun invoke(defaultValue: T) = AttributeDelegate(this, defaultValue) + override fun toString(): String = MoreObjects.toStringHelper(this).add("persistenceKey", persistenceKey).add("resetOnDeath", resetOnDeath).toString() override fun equals(other: Any?): Boolean { diff --git a/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/VarbitDelegate.kt b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/VarbitDelegate.kt new file mode 100644 index 0000000000..a9e00826a4 --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/VarbitDelegate.kt @@ -0,0 +1,68 @@ +package gg.rsmod.game.model.varbit.delegate + +import gg.rsmod.game.fs.def.VarbitDef +import gg.rsmod.game.model.entity.Player +import kotlin.reflect.KProperty + +/** + * Allows you to delegate a [Player] extension property to have quick simple and easy access to a varbit + * + * @property [varbitId] The id of the varbit you are writing to and reading from + * + * @author Curtis Woodard + */ +abstract class VarbitDelegate(val varbitId: Int) { + + private var _varbitDef: VarbitDef? = null + + /** @property [varbitDef] The [VarbitDef] used in [getVarbit] and [setVarbit] */ + val varbitDef: VarbitDef + get() = _varbitDef ?: throw Exception("Varbit Def $varbitId not found") + + /** + * Translates your input to [Int] to write to the varbit + * + * @param [inValue] The value you are translating to [Int] + * + * @return [Int] + */ + abstract fun translateIn(inValue: T): Int + + /** + * Translates the varbit [Int] to the output type [T] + * + * @param [outValue] The value you are translating to [T] + * + * @return [T] + */ + abstract fun translateOut(outValue: Int): T + + operator fun getValue(player: Player, property: KProperty<*>): T { + ensureVarbitDef(player) + return translateOut(getVarbit(player)) + } + + operator fun setValue(player: Player, property: KProperty<*>, value: T) { + ensureVarbitDef(player) + setVarbit(player, translateIn(value)) + } + + private fun getVarbit(player: Player): Int { + ensureVarbitDef(player) + return player.varps.getBit(varbitDef.varp, varbitDef.startBit, varbitDef.endBit) + } + + private fun setVarbit(player: Player, value: Int) { + ensureVarbitDef(player) + player.varps.setBit(varbitDef.varp, varbitDef.startBit, varbitDef.endBit, value) + } + + /** + * Ensures that [varbitDef] is set + */ + private fun ensureVarbitDef(player: Player) { + if (_varbitDef == null) { + _varbitDef = player.world.definitions.get(VarbitDef::class.java, varbitId) + } + } +} diff --git a/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/BoolVarbit.kt b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/BoolVarbit.kt new file mode 100644 index 0000000000..6d705d8255 --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/BoolVarbit.kt @@ -0,0 +1,8 @@ +package gg.rsmod.game.model.varbit.delegate.impl + +import gg.rsmod.game.model.varbit.delegate.VarbitDelegate + +class BoolVarbit(varbitId: Int): VarbitDelegate(varbitId) { + override fun translateIn(inValue: Boolean): Int = if (inValue) 1 else 0 + override fun translateOut(outValue: Int): Boolean = outValue != 0 +} diff --git a/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/IntVarbit.kt b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/IntVarbit.kt new file mode 100644 index 0000000000..109b19ae07 --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/varbit/delegate/impl/IntVarbit.kt @@ -0,0 +1,8 @@ +package gg.rsmod.game.model.varbit.delegate.impl + +import gg.rsmod.game.model.varbit.delegate.VarbitDelegate + +class IntVarbit(varbitId: Int): VarbitDelegate(varbitId) { + override fun translateIn(inValue: Int): Int = inValue + override fun translateOut(outValue: Int): Int = outValue +} diff --git a/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/VarpDelegate.kt b/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/VarpDelegate.kt new file mode 100644 index 0000000000..5641c773e5 --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/VarpDelegate.kt @@ -0,0 +1,38 @@ +package gg.rsmod.game.model.varp.delegate + +import gg.rsmod.game.model.entity.Player +import kotlin.reflect.KProperty + +/** + * Allows you to delegate a [Player] extension property to have quick simple and easy access to a varp + * + * @property [varpId] The id of the varp you are writing to and reading from + * + * @author Curtis Woodard + */ +abstract class VarpDelegate(val varpId: Int) { + + /** + * Translates your input to [Int] to write to the varp + * + * @param [inValue] The value you are translating to [Int] + */ + abstract fun translateIn(inValue: T): Int + + /** + * Translates the varp [Int] to output type [T] + * + * @param [outValue] The value getting translated to [Int] + */ + abstract fun translateOut(outValue: Int): T + + operator fun getValue(player: Player, property: KProperty<*>): T = translateOut(getVarp(player, varpId)) + + operator fun setValue(player: Player, property: KProperty<*>, value: T) = setVarp(player, varpId, translateIn(value)) + + companion object { + fun getVarp(player: Player, varpId: Int): Int = player.varps.getState(varpId) + + fun setVarp(player: Player, varpId: Int, value: Int) = player.varps.setState(varpId, value) + } +} diff --git a/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/impl/IntVarp.kt b/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/impl/IntVarp.kt new file mode 100644 index 0000000000..0bdad399c4 --- /dev/null +++ b/game/src/main/kotlin/gg/rsmod/game/model/varp/delegate/impl/IntVarp.kt @@ -0,0 +1,8 @@ +package gg.rsmod.game.model.varp.delegate.impl + +import gg.rsmod.game.model.varp.delegate.VarpDelegate + +class IntVarp(varpId: Int): VarpDelegate(varpId) { + override fun translateIn(inValue: Int): Int = inValue + override fun translateOut(outValue: Int): Int = outValue +}