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.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
* 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.
*/
class DynamicSynchableGroup<T : ISynchable>(
class DynamicSynchableGroup<T : Any>(
/**
* Constructs new [T] instance locally, when remote created one.
* Data written by [writer] must be read here, if there is any.
*/
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
* first-time networking of [T] to remote
*/
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {}
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {},
) : ISynchable, MutableSet<T> {
constructor(factory: () -> T) : this({ factory() }, {})
private inner class RemoteState(val listener: Runnable) : IRemoteState {
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)
var isRemoved = false
private set
@ -114,7 +124,7 @@ class DynamicSynchableGroup<T : ISynchable>(
firstTime.forEach {
stream.writeByte(ADD_ENTRY)
stream.writeVarInt(it.slot.id)
writer(it.slot.synchable, stream)
writer(it.slot.value, stream)
}
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 value2slot = HashMap<T, Slot<T>>()
@ -199,7 +209,7 @@ class DynamicSynchableGroup<T : ISynchable>(
REMOVE_ENTRY -> {
val id = stream.readVarInt()
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) }
}
@ -212,7 +222,7 @@ class DynamicSynchableGroup<T : ISynchable>(
if (id2slot.containsKey(id)) {
val slot = id2slot.remove(id)!!
check(value2slot.remove(slot.synchable) == value2slot)
check(value2slot.remove(slot.value) == value2slot)
remoteStates.forEach { it.remove(slot) }
}
@ -225,7 +235,7 @@ class DynamicSynchableGroup<T : ISynchable>(
SYNC_ENTRY -> {
val id = stream.readVarInt()
val slot = checkNotNull(id2slot.get(id)) { "No such slot with ID: $id" }
slot.synchable.read(stream)
synchable(slot.value).read(stream)
}
CLEAR -> {
@ -299,7 +309,7 @@ class DynamicSynchableGroup<T : ISynchable>(
override fun next(): T {
val slot = parent.next()
last = KOptional(slot)
return slot.synchable
return slot.value
}
override fun remove() {