AnvilInventoryWrapper8.java
package it.fulminazzo.yagl.inventory;
import it.fulminazzo.fulmicollection.objects.Refl;
import it.fulminazzo.yagl.util.NMSUtils;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* An implementation of {@link AnvilInventoryWrapper} with support for Minecraft 1.8.
*/
class AnvilInventoryWrapper8 extends AnvilInventoryWrapper {
/**
* Instantiates a new Anvil inventory wrapper.
*
* @param actualInventory the actual inventory
*/
public AnvilInventoryWrapper8(final @NotNull Inventory actualInventory) {
super(actualInventory);
}
@Override
public void open(@NotNull Player player) {
final @NotNull Refl<?> entityPlayer = NMSUtils.getHandle(player);
Refl<?> containerRefl = new Refl<>(NMSUtils.getCraftBukkitClass("inventory.CraftContainer"),
this.actualInventory,
player,
entityPlayer.invokeMethod("nextContainerCounter")
);
Object internalInventory = new Refl<>(this.actualInventory).invokeMethod("getInventory");
final @NotNull Class<?> slotClass = NMSUtils.getLegacyNMSClass("Slot");
List<Object> slots = containerRefl.getFieldObject(f -> checkFieldListOf(f, slotClass));
slots.add(new Refl<>(slotClass, internalInventory, 0, 27, 47).getObject());
slots.add(new Refl<>(slotClass, internalInventory, 1, 76, 47).getObject());
slots.add(new Refl<>(slotClass, internalInventory, 2, 134, 47).getObject());
setPlayerInventorySlots(player, containerRefl.getObject());
List<Object> itemStacks = containerRefl.getFieldObject(f ->
checkFieldListOf(f, NMSUtils.getLegacyNMSClass("ItemStack"))
);
for (int i = 0; i < this.actualInventory.getSize(); i++) {
ItemStack item = this.actualInventory.getItem(i);
if (item != null) itemStacks.add(NMSUtils.itemStackToNMS(item));
else itemStacks.add(null);
}
// Set player inventory items
for (int i = 0; i < player.getInventory().getSize(); i++)
itemStacks.add(null);
InventoryView view = containerRefl.invokeMethod("getBukkitView");
Object openWindowPacket = NMSUtils.newOpenWindowPacket(
containerRefl.getObject(),
containerRefl.getFieldObject("windowId"),
view.getTitle(),
this.actualInventory
);
NMSUtils.sendPacket(player, openWindowPacket);
// Set fields
entityPlayer.setFieldObject("activeContainer", containerRefl.getObject());
containerRefl.invokeMethod("addSlotListener", entityPlayer.getObject());
}
/**
* Sets the corresponding {@link Player#getInventory()} slots in the specified container.
*
* @param player the player
* @param container the container
*/
static void setPlayerInventorySlots(final @NotNull Player player,
final @NotNull Object container) {
final @NotNull Class<?> slotClass = NMSUtils.getLegacyNMSClass("Slot");
List<Object> slots = new Refl<>(container).getFieldObject(f -> checkFieldListOf(f, slotClass));
Object bottomInventory = new Refl<>(player.getInventory()).invokeMethod("getInventory");
// Set storage slots
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 9; col++) {
Object slot = new Refl<>(slotClass,
bottomInventory,
col + row * 9 + 9, 8 + col * 18, 31 + row * 18
).getObject();
slots.add(slot);
}
}
// Set hotbar contents
for (int col = 0; col < 9; col++) {
Object slot = new Refl<>(slotClass,
bottomInventory,
col, 8 + col * 18, 89
).getObject();
slots.add(slot);
}
}
/**
* Checks if the given field is a {@link List} containing elements of the specified class.
*
* @param field the field
* @param clazz the class
* @return true if it is
*/
static boolean checkFieldListOf(final @NotNull Field field, final @NotNull Class<?> clazz) {
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
Type parameterType = ((ParameterizedType) type).getActualTypeArguments()[0];
return parameterType.equals(clazz);
}
return false;
}
}