diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt index 8b3a74510..a93faed9a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt @@ -62,11 +62,8 @@ class RedstoneControl(private val valueChanges: (new: Boolean, old: Boolean) -> class SynchronizedRedstoneControl( synchronizer: FieldSynchronizer, - fieldNamePrefix: String?, private val valueChanges: (new: Boolean, old: Boolean) -> Unit, ) : AbstractRedstoneControl() { - constructor(synchronizer: FieldSynchronizer, valueChanges: (new: Boolean, old: Boolean) -> Unit) : this(synchronizer, "", valueChanges) - override var redstoneSetting: RedstoneSetting by synchronizer.enum(RedstoneSetting.LOW, setter = { value, access, setByRemote -> if (access.read() == value) return@enum if (setByRemote) { @@ -77,7 +74,7 @@ class SynchronizedRedstoneControl( val state = isBlockedByRedstone valueChanges.invoke(state, old) } - }, name = if (fieldNamePrefix != null) "${fieldNamePrefix}_redstoneSetting" else null) + }) override var redstoneSignal: Int by synchronizer.int(0, setter = { value, access, setByRemote -> if (access.read() == value) return@int @@ -89,5 +86,5 @@ class SynchronizedRedstoneControl( val state = isBlockedByRedstone valueChanges.invoke(state, old) } - }, name = if (fieldNamePrefix != null) "${fieldNamePrefix}_redstoneSignal" else null) + }) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt index dd121d04a..e6eecaf09 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt @@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.registry.MBlocks class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.HOLO_SIGN, blockPos, blockState), MenuProvider, IRedstoneControlled { override val redstoneControl = SynchronizedRedstoneControl(synchronizer) { _, _ -> setChanged() } - var signText by synchronizer.string("", name = "text", setter = { value, access, remote -> + var signText by synchronizer.string("", setter = { value, access, remote -> setChanged() access.write(value) }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt index 3777bb4de..986da9232 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt @@ -131,7 +131,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) }.also(::addDroppableContainer) val capacitorStatus = immutableList(BatteryBankBlockEntity.CAPACITY) { - synchronizer.bool(false, name = "capacitor$it") + synchronizer.bool(false) } init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt index f8753ac68..a0f1de59c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt @@ -39,7 +39,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte }.also(::addDroppableContainer) val batteryStatus = immutableList(CAPACITY) { - synchronizer.bool(false, name = "battery$it") + synchronizer.bool(false) } private val itemHandler = container.handler( 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 10fb5fb41..60f2b8c83 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -121,12 +121,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever player has Exopack */ - var hasExoPack by publicSynchronizer.bool(name = "hasExoPack") + var hasExoPack by publicSynchronizer.bool() /** * Whenever to render Exopack on player */ - var displayExoPack by publicSynchronizer.bool(true, name = "displayExoPack") + var displayExoPack by publicSynchronizer.bool(true) private val exoPackSlotModifierMap: MutableMap by synchronizer.Map( keyCodec = UUIDValueCodec, @@ -135,7 +135,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial callback = { this.exoPackSlotModifier.recompute() }, - name = "exoPackSlotModifierMap" ) /** @@ -167,7 +166,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial _exoPackMenu = null exoPackContainer = PlayerMatteryContainer(value) } - }, name = "exoPackSlotCount") + }) /** * Exopack container, which actually store items inside Exopack @@ -202,7 +201,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial access.write(value) _exoPackMenu = null } - }, name = "isExoPackCraftingUpgraded") + }) private var _exoPackMenu: ExoPackInventoryMenu? = null set(value) { @@ -276,7 +275,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(name = "willBecomeAndroid") + var willBecomeAndroid by publicSynchronizer.bool() /** * Whenever player is an Android @@ -290,7 +289,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(name = "isAndroid") + var isAndroid by publicSynchronizer.bool() /** * [IMatteryEnergyStorage] instance, representing Android' battery charge diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt index 1f1bc6445..82f17061f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt @@ -27,8 +27,8 @@ class AndroidPowerSource( override val energyFlow: FlowDirection get() = FlowDirection.INPUT - private var battery by synchronizer.fraction(initialCharge, name = "android battery") - private var maxBattery by synchronizer.fraction(maxCharge, name = "android max battery") + private var battery by synchronizer.fraction(initialCharge) + private var maxBattery by synchronizer.fraction(maxCharge) var item by synchronizer.item(setter = setter@{ value, access, setByRemote -> access.write(value) @@ -36,7 +36,7 @@ class AndroidPowerSource( if (ply is ServerPlayer) { AndroidBatteryTrigger.trigger(ply, value) } - }, name = "android battery item") + }) override fun serializeNBT(): CompoundTag { return CompoundTag().also { 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 50aa0ff4e..bf67dfcda 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -1,14 +1,9 @@ package ru.dbotthepony.mc.otm.network -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap -import it.unimi.dsi.fastutil.io.FastByteArrayInputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream -import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import net.minecraft.nbt.NbtAccounter import net.minecraft.world.item.ItemStack import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.core.* @@ -40,9 +35,6 @@ import java.lang.ref.WeakReference import java.math.BigDecimal import java.util.* import java.util.function.Supplier -import kotlin.ConcurrentModificationException -import kotlin.collections.ArrayList -import kotlin.collections.HashMap import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty @@ -66,13 +58,8 @@ sealed interface IField : ReadOnlyProperty, Supplier, () -> V { fun markDirty() fun markDirty(endpoint: FieldSynchronizer.Endpoint) val value: V - val name: String fun write(stream: DataOutputStream, endpoint: FieldSynchronizer.Endpoint) - fun read(stream: DataInputStream, payloadSize: Int) { - read(stream) - } - fun read(stream: DataInputStream) override fun getValue(thisRef: Any?, property: KProperty<*>): V { @@ -128,12 +115,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa private var nextFieldID = 0 - /** - * returns dummy field name - */ - fun nextFieldName() = "___field_${nextFieldID++}" - private var mappingVersion = 0 - val hasObservers: Boolean get() = observers.isNotEmpty() val isEmpty: Boolean get() = fields.isEmpty() val isNotEmpty: Boolean get() = fields.isNotEmpty() @@ -157,68 +138,68 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa hasChanges = false } - @JvmOverloads fun byte(getter: () -> Byte, name: String? = nextFieldName()) = ComputedField(getter, ByteValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bool(getter: () -> Boolean, name: String? = nextFieldName()) = ComputedField(getter, BooleanValueCodec, name ?: nextFieldName()) - @JvmOverloads fun short(getter: () -> Short, name: String? = nextFieldName()) = ComputedField(getter, ShortValueCodec, name ?: nextFieldName()) - @JvmOverloads fun long(getter: () -> Long, name: String? = nextFieldName()) = ComputedField(getter, VarLongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedLong(getter: () -> Long, name: String? = nextFieldName()) = ComputedField(getter, LongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun float(getter: () -> Float, name: String? = nextFieldName()) = ComputedField(getter, FloatValueCodec, name ?: nextFieldName()) - @JvmOverloads fun double(getter: () -> Double, name: String? = nextFieldName()) = ComputedField(getter, DoubleValueCodec, name ?: nextFieldName()) - @JvmOverloads fun uuid(getter: () -> UUID, name: String? = nextFieldName()) = ComputedField(getter, UUIDValueCodec, name ?: nextFieldName()) - @JvmOverloads fun int(getter: () -> Int, name: String? = nextFieldName()) = ComputedField(getter, VarIntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedInt(getter: () -> Int, name: String? = nextFieldName()) = ComputedField(getter, IntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fraction(getter: () -> Decimal, name: String? = nextFieldName()) = ComputedField(getter, ImpreciseFractionValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bigDecimal(getter: () -> BigDecimal, name: String? = nextFieldName()) = ComputedField(getter, BigDecimalValueCodec, name ?: nextFieldName()) - @JvmOverloads fun item(getter: () -> ItemStack, name: String? = nextFieldName()) = ComputedField(getter, ItemStackValueCodec, name ?: nextFieldName()) - @JvmOverloads fun string(getter: () -> String, name: String? = nextFieldName()) = ComputedField(getter, BinaryStringCodec, name ?: nextFieldName()) + fun byte(getter: () -> Byte) = ComputedField(getter, ByteValueCodec) + fun bool(getter: () -> Boolean) = ComputedField(getter, BooleanValueCodec) + 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 uuid(getter: () -> UUID) = ComputedField(getter, UUIDValueCodec) + fun int(getter: () -> Int) = ComputedField(getter, VarIntValueCodec) + fun fixedInt(getter: () -> Int) = ComputedField(getter, IntValueCodec) + fun fraction(getter: () -> Decimal) = ComputedField(getter, ImpreciseFractionValueCodec) + fun bigDecimal(getter: () -> BigDecimal) = ComputedField(getter, BigDecimalValueCodec) + fun item(getter: () -> ItemStack) = ComputedField(getter, ItemStackValueCodec) + fun string(getter: () -> String) = ComputedField(getter, BinaryStringCodec) - @JvmOverloads fun byte(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, ByteValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bool(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, BooleanValueCodec, name ?: nextFieldName()) - @JvmOverloads fun short(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, ShortValueCodec, name ?: nextFieldName()) - @JvmOverloads fun long(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, VarLongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedLong(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, LongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun float(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, FloatValueCodec, name ?: nextFieldName()) - @JvmOverloads fun double(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, DoubleValueCodec, name ?: nextFieldName()) - @JvmOverloads fun uuid(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, UUIDValueCodec, name ?: nextFieldName()) - @JvmOverloads fun int(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, VarIntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedInt(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, IntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fraction(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, ImpreciseFractionValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bigDecimal(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, BigDecimalValueCodec, name ?: nextFieldName()) - @JvmOverloads fun item(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, ItemStackValueCodec, name ?: nextFieldName()) - @JvmOverloads fun string(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, BinaryStringCodec, name ?: nextFieldName()) + fun byte(getter: KProperty0) = ComputedField(getter, ByteValueCodec) + fun bool(getter: KProperty0) = ComputedField(getter, BooleanValueCodec) + 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 uuid(getter: KProperty0) = ComputedField(getter, UUIDValueCodec) + fun int(getter: KProperty0) = ComputedField(getter, VarIntValueCodec) + fun fixedInt(getter: KProperty0) = ComputedField(getter, IntValueCodec) + fun fraction(getter: KProperty0) = ComputedField(getter, ImpreciseFractionValueCodec) + fun bigDecimal(getter: KProperty0) = ComputedField(getter, BigDecimalValueCodec) + fun item(getter: KProperty0) = ComputedField(getter, ItemStackValueCodec) + fun string(getter: KProperty0) = ComputedField(getter, BinaryStringCodec) - @JvmOverloads fun byte(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, ByteValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bool(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, BooleanValueCodec, name ?: nextFieldName()) - @JvmOverloads fun short(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, ShortValueCodec, name ?: nextFieldName()) - @JvmOverloads fun long(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, VarLongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedLong(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, LongValueCodec, name ?: nextFieldName()) - @JvmOverloads fun float(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, FloatValueCodec, name ?: nextFieldName()) - @JvmOverloads fun double(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, DoubleValueCodec, name ?: nextFieldName()) - @JvmOverloads fun uuid(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, UUIDValueCodec, name ?: nextFieldName()) - @JvmOverloads fun int(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, VarIntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fixedInt(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, IntValueCodec, name ?: nextFieldName()) - @JvmOverloads fun fraction(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, ImpreciseFractionValueCodec, name ?: nextFieldName()) - @JvmOverloads fun bigDecimal(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, BigDecimalValueCodec, name ?: nextFieldName()) - @JvmOverloads fun item(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, ItemStackValueCodec, name ?: nextFieldName()) - @JvmOverloads fun string(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, BinaryStringCodec, name ?: nextFieldName()) + fun byte(getter: Supplier) = ComputedField(getter::get, ByteValueCodec) + fun bool(getter: Supplier) = ComputedField(getter::get, BooleanValueCodec) + 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 uuid(getter: Supplier) = ComputedField(getter::get, UUIDValueCodec) + fun int(getter: Supplier) = ComputedField(getter::get, VarIntValueCodec) + fun fixedInt(getter: Supplier) = ComputedField(getter::get, IntValueCodec) + fun fraction(getter: Supplier) = ComputedField(getter::get, ImpreciseFractionValueCodec) + fun bigDecimal(getter: Supplier) = ComputedField(getter::get, BigDecimalValueCodec) + fun item(getter: Supplier) = ComputedField(getter::get, ItemStackValueCodec) + fun string(getter: Supplier) = ComputedField(getter::get, BinaryStringCodec) - @JvmOverloads fun > enum(type: Class, getter: () -> T, name: String? = nextFieldName()) = ComputedField(getter, EnumValueCodec.of(type), name ?: nextFieldName()) - inline fun > enum(noinline getter: () -> T, name: String? = nextFieldName()) = ComputedField(getter, EnumValueCodec.of(T::class.java), name ?: nextFieldName()) + fun > enum(type: Class, getter: () -> T) = ComputedField(getter, EnumValueCodec.of(type)) + inline fun > enum(noinline getter: () -> T) = ComputedField(getter, EnumValueCodec.of(T::class.java)) - @JvmOverloads fun > enum(type: Class, getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, EnumValueCodec.of(type), name ?: nextFieldName()) - inline fun > enum(getter: KProperty0, name: String? = nextFieldName()) = ComputedField(getter, EnumValueCodec.of(T::class.java), name ?: nextFieldName()) + fun > enum(type: Class, getter: KProperty0) = ComputedField(getter, EnumValueCodec.of(type)) + inline fun > enum(getter: KProperty0) = ComputedField(getter, EnumValueCodec.of(T::class.java)) - @JvmOverloads fun > enum(type: Class, getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, EnumValueCodec.of(type), name ?: nextFieldName()) - inline fun > enum(getter: Supplier, name: String? = nextFieldName()) = ComputedField(getter::get, EnumValueCodec.of(T::class.java), name ?: nextFieldName()) + fun > enum(type: Class, getter: Supplier) = ComputedField(getter::get, EnumValueCodec.of(type)) + inline fun > enum(getter: Supplier) = ComputedField(getter::get, EnumValueCodec.of(T::class.java)) @JvmOverloads fun byte( value: Byte = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, ByteValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, ByteValueCodec, getter, setter) } @JvmOverloads @@ -226,9 +207,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Boolean = false, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, BooleanValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, BooleanValueCodec, getter, setter) } @JvmOverloads @@ -236,9 +217,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Short = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, ShortValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, ShortValueCodec, getter, setter) } @JvmOverloads @@ -246,9 +227,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Long = 0L, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, VarLongValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, VarLongValueCodec, getter, setter) } @JvmOverloads @@ -256,9 +237,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Long = 0L, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, LongValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, LongValueCodec, getter, setter) } @JvmOverloads @@ -266,9 +247,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Float = 0f, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, FloatValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, FloatValueCodec, getter, setter) } @JvmOverloads @@ -276,9 +257,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Double = 0.0, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, DoubleValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, DoubleValueCodec, getter, setter) } @JvmOverloads @@ -286,9 +267,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: UUID = UUID(0L, 0L), getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, UUIDValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, UUIDValueCodec, getter, setter) } @JvmOverloads @@ -296,9 +277,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Int = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, VarIntValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, VarIntValueCodec, getter, setter) } @JvmOverloads @@ -306,9 +287,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: String = "", getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, BinaryStringCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, BinaryStringCodec, getter, setter) } @JvmOverloads @@ -316,9 +297,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Int = 0, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, IntValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, IntValueCodec, getter, setter) } @JvmOverloads @@ -326,9 +307,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: Decimal = Decimal.ZERO, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, ImpreciseFractionValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, ImpreciseFractionValueCodec, getter, setter) } @JvmOverloads @@ -336,9 +317,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: BigDecimal = BigDecimal.ZERO, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, BigDecimalValueCodec, getter, setter, name = name ?: nextFieldName()) + return Field(value, BigDecimalValueCodec, getter, setter) } @JvmOverloads @@ -347,9 +328,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: T = type.enumConstants[0], getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, EnumValueCodec.of(type), getter, setter, name = name ?: nextFieldName()) + return Field(value, EnumValueCodec.of(type), getter, setter) } @JvmOverloads @@ -357,9 +338,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa value: T, getter: FieldGetter? = null, setter: FieldSetter? = null, - name: String? = nextFieldName(), + ): Field { - return Field(value, EnumValueCodec.of(value::class.java), getter, setter, name = name ?: nextFieldName()) + return Field(value, EnumValueCodec.of(value::class.java), getter, setter) } @JvmOverloads @@ -368,17 +349,14 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa getter: FieldGetter? = null, setter: FieldSetter? = null, observe: Boolean = true, - name: String? = nextFieldName(), ): Field { - return Field(value, ItemStackValueCodec, getter, setter, isObserver = observe, name = name ?: nextFieldName()) + return Field(value, ItemStackValueCodec, getter, setter, isObserver = observe) } - @JvmOverloads fun item( delegate: KMutableProperty0, - name: String? = nextFieldName(), ): ObservedField { - return ObservedField(delegate, ItemStackValueCodec, name = name ?: nextFieldName()) + return ObservedField(delegate, ItemStackValueCodec) } @JvmOverloads @@ -388,7 +366,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa callback: ((changes: Collection>) -> Unit)? = null, backingMap: MutableMap = HashMap(), observingBackingMap: MutableMap? = null, - name: String? = nextFieldName(), ): Map { return Map( keyCodec = keyCodec, @@ -396,7 +373,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa callback = callback, backingMap = backingMap, observingBackingMap = observingBackingMap, - name = name ?: nextFieldName(), ) } @@ -516,36 +492,11 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } val stream = FastByteArrayOutputStream() - - if (mappingVersion != this@FieldSynchronizer.mappingVersion) { - stream.write(1) - - for (field in fields) { - check(field.id > 0) { "This should never happen: $field maps to invalid ID: ${field.id}!" } - stream.writeVarIntLE(field.id) - val bytes = field.name.toByteArray(Charsets.UTF_8) - stream.writeVarIntLE(bytes.size) - stream.write(bytes) - } - - stream.writeVarIntLE(0) - mappingVersion = this@FieldSynchronizer.mappingVersion - } else { - stream.write(0) - } + val dataStream = DataOutputStream(stream) for (field in dirtyFields) { - val id = field.id - check(id > 0) { "This should never happen: $field maps to invalid ID: $id!" } - stream.writeVarIntLE(id) - - val innerStream = FastByteArrayOutputStream() - val dataStream = DataOutputStream(innerStream) - + stream.writeVarIntLE(field.id) field.write(dataStream, this) - - stream.writeVarIntLE(innerStream.length) - stream.write(innerStream.array, 0, innerStream.length) } dirtyFields.clear() @@ -570,15 +521,11 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } @Suppress("LeakingThis") - abstract inner class AbstractField( - final override val name: String = nextFieldName(), - ) : IField { - var id: Int = fields.size + 1 + abstract inner class AbstractField : IField { + val id: Int = fields.size + 1 init { - check(!fields.any { it.name == name }) { "Duplicate field name $name" } fields.add(this) - mappingVersion++ } } @@ -591,8 +538,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa private val getter: FieldGetter? = null, private val setter: FieldSetter? = null, isObserver: Boolean = false, - name: String = nextFieldName(), - ) : AbstractField(name), IMutableField { + ) : AbstractField(), IMutableField { private var remote: V = codec.copy(field) init { @@ -691,9 +637,8 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa inner class ComputedField( private val getter: () -> V, private val codec: IStreamCodec, - name: String = nextFieldName(), private val observer: (new: V) -> Unit = {} - ) : AbstractField(name), IField { + ) : AbstractField(), IField { private var remote: V? = null private var clientValue: V? = null private var isDirty = false @@ -750,14 +695,14 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa get() = getter.invoke() set(value) { setter.invoke(value) } - constructor(field: KMutableProperty0, codec: IStreamCodec, name: String = nextFieldName()) : super(name) { + constructor(field: KMutableProperty0, codec: IStreamCodec) : super() { this.codec = codec getter = field::get setter = field::set remote = codec.copy(value) } - constructor(getter: () -> V, setter: (V) -> Unit, codec: IStreamCodec, name: String = nextFieldName()) : super(name) { + constructor(getter: () -> V, setter: (V) -> Unit, codec: IStreamCodec) : super() { this.codec = codec this.getter = getter this.setter = setter @@ -806,8 +751,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa private val backingMap: MutableMap, private val observingBackingMap: MutableMap? = null, private val callback: ((changes: Collection>) -> Unit)? = null, - name: String = nextFieldName(), - ) : AbstractField>(name), IField> { + ) : AbstractField>(), IField> { private var isDirty = false private var sentAllValues = false private var isRemote = false @@ -1116,63 +1060,15 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa return values } - private val idToField = Int2ObjectOpenHashMap>() - private val missingFields = ObjectArraySet() - private val missingFieldsMap = Int2ObjectArrayMap() - - fun read(stream: InputStream, sizeLimit: NbtAccounter = NbtAccounter(1L shl 21 /* 2 MiB */)): Int { - if (stream.read() > 0) { - idToField.clear() - missingFieldsMap.clear() - - var fieldId = stream.readVarIntLE(sizeLimit) - - while (fieldId != 0) { - val size = stream.readVarIntLE(sizeLimit) - val nameBytes = ByteArray(size) - stream.read(nameBytes) - val name = String(nameBytes, Charsets.UTF_8) - - val findField = fields.firstOrNull { it.name == name } - - if (findField == null) { - if (missingFields.add(name)) { - LOGGER.error("Unable to find field $name in $this, expect issues!") - } - - missingFieldsMap[fieldId] = name - } else { - idToField[fieldId] = findField - findField.id = fieldId - } - - fieldId = stream.readVarIntLE(sizeLimit) - } - } - - if (idToField.isEmpty()) { - throw IllegalStateException("Can't read anything, field ID mapping is empty!") - } - - var fieldId = stream.readVarIntLE(sizeLimit) + fun read(stream: InputStream): Int { + var fieldId = stream.readVarIntLE() var i = 0 + val dataStream = DataInputStream(stream) while (fieldId != 0) { - val field = idToField[fieldId] - val payloadSize = stream.readVarIntLE(sizeLimit) - - if (field == null) { - LOGGER.error("Unable to read field $fieldId (${missingFieldsMap[fieldId]}) because we don't know anything about it! Skipping $payloadSize bytes", IllegalStateException("Unknown field $fieldId")) - sizeLimit.accountBytes(payloadSize.toLong()) - stream.skipNBytes(payloadSize.toLong()) - continue - } - - sizeLimit.accountBytes(payloadSize.toLong()) - val bytes = ByteArray(payloadSize) - stream.read(bytes) - field.read(DataInputStream(FastByteArrayInputStream(bytes)), payloadSize) - fieldId = stream.readVarIntLE(sizeLimit) + val field = fields.getOrNull(fieldId - 1) ?: throw IllegalArgumentException("Unknown field ID ${fieldId - 1}") + field.read(dataStream) + fieldId = stream.readVarIntLE() i++ } @@ -1183,6 +1079,5 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa private val ClearBacklogEntry = { stream: DataOutputStream -> stream.write(MapAction.CLEAR.ordinal + 1) } private val MapActionList = MapAction.values() private val ClearMapChangeset = MapChangeset(MapAction.CLEAR, null, null) - private val LOGGER = LogManager.getLogger() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt index 1d66bc2fa..6d709eda3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -511,7 +511,7 @@ object HideExosuitPacket : MatteryPacket { } object MatteryPlayerNetworkChannel : MatteryNetworkChannel( - version = "1", + version = "2", name = "player" ) { fun register() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WeaponNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WeaponNetworkChannel.kt index 694b593c6..d879bed32 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WeaponNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WeaponNetworkChannel.kt @@ -5,7 +5,7 @@ import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket object WeaponNetworkChannel : MatteryNetworkChannel( - version = "1", + version = "2", name = "weapon" ) { fun register() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt index 30a9e1273..c500243d1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt @@ -93,7 +93,7 @@ class BlockEntitySyncPacket(val position: BlockPos, val buffer: ByteArray, val v } object WorldNetworkChannel : MatteryNetworkChannel( - version = "3", + version = "4", name = "world" ) { fun register() { diff --git a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt index 550469f3f..dae1dc541 100644 --- a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt +++ b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt @@ -131,32 +131,4 @@ object FieldSynchronizerTests { assertEquals(fieldsa[i].value, fieldsb[i].value) } } - - @Test - @DisplayName("Field Synchronizer field order definition mismatch") - fun orderMismatch() { - val a = FieldSynchronizer() - val b = FieldSynchronizer() - - val fieldsa = ArrayList>() - val fieldsb = ArrayList>() - - for (i in 0 .. 900) { - fieldsa.add(a.int(name = "int$i")) - } - - for (i in 900 downTo 0) { - fieldsb.add(0, b.int(name = "int$i")) - } - - for (i in 0 .. 900) { - fieldsa[i].value = i - } - - b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - - for (i in 0 .. 900) { - assertEquals(fieldsa[i].value, fieldsb[i].value) - } - } }