时装护甲物品栏

[!INFO] 实现类:lain.mods.cos.inventory.InventoryCosArmor(服务端 + 客户端各一份)

基本信息

属性 值
槽位总数 4(ItemStack[] stacks = new ItemStack[4])
每槽堆叠上限 1(getInventoryStackLimit())
对应原版护甲格 EntityPlayer.inventory.armorInventory[0..3]
槽位容器名 空字符串(getInventoryName() 返回 "",hasCustomInventoryName() 返回 false,因此不参与 NBT 键名)
数量上限 无(isItemValidForSlot() 对任意 ItemStack 都返回 true,校验全部在 Slot 层)
使用权限 无(isUseableByPlayer() 恒为 true;ContainerCosArmor.canInteractWith() 也恒为 true)

功能

在玩家身上挂载第二套纯装饰护甲。这套护甲只参与渲染,不参与伤害计算、不被原版护甲值读取、也不影响摔落/爆炸等护甲减伤判定。玩家同时拥有原版护甲格和本物品栏两套数据。

InventoryCosArmor 除 IInventory 全部方法外还维护一个 boolean[] isSkinArmor = new boolean[4],表示该槽是否处于「不穿」状态(皮肤模式),详见 皮肤模式开关。

槽位索引映射

InventoryCosArmor 的数组下标与原版 armorInventory 完全对齐,而容器内部为了画在正确的高度做了 3 - i 的翻转(ContainerCosArmor 构造函数第 69~71 行 invCosArmor.getSizeInventory() - 1 - i):

存储下标 对应原版 armorInventory 部位 ItemArmor.armorType 容器槽位号 容器内 Y 坐标 皮肤模式按钮 ID
0 armorInventory[0] 靴子 3 12 8 + 3×18 = 62 83
1 armorInventory[1] 护腿 2 11 8 + 2×18 = 44 82
2 armorInventory[2] 胸甲 1 10 8 + 1×18 = 26 81
3 armorInventory[3] 头盔 0 9 8 + 0×18 = 8 80

容器槽位号在成品界面中由上至下是 9(头盔) / 10(胸甲) / 11(护腿) / 12(靴子),即界面上方是头盔,与原版玩家背包一致。

槽位合法性校验

ContainerCosArmor 的 4 个时装槽各自重写了 isItemValid(ItemStack)(第 85~93 行),与 4 个原版护甲槽(第 55~63 行)逻辑完全相同:

Item item = stack == null ? null : stack.getItem();
boolean isValidArmor = false;
if (item instanceof ItemArmor) isValidArmor = ((ItemArmor) item).armorType == j;
return item != null
    && (isValidArmor || ((item instanceof ItemBlock || item instanceof ItemSkull) && j == 0));
  • j 是容器绘制序号(0=头盔行,3=靴子行),不是存储下标。
  • 头盔行(j == 0)额外接受 ItemBlock 与 ItemSkull——这让玩家可以把方块或头颅塞进「时装」里做外观展示。
  • 头盔以外的三行只接受 armorType 完全匹配的 ItemArmor。
  • 注意 IInventory.isItemValidForSlot() 恒返回 true,所以只有通过界面放入才会被限制;setInventorySlotContents() 与网络包可以写入任意 ItemStack。

容器槽位总数

ContainerCosArmor 构造时共注册 49 个 Slot:

区段 槽位号 数量 坐标
合成产物 0 1 (144, 36)
2×2 合成网格 1~4 4 (106, 26) 起,步进 18
原版护甲格 5~8 4 (8, 8 + i×18)
时装护甲格 9~12 4 (80, 8 + i×18)
玩家背包 13~39 27 (8 + j×18, 84 + i×18)
快捷栏 40~48 9 (8 + i×18, 142)

容器自带一个 InventoryCrafting(this, 2, 2) 与 InventoryCraftResult,onCraftMatrixChanged() 用 CraftingManager.findMatchingRecipe(craftMatrix, player.worldObj) 实时算产物,因此成品界面可以就地合成。

搬运与交互行为

全部沿用原版 Container 逻辑,transferStackInSlot() 的分区(无任何自定义右键/Shift+左键分支):

源槽位号 目标区间 说明
0(合成产物) 13~49 先尝试整叠搬运
1~4(合成网格) 13~49 false,不整叠
5~12(两套护甲) 13~49 false,不整叠
13~39(玩家背包) 40~49 优先快捷栏
40~48(快捷栏) 13~40 优先背包

另有一段原版自动穿装备快捷逻辑(第 159~164 行):当拖动的物品是 ItemArmor 且 5 + armorType 号槽为空时,先尝试合并到 j = 5 + armorType(原版护甲格),失败再尝试 j + 4 = 9 + armorType(同一部位的时装格)。因此 Shift 拖动一件护甲会优先装到原版护甲位,只有该位被占用时才落到时装位。

func_94530_a() 被重写为对合成产物槽返回 false,即禁止 Shift+左键从产物槽取货。

onContainerClosed() 关闭界面时把 2×2 网格里的 4 件物品用 player.dropPlayerItemWithRandomChoice(stack, false) 丢回玩家(不是扔在地上),并清空产物槽。

同步与持久化

相关条目