
CobblemonOptimizer
CobbleOptimizer is a server-side Fabric mod that reduces lag caused by Cobblemon's Pokemon entities.
- Загрузки
- 20K
- Подписчики
- 29
- Обновлён
- 17 августа 2026 г.
- Лицензия
- MIT
Опубликован 11 февраля 2026 г.
CobbleOptimizer
A server-side Fabric mod for Minecraft 1.21.1 that optimizes Cobblemon (the Pokemon mod) entity performance based on server load (TPS). It has 4 main
features:
- Tick Throttle — Reduces how often distant/unimportant Pokemon entities are ticked. When the server TPS drops, Pokemon far from players get their tick rate reduced, saving CPU cycles.
- AI Freeze — Completely freezes the AI of Pokemon entities that are far from any player. If no one is nearby to observe them, there's no need to run their pathfinding and behavior logic.
- Adaptive Spawn — Dynamically adjusts Pokemon spawn rates based on current server TPS. When the server is struggling, fewer Pokemon spawn; when it's healthy, spawns return to normal.
- Batch Despawn — Removes excess Pokemon entities in bulk when the server is overloaded, prioritizing removal of unimportant ones (non-shiny, non-legendary, unowned, not in battle).
Shared Infrastructure
- TPS Monitor — Continuously tracks server TPS to inform all features.
- Player Tracker — Caches player-to-entity distances so multiple features can cheaply check proximity.
- Config — TOML-based configuration with in-game commands (/cobbleoptimizer) to tweak thresholds on the fly.
In short
It's a performance optimization mod that keeps Cobblemon servers running smoothly by intelligently scaling back Pokemon entity processing when the server is under load, while protecting important Pokemon (shinies, legendaries, battling, owned) from aggressive optimization.
Ченджлог
4.8.0Релиз1.21.1 · 17 августа 2026 г.
Drop in a new version of the mod and cobbleoptimizer.toml now picks up any new options automatically on startup. Your existing settings are kept exactly as they were - only missing keys are added, and comments are refreshed.
No more editing the file by hand or deleting it to force a regeneration.
The server log tells you what happened, for example:
[CobbleOptimizer] Config updated with 3 new option(s):
batch_despawn.spawn_grace_period_ticks, batch_despawn.protect_player_npc,
patches.fix_cobbreeding_semver
If your config fails validation, the file is left untouched so you can see and correct the offending values.
Note: if you have been running the mod for a while, your config may be missing options that were added in earlier releases and never appeared in your file. This update adds them. patches.fix_cobbreeding_semver is a common example.
FIXES
Settings could silently fail to save. Running "/cobbleoptimizer set ..." and then stopping the server within a few seconds lost the change. Config writes were asynchronous and were not flushed on shutdown. They are now written to disk immediately.
spawn_grace_period_ticks is now actually adjustable. This is the window that protects freshly spawned Pokemon near a player, so a fishing catch is not swept away mid-reel. It existed and was in use, but was locked at 600 ticks (30 seconds) with no way to change it and was never saved to the config file. It is now a real, editable option.
Removed a dead setting. batch_despawn.despawn_on_chunk_load appeared in command tab-completion but had nothing behind it, and returned "Invalid key or value" if you tried to set it. It has been removed.
Wild Pokemon could accumulate without ever being cleaned up. Affects some 4.7 builds only. Pokemon holding an item, and Combee working saccharine trees, were incorrectly treated as permanent. Because Cobblemon does not despawn those on its own either, they could pile up over time and cost TPS. Only deliberately persistent Pokemon are protected now.
NEW CONFIG OPTIONS
[batch_despawn]
# Protect player-made NPC Pokemon from despawn (Pokemon whose vanilla
# PersistenceRequired flag was set via /data modify, e.g. pokemon center
# receptionists)
protect_player_npc = true
# Newly spawned Pokemon near a player are protected for this many ticks,
# so fishing/spawn results are not swept away
# (600 = 30 seconds, 0 = disabled)
spawn_grace_period_ticks = 600
Both are also settable in game:
/cobbleoptimizer set batch_despawn.protect_player_npc false
/cobbleoptimizer set batch_despawn.spawn_grace_period_ticks 1200
"/cobbleoptimizer status" now lists player_npc among the active protections.
4.8.0Релиз1.21.1 · 17 августа 2026 г.
Drop in a new version of the mod and cobbleoptimizer.toml now picks up any new options automatically on startup. Your existing settings are kept exactly as they were - only missing keys are added, and comments are refreshed.
No more editing the file by hand or deleting it to force a regeneration.
The server log tells you what happened, for example:
[CobbleOptimizer] Config updated with 3 new option(s):
batch_despawn.spawn_grace_period_ticks, batch_despawn.protect_player_npc,
patches.fix_cobbreeding_semver
If your config fails validation, the file is left untouched so you can see and correct the offending values.
Note: if you have been running the mod for a while, your config may be missing options that were added in earlier releases and never appeared in your file. This update adds them. patches.fix_cobbreeding_semver is a common example.
FIXES
Settings could silently fail to save. Running "/cobbleoptimizer set ..." and then stopping the server within a few seconds lost the change. Config writes were asynchronous and were not flushed on shutdown. They are now written to disk immediately.
spawn_grace_period_ticks is now actually adjustable. This is the window that protects freshly spawned Pokemon near a player, so a fishing catch is not swept away mid-reel. It existed and was in use, but was locked at 600 ticks (30 seconds) with no way to change it and was never saved to the config file. It is now a real, editable option.
Removed a dead setting. batch_despawn.despawn_on_chunk_load appeared in command tab-completion but had nothing behind it, and returned "Invalid key or value" if you tried to set it. It has been removed.
Wild Pokemon could accumulate without ever being cleaned up. Affects some 4.7 builds only. Pokemon holding an item, and Combee working saccharine trees, were incorrectly treated as permanent. Because Cobblemon does not despawn those on its own either, they could pile up over time and cost TPS. Only deliberately persistent Pokemon are protected now.
NEW CONFIG OPTIONS
[batch_despawn]
# Protect player-made NPC Pokemon from despawn (Pokemon whose vanilla
# PersistenceRequired flag was set via /data modify, e.g. pokemon center
# receptionists)
protect_player_npc = true
# Newly spawned Pokemon near a player are protected for this many ticks,
# so fishing/spawn results are not swept away
# (600 = 30 seconds, 0 = disabled)
spawn_grace_period_ticks = 600
Both are also settable in game:
/cobbleoptimizer set batch_despawn.protect_player_npc false
/cobbleoptimizer set batch_despawn.spawn_grace_period_ticks 1200
"/cobbleoptimizer status" now lists player_npc among the active protections.
4.7.0Релиз1.21.1 · 16 августа 2026 г.
CobbleOptimizer 4.7.0 — What's New
Got tired of your Pokémon Center receptionist or NPC Pokémon vanishing when the server gets busy? That's fixed.
- NPC Pokémon are now protected from despawning. If you've set up a Pokémon as an NPC using the classic /data modify entity ... PersistenceRequired set value 1b trick, CobbleOptimizer will now recognize it and never remove it during a despawn cleanup — no matter how far it is from players or how long it's been standing there.
- This is on by default, no config changes needed. Server admins can still turn it off with protect_player_npc = false in cobbleoptimizer.toml if they don't want the exception.
- Everything else about your setup (NoAI, Unbattleable, Invulnerable, uncatchable) keeps working exactly as before — this change only stops the mod from despawning it.
TL;DR: build your Pokémon Center, your gym, your NPC trainers
4.7.0Релиз1.21.1 · 16 августа 2026 г.
CobbleOptimizer 4.7.0 — What's New
Got tired of your Pokémon Center receptionist or NPC Pokémon vanishing when the server gets busy? That's fixed.
- NPC Pokémon are now protected from despawning. If you've set up a Pokémon as an NPC using the classic /data modify entity ... PersistenceRequired set value 1b trick, CobbleOptimizer will now recognize it and never remove it during a despawn cleanup — no matter how far it is from players or how long it's been standing there.
- This is on by default, no config changes needed. Server admins can still turn it off with protect_player_npc = false in cobbleoptimizer.toml if they don't want the exception.
- Everything else about your setup (NoAI, Unbattleable, Invulnerable, uncatchable) keeps working exactly as before — this change only stops the mod from despawning it.
TL;DR: build your Pokémon Center, your gym, your NPC trainers
4.6.0Релиз1.21.1 · 24 мая 2026 г.
● CobbleOptimizer 4.6.0 — Changelog
New: CobBreeding compatibility patch
Added a @Pseudo mixin targeting ludichat.cobbreeding.utils.SemVerKt::toSemVer to address two distinct issues in CobBreeding (Ludichat/Cobbreeding) versions ≤ 2.2.1.
Performance fix (always active, zero risk)
CobBreeding's toSemVer constructed a new kotlin.text.Regex on every invocation, triggering Pattern.compile (1–10 µs per call). On servers with many eggs, spark profiler flagged this as a measurable hotspot during egg deserialization.
The mixin uses @Redirect on the new kotlin/text/Regex(String) instruction inside toSemVer to return one of two process-wide cached Regex singletons. Pattern compilation now happens twice total at class load instead of once per call.
Correctness fix (toggleable, off by default)
The original regex ^\d(.\d(.\d([.-_].+)?)?)?$ has two bugs:
- Single \d per component. Multi-digit version components (e.g. 1.21.1, 2.2.10) fail to match, so toSemVer returns SemVer(emptyList()) with major=minor=patch=0. Downstream, PokemonEgg.verifyComponentsAfterLoad() misidentifies the egg as pre-2.0.0 and runs the wrong migration, crashing the server with NumberFormatException when an egg is moved/cloned from a pasture block.
- [.-_] as a character class. This is a regex range from . (0x2E) to _ (0x5F) instead of three literal characters. It accidentally matches digits, uppercase letters, and various punctuation.
When the toggle is enabled, the cached regex is the corrected version: ^\d+(.\d+(.\d+([._-].+)?)?)?$.
New config option
[patches] fix_cobbreeding_semver = false # default off, opt-in
Also reachable via the existing /cobbleoptimizer config patches.fix_cobbreeding_semver <true|false> command. The mixin re-reads the config on every call to toSemVer, so the toggle takes effect immediately without a server restart.
When the toggle is false, the cache still returns a singleton with the original (buggy) regex — semantics are bit-identical to vanilla CobBreeding, but the per-call Pattern.compile cost is eliminated. When the toggle is true, the cache returns the corrected regex.
Safety properties
- No compile-time dependency on CobBreeding. The mixin uses @Pseudo + string target, so CobbleOptimizer builds and runs identically whether CobBreeding is installed or not.
- Silent no-op when CobBreeding is absent. Registered in cobbleoptimizer-patches.mixins.json with defaultRequire: 0, so missing target classes don't propagate as errors.
- Forward compatibility. If a future CobBreeding release changes the bytecode shape of toSemVer (e.g. caches the regex upstream, renames the method), the @Redirect no longer matches and the mixin becomes a silent no-op.
4.6.0Релиз1.21.1 · 24 мая 2026 г.
● CobbleOptimizer 4.6.0 — Changelog
New: CobBreeding compatibility patch
Added a @Pseudo mixin targeting ludichat.cobbreeding.utils.SemVerKt::toSemVer to address two distinct issues in CobBreeding (Ludichat/Cobbreeding) versions ≤ 2.2.1.
Performance fix (always active, zero risk)
CobBreeding's toSemVer constructed a new kotlin.text.Regex on every invocation, triggering Pattern.compile (1–10 µs per call). On servers with many eggs, spark profiler flagged this as a measurable hotspot during egg deserialization.
The mixin uses @Redirect on the new kotlin/text/Regex(String) instruction inside toSemVer to return one of two process-wide cached Regex singletons. Pattern compilation now happens twice total at class load instead of once per call.
Correctness fix (toggleable, off by default)
The original regex ^\d(.\d(.\d([.-_].+)?)?)?$ has two bugs:
- Single \d per component. Multi-digit version components (e.g. 1.21.1, 2.2.10) fail to match, so toSemVer returns SemVer(emptyList()) with major=minor=patch=0. Downstream, PokemonEgg.verifyComponentsAfterLoad() misidentifies the egg as pre-2.0.0 and runs the wrong migration, crashing the server with NumberFormatException when an egg is moved/cloned from a pasture block.
- [.-_] as a character class. This is a regex range from . (0x2E) to _ (0x5F) instead of three literal characters. It accidentally matches digits, uppercase letters, and various punctuation.
When the toggle is enabled, the cached regex is the corrected version: ^\d+(.\d+(.\d+([._-].+)?)?)?$.
New config option
[patches] fix_cobbreeding_semver = false # default off, opt-in
Also reachable via the existing /cobbleoptimizer config patches.fix_cobbreeding_semver <true|false> command. The mixin re-reads the config on every call to toSemVer, so the toggle takes effect immediately without a server restart.
When the toggle is false, the cache still returns a singleton with the original (buggy) regex — semantics are bit-identical to vanilla CobBreeding, but the per-call Pattern.compile cost is eliminated. When the toggle is true, the cache returns the corrected regex.
Safety properties
- No compile-time dependency on CobBreeding. The mixin uses @Pseudo + string target, so CobbleOptimizer builds and runs identically whether CobBreeding is installed or not.
- Silent no-op when CobBreeding is absent. Registered in cobbleoptimizer-patches.mixins.json with defaultRequire: 0, so missing target classes don't propagate as errors.
- Forward compatibility. If a future CobBreeding release changes the bytecode shape of toSemVer (e.g. caches the regex upstream, renames the method), the @Redirect no longer matches and the mixin becomes a silent no-op.
4.4.0Релиз1.21.1 · 12 мая 2026 г.
CobbleOptimizer 4.4.0 — Release Notes
New optimization: Berry ticker backport (Cobblemon 1.8 → 1.7.3)
Added a new patch that eliminates the per-tick BlockEntityTicker overhead from BerryBlock, ported from how Cobblemon 1.8 handles berry growth.
What it does
- Cancels the original BerryBlock.getTicker() registration (no more per-tick callback on every loaded berry tree).
- Adds hasRandomTicks / randomTick / scheduledTick overrides that drive berry growth via vanilla random ticking instead, with delta-time compensation so average maturation time stays identical to vanilla Cobblemon.
- Mature berries (age = 5) and rooted berries don't tick at all → zero per-tick cost.
Performance
- Before: every loaded BerryBlockEntity ran a callback 20×/s → linear cost scaling with the number of loaded berry trees.
- After: each berry block is visited on average ~once per 68 s (at randomTickSpeed=3), with the elapsed game-time subtracted in one batch from stageTimer.
- On servers with large berry farms, this removes a constant per-tick overhead proportional to the farm size.
Configuration
- Config key: patches.berry_ticker_optimization
- Default: true (enabled out of the box for new installs; existing config files preserve their previous values).
- To disable: edit cobbleoptimizer.toml or run /cobbleoptimizer set patches.berry_ticker_optimization false and reload.
4.4.0Релиз1.21.1 · 12 мая 2026 г.
CobbleOptimizer 4.4.0 — Release Notes
New optimization: Berry ticker backport (Cobblemon 1.8 → 1.7.3)
Added a new patch that eliminates the per-tick BlockEntityTicker overhead from BerryBlock, ported from how Cobblemon 1.8 handles berry growth.
What it does
- Cancels the original BerryBlock.getTicker() registration (no more per-tick callback on every loaded berry tree).
- Adds hasRandomTicks / randomTick / scheduledTick overrides that drive berry growth via vanilla random ticking instead, with delta-time compensation so average maturation time stays identical to vanilla Cobblemon.
- Mature berries (age = 5) and rooted berries don't tick at all → zero per-tick cost.
Performance
- Before: every loaded BerryBlockEntity ran a callback 20×/s → linear cost scaling with the number of loaded berry trees.
- After: each berry block is visited on average ~once per 68 s (at randomTickSpeed=3), with the elapsed game-time subtracted in one batch from stageTimer.
- On servers with large berry farms, this removes a constant per-tick overhead proportional to the farm size.
Configuration
- Config key: patches.berry_ticker_optimization
- Default: true (enabled out of the box for new installs; existing config files preserve their previous values).
- To disable: edit cobbleoptimizer.toml or run /cobbleoptimizer set patches.berry_ticker_optimization false and reload.
Комментарии
Загружаем…