Fields now know their payload sizes, field synchronizer stream now can be safely embedded into any other data structure

This commit is contained in:
DBotThePony 2022-10-21 16:37:06 +07:00
parent 0396a4f7c0
commit 286174d8a7
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.network
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
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
@ -48,6 +49,10 @@ sealed interface IField<V> : ReadOnlyProperty<Any, V>, Supplier<V>, () -> 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 {
@ -463,7 +468,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
}
val stream = FastByteArrayOutputStream()
val dataStream = DataOutputStream(stream)
if (mappingVersion != this@FieldSynchronizer.mappingVersion) {
stream.write(1)
@ -486,11 +490,18 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
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)
field.write(dataStream, this)
stream.writeVarIntLE(innerStream.length)
stream.write(innerStream.array, 0, innerStream.length)
}
dirtyFields.clear()
dataStream.write(0)
stream.write(0)
return stream
}
@ -1045,8 +1056,8 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
private val missingFields = ObjectArraySet<String>()
private val missingFieldsMap = Int2ObjectAVLTreeMap<String>()
fun applyNetworkPayload(stream: DataInputStream): Int {
if (stream.readBoolean()) {
fun applyNetworkPayload(stream: InputStream): Int {
if (stream.read() > 0) {
idToField.clear()
missingFieldsMap.clear()
@ -1080,28 +1091,24 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
while (fieldId != 0) {
val field = idToField[fieldId]
val payloadSize = stream.readVarIntLE()
if (field == null) {
LOGGER.error("Unable to read field $fieldId (${missingFieldsMap[fieldId]}) because we don't know anything about it!")
stream.skipNBytes(payloadSize.toLong())
continue
}
field.read(stream)
val bytes = ByteArray(payloadSize)
stream.read(bytes)
field.read(DataInputStream(FastByteArrayInputStream(bytes)), payloadSize)
fieldId = stream.readVarIntLE()
i++
}
if (stream.read() != -1) {
throw IllegalStateException("Stream wasn't fully drain!")
}
return i
}
fun applyNetworkPayload(stream: InputStream): Int {
return applyNetworkPayload(DataInputStream(stream))
}
companion object {
private val ClearBacklogEntry = { stream: DataOutputStream -> stream.write(MapAction.CLEAR.ordinal + 1) }
private val MapActionList = MapAction.values()