Skip to content

Profile API ​

The MobProfile is the blueprint for a custom mob. It is immutable and contains all the logic, stats, and behaviors needed to spawn and tick a mob.

Structure ​

A MobProfile consists of:

  • ID (String): Unique identifier (e.g., custom:raider).
  • Entity Type (EntityType): The Minestom entity type (e.g., ZOMBIE, VILLAGER).
  • Stats (MobStats): Combat and movement attributes that scale with level.
  • Goals (List<GoalFactory>): AI goals (e.g., wander, attack).
  • Targets (List<TargetFactory>): AI target selectors (e.g., nearest player).
  • Lifecycle Hooks: Callbacks for specific entity events.

MobStats ​

MobStats defines the base attributes of the mob and how they increase per level.

AttributeDescriptionBase ValuePer Level Increase
HealthMax health of the mob.baseHealthhealthPerLevel
AttackMelee damage dealt.baseAttackattackPerLevel
SpeedMovement speed (blocks/tick).baseMoveSpeedspeedPerLevel
ArmorDamage reduction.baseArmorarmorPerLevel
Follow RangeDistance to track targets.baseFollowRangefollowRangePerLevel

Example Stats Calculation ​

If a mob is spawned at Level 5: $$ \text{Total Health} = \text{baseHealth} + (\text{healthPerLevel} \times (5 - 1)) $$

Lifecycle Hooks ​

Hooks allow you to run custom code when specific events occur.

onSpawn ​

Triggered immediately after the mob is spawned into the instance.

  • Use Case: Equip items, set custom metadata, play a sound.

onTick ​

Triggered every tick (50ms).

  • Use Case: Custom particles, regeneration, conditional checks.

onDeath ​

Triggered when the mob dies.

  • Use Case: Custom drops, explosion effects, chat messages.

onAttack ​

Triggered when the mob successfully attacks a target.

  • Use Case: Apply potion effects (poison, slow), knockback.

Creating Profiles ​

You can build profiles using the fluid Java Builder or the Kotlin DSL.

java
var profile = MobProfileBuilder.create("custom:raider", EntityType.HUSK)
    .stats(new MobStats(
        28.0, 4.5,   // Health (Base, PerLevel)
        6.0, 1.4,    // Attack
        0.26, 0.012, // Speed
        3.0, 0.25,   // Armor
        30.0, 0.25   // Follow Range
    ))
    .onSpawn(mob -> {
        mob.setItemInMainHand(ItemStack.of(Material.IRON_AXE));
        mob.setCustomName(Component.text("Raider"));
        mob.setCustomNameVisible(true);
    })
    .onDeath((mob, killer) -> {
        // Drop custom loot
        if (killer instanceof Player) {
             mob.getInstance().dropItem(ItemStack.of(Material.EMERALD), mob.getPosition());
        }
    })
    .applyPathing(PathingPresets.hostileMelee(
        0.26, // Speed match stats
        20,   // Attack delay
        30.0, // Search range match stats
        true, // Line of sight
        entity -> true // Target everyone
    ))
    .build();
kotlin
import codes.bed.minestom.mobs.dsl.mobProfile

val profile = mobProfile("custom:guardian", EntityType.DROWNED) {
    stats(MobStats(
        baseHealth = 34.0, healthPerLevel = 4.0,
        baseAttack = 7.0, attackPerLevel = 1.0,
        baseMoveSpeed = 0.24, speedPerLevel = 0.01,
        baseArmor = 2.0, armorPerLevel = 0.2,
        baseFollowRange = 32.0, followRangePerLevel = 0.5
    ))

    onSpawn { mob ->
        mob.itemInMainHand = ItemStack.of(Material.TRIDENT)
    }

    onAttack { mob, target ->
         // 50% chance to poison target
        if (Math.random() < 0.5 && target is LivingEntity) {
             target.addEffect(PotionEffect(PotionEffectType.POISON, 1, 100))
        }
    }

    pathing(
        PathingPresets.hostileMelee(
            speed = 0.24,
            attackDelay = 16,
            searchRange = 32.0
        )
    )
}

Registration ​

Before you can spawn a mob by its ID, you must register the profile with the spawner.

kotlin
// Register single
spawner.register(profile)

// Register multiple
spawner.registerAll(listOf(profileA, profileB))
java
// Register single
spawner.register(profile);

// Register multiple
spawner.registerAll(List.of(profileA, profileB));

Released under the MIT License.