From 4acb3629167da92a77cef9f2295e77af672a18dc Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 17 Sep 2022 15:14:18 +0700 Subject: [PATCH] Use synchronizers for research/features fields --- .../mc/otm/android/AndroidFeature.kt | 36 +++++++++---------- .../mc/otm/android/AndroidResearch.kt | 31 +++++++--------- .../mc/otm/android/AndroidResearchBuilder.kt | 4 --- .../otm/capability/MatteryPlayerCapability.kt | 31 ++++++++++------ .../network/MatteryPlayerNetworkChannel.kt | 19 ++-------- 5 files changed, 51 insertions(+), 70 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt index 5c335adb3..4439f9bc0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt @@ -1,31 +1,25 @@ package ru.dbotthepony.mc.otm.android +import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.event.entity.living.LivingHurtEvent import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability -import ru.dbotthepony.mc.otm.core.readNbt -import ru.dbotthepony.mc.otm.container.set import ru.dbotthepony.mc.otm.core.set -import ru.dbotthepony.mc.otm.core.writeNbt +import ru.dbotthepony.mc.otm.network.FieldSynchronizer +import java.io.DataInputStream import java.io.InputStream -import java.io.OutputStream abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable { val entity get() = android.ply + val synchronizer = FieldSynchronizer() - /** - * Whenever there are changes to network - */ - var isDirty = false - - open var level = 0 - set(value) { - if (value != field) { - field = value - applyModifiers() - } + open var level by synchronizer.int(setter = setter@{ value, field, setByRemote -> + if (value != field.read()) { + field.write(value) + applyModifiers() } + }) open fun tickClient() {} open fun tickServer() {} @@ -33,19 +27,21 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt /** * Called when it is required to network everything again */ - open fun invalidateNetwork() {} + open fun invalidateNetwork() { + synchronizer.invalidate() + } open fun applyModifiers() {} open fun removeModifiers() {} open fun onHurt(event: LivingHurtEvent) {} - open fun writeNetwork(stream: OutputStream) { - stream.writeNbt(serializeNBT()) + open fun collectNetworkPayload(): FastByteArrayOutputStream? { + return synchronizer.collectNetworkPayload() } - open fun readNetwork(stream: InputStream) { - deserializeNBT(stream.readNbt()) + open fun applyNetworkPayload(stream: InputStream) { + synchronizer.applyNetworkPayload(DataInputStream(stream)) } override fun serializeNBT(): CompoundTag { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt index 9d1181152..c1c49004f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.android +import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import net.minecraft.ChatFormatting import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component @@ -7,26 +8,23 @@ import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.client.render.SkinElement -import ru.dbotthepony.mc.otm.core.readNbt -import ru.dbotthepony.mc.otm.container.set import ru.dbotthepony.mc.otm.core.set -import ru.dbotthepony.mc.otm.core.writeNbt +import ru.dbotthepony.mc.otm.network.FieldSynchronizer +import java.io.DataInputStream import java.io.InputStream -import java.io.OutputStream abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: MatteryPlayerCapability) : INBTSerializable { - var isResearched = false - protected set + val synchronizer = FieldSynchronizer() - /** - * Whenever there are changes to network - */ - var isDirty = false + var isResearched by synchronizer.bool() + protected set /** * Called when it is required to network everything again */ - abstract fun invalidateNetwork() + open fun invalidateNetwork() { + synchronizer.invalidate() + } fun unResearch() { if (!isResearched) { @@ -35,7 +33,6 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: onUnResearch() isResearched = false - isDirty = true } abstract fun onUnResearch() @@ -57,12 +54,12 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: */ abstract fun refund(simulate: Boolean): Boolean - open fun writeNetwork(buff: OutputStream) { - buff.writeNbt(serializeNBT()) + open fun collectNetworkPayload(): FastByteArrayOutputStream? { + return synchronizer.collectNetworkPayload() } - open fun readNetwork(buff: InputStream) { - deserializeNBT(buff.readNbt()) + open fun applyNetworkPayload(stream: InputStream) { + synchronizer.applyNetworkPayload(DataInputStream(stream)) } open val canResearch: Boolean get() { @@ -146,12 +143,10 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: if (force) { onResearched() isResearched = true - isDirty = true return true } else if (consumeResearchCost(false)) { onResearched() isResearched = true - isDirty = true return true } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt index 14ee37c60..1ecf594fa 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt @@ -193,10 +193,6 @@ class AndroidResearchBuilder( return object : AndroidResearchType(factory@{ it, capability -> return@factory object : AndroidResearch(it, capability) { - override fun invalidateNetwork() { - // NO-OP - } - override fun onUnResearch() { for (feature in features) { val level = oldResearchLevel[feature.feature] 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 23a47eae5..e90032f8c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -30,7 +30,6 @@ import net.minecraftforge.event.TickEvent import net.minecraftforge.event.TickEvent.PlayerTickEvent import net.minecraftforge.event.entity.living.LivingDeathEvent import net.minecraftforge.event.entity.living.LivingDropsEvent -import net.minecraftforge.event.entity.living.LivingEvent import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.LivingSpawnEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent @@ -279,7 +278,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } if (ply is ServerPlayer) { - sendNetwork(AndroidFeatureSyncPacket(feature)) + feature.invalidateNetwork() + val payload = feature.collectNetworkPayload() + + if (payload != null) { + sendNetwork(AndroidFeatureSyncPacket(feature.type, payload, null)) + } } return true @@ -299,7 +303,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } if (ply is ServerPlayer) { - sendNetwork(AndroidFeatureSyncPacket(factory)) + factory.invalidateNetwork() + val payload = factory.collectNetworkPayload() + + if (payload != null) { + sendNetwork(AndroidFeatureSyncPacket(feature, payload, null)) + } } return factory @@ -582,12 +591,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial synchronizer.invalidate() for (instance in research.values) { - instance.isDirty = true instance.invalidateNetwork() } for (feature in features.values) { - feature.isDirty = true feature.invalidateNetwork() } } @@ -609,16 +616,18 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } for (instance in research.values) { - if (instance.isDirty) { - instance.isDirty = false - sendNetwork(AndroidResearchSyncPacket(instance)) + val researchPayload = instance.collectNetworkPayload() + + if (researchPayload != null) { + sendNetwork(AndroidResearchSyncPacket(instance.type, researchPayload, null)) } } for (instance in features.values) { - if (instance.isDirty) { - instance.isDirty = false - sendNetwork(AndroidFeatureSyncPacket(instance)) + val featurePayload = instance.collectNetworkPayload() + + if (featurePayload != null) { + sendNetwork(AndroidFeatureSyncPacket(instance.type, featurePayload, null)) } } 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 3afbc7960..4de9a66d0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.network -import it.unimi.dsi.fastutil.bytes.ByteArrayList import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component @@ -13,13 +12,9 @@ import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidFeatureType import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType -import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.MatteryGUI import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.readImpreciseFraction -import ru.dbotthepony.mc.otm.core.writeImpreciseFraction import ru.dbotthepony.mc.otm.menu.AndroidStationMenu import ru.dbotthepony.mc.otm.registry.MRegistry import java.io.ByteArrayInputStream @@ -75,15 +70,7 @@ class AndroidResearchRequestPacket(val type: AndroidResearchType<*>) : MatteryPa } } -private fun getData(invoke: (stream: OutputStream) -> Unit): FastByteArrayOutputStream { - val stream = FastByteArrayOutputStream() - invoke(stream) - return stream -} - class AndroidResearchSyncPacket(val type: AndroidResearchType<*>, val dataList: FastByteArrayOutputStream?, val dataBytes: ByteArray?) : MatteryPacket { - constructor(feature: AndroidResearch) : this(feature.type, getData(feature::writeNetwork), null) - override fun write(buff: FriendlyByteBuf) { dataList ?: throw NullPointerException("No byte list is present") buff.writeInt(MRegistry.ANDROID_RESEARCH.getID(type)) @@ -97,7 +84,7 @@ class AndroidResearchSyncPacket(val type: AndroidResearchType<*>, val dataList: context.get().enqueueWork { val android = minecraft.player?.matteryPlayer ?: return@enqueueWork - android.getResearch(type).readNetwork(ByteArrayInputStream(dataBytes)) + android.getResearch(type).applyNetworkPayload(ByteArrayInputStream(dataBytes)) } } @@ -112,8 +99,6 @@ class AndroidResearchSyncPacket(val type: AndroidResearchType<*>, val dataList: } class AndroidFeatureSyncPacket(val type: AndroidFeatureType<*>, val dataList: FastByteArrayOutputStream?, val dataBytes: ByteArray?) : MatteryPacket { - constructor(feature: AndroidFeature) : this(feature.type, getData(feature::writeNetwork), null) - override fun write(buff: FriendlyByteBuf) { dataList ?: throw NullPointerException("No byte list is present") buff.writeInt(MRegistry.ANDROID_FEATURES.getID(type)) @@ -127,7 +112,7 @@ class AndroidFeatureSyncPacket(val type: AndroidFeatureType<*>, val dataList: Fa context.get().enqueueWork { val android = minecraft.player?.matteryPlayer ?: return@enqueueWork - android.computeIfAbsent(type).readNetwork(ByteArrayInputStream(dataBytes)) + android.computeIfAbsent(type).applyNetworkPayload(ByteArrayInputStream(dataBytes)) } }