diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/DataStreams.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/DataStreams.kt index 547c33d93..94a4586f6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/DataStreams.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/DataStreams.kt @@ -7,6 +7,7 @@ import java.io.InputStream import java.io.OutputStream import java.util.* import java.util.function.Predicate +import kotlin.math.absoluteValue interface IStreamCodec { fun read(stream: DataInputStream): V @@ -134,59 +135,79 @@ fun OutputStream.writeDouble(value: Double) = writeLong(value.toBits()) fun InputStream.readDouble() = Double.fromBits(readLong()) fun InputStream.readVarIntLE(): Int { - var result = 0 - var read = read() - var i = 0 + val readFirst = read() - while (read and 128 != 0) { - result = result or ((read and 127) shl i) - read = read() - i += 7 + if (readFirst and 64 == 0) { + return if (readFirst and 128 != 0) -(readFirst and 63) else readFirst and 63 } - result = result or ((read and 127) shl i) + var result = 0 + var nextBit = readFirst and 64 + var read = readFirst and 63 + var i = 0 - return result + while (nextBit != 0) { + result = result or (read shl i) + read = read() + nextBit = read and 128 + read = read and 127 + + if (i == 0) + i = 6 + else + i += 7 + } + + result = result or (read shl i) + return if (readFirst and 128 != 0) -result else result } fun OutputStream.writeVarIntLE(value: Int) { - require(value >= 0) { "Negative number provided: $value" } - var written = value + write((if (value < 0) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63)) + var written = value.absoluteValue ushr 6 - while (written >= 128) { - write((written and 127) or 128) + while (written != 0) { + write((written and 127) or (if (written >= 128) 128 else 0)) written = written ushr 7 } - - write(written) } fun InputStream.readVarLongLE(): Long { - var result = 0L - var read = read() - var i = 0 + val readFirst = read() - while (read and 128 != 0) { - result = result or ((read and 127) shl i).toLong() - read = read() - i += 7 + if (readFirst and 64 == 0) { + return if (readFirst and 128 != 0) -(readFirst and 63).toLong() else (readFirst and 63).toLong() } - result = result or ((read and 127) shl i).toLong() + var result = 0L + var nextBit = readFirst and 64 + var read = readFirst and 63 + var i = 0 - return result + while (nextBit != 0) { + result = result or (read shl i).toLong() + read = read() + nextBit = read and 128 + read = read and 127 + + if (i == 0) + i = 6 + else + i += 7 + } + + result = result or (read shl i).toLong() + return if (readFirst and 128 != 0) -result else result } fun OutputStream.writeVarLongLE(value: Long) { - require(value >= 0L) { "Negative number provided: $value" } - var written = value + write((if (value < 0L) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63).toInt()) + var written = value.absoluteValue ushr 6 - while (written >= 128) { - write(((written and 127) or 128).toInt()) + while (written != 0L) { + write((written and 127).toInt() or (if (written >= 128) 128 else 0)) written = written ushr 7 } - - write(written.toInt()) } private data class IndexedStreamCodec( 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 94f444ec8..0c122db40 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -101,6 +101,14 @@ class FieldSynchronizer { return Field(value, VarLongValueCodec, getter, setter) } + fun fixedLong( + value: Long = 0L, + getter: FieldGetter? = null, + setter: FieldSetter? = null, + ): Field { + return Field(value, LongValueCodec, getter, setter) + } + fun float( value: Float = 0f, getter: FieldGetter? = null, @@ -133,6 +141,14 @@ class FieldSynchronizer { return Field(value, VarIntValueCodec, getter, setter) } + fun fixedInt( + value: Int = 0, + getter: FieldGetter? = null, + setter: FieldSetter? = null, + ): Field { + return Field(value, IntValueCodec, getter, setter) + } + fun fraction( value: ImpreciseFraction = ImpreciseFraction.ZERO, getter: FieldGetter? = null, diff --git a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FriendlyStreams.kt b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FriendlyStreams.kt index 61525fff7..371cfb050 100644 --- a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FriendlyStreams.kt +++ b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FriendlyStreams.kt @@ -7,8 +7,10 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import ru.dbotthepony.mc.otm.core.readInt import ru.dbotthepony.mc.otm.core.readVarIntLE +import ru.dbotthepony.mc.otm.core.readVarLongLE import ru.dbotthepony.mc.otm.core.writeInt import ru.dbotthepony.mc.otm.core.writeVarIntLE +import ru.dbotthepony.mc.otm.core.writeVarLongLE object FriendlyStreams { @Test @@ -32,22 +34,88 @@ object FriendlyStreams { output.writeVarIntLE(10023) output.writeVarIntLE(100000) + output.writeVarIntLE(-0) + output.writeVarIntLE(-1) + output.writeVarIntLE(-4) + output.writeVarIntLE(-15) + output.writeVarIntLE(-16) + output.writeVarIntLE(-127) + output.writeVarIntLE(-128) + output.writeVarIntLE(-129) + output.writeVarIntLE(-10023) + output.writeVarIntLE(-100000) + + output.writeVarLongLE(0) + output.writeVarLongLE(1) + output.writeVarLongLE(4) + output.writeVarLongLE(15) + output.writeVarLongLE(16) + output.writeVarLongLE(127) + output.writeVarLongLE(128) + output.writeVarLongLE(129) + output.writeVarLongLE(10023) + output.writeVarLongLE(100000) + + output.writeVarLongLE(-0) + output.writeVarLongLE(-1) + output.writeVarLongLE(-4) + output.writeVarLongLE(-15) + output.writeVarLongLE(-16) + output.writeVarLongLE(-127) + output.writeVarLongLE(-128) + output.writeVarLongLE(-129) + output.writeVarLongLE(-10023) + output.writeVarLongLE(-100000) + val input = FastByteArrayInputStream(output.array, 0, output.length) - assertEquals(input.readInt(), 4) - assertEquals(input.readInt(), 16) - assertEquals(input.readInt(), -1) - assertEquals(input.readInt(), 1000000) + assertEquals(4, input.readInt()) + assertEquals(16, input.readInt()) + assertEquals(-1, input.readInt()) + assertEquals(1000000, input.readInt()) - assertEquals(input.readVarIntLE(), 0) - assertEquals(input.readVarIntLE(), 1) - assertEquals(input.readVarIntLE(), 4) - assertEquals(input.readVarIntLE(), 15) - assertEquals(input.readVarIntLE(), 16) - assertEquals(input.readVarIntLE(), 127) - assertEquals(input.readVarIntLE(), 128) - assertEquals(input.readVarIntLE(), 129) - assertEquals(input.readVarIntLE(), 10023) - assertEquals(input.readVarIntLE(), 100000) + assertEquals(0, input.readVarIntLE()) + assertEquals(1, input.readVarIntLE()) + assertEquals(4, input.readVarIntLE()) + assertEquals(15, input.readVarIntLE()) + assertEquals(16, input.readVarIntLE()) + assertEquals(127, input.readVarIntLE()) + assertEquals(128, input.readVarIntLE()) + assertEquals(129, input.readVarIntLE()) + assertEquals(10023, input.readVarIntLE()) + assertEquals(100000, input.readVarIntLE()) + + assertEquals(-0, input.readVarIntLE()) + assertEquals(-1, input.readVarIntLE()) + assertEquals(-4, input.readVarIntLE()) + assertEquals(-15, input.readVarIntLE()) + assertEquals(-16, input.readVarIntLE()) + assertEquals(-127, input.readVarIntLE()) + assertEquals(-128, input.readVarIntLE()) + assertEquals(-129, input.readVarIntLE()) + assertEquals(-10023, input.readVarIntLE()) + assertEquals(-100000, input.readVarIntLE()) + + assertEquals(0, input.readVarLongLE()) + assertEquals(1, input.readVarLongLE()) + assertEquals(4, input.readVarLongLE()) + assertEquals(15, input.readVarLongLE()) + assertEquals(16, input.readVarLongLE()) + assertEquals(127, input.readVarLongLE()) + assertEquals(128, input.readVarLongLE()) + assertEquals(129, input.readVarLongLE()) + assertEquals(10023, input.readVarLongLE()) + assertEquals(100000, input.readVarLongLE()) + + assertEquals(-0, input.readVarLongLE()) + assertEquals(-1, input.readVarLongLE()) + assertEquals(-4, input.readVarLongLE()) + assertEquals(-15, input.readVarLongLE()) + assertEquals(-16, input.readVarLongLE()) + assertEquals(-127, input.readVarLongLE()) + assertEquals(-128, input.readVarLongLE()) + assertEquals(-129, input.readVarLongLE()) + assertEquals(-10023, input.readVarLongLE()) + assertEquals(-100000, input.readVarLongLE()) } } \ No newline at end of file