容器API¶
容器API负责管理玩家物品栏、箱子、熔炉,以及Allay里非常实用的伪容器界面。本指南重点讲“怎么拿到容器”“怎么改槽位”“怎么做自定义GUI”。
容器是什么¶
Allay里最基础的接口是Container。它负责保存物品,也负责管理查看者和监听器。
常见容器类型如下:
| 类型 | 大小 | 说明 |
|---|---|---|
INVENTORY | 36 | 玩家主物品栏。 |
ARMOR | 4 | 盔甲槽。 |
OFFHAND | 1 | 副手槽。 |
CHEST | 27 | 单箱子。 |
DOUBLE_CHEST | 54 | 大箱子。 |
BARREL | 27 | 木桶。 |
ENDER_CHEST | 27 | 末影箱。 |
BREWING_STAND | 5 | 酿造台。 |
CRAFTING_TABLE | 9 | 工作台。 |
FAKE_CHEST | 27 | 伪箱子容器。 |
FAKE_DOUBLE_CHEST | 54 | 伪大箱子容器。 |
先拿到玩家容器¶
玩家本身实现了ContainerHolder,所以可以直接取出不同类型的容器:
import org.allaymc.api.container.ContainerTypes;
import org.allaymc.api.entity.interfaces.EntityPlayer;
public void inspectPlayer(EntityPlayer player) {
var inventory = player.getContainer(ContainerTypes.INVENTORY);
var armor = player.getContainer(ContainerTypes.ARMOR);
var offhand = player.getContainer(ContainerTypes.OFFHAND);
}
如果你只想处理手上物品,也可以直接用玩家接口:
var itemInHand = player.getItemInHand();
int handSlot = player.getHandSlot();
player.clearItemInHand();
读写槽位¶
日常物品栏操作基本都围绕getItemStack()、setItemStack()、clearSlot()和tryAddItem()。
import org.allaymc.api.container.ContainerTypes;
import org.allaymc.api.item.type.ItemTypes;
var inventory = player.getContainer(ContainerTypes.INVENTORY);
inventory.setItemStack(0, ItemTypes.DIAMOND.createItemStack(64));
var firstItem = inventory.getItemStack(0);
inventory.clearSlot(0);
player.tryAddItem(ItemTypes.EMERALD.createItemStack(16));
tryAddItem()会优先合并已有堆叠,再尝试找空槽,所以通常比你手动遍历槽位更省事。
处理方块容器¶
玩家打开某个容器方块以后,可以从控制器里读到当前界面对应的容器:
import org.allaymc.api.container.ContainerTypes;
import org.allaymc.api.item.type.ItemTypes;
var controller = player.getController();
if (controller != null) {
var openedChest = controller.getOpenedContainer(ContainerTypes.CHEST);
if (openedChest != null) {
openedChest.tryAddItem(ItemTypes.GOLD_INGOT.createItemStack(16));
}
}
这类写法适合做“打开箱子时自动塞入奖励”“检查玩家当前正在编辑哪个容器”之类的逻辑。
监听容器变化¶
Allay容器支持打开、关闭和槽位变化监听:
import org.allaymc.api.container.Container;
import org.allaymc.api.container.ContainerViewer;
public void bindListeners(Container container) {
container.addOpenListener((ContainerViewer viewer) -> {
System.out.println("有人打开了容器");
});
container.addCloseListener((ContainerViewer viewer) -> {
System.out.println("有人关闭了容器");
});
container.addSlotChangeListener(0, itemStack -> {
System.out.println("0号槽被改成了:" + itemStack.getItemType().getIdentifier());
});
}
如果你要做商店、拍卖行或任务面板,这组监听器会非常常用。
用伪容器做自定义GUI¶
Allay提供了伪容器系统,它不依赖真实方块,非常适合做菜单。
import org.allaymc.api.container.FakeContainerFactory;
import org.allaymc.api.item.type.ItemTypes;
var menu = FakeContainerFactory.getFactory().createFakeChestContainer();
menu.setCustomName("主菜单");
menu.setItemStack(0, ItemTypes.DIAMOND.createItemStack());
menu.setItemStack(4, ItemTypes.EMERALD.createItemStack());
你还可以给某个槽位直接绑定点击逻辑:
menu.setItemStackWithListener(0, ItemTypes.DIAMOND_SWORD.createItemStack(), () -> {
player.sendMessage("你点击了钻石剑。");
});
menu.addClickListener(4, () -> {
player.sendMessage("你点击了绿宝石。");
});
最后把它展示给玩家:
addPlayer()与addViewer()不要混用
伪容器要优先使用addPlayer()而不是普通的addViewer()。Allay资料明确说明,addPlayer()会在打开界面前处理客户端所需的伪方块流程;只加查看者可能导致界面状态不完整。