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:
Ursprung
7a9b9afe2e
Commit
684b687e42
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren