-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ and Troubleshooting
Check the basics first, in order:
- Are you actually calling
runtime.tick()from your entity'stick()method, guarded by!level().isClientSide() && isAlive() && !isNoAi()? AzureCortex does nothing on its own, nothing ticks aCortexRuntimefor you. - Is
isNoAi()true on the entity (e.g. spawned via/summon ... {NoAI:1}, or a passive display entity)?CortexRuntime.tick()no-ops immediately ifagent.isNoAi(). - Did you remove the conflicting vanilla goals (
NearestAttackableTargetGoal, movement goals, etc.) fromregisterGoals()? Leaving both vanilla's own targeting/movement goals and AzureCortex active on the same entity means they'll fight over the same navigator and target, see Full Example Walkthrough step 4.
This is almost always a min-commit/priority-tuning issue, not a bug in the framework:
- If two goals score too closely and
minCommitTicksis too low,GoalExecutor.shouldReplanwill let the planner swap between them constantly. RaiseminCommitTicks, or bias the scoring further apart. - If two tree branches have equal or near-equal priority and their preconditions both hold intermittently (e.g. a
target flickering in and out of range), consider a
CooldownGatearound the noisier branch, or tighten the precondition's hysteresis (e.g. require a slightly larger "leave" threshold than the "enter" threshold). - Check whether
PlanInvalidationis firing more than expected, a target's distance bucket flipping back and forth right at a bucket boundary will force replans repeatedly.WorldStateSnapshot's buckets are deliberately coarse for this reason; if you're still seeing boundary flicker, that suggests the agent is genuinely hovering at a boundary (e.g. orbiting at maximum engagement range) worth addressing in the action's own movement logic.
Check its interruptCategory(). An action reporting LOCKED (or isInterruptible() == false) can only be
preempted by an EMERGENCY candidate, a higher-priority NORMAL candidate will never take over. This is
deliberate (see Core Concepts) but is a common surprise the first time someone builds a "committed" action and
then can't figure out why nothing else ever wins.
GoalUrgency.EMERGENCY on the GOAP side only controls whether the planner is allowed to replan immediately —
it says nothing about tree-side preemption. The resulting action also needs a high enough priority (and/or an
InterruptCategory.EMERGENCY on the action itself, or via BehaviorResult.runEmergency) to actually win against
whatever's currently running in the tree. See the eat-to-heal branch in Full Example Walkthrough for a worked
example of getting both sides to agree.
- Check
maxRange, both pathfinders cap search cost by Manhattan distance from the start; a path outside that range is never found.AStarPathfinderalso caps at 2,000 expanded nodes (6,000 forCrawlTraversalEvaluator) regardless of range. - If you're using
MovementCapability/CrawlCapabilityand haven't implemented them on your entity, you get the fully-permissive defaults, that shouldn't block a path, but double-check you haven't accidentally marked something as a hazard/non-passable that should be walkable. - Remember both pathfinders return the best partial path rather than an empty list whenever a full route can't be found within budget, so "empty list" specifically means no progress was made at all (e.g. start position itself isn't standable), not merely "goal unreachable."
You don't get this for free, both Blackboard and AgentMemory are transient, in-memory stores discarded when the
entity is removed from the world (including on unload/save). If something needs to survive, persist it yourself via
your entity's addAdditionalSaveData/readAdditionalSaveData and re-populate the relevant blackboard/memory key on
load.
Yes. CortexRuntime only requires a BehaviorNode tree and (optionally) a Sensor, nothing about GoalPlanner,
PlannedGoal, or GoalExecutor is mandatory. A tree built entirely from PrioritySelector/Condition/ActionNode
against blackboard state you manage yourself (without ever touching ACTIVE_GOAL_TYPE) works fine for simpler agents
that don't need multi-goal planning.
Only if your agent targets other entities. Purely environmental/wandering agents (no combat, no pursuit) can use
CortexRuntime with a null sensor and a tree built from movement/utility actions alone.
- Source & issue tracker: https://github.com/AzureDoom/AzureCortex
- CurseForge: https://www.curseforge.com/minecraft/mc-mods/azurecortex
- Modrinth: https://modrinth.com/project/azurecortex
If your question isn't answered here, the Full Example Walkthrough and the relevant reference page (linked from Home) are the next places to check, most of AzureCortex's classes carry substantial Javadoc explaining why a given piece of behavior exists, not just what it does.