diff --git a/patches/minecraft/net/minecraft/network/play/server/S3FPacketCustomPayload.java.patch b/patches/minecraft/net/minecraft/network/play/server/S3FPacketCustomPayload.java.patch new file mode 100644 index 0000000000..0dc3a9ea4a --- /dev/null +++ b/patches/minecraft/net/minecraft/network/play/server/S3FPacketCustomPayload.java.patch @@ -0,0 +1,37 @@ +--- ../src-base/minecraft/net/minecraft/network/play/server/S3FPacketCustomPayload.java ++++ ../src-work/minecraft/net/minecraft/network/play/server/S3FPacketCustomPayload.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.play.server; + ++import cpw.mods.fml.common.network.ByteBufUtils; + import cpw.mods.fml.relauncher.Side; + import cpw.mods.fml.relauncher.SideOnly; + import io.netty.buffer.ByteBuf; +@@ -27,23 +28,23 @@ + this.field_149172_a = p_i45190_1_; + this.field_149171_b = p_i45190_2_; + +- if (p_i45190_2_.length >= 32767) ++ if (p_i45190_2_.length > 0x1ffff0) + { +- throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); ++ throw new IllegalArgumentException("Payload may not be larger than 2097136 (0x1ffff0) bytes"); + } + } + + public void func_148837_a(PacketBuffer p_148837_1_) throws IOException + { + this.field_149172_a = p_148837_1_.func_150789_c(20); +- this.field_149171_b = new byte[p_148837_1_.readUnsignedShort()]; ++ this.field_149171_b = new byte[ByteBufUtils.readVarShort(p_148837_1_)]; + p_148837_1_.readBytes(this.field_149171_b); + } + + public void func_148840_b(PacketBuffer p_148840_1_) throws IOException + { + p_148840_1_.func_150785_a(this.field_149172_a); +- p_148840_1_.writeShort(this.field_149171_b.length); ++ ByteBufUtils.writeVarShort(p_148840_1_, this.field_149171_b.length); + p_148840_1_.writeBytes(this.field_149171_b); + } + diff --git a/src/main/java/cpw/mods/fml/common/network/ByteBufUtils.java b/src/main/java/cpw/mods/fml/common/network/ByteBufUtils.java index d8904b9d97..d5ebb58826 100644 --- a/src/main/java/cpw/mods/fml/common/network/ByteBufUtils.java +++ b/src/main/java/cpw/mods/fml/common/network/ByteBufUtils.java @@ -55,7 +55,38 @@ public class ByteBufUtils { return i; } + /** + * An extended length short. Used by custom payload packets to extend size. + * + * @param buf + * @return + */ + public static int readVarShort(ByteBuf buf) + { + int low = buf.readUnsignedShort(); + int high = 0; + if ((low & 0x8000) != 0) + { + low = low & 0x7FFF; + high = buf.readUnsignedByte(); + } + return ((high & 0xFF) << 15) | low; + } + public static void writeVarShort(ByteBuf buf, int toWrite) + { + int low = toWrite & 0x7FFF; + int high = ( toWrite & 0x7F8000 ) >> 15; + if (high != 0) + { + low = low | 0x8000; + } + buf.writeShort(low); + if (high != 0) + { + buf.writeByte(high); + } + } /** * Write an integer to the buffer using variable length encoding. The maxSize constrains * how many bytes (and therefore the maximum number) that will be written. diff --git a/src/test/java/cpw/mods/fml/test/TestNetStuff.java b/src/test/java/cpw/mods/fml/test/TestNetStuff.java index 4098aba0a4..31467019d1 100644 --- a/src/test/java/cpw/mods/fml/test/TestNetStuff.java +++ b/src/test/java/cpw/mods/fml/test/TestNetStuff.java @@ -120,4 +120,55 @@ public class TestNetStuff { assertArrayEquals("String repeat bytes", new byte[] {-112, 3, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, buf.array()); } + + @Test + public void testVarShort() + { + ByteBuf buf = Unpooled.buffer(3,3); + ByteBufUtils.writeVarShort(buf, 32766); + assertArrayEquals("Two byte short written", new byte[] { 127, -2, 0}, buf.array()); + assertEquals("Two byte short written", 2, buf.readableBytes()); + + buf.clear(); + buf.writeZero(3); + buf.clear(); + + buf.writeShort(32766); + assertArrayEquals("Two byte short written", new byte[] { 127, -2, 0}, buf.array()); + int val = ByteBufUtils.readVarShort(buf); + + assertEquals("Two byte short read correctly", 32766, val); + + buf.clear(); + buf.writeZero(3); + buf.clear(); + + ByteBufUtils.writeVarShort(buf, 32768); + assertArrayEquals("Three byte short written", new byte[] { -128, 0, 1}, buf.array()); + assertEquals("Three byte short written", 3, buf.readableBytes()); + + buf.clear(); + buf.writeZero(3); + buf.clear(); + buf.writeShort(-32768); + buf.writeByte(1); + val = ByteBufUtils.readVarShort(buf); + assertEquals("Three byte short read correctly", 32768, val); + + buf.clear(); + buf.writeZero(3); + buf.clear(); + + ByteBufUtils.writeVarShort(buf, 8388607); + assertArrayEquals("Three byte short written", new byte[] { -1, -1, -1}, buf.array()); + assertEquals("Three byte short written", 3, buf.readableBytes()); + + buf.clear(); + buf.writeZero(3); + buf.clear(); + buf.writeShort(-1); + buf.writeByte(-1); + val = ByteBufUtils.readVarShort(buf); + assertEquals("Three byte short read correctly", 8388607, val); + } }