我的世界1.20.1forge开发进阶教程——生物AI(1)
进阶教程之生物AI
- 生物AI
 - 
   
- GoalSelector类
 - 
     
- 一、核心架构
 - 二、核心方法解析
 - 三、标志冲突管理机制
 - 四、性能优化特性
 - 五、典型应用场景
 
 - FleeSunGoal
 - 
     
- 一、代码作用解析
 - 
       
- 1. **触发条件**(`canUse()` 方法)
 - 2. **遮蔽位置搜索**(`getHidePos()` 方法)
 - 3. **行为执行**
 
 - 二、与 `GoalSelector` 的联系
 - 
       
- 1. **注册到生物 AI 系统**
 - 2. **标志冲突管理**
 - 3. **调度流程**
 
 - 三、实际应用场景
 - 四、总结
 
 - FollowParentGoal类介绍
 - 
     
- 代码原理剖析
 - 
       
- 1. 继承体系
 - 2. 距离优化策略
 - 3. 实体搜索机制
 - 4. 导航系统集成
 - 5. 生命周期管理
 
 - 语法特点分析
 - 
       
- 1. 类型强制转换
 - 2. 原始类型使用
 - 3. 数值比较方式
 - 4. 位运算优化
 - 5. 方法命名规范
 
 - 设计模式应用
 - 
       
- 1. 模板方法模式
 - 2. 观察者模式
 - 3. 策略模式
 
 - 性能优化点
 - 典型应用场景
 
 
 - Minecraft的导航系统
 - 
   
- `PathNavigation` 类详解
 - 
     
- 
       
- 一、核心职责
 - 二、核心成员变量解析
 - 三、关键方法解析
 - 
         
- 1. 路径创建与更新
 - 2. 每刻更新逻辑(`tick()`)
 - 3. 路径跟随(`followThePath()`)
 - 4. 卡顿检测(`doStuckDetection()`)
 
 - 四、关键算法与设计模式
 - 
         
- 1. 路径搜索算法
 - 2. 状态模式应用
 - 3. 性能优化策略
 
 - 五、子类化与扩展
 - 
         
- 1. 抽象方法说明
 - 2. 典型子类
 
 - 六、与Minecraft其他系统的交互
 
 - 总结
 
 - 
       
 - PathFinder
 - 
     
- 一、代码作用与原理
 - 
       
- 1. **核心功能**
 - 2. **关键算法逻辑**
 
 - 二、与 `PathNavigation` 的区别与联系
 - 
       
- 1. **分工关系**
 - 2. **协作流程**
 
 - 三、代码实现特点
 - 
       
- 1. **数据结构优化**
 - 2. **多目标处理**
 - 3. **地形适应性**
 
 - 四、性能关键设计
 - 五、与同类系统的对比
 - 六、应用场景
 
 - GroundPathNavigation类
 - 
     
- **代码作用**
 - **代码逐段解析**
 - 
       
- **1. 初始化与依赖**
 - **2. 路径查找器初始化**
 - **3. 路径更新条件**
 - **4. 处理目标位置**
 - **5. 水中路径修正**
 - **6. 避开阳光的逻辑**
 - **7. 路径类型验证**
 - **8. 可配置方法**
 
 - **设计优势分析**
 - **潜在改进点**
 - **总结**
 
 
 - Mob类
 - 
   
- 
     
- `Mob` 类详解
 - 
       
- 一、核心功能与原理
 - 
         
- 1. **AI 系统控制**
 - 2. **路径导航集成**
 - 3. **装备与交互**
 - 4. **环境适应**
 
 - 二、与 `PathNavigation` 和 `PathFinder` 的协作
 - 
         
- 1. **层级调用关系**
 - 2. **关键交互点**
 - 3. **区别对比**
 
 - 三、核心代码解析
 - 
         
- 1. **导航初始化**
 - 2. **AI 与导航协同**
 - 3. **路径惩罚应用**
 
 - 四、典型应用场景
 - 
         
- 1. **僵尸追击玩家**
 - 2. **村民工作路径**
 - 3. **跨地形移动**
 
 - 五、性能与优化策略
 
 - 总结
 
 
 - 
     
 - MoveControl类
 - 
   
- 
     
- **代码作用**
 - **核心原理**
 - **代码架构优势**
 - **关键方法解析**
 - **使用场景示例**
 - **总结**
 
 
 - 
     
 - NearestAttackableTargetGoal类
 - 
   
- 
     
- **代码作用**
 - **代码原理**
 - **代码架构分析**
 - **类在 Minecraft 中的作用**
 - **代码示例与场景**
 - 
       
- **自定义过滤条件**
 - **生物类型扩展**
 
 - **架构优势**
 - **潜在改进点**
 - **总结**
 
 
 - 
     
 - 作业:
 
生物AI
生物AI分两部分,一部分是目标选择AI,一部分是行为AI,对应targetSelector和goalSelector。分享点赞过100免费公布我自己的实体代码
GoalSelector类
package net.minecraft.world.entity.ai.goal;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import net.minecraft.util.profiling.ProfilerFiller;
import org.slf4j.Logger;
public class GoalSelector {
   
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final WrappedGoal NO_GOAL = new WrappedGoal(Integer.MAX_VALUE, new Goal() {
   
        @Override
        public boolean canUse() {
   
            return false;
        }
    }) {
   
        @Override
        public boolean isRunning() {
   
            return false;
        }
    };
    private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap(Goal.Flag.class);
    private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet();
    private final Supplier<ProfilerFiller> profiler;
    private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
    private int tickCount;
    private int newGoalRate = 3;
    public GoalSelector(Supplier<ProfilerFiller> supplier) {
   
        this.profiler = supplier;
    }
    public void addGoal(int i, Goal goal) {
   
        this.availableGoals.add(new WrappedGoal(i, goal));
    }
    @VisibleForTesting
    public void removeAllGoals(Predicate<Goal> predicate) {
   
        this.availableGoals.removeIf((wrappedgoal) -> {
   
            return predicate.test(wrappedgoal.getGoal());
        });
    }
    public void removeGoal(Goal goal) {
   
        this.availableGoals.stream().filter((wrappedgoal) -> {
   
            return wrappedgoal.getGoal() == goal;
        }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop);
        this.availableGoals.removeIf((wrappedgoal) -> {
   
            return wrappedgoal.getGoal() == goal;
        });
    }
    private static boolean goalContainsAnyFlags(WrappedGoal wrappedgoal, EnumSet<Goal.Flag> enumset) {
   
        Iterator iterator = wrappedgoal.getFlags().iterator();
        Goal.Flag goal_flag;
        do {
   
            if (!iterator.hasNext()) {
   
                return false;
            }
            goal_flag = (Goal.Flag) iterator.next();
        } while (!enumset.contains(goal_flag));
        return true;
    }
    private static boolean goalCanBeReplacedForAllFlags(WrappedGoal wrappedgoal, Map<Goal.Flag, WrappedGoal> map) {
   
        Iterator iterator = wrappedgoal.getFlags().iterator();
        Goal.Flag goal_flag;
        do {
   
            if (!iterator.hasNext()) {
   
                return true;
            }
            goal_flag = (Goal.Flag) iterator.next();
        } while (((WrappedGoal) map.getOrDefault(goal_flag, GoalSelector.NO_GOAL)).canBeReplacedBy(wrappedgoal));
        return false;
    }
    public void tick() {
   
        ProfilerFiller profilerfiller = (ProfilerFiller) this.profiler.get();
        profilerfiller.push("goalCleanup");
        Iterator iterator = this.availableGoals.iterator();
        WrappedGoal wrappedgoal;
        while (iterator.hasNext()) {
   
            wrappedgoal = (WrappedGoal) iterator.next();
            if (wrappedgoal.isRunning() && (goalContainsAnyFlags(wrappedgoal, this.disabledFlags) || !wrappedgoal.canContinueToUse())) {
   
                wrappedgoal.stop();
            }
        }
        iterator = this.lockedFlags.entrySet().iterator();
        while (iterator.hasNext()) {
   
            Entry entry = (Entry) iterator.next();
            if (!((WrappedGoal) entry.getValue()).isRunning()) {
   
                iterator.remove();
            }
        }
        profilerfiller.pop();
        profilerfiller.push("goalUpdate");
        iterator = this.availableGoals.iterator();
        while (iterator.hasNext()) {
   
            wrappedgoal = (WrappedGoal) iterator.next();
            if (!wrappedgoal.isRunning() && !goalContainsAnyFlags(wrappedgoal, this.disabledFlags) && goalCanBeReplacedForAllFlags(wrappedgoal, this.lockedFlags) && wrappedgoal.canUse()) {
   
                Iterator iterator1 = wrappedgoal.getFlags().iterator();
                while (iterator1.hasNext()) {
   
                    Goal.Flag goal_flag = (Goal.Flag) iterator1.next();
                    WrappedGoal wrappedgoal1 = (WrappedGoal) this.lockedFlags.getOrDefault(goal_flag, GoalSelector.NO_GOAL);
                    wrappedgoal1.stop();
                    this.lockedFlags.put(goal_flag, wrappedgoal);
                }
                wrappedgoal.start();
            }
        }
        profilerfiller.pop();
        this.tickRunningGoals(true);
    }
    public void tickRunningGoals(boolean flag) {
   
        ProfilerFiller profilerfiller = (ProfilerFiller) this.profiler.get();
        profilerfiller.push("goalTick");
        Iterator iterator = this.availableGoals.ite
                