package com.supaham.commons.bukkit;
import com.google.common.base.Preconditions;
import com.supaham.commons.bukkit.utils.ReflectionUtils.PackageType;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A class that adds the possibility to create an {@link ItemMeta} from an old {@link ItemMeta} for
* a specific {@link Material}. This class reflects the {@code org.bukkit.craftbukkit} {@link
* ItemFactory} which contains the implementation of said feature.
*
* @since 0.1
*/
public class ItemMetaCopyCat {
private static Method getItemMetaMethod;
static {
try {
ItemFactory itemFactory = Bukkit.getItemFactory();
Class<?> clazz = PackageType.CRAFTBUKKIT.getClass("inventory.CraftMetaItem");
getItemMetaMethod = itemFactory.getClass().getDeclaredMethod("getItemMeta",
Material.class, clazz);
getItemMetaMethod.setAccessible(true);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* Creates an {@link ItemMeta} from an old {@link ItemMeta} for a specific {@link Material}. If
* the new type does not support some of the old item meta, it will be ignored.
* <p />
* A case where item meta would not be supported is if the given item meta is of type
* {@link BookMeta} but the given {@link Material} is something other than a book, such as a dirt
* block. Everything but the {@link BookMeta} would be copied.
*
* @param material material to create new item meta for
* @param readFrom old item meta to write to new item meta
*
* @return new item meta
*
* @throws CommonBukkitException thrown if an error occurred during the copying process.
*/
@Nullable
public static ItemMeta copy(@Nonnull Material material, @Nonnull ItemMeta readFrom)
throws CommonBukkitException {
Preconditions.checkNotNull(material, "material cannot be null.");
Preconditions.checkNotNull(readFrom, "item meta cannot be null.");
if (getItemMetaMethod == null) {
throw new UnsupportedOperationException("Reflection initialization failed.");
}
try {
return ((ItemMeta) getItemMetaMethod.invoke(Bukkit.getItemFactory(), material, readFrom));
} catch (IllegalAccessException | InvocationTargetException e) {
throw ((CommonBukkitException)
new CommonBukkitException("Failed to create ItemMeta out of material " + material)
.initCause(e));
}
}
}