AI 注入器(ai-handler)
基本信息
| 属性 | 值 |
|---|---|
| 类名 | toast.specialAI.ai.AIHandler |
| 实例化时机 | _SpecialAI.init() 中 new AIHandler() |
| 监听 | FMLCommonHandler.bus() + MinecraftForge.EVENT_BUS |
| 关键事件 | EntityJoinWorldEvent, LivingDeathEvent, TickEvent.ServerTickEvent, TickEvent.WorldTickEvent |
作用
所有 AI 注入都通过 onEntityJoinWorld 集中处理:当任意 EntityLiving 加入世界时,根据其类型/列表/随机数向其 tasks 与 targetTasks 注入一套 AI。TickEvent.WorldTickEvent 还在每 tick 末尾扫描世界中的 EntityItem,把带有 ThiefUUID* 标签的物品归还给它对应的偷窃 AI 生物。
流程(onEntityJoinWorld)
按 EntityCreature 分支与通用分支依次注入:
| 阶段 | 条件 | 注入的 AI |
|---|---|---|
| 避爆 | AvoidExplosions NBT 启用 |
EntityAIAvoidExplosions |
| 防御村庄 | DefendVillage NBT 启用(villagers_defend 且为 EntityVillager) |
EntityAIAttackOnCollidePassive + EntityAIVillagerDefendVillage |
| 反击(depacify) | DEPACIFY_TAG 1 或 2 |
EntityAIAttackOnCollidePassive + EntityAIHurtByTarget;2 时附加 EntityAINearestAttackableTarget |
| 呼救 | CALL_FOR_HELP=true 且未 depacify |
把现有 EntityAIHurtByTarget 替换为支持 callForHelp=true 版本 |
| 可骑乘(mount) | 在 MOUNT_SET 或 MOUNT_SET_SMALL 中 |
EntityAIRiderTarget(目标跟随) |
| 骑手(rider) | RIDER_CHANCE 随机命中 RIDER_SET / RIDER_SET_SMALL |
EntityAIRider(找坐骑) |
| 吃育种物品 | EAT_BREEDING_ITEMS=true 且为 EntityAnimal |
EntityAIEatBreedingItem |
| 被动破坏 | GRIEFING && GRIEF_TAG=true |
EntityAIGriefBlocks |
| 被动翻动 | FIDDLING && FIDDLE_TAG=true |
同上(注入时 fiddling 启用) |
| 特殊 AI(uAI) | 落入 _mob_list_1/2/3 且命中概率 |
SpecialAIHandler.saveSpecialAI |
⚠️ 每个 AI 都在
tag上对应持久化 NBT 键,保证只注入一次(重新进入世界不会重复加)。
死亡事件
onLivingDeath 当 call_for_help_on_death > 0 时按 SharedMonsterAttributes.followRange(默认 16)搜索同种/同祖先的同盟生物,让它们把 setAttackTarget(target) 指向击杀者。
物品归还
每 tick 末尾遍历 loadedEntityList 中所有 EntityItem:若 NBT 含 ThiefUUIDMost / ThiefUUIDLeast:
- 查找对应 UUID 的活体
EntityLiving - 把物品塞入主手(slot 0),设置
setEquipmentDropChance(0, 2.0F)(不掉落),func_110163_bv()标记永不过期 setDead()移除物品实体
这是偷窃 AI 把偷到的物品自动送到偷窃者手里的归还机制。
扫描速率节流
scan_count_global > 0 时整个 mod 全部实体的 EntityAIGriefBlocks.shouldExecute 每 tick 调用 AIHandler.canScan(),全局每 tick 用满 scan_count_global 配额即停止扫描,避免卡顿。
互斥位(mutex bits)
| 常量 | 值 | 含义 |
|---|---|---|
BIT_NONE |
0 | 不与任何 AI 互斥 |
BIT_MOVEMENT |
1 | 与移动类 AI 互斥 |
BIT_FACING |
2 | 与朝向类 AI 互斥 |
BIT_SWIMMING |
4 | 与游泳类 AI 互斥 |
TARGET_BIT |
1 | 所有 target AI 共享互斥 |
注:源码中
BIT_MOVEMENT/BIT_FACING/BIT_SWIMMING与TARGET_BIT的二进制值都是 1,但它们注册在tasks与targetTasks两个独立列表里,因此不会相互干扰。