From 286174d8a76a5411d142527ecca815a1ac3cedbb Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 21 Oct 2022 16:37:06 +0700 Subject: [PATCH] Fields now know their payload sizes, field synchronizer stream now can be safely embedded into any other data structure --- .../mc/otm/network/FieldSynchronizer.kt | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt index 880199921..a0320a8e6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -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 : ReadOnlyProperty, Supplier, () -> 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() private val missingFieldsMap = Int2ObjectAVLTreeMap() - 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()