Revert changes to ItemStack handling, fix StreamSerializer
Dieser Commit ist enthalten in:
Ursprung
47632e1fb1
Commit
f825acb4d6
@ -49,6 +49,7 @@ import com.comphenix.protocol.ProtocolLibrary;
|
|||||||
import com.comphenix.protocol.error.ErrorReporter;
|
import com.comphenix.protocol.error.ErrorReporter;
|
||||||
import com.comphenix.protocol.error.Report;
|
import com.comphenix.protocol.error.Report;
|
||||||
import com.comphenix.protocol.error.ReportType;
|
import com.comphenix.protocol.error.ReportType;
|
||||||
|
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||||
import com.comphenix.protocol.reflect.ClassAnalyser;
|
import com.comphenix.protocol.reflect.ClassAnalyser;
|
||||||
import com.comphenix.protocol.reflect.ClassAnalyser.AsmMethod;
|
import com.comphenix.protocol.reflect.ClassAnalyser.AsmMethod;
|
||||||
@ -126,6 +127,15 @@ public class MinecraftReflection {
|
|||||||
// The NMS version
|
// The NMS version
|
||||||
private static String packageVersion;
|
private static String packageVersion;
|
||||||
|
|
||||||
|
// Item stacks
|
||||||
|
private static Method craftNMSMethod;
|
||||||
|
private static Method craftBukkitNMS;
|
||||||
|
private static Method craftBukkitOBC;
|
||||||
|
private static boolean craftItemStackFailed;
|
||||||
|
|
||||||
|
private static Constructor<?> craftNMSConstructor;
|
||||||
|
private static Constructor<?> craftBukkitConstructor;
|
||||||
|
|
||||||
// net.minecraft.server
|
// net.minecraft.server
|
||||||
private static Class<?> itemStackArrayClass;
|
private static Class<?> itemStackArrayClass;
|
||||||
|
|
||||||
@ -1746,50 +1756,119 @@ public class MinecraftReflection {
|
|||||||
return getArrayClass(getMultiBlockChangeInfoClass());
|
return getArrayClass(getMultiBlockChangeInfoClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodAccessor asCraftMirror;
|
|
||||||
private static MethodAccessor asCraftCopy;
|
|
||||||
private static MethodAccessor asNMSCopy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a CraftItemStack from a given NMS ItemStack.
|
|
||||||
*
|
|
||||||
* @param nmsItem - the NMS ItemStack to convert.
|
|
||||||
* @return A CraftItemStack as a NMS ItemStack.
|
|
||||||
*/
|
|
||||||
public static ItemStack getBukkitItemStack(Object nmsItem) {
|
|
||||||
if (asCraftMirror == null) {
|
|
||||||
asCraftMirror = Accessors.getMethodAccessor(getCraftItemStackClass(), "asCraftMirror", getItemStackClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ItemStack) asCraftMirror.invoke(null, nmsItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a CraftItemStack from a given ItemStack.
|
* Retrieve a CraftItemStack from a given ItemStack.
|
||||||
*
|
* @param bukkitItemStack - the Bukkit ItemStack to convert.
|
||||||
* @param stack - the Bukkit ItemStack to convert.
|
|
||||||
* @return A CraftItemStack as an ItemStack.
|
* @return A CraftItemStack as an ItemStack.
|
||||||
*/
|
*/
|
||||||
public static ItemStack getCraftItemStack(ItemStack stack) {
|
public static ItemStack getBukkitItemStack(ItemStack bukkitItemStack) {
|
||||||
if (asCraftCopy == null) {
|
// Delegate this task to the method that can execute it
|
||||||
asCraftCopy = Accessors.getMethodAccessor(getCraftItemStackClass(), "asCraftCopy", ItemStack.class);
|
if (craftBukkitNMS != null)
|
||||||
|
return getBukkitItemByMethod(bukkitItemStack);
|
||||||
|
|
||||||
|
if (craftBukkitConstructor == null) {
|
||||||
|
try {
|
||||||
|
craftBukkitConstructor = getCraftItemStackClass().getConstructor(ItemStack.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// See if this method works
|
||||||
|
if (!craftItemStackFailed)
|
||||||
|
return getBukkitItemByMethod(bukkitItemStack);
|
||||||
|
|
||||||
|
throw new RuntimeException("Cannot find CraftItemStack(org.bukkit.inventory.ItemStack).", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ItemStack) asCraftCopy.invoke(null, stack);
|
// Try to create the CraftItemStack
|
||||||
|
try {
|
||||||
|
return (ItemStack) craftBukkitConstructor.newInstance(bukkitItemStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot construct CraftItemStack.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack getBukkitItemByMethod(ItemStack bukkitItemStack) {
|
||||||
|
if (craftBukkitNMS == null) {
|
||||||
|
try {
|
||||||
|
craftBukkitNMS = getCraftItemStackClass().getMethod("asNMSCopy", ItemStack.class);
|
||||||
|
craftBukkitOBC = getCraftItemStackClass().getMethod("asCraftMirror", MinecraftReflection.getItemStackClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
craftItemStackFailed = true;
|
||||||
|
throw new RuntimeException("Cannot find CraftItemStack.asCraftCopy(org.bukkit.inventory.ItemStack).", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, construct it
|
||||||
|
try {
|
||||||
|
Object nmsItemStack = craftBukkitNMS.invoke(null, bukkitItemStack);
|
||||||
|
return (ItemStack) craftBukkitOBC.invoke(null, nmsItemStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot construct CraftItemStack.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the NMS ItemStack from a given ItemStack.
|
* Retrieve the Bukkit ItemStack from a given net.minecraft.server ItemStack.
|
||||||
*
|
* @param minecraftItemStack - the NMS ItemStack to wrap.
|
||||||
* @param stack - the ItemStack to convert.
|
* @return The wrapped ItemStack.
|
||||||
* @return The NMS ItemStack.
|
|
||||||
*/
|
*/
|
||||||
public static Object getMinecraftItemStack(ItemStack stack) {
|
public static ItemStack getBukkitItemStack(Object minecraftItemStack) {
|
||||||
if (asNMSCopy == null) {
|
// Delegate this task to the method that can execute it
|
||||||
asNMSCopy = Accessors.getMethodAccessor(getCraftItemStackClass(), "asNMSCopy", ItemStack.class);
|
if (craftNMSMethod != null)
|
||||||
|
return getBukkitItemByMethod(minecraftItemStack);
|
||||||
|
|
||||||
|
if (craftNMSConstructor == null) {
|
||||||
|
try {
|
||||||
|
craftNMSConstructor = getCraftItemStackClass().getConstructor(minecraftItemStack.getClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Give it a try
|
||||||
|
if (!craftItemStackFailed)
|
||||||
|
return getBukkitItemByMethod(minecraftItemStack);
|
||||||
|
|
||||||
|
throw new RuntimeException("Cannot find CraftItemStack(net.minecraft.server.ItemStack).", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return asNMSCopy.invoke(null, stack);
|
// Try to create the CraftItemStack
|
||||||
|
try {
|
||||||
|
return (ItemStack) craftNMSConstructor.newInstance(minecraftItemStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot construct CraftItemStack.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack getBukkitItemByMethod(Object minecraftItemStack) {
|
||||||
|
if (craftNMSMethod == null) {
|
||||||
|
try {
|
||||||
|
craftNMSMethod = getCraftItemStackClass().getMethod("asCraftMirror", minecraftItemStack.getClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
craftItemStackFailed = true;
|
||||||
|
throw new RuntimeException("Cannot find CraftItemStack.asCraftMirror(net.minecraft.server.ItemStack).", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, construct it
|
||||||
|
try {
|
||||||
|
return (ItemStack) craftNMSMethod.invoke(null, minecraftItemStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot construct CraftItemStack.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the net.minecraft.server ItemStack from a Bukkit ItemStack.
|
||||||
|
* <p>
|
||||||
|
* By convention, item stacks that contain air are usually represented as NULL.
|
||||||
|
*
|
||||||
|
* @param stack - the Bukkit ItemStack to convert.
|
||||||
|
* @return The NMS ItemStack, or NULL if the stack represents air.
|
||||||
|
*/
|
||||||
|
public static Object getMinecraftItemStack(ItemStack stack) {
|
||||||
|
// Make sure this is a CraftItemStack
|
||||||
|
if (!isCraftItemStack(stack))
|
||||||
|
stack = getBukkitItemStack(stack);
|
||||||
|
|
||||||
|
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||||
|
return unwrapper.unwrapItem(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,12 +14,14 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||||
|
|
||||||
import com.comphenix.protocol.compat.netty.Netty;
|
import com.comphenix.protocol.compat.netty.Netty;
|
||||||
|
import com.comphenix.protocol.compat.netty.WrappedByteBuf;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||||
|
import com.comphenix.protocol.wrappers.nbt.NbtType;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,7 +310,10 @@ public class StreamSerializer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_NBT_METHOD.invoke(Netty.packetWriter(output).getHandle(), handle);
|
WrappedByteBuf buf = Netty.packetWriter(output);
|
||||||
|
buf.writeByte(NbtType.TAG_COMPOUND.getRawID());
|
||||||
|
|
||||||
|
WRITE_NBT_METHOD.invoke(buf.getHandle(), handle);
|
||||||
} else {
|
} else {
|
||||||
if (WRITE_NBT_METHOD == null) {
|
if (WRITE_NBT_METHOD == null) {
|
||||||
WRITE_NBT_METHOD = Accessors.getMethodAccessor(
|
WRITE_NBT_METHOD = Accessors.getMethodAccessor(
|
||||||
|
@ -18,11 +18,14 @@ import org.junit.runner.RunWith;
|
|||||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||||
|
|
||||||
import com.comphenix.protocol.BukkitInitialization;
|
import com.comphenix.protocol.BukkitInitialization;
|
||||||
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
|
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||||
|
|
||||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||||
//@PrepareForTest(CraftItemFactory.class)
|
//@PrepareForTest(CraftItemFactory.class)
|
||||||
public class StreamSerializerTest {
|
public class StreamSerializerTest {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void initializeBukkit() throws IllegalAccessException {
|
public static void initializeBukkit() throws IllegalAccessException {
|
||||||
BukkitInitialization.initializeItemMeta();
|
BukkitInitialization.initializeItemMeta();
|
||||||
@ -61,17 +64,15 @@ public class StreamSerializerTest {
|
|||||||
assertEquals(initial, deserialized);
|
assertEquals(initial, deserialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO This is an actual issue, probably need to fix the NBT API
|
|
||||||
// For future reference, items are saved in the ChunkRegionLoader and TileEntityChest
|
// For future reference, items are saved in the ChunkRegionLoader and TileEntityChest
|
||||||
|
|
||||||
/* @Test
|
@Test
|
||||||
public void testCompound() throws IOException {
|
public void testCompound() throws IOException {
|
||||||
StreamSerializer serializer = new StreamSerializer();
|
StreamSerializer serializer = new StreamSerializer();
|
||||||
NbtCompound initial = NbtFactory.ofCompound("tag");
|
NbtCompound initial = NbtFactory.ofCompound("tag");
|
||||||
initial.put("name", "Ole");
|
initial.put("name", "Ole");
|
||||||
initial.put("age", 20);
|
initial.put("age", 20);
|
||||||
|
|
||||||
// Buffer
|
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
serializer.serializeCompound(new DataOutputStream(buffer), initial);
|
serializer.serializeCompound(new DataOutputStream(buffer), initial);
|
||||||
|
|
||||||
@ -80,5 +81,20 @@ public class StreamSerializerTest {
|
|||||||
NbtCompound deserialized = serializer.deserializeCompound(input);
|
NbtCompound deserialized = serializer.deserializeCompound(input);
|
||||||
|
|
||||||
assertEquals(initial, deserialized);
|
assertEquals(initial, deserialized);
|
||||||
} */
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testItems() throws IOException {
|
||||||
|
StreamSerializer serializer = new StreamSerializer();
|
||||||
|
ItemStack initial = new ItemStack(Material.STRING);
|
||||||
|
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
serializer.serializeItemStack(new DataOutputStream(buffer), initial);
|
||||||
|
|
||||||
|
DataInputStream input = new DataInputStream(
|
||||||
|
new ByteArrayInputStream(buffer.toByteArray()));
|
||||||
|
ItemStack deserialized = serializer.deserializeItemStack(input);
|
||||||
|
|
||||||
|
assertEquals(initial, deserialized);
|
||||||
|
}
|
||||||
}
|
}
|
@ -26,12 +26,16 @@ import java.io.DataInputStream;
|
|||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_8_R3.ItemStack;
|
||||||
|
import net.minecraft.server.v1_8_R3.Items;
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||||
|
|
||||||
import com.comphenix.protocol.BukkitInitialization;
|
import com.comphenix.protocol.BukkitInitialization;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
|
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
|
||||||
|
|
||||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||||
@ -65,9 +69,7 @@ public class NbtFactoryTest {
|
|||||||
assertEquals(compound.getList("nicknames"), cloned.getList("nicknames"));
|
assertEquals(compound.getList("nicknames"), cloned.getList("nicknames"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO See StreamSerializerTest
|
@Test
|
||||||
|
|
||||||
/* @Test
|
|
||||||
public void testItemTag() {
|
public void testItemTag() {
|
||||||
ItemStack test = new ItemStack(Items.GOLDEN_AXE);
|
ItemStack test = new ItemStack(Items.GOLDEN_AXE);
|
||||||
org.bukkit.inventory.ItemStack craftTest = MinecraftReflection.getBukkitItemStack(test);
|
org.bukkit.inventory.ItemStack craftTest = MinecraftReflection.getBukkitItemStack(test);
|
||||||
@ -79,5 +81,5 @@ public class NbtFactoryTest {
|
|||||||
NbtFactory.setItemTag(craftTest, compound);
|
NbtFactory.setItemTag(craftTest, compound);
|
||||||
|
|
||||||
assertEquals(compound, NbtFactory.fromItemTag(craftTest));
|
assertEquals(compound, NbtFactory.fromItemTag(craftTest));
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren