Перейти к содержимому
Mineforgian

CobblemonOptimizer

CobbleOptimizer is a server-side Fabric mod that reduces lag caused by Cobblemon's Pokemon entities.

15K загрузок23 подписчиковMITfabricneoforge

Обновлён 24 мая 2026 г. · опубликован 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.

Центр версий

33 версий
  • Релиз120 КБ
  • Релиз489 КБ
  • Релиз118 КБ
  • Релиз486 КБ
  • Релиз114 КБ
  • Релиз482 КБ
  • Релиз116 КБ
  • Релиз484 КБ
  • Релиз116 КБ
  • Релиз485 КБ
  • Релиз479 КБ
  • Релиз110 КБ
  • Релиз109 КБ
  • Релиз478 КБ
  • Релиз109 КБ
  • Релиз478 КБ
  • Релиз109 КБ
  • Релиз477 КБ
  • Релиз109 КБ
  • Релиз478 КБ

Ченджлог

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:

  1. 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.
  2. [.-_] 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:

  1. 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.
  2. [.-_] 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.
4.3.3Релиз1.21.1 · 5 мая 2026 г.

Changes — v4.3.3

  1. Removed console log spam

The Batch despawn: removed X (Y aged out) [Skitty x6, Bramblin x4, ...] log line was being printed on every sweep cycle (every ~10 seconds when entities were despawned). It's now gone. Internal counters (lastDespawnCount, lastAgeDespawnCount) are still updated and remain visible via the /cobbleoptimizer status
command — only the log noise was removed.

  1. TPS-gated sweep

Previously the batch despawn ran on a fixed timer (every check_interval_ticks, default 200 ticks = 10s) regardless of server health. Now it only runs when TPS drops below a configurable threshold.

New config field: batch_despawn.tps_threshold (default 18.0).

  • TPS ≥ 18.0 → no despawn sweep (server is healthy, no need)
  • TPS < 18.0 → sweep runs at the normal interval

This brings batch despawn in line with the other features (tick_throttle, ai_freeze), which already use the same TPS-gating pattern.

  1. Emergency override preserved

The forceNextSweep() flag (used by the Emergency Manager when TPS drops below emergency.tps_threshold, default 12.0) bypasses both the interval check and the new TPS gate. So even if you set batch_despawn.tps_threshold to something low like 14.0, an emergency at TPS 11 will still force an immediate sweep.

Files changed (mirrored on Fabric + NeoForge)

  • CobbleOptimizerConfig.kt — added tpsThreshold: Double = 18.0 to BatchDespawnConfig
  • BatchDespawnManager.kt — added TPS gate, removed log line, removed dead species-counting code
  • ConfigManager.kt — TOML parse/write, key list, and setValue support for the new field
  • ConfigValidator.kt — validates tps_threshold in range 1.0..20.0
  • gradle.properties — version bumped 4.3.2 → 4.3.3

How to tune

/cobbleoptimizer config set batch_despawn.tps_threshold 17.0 # stricter (only at 17 TPS) /cobbleoptimizer config set batch_despawn.tps_threshold 19.5 # more aggressive /cobbleoptimizer config set batch_despawn.tps_threshold 20.0 # effectively "always on" (old behavior)

The change is backwards-compatible: existing cobbleoptimizer.toml files without the new key fall back to the default 18.0 and the key is written on the next save.

4.3.3Релиз1.21.1 · 5 мая 2026 г.

Changes — v4.3.3

  1. Removed console log spam

The Batch despawn: removed X (Y aged out) [Skitty x6, Bramblin x4, ...] log line was being printed on every sweep cycle (every ~10 seconds when entities were despawned). It's now gone. Internal counters (lastDespawnCount, lastAgeDespawnCount) are still updated and remain visible via the /cobbleoptimizer status
command — only the log noise was removed.

  1. TPS-gated sweep

Previously the batch despawn ran on a fixed timer (every check_interval_ticks, default 200 ticks = 10s) regardless of server health. Now it only runs when TPS drops below a configurable threshold.

New config field: batch_despawn.tps_threshold (default 18.0).

  • TPS ≥ 18.0 → no despawn sweep (server is healthy, no need)
  • TPS < 18.0 → sweep runs at the normal interval

This brings batch despawn in line with the other features (tick_throttle, ai_freeze), which already use the same TPS-gating pattern.

  1. Emergency override preserved

The forceNextSweep() flag (used by the Emergency Manager when TPS drops below emergency.tps_threshold, default 12.0) bypasses both the interval check and the new TPS gate. So even if you set batch_despawn.tps_threshold to something low like 14.0, an emergency at TPS 11 will still force an immediate sweep.

Files changed (mirrored on Fabric + NeoForge)

  • CobbleOptimizerConfig.kt — added tpsThreshold: Double = 18.0 to BatchDespawnConfig
  • BatchDespawnManager.kt — added TPS gate, removed log line, removed dead species-counting code
  • ConfigManager.kt — TOML parse/write, key list, and setValue support for the new field
  • ConfigValidator.kt — validates tps_threshold in range 1.0..20.0
  • gradle.properties — version bumped 4.3.2 → 4.3.3

How to tune

/cobbleoptimizer config set batch_despawn.tps_threshold 17.0 # stricter (only at 17 TPS) /cobbleoptimizer config set batch_despawn.tps_threshold 19.5 # more aggressive /cobbleoptimizer config set batch_despawn.tps_threshold 20.0 # effectively "always on" (old behavior)

The change is backwards-compatible: existing cobbleoptimizer.toml files without the new key fall back to the default 18.0 and the key is written on the next save.

4.3.2Релиз26.1, 26.1.1, 26.1.2 · 2 мая 2026 г.

CobbleOptimizer 4.3.2 — Patch Notes

Fixed: ghost Pokémon after batch despawn

Sometimes when the mod cleaned up extra wild Pokémon to keep TPS healthy, you'd still see them standing around on your screen — they couldn't be interacted with, didn't move, and only disappeared after relogging or moving far away.

This happened because the server removed the Pokémon, but in some cases forgot to tell your client about it. Now the server sends an explicit "remove this entity" message to every player who could see the Pokémon, right at the moment it gets despawned. No more invisible-to-the-server ghosts cluttering your view.

4.3.2Релиз1.21.1 · 2 мая 2026 г.

CobbleOptimizer 4.3.2 — Patch Notes

Fixed: ghost Pokémon after batch despawn

Sometimes when the mod cleaned up extra wild Pokémon to keep TPS healthy, you'd still see them standing around on your screen — they couldn't be interacted with, didn't move, and only disappeared after relogging or moving far away.

This happened because the server removed the Pokémon, but in some cases forgot to tell your client about it. Now the server sends an explicit "remove this entity" message to every player who could see the Pokémon, right at the moment it gets despawned. No more invisible-to-the-server ghosts cluttering your view.

Комментарии

Загружаем…