API reference / @jsprismarine/spawning
@jsprismarine/spawning
Bedrock natural spawning: the spawn_rules/*.json grammar, the condition evaluator, the population pools and the spawn loop. It builds on @jsprismarine/packs for the filter grammar, on @jsprismarine/entities for the filter evaluator that spawn rules, entity definitions and trade tables all share, and on @jsprismarine/predicates for the injected random source.
import { Spawner, parseSpawnRule } from '@jsprismarine/spawning';
import { seededRandom } from '@jsprismarine/predicates';
const rules = files.map((file) => parseSpawnRule(file.data, { pack: file.pack, path: file.path }));
const spawner = new Spawner({ rules: rules.filter((rule) => rule !== undefined), world, random: seededRandom(seed) });
for (const request of spawner.tick(tick)) {
world.create(request.identifier, request.position, request.spawnEvent);
}The grammar
A file is {"format_version": "<semver>", "minecraft:spawn_rules": {description, conditions}}. description carries identifier and population_control; conditions is a list of alternatives, and a rule allows a position when any one of them does.
parseSpawnRule reads all 24 components Spawn Rules.json declares and reports an unknown one rather than refusing the file, so a pack written against a newer game still loads. Vanilla writes 21 of the 24. The three it never writes, minecraft:spawns_above_block_filter, minecraft:is_persistent and minecraft:is_experimental, parse into the condition and keep their meaning for the caller, because Mojang documents none of them.
Three components are written in more than one shape, and all of them read:
minecraft:spawns_on_block_filteras one name, as a list of names, or as a list of{name}objects.minecraft:herdas one object or as a list of alternatives, which is how the tropical fish picks a color event.minecraft:biome_filteras one test, as a bare array (an implicitall_of), or as a group map.@jsprismarine/packsparses it, including the integersubjectandoperatorencoding and theAND,ORandNOTaliases.
minecraft:permute_type entries read both spellings of their third field: the schema's min_guaranteed and the documentation page's guaranteed_count.
What a condition decides
evaluateSpawnCondition runs the components cheapest first and names the first one that rejected the position, so a server can explain an empty attempt and a test can name the component it covers.
| Component | What it compares |
|---|---|
minecraft:spawns_on_surface, minecraft:spawns_underground | The pass the position is in. Naming both takes either; naming neither takes any. |
minecraft:spawns_underwater, minecraft:spawns_lava | The medium. Naming neither refuses a position inside either liquid. |
minecraft:disallow_spawns_in_bubble | A bubble column at the position. |
minecraft:height_filter | The position's Y against the inclusive range. |
minecraft:spawns_on_block_filter, minecraft:spawns_on_block_prevented_filter | The block one below the position. |
minecraft:spawns_above_block_filter | The distance blocks below the position. |
minecraft:brightness_filter | The light the world reports, lowered by the weather when adjust_for_weather is set. |
minecraft:difficulty_filter | The world difficulty against the inclusive range. |
minecraft:world_age_filter | The world age in ticks; a maximum of -1 is no upper bound. |
minecraft:mob_event_filter | Whether the named mob event is running. |
minecraft:distance_filter | The distance to the nearest player. |
minecraft:player_in_village_filter | A player within distance who is within village_border_tolerance of a village border. |
minecraft:biome_filter | The shared filter grammar, through the @jsprismarine/entities evaluator. |
minecraft:density_limit | How many entities of this type stand within densityRadius, per pass. |
minecraft:delay_filter | A cooldown keyed by the filter's identifier, then a spawn_chance roll. |
The remaining six components are not gates. minecraft:weight and its rarity pick between the conditions that passed, minecraft:herd and minecraft:permute_type build the group, and minecraft:spawn_event, minecraft:is_persistent and minecraft:is_experimental describe what spawns.
Three readings in that table are this project's, because Mojang states the component and not the rule. A condition that names neither liquid refuses a position inside one, which is what keeps cows out of the ocean. minecraft:spawns_above_block_filter scans downward, because an entity "above a block" stands on it. rarity is read as a one-in-N roll on top of the weight, which is the only reading under which a rarity of 3 makes a spawn rarer.
The spawn loop
Mojang's spawn cycle diagram names six steps, "check spawn conditions, find valid spawn locations, check population caps, evaluate spawn weight, spawn entity, and run spawn event". Spawner.tick(tick) runs them for every pool whose cadence falls on that tick, and Spawner.cycle(pool, tick) runs one pool on demand.
One cycle of one pool:
- Read the pool's cap. A
per_playercap multiplies by the players in the region; aper_regioncap does not. A pool with no cap, which is the pillager pool, skips the check. - For each player, sample
chunksPerCyclechunks insidespawnRadiusChunks. - In each chunk, try
positionsPerChunkpositions for the surface pass, where Y isSpawnWorld.surfaceY, and the same number for the underground pass, where Y is drawn betweenSpawnWorld.minYand the surface. - At each position, collect every condition of every rule in the pool that passes, draw one weighted by
minecraft:weight.default, then apply itsrarityroll. - Draw a herd size inside the chosen
minecraft:herdalternative, place the first member at the position and the rest withinherdRadius, following the terrain on the surface pass. Reject each member withinminimumSpawnDistanceof any player or inside that distance from the current world spawn. - Give each member its entity type and spawn event.
minecraft:permute_typeswaps the type, taking itsmin_guaranteedmembers first and drawing the rest by weight, and theminecraft:pillager<minecraft:spawn_as_patrol_follower>form splits into a type and an event. The event isinitial_eventfor the firstinitial_event_countmembers, theneventfor every member pastevent_skip_count, then the permutation's own event, thenminecraft:spawn_event. - Stop as soon as the pool reaches its cap, mid-herd if that is where the cap falls.
despawnReason carries the two rules that belong to the population rather than to an entity: the published Y floor of -128, and the edge of the simulated region. The per-entity policy is minecraft:despawn in @jsprismarine/entities, which this package does not duplicate.
The injected seams
SpawnWorld is the one interface the loop reads the world through, so a test drives the whole algorithm with a typed double and a server implements it once.
site(flag, at)answers the six site facts, each named by the component or filter test that reads it:surface,underground,underwater,lava,bubble_columnandsnow_covered.block(at),light(at),biomeTags(at)andbiome(at)answer one position.surfaceY(x, z)andminY()give the two passes their Y.players()andworldSpawn()answer the player and world-spawn distances.poolCount(pool)andtypeCount(identifier, at, radius)answer the caps and the density limit.difficulty(),weather(),age(),mobEventActive(event)andvillageBorderDistance(at)answer the rest.
RandomSource from @jsprismarine/predicates is the only source of randomness, so one seed reproduces one set of spawns. SpawnDelays holds the minecraft:delay_filter cooldowns and a caller can persist it across a restart. SpawnConstants replaces the numbers below.
Which numbers Mojang publishes
Mojang documents the pool names and every component's parameters, but the spawn-rule data has no field for the algorithm's attempt rate, population caps, sampling radius, herd placement, or density radius. It also does not state which light value minecraft:brightness_filter compares or what adjust_for_weather does to it. The research note docs/research/bedrock-entities-spawning-loot-trading.md section 4 lists the gaps one by one.
The one place numbers appear is the "Typical Cap" column of EntitySpawningDeepDive.md, and every entry there is hedged with a tilde: animal "~10 per player", monster "~70 in loaded chunks", water_animal "~5 per water body", water_ambient "~20 per water body", ambient "~15 in caves", pillager "Limited by patrols".
Most numbers this package uses are this project's choices. They live in src/tables/spawnConstants.json rather than in code, each with a source string, so a reader can judge them and a host can replace the whole table through SpawnerOptions.constants.
The minimum spawn distance is the exception. Java 26.3's NaturalSpawner rejects spawn positions at or within 24 blocks of a player and inside 24 blocks of the shared world spawn in its dimension. The spawner reads this radius from the same JSON table and checks every herd member as well as the initial position. Mojang's Bedrock spawn-rule files do not carry this distance.
| Constant | Value | Where it came from |
|---|---|---|
pools.animal.cap | 10 per player | The tilde-hedged "~10 per player". |
pools.water_animal.cap | 5 per player | "~5 per water body". A water body is not a quantity this server tracks, so the cap counts per player. |
pools.water_ambient.cap | 20 per player | "~20 per water body". No vanilla rule names this pool. |
pools.ambient.cap | 15 per player | "~15 in caves". Only the bat uses this pool. |
pools.monster.cap | 70 per region | "~70 in loaded chunks", so it covers the region rather than scaling with players. |
pools.cat.cap | 5 per region | Mojang says only that cat limits are "based upon the amount within a village" and gives no number. |
pools.pillager.cap | none | "Limited by patrols", so minecraft:delay_filter and minecraft:mob_event_filter gate it instead. |
pools.*.cycleTicks | 400 for the calm pools, 20 for monsters and pillagers, 1200 for cats | Mojang publishes no rate. Java's animal pass runs every 400 ticks and its monster pass every tick; 20 is this project's cheaper monster cadence. |
spawnRadiusChunks | 4 | Bedrock's documented default simulation distance, because the ticking area documentation says spawning happens "in a radius centered on a player". |
minimumSpawnDistance | 24 blocks | Java 26.3's NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint; excludes near-player and near-world-spawn positions. |
chunksPerCycle, positionsPerChunk | 8 and 3 | This project's budget, picked so one player in an empty plains biome reaches the animal cap within a few cycles. |
herdRadius | 5 blocks | Java's horizontal pack spread. |
densityRadius | 16 blocks | One chunk's width, as this project's reading of the "certain locations" the density limit talks about. |
rainDarkening, thunderDarkening | 5 and 10 | Java's Level.getSkyDarken subtracts these under rain and thunder. |
despawnRadiusChunks | 8 | The 128 blocks of minecraft:despawn.despawn_from_distance.max_distance, the one published spawning distance. |
despawnFloorY | -128 | Published, and the same in both editions. |
The project chose Bedrock's model over Java's deliberately. docs/plans/data-driven-vanilla.md section 12 decision 3 records why: Java's model is implementable and invisible to a Bedrock client, and it would break every farm a Bedrock player has built.
Measured coverage
Against the composed vanilla behavior pack of Bedrock Dedicated Server 1.26.51.1, through the corpus test in src/vanillaSpawnRules.test.ts:
| Measure | Result |
|---|---|
| Spawn rule files composed | 60 |
| Files that parse with no diagnostic | 60 |
| Condition components the schema declares | 24, all parsed |
| Condition components vanilla writes | 21, all evaluated |
| Population pools in vanilla | animal 27, monster 24, water_animal 5, pillager 2, cat 1, ambient 1 |
| Rules with no conditions | 4: blaze, cat, pillager, wither skeleton |
| Biome filter tests left unanswered by the spawn filter context | 0 |
The corpus test needs the sources that pnpm --filter @jsprismarine/bedrock-data run fetch:sources caches and runs only with JSP_VANILLA_SPAWN_RULES set:
JSP_VANILLA_SPAWN_RULES=1 pnpm --filter @jsprismarine/spawning exec vitest run src/vanillaSpawnRules.test.tsWhat a later agent adds
- The four rules with no conditions. Blaze, cat, pillager and wither skeleton register a pool and leave placement to engine code: fortress spawns, village cats and patrol placement. This package spawns them wherever the pool cycle looks, which is wrong for all four.
- Structure-based spawn selection. When the world supplies Java structure data, the spawner suppresses a rule candidate if Java reserves that entity type exclusively for structure overrides and the candidate is outside every matching structure. This keeps guardians out of ordinary ocean water while leaving entities also listed in Java biome spawn tables eligible outside structures. Structure overrides do not yet create spawn attempts or replace the biome category's weighted selection.
- Measuring the constants. Every number in the table above is replaceable, and a capture against a running BDS would turn the guesses into measurements.
Classes
Interfaces
AboveBlockFilter
Defined in: rules.ts:129
The minecraft:spawns_above_block_filter body, which no vanilla rule writes.
Properties
blocks
readonlyblocks: readonlystring[]
Defined in: rules.ts:130
distance
readonlydistance:number
Defined in: rules.ts:131
DespawnCandidate
Defined in: despawn.ts:21
One entity the population cull looks at.
Properties
persistent?
readonlyoptionalpersistent?:boolean
Defined in: despawn.ts:24
Whether minecraft:persistent or a name tag keeps the entity loaded.
position
readonlyposition:SpawnPosition
Defined in: despawn.ts:22
EngineSpawnContext
Defined in: engineRules.ts:24
What an engine rule reads besides the position it is deciding.
Properties
random
readonlyrandom:RandomSource
Defined in: engineRules.ts:27
The spawner's own source, so one seed still reproduces one set of spawns.
world
readonlyworld:SpawnWorld
Defined in: engineRules.ts:25
HerdRule
Defined in: rules.ts:89
One minecraft:herd alternative: how many spawn together and which events they run.
Properties
event?
readonlyoptionalevent?:string
Defined in: rules.ts:96
The event every member past eventSkipCount runs.
eventSkipCount
readonlyeventSkipCount:number
Defined in: rules.ts:97
initialEvent?
readonlyoptionalinitialEvent?:string
Defined in: rules.ts:93
The event the first initialEventCount members run instead of their spawn event.
initialEventCount
readonlyinitialEventCount:number
Defined in: rules.ts:94
maxSize
readonlymaxSize:number
Defined in: rules.ts:91
minSize
readonlyminSize:number
Defined in: rules.ts:90
PlayerInVillageFilter
Defined in: rules.ts:123
The minecraft:player_in_village_filter body.
Properties
distance
readonlydistance:number
Defined in: rules.ts:124
villageBorderTolerance
readonlyvillageBorderTolerance:number
Defined in: rules.ts:125
PoolConstants
Defined in: constants.ts:19
One pool's cap, cadence and the provenance of both.
Properties
cap
readonlycap:number|null
Defined in: constants.ts:21
The cap, or null for a pool the documentation leaves to other machinery.
cycleTicks
readonlycycleTicks:number
Defined in: constants.ts:24
How many ticks pass between two spawn cycles of this pool.
scope
readonlyscope:PoolCapScope
Defined in: constants.ts:22
source
readonlysource:string
Defined in: constants.ts:26
Where the two numbers came from, quoted so a reader can judge them.
SpawnCondition
Defined in: rules.ts:139
One member of conditions: a complete alternative set of requirements with its own weight, herd and permutations. A rule passes at a position when any one of its conditions does.
Properties
aboveBlocks?
readonlyoptionalaboveBlocks?:AboveBlockFilter
Defined in: rules.ts:161
biomeFilter?
readonlyoptionalbiomeFilter?:Filter
Defined in: rules.ts:141
blocks?
readonlyoptionalblocks?: readonlystring[]
Defined in: rules.ts:158
The blocks the position may stand on; an empty list means the component is absent.
brightness?
readonlyoptionalbrightness?:object
Defined in: rules.ts:142
adjustForWeather
readonlyadjustForWeather:boolean
max
readonlymax:number
min
readonlymin:number
delay?
readonlyoptionaldelay?:SpawnDelay
Defined in: rules.ts:164
density?
readonlyoptionaldensity?:object
Defined in: rules.ts:148
How many of this entity may already stand nearby, per pass; -1 is no limit.
surface
readonlysurface:number
underground
readonlyunderground:number
difficulty?
readonlyoptionaldifficulty?:object
Defined in: rules.ts:143
max
readonlymax:"normal"|"peaceful"|"easy"|"hard"
min
readonlymin:"normal"|"peaceful"|"easy"|"hard"
disallowSpawnsInBubble
readonlydisallowSpawnsInBubble:boolean
Defined in: rules.ts:154
distance?
readonlyoptionaldistance?:SpawnRange
Defined in: rules.ts:146
How far from the nearest player the position must be.
height?
readonlyoptionalheight?:SpawnRange
Defined in: rules.ts:144
herd
readonlyherd: readonlyHerdRule[]
Defined in: rules.ts:162
isExperimental
readonlyisExperimental:boolean
Defined in: rules.ts:156
isPersistent
readonlyisPersistent:boolean
Defined in: rules.ts:155
mobEvent?
readonlyoptionalmobEvent?:string
Defined in: rules.ts:165
permutations?
readonlyoptionalpermutations?: readonlySpawnPermutation[]
Defined in: rules.ts:163
playerInVillage?
readonlyoptionalplayerInVillage?:PlayerInVillageFilter
Defined in: rules.ts:168
preventedBlocks?
readonlyoptionalpreventedBlocks?: readonlystring[]
Defined in: rules.ts:160
The blocks the position may not stand on.
spawnEvent?
readonlyoptionalspawnEvent?:string
Defined in: rules.ts:167
The event a spawned entity runs instead of minecraft:entity_spawned.
spawnsLava
readonlyspawnsLava:boolean
Defined in: rules.ts:153
spawnsOnSurface
readonlyspawnsOnSurface:boolean
Defined in: rules.ts:150
spawnsUnderground
readonlyspawnsUnderground:boolean
Defined in: rules.ts:151
spawnsUnderwater
readonlyspawnsUnderwater:boolean
Defined in: rules.ts:152
weight
readonlyweight:SpawnWeight
Defined in: rules.ts:140
worldAge?
readonlyoptionalworldAge?:SpawnRange
Defined in: rules.ts:149
SpawnConditionContext
Defined in: conditions.ts:67
Everything one condition evaluation needs beyond the condition and the position.
Properties
constants?
readonlyoptionalconstants?:SpawnConstants
Defined in: conditions.ts:74
delays?
readonlyoptionaldelays?:SpawnDelayView
Defined in: conditions.ts:75
identifier
readonlyidentifier:string
Defined in: conditions.ts:70
The entity the rule spawns, which minecraft:density_limit counts.
onUnanswered?
readonlyoptionalonUnanswered?: (test,reason) =>void
Defined in: conditions.ts:77
Receives every biome filter test the evaluator could not answer.
Parameters
test
reason
"unknownTest" | "missingSubject" | "missingFact"
Returns
void
random
readonlyrandom:RandomSource
Defined in: conditions.ts:71
tick
readonlytick:number
Defined in: conditions.ts:73
The current world tick, which minecraft:delay_filter compares.
world
readonlyworld:SpawnWorld
Defined in: conditions.ts:68
SpawnConditionResult
Defined in: conditions.ts:26
What one condition evaluation produced.
Properties
passed
readonlypassed:boolean
Defined in: conditions.ts:27
rejectedBy?
readonlyoptionalrejectedBy?:"minecraft:biome_filter"|"minecraft:brightness_filter"|"minecraft:delay_filter"|"minecraft:density_limit"|"minecraft:difficulty_filter"|"minecraft:disallow_spawns_in_bubble"|"minecraft:distance_filter"|"minecraft:height_filter"|"minecraft:herd"|"minecraft:is_experimental"|"minecraft:is_persistent"|"minecraft:mob_event_filter"|"minecraft:permute_type"|"minecraft:player_in_village_filter"|"minecraft:spawn_event"|"minecraft:spawns_above_block_filter"|"minecraft:spawns_lava"|"minecraft:spawns_on_block_filter"|"minecraft:spawns_on_block_prevented_filter"|"minecraft:spawns_on_surface"|"minecraft:spawns_underground"|"minecraft:spawns_underwater"|"minecraft:weight"|"minecraft:world_age_filter"
Defined in: conditions.ts:29
The first component that rejected the position, absent when the condition passed.
SpawnConstants
Defined in: constants.ts:30
The whole constants table.
Properties
attemptSource
readonlyattemptSource:string
Defined in: constants.ts:45
chunksPerCycle
readonlychunksPerCycle:number
Defined in: constants.ts:42
How many chunks one cycle samples per player.
darkeningSource
readonlydarkeningSource:string
Defined in: constants.ts:56
densityRadius
readonlydensityRadius:number
Defined in: constants.ts:50
The radius minecraft:density_limit counts entities over.
densityRadiusSource
readonlydensityRadiusSource:string
Defined in: constants.ts:51
despawnFloorY
readonlydespawnFloorY:number
Defined in: constants.ts:60
The height at and below which every mob despawns.
despawnRadiusChunks
readonlydespawnRadiusChunks:number
Defined in: constants.ts:58
How far from every player, in chunks, a mob is culled.
despawnSource
readonlydespawnSource:string
Defined in: constants.ts:61
herdRadius
readonlyherdRadius:number
Defined in: constants.ts:47
How far from the anchor, in blocks, a herd member may be placed.
herdRadiusSource
readonlyherdRadiusSource:string
Defined in: constants.ts:48
minimumSpawnDistance?
readonlyoptionalminimumSpawnDistance?:number
Defined in: constants.ts:38
Minimum natural spawn distance in blocks from players and the world spawn.
minimumSpawnDistanceSource?
readonlyoptionalminimumSpawnDistanceSource?:string
Defined in: constants.ts:40
Where the minimum spawn distance came from. Optional for older custom tables.
pools
readonlypools:Readonly<Record<string,PoolConstants>>
Defined in: constants.ts:33
positionsPerChunk
readonlypositionsPerChunk:number
Defined in: constants.ts:44
How many positions one cycle tries in each sampled chunk.
provenance
readonlyprovenance:string
Defined in: constants.ts:32
Where the table's values came from.
rainDarkening
readonlyrainDarkening:number
Defined in: constants.ts:53
How much rain lowers the light an adjust_for_weather brightness filter compares.
spawnRadiusChunks
readonlyspawnRadiusChunks:number
Defined in: constants.ts:35
How far from a player, in chunks, the spawner looks for a position.
spawnRadiusSource
readonlyspawnRadiusSource:string
Defined in: constants.ts:36
thunderDarkening
readonlythunderDarkening:number
Defined in: constants.ts:55
How much a thunderstorm lowers that light.
SpawnDelay
Defined in: rules.ts:113
The minecraft:delay_filter body: a cooldown shared by every rule naming the same identifier.
Properties
identifier?
readonlyoptionalidentifier?:string
Defined in: rules.ts:117
The cooldown's name, which is how the three pillager patrol conditions keep separate timers.
max
readonlymax:number
Defined in: rules.ts:115
min
readonlymin:number
Defined in: rules.ts:114
spawnChance
readonlyspawnChance:number
Defined in: rules.ts:119
The percent chance the attempt takes once the cooldown has elapsed.
SpawnDelayView
Defined in: conditions.ts:33
Reads the cooldowns minecraft:delay_filter keeps, keyed by its identifier.
Methods
readyAt()
readyAt(
identifier):number|undefined
Defined in: conditions.ts:35
The tick the named cooldown next allows a spawn, or undefined when it has never run.
Parameters
identifier
string
Returns
number | undefined
SpawnPermutation
Defined in: rules.ts:101
One minecraft:permute_type entry: a weighted swap of the entity a herd member spawns as.
Properties
entityType?
readonlyoptionalentityType?:string
Defined in: rules.ts:107
The entity to spawn instead, optionally in the type<event> form. Absent means the rule's own entity, which is how vanilla writes the common branch.
minGuaranteed
readonlyminGuaranteed:number
Defined in: rules.ts:109
How many herd members this permutation takes before the weighted draw runs.
weight
readonlyweight:number
Defined in: rules.ts:102
SpawnPlayer
Defined in: world.ts:49
One player the spawner spawns around.
Properties
position
readonlyposition:SpawnPosition
Defined in: world.ts:50
SpawnPosition
Defined in: world.ts:12
A block position. Spawn positions are integers; distances are measured between centers.
Properties
x
readonlyx:number
Defined in: world.ts:13
y
readonlyy:number
Defined in: world.ts:14
z
readonlyz:number
Defined in: world.ts:15
SpawnRange
Defined in: rules.ts:75
An inclusive numeric range, as every {min, max} component writes one.
Properties
max
readonlymax:number
Defined in: rules.ts:77
min
readonlymin:number
Defined in: rules.ts:76
SpawnRequest
Defined in: spawner.ts:33
One entity the spawner asks the server to create.
Properties
identifier
readonlyidentifier:string
Defined in: spawner.ts:35
The entity type, with any <event> suffix already split off.
pass
readonlypass:SpawnPass
Defined in: spawner.ts:44
pool
readonlypool:string
Defined in: spawner.ts:41
The pool whose cap this spawn counts against.
position
readonlyposition:SpawnPosition
Defined in: spawner.ts:39
The block position whose center the host uses to place the entity.
rule
readonlyrule:string
Defined in: spawner.ts:43
The rule that produced the spawn, which is the identifier of its file.
spawnEvent?
readonlyoptionalspawnEvent?:string
Defined in: spawner.ts:37
The event to run instead of minecraft:entity_spawned, when the rule names one.
SpawnRule
Defined in: rules.ts:172
One parsed spawn_rules/*.json.
Properties
conditions
readonlyconditions: readonlySpawnCondition[]
Defined in: rules.ts:177
formatVersion?
readonlyoptionalformatVersion?:string
Defined in: rules.ts:176
identifier
readonlyidentifier:string
Defined in: rules.ts:173
populationControl?
readonlyoptionalpopulationControl?:string
Defined in: rules.ts:175
The pool whose cap gates this entity, absent when the file names none.
SpawnRuleParseOptions
Defined in: rules.ts:181
Where a parse reports its findings.
Properties
pack
readonlypack:string
Defined in: rules.ts:183
The pack the file came from, used in the diagnostics.
path?
readonlyoptionalpath?:string
Defined in: rules.ts:184
report?
readonlyoptionalreport?: (diagnostic) =>void
Defined in: rules.ts:185
Parameters
diagnostic
Returns
void
SpawnWeight
Defined in: rules.ts:81
How often one condition is drawn against the others that pass at the same position.
Properties
default
readonlydefault:number
Defined in: rules.ts:83
The relative weight; a weight of 100 among a total of 1000 is drawn a tenth of the time.
rarity
readonlyrarity:number
Defined in: rules.ts:85
An extra rarity roll Mojang documents by name only. Zero means no roll.
SpawnWorld
Defined in: world.ts:54
Everything one spawn cycle reads about the world.
Methods
age()
age():
number
Defined in: world.ts:103
The world's age in ticks, which is what minecraft:world_age_filter compares.
Returns
number
biome()?
optionalbiome(at):string
Defined in: world.ts:80
The biome name at one position, for is_biome.
Parameters
at
Returns
string
biomeTags()
biomeTags(
at): readonlystring[]
Defined in: world.ts:78
The biome tags at one position, which is what has_biome_tag compares.
Parameters
at
Returns
readonly string[]
block()
block(
at):string|undefined
Defined in: world.ts:61
The block identifier at one position, or undefined when the chunk is not loaded, which stops the attempt.
Parameters
at
Returns
string | undefined
difficulty()
difficulty():
"normal"|"peaceful"|"easy"|"hard"
Defined in: world.ts:100
Returns
"normal" | "peaceful" | "easy" | "hard"
light()
light(
at):number
Defined in: world.ts:76
The light level at one position, 0 to 15, before this package applies the weather darkening that adjust_for_weather asks for.
Parameters
at
Returns
number
minY()
minY():
number
Defined in: world.ts:88
The lowest y the world generates, which bounds the underground pass.
Returns
number
mobEventActive()
mobEventActive(
event):boolean
Defined in: world.ts:105
Whether a named mob event, such as minecraft:pillager_patrols_event, is running.
Parameters
event
string
Returns
boolean
players()
players(): readonly
SpawnPlayer[]
Defined in: world.ts:90
The players the spawner spawns around, which is every player in the spawn region.
Returns
readonly SpawnPlayer[]
poolCount()
poolCount(
pool):number
Defined in: world.ts:97
How many entities of one population pool stand in the spawn region now.
Parameters
pool
string
Returns
number
site()
site(
flag,at):boolean
Defined in: world.ts:56
A boolean fact about one position, named by the component that reads it.
Parameters
flag
"lava" | "bubble_column" | "surface" | "underground" | "underwater" | "snow_covered"
at
Returns
boolean
solid()
solid(
at):boolean
Defined in: world.ts:71
Whether the block at one position stops an entity standing in it.
The underground pass draws a y uniformly between the world floor and the surface, so most of what it draws is inside rock. Java rejects such a draw in NaturalSpawner.isSpawnPositionOk; without this the spawner puts a zombie inside a stone block, where it can path nowhere and never despawns.
Parameters
at
Returns
boolean
structureSpawnOverrideAt()?
optionalstructureSpawnOverrideAt(identifier,at):boolean|undefined
Defined in: world.ts:121
Whether Java restricts this entity type to a structure spawn override at this position.
false means the Java data declares at least one structure override for the entity, but this position is outside every active override. true means a matching override covers this position. undefined means Java's biome data also permits this entity to spawn outside structures, or that the world has no Java override data for it, so the spawn rule decides as usual.
Parameters
identifier
string
at
Returns
boolean | undefined
surfaceY()
surfaceY(
x,z):number|undefined
Defined in: world.ts:86
The lowest y an entity may stand on in one column, which is the position the surface pass tries. Undefined when the column is not loaded, which skips the attempt.
Parameters
x
number
z
number
Returns
number | undefined
typeCount()
typeCount(
identifier,at,radius):number
Defined in: world.ts:99
How many entities of one type stand within radius blocks of a position.
Parameters
identifier
string
at
radius
number
Returns
number
villageBorderDistance()?
optionalvillageBorderDistance(at):number|undefined
Defined in: world.ts:111
How far a position is from the nearest village border, negative inside it and undefined when no village is near. minecraft:player_in_village_filter reads it.
Parameters
at
Returns
number | undefined
weather()
weather():
"thunder"|"clear"|"rain"
Defined in: world.ts:101
Returns
"thunder" | "clear" | "rain"
worldSpawn()?
optionalworldSpawn():SpawnPosition|undefined
Defined in: world.ts:95
The shared world spawn in this dimension, when one applies. Java's exclusion only applies in the dimension that owns this spawn point.
Returns
SpawnPosition | undefined
SpawnerOptions
Defined in: spawner.ts:48
How to build a Spawner.
Properties
constants?
readonlyoptionalconstants?:SpawnConstants
Defined in: spawner.ts:52
delays?
readonlyoptionaldelays?:SpawnDelays
Defined in: spawner.ts:54
The minecraft:delay_filter cooldowns, so a caller can persist them across a restart.
engineRules?
readonlyoptionalengineRules?:ReadonlyMap<string,EngineSpawnRule>
Defined in: spawner.ts:60
The conditions Bedrock keeps in engine code, keyed by the entity each one gates. Defaults to VANILLA_ENGINE_SPAWN_RULES; pass an empty map to run the JSON conditions alone.
onUnanswered?
readonlyoptionalonUnanswered?: (test,reason) =>void
Defined in: spawner.ts:62
Receives every biome filter test the evaluator could not answer.
Parameters
test
reason
"unknownTest" | "missingSubject" | "missingFact"
Returns
void
random
readonlyrandom:RandomSource
Defined in: spawner.ts:51
rules
readonlyrules:Iterable<SpawnRule>
Defined in: spawner.ts:49
world
readonlyworld:SpawnWorld
Defined in: spawner.ts:50
Type Aliases
DespawnReason
DespawnReason =
"below_floor"|"simulation_edge"
Defined in: despawn.ts:18
Why one entity despawned.
Difficulty
Difficulty = typeof
DIFFICULTIES[number]
Defined in: rules.ts:35
One of DIFFICULTIES.
EngineSpawnRule
EngineSpawnRule = (
at,context) =>boolean
Defined in: engineRules.ts:36
One entity's engine-side spawn condition.
Parameters
at
context
Returns
boolean
Whether the entity may spawn at the position, with the entity's spawn_rules/*.json conditions already satisfied.
PoolCapScope
PoolCapScope =
"per_player"|"per_region"
Defined in: constants.ts:16
Whether a pool's cap covers the whole spawn region or scales with the players in it.
PopulationPool
PopulationPool = typeof
POPULATION_POOLS[number]
Defined in: rules.ts:29
One of POPULATION_POOLS.
SpawnPass
SpawnPass =
"surface"|"underground"
Defined in: world.ts:40
Which of the two passes a position belongs to.
SpawnRuleComponent
SpawnRuleComponent = typeof
SPAWN_RULE_COMPONENTS[number]
Defined in: rules.ts:72
One of SPAWN_RULE_COMPONENTS.
SpawnSiteFlag
SpawnSiteFlag = typeof
SPAWN_SITE_FLAGS[number]
Defined in: world.ts:37
One of SPAWN_SITE_FLAGS.
SpawnWeather
SpawnWeather = typeof
SPAWN_WEATHER[number]
Defined in: world.ts:46
One of SPAWN_WEATHER.
Variables
DIFFICULTIES
constDIFFICULTIES: readonly ["peaceful","easy","normal","hard"]
Defined in: rules.ts:32
The difficulty names minecraft:difficulty_filter compares, in ascending order.
MOON_BRIGHTNESS
constMOON_BRIGHTNESS: readonlynumber[]
Defined in: engineRules.ts:117
How bright the moon is at each of its eight phases, starting at the full moon. The swamp branch of the slime rule draws against this number, so a swamp spawns no slimes at all on a new moon.
POPULATION_POOLS
constPOPULATION_POOLS: readonly ["animal","water_animal","water_ambient","ambient","monster","cat","pillager","villager"]
Defined in: rules.ts:17
The pools description.population_control names, each with its own cap.
SLIME_SURFACE_BIOME_TAG
constSLIME_SURFACE_BIOME_TAG:"spawns_slimes_on_surface"='spawns_slimes_on_surface'
Defined in: engineRules.ts:151
The biome tag the swamp branch reads. Three vanilla biomes carry it: swampland, swampland_mutated and mangrove_swamp.
SPAWN_CONSTANTS
constSPAWN_CONSTANTS:Required<SpawnConstants>
Defined in: constants.ts:70
The default spawning values, read from src/tables/spawnConstants.json. A host replaces the table through SpawnerOptions.constants.
SPAWN_RULE_COMPONENTS
constSPAWN_RULE_COMPONENTS: readonly ["minecraft:biome_filter","minecraft:brightness_filter","minecraft:delay_filter","minecraft:density_limit","minecraft:difficulty_filter","minecraft:disallow_spawns_in_bubble","minecraft:distance_filter","minecraft:height_filter","minecraft:herd","minecraft:is_experimental","minecraft:is_persistent","minecraft:mob_event_filter","minecraft:permute_type","minecraft:player_in_village_filter","minecraft:spawn_event","minecraft:spawns_above_block_filter","minecraft:spawns_lava","minecraft:spawns_on_block_filter","minecraft:spawns_on_block_prevented_filter","minecraft:spawns_on_surface","minecraft:spawns_underground","minecraft:spawns_underwater","minecraft:weight","minecraft:world_age_filter"]
Defined in: rules.ts:44
Every condition component Spawn Rules.json declares, in the schema's order. Vanilla writes 21 of the 24; minecraft:spawns_above_block_filter, minecraft:is_persistent and minecraft:is_experimental appear in the schema alone, so this package parses them and leaves their meaning to the caller.
SPAWN_SITE_FLAGS
constSPAWN_SITE_FLAGS: readonly ["surface","underground","underwater","lava","bubble_column","snow_covered"]
Defined in: world.ts:27
The boolean facts about one position, each named by the rule component or filter test that reads it.
surface and underground select the pass; underwater and lava are the medium the position sits in; bubble_column answers minecraft:disallow_spawns_in_bubble; snow_covered answers the one is_snow_covered test a vanilla biome filter writes.
SPAWN_WEATHER
constSPAWN_WEATHER: readonly ["clear","rain","thunder"]
Defined in: world.ts:43
The weather names adjust_for_weather reads.
VANILLA_ENGINE_SPAWN_RULES
constVANILLA_ENGINE_SPAWN_RULES:ReadonlyMap<string,EngineSpawnRule>
Defined in: engineRules.ts:188
Every engine rule vanilla needs, keyed by the entity it gates.
import('./spawner').Spawner applies these by default. A host that wants a different set passes its own map, and a host that wants none passes an empty one.
slimeSpawnRule
constslimeSpawnRule:EngineSpawnRule
Defined in: engineRules.ts:167
Where a slime may spawn, which spawn_rules/slime.json does not say.
Two branches, as Bedrock writes them. At Y 38 and below the position has to be in a slime chunk and nothing else is asked, which is why a slime farm is dug out rather than lit up. Above that the position has to be in a swamp between Y 50 and Y 68, dark enough, and lucky against the moon phase. Everything in between, and every lit surface, spawns no slimes at all.
The one divergence from the Bedrock function is the position the biome tag is read at. Bedrock reads it one block higher than the spawn position; this reads it at the spawn position, because a biome boundary is the only place the two can differ and neither answer is more correct there.
Functions
cycleTicksFor()
cycleTicksFor(
pool,constants?):number|undefined
Defined in: constants.ts:91
How many ticks pass between two spawn cycles of one pool.
Parameters
pool
string
constants?
SpawnConstants = SPAWN_CONSTANTS
Returns
number | undefined
despawnReason()
despawnReason(
candidate,world,constants?):DespawnReason|undefined
Defined in: despawn.ts:38
Decides whether one entity leaves the world for a population reason.
The Y floor is published and is the same in both editions: every mob despawns at Y=-128 and below. The simulation edge is not published; this project uses despawnRadiusChunks on the X and Z axes, whose default of 8 chunks is the 128 blocks of minecraft:despawn.despawn_from_distance.max_distance.
Parameters
candidate
world
constants?
SpawnConstants = SPAWN_CONSTANTS
Returns
DespawnReason | undefined
The reason, or undefined when the entity stays.
distanceSquared()
distanceSquared(
from,to):number
Defined in: world.ts:125
The squared distance between two positions, which is what the range checks compare.
Parameters
from
to
Returns
number
evaluateSpawnCondition()
evaluateSpawnCondition(
condition,at,context,requestedPass?):SpawnConditionResult
Defined in: conditions.ts:168
Decides whether one condition allows a spawn at a position.
The components run cheapest first, and the first one that rejects names itself in the result. A condition that declares neither minecraft:spawns_underwater nor minecraft:spawns_lava refuses a position inside either liquid, which is the reading that keeps land mobs out of the ocean; Mojang states the components and not that rule.
Parameters
condition
at
context
requestedPass?
The pass the spawn loop is evaluating, or absent to derive it from the world's site facts.
Returns
horizontalDistanceSquared()
horizontalDistanceSquared(
from,to):number
Defined in: world.ts:136
The squared distance between two positions on the X and Z axes alone, which is what a chunk radius such as the simulation distance measures.
Parameters
from
to
Returns
number
isSlimeChunk()
isSlimeChunk(
chunkX,chunkZ):boolean
Defined in: engineRules.ts:98
Whether a chunk is a slime chunk.
Bedrock seeds a Mersenne twister with chunkX * 0x1f1f1f1f ^ chunkZ and takes its first draw modulo ten. The world seed is not part of it, which is why a Bedrock slime farm sits at the same chunk coordinates in every world and why Java's seeded formula is the wrong answer here.
Parameters
chunkX
number
The chunk's X coordinate, which is a block X shifted right by four.
chunkZ
number
The chunk's Z coordinate.
Returns
boolean
moonPhase()
moonPhase(
time):number
Defined in: engineRules.ts:125
The moon phase at one world time.
Parameters
time
number
The world's age in ticks, which is never negative on a running server.
Returns
number
A phase from 0, the full moon, to 7.
parseSpawnRule()
parseSpawnRule(
file,options):SpawnRule|undefined
Defined in: rules.ts:391
Parses one spawn_rules/*.json file.
Parameters
file
unknown
options
Returns
SpawnRule | undefined
The rule, or undefined when the file is not a spawn rule or names no identifier. Everything else loads and reports.
passAt()
passAt(
world,at):SpawnPass
Defined in: world.ts:143
Which pass a position belongs to, which the world decides and the conditions read.
Parameters
world
at
Returns
poolCapFor()
poolCapFor(
pool,players,constants?):number|undefined
Defined in: constants.ts:80
The cap one pool is allowed in the spawn region right now.
Parameters
pool
string
players
number
How many players the spawn region holds, which scales a per_player cap.
constants?
SpawnConstants = SPAWN_CONSTANTS
Returns
number | undefined
The cap, or undefined when the pool has none and other machinery limits it.
spawnFilterContext()
spawnFilterContext(
world,at):FilterContext
Defined in: conditions.ts:93
Builds the filter context a minecraft:biome_filter reads.
A spawn rule has no entity yet, so the self subject is the position: its biome tags answer has_biome_tag, its biome answers is_biome, and its site flags answer is_snow_covered, is_underground, is_underwater and in_lava. Every other test the shared grammar allows goes unanswered and is reported, which is what the engine does for a fact it cannot establish.