Skip to content

Spawn Rules ​

spawn_rules/*.yml spawn rules define under which conditions a custom mob appears. Spawn rule files live in plugins/EmakiMobs/spawn_rules/*.yml. Each file can contain multiple rules under a rules: list. A missing file, a missing rules key, or a rules value that is not a list produces no rules at all. The rules released on first start are spawn_rules/overworld_elites.yml (a single natural rule)

File structure ​

yaml
rules:
  - mob_id: <mob id>
    type: <spawn type>
    # type-specific fields...

Only two type values are accepted ​

The current loader recognises only type: natural and type: autonomous. Writing structure, biome, player_relative, day_interval, custom or anything else does not raise an error — it is logged as Unknown spawn type and the whole rule is skipped silently. A missing mob_id or type skips the rule with a WARN

Two rules in the bundled reference file spawn_rules/overworld.yml are never loaded

That file lives inside the plugin jar and is not released into plugins/EmakiMobs/spawn_rules/ (the first-start release is overworld_elites.yml). It holds three rules: the natural one (elite_zombie) works, while type: structure (bone_lord) and type: biome (jungle_stalker) hit the unknown-type branch above and are skipped silently. Rewrite those two using the natural / autonomous forms documented here if you copy the file


natural — intercept vanilla spawn events ​

Replaces naturally spawning mobs with a custom mob by probability once the conditions hold. Natural spawns are intercepted at PreCreatureSpawnEvent (before the entity is created); other spawn reasons that are neither NATURAL nor SPAWNER are intercepted at CreatureSpawnEvent, which is cancelled

yaml
- mob_id: elite_zombie
  type: natural
  biomes: [plains, forest]   # optional biome restriction; empty means any
  y_range: [-64, 50]         # only replace within this Y range
  light_level_max: 7         # inclusive light level ceiling
  replacement_chance: 0.08   # replacement probability, 0.0–1.0
  max_nearby: 3              # max same-id mobs within 64 blocks; 0 = unlimited
  count:
    min: 1
    max: 1
FieldTypeRequiredDefaultAccepted valuesDescription
mob_idstringYesnonea loaded mob definition idThe mob to spawn; a missing or non-string value skips the whole rule. An unregistered id spawns nothing
typestringYesnonenaturalFixed value
worldsstring listNo[] (any)world names (World#getName)Restrict to these worlds
biomesstring listNo[] (any)biome keys, optionally namespaced (the part after : is taken, lower-cased)Restrict to these biomes; an unrecognised name logs a WARN and is dropped while the rest of the rule still applies
y_rangeint list [min, max]No[-64, 320]read positionally: item 1 is min, item 2 is max; missing items fall back to the defaultY range of the spawn position (inclusive)
light_level_maxintNo150–15The spawn position's combined light level must not exceed this; the default 15 means no restriction
replacement_chancedoubleNo1.0—Replacement probability once conditions match: 0.0 never replaces, ≥ 1.0 always replaces (not clamped)
max_nearbyintNo0≥ 0; 0 = unlimitedSkip the trigger once this many same-id managed mobs exist within 64 blocks
count{min, max}No{1, 1}min ≤ maxMobs spawned per trigger (random range, inclusive). min > max throws when the rule fires, so that replacement fails
conditionsectionNononea CoreLib condition blockExtra conditions. There is no player context, so player placeholders cannot be used here (unlike autonomous)

autonomous — self-scheduled spawning ​

Runs entirely outside vanilla spawn events, driven by its own scheduler. trigger selects the scheduling mode. Candidate positions are generated at a random angle at distance from the player, with up to 6 attempts, requiring a passable block above solid ground — so not every attempt produces a spawn

yaml
- mob_id: elite_zombie
  type: autonomous
  trigger: interval
  interval_ticks: 1200
  worlds:
    - world
  biomes:
    - plains
  distance:
    min: 16
    max: 64
  max_nearby: 4
  max_global: 10
  count:
    min: 1
    max: 2

The four triggers ​

triggerSchedulingKey fields
intervalGlobal fixed rate (first run 1 tick after start); each round scans every online player and attempts once per playerinterval_ticks, worlds, max_global
player_followGlobal fixed rate; each round picks one random online player and attempts onceinterval_ticks, worlds, max_global
day_intervalChecks each world's in-game day counter every 20 ticks (last trigger day stored per world) and attempts once for every player in that world when dueinterval_days, on_day_start, worlds, max_global
cronFires on real system time via a Cron expression and attempts once per online playercron, worlds, max_global

trigger values are case-insensitive. cron uses the 6-field Quartz format (second minute hour day-of-month month day-of-week), documented in CoreLib expressions - Cron; a blank or unparsable expression is logged as a warning and the rule never fires

autonomous fields ​

FieldTypeRequiredDefaultAccepted valuesDescription
mob_idstringYesnonea loaded mob definition idThe mob to spawn; a missing or non-string value skips the whole rule
typestringYesnoneautonomousFixed value
triggerstringYesnoneinterval / player_follow / day_interval / cron (case-insensitive)Scheduling mode. Missing or unknown skips the whole rule with a WARN
interval_tickslongNo600≥ 1 (ticks)Scheduling period for interval / player_follow
interval_daysintNo1≥ 1 (in-game days)Interval in in-game days for day_interval
on_day_startbooleanNofalsetrue / falseWhen true, only fires while that world's time is < 1000 (just after sunrise); when false, it fires as soon as the counter is due
cronstringNo""a 6-field Quartz expressionExpression for trigger: cron; when blank a warning is logged and the rule never fires
worldsstring listNo[] (any)world namesRestrict to these worlds
biomesstring listNo[] (any)biome keys (same as natural)Restrict the spawn position's biome
structuresstring listNo[] (any)NamespacedKeys such as minecraft:strongholdRestrict to positions inside that structure's bounding box in the chunk; an unknown structure logs a WARN and is dropped
y_rangeint list [min, max]No[-64, 320]same as naturalY range of the spawn position (inclusive)
light_level_maxintNo150–15Combined light ceiling. Only checked when the value is below 15; the default 15 skips the light check entirely
time_of_daystringNoanyany / day (1000–12999) / night (≥ 13000 or < 1000) (case-insensitive)Restrict the time of day; an unknown value behaves like any
require_surfacebooleanNofalsetrue / falseWhen true, the spawn position must have sky light 15
distance{min, max}No{16, 64}≥ 0 (blocks)Spawn distance from the player (inclusive); when min ≥ max the value is fixed to min
max_nearbyintNo0≥ 0; 0 = unlimitedMax same-id managed mobs within 64 blocks
max_globalintNo0≥ 0; 0 = unlimitedGlobal cap on same-id mobs across all worlds; when reached the whole round is skipped
count{min, max}No{1, 1}≥ 1Mobs spawned per trigger (random range, inclusive); when min ≥ max the value is fixed to min
conditionsectionNononea CoreLib condition blockExtra conditions; the player that triggered this attempt is the context, so PlaceholderAPI placeholders are rendered

How this differs from natural

A natural rule's condition has no player context, while an autonomous rule renders placeholders from the player being attempted. Both types collapse count and distance to a fixed value when min and max are equal