Skip to content

Custom Mobs

Alexander Parent edited this page Jul 31, 2026 · 1 revision

Custom Mobs

A mob the game does not ship is composed, not subclassed. Four immutable pieces answer four separate questions, and none is inferred from another.

Piece Answers
MobTraversalProfile what terrain costs, and what it may pass or open
TerrainClassification what an unknown block is
GroundCapabilities what the body can physically do
NavigationInfluence what this one request wants
TerrainClassification moddedTerrain = TerrainClassification.ofBlocks(Map.of(
        Block.SCULK, TerrainType.DAMAGING,
        Block.SLIME_BLOCK, TerrainType.STICKY_HONEY));

MobTraversalProfile ashcrawler = MobTraversalProfile.builder("ashcrawler")
        .from(MobTraversalProfile.STRIDER)   // walks lava, refuses water
        .malus(TerrainType.DAMAGING, 4)      // singed, not stopped
        .canOpenDoors(true)
        .classification(moddedTerrain)
        .build();

GroundCapabilities body = GroundCapabilities.builder()
        .platformJump(PlatformJumpCapabilities.acrossGaps(3))
        .climbables(ClimbableCapabilities.STANDARD)
        .build();

NavigationProfile profile =
        NavigationProfile.builder(NavigationMode.GROUND, ashcrawler, body)
                .avoidSun(true)
                .build();

EntityNavigationController controller =
        navigation.controller(entity, profile, 0.2);

Every flag defaults to false, so a built profile states only what it turns on. Capabilities are built rather than constructed positionally, because a transposed pair of distances would otherwise compile into a different mob.

Naming your own blocks

ofBlocks matches by block identity, ignoring state, so Block.WHEAT covers wheat at every age. A plain Map<Block, TerrainType> lookup would not: block equality is state-sensitive, so grown wheat is not equal to the constant.

The map is the equality key, so two mobs given the same mapping may share a computed route without anyone stamping a version string.

A classified block picks up every rule that already reads that type: maluses, the corner-cut and diagonal rules, the DAMAGING_IN_NEIGHBOR halo the search paints around it, and the platform-jump landing test.

Three limits:

  • It maps onto the existing 27 TerrainTypes and cannot add new ones.
  • It renames terrain only. Collision shape, fluid presence and the climbable and openable tags stay Minestom's, so a renamed block is priced differently but occupies exactly the space it did.
  • It must answer from the block alone. One search asks at most once per distinct block state and reuses the answer.

Built-in profiles

BuiltinNavigationProfiles.forEntityType(EntityType.ZOMBIE);
BuiltinNavigationProfiles.forEntity(entity);   // uses live metadata too

Navigation modes are chosen from the entity type: ground, water-volume, flying-volume, amphibious and wall-climber. Amphibious is the ground graph plus two vertical WATER neighbours rather than free 3D swimming, and spiders use ground A* with the wall-climber follower fallback, matching the game.

Clone this wiki locally