魔杖物品通用行为
四根魔杖的物品类都继承自 ItemBasicWand(core/items/ItemBasicWand.java),
共用以下行为。ItemBasicWand 实现 IWandItem 接口并持有唯一字段 IWand wand。
三个具体子类
| 类 | 使用的魔杖 | 额外覆写 |
|---|---|---|
ItemRestrictedWandBasic |
Stone Wand | nextMode 写死 HORIZONTAL、getFaceLock 恒 HORIZONTAL |
ItemRestrictedWandAdvanced |
Iron Wand | nextMode 在 HORIZONTAL/VERTICAL 间轮转、getFaceLock 恒 NOLOCK |
ItemUnrestrictedWand |
Diamond / Unbreakable Wand | 7 模式轮转、getFaceLock 随模式联动、addSubMeta 多形态 |
⚠️
ItemUnrestrictedWand这个类名有误导性 —— Diamond Wand 用的就是它, 并且内部装的是RestrictedWand(会掉耐久)。名字里的 “Unrestricted” 指的是 锁定模式不受限,不是"耐久无限"。真正无限耐久的是UnbreakingWand这个IWand实现。
通用属性
| 属性 | 值 | 来源 |
|---|---|---|
| 最大堆叠 | 1 | setMaxStackSize(1) |
| 创造模式物品栏 | CreativeTabs.tabTools(工具) |
setCreativeTab |
| 附魔适用 | 是(继承 Item,未覆写任何附魔相关方法) |
— |
| 可收获方块 | 否 | canHarvestBlock() 硬编码 return false |
魔杖作为"工具"的副作用
| 触发 | 耐久消耗 | 源码 |
|---|---|---|
| 破坏方块 | 2 | onBlockDestroyed() → damageItem(2, entity) |
| 攻击实体 | 2 | hitEntity() → damageItem(2, entity) |
| 右键放置方块 | 1(Stone/Iron/Diamond)或 0(Unbreakable) | IWand.placeBlock |
| 切换锁定模式 | 0 | setMode() 只写 NBT |
| 切换流体模式 | 0 | setFluidMode() 只写 NBT |
由于 canHarvestBlock() 返回 false,魔杖不能用来挖方块采集材料;
但左键挖/打时仍会掉 2 点耐久。
NBT 结构
所有状态都写在 ItemStack 根标签下的 bbw 复合标签里
(常量 BetterBuildersWandsMod.LANGID = "bbw"):
{
"bbw": {
"mask": <short>, // 方向锁定,EnumLock.mask(1~7)
"fluidmask": <short>, // 流体锁定,EnumFluidLock.mask(1~2)
"lastPlaced": <int[]>, // 上次放置的坐标,每 3 个 int 一个点
"lastBlock": <string>, // 上次用的物品注册名,如 "minecraft:stone"
"lastDamage": <int>, // 上次用的物品 metadata
"lastPerBlock": <int> // 每放置 1 个方块消耗多少材料
}
}
| 字段 | 写入时机 | 读取方 |
|---|---|---|
mask |
setMode(),或首次放置时写入默认值 |
getMode() |
fluidmask |
setFluidMode(),或首次放置时写入默认值 |
getFluidMode() |
lastPlaced / lastBlock / lastDamage / lastPerBlock |
每次成功放置后 | /wandOops Command 撤销时 |
读取时的容错(getMode / getFluidMode):
- 没有
bbw标签 → 返回getDefaultMode()(NOLOCK)/STOPAT - 有
bbw但没有mask→ 用EnumLock.NOLOCK.mask - 有
bbw但没有fluidmask→ 用EnumFluidLock.STOPAT.mask
注意
setFluidMode()写的是mode.mask & 7(掩码是 7 而不是EnumFluidLock的 2)。 因为值只有 1、2,效果上无差别,但属于实现上的宽掩码。
物品提示文本
addInformation() 按当前 NBT 状态逐行生成(语言键前缀 bbw.):
| 行 | 语言键 | 内容 |
|---|---|---|
| 1 | bbw.hover.mode.<模式名> |
当前方向锁定模式 |
| 2 | bbw.hover.fluidmode.<模式名> |
当前流体锁定模式 |
| 3 | bbw.hover.maxblocks |
最大%d个方块,仅在物品完全未损时显示 |
第 3 行的条件是 !itemstack.isItemStackDamageable() || !itemstack.isItemDamaged()
—— 一旦魔杖有磨损就不再显示上限。
Unbreakable Wand 的 isItemStackDamageable() 因最大耐久为 0 而为 false,
所以它永远显示"最大 4096 个方块"之类的上限提示。
创造模式物品栏形态
ItemUnrestrictedWand.getSubItems() 重写了物品形态枚举:
subItemMetas为空(Stone / Iron / Diamond Wand)→ 只列出 meta 0- 非空(Unbreakable Wand)→ 把
addSubMeta()注册过的 meta 排序后全部列出
网络
模式切换不在客户端本地执行,而是发包到服务端由服务端改写 NBT
(详见 网络协议)。PacketWandActivate.Handler 在改写后
用 ChatComponentTranslation 回复一条聊天消息,语言键为
bbw.chat.mode.<模式名> / bbw.chat.fluidmode.<模式名>。
相关条目
- 魔杖等级系统 -
IWand两种实现的区别 - BFS 方块扩展算法 -
onItemUse的完整调用链 - 模式切换热键 - 触发
nextMode的热键 - 流体模式切换热键 - 触发
nextFluidMode的热键 - 网络协议 - 模式切换的客户端→服务端通信