Allow DynamicSynchableGroup to accept non-ISynchables

This commit is contained in:
DBotThePony 2025-04-04 13:30:14 +07:00
parent afb6cd5907
commit d35da8c7f4
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -10,29 +10,39 @@ import java.io.Closeable
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
/**
* Constructs a new [DynamicSynchableGroup] where [T] is itself an [ISynchable]
*/
fun <T : ISynchable> DynamicSynchableGroup(reader: RegistryFriendlyByteBuf.() -> T, writer: T.(RegistryFriendlyByteBuf) -> Unit): DynamicSynchableGroup<T> {
return DynamicSynchableGroup(reader, { this }, writer)
}
/** /**
* Syncher group/set, which deals with synchables of only one type, and which are created and removed * Syncher group/set, which deals with synchables of only one type, and which are created and removed
* on remote (e.g. server adding and removing synchables at will), which makes it distinct from * on remote (e.g. server adding and removing synchables at will), which makes it distinct from
* [SynchableGroup], in which attached synchables are created/removed manually on both sides. * [SynchableGroup], in which attached synchables are created/removed manually on both sides.
*/ */
class DynamicSynchableGroup<T : ISynchable>( class DynamicSynchableGroup<T : Any>(
/** /**
* Constructs new [T] instance locally, when remote created one. * Constructs new [T] instance locally, when remote created one.
* Data written by [writer] must be read here, if there is any. * Data written by [writer] must be read here, if there is any.
*/ */
private val reader: RegistryFriendlyByteBuf.() -> T, private val reader: RegistryFriendlyByteBuf.() -> T,
/**
* Gets an [ISynchable] out of value [T] for synching state
*/
private val synchable: T.() -> ISynchable,
/** /**
* Allows to write additional data to network stream during * Allows to write additional data to network stream during
* first-time networking of [T] to remote * first-time networking of [T] to remote
*/ */
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {} private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {},
) : ISynchable, MutableSet<T> { ) : ISynchable, MutableSet<T> {
constructor(factory: () -> T) : this({ factory() }, {})
private inner class RemoteState(val listener: Runnable) : IRemoteState { private inner class RemoteState(val listener: Runnable) : IRemoteState {
private inner class RemoteSlot(val slot: Slot<T>, fromConstructor: Boolean) : Runnable, Closeable { private inner class RemoteSlot(val slot: Slot<T>, fromConstructor: Boolean) : Runnable, Closeable {
val remoteState = slot.synchable.createRemoteState(this) val remoteState = synchable(slot.value).createRemoteState(this)
val isDirty = AtomicBoolean(true) val isDirty = AtomicBoolean(true)
var isRemoved = false var isRemoved = false
private set private set
@ -114,7 +124,7 @@ class DynamicSynchableGroup<T : ISynchable>(
firstTime.forEach { firstTime.forEach {
stream.writeByte(ADD_ENTRY) stream.writeByte(ADD_ENTRY)
stream.writeVarInt(it.slot.id) stream.writeVarInt(it.slot.id)
writer(it.slot.synchable, stream) writer(it.slot.value, stream)
} }
firstTime.clear() firstTime.clear()
@ -177,7 +187,7 @@ class DynamicSynchableGroup<T : ISynchable>(
} }
} }
private data class Slot<T : Any>(val synchable: T, val id: Int) private data class Slot<T : Any>(val value: T, val id: Int)
private val remoteStates = ArrayList<RemoteState>() private val remoteStates = ArrayList<RemoteState>()
private val value2slot = HashMap<T, Slot<T>>() private val value2slot = HashMap<T, Slot<T>>()
@ -199,7 +209,7 @@ class DynamicSynchableGroup<T : ISynchable>(
REMOVE_ENTRY -> { REMOVE_ENTRY -> {
val id = stream.readVarInt() val id = stream.readVarInt()
val slot = checkNotNull(id2slot.remove(id)) { "No such slot with ID: $id" } val slot = checkNotNull(id2slot.remove(id)) { "No such slot with ID: $id" }
check(value2slot.remove(slot.synchable) == value2slot) check(value2slot.remove(slot.value) == value2slot)
remoteStates.forEach { it.remove(slot) } remoteStates.forEach { it.remove(slot) }
} }
@ -212,7 +222,7 @@ class DynamicSynchableGroup<T : ISynchable>(
if (id2slot.containsKey(id)) { if (id2slot.containsKey(id)) {
val slot = id2slot.remove(id)!! val slot = id2slot.remove(id)!!
check(value2slot.remove(slot.synchable) == value2slot) check(value2slot.remove(slot.value) == value2slot)
remoteStates.forEach { it.remove(slot) } remoteStates.forEach { it.remove(slot) }
} }
@ -225,7 +235,7 @@ class DynamicSynchableGroup<T : ISynchable>(
SYNC_ENTRY -> { SYNC_ENTRY -> {
val id = stream.readVarInt() val id = stream.readVarInt()
val slot = checkNotNull(id2slot.get(id)) { "No such slot with ID: $id" } val slot = checkNotNull(id2slot.get(id)) { "No such slot with ID: $id" }
slot.synchable.read(stream) synchable(slot.value).read(stream)
} }
CLEAR -> { CLEAR -> {
@ -299,7 +309,7 @@ class DynamicSynchableGroup<T : ISynchable>(
override fun next(): T { override fun next(): T {
val slot = parent.next() val slot = parent.next()
last = KOptional(slot) last = KOptional(slot)
return slot.synchable return slot.value
} }
override fun remove() { override fun remove() {