Archiviert
13
0

Rework ItemStack handling for 1.11

Note to developers: You should never supply a null ItemStack to any
method. ProtocolLib will never return a null ItemStack. Update your
plugins accordingly.
Dieser Commit ist enthalten in:
Dan Mulloy 2016-11-20 16:29:23 -05:00
Ursprung 7a9b9afe2e
Commit 684b687e42
2 geänderte Dateien mit 106 neuen und 14 gelöschten Zeilen

Datei anzeigen

@ -41,6 +41,7 @@ import java.util.regex.Pattern;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -128,13 +129,13 @@ public class MinecraftReflection {
private static String packageVersion; private static String packageVersion;
// Item stacks // Item stacks
private static Method craftNMSMethod; /* private static Method craftNMSMethod;
private static Method craftBukkitNMS; private static Method craftBukkitNMS;
private static Method craftBukkitOBC; private static Method craftBukkitOBC;
private static boolean craftItemStackFailed; private static boolean craftItemStackFailed;
private static Constructor<?> craftNMSConstructor; private static Constructor<?> craftNMSConstructor;
private static Constructor<?> craftBukkitConstructor; private static Constructor<?> craftBukkitConstructor; */
// net.minecraft.server // net.minecraft.server
private static Class<?> itemStackArrayClass; private static Class<?> itemStackArrayClass;
@ -1840,7 +1841,7 @@ public class MinecraftReflection {
* @param bukkitItemStack - the Bukkit ItemStack to convert. * @param bukkitItemStack - the Bukkit ItemStack to convert.
* @return A CraftItemStack as an ItemStack. * @return A CraftItemStack as an ItemStack.
*/ */
public static ItemStack getBukkitItemStack(ItemStack bukkitItemStack) { /* public static ItemStack getBukkitItemStack(ItemStack bukkitItemStack) {
// Delegate this task to the method that can execute it // Delegate this task to the method that can execute it
if (craftBukkitNMS != null) if (craftBukkitNMS != null)
return getBukkitItemByMethod(bukkitItemStack); return getBukkitItemByMethod(bukkitItemStack);
@ -1890,7 +1891,7 @@ public class MinecraftReflection {
* @param minecraftItemStack - the NMS ItemStack to wrap. * @param minecraftItemStack - the NMS ItemStack to wrap.
* @return The wrapped ItemStack. * @return The wrapped ItemStack.
*/ */
public static ItemStack getBukkitItemStack(Object minecraftItemStack) { /* public static ItemStack getBukkitItemStack(Object minecraftItemStack) {
// Delegate this task to the method that can execute it // Delegate this task to the method that can execute it
if (craftNMSMethod != null) if (craftNMSMethod != null)
return getBukkitItemByMethod(minecraftItemStack); return getBukkitItemByMethod(minecraftItemStack);
@ -1941,13 +1942,104 @@ public class MinecraftReflection {
* @param stack - the Bukkit ItemStack to convert. * @param stack - the Bukkit ItemStack to convert.
* @return The NMS ItemStack, or NULL if the stack represents air. * @return The NMS ItemStack, or NULL if the stack represents air.
*/ */
public static Object getMinecraftItemStack(ItemStack stack) { /* public static Object getMinecraftItemStack(ItemStack stack) {
// Make sure this is a CraftItemStack // Make sure this is a CraftItemStack
if (!isCraftItemStack(stack)) if (!isCraftItemStack(stack))
stack = getBukkitItemStack(stack); stack = getBukkitItemStack(stack);
BukkitUnwrapper unwrapper = new BukkitUnwrapper(); BukkitUnwrapper unwrapper = new BukkitUnwrapper();
return unwrapper.unwrapItem(stack); return unwrapper.unwrapItem(stack);
} */
// ---- ItemStack conversions
private static Method asNMSCopy = null;
private static Method asCraftMirror = null;
private static Boolean nullEnforced = null;
private static Method isEmpty = null;
/**
* Retrieves the Bukkit equivalent of a NMS ItemStack. This method should
* preserve NBT data and will never return null when supplied with a valid
* ItemStack. Empty ItemStacks are returned as AIR.
*
* @param generic NMS ItemStack
* @return The Bukkit equivalent
*/
public static ItemStack getBukkitItemStack(Object generic) {
// Make sure it actually is an ItemStack
if (!is(getItemStackClass(), generic)) {
return null;
}
// Convert null to AIR
if (generic == null) {
return new ItemStack(Material.AIR);
}
// Check null enforcement
try {
if (nullEnforced == null) {
isEmpty = getItemStackClass().getMethod("isEmpty");
nullEnforced = true;
}
if (nullEnforced) {
if ((boolean) isEmpty.invoke(generic)) {
return new ItemStack(Material.AIR);
}
}
} catch (ReflectiveOperationException ex) {
nullEnforced = false;
}
// Find asCraftMirror
if (asCraftMirror == null) {
try {
asCraftMirror = getCraftItemStackClass().getMethod("asCraftMirror", getItemStackClass());
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to obtain CraftItemStack.asCraftMirror", ex);
}
}
// Convert to a craft mirror to preserve NBT data
try {
return (ItemStack) asCraftMirror.invoke(nullEnforced, generic);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to obtain craft mirror of " + generic, ex);
}
}
/**
* Retrieves the NMS equivalent of a Bukkit ItemStack. This method will
* never return null and should preserve NBT data. Null inputs are treated
* as empty (AIR) ItemStacks.
*
* @param specific Bukkit ItemStack
* @return The NMS equivalent
*/
public static Object getMinecraftItemStack(ItemStack specific) {
// Grab asNMSCopy first
if (asNMSCopy == null) {
try {
asNMSCopy = getCraftItemStackClass().getMethod("asNMSCopy", ItemStack.class);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to obtain CraftItemStack.asNMSCopy", ex);
}
}
// If it's already a CraftItemStack, use its handle
if (is(getCraftItemStackClass(), specific)) {
return new BukkitUnwrapper().unwrapItem(specific);
}
// If it's not, grab a NMS copy
try {
return asNMSCopy.invoke(null, specific);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to make NMS copy of " + specific, ex);
}
} }
/** /**

Datei anzeigen

@ -713,24 +713,24 @@ public class BukkitConverters {
* @return Item stack converter. * @return Item stack converter.
*/ */
public static EquivalentConverter<ItemStack> getItemStackConverter() { public static EquivalentConverter<ItemStack> getItemStackConverter() {
return new IgnoreNullConverter<ItemStack>() { return new EquivalentConverter<ItemStack>() {
@Override @Override
protected Object getGenericValue(Class<?> genericType, ItemStack specific) { public ItemStack getSpecific(Object generic) {
return MinecraftReflection.getMinecraftItemStack(specific);
}
@Override
protected ItemStack getSpecificValue(Object generic) {
return MinecraftReflection.getBukkitItemStack(generic); return MinecraftReflection.getBukkitItemStack(generic);
} }
@Override
public Object getGeneric(Class<?> genericType, ItemStack specific) {
return MinecraftReflection.getMinecraftItemStack(specific);
}
@Override @Override
public Class<ItemStack> getSpecificType() { public Class<ItemStack> getSpecificType() {
return ItemStack.class; return ItemStack.class;
} }
}; };
} }
/** /**
* Retrieve the converter for the ServerPing packet in {@link PacketType.Status.Server#OUT_SERVER_INFO}. * Retrieve the converter for the ServerPing packet in {@link PacketType.Status.Server#OUT_SERVER_INFO}.
* @return Server ping converter. * @return Server ping converter.