Skip to content

How spawners work

A spawner’s own state — its type, its five upgrade levels, its stack size, its owner, its itemised store contents, its banked experience, and its own boosters — lives in the block’s own persistent data. It travels with the chunk and costs nothing to keep.

The database holds only what has to be answerable while that chunk is asleep:

  • how many spawners each player owns (for the ownership limit and for lists),
  • who is whitelisted on which spawner,
  • unused owner-wide boosters,
  • spawners waiting to be claimed back after a team or land change,
  • the action log.

A spawner block is considered “ours” — marked — from the moment its data is first written, not from the next time it is read. This is why a migration from another spawner plugin always reads, then releases the other plugin’s hold, then writes here, in that order: two plugins holding one block would both try to answer the same break.

A spawner only runs while a player is within its range. Range is itself an upgrade axis (range), so a fresh spawner’s range is whatever level 1 gives it, and upgrading range reaches further. If no player is in range, the spawner is marked idle and does not check again for engine.idle-recheck ticks (default 100) — searching for a player is the most expensive thing the production engine does, so it is throttled.

This also governs holograms and cage models: a label or a model entity exists only while a player is close enough to see it. Entity count follows how many people are playing, not how many spawners the server has. A vanished player does not count, unless integrations.vanish is set to NONE.

Right-click a spawner while holding another spawner item to add it to the stack (crouch to add as many as fit at once). A stack is still one block: one whitelist grant, one set of upgrade levels, and one production cycle cover the whole stack. How many spawners may share one block is capped by stacking.limit in config.yml (world baseline, raised by permission, capped again by the type’s own stack-limit in spawners.yml).

The one rule: kills = amount × stack × booster

Section titled “The one rule: kills = amount × stack × booster”

Every DROPS-mode production cycle multiplies three things, and nothing else:

  • the amount upgrade’s current level value,
  • the stack size,
  • any active boosters of the AMOUNT kind.

There is no cap per block, no cap per chunk, no count of what is already nearby, and no falloff with distance. A hundred spawners stacked into one block produce exactly what a hundred spawners spread over a field produce — not close, the same number. The only levers a server owner has to bound the work this does are the stack limit and the amount upgrade’s own price and max-level.

Two things follow from this on purpose:

  • A cycle is all or nothing. If the store (or a container, or the ground) cannot take the whole cycle’s output, delivery either passes the rest to the next target in the chain or the cycle produces nothing at all — never a partial delivery. Half a cycle delivered would make a stack worth less than the same spawners kept apart.
  • Nothing rounds per spawner. The kill count is rounded exactly once, for the whole cycle, by a coin weighted by the leftover fraction — never by rounding each spawner’s own contribution. Rounding per spawner would give a single spawner with a 1.5× booster 2 kills, and a stack of a hundred of the same spawners 150 — a quarter less per spawner for having stacked them.

A type set to mode: MOBS is the vanilla spawner, with the upgrade values written onto the block — the server does the spawning, so it costs the plugin nothing to run. But vanilla itself stops spawning once enough mobs are already nearby, which is exactly the ceiling DROPS mode exists to remove. MOBS mode does not carry the equal-output promise above: a packed farm in MOBS mode produces less than the same spawners spread out, because vanilla’s own cap still applies.

A type that names a mythic-mob in MOBS mode is spawned by the plugin’s own timer instead of vanilla’s, and that timer has its own, deliberate ceiling — engine.mobs.max-nearby, engine.mobs.radius and engine.mobs.spread in config.yml. This exists because MythicMobs mobs need somewhere to go and some spread to look natural; it is not a workaround, it is a different mode with a different promise.