菜单
# 菜单
可以应对多种复杂场景的箱子菜单组件。
# 新建菜单
以 GuiExample 为例
public class GuiExample implements IGuiHolder {
private final Player player;
private Inventory inv;
public GuiExample(Player player) {
this.player = player;
}
@Override
public Player getPlayer() {
return player;
}
@Override
public Inventory newInventory() {
this.inv = Bukkit.createInventory(this, 9, "示例菜单");
this.inv.setItem(4, ItemStackUtil.buildItem(
Material.DIAMOND,
"&e你好",
"&7点我领取一组钻石"
));
return this.inv;
}
@Override
public @NotNull Inventory getInventory() {
return this.inv;
}
@Override
public void onClick(
InventoryAction action, ClickType click,
InventoryType.SlotType slotType, int slot,
ItemStack currentItem, ItemStack cursor,
InventoryView view, InventoryClickEvent event
) {
event.setCancelled(true);
if (slot == 4) {
if (!click.isShiftClick() && click.isLeftClick()) {
ItemStackUtil.giveItemToPlayer(player, new ItemStack(Material.DIAMOND, 64));
player.closeInventory();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
只需要执行 new GuiExample(player).open();
即可为玩家打开菜单。
# 动态更新图标
Bukkit 自带的还是有点难用,暂未设计合适的接口,敬请期待。
可以在 setItem
之后,执行
updateInventory(getInventory());
Util.submitInvUpdate(getPlayer());
1
2
2
来提交更新菜单图标。
也可以直接执行 open();
重新打开菜单,但相对有点耗性能,如果不需要更新菜单标题,不要偷懒用 open();
刷新菜单。
注意
在 onClick
中,因为此时界面点击事件还未结束,所以不能直接调用更新菜单的方法,否则可能会出现预期之外的问题。
要在下一 tick 执行更新才是正确做法,例如
plugin.getScheduler().runTask(() -> {
updateInventory(getInventory());
Util.submitInvUpdate(getPlayer());
});
1
2
3
4
2
3
4
# 翻页菜单
详见 PageGuide (opens new window)
public class GuiExample implements IGuiHolder {
private final Player player;
private final PageGuide<String> pageGuide = new PageGuide<>();
private Inventory inv;
public GuiExample(Player player) {
this.player = player;
}
@Override
public Player getPlayer() {
return player;
}
@Override
public Inventory newInventory() {
this.inv = Bukkit.createInventory(this, 9, "示例菜单");
pageGuide.setupPrevPageButton(
ItemStackUtil.buildItem(Material.LIME_STAINED_GLASS_PANE, "&a上一页"),
ItemStackUtil.buildItem(Material.RED_STAINED_GLASS_PANE, "&c上一页", "&7没有上一页了"),
0); // “上一页”在第 1 格
pageGuide.setupNextPageButton(
ItemStackUtil.buildItem(Material.LIME_STAINED_GLASS_PANE, "&a下一页"),
ItemStackUtil.buildItem(Material.RED_STAINED_GLASS_PANE, "&c下一页", "&7没有下一页了"),
3); // “下一页”在第 4 格
pageGuide.setContentSlots(1, 2); // 内容在 2、3 格
// 添加数据和显示物品
pageGuide.add("钻石", new ItemStack(Material.DIAMOND));
pageGuide.add("金锭", new ItemStack(Material.GOLD_INGOT));
pageGuide.add("铁锭", new ItemStack(Material.IRON_INGOT));
pageGuide.add("煤炭", new ItemStack(Material.COAL));
pageGuide.add("石头", new ItemStack(Material.STONE));
// 更新到 Inventory
pageGuide.updateInventory(this.inv);
return this.inv;
}
@Override
public @NotNull Inventory getInventory() {
return this.inv;
}
@Override
public void onClick(
InventoryAction action, ClickType click,
InventoryType.SlotType slotType, int slot,
ItemStack currentItem, ItemStack cursor,
InventoryView view, InventoryClickEvent event
) {
// 处理翻页按钮点击
if (pageGuide.handlePageBtnClick(event)) return;
event.setCancelled(true);
// 获取点击的图标携带的数据 (前面调用 add 那里的第一个参数)
String data = pageGuide.get(slot);
if (data != null) {
player.sendMessage("点击的图标所携带的自定义数据: " + data);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
上次更新: 2025/08/20, 17:50:57