ActivatableFromInventoryServerSide API
基本信息
| 属性 | 值 |
|---|---|
| 类型 | 接口 net.xonich.mc.nohotbarneeded.api.ActivatableFromInventoryServerSide |
| 方法 | void activateFromInventory(EntityPlayerMP playerMP, int slotIdx) |
| 声明位置 | api/ActivatableFromInventoryServerSide.java:11 |
| Gradle 声明 | apiPackage =(留空,即未通过 Gradle 显式发布 API 包) |
用途
这是本模组唯一的对外接口。任何 Item 实现它之后,就能在玩家打开背包时通过热键直接触发使用,无需先把物品挪到快捷栏再关掉背包切出去右键。
README 给出的动机场景是背包类物品(如 Backpack)放在背包 9–35 区间时无法就地打开。
调用点
模组自身不实现该接口,只在两处做 instanceof 判定:
| 位置 | 作用 |
|---|---|
handlers/KeyboardEventHandler.java:59 |
客户端:判断鼠标所指物品是否可触发,是则发包 |
network/ActivateItemHandler.java:20-21 |
服务端:取该槽位物品,二次 instanceof 后调用 activateFromInventory |
服务端二次校验
ActivateItemHandler.onMessage 不信任客户端发来的槽位是否合法,而是重新从玩家真实背包取值:
EntityPlayerMP player = ctx.getServerHandler().playerEntity;
int slotIdx = msg.slotIdx();
ItemStack itemInSlot = player.inventory.getStackInSlot(slotIdx);
if (itemInSlot != null && itemInSlot.getItem() instanceof ActivatableFromInventoryServerSide item) {
item.activateFromInventory(player, slotIdx);
}
两次 instanceof 构成前后端双重门控。但服务端侧没有客户端那段 slotIdx < 0 || slotIdx > 35 的范围检查,若被构造的非法 slotIdx 到达,getStackInSlot 的行为取决于该负数/超界索引(本模组未防护)。
限制
- 方法签名带
EntityPlayerMP,意味着只能在服务端语义下执行;接口本身不做线程或世界加载校验。 - 源码第 9–10 行的 javadoc 是残句(
Each item will define后无内容),未说明实现方应如何处理槽位索引。
相关条目
- ActivateItemRequest 网络包 - 调用该接口的消息载体
- 激活物品热键 - 触发客户端判定的热键
- NEI 输入处理器注册 - 判定的分发入口