跳到正文
烈焰甘蔗Wiki

Backhand 集成

BetterBuildersWands 集成 xonin 的 Backhand 模组,允许把副手中的方块 当作魔杖的材料,从而在不占用快捷栏的情况下批量放置。

触发条件

源码中所有入口都用运行时类检测:

if (Loader.isModLoaded("backhand")) { … }

WandWorker.getProperItemStackBackhand 标注了 @Optional.Method(modid = "backhand"):

@Optional.Method(modid = "backhand")
public static ItemStack getProperItemStackBackhand(IPlayerShim player) {
    return BackhandUtils.getOffhandItem(player.getPlayer());
}

这是 Forge 的**可选依赖(optional dependency)**声明:Backhand 不在时 该方法被剔除,调用点也不会被执行,因此未安装 Backhand 时本 mod 正常工作。

行为一:材料来源改为副手

WandWorker.getProperItemStack() 先查副手,优先级高于被点中的方块:

boolean usedBackhand = false;
if (Loader.isModLoaded("backhand")) {
    ItemStack itemStack = getProperItemStackBackhand(player);
    if (itemStack != null && itemStack.getItem() instanceof ItemBlock) {
        Block offhandBlock = ((ItemBlock) itemStack.getItem()).field_150939_a;
        if (offhandBlock != null && offhandBlock != Blocks.air) {
            block = offhandBlock;
            meta = itemStack.getItemDamage();
            usedBackhand = true;
        }
    }
}
if (!usedBackhand) { …查自定义映射 / 精确匹配 / 等效物品… }
条件 结果
副手是 ItemBlock 且方块不是空气 完全无视点中的方块,改用副手方块作为材料和目标
副手是其它物品 / 为空 / 是空气 回退到正常逻辑(点中的方块 → 映射 → 精确 → 等效)

usedBackhand 为真时会跳过自定义映射查询 —— 也就是说副手方块 不会经过 forced_blocks 映射。

行为二:临时映射(ItemBasicWand.getCustomMapping)

这是一个容易忽略的独立分支:

public static ICustomMapping getCustomMapping(IWorldShim worldShim, IPlayerShim playerShim, Point3d clickedPos) {
    if (Loader.isModLoaded("backhand")) {
        ItemStack backhandItem = WandWorker.getProperItemStackBackhand(playerShim);
        if (backhandItem != null && backhandItem.getItem() instanceof ItemBlock) {
            Block offhandBlock = ((ItemBlock) backhandItem.getItem()).field_150939_a;
            int meta = backhandItem.getItemDamage();
            ICustomMapping existing = BetterBuildersWandsMod.instance.mappingManager.getMapping(offhandBlock, meta);
            if (existing != null) return existing;                       // 复用已注册映射
            return new CustomMapping(offhandBlock, meta, backhandItem, offhandBlock, meta);  // 临时 1:1 映射
        }
    }
    … 正常的按点击方块查表 …
}
情况 返回
副手方块已注册过映射 返回注册表里那条(可能 shouldCopyTileNBT = true)
副手方块未注册 临时构造 1:1 映射,shouldCopyTileNBT = false
没装 Backhand 按被点中的方块 + metadata 查表

因为这条临时映射的 shouldCopyTileNBT 是 false,通过副手放置不会复制 TileEntity 的 NBT,与 Forestry / ArchitectureCraft 的正式映射行为不同。

行为三:BFS 过滤中的额外校验

WandWorker.shouldContinue() 里多了一道针对副手方块的放置校验:

if (Loader.isModLoaded("backhand")) {
    ItemStack backhandItem = WandWorker.getProperItemStackBackhand(player);
    if (backhandItem != null && backhandItem.getItem() instanceof ItemBlock) {
        if (!((ItemBlock) backhandItem.getItem()).field_150939_a
                .canPlaceBlockAt(world.getWorld(), x, y, z))
            return false;
    }
}

即:副手方块在每个候选位置都必须通过 canPlaceBlockAt, 否则该点被丢弃(且不再向它扩展)。

行为四:消耗改为扣副手

WandWorker.placeBlocks() 把 needItem 换成副手物品:

ItemStack needItem = sourceItems.copy();
if (Loader.isModLoaded("backhand")) {
    ItemStack backhandItem = WandWorker.getProperItemStackBackhand(playerShim);
    if (backhandItem != null && backhandItem.getItem() instanceof ItemBlock) {
        needItem = backhandItem.copy();
    }
}
Block targetBlock = Block.getBlockFromItem(needItem.getItem());

注意扣材料的动作仍然是 playerShim.useItem(needItem, …),即从 主背包里扣 —— needItem 只作为"要扣什么/放什么"的描述。 副手在此只扮演"指定建造目标"的角色,不直接提供材料 (材料仍需来自背包、Botania 或 AE2)。

BasicPlayerShim 的 slotPriority 注释 Inventory > Hotbar > Backhand 也印证了这一顺序:主背包优先扣,热键栏最后扣。

使用场景

装好 Backhand 后,把方块放在副手、魔杖拿在主手右键任意方块, 即可在副手方块的空位上批量铺开 —— 主手快捷栏不会被材料占掉。 /wandOops 撤销同样适用(见 BFS 方块扩展算法)。

相关条目

浏览全部模组