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 后无内容),未说明实现方应如何处理槽位索引。

相关条目