Use synchronizers for research/features fields

This commit is contained in:
DBotThePony 2022-09-17 15:14:18 +07:00
parent 97457ab027
commit 4acb362916
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 51 additions and 70 deletions

View File

@ -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<CompoundTag> {
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 {

View File

@ -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<CompoundTag> {
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
}

View File

@ -193,10 +193,6 @@ class AndroidResearchBuilder(
return object : AndroidResearchType<AndroidResearch>(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]

View File

@ -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))
}
}

View File

@ -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))
}
}