睁开双眼

睁开双眼

API for Logica

项目概览

1.1 设计理念

Aperi Oculos 是为 Minecraft 设计的感知层框架:

Aperi Oculos(感知层)包含视觉系统与听觉系统(振动系统)。它会广播事件,并为上层 AI 模组(决策层)提供 API,用于处理行为树/状态机、群体警报逻辑以及寻路等。

核心原则:

  • 单一职责:仅回答“生物能感知到什么?”
  • 零耦合:不包含任何 AI 行为逻辑。
  • 数据驱动:高度可配置,支持整合包自定义。
  • 性能优先:多层缓存 + 惰性求值 + 优先执行低成本检查。

视觉系统

工作流程

流程从 ServerTickEvent 开始。每 10 tick 遍历所有玩家,检查玩家附近是否存在生物。若存在,则进行距离检查以判断生物是否处于 FOLLOW_RANGE 范围内。若在范围内,则进行视场(FoV)角度检查。若玩家处于 FoV 内,则进行光照等级检查。若玩家不在潜行光照范围内,则结合缓存进行视线(LOS)检查。若视线畅通,触发 TargetSpottedEvent,随后进行条件日志记录。

关键特性

  1. 主动扫描机制

    // 以玩家为中心,避免遍历所有生物
    AABB scanBounds = player.getBoundingBox().inflate(MAX_SCAN_RADIUS);
    for (PathfinderMob mob : level.getEntitiesOfClass(PathfinderMob.class, scanBounds)) {
        if (AperiOculosAPI.canSee(mob, player)) {
            MinecraftForge.EVENT_BUS.post(new TargetSpottedEvent(mob, player));
        }
    }
    
  2. 五级检查梯度

    • 检查顺序:隐身 → 距离 → 视场 → 光照等级 → 视线
    • 性能开销:O(1) O(1) O(1) O(1) O(n) [n=路径上的方块数]
  3. 隐身检查

    • 如果目标拥有隐身效果 (MobEffects.INVISIBILITY),则无法被看见。
    • 例外:如果目标同时拥有发光效果 (MobEffects.GLOWING),则可以看见。
    • 这实现了一种类似原版的隐身机制,但效率更高。
  4. 夜视豁免

    • 支持药水效果 (MobEffects.NIGHT_VISION)
    • 支持实体标签 (#minecraft:undead)
    • 支持直接 ID (minecraft:spider)

听觉系统(振动系统)

工作原理

基于 Minecraft 原版的 GameEvent 系统(与幽匿感测体相同来源),监听世界中发生的所有“振动”事件。

@SubscribeEvent
public void onGameEvent(VanillaGameEvent event) {
    GameEvent gameEvent = event.getVanillaEvent();
    Vec3 sourcePos = event.getEventPosition();

    // 获取事件的基础传播半径
    int baseRadius = gameEvent.getNotificationRadius();

    // 为每个潜在监听者计算有效范围
    for (Mob listener : nearbyMobs) {
        // 从 Capability 读取
        double hearingMultiplier = getHearingMultiplier(listener);
        double effectiveRange = baseRadius * hearingMultiplier;

        if (distance <= effectiveRange && !isOccluded(listener, sourcePos)) {
            MinecraftForge.EVENT_BUS.post(
                new VibrationPerceivedEvent(listener, sourcePos, gameEvent, ...)
            );
        }
    }
}

能力系统

存储:为每个 LivingEntity 附加 IHearingCapability

// 读取
double multiplier = entity.getCapability(HearingCapabilityProvider.HEARING_CAPABILITY)
    .map(IHearingCapability::getHearingMultiplier)
    .orElse(1.0);

// 修改(需要同步到客户端)
entity.getCapability(HearingCapabilityProvider.HEARING_CAPABILITY)
    // 听觉提升 2 倍
    .ifPresent(cap -> cap.setHearingMultiplier(2.0));

自定义吸引范围

可以为特定的 GameEvent 覆盖默认传播范围:

[hearing]
customAttractionRanges = [
    "minecraft:projectile_land = 16.0",  # 抛射物着陆:16 格
    "minecraft:hit_ground = 8.0",        # 实体着陆:8 格
    "minecraft:explode = 32.0"           # 爆炸:32 格
]

吸引持续时间(10 秒)

vibrationAttractionDurationTicks = 200

遮挡检测

# 可选:声音是否能无损耗穿过墙壁
# true=启用遮挡衰减,false=声音穿过墙壁
enableVibrationOcclusion = false