diff --git a/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java b/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java index 0d1f4de24..e6a5ae967 100644 --- a/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java +++ b/src/main/java/com/comphenix/protocol/utility/StreamSerializer.java @@ -10,7 +10,9 @@ import com.comphenix.protocol.injector.netty.NettyByteBufAdapter; import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.accessors.Accessors; +import com.comphenix.protocol.reflect.accessors.FieldAccessor; import com.comphenix.protocol.reflect.accessors.MethodAccessor; +import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtFactory; @@ -31,6 +33,7 @@ public class StreamSerializer { private static final StreamSerializer DEFAULT = new StreamSerializer(); // Cached methods + private static FieldAccessor STREAM_CODEC; private static MethodAccessor READ_ITEM_METHOD; private static MethodAccessor WRITE_ITEM_METHOD; @@ -235,14 +238,35 @@ public ItemStack deserializeItemStackFromByteArray(byte[] input) { Object serializer = MinecraftReflection.getPacketDataSerializer(buf); if (READ_ITEM_METHOD == null) { - READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection - .fromClass(serializer.getClass(), false) - .getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass())); + if (MinecraftVersion.v1_21_0.atOrAbove()) { + if (STREAM_CODEC == null) { + STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection + .fromClass(MinecraftReflection.getItemStackClass()) + .getFieldList(FuzzyFieldContract.newBuilder() + .typeExact(MinecraftReflection.getStreamCodecClass()) + .build()).get(1)); //skip OPTIONAL_STREAM_CODEC + } + + READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true) + .getMethod(FuzzyMethodContract.newBuilder() + .parameterExactType(MinecraftReflection.getRegistryFriendlyByteBufClass().get()) + .returnTypeExact(MinecraftReflection.getItemStackClass()) + .build())); + } else { + READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection + .fromClass(serializer.getClass(), false) + .getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass())); + } } try { // unwrap the item - Object nmsItem = READ_ITEM_METHOD.invoke(serializer); + Object nmsItem; + if (MinecraftVersion.v1_21_0.atOrAbove()) { + nmsItem = READ_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer); + } else { + nmsItem = READ_ITEM_METHOD.invoke(serializer); + } return nmsItem != null ? MinecraftReflection.getBukkitItemStack(nmsItem) : null; } finally { ReferenceCountUtil.safeRelease(buf); @@ -262,11 +286,26 @@ public ItemStack deserializeItemStackFromByteArray(byte[] input) { * @throws IOException If the operation fails due to reflection problems. */ public void serializeItemStack(DataOutputStream output, ItemStack stack) throws IOException { - // TODO this functionality was replaced by the CODEC field in the nms ItemStack if (WRITE_ITEM_METHOD == null) { - WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection - .fromClass(MinecraftReflection.getPacketDataSerializerClass(), true) - .getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass())); + if (MinecraftVersion.v1_21_0.atOrAbove()) { + if (STREAM_CODEC == null) { + STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection + .fromClass(MinecraftReflection.getItemStackClass()) + .getFieldList(FuzzyFieldContract.newBuilder() + .typeExact(MinecraftReflection.getStreamCodecClass()) + .build()).get(1)); //skip OPTIONAL_STREAM_CODEC + } + + WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true) + .getMethod(FuzzyMethodContract.newBuilder() + .parameterExactArray(MinecraftReflection.getRegistryFriendlyByteBufClass().get(), MinecraftReflection.getItemStackClass()) + .returnTypeExact(void.class) + .build())); + } else { + WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection + .fromClass(MinecraftReflection.getPacketDataSerializerClass(), true) + .getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass())); + } } ByteBuf buf = Unpooled.buffer(); @@ -274,7 +313,12 @@ public void serializeItemStack(DataOutputStream output, ItemStack stack) throws // Get the NMS version of the ItemStack and write it into the buffer Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack); - WRITE_ITEM_METHOD.invoke(serializer, nmsItem); + + if (MinecraftVersion.v1_21_0.atOrAbove()) { + WRITE_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer, nmsItem); + } else { + WRITE_ITEM_METHOD.invoke(serializer, nmsItem); + } // write the serialized content to the stream output.write(this.getBytesAndRelease(buf)); diff --git a/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java b/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java index 1d73f7c24..301ad6877 100644 --- a/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java +++ b/src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java @@ -60,7 +60,6 @@ public void testCompound() throws IOException { } @Test - @Disabled // TODO -- replaced with registry friendly bytebuf public void testItems() throws IOException { StreamSerializer serializer = new StreamSerializer(); ItemStack initial = new ItemStack(Material.STRING); @@ -72,7 +71,6 @@ public void testItems() throws IOException { } @Test - @Disabled // TODO -- replaced with registry friendly bytebuf public void testItemMeta() throws IOException { StreamSerializer serializer = new StreamSerializer(); ItemStack initial = new ItemStack(Material.BLUE_WOOL, 2);