mirror of
https://github.com/GeyserMC/MCProtocolLib.git
synced 2024-11-24 08:08:20 -05:00
Compare commits
5 commits
46897ebe63
...
896fe427a4
Author | SHA1 | Date | |
---|---|---|---|
|
896fe427a4 | ||
|
88188c5b39 | ||
|
f82aa5bc87 | ||
|
cb596f1105 | ||
|
c2795892fd |
4 changed files with 84 additions and 119 deletions
|
@ -9,135 +9,58 @@ public class BasePacketCodecHelper implements PacketCodecHelper {
|
|||
|
||||
@Override
|
||||
public void writeVarInt(ByteBuf buf, int value) {
|
||||
this.writeVarLong(buf, value & 0xFFFFFFFFL);
|
||||
while ((value & ~0x7F) != 0) {
|
||||
buf.writeByte(value & 0x7F | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
|
||||
buf.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readVarInt(ByteBuf buf) {
|
||||
int value = 0;
|
||||
int size = 0;
|
||||
int b;
|
||||
while (((b = buf.readByte()) & 0x80) == 0x80) {
|
||||
value |= (b & 0x7F) << (size++ * 7);
|
||||
if (size > 5) {
|
||||
throw new IllegalArgumentException("VarInt too long (length must be <= 5)");
|
||||
}
|
||||
}
|
||||
|
||||
return value | ((b & 0x7F) << (size * 7));
|
||||
byte b;
|
||||
do {
|
||||
if (size >= 35) {
|
||||
throw new RuntimeException("VarInt wider than 5 bytes");
|
||||
}
|
||||
b = buf.readByte();
|
||||
value |= (b & 0x7F) << size;
|
||||
size += 7;
|
||||
} while ((b & 0x80) == 0x80);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Based off of Andrew Steinborn's blog post:
|
||||
// https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
|
||||
@Override
|
||||
public void writeVarLong(ByteBuf buf, long value) {
|
||||
// Peel the one and two byte count cases explicitly as they are the most common VarInt sizes
|
||||
// that the server will write, to improve inlining.
|
||||
if ((value & ~0x7FL) == 0) {
|
||||
buf.writeByte((byte) value);
|
||||
} else if ((value & ~0x3FFFL) == 0) {
|
||||
int w = (int) ((value & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 7));
|
||||
buf.writeShort(w);
|
||||
} else {
|
||||
writeVarLongFull(buf, value);
|
||||
while ((value & ~0x7FL) != 0) {
|
||||
buf.writeByte((int) (value & 0x7F | 0x80));
|
||||
value >>>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeVarLongFull(ByteBuf buf, long value) {
|
||||
if ((value & ~0x7FL) == 0) {
|
||||
buf.writeByte((byte) value);
|
||||
} else if ((value & ~0x3FFFL) == 0) {
|
||||
int w = (int) ((value & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 7));
|
||||
buf.writeShort(w);
|
||||
} else if ((value & ~0x1FFFFFL) == 0) {
|
||||
int w = (int) ((value & 0x7FL | 0x80L) << 16 |
|
||||
((value >>> 7) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 14));
|
||||
buf.writeMedium(w);
|
||||
} else if ((value & ~0xFFFFFFFL) == 0) {
|
||||
int w = (int) ((value & 0x7F | 0x80) << 24 |
|
||||
(((value >>> 7) & 0x7F | 0x80) << 16) |
|
||||
((value >>> 14) & 0x7F | 0x80) << 8 |
|
||||
(value >>> 21));
|
||||
buf.writeInt(w);
|
||||
} else if ((value & ~0x7FFFFFFFFL) == 0) {
|
||||
int w = (int) ((value & 0x7F | 0x80) << 24 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 16 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 8 |
|
||||
((value >>> 21) & 0x7F | 0x80));
|
||||
buf.writeInt(w);
|
||||
buf.writeByte((int) (value >>> 28));
|
||||
} else if ((value & ~0x3FFFFFFFFFFL) == 0) {
|
||||
int w = (int) ((value & 0x7F | 0x80) << 24 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 16 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 8 |
|
||||
((value >>> 21) & 0x7F | 0x80));
|
||||
int w2 = (int) (((value >>> 28) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 35));
|
||||
buf.writeInt(w);
|
||||
buf.writeShort(w2);
|
||||
} else if ((value & ~0x1FFFFFFFFFFFFL) == 0) {
|
||||
int w = (int) ((value & 0x7F | 0x80) << 24 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 16 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 8 |
|
||||
((value >>> 21) & 0x7F | 0x80));
|
||||
int w2 = (int) ((((value >>> 28) & 0x7FL | 0x80L) << 16 |
|
||||
((value >>> 35) & 0x7FL | 0x80L) << 8) |
|
||||
(value >>> 42));
|
||||
buf.writeInt(w);
|
||||
buf.writeMedium(w2);
|
||||
} else if ((value & ~0xFFFFFFFFFFFFFFL) == 0) {
|
||||
long w = (value & 0x7F | 0x80) << 56 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 48 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 40 |
|
||||
((value >>> 21) & 0x7F | 0x80) << 32 |
|
||||
((value >>> 28) & 0x7FL | 0x80L) << 24 |
|
||||
((value >>> 35) & 0x7FL | 0x80L) << 16 |
|
||||
((value >>> 42) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 49);
|
||||
buf.writeLong(w);
|
||||
} else if ((value & ~0x7FFFFFFFFFFFFFFFL) == 0) {
|
||||
long w = (value & 0x7F | 0x80) << 56 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 48 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 40 |
|
||||
((value >>> 21) & 0x7F | 0x80) << 32 |
|
||||
((value >>> 28) & 0x7FL | 0x80L) << 24 |
|
||||
((value >>> 35) & 0x7FL | 0x80L) << 16 |
|
||||
((value >>> 42) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 49);
|
||||
buf.writeLong(w);
|
||||
buf.writeByte((byte) (value >>> 56));
|
||||
} else {
|
||||
long w = (value & 0x7F | 0x80) << 56 |
|
||||
((value >>> 7) & 0x7F | 0x80) << 48 |
|
||||
((value >>> 14) & 0x7F | 0x80) << 40 |
|
||||
((value >>> 21) & 0x7F | 0x80) << 32 |
|
||||
((value >>> 28) & 0x7FL | 0x80L) << 24 |
|
||||
((value >>> 35) & 0x7FL | 0x80L) << 16 |
|
||||
((value >>> 42) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 49);
|
||||
int w2 = (int) (((value >>> 56) & 0x7FL | 0x80L) << 8 |
|
||||
(value >>> 63));
|
||||
buf.writeLong(w);
|
||||
buf.writeShort(w2);
|
||||
}
|
||||
buf.writeByte((int) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readVarLong(ByteBuf buf) {
|
||||
int value = 0;
|
||||
long value = 0;
|
||||
int size = 0;
|
||||
int b;
|
||||
while (((b = buf.readByte()) & 0x80) == 0x80) {
|
||||
value |= (b & 0x7F) << (size++ * 7);
|
||||
if (size > 10) {
|
||||
throw new IllegalArgumentException("VarLong too long (length must be <= 10)");
|
||||
}
|
||||
}
|
||||
|
||||
return value | ((b & 0x7FL) << (size * 7));
|
||||
byte b;
|
||||
do {
|
||||
if (size >= 70) {
|
||||
throw new RuntimeException("VarLong wider than 10 bytes");
|
||||
}
|
||||
b = buf.readByte();
|
||||
value |= (b & 0x7FL) << size;
|
||||
size += 7;
|
||||
} while ((b & 0x80) == 0x80);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -86,7 +86,7 @@ public class DataComponentType<T> {
|
|||
public static final DataComponentType<List<ItemStack>> CONTAINER = new DataComponentType<>(listReader(ItemCodecHelper::readOptionalItemStack), listWriter(MinecraftCodecHelper::writeOptionalItemStack), ObjectDataComponent::new);
|
||||
public static final DataComponentType<BlockStateProperties> BLOCK_STATE = new DataComponentType<>(ItemCodecHelper::readBlockStateProperties, ItemCodecHelper::writeBlockStateProperties, ObjectDataComponent::new);
|
||||
public static final DataComponentType<List<BeehiveOccupant>> BEES = new DataComponentType<>(listReader(ItemCodecHelper::readBeehiveOccupant), listWriter(ItemCodecHelper::writeBeehiveOccupant), ObjectDataComponent::new);
|
||||
public static final DataComponentType<String> LOCK = new DataComponentType<>(ItemCodecHelper::readLock, ItemCodecHelper::writeLock, ObjectDataComponent::new);
|
||||
public static final DataComponentType<NbtMap> LOCK = new DataComponentType<>(ItemCodecHelper::readCompoundTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
|
||||
public static final DataComponentType<NbtMap> CONTAINER_LOOT = new DataComponentType<>(ItemCodecHelper::readCompoundTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
|
||||
|
||||
protected final int id;
|
||||
|
|
|
@ -637,12 +637,4 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
|
|||
this.writeVarInt(buf, occupant.getTicksInHive());
|
||||
this.writeVarInt(buf, occupant.getMinTicksInHive());
|
||||
}
|
||||
|
||||
public String readLock(ByteBuf buf) {
|
||||
return this.readAnyTag(buf, NbtType.STRING);
|
||||
}
|
||||
|
||||
public void writeLock(ByteBuf buf, String key) {
|
||||
this.writeAnyTag(buf, key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package org.geysermc.mcprotocollib.protocol.codec;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.geysermc.mcprotocollib.network.codec.BasePacketCodecHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class BasePacketCodecHelperTest {
|
||||
private static final BasePacketCodecHelper codecHelper = new BasePacketCodecHelper();
|
||||
|
||||
@Test
|
||||
public void readVarInt() {
|
||||
assertEquals(0x80808080, codecHelper.readVarInt(Unpooled.wrappedBuffer(new byte[]{
|
||||
(byte) 0x80, (byte) 0x81, (byte) 0x82, (byte) 0x84, (byte) 0x08
|
||||
})));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readVarIntTooLong() {
|
||||
try {
|
||||
// VarInt too long error should take precedence over IndexOutOfBoundsException
|
||||
codecHelper.readVarInt(Unpooled.wrappedBuffer(new byte[]{
|
||||
(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80
|
||||
}));
|
||||
} catch (RuntimeException ex) {
|
||||
// (assertThrow doesn't work as IndexOutOfBoundsException is also a RuntimeException)
|
||||
assertEquals("VarInt wider than 5 bytes", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readVarLong() {
|
||||
assertEquals(0x8080808080808080L, codecHelper.readVarLong(Unpooled.wrappedBuffer(new byte[]{
|
||||
(byte) 0x80, (byte) 0x81, (byte) 0x82, (byte) 0x84, (byte) 0x88, (byte) 0x90, (byte) 0xa0, (byte) 0xc0, (byte) 0x80, (byte) 0x01
|
||||
})));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readVarLongTooLong() {
|
||||
try {
|
||||
// VarLong too long error should take precedence over IndexOutOfBoundsException
|
||||
codecHelper.readVarLong(Unpooled.wrappedBuffer(new byte[]{
|
||||
(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80
|
||||
}));
|
||||
} catch (RuntimeException ex) {
|
||||
assertEquals("VarLong wider than 10 bytes", ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue