From a293ae021d624215a61345fc85ff39e06ded0a85 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 2 May 2020 04:59:03 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20NetInputStream=20=D0=B8=20NetOutputStream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/mc/protocol/io/NetInputStream.java | 78 ++++++++++++++++--- .../java/mc/protocol/io/NetOutputStream.java | 28 ++++++- .../io/coder/ByteArrayNetOutputStream.java | 31 ++++++++ 3 files changed, 121 insertions(+), 16 deletions(-) diff --git a/src/main/java/mc/protocol/io/NetInputStream.java b/src/main/java/mc/protocol/io/NetInputStream.java index fa2169e..44950af 100644 --- a/src/main/java/mc/protocol/io/NetInputStream.java +++ b/src/main/java/mc/protocol/io/NetInputStream.java @@ -3,6 +3,7 @@ package mc.protocol.io; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.UUID; public abstract class NetInputStream extends InputStream { @@ -11,11 +12,13 @@ public abstract class NetInputStream extends InputStream { } @Override - public int read() throws IOException { + public int read() { return readByte(); } - // Unsigned Byte [1] + public int readUnsignedByte() { + return readByte() & 0xFF; + } public int readUnsignedShort() { return readShort() & 0xFFFF; @@ -39,20 +42,37 @@ public abstract class NetInputStream extends InputStream { if (length == 0) { return ""; } else if (length > maxLength) { - throw new DecoderException("String length exceeds maximum length: " + length + " > " + maxLength); + throw new DecoderException("String length exceeds maximum length: " + length + " > " + maxLength); } else if (length < 0) { throw new DecoderException("String length less zero!"); } - byte[] bytes = new byte[length]; - readBytes(bytes); - return new String(bytes, StandardCharsets.UTF_8); + byte[] bytes = new byte[length * 4]; + int readbleBytes = 0; + for (int i = 0; i < length; i++) { + byte b = readByte(); + bytes[readbleBytes++] = b; + + switch ((b & 0xFF) >> 4) { + case 0b1100: + case 0b1101: + bytes[readbleBytes++] = readByte(); + break; + case 0b1110: + bytes[readbleBytes++] = readByte(); + bytes[readbleBytes++] = readByte(); + break; + case 0b1111: + bytes[readbleBytes++] = readByte(); + bytes[readbleBytes++] = readByte(); + bytes[readbleBytes++] = readByte(); + break; + } + } + + return new String(bytes, 0, readbleBytes, StandardCharsets.UTF_8); } - // Chat - - // Identifier - public int readVarInt() { int numRead = 0; int result = 0; @@ -72,7 +92,25 @@ public abstract class NetInputStream extends InputStream { return result; } - // VarLong + public long readVarLong() { + int numRead = 0; + long result = 0L; + byte read; + do { + if (numRead > 10) { + //FIXME выводить в лог предупреждение + break; // VarLong is too big + } + + read = readByte(); + long value = (read & 0b01111111); + result |= (value << (7 * numRead)); + + numRead++; + } while ((read & 0b10000000) != 0); + + return result; + } // Entity Metadata @@ -84,7 +122,9 @@ public abstract class NetInputStream extends InputStream { // Angle [1] - // UUID [16] + public UUID readUUID() { + return new UUID(readLong(), readLong()); + } public int readBytes(byte[] buffer) { return readBytes(buffer, 0, buffer.length); @@ -100,9 +140,23 @@ public abstract class NetInputStream extends InputStream { return readBytes(buffer, offset, length); } + public abstract void markReadIndex(); + + public abstract void resetReadIndex(); + + public abstract int readableBytes(); + public abstract byte readByte(); public abstract int readBytes(byte[] buffer, int offset, int lengtn); public abstract int readShort(); + + public abstract int readInt(); + + public abstract long readLong(); + + public abstract float readFloat(); + + public abstract double readDouble(); } diff --git a/src/main/java/mc/protocol/io/NetOutputStream.java b/src/main/java/mc/protocol/io/NetOutputStream.java index 0435ad0..7ffb26d 100644 --- a/src/main/java/mc/protocol/io/NetOutputStream.java +++ b/src/main/java/mc/protocol/io/NetOutputStream.java @@ -3,6 +3,7 @@ package mc.protocol.io; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.UUID; public abstract class NetOutputStream extends OutputStream { @@ -29,14 +30,15 @@ public abstract class NetOutputStream extends OutputStream { public void writeString(String string) { byte[] buf; + int length = (int) string.codePoints().count(); - if (string.length() > Short.MAX_VALUE) { + if (length > Short.MAX_VALUE) { //FIXME нужно выдавать предупреждение в лог buf = string.substring(0, Short.MAX_VALUE).getBytes(StandardCharsets.UTF_8); writeVarInt(Short.MAX_VALUE); } else { buf = string.getBytes(StandardCharsets.UTF_8); - writeVarInt(string.length()); + writeVarInt(length); } writeBytes(buf); @@ -55,7 +57,14 @@ public abstract class NetOutputStream extends OutputStream { writeByte(value); } - // VarLong + public void writeVarLong(long value) { + while ((value & -128L) != 0L) { + writeByte((int)(value & 127L) | 128); + value >>>= 7; + } + + writeByte((int)value); + } // Entity Metadata @@ -67,7 +76,10 @@ public abstract class NetOutputStream extends OutputStream { // Angle [1] - // UUID [16] + public void writeUUID(UUID uuid) { + writeLong(uuid.getMostSignificantBits()); + writeLong(uuid.getLeastSignificantBits()); + } public void writeBytes(byte[] buffer) { writeBytes(buffer, 0, buffer.length); @@ -88,4 +100,12 @@ public abstract class NetOutputStream extends OutputStream { public abstract void writeBytes(byte[] buffer, int offset, int lengtn); public abstract void writeShort(int value); + + public abstract void writeInt(int value); + + public abstract void writeLong(long value); + + public abstract void writeFloat(float value); + + public abstract void writeDouble(double value); } diff --git a/src/main/java/mc/protocol/io/coder/ByteArrayNetOutputStream.java b/src/main/java/mc/protocol/io/coder/ByteArrayNetOutputStream.java index f42ee07..ba93d38 100644 --- a/src/main/java/mc/protocol/io/coder/ByteArrayNetOutputStream.java +++ b/src/main/java/mc/protocol/io/coder/ByteArrayNetOutputStream.java @@ -6,6 +6,7 @@ import java.io.ByteArrayOutputStream; class ByteArrayNetOutputStream extends NetOutputStream { + //TODO может заменить на DataOutputStream? private ByteArrayOutputStream baos = new ByteArrayOutputStream(); @Override @@ -24,6 +25,36 @@ class ByteArrayNetOutputStream extends NetOutputStream { baos.write(value & 0xFF); } + @Override + public void writeInt(int value) { + baos.write((value >>> 24) & 0xFF); + baos.write((value >>> 16) & 0xFF); + baos.write((value >>> 8) & 0xFF); + baos.write(value & 0xFF); + } + + @Override + public void writeLong(long value) { + baos.write((int) ((value >>> 56) & 0xFF)); + baos.write((int) ((value >>> 48) & 0xFF)); + baos.write((int) ((value >>> 40) & 0xFF)); + baos.write((int) ((value >>> 32) & 0xFF)); + baos.write((int) ((value >>> 24) & 0xFF)); + baos.write((int) ((value >>> 16) & 0xFF)); + baos.write((int) ((value >>> 8) & 0xFF)); + baos.write((int) (value & 0xFF)); + } + + @Override + public void writeFloat(float value) { + writeInt(Float.floatToIntBits(value)); + } + + @Override + public void writeDouble(double value) { + writeLong(Double.doubleToLongBits(value)); + } + int size() { return baos.size(); }