From 588f7363481ddd93244e5407b21a0f8e1c37e8b4 Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Sat, 27 Aug 2016 13:07:49 -0400 Subject: [PATCH] Fix missing TileEntity write methods Fixes #249 --- .../wrappers/nbt/TileEntityAccessor.java | 53 ++++++++++--------- .../protocol/BukkitInitialization.java | 14 +++-- .../comphenix/protocol/PacketTypeTest.java | 19 +++++++ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/nbt/TileEntityAccessor.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/nbt/TileEntityAccessor.java index 9377fa0f..db3ffd80 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/nbt/TileEntityAccessor.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/nbt/TileEntityAccessor.java @@ -46,7 +46,7 @@ class TileEntityAccessor { private boolean writeDetected; private boolean readDetected; - private TileEntityAccessor() { + TileEntityAccessor() { // Do nothing } @@ -59,27 +59,30 @@ class TileEntityAccessor { if (tileEntityField != null) { this.tileEntityField = tileEntityField; Class type = tileEntityField.getField().getType(); - - // Possible read/write methods - try { - findMethodsUsingASM(); - } catch (IOException ex1) { - try { - // Much slower though - findMethodUsingCGLib(state); - } catch (Exception ex2) { - throw new RuntimeException("Cannot find read/write methods in " + type, ex2); - } - } - - // Ensure we found them - if (readCompound == null) - throw new RuntimeException("Unable to find read method in " + type); - if (writeCompound == null) - throw new RuntimeException("Unable to find write method in " + type); + findMethods(type, state); } } + void findMethods(Class type, T state) { + // Possible read/write methods + try { + findMethodsUsingASM(); + } catch (IOException ex1) { + try { + // Much slower though + findMethodUsingCGLib(state); + } catch (Exception ex2) { + throw new RuntimeException("Cannot find read/write methods in " + type, ex2); + } + } + + // Ensure we found them + if (readCompound == null) + throw new RuntimeException("Unable to find read method in " + type); + if (writeCompound == null) + throw new RuntimeException("Unable to find write method in " + type); + } + /** * Find the read/write methods in TileEntity. * @throws IOException If we cannot find these methods. @@ -90,7 +93,7 @@ class TileEntityAccessor { final ClassReader reader = new ClassReader(tileEntityClass.getCanonicalName()); final String tagCompoundName = getJarName(MinecraftReflection.getNBTCompoundClass()); - final String expectedDesc = "(L" + tagCompoundName + ";)V"; + final String expectedDesc = "(L" + tagCompoundName + ";)"; reader.accept(new EmptyClassVisitor() { @Override @@ -98,7 +101,7 @@ class TileEntityAccessor { final String methodName = name; // Detect read/write calls to NBTTagCompound - if (expectedDesc.equals(desc)) { + if (desc.startsWith(expectedDesc)) { return new EmptyMethodVisitor() { private int readMethods; private int writeMethods; @@ -106,9 +109,9 @@ class TileEntityAccessor { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { // This must be a virtual call on NBTTagCompound that accepts a String - if (opcode == Opcodes.INVOKEVIRTUAL && - tagCompoundName.equals(owner) && - desc.startsWith("(Ljava/lang/String")) { + if (opcode == Opcodes.INVOKEVIRTUAL + && tagCompoundName.equals(owner) + && desc.startsWith("(Ljava/lang/String")) { // Is this a write call? if (desc.endsWith(")V")) { @@ -126,10 +129,12 @@ class TileEntityAccessor { } else if (writeMethods > readMethods) { writeCompound = Accessors.getMethodAccessor(tileEntityClass, methodName, nbtCompoundClass); } + super.visitEnd(); } }; } + return null; } }, 0); diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java index 3ccc9ac7..4e365e79 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java @@ -24,6 +24,7 @@ import net.minecraft.server.v1_10_R1.DispenserRegistry; */ public class BukkitInitialization { private static boolean initialized; + private static boolean packaged; /** * Initialize Bukkit and ProtocolLib such that we can perfrom unit testing. @@ -34,6 +35,8 @@ public class BukkitInitialization { // Denote that we're done initialized = true; + initializePackage(); + DispenserRegistry.c(); // Basically registers everything // Mock the server object @@ -50,7 +53,7 @@ public class BukkitInitialization { // Inject this fake server Bukkit.setServer(mockedServer); - initializePackage(); + } } @@ -58,8 +61,11 @@ public class BukkitInitialization { * Ensure that package names are correctly set up. */ public static void initializePackage() { - // Initialize reflection - MinecraftReflection.setMinecraftPackage(Constants.NMS, Constants.OBC); - MinecraftVersion.setCurrentVersion(MinecraftVersion.COMBAT_UPDATE); + if (!packaged) { + packaged = true; + + MinecraftReflection.setMinecraftPackage(Constants.NMS, Constants.OBC); + MinecraftVersion.setCurrentVersion(MinecraftVersion.FROSTBURN_UPDATE); + } } } diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/PacketTypeTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/PacketTypeTest.java index bb947c3a..1eb0f462 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/PacketTypeTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/PacketTypeTest.java @@ -1,3 +1,19 @@ +/** + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2016 dmulloy2 + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ package com.comphenix.protocol; import static org.junit.Assert.assertEquals; @@ -16,6 +32,9 @@ import com.comphenix.protocol.injector.netty.ProtocolRegistry; import net.minecraft.server.v1_10_R1.PacketLoginInStart; +/** + * @author dmulloy2 + */ public class PacketTypeTest { @BeforeClass