No description
- Python 100%
Next tier down by usage frequency (11 and 5-6 occurrences). Verified against each class's decompiled source: - FollowParentGoal: only usable while the animal is a baby, holds a rough 3-16 block follow band rather than beelining onto the parent. - ResetUniversalAngerTargetGoal: only matters if the universalAnger gamerule is on; alertOthersOfSameType mirrors HurtByTargetGoal's same-class alert pattern almost exactly (same FOLLOW_RANGE/±10 box). - RangedAttackGoal: never finds its own target (reads whatever targetSelector already set); the 4-arg constructor interpolates shot cadence by distance, faster up close. - LeapAtTargetGoal: only fires in a 2-4 block band, and even then only on a ~1-in-3 per-tick roll (reducedTickDelay halves the literal "5") - explains why leaps look bursty rather than immediate. - PatrollingMonster.LongDistancePatrolGoal: doesn't decide to patrol, just executes an already-assigned destination; patrol leaders push new waypoints to companions directly, which is why patrols move as a pack. Coverage: 48 -> 50 mob reports (the remaining uncovered classes mostly appear only on 1-2 mobs each, so this is a reasonable stopping point). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| analysis | ||
| scripts | ||
| .gitignore | ||
| README.md | ||
Minecraft Mob AI Investigation
Pulls the official Mojang server jar for a given version, decompiles it, and extracts every mob's AI logic (goal-selector priorities and brain activities/behaviors) into readable per-mob reports.
Minecraft's server jar is no longer obfuscated as of recent versions — Mojang ships it with real class/method names, so no separate deobfuscation mapping step is needed, just a plain decompiler.
Pipeline
tools/jdk/— portable JDK 21 (Temurin), used to run the decompiler.tools/vineflower.jar— decompiler.versions/<version>/server.jar— downloaded from Mojang's version manifest.versions/<version>/src/— decompiled source (via Vineflower).scripts/extract_mob_ai.py— parsesnet.minecraft.world.entity.*classes forregisterGoals()(classic goal system) andBrain.Providersetups (activity/behavior system), writinganalysis/mob_ai.json.scripts/generate_reports.py— turns that JSON intoanalysis/mobs/*.md(one file per mob) plusanalysis/index.md.
Outputs
Two deliberately different artifacts, both under analysis/:
mob_ai.json— machine-readable. One record per mob with the full, untruncated data: every goal/behavior's raw expression text, priorities, weighted-choice sublists, sensors, memory types, etc. This is the thing to parse if you're writing another tool against the extracted data.mobs/*.md+index.md— human-readable. Same underlying data, formatted as prose explanations, fenced/pretty-printed Java snippets, and an index grouped by mob category (Monsters / Animals / NPCs / Bosses / Raiders). This is the thing to actually read.
Reproducing for a new version
# 1. Get the version's server jar URL from Mojang's manifest, download it to
# versions/<version>/server.jar, then unzip the nested
# META-INF/versions/<version>/server-<version>.jar (bundler format).
# 2. Decompile:
tools/jdk/bin/java -jar tools/vineflower.jar -log=WARN \
versions/<version>/META-INF/versions/<version>/server-<version>.jar \
versions/<version>/src/
# 3. Extract + report (edit VERSION_DIR in both scripts first):
python3 scripts/extract_mob_ai.py
python3 scripts/generate_reports.py
Notes / limitations
tools/andversions/are gitignored: the JDK/decompiler are large binaries, and the Mojang jars + decompiled source aren't ours to redistribute (Mojang's EULA permits decompiling your own copy for personal study/modding, not republishing the result).analysis/— our own derived notes about goal names, priorities, and behavior structure — is the actual output of this project.- The extractor is regex/brace-matching based, not a real Java parser. It
handles the common patterns well — Guava's
Pair.of(priority, behavior)lists, thenew Pair[]{...}overflow-array pattern for lists with more than 12 entries, and the weighted random-choice sublists insideRunOneandTriggerGate.triggerOneShuffled/triggerGate— but for a mob with unusual code layout, the decompiled source inversions/<version>/src/is the ground truth — check it directly. - Expressions are pretty-printed by breaking top-level arguments onto their
own line once they get long, recursing into single-argument wrapper calls
(e.g.
TriggerGate.triggerOneShuffled(ImmutableList.of(...))). It doesn't understand lambdas or anonymous-class bodies, so those occasionally still render as one long (but complete, untruncated) line. - Mobs that only inherit AI from a superclass without overriding it (e.g.
HuskinheritsZombie's goals untouched) don't get their own entry; look up the superclass's report instead.