被动破坏与翻动 AI(griefing-ai)

基本信息

属性 值
类名 toast.specialAI.ai.grief.EntityAIGriefBlocks
实例化 AIHandler 在 onEntityJoinWorld 中根据 GRIEFING && GRIEF_TAG 与 FIDDLING && FIDDLE_TAG 调用
互斥位 MOVEMENT + FACING
优先级 与 wander/watch/lookIdle 同级(getPassivePriority)

功能

实体在无事可做时(被任何更高级 AI 抢占前),周期性扫描附近方块并执行:

  • GRIEFING:破坏可破坏方块(默认 farmland, bed, crafting_table, wooden_door, trapdoor, fence_gate, ladder;或所有光强>1 的方块)
  • FIDDLING:右键交互方块(默认 lever, button, comparator, repeater, cake;通过构造 EntityFakePlayer 触发 onBlockActivated)

Activity 状态机

状态 触发 行为
NONE 初始 / 重置 不做任何事
GRIEFING isValidTargetForGriefing 命中 走过去 → 视线确认 → 持续伤害方块直到破损
FIDDLING isValidTargetForFiddling 命中 + fiddleDelay <= 0 走过去 → 视线确认 → 调一次 targetBlock.onBlockActivated(fakePlayer)

两个状态都通过 tryTargetBlock(x,y,z) 在同一函数里独立判定,griefing 优先。

扫描循环(shouldExecute)

每 tick 最多 SCAN_COUNT(默认 24)次随机采样,受 AIHandler.canScan() 全局配额(scan_count_global)限制。采样范围:

x = X + nextInt(scanRange) - nextInt(scanRange)        // 默认 [X-11, X+11]
y = Y + nextInt(scanRangeY) - nextInt(scanRangeY)      // 默认 [Y-5, Y+5]
z = Z + nextInt(scanRange) - nextInt(scanRange)

scanRange = max(0, scan_range_config) + 1,保证至少 1×1 半径。 还需要游戏规则 mobGriefing = true。

视线确认(checkSight)

对候选方块发射 3 条 rayTrace:

  1. 朝方块中心上/下偏 0.5(取决于实体相对高度)
  2. 朝方块中心左/右偏 0.5(取决于实体相对 X)
  3. 朝方块中心前/后偏 0.5(取决于实体相对 Z)

任一命中候选方块或可顺路破坏的遮蔽方块即视为视线可达。sightCounter 控制重新检测节奏(基础 10~14 tick,命中延长 3 tick)。

GRIEFING 详细

步骤 行为
路径 tryMoveToXYZ(blockX, blockY, blockZ, 1.0)
视线确认 见上
抵达后 锁死路径 + 锁死视线(连续 swingItem() + 播放方块 stepSound)
伤害累加 blockDamage += BlockHelper.getDamageAmount(targetBlock, ...)
进度展示 worldObj.destroyBlockInWorldPartially(entityId, ..., (int)(blockDamage * 10) - 1)
破坏后 若为 farmland → 改为 dirt;否则 setBlockToAir,可选 dropBlockAsItem 留物品
音效 playAuxSFX(2001, ..., Block.getIdFromBlock(targetBlock)) 破坏音;break_sound=true 时再播 1012 远处破碎音

giveUpDelay > 400 强制放弃。

MAD_CREEPERS 特性

若实体是 EntityCreeper 且 mad_creepers = true:

  • startExecuting 不记录 stepSound 等
  • updateTaskGriefing 直接 setCreeperState(1) + blockDamage = 1.0F,等下一 tick 立即引爆
  • resetTaskGriefing 调用 setCreeperState(-1) 取消点燃

FIDDLING 详细

构造 EntityFakePlayer(同坐标、同 motion),调用:

targetBlock.onBlockActivated(worldObj, x, y, z, fakePlayer, 0, 0.5F, 0.5F, 0.5F);
fakePlayer.updateWrappedEntityState();

失败时输出 Failed to fiddle with block! ({blockId})。完成后 10 tick 冷却(fiddleDelay = 10)。

NBT 个性化字段

AI 在 NBT 上为每个实体覆盖默认行为:

字段 含义
GriefScanRange 自定义 scanRange(>0 时生效)
GriefScanRangeVertical 自定义 scanRangeY
GriefNeedsTool 该实体是否需要正确工具
GriefLights 该实体是否瞄准光强方块
GriefBlocks 该实体的目标方块列表(字符串)
GriefBlacklist 该实体的黑名单(字符串)
FiddleBlocks 该实体的翻动目标
FiddleBlacklist 该实体的翻动黑名单

字段不存在时回落到 passive_griefing 配置项。

方块列表语法(BlockHelper.newBlockSet)

  • farmland — 任意 metadata
  • cake 0 — 仅 metadata=0(未咬过的蛋糕)
  • minecraft:* — 整个命名空间所有方块(递归 BlockRegistry)
  • 多项用 , 分隔

相关条目