#1049: Add MenuType API

By: Miles Holder <mwholder2005@gmail.com>
This commit is contained in:
Bukkit/Spigot 2024-09-07 18:51:55 +10:00
parent aae72268cb
commit f585e110be
3 changed files with 258 additions and 33 deletions

View File

@ -27,6 +27,7 @@ import org.bukkit.entity.memory.MemoryKey;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemType;
import org.bukkit.inventory.MenuType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.bukkit.loot.LootTables;
@ -173,6 +174,13 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @see Material
*/
Registry<Material> MATERIAL = new SimpleRegistry<>(Material.class, (mat) -> !mat.isLegacy());
/**
* Server menus.
*
* @see MenuType
*/
@ApiStatus.Experimental
Registry<MenuType> MENU = Objects.requireNonNull(Bukkit.getRegistry(MenuType.class), "No registry present for MenuType. This is a bug.");
/**
* Server mob effects.
*

View File

@ -1,8 +1,10 @@
package org.bukkit.event.inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.MenuType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents the different kinds of inventories available in Bukkit.
@ -26,148 +28,150 @@ public enum InventoryType {
* A chest inventory, with 0, 9, 18, 27, 36, 45, or 54 slots of type
* CONTAINER.
*/
CHEST(27, "Chest"),
CHEST(27, "Chest", MenuType.GENERIC_9X3),
/**
* A dispenser inventory, with 9 slots of type CONTAINER.
*/
DISPENSER(9, "Dispenser"),
DISPENSER(9, "Dispenser", MenuType.GENERIC_3X3),
/**
* A dropper inventory, with 9 slots of type CONTAINER.
*/
DROPPER(9, "Dropper"),
DROPPER(9, "Dropper", MenuType.GENERIC_3X3),
/**
* A furnace inventory, with a RESULT slot, a CRAFTING slot, and a FUEL
* slot.
*/
FURNACE(3, "Furnace"),
FURNACE(3, "Furnace", MenuType.FURNACE),
/**
* A workbench inventory, with 9 CRAFTING slots and a RESULT slot.
*/
WORKBENCH(10, "Crafting"),
WORKBENCH(10, "Crafting", MenuType.CRAFTING),
/**
* A player's crafting inventory, with 4 CRAFTING slots and a RESULT slot.
* Also implies that the 4 ARMOR slots are accessible.
*/
CRAFTING(5, "Crafting", false),
CRAFTING(5, "Crafting", null, false),
/**
* An enchantment table inventory, with two CRAFTING slots and three
* enchanting buttons.
*/
ENCHANTING(2, "Enchanting"),
ENCHANTING(2, "Enchanting", MenuType.ENCHANTMENT),
/**
* A brewing stand inventory, with one FUEL slot and four CRAFTING slots.
*/
BREWING(5, "Brewing"),
BREWING(5, "Brewing", MenuType.BREWING_STAND),
/**
* A player's inventory, with 9 QUICKBAR slots, 27 CONTAINER slots, 4 ARMOR
* slots and 1 offhand slot. The ARMOR and offhand slots may not be visible
* to the player, though.
*/
PLAYER(41, "Player"),
PLAYER(41, "Player", MenuType.GENERIC_9X4),
/**
* The creative mode inventory, with only 9 QUICKBAR slots and nothing
* else. (The actual creative interface with the items is client-side and
* cannot be altered by the server.)
*/
CREATIVE(9, "Creative", false),
CREATIVE(9, "Creative", null, false),
/**
* The merchant inventory, with 2 CRAFTING slots, and 1 RESULT slot.
*/
MERCHANT(3, "Villager", false),
MERCHANT(3, "Villager", MenuType.MERCHANT, false),
/**
* The ender chest inventory, with 27 slots.
*/
ENDER_CHEST(27, "Ender Chest"),
ENDER_CHEST(27, "Ender Chest", MenuType.GENERIC_9X3),
/**
* An anvil inventory, with 2 CRAFTING slots and 1 RESULT slot
*/
ANVIL(3, "Repairing"),
ANVIL(3, "Repairing", MenuType.ANVIL),
/**
* A smithing inventory, with 3 CRAFTING slots and 1 RESULT slot.
*/
SMITHING(4, "Upgrade Gear"),
SMITHING(4, "Upgrade Gear", MenuType.SMITHING),
/**
* A beacon inventory, with 1 CRAFTING slot
*/
BEACON(1, "container.beacon"),
BEACON(1, "container.beacon", MenuType.BEACON),
/**
* A hopper inventory, with 5 slots of type CONTAINER.
*/
HOPPER(5, "Item Hopper"),
HOPPER(5, "Item Hopper", MenuType.HOPPER),
/**
* A shulker box inventory, with 27 slots of type CONTAINER.
*/
SHULKER_BOX(27, "Shulker Box"),
SHULKER_BOX(27, "Shulker Box", MenuType.SHULKER_BOX),
/**
* A barrel box inventory, with 27 slots of type CONTAINER.
*/
BARREL(27, "Barrel"),
BARREL(27, "Barrel", MenuType.GENERIC_9X3),
/**
* A blast furnace inventory, with a RESULT slot, a CRAFTING slot, and a
* FUEL slot.
*/
BLAST_FURNACE(3, "Blast Furnace"),
BLAST_FURNACE(3, "Blast Furnace", MenuType.BLAST_FURNACE),
/**
* A lectern inventory, with 1 BOOK slot.
*/
LECTERN(1, "Lectern"),
LECTERN(1, "Lectern", MenuType.LECTERN),
/**
* A smoker inventory, with a RESULT slot, a CRAFTING slot, and a FUEL slot.
*/
SMOKER(3, "Smoker"),
SMOKER(3, "Smoker", MenuType.SMOKER),
/**
* Loom inventory, with 3 CRAFTING slots, and 1 RESULT slot.
*/
LOOM(4, "Loom"),
LOOM(4, "Loom", MenuType.LOOM),
/**
* Cartography inventory with 2 CRAFTING slots, and 1 RESULT slot.
*/
CARTOGRAPHY(3, "Cartography Table"),
CARTOGRAPHY(3, "Cartography Table", MenuType.CARTOGRAPHY_TABLE),
/**
* Grindstone inventory with 2 CRAFTING slots, and 1 RESULT slot.
*/
GRINDSTONE(3, "Repair & Disenchant"),
GRINDSTONE(3, "Repair & Disenchant", MenuType.GRINDSTONE),
/**
* Stonecutter inventory with 1 CRAFTING slot, and 1 RESULT slot.
*/
STONECUTTER(2, "Stonecutter"),
STONECUTTER(2, "Stonecutter", MenuType.STONECUTTER),
/**
* Pseudo composter inventory with 0 or 1 slots of undefined type.
*/
COMPOSTER(1, "Composter", false),
COMPOSTER(1, "Composter", null, false),
/**
* Pseudo chiseled bookshelf inventory, with 6 slots of undefined type.
*/
CHISELED_BOOKSHELF(6, "Chiseled Bookshelf", false),
CHISELED_BOOKSHELF(6, "Chiseled Bookshelf", null, false),
/**
* Pseudo jukebox inventory with 1 slot of undefined type.
*/
JUKEBOX(1, "Jukebox", false),
JUKEBOX(1, "Jukebox", null, false),
/**
* A crafter inventory, with 9 CRAFTING slots.
*/
@ApiStatus.Experimental
CRAFTER(9, "Crafter"),
CRAFTER(9, "Crafter", MenuType.CRAFTER_3X3),
/**
* The new smithing inventory, with 3 CRAFTING slots and 1 RESULT slot.
*
* @deprecated use {@link #SMITHING}
*/
@Deprecated
SMITHING_NEW(4, "Upgrade Gear"),
SMITHING_NEW(4, "Upgrade Gear", MenuType.SMITHING),
;
private final int size;
private final String title;
private final MenuType menuType;
private final boolean isCreatable;
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) {
this(defaultSize, defaultTitle, true);
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, @Nullable MenuType type) {
this(defaultSize, defaultTitle, type, true);
}
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, boolean isCreatable) {
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, @Nullable MenuType type, boolean isCreatable) {
size = defaultSize;
title = defaultTitle;
this.menuType = type;
this.isCreatable = isCreatable;
}
@ -180,6 +184,28 @@ public enum InventoryType {
return title;
}
/**
* Gets the corresponding {@link MenuType} of this InventoryType.
* <p>
* Not all InventoryType correspond to a {@link MenuType}. These
* InventoryTypes are also not creatable. If this method returns null,
* {@link #isCreatable()} will return false, with the exception of
* {@link #MERCHANT}.
* <p>
* As well as not necessarily corresponding to a {@link MenuType} some
* InventoryType correspond to the same {@link MenuType}, including:
* <ul>
* <li>Dropper, Dispenser
* <li>ShulkerBox, Barrel, Chest
* </ul>
*
* @return the corresponding {@link MenuType}
*/
@Nullable
public MenuType getMenuType() {
return menuType;
}
/**
* Denotes that this InventoryType can be created via the normal
* {@link org.bukkit.Bukkit#createInventory} methods.

View File

@ -0,0 +1,191 @@
package org.bukkit.inventory;
import com.google.common.base.Preconditions;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.view.AnvilView;
import org.bukkit.inventory.view.BeaconView;
import org.bukkit.inventory.view.BrewingStandView;
import org.bukkit.inventory.view.CrafterView;
import org.bukkit.inventory.view.EnchantmentView;
import org.bukkit.inventory.view.FurnaceView;
import org.bukkit.inventory.view.LecternView;
import org.bukkit.inventory.view.LoomView;
import org.bukkit.inventory.view.MerchantView;
import org.bukkit.inventory.view.StonecutterView;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Represents different kinds of views, also known as menus, which can be
* created and viewed by the player.
*/
@ApiStatus.Experimental
public interface MenuType extends Keyed {
/**
* A MenuType which represents a chest with 1 row.
*/
MenuType.Typed<InventoryView> GENERIC_9X1 = get("generic_9x1");
/**
* A MenuType which represents a chest with 2 rows.
*/
MenuType.Typed<InventoryView> GENERIC_9X2 = get("generic_9x2");
/**
* A MenuType which represents a chest with 3 rows.
*/
MenuType.Typed<InventoryView> GENERIC_9X3 = get("generic_9x3");
/**
* A MenuType which represents a chest with 4 rows.
*/
MenuType.Typed<InventoryView> GENERIC_9X4 = get("generic_9x4");
/**
* A MenuType which represents a chest with 5 rows.
*/
MenuType.Typed<InventoryView> GENERIC_9X5 = get("generic_9x5");
/**
* A MenuType which represents a chest with 6 rows.
*/
MenuType.Typed<InventoryView> GENERIC_9X6 = get("generic_9x6");
/**
* A MenuType which represents a dispenser/dropper like menu with 3 columns
* and 3 rows.
*/
MenuType.Typed<InventoryView> GENERIC_3X3 = get("generic_3x3");
/**
* A MenuType which represents a crafter
*/
MenuType.Typed<CrafterView> CRAFTER_3X3 = get("crafter_3x3");
/**
* A MenuType which represents an anvil.
*/
MenuType.Typed<AnvilView> ANVIL = get("anvil");
/**
* A MenuType which represents a beacon.
*/
MenuType.Typed<BeaconView> BEACON = get("beacon");
/**
* A MenuType which represents a blast furnace.
*/
MenuType.Typed<FurnaceView> BLAST_FURNACE = get("blast_furnace");
/**
* A MenuType which represents a brewing stand.
*/
MenuType.Typed<BrewingStandView> BREWING_STAND = get("brewing_stand");
/**
* A MenuType which represents a crafting table.
*/
MenuType.Typed<InventoryView> CRAFTING = get("crafting");
/**
* A MenuType which represents an enchantment table.
*/
MenuType.Typed<EnchantmentView> ENCHANTMENT = get("enchantment");
/**
* A MenuType which represents a furnace.
*/
MenuType.Typed<FurnaceView> FURNACE = get("furnace");
/**
* A MenuType which represents a grindstone.
*/
MenuType.Typed<InventoryView> GRINDSTONE = get("grindstone");
/**
* A MenuType which represents a hopper.
*/
MenuType.Typed<InventoryView> HOPPER = get("hopper");
/**
* A MenuType which represents a lectern, a book like view.
*/
MenuType.Typed<LecternView> LECTERN = get("lectern");
/**
* A MenuType which represents a loom.
*/
MenuType.Typed<LoomView> LOOM = get("loom");
/**
* A MenuType which represents a merchant.
*/
MenuType.Typed<MerchantView> MERCHANT = get("merchant");
/**
* A MenuType which represents a shulker box.
*/
MenuType.Typed<InventoryView> SHULKER_BOX = get("shulker_box");
/**
* A MenuType which represents a stonecutter.
*/
MenuType.Typed<InventoryView> SMITHING = get("smithing");
/**
* A MenuType which represents a smoker.
*/
MenuType.Typed<FurnaceView> SMOKER = get("smoker");
/**
* A MenuType which represents a cartography table.
*/
MenuType.Typed<InventoryView> CARTOGRAPHY_TABLE = get("cartography_table");
/**
* A MenuType which represents a stonecutter.
*/
MenuType.Typed<StonecutterView> STONECUTTER = get("stonecutter");
/**
* Typed represents a subtype of {@link MenuType}s that have a known
* {@link InventoryView} type at compile time.
*
* @param <V> the generic type of {@link InventoryView} that represents the
* view type.
*/
interface Typed<V extends InventoryView> extends MenuType {
/**
* Creates a view of the specified menu type.
* <p>
* The player provided to create this view must be the player the view
* is opened for. See {@link HumanEntity#openInventory(InventoryView)}
* for more information.
*
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
*/
@NotNull
V create(@NotNull HumanEntity player, @NotNull String title);
}
/**
* Yields this MenuType as a typed version of itself with a plain
* {@link InventoryView} representing it.
*
* @return the typed MenuType.
*/
@NotNull
MenuType.Typed<InventoryView> typed();
/**
* Yields this MenuType as a typed version of itself with a specific
* {@link InventoryView} representing it.
*
* @param viewClass the class type of the {@link InventoryView} to type this
* {@link InventoryView} with.
* @param <V> the generic type of the InventoryView to get this MenuType
* with
* @return the typed MenuType
* @throws IllegalArgumentException if the provided viewClass cannot be
* typed to this MenuType
*/
@NotNull
<V extends InventoryView> MenuType.Typed<V> typed(@NotNull final Class<V> viewClass) throws IllegalArgumentException;
/**
* Gets the {@link InventoryView} class of this MenuType.
*
* @return the {@link InventoryView} class of this MenuType
*/
@NotNull
Class<? extends InventoryView> getInventoryViewClass();
private static <T extends MenuType> T get(@NotNull final String key) {
final MenuType type = Registry.MENU.get(NamespacedKey.minecraft(key));
Preconditions.checkArgument(type != null, "The given string key must be an existing menu type");
return (T) type;
}
}