diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index b8068c354..4f67fa783 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -160,12 +160,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever player has Exopack */ - var hasExoPack by publicSynchronizer.bool() + var hasExoPack by publicSynchronizer.bool().property /** * Whenever to render Exopack on player */ - var displayExoPack by publicSynchronizer.bool(true) + var displayExoPack by publicSynchronizer.bool(true).property /** * Tick event schedulers @@ -231,7 +231,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial access.write(value) _exoPackMenu = null } - }) + }).property private var _exoPackMenu: ExoPackInventoryMenu? = null set(value) { @@ -301,7 +301,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever player should become an Android once transformation conditions are met (e.g. player dies or sleeps in bed) */ - var willBecomeAndroid by publicSynchronizer.bool() + var willBecomeAndroid by publicSynchronizer.bool().property /** * Whenever player is an Android @@ -315,7 +315,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * * Android-immune (de)buffs are specified in `data/overdrive_that_matters/tags/mob_effect/android_immune_effects.json` */ - var isAndroid by publicSynchronizer.bool() + var isAndroid by publicSynchronizer.bool().property /** * [IMatteryEnergyStorage] instance, representing Android' battery charge diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt index 055351d11..f161c5fe4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -1,30 +1,27 @@ +@file:Suppress("DeprecatedCallableAddReplaceWith") + package ru.dbotthepony.mc.otm.network +import it.unimi.dsi.fastutil.booleans.BooleanConsumer +import it.unimi.dsi.fastutil.floats.FloatConsumer import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet +import mekanism.api.functions.FloatSupplier import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.collect.ProxiedMap import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec -import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec import ru.dbotthepony.mc.otm.core.util.ByteValueCodec -import ru.dbotthepony.mc.otm.core.util.DoubleValueCodec -import ru.dbotthepony.mc.otm.core.util.EnumValueCodec -import ru.dbotthepony.mc.otm.core.util.FloatValueCodec -import ru.dbotthepony.mc.otm.core.util.IStreamCodec import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec -import ru.dbotthepony.mc.otm.core.util.IntValueCodec +import ru.dbotthepony.mc.otm.core.util.EnumValueCodec +import ru.dbotthepony.mc.otm.core.util.IStreamCodec import ru.dbotthepony.mc.otm.core.util.ItemStackValueCodec -import ru.dbotthepony.mc.otm.core.util.LongValueCodec import ru.dbotthepony.mc.otm.core.util.ShortValueCodec import ru.dbotthepony.mc.otm.core.util.UUIDValueCodec -import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec -import ru.dbotthepony.mc.otm.core.util.VarLongValueCodec import ru.dbotthepony.mc.otm.core.util.readVarIntLE import ru.dbotthepony.mc.otm.core.util.writeVarIntLE import ru.dbotthepony.mc.otm.secondTime @@ -34,8 +31,14 @@ import java.io.InputStream import java.lang.ref.WeakReference import java.math.BigDecimal import java.util.* +import java.util.function.BooleanSupplier +import java.util.function.DoubleConsumer +import java.util.function.DoubleSupplier +import java.util.function.IntConsumer +import java.util.function.IntSupplier +import java.util.function.LongConsumer +import java.util.function.LongSupplier import java.util.function.Supplier -import kotlin.collections.ArrayList import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty @@ -46,14 +49,139 @@ interface FieldAccess { fun write(value: V) } +interface FloatFieldAccess : FieldAccess { + override fun write(value: Float) + @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readFloat()")) + override fun read() = readFloat() + fun readFloat(): Float +} + +interface DoubleFieldAccess : FieldAccess { + override fun write(value: Double) + @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readDouble()")) + override fun read() = readDouble() + fun readDouble(): Double +} + +interface IntFieldAccess : FieldAccess { + override fun write(value: Int) + @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readInt()")) + override fun read() = readInt() + fun readInt(): Int +} + +interface LongFieldAccess : FieldAccess { + override fun write(value: Long) + @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readLong()")) + override fun read() = readLong() + fun readLong(): Long +} + +interface BooleanFieldAccess : FieldAccess { + override fun write(value: Boolean) + @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readBoolean()")) + override fun read() = readBoolean() + fun readBoolean(): Boolean +} + fun interface FieldGetter { fun invoke(field: FieldAccess): V } +fun interface FloatFieldGetter : FieldGetter { + fun invoke(field: FloatFieldAccess): Float + + @Deprecated("Use type specific invoke") + override fun invoke(field: FieldAccess): Float { + return invoke(field as FloatFieldAccess) + } +} + +fun interface DoubleFieldGetter : FieldGetter { + fun invoke(field: DoubleFieldAccess): Double + + @Deprecated("Use type specific invoke") + override fun invoke(field: FieldAccess): Double { + return invoke(field as DoubleFieldAccess) + } +} + +fun interface IntFieldGetter : FieldGetter { + fun invoke(field: IntFieldAccess): Int + + @Deprecated("Use type specific invoke") + override fun invoke(field: FieldAccess): Int { + return invoke(field as IntFieldAccess) + } +} + +fun interface LongFieldGetter : FieldGetter { + fun invoke(field: LongFieldAccess): Long + + @Deprecated("Use type specific invoke") + override fun invoke(field: FieldAccess): Long { + return invoke(field as LongFieldAccess) + } +} + +fun interface BooleanFieldGetter : FieldGetter { + fun invoke(field: BooleanFieldAccess): Boolean + + @Deprecated("Use type specific invoke") + override fun invoke(field: FieldAccess): Boolean { + return invoke(field as BooleanFieldAccess) + } +} + fun interface FieldSetter { fun invoke(value: V, access: FieldAccess, setByRemote: Boolean) } +fun interface FloatFieldSetter : FieldSetter { + fun invoke(value: Float, access: FloatFieldAccess, setByRemote: Boolean) + + @Deprecated("Use type specific invoke") + override fun invoke(value: Float, access: FieldAccess, setByRemote: Boolean) { + invoke(value, access as FloatFieldAccess, setByRemote) + } +} + +fun interface DoubleFieldSetter : FieldSetter { + fun invoke(value: Double, access: DoubleFieldAccess, setByRemote: Boolean) + + @Deprecated("Use type specific invoke") + override fun invoke(value: Double, access: FieldAccess, setByRemote: Boolean) { + invoke(value, access as DoubleFieldAccess, setByRemote) + } +} + +fun interface IntFieldSetter : FieldSetter { + fun invoke(value: Int, access: IntFieldAccess, setByRemote: Boolean) + + @Deprecated("Use type specific invoke") + override fun invoke(value: Int, access: FieldAccess, setByRemote: Boolean) { + invoke(value, access as IntFieldAccess, setByRemote) + } +} + +fun interface LongFieldSetter : FieldSetter { + fun invoke(value: Long, access: LongFieldAccess, setByRemote: Boolean) + + @Deprecated("Use type specific invoke") + override fun invoke(value: Long, access: FieldAccess, setByRemote: Boolean) { + invoke(value, access as LongFieldAccess, setByRemote) + } +} + +fun interface BooleanFieldSetter : FieldSetter { + fun invoke(value: Boolean, access: BooleanFieldAccess, setByRemote: Boolean) + + @Deprecated("Use type specific invoke") + override fun invoke(value: Boolean, access: FieldAccess, setByRemote: Boolean) { + invoke(value, access as BooleanFieldAccess, setByRemote) + } +} + sealed interface IField : ReadOnlyProperty, Supplier, () -> V { fun observe(): Boolean fun markDirty() @@ -79,6 +207,111 @@ sealed interface IField : ReadOnlyProperty, Supplier, () -> V { } } +interface IFloatProperty { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Float +} + +sealed interface IFloatField : IField, FloatSupplier { + val float: Float + val property: IFloatProperty + + override val value: Float + get() = float + + override fun getAsFloat(): Float { + return float + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Float { + return float + } +} + +interface IDoubleProperty { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Double +} + +sealed interface IDoubleField : IField, DoubleSupplier { + val double: Double + val property: IDoubleProperty + + override val value: Double + get() = double + + override fun getAsDouble(): Double { + return double + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + return double + } +} + +interface IIntProperty { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Int +} + +sealed interface IIntField : IField, IntSupplier { + val int: Int + val property: IIntProperty + + override val value: Int + get() = int + + override fun getAsInt(): Int { + return int + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return int + } +} + +interface ILongProperty { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Long +} + +sealed interface ILongField : IField, LongSupplier { + val long: Long + val property: ILongProperty + + override val value: Long + get() = long + + override fun getAsLong(): Long { + return long + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Long { + return long + } +} + +interface IBooleanProperty { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean +} + +sealed interface IBooleanField : IField, BooleanSupplier { + val boolean: Boolean + val property: IBooleanProperty + + override val value: Boolean + get() = boolean + + override fun getAsBoolean(): Boolean { + return boolean + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { + return boolean + } +} + sealed interface IMutableField : IField, GetterSetter { override fun getValue(thisRef: Any?, property: KProperty<*>): V { return this.value @@ -95,6 +328,146 @@ sealed interface IMutableField : IField, GetterSetter { } } +interface IMutableFloatProperty : IFloatProperty { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) +} + +sealed interface IMutableFloatField : IMutableField, FloatConsumer { + var float: Float + val property: IMutableFloatProperty + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.float")) + override var value: Float + get() = float + set(value) { float = value } + + override fun accept(t: Float) { + float = t + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Float { + return float + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) { + float = value + } +} + +interface IMutableDoubleProperty : IDoubleProperty { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) +} + +sealed interface IMutableDoubleField : IMutableField, DoubleConsumer { + var double: Double + val property: IMutableDoubleProperty + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.double")) + override var value: Double + get() = double + set(value) { double = value } + + override fun accept(t: Double) { + double = t + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + return double + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { + double = value + } +} + +interface IMutableIntProperty : IIntProperty { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) +} + +sealed interface IMutableIntField : IMutableField, IntConsumer { + var int: Int + val property: IMutableIntProperty + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.int")) + override var value: Int + get() = int + set(value) { int = value } + + override fun accept(t: Int) { + int = t + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return int + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { + int = value + } +} + +interface IMutableLongProperty : ILongProperty { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) +} + +sealed interface IMutableLongField : IMutableField, LongConsumer { + var long: Long + val property: IMutableLongProperty + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.long")) + override var value: Long + get() = long + set(value) { long = value } + + override fun accept(t: Long) { + long = t + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Long { + return long + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { + long = value + } +} + +interface IMutableBooleanProperty : IBooleanProperty { + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) +} + +sealed interface IMutableBooleanField : IMutableField, BooleanConsumer { + var boolean: Boolean + val property: IMutableBooleanProperty + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.boolean")) + override var value: Boolean + get() = boolean + set(value) { boolean = value } + + override fun accept(t: Boolean) { + boolean = t + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { + return boolean + } + + @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { + boolean = value + } +} + data class MapChangeset( val action: MapAction, val key: K?, @@ -165,45 +538,45 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } fun byte(getter: () -> Byte) = ComputedField(getter, ByteValueCodec) - fun bool(getter: () -> Boolean) = ComputedField(getter, BooleanValueCodec) + fun bool(getter: BooleanSupplier) = ComputedBooleanField(getter) fun short(getter: () -> Short) = ComputedField(getter, ShortValueCodec) - fun long(getter: () -> Long) = ComputedField(getter, VarLongValueCodec) - fun fixedLong(getter: () -> Long) = ComputedField(getter, LongValueCodec) - fun float(getter: () -> Float) = ComputedField(getter, FloatValueCodec) - fun double(getter: () -> Double) = ComputedField(getter, DoubleValueCodec) + fun long(getter: LongSupplier) = ComputedLongField(getter) + fun fixedLong(getter: LongSupplier) = ComputedLongField(getter) + fun float(getter: FloatSupplier) = ComputedFloatField(getter) + fun double(getter: DoubleSupplier) = ComputedDoubleField(getter) fun uuid(getter: () -> UUID) = ComputedField(getter, UUIDValueCodec) - fun int(getter: () -> Int) = ComputedField(getter, VarIntValueCodec) - fun fixedInt(getter: () -> Int) = ComputedField(getter, IntValueCodec) + fun int(getter: IntSupplier) = ComputedIntField(getter) + fun fixedInt(getter: IntSupplier) = ComputedIntField(getter) fun fraction(getter: () -> Decimal) = ComputedField(getter, DecimalValueCodec) fun bigDecimal(getter: () -> BigDecimal) = ComputedField(getter, BigDecimalValueCodec) fun item(getter: () -> ItemStack) = ComputedField(getter, ItemStackValueCodec) fun string(getter: () -> String) = ComputedField(getter, BinaryStringCodec) fun byte(getter: KProperty0) = ComputedField(getter, ByteValueCodec) - fun bool(getter: KProperty0) = ComputedField(getter, BooleanValueCodec) + fun bool(getter: KProperty0) = ComputedBooleanField(getter::get) fun short(getter: KProperty0) = ComputedField(getter, ShortValueCodec) - fun long(getter: KProperty0) = ComputedField(getter, VarLongValueCodec) - fun fixedLong(getter: KProperty0) = ComputedField(getter, LongValueCodec) - fun float(getter: KProperty0) = ComputedField(getter, FloatValueCodec) - fun double(getter: KProperty0) = ComputedField(getter, DoubleValueCodec) + fun long(getter: KProperty0) = ComputedLongField(getter::get) + fun fixedLong(getter: KProperty0) = ComputedLongField(getter::get) + fun float(getter: KProperty0) = ComputedFloatField(getter::get) + fun double(getter: KProperty0) = ComputedDoubleField(getter::get) fun uuid(getter: KProperty0) = ComputedField(getter, UUIDValueCodec) - fun int(getter: KProperty0) = ComputedField(getter, VarIntValueCodec) - fun fixedInt(getter: KProperty0) = ComputedField(getter, IntValueCodec) + fun int(getter: KProperty0) = ComputedIntField(getter::get) + fun fixedInt(getter: KProperty0) = ComputedIntField(getter::get) fun fraction(getter: KProperty0) = ComputedField(getter, DecimalValueCodec) fun bigDecimal(getter: KProperty0) = ComputedField(getter, BigDecimalValueCodec) fun item(getter: KProperty0) = ComputedField(getter, ItemStackValueCodec) fun string(getter: KProperty0) = ComputedField(getter, BinaryStringCodec) fun byte(getter: Supplier) = ComputedField(getter::get, ByteValueCodec) - fun bool(getter: Supplier) = ComputedField(getter::get, BooleanValueCodec) + fun bool(getter: Supplier) = ComputedBooleanField(getter::get) fun short(getter: Supplier) = ComputedField(getter::get, ShortValueCodec) - fun long(getter: Supplier) = ComputedField(getter::get, VarLongValueCodec) - fun fixedLong(getter: Supplier) = ComputedField(getter::get, LongValueCodec) - fun float(getter: Supplier) = ComputedField(getter::get, FloatValueCodec) - fun double(getter: Supplier) = ComputedField(getter::get, DoubleValueCodec) + fun long(getter: Supplier) = ComputedLongField(getter::get) + fun fixedLong(getter: Supplier) = ComputedLongField(getter::get) + fun float(getter: Supplier) = ComputedFloatField(getter::get) + fun double(getter: Supplier) = ComputedDoubleField(getter::get) fun uuid(getter: Supplier) = ComputedField(getter::get, UUIDValueCodec) - fun int(getter: Supplier) = ComputedField(getter::get, VarIntValueCodec) - fun fixedInt(getter: Supplier) = ComputedField(getter::get, IntValueCodec) + fun int(getter: Supplier) = ComputedIntField(getter::get) + fun fixedInt(getter: Supplier) = ComputedIntField(getter::get) fun fraction(getter: Supplier) = ComputedField(getter::get, DecimalValueCodec) fun bigDecimal(getter: Supplier) = ComputedField(getter::get, BigDecimalValueCodec) fun item(getter: Supplier) = ComputedField(getter::get, ItemStackValueCodec) @@ -223,7 +596,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Byte = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, ByteValueCodec, getter, setter) } @@ -231,11 +603,10 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa @JvmOverloads fun bool( value: Boolean = false, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, BooleanValueCodec, getter, setter) + getter: BooleanFieldGetter? = null, + setter: BooleanFieldSetter? = null, + ): BooleanField { + return BooleanField(value, getter, setter) } @JvmOverloads @@ -243,7 +614,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Short = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, ShortValueCodec, getter, setter) } @@ -251,41 +621,37 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa @JvmOverloads fun long( value: Long = 0L, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, VarLongValueCodec, getter, setter) + getter: LongFieldGetter? = null, + setter: LongFieldSetter? = null, + ): LongField { + return LongField(value, getter, setter) } @JvmOverloads fun fixedLong( value: Long = 0L, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, LongValueCodec, getter, setter) + getter: LongFieldGetter? = null, + setter: LongFieldSetter? = null, + ): LongField { + return LongField(value, getter, setter) } @JvmOverloads fun float( value: Float = 0f, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, FloatValueCodec, getter, setter) + getter: FloatFieldGetter? = null, + setter: FloatFieldSetter? = null, + ): FloatField { + return FloatField(value, getter, setter) } @JvmOverloads fun double( value: Double = 0.0, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, DoubleValueCodec, getter, setter) + getter: DoubleFieldGetter? = null, + setter: DoubleFieldSetter? = null, + ): DoubleField { + return DoubleField(value, getter, setter) } @JvmOverloads @@ -293,7 +659,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: UUID = UUID(0L, 0L), getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, UUIDValueCodec, getter, setter) } @@ -301,11 +666,10 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa @JvmOverloads fun int( value: Int = 0, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, VarIntValueCodec, getter, setter) + getter: IntFieldGetter? = null, + setter: IntFieldSetter? = null, + ): IntField { + return IntField(value, getter, setter) } @JvmOverloads @@ -313,7 +677,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: String = "", getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, BinaryStringCodec, getter, setter) } @@ -321,11 +684,10 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa @JvmOverloads fun fixedInt( value: Int = 0, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - - ): Field { - return Field(value, IntValueCodec, getter, setter) + getter: IntFieldGetter? = null, + setter: IntFieldSetter? = null, + ): IntField { + return IntField(value, getter, setter) } @JvmOverloads @@ -333,7 +695,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Decimal = Decimal.ZERO, getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, DecimalValueCodec, getter, setter) } @@ -343,7 +704,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: BigDecimal = BigDecimal.ZERO, getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, BigDecimalValueCodec, getter, setter) } @@ -354,7 +714,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: T = type.enumConstants[0], getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, EnumValueCodec(type), getter, setter) } @@ -364,7 +723,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: T, getter: FieldGetter? = null, setter: FieldSetter? = null, - ): Field { return Field(value, EnumValueCodec(value::class.java), getter, setter) } @@ -385,23 +743,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa return ObservedField(delegate, ItemStackValueCodec) } - @JvmOverloads - fun map( - keyCodec: IStreamCodec, - valueCodec: IStreamCodec, - callback: ((changes: Collection>) -> Unit)? = null, - backingMap: MutableMap = HashMap(), - observingBackingMap: MutableMap? = null, - ): Map { - return Map( - keyCodec = keyCodec, - valueCodec = valueCodec, - callback = callback, - backingMap = backingMap, - observingBackingMap = observingBackingMap, - ) - } - private var endpointsMaxCapacity = 1 private val endpoints = ArrayList>(1) val defaultEndpoint = Endpoint() @@ -705,6 +1046,421 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } } + /** + * Type specific field, storing primitive [Float] directly + */ + inner class FloatField(private var field: Float, private val getter: FloatFieldGetter? = null, private val setter: FloatFieldSetter? = null) : AbstractField(), IMutableFloatField { + private var isDirty = false + + override val property = object : IMutableFloatProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Float { + return this@FloatField.float + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) { + this@FloatField.float = value + } + } + + private val access = object : FloatFieldAccess { + override fun readFloat(): Float { + return this@FloatField.field + } + + override fun write(value: Float) { + if (!isDirty && value != this@FloatField.field) { + notifyEndpoints(this@FloatField) + isDirty = true + } + + this@FloatField.field = value + } + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + return isDirty + } + + override var float: Float + get() { + return getter?.invoke(access) ?: this.field + } + set(value) { + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, false) + return + } + + if (value != this.field) { + if (!isDirty) { + notifyEndpoints(this) + isDirty = true + } + + this.field = value + } + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeFloat(this.field) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val value = stream.readFloat() + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, true) + } else { + this.field = value + } + } + } + + /** + * Type specific field, storing primitive [Double] directly + */ + inner class DoubleField(private var field: Double, private val getter: DoubleFieldGetter? = null, private val setter: DoubleFieldSetter? = null) : AbstractField(), IMutableDoubleField { + private var isDirty = false + + override val property = object : IMutableDoubleProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + return this@DoubleField.double + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { + this@DoubleField.double = value + } + } + + private val access = object : DoubleFieldAccess { + override fun readDouble(): Double { + return this@DoubleField.field + } + + override fun write(value: Double) { + if (!isDirty && value != this@DoubleField.field) { + notifyEndpoints(this@DoubleField) + isDirty = true + } + + this@DoubleField.field = value + } + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + return isDirty + } + + override var double: Double + get() { + return getter?.invoke(access) ?: this.field + } + set(value) { + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, false) + return + } + + if (value != this.field) { + if (!isDirty) { + notifyEndpoints(this) + isDirty = true + } + + this.field = value + } + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeDouble(this.field) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val value = stream.readDouble() + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, true) + } else { + this.field = value + } + } + } + + /** + * Type specific field, storing primitive [Int] directly + */ + inner class IntField(private var field: Int, private val getter: IntFieldGetter? = null, private val setter: IntFieldSetter? = null) : AbstractField(), IMutableIntField { + private var isDirty = false + + override val property = object : IMutableIntProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return this@IntField.int + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { + this@IntField.int = value + } + } + + private val access = object : IntFieldAccess { + override fun readInt(): Int { + return this@IntField.field + } + + override fun write(value: Int) { + if (!isDirty && value != this@IntField.field) { + notifyEndpoints(this@IntField) + isDirty = true + } + + this@IntField.field = value + } + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + return isDirty + } + + override var int: Int + get() { + return getter?.invoke(access) ?: this.field + } + set(value) { + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, false) + return + } + + if (value != this.field) { + if (!isDirty) { + notifyEndpoints(this) + isDirty = true + } + + this.field = value + } + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeInt(this.field) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val value = stream.readInt() + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, true) + } else { + this.field = value + } + } + } + + /** + * Type specific field, storing primitive [Long] directly + */ + inner class LongField(private var field: Long, private val getter: LongFieldGetter? = null, private val setter: LongFieldSetter? = null) : AbstractField(), IMutableLongField { + private var isDirty = false + + override val property = object : IMutableLongProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Long { + return this@LongField.long + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { + this@LongField.long = value + } + } + + private val access = object : LongFieldAccess { + override fun readLong(): Long { + return this@LongField.field + } + + override fun write(value: Long) { + if (!isDirty && value != this@LongField.field) { + notifyEndpoints(this@LongField) + isDirty = true + } + + this@LongField.field = value + } + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + return isDirty + } + + override var long: Long + get() { + return getter?.invoke(access) ?: this.field + } + set(value) { + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, false) + return + } + + if (value != this.field) { + if (!isDirty) { + notifyEndpoints(this) + isDirty = true + } + + this.field = value + } + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeLong(this.field) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val value = stream.readLong() + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, true) + } else { + this.field = value + } + } + } + + /** + * Type specific field, storing primitive [Boolean] directly + */ + inner class BooleanField(private var field: Boolean, private val getter: BooleanFieldGetter? = null, private val setter: BooleanFieldSetter? = null) : AbstractField(), IMutableBooleanField { + private var isDirty = false + + override val property = object : IMutableBooleanProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { + return this@BooleanField.boolean + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { + this@BooleanField.boolean = value + } + } + + private val access = object : BooleanFieldAccess { + override fun readBoolean(): Boolean { + return this@BooleanField.field + } + + override fun write(value: Boolean) { + if (!isDirty && value != this@BooleanField.field) { + notifyEndpoints(this@BooleanField) + isDirty = true + } + + this@BooleanField.field = value + } + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + return isDirty + } + + override var boolean: Boolean + get() { + return getter?.invoke(access) ?: this.field + } + set(value) { + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, false) + return + } + + if (value != this.field) { + if (!isDirty) { + notifyEndpoints(this) + isDirty = true + } + + this.field = value + } + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeBoolean(this.field) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val value = stream.readBoolean() + val setter = this.setter + + if (setter != null) { + setter.invoke(value, access, true) + } else { + this.field = value + } + } + } + /** * Networked value with backing getter which is constantly polled */ @@ -758,6 +1514,341 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } } + /** + * Networked value with backing getter which is constantly polled + * + * This class has concrete implementation for [Float] primitive + */ + inner class ComputedFloatField(private val getter: FloatSupplier, private val observer: FloatConsumer = FloatConsumer {}) : AbstractField(), IFloatField { + private var remote: Float = 0f + private var isRemoteSet = false + private var clientValue: Float = 0f + private var isClientValue = false + private var isDirty = false + + override val property = object : IFloatProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Float { + return float + } + } + + init { + observers.add(this) + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + + val value = getter.asFloat + + if (!isDirty && (!isRemoteSet || remote != value)) { + notifyEndpoints(this) + isDirty = true + isRemoteSet = true + remote = value + } + + return isDirty + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override val float: Float + get() { + if (isClientValue) { + return clientValue + } else { + return getter.asFloat + } + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeFloat(getter.asFloat) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val newValue = stream.readFloat() + clientValue = newValue + isClientValue = true + observer.accept(newValue) + } + } + + /** + * Networked value with backing getter which is constantly polled + * + * This class has concrete implementation for [Double] primitive + */ + inner class ComputedDoubleField(private val getter: DoubleSupplier, private val observer: DoubleConsumer = DoubleConsumer {}) : AbstractField(), IDoubleField { + private var remote: Double = 0.0 + private var isRemoteSet = false + private var clientValue: Double = 0.0 + private var isClientValue = false + private var isDirty = false + + override val property = object : IDoubleProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Double { + return double + } + } + + init { + observers.add(this) + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + + val value = getter.asDouble + + if (!isDirty && (!isRemoteSet || remote != value)) { + notifyEndpoints(this) + isDirty = true + isRemoteSet = true + remote = value + } + + return isDirty + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override val double: Double + get() { + if (isClientValue) { + return clientValue + } else { + return getter.asDouble + } + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeDouble(getter.asDouble) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val newValue = stream.readDouble() + clientValue = newValue + isClientValue = true + observer.accept(newValue) + } + } + + /** + * Networked value with backing getter which is constantly polled + * + * This class has concrete implementation for [Int] primitive + */ + inner class ComputedIntField(private val getter: IntSupplier, private val observer: IntConsumer = IntConsumer {}) : AbstractField(), IIntField { + private var remote: Int = 0 + private var isRemoteSet = false + private var clientValue: Int = 0 + private var isClientValue = false + private var isDirty = false + + override val property = object : IIntProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return int + } + } + + init { + observers.add(this) + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + + val value = getter.asInt + + if (!isDirty && (!isRemoteSet || remote != value)) { + notifyEndpoints(this) + isDirty = true + isRemoteSet = true + remote = value + } + + return isDirty + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override val int: Int + get() { + if (isClientValue) { + return clientValue + } else { + return getter.asInt + } + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeInt(getter.asInt) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val newValue = stream.readInt() + clientValue = newValue + isClientValue = true + observer.accept(newValue) + } + } + + /** + * Networked value with backing getter which is constantly polled + * + * This class has concrete implementation for [Long] primitive + */ + inner class ComputedLongField(private val getter: LongSupplier, private val observer: LongConsumer = LongConsumer {}) : AbstractField(), ILongField { + private var remote: Long = 0L + private var isRemoteSet = false + private var clientValue: Long = 0L + private var isClientValue = false + private var isDirty = false + + override val property = object : ILongProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Long { + return long + } + } + + init { + observers.add(this) + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + + val value = getter.asLong + + if (!isDirty && (!isRemoteSet || remote != value)) { + notifyEndpoints(this) + isDirty = true + isRemoteSet = true + remote = value + } + + return isDirty + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override val long: Long + get() { + if (isClientValue) { + return clientValue + } else { + return getter.asLong + } + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeLong(getter.asLong) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val newValue = stream.readLong() + clientValue = newValue + isClientValue = true + observer.accept(newValue) + } + } + + /** + * Networked value with backing getter which is constantly polled + * + * This class has concrete implementation for [Boolean] primitive + */ + inner class ComputedBooleanField(private val getter: BooleanSupplier, private val observer: BooleanConsumer = BooleanConsumer {}) : AbstractField(), IBooleanField { + private var remote: Boolean = false + private var isRemoteSet = false + private var clientValue: Boolean = false + private var isClientValue = false + private var isDirty = false + + override val property = object : IBooleanProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { + return boolean + } + } + + init { + observers.add(this) + } + + override fun observe(): Boolean { + check(!isRemoved) { "Field was removed" } + + val value = getter.asBoolean + + if (!isDirty && (!isRemoteSet || remote != value)) { + notifyEndpoints(this) + isDirty = true + isRemoteSet = true + remote = value + } + + return isDirty + } + + override fun markDirty() { + check(!isRemoved) { "Field was removed" } + notifyEndpoints(this) + isDirty = true + } + + override val boolean: Boolean + get() { + if (isClientValue) { + return clientValue + } else { + return getter.asBoolean + } + } + + override fun write(stream: DataOutputStream, endpoint: Endpoint) { + check(!isRemoved) { "Field was removed" } + stream.writeBoolean(getter.asBoolean) + isDirty = false + } + + override fun read(stream: DataInputStream) { + check(!isRemoved) { "Field was removed" } + val newValue = stream.readBoolean() + clientValue = newValue + isClientValue = true + observer.accept(newValue) + } + } + /** * Networked variable with backing field holding mutable value, which is constantly observed for changes */