跳到正文
烈焰甘蔗Wiki

/wandOops Command

服务器命令,撤销魔杖最近一次批量放置的方块,并把材料掉回给玩家。

基本信息

属性 值
命令名称 /wandOops
源码 getCommandName() 返回 "wandOops"
用法字符串 /wandOops
类 portablejim.bbw.core.OopsCommand(继承 CommandBase)
注册时机 FMLServerStartingEvent
权限等级 0(所有玩家)
是否仅限手持魔杖 是
参数 无

⚠️ 命令名是 /wandOops,不是 /oo。源码中没有注册任何别名 (getCommandName() 只返回 "wandOops",也没有覆写 getCommandAliases()), 所以 /oo 不会被识别,会报"未知命令"。

注册

@EventHandler
public void serverStarting(FMLServerStartingEvent event) {
    event.registerServerCommand(new OopsCommand());
}

本 mod 只注册这一个命令(源码中 CommandBase 的唯一子类就是 OopsCommand)。

权限

方法 返回值 含义
getRequiredPermissionLevel() 0 所有玩家都能用
canCommandSenderUseCommand() true 不做额外限制

权限等级 0 意味着服务器上的任何玩家都能对自己手持的魔杖执行撤销, 无需 OP。

前置条件与报错

命令在服务端执行,按顺序检查,任一不满足就抛 WrongUsageException (客户端收到本地化错误消息):

顺序 条件 不满足时的语言键 中文消息
0 执行者必须是 EntityPlayerMP bbw.chat.error.bot AI检测使用者不是玩家。请不要再这样做了。
1 手持物品非空且 instanceof IWandItem bbw.chat.error.nowand 你需要手持更好的建筑法杖来运行它。
2 NBT 里有 bbw.lastPlaced(int 数组) bbw.chat.error.noundo 我记不得这个建筑之杖上次修建的历史了。

非玩家执行(控制台 / 命令方块)会得到 bot 错误。 手持非魔杖物品得到 nowand。魔杖从未放置过方块(或已经撤销过一次)得到 noundo。

撤销流程

1. 重建要掉的物品

GameRegistry.UniqueIdentifier lastBlock = new GameRegistry.UniqueIdentifier(bbwCompound.getString("lastBlock"));
int damageValue = bbwCompound.getInteger("lastDamage");
ItemStack itemStack = GameRegistry.findItemStack(lastBlock.modId, lastBlock.name, 1);
itemStack.setItemDamage(damageValue);
Block block = Block.getBlockFromItem(itemStack.getItem());

从 NBT 的 lastBlock(注册名)+ lastDamage(metadata)还原出物品和方块。 这些字段由每次成功放置后写入,见 魔杖物品通用行为。

2. 逐点校验并清除

for (Point3d point : pointList) {
    if (world.getBlock(point.x, point.y, point.z) == block
            && world.getBlockMetadata(point.x, point.y, point.z) == damageValue) {
        world.setBlockToAir(point.x, point.y, point.z);
        count++;
    }
}
关键行为 说明
双重要求 位置上的方块和 metadata 都必须与上次一致才清除
被玩家改动过就跳过 玩家在撤销前手动拆掉/替换了某个方块,那个点会被跳过(不误删)
只清空气 用 setBlockToAir,不返还掉落物(材料统一在下一步按计数掉)
坐标校验 y >= 255 之外的越界点不会被记录,所以不涉及越界

3. 按倍数掉回材料

int count = lastPerBlock * amount;              // amount = 成功清除的点数
int stackSize = itemStack.getMaxStackSize();
int fullStacks = count / stackSize;
for (int i = 0; i < fullStacks; i++) { … 生成满堆 EntityItem … }
… 再掉一个 count % stackSize 的余数堆 …
环节 行为
倍数 lastPerBlock × 实际清除点数(lastPerBlock 是每放 1 格消耗的材料数)
拆分 按物品最大堆叠数拆成 N 个满堆 + 1 个余数堆
掉落位置 全部掉在玩家脚下(player.posX/posY/posZ)
尾数 即使余数为 0 也会额外 spawnEntityInWorld 一个 stackSize = 0 的空堆

4. 清除 NBT(保证只能用一次)

bbwCompound.removeTag("lastPlaced");
bbwCompound.removeTag("lastBlock");
bbwCompound.removeTag("lastDamage");
bbwCompound.removeTag("lastPerBlock");

mask 和 fluidmask 保留不变 —— 撤销不会重置锁定模式。 因为 lastPlaced 被移除,同一根魔杖无法连续撤销两次, 必须先重新放置方块才能再次撤销。

坐标解包

lastPlaced 是扁平的 int 数组,每 3 个 int 表示一个点:

protected ArrayList<Point3d> unpackNbt(int[] placedBlocks) {
    int countPoints = placedBlocks.length / 3;
    for (int i = 0; i < countPoints * 3; i += 3) {
        output.add(new Point3d(placedBlocks[i], placedBlocks[i+1], placedBlocks[i+2]));
    }
}

数组长度由 ItemBasicWand.onItemUse 写入:placedBlocks.size() * 3。

限制

限制 说明
只能撤销最近一次 每次放置覆盖 lastPlaced
只能撤销自己手持的魔杖 NBT 在物品上,换人换杖无效
只能撤销同一物品同一 metadata 玩家改动过的方块被跳过,不会误删
不能恢复 TileEntity 数据 只用 setBlockToAir,已放置方块的 NBT 一并丢失
不能撤销副手(Backhand)以外的取料差异 材料按 lastPerBlock 统一计算,不区分来源

⚠️ 不返还 TileEntity NBT:撤销后重新放置得到的是默认状态的方块, Forestry 原木的树种等数据不会恢复。

相关条目

浏览全部模组