箱子 GUI
服务器里常见的"按钮菜单"本质是箱子界面(Inventory)。这一篇讲怎么用代码创建箱子界面、填充物品、监听点击。
Bukkit 类
早先注册监听器时就见过 Bukkit 类:
java
Bukkit.getPluginManager().registerEvents(this, this);Bukkit 是服务器的单例,通过它能操作服务器(封 IP、广播、获取在线玩家等,详见 JavaDoc)。Server 对象(主类 getServer() 返回)几乎等价——Bukkit 内部就是操作 Server。
创建 Inventory
箱子 GUI 本质是 Inventory 对象。但 Inventory 是接口,不能直接 new,用 Bukkit.createInventory 创建:
java
Inventory inv = Bukkit.createInventory(null, 9 * 6, "URARA!");
// 第一参:持有者,通常传 null 或 player
// 第二参:大小,必须是 9 的倍数(9/18/27/36/45/54)
// 第三参:标题填充物品用 setItem:
java
ItemStack border = new ItemStack(Material.DIAMOND);
for (int i : new int[]{0,1,2,3,4,5,6,7,8,9,17,18,26,27,35,36,44,45,46,47,48,49,50,51,52,53}) {
inv.setItem(i, border); // 钻石边框
}
player.openInventory(inv); // 打开给玩家监听点击
玩家点箱子 GUI 会触发 InventoryClickEvent。监听它来判断点了哪格、执行对应逻辑:
java
@EventHandler
public void onClick(InventoryClickEvent e) {
if (!e.getView().getTitle().equals("URARA!")) return; // 只处理我们的 GUI
if (e.getCurrentItem() == null) return;
Player player = (Player) e.getWhoClicked();
if (e.getCurrentItem().getType() == Material.DIAMOND) {
e.setCancelled(true); // 防止拿走边框
player.sendMessage("你点了边框");
} else if (e.getCurrentItem().getType() == Material.EMERALD) {
e.setCancelled(true);
player.sendMessage("你点了确认按钮");
player.closeInventory();
}
}务必取消不需要的点击
不 setCancelled(true),玩家能把 GUI 里的物品拿进自己背包(包括边框/按钮)。除非你故意允许拿取,否则一律取消。
监听拖动
玩家还可能拖动物品进 GUI(InventoryDragEvent)。若禁止往 GUI 里放东西,也要监听:
java
@EventHandler
public void onDrag(InventoryDragEvent e) {
if (e.getView().getTitle().equals("URARA!")) {
e.setCancelled(true);
}
}给物品加名字和 lore
按钮通常要有显示名和说明文字(lore):
java
ItemStack button = new ItemStack(Material.EMERALD);
ItemMeta meta = button.getItemMeta();
meta.setDisplayName(ChatColor.GREEN + "确认");
meta.setLore(Arrays.asList(
ChatColor.GRAY + "点击确认操作",
ChatColor.GRAY + "不可撤销"
));
button.setItemMeta(meta);
inv.setItem(22, button);TIP
改 ItemStack 必须先 getItemMeta()、改完 setItemMeta() 回去——ItemMeta 是不可变快照,不改 meta 原物品不变。
箱子 GUI 是做菜单、商店、选择界面的基础。下一篇自定义事件。
