Skip to content

Commit c9ee2f1

Browse files
authored
Fix serializing and deserializing of ItemStack on 1.21 (#3217)
1 parent 7f61537 commit c9ee2f1

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

src/main/java/com/comphenix/protocol/utility/StreamSerializer.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import com.comphenix.protocol.injector.netty.NettyByteBufAdapter;
1111
import com.comphenix.protocol.reflect.FuzzyReflection;
1212
import com.comphenix.protocol.reflect.accessors.Accessors;
13+
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
1314
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
15+
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
1416
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
1517
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
1618
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
@@ -31,6 +33,7 @@ public class StreamSerializer {
3133
private static final StreamSerializer DEFAULT = new StreamSerializer();
3234

3335
// Cached methods
36+
private static FieldAccessor STREAM_CODEC;
3437
private static MethodAccessor READ_ITEM_METHOD;
3538
private static MethodAccessor WRITE_ITEM_METHOD;
3639

@@ -235,14 +238,35 @@ public ItemStack deserializeItemStackFromByteArray(byte[] input) {
235238
Object serializer = MinecraftReflection.getPacketDataSerializer(buf);
236239

237240
if (READ_ITEM_METHOD == null) {
238-
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
239-
.fromClass(serializer.getClass(), false)
240-
.getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass()));
241+
if (MinecraftVersion.v1_21_0.atOrAbove()) {
242+
if (STREAM_CODEC == null) {
243+
STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection
244+
.fromClass(MinecraftReflection.getItemStackClass())
245+
.getFieldList(FuzzyFieldContract.newBuilder()
246+
.typeExact(MinecraftReflection.getStreamCodecClass())
247+
.build()).get(1)); //skip OPTIONAL_STREAM_CODEC
248+
}
249+
250+
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true)
251+
.getMethod(FuzzyMethodContract.newBuilder()
252+
.parameterExactType(MinecraftReflection.getRegistryFriendlyByteBufClass().get())
253+
.returnTypeExact(MinecraftReflection.getItemStackClass())
254+
.build()));
255+
} else {
256+
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
257+
.fromClass(serializer.getClass(), false)
258+
.getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass()));
259+
}
241260
}
242261

243262
try {
244263
// unwrap the item
245-
Object nmsItem = READ_ITEM_METHOD.invoke(serializer);
264+
Object nmsItem;
265+
if (MinecraftVersion.v1_21_0.atOrAbove()) {
266+
nmsItem = READ_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer);
267+
} else {
268+
nmsItem = READ_ITEM_METHOD.invoke(serializer);
269+
}
246270
return nmsItem != null ? MinecraftReflection.getBukkitItemStack(nmsItem) : null;
247271
} finally {
248272
ReferenceCountUtil.safeRelease(buf);
@@ -262,19 +286,39 @@ public ItemStack deserializeItemStackFromByteArray(byte[] input) {
262286
* @throws IOException If the operation fails due to reflection problems.
263287
*/
264288
public void serializeItemStack(DataOutputStream output, ItemStack stack) throws IOException {
265-
// TODO this functionality was replaced by the CODEC field in the nms ItemStack
266289
if (WRITE_ITEM_METHOD == null) {
267-
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
268-
.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true)
269-
.getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass()));
290+
if (MinecraftVersion.v1_21_0.atOrAbove()) {
291+
if (STREAM_CODEC == null) {
292+
STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection
293+
.fromClass(MinecraftReflection.getItemStackClass())
294+
.getFieldList(FuzzyFieldContract.newBuilder()
295+
.typeExact(MinecraftReflection.getStreamCodecClass())
296+
.build()).get(1)); //skip OPTIONAL_STREAM_CODEC
297+
}
298+
299+
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true)
300+
.getMethod(FuzzyMethodContract.newBuilder()
301+
.parameterExactArray(MinecraftReflection.getRegistryFriendlyByteBufClass().get(), MinecraftReflection.getItemStackClass())
302+
.returnTypeExact(void.class)
303+
.build()));
304+
} else {
305+
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
306+
.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true)
307+
.getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass()));
308+
}
270309
}
271310

272311
ByteBuf buf = Unpooled.buffer();
273312
Object serializer = MinecraftReflection.getPacketDataSerializer(buf);
274313

275314
// Get the NMS version of the ItemStack and write it into the buffer
276315
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
277-
WRITE_ITEM_METHOD.invoke(serializer, nmsItem);
316+
317+
if (MinecraftVersion.v1_21_0.atOrAbove()) {
318+
WRITE_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer, nmsItem);
319+
} else {
320+
WRITE_ITEM_METHOD.invoke(serializer, nmsItem);
321+
}
278322

279323
// write the serialized content to the stream
280324
output.write(this.getBytesAndRelease(buf));

src/test/java/com/comphenix/protocol/utility/StreamSerializerTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public void testCompound() throws IOException {
6060
}
6161

6262
@Test
63-
@Disabled // TODO -- replaced with registry friendly bytebuf
6463
public void testItems() throws IOException {
6564
StreamSerializer serializer = new StreamSerializer();
6665
ItemStack initial = new ItemStack(Material.STRING);
@@ -72,7 +71,6 @@ public void testItems() throws IOException {
7271
}
7372

7473
@Test
75-
@Disabled // TODO -- replaced with registry friendly bytebuf
7674
public void testItemMeta() throws IOException {
7775
StreamSerializer serializer = new StreamSerializer();
7876
ItemStack initial = new ItemStack(Material.BLUE_WOOL, 2);

0 commit comments

Comments
 (0)