Files
onion-mc/analysis/client-perf/SPAWN-TUNING.md
T
logan 611a1a5952 docs: client-perf analysis, bench harness and work journal
Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:

- analysis/client-perf/: LEVERS (ranked levers + corrections), BENCH-MATRIX
  (world, scenes, config IDs, blocks B0-B14 with decision rules),
  PLAYER-TUNING, SPAWN-TUNING, research briefs, the jar scanner and its
  output, observed default configs, and proposed-configs/ (build.py
  generates tiers and bench variants and fails on unknown keys;
  apply_variant.py applies a variant and merges options.txt).
- analysis/client-perf/bench/onion-bench/: bench-world datapack (scene
  teleports, Create grid, mob pen, sound storm, 120 s teleport tour).
- analysis/audit/: the static recipe/dependency audit, including gen_fixes.py,
  which generates the shipped Paxi datapack and was never tracked.
- phase0/: per-machine measurement harness (Steam Deck, 7700K/1060,
  6700K/1080 Ti).
- .pi/journal.md: running work log; read it first.

All of it is packwizignored, so nothing here ships to players.
2026-10-14 18:15:32 -04:00

4.2 KiB
Raw Blame History

Spawn tuning (server-side lever 3)

Owner brief (2026-10-14): tune spawns, but not in a way that hurts gameplay much. All three files ship enforced from config/ (this repo is the server directory, and clients get them too, which only matters in singleplayer). Each file is partial: the mod fills every other key with its default. Research came from three subagent briefs (2026-10-14); every load-bearing fact below was re-checked against the pinned jar or the source at the matching version. Unmeasured: bench block B14 (below) checks it.

What shipped

Alex's Mobs 1.22.17: config/alexsmobs-common.toml

  • Format: NeoForge ModConfigSpec COMMON (AlexsMobs.class: registerConfig(COMMON, …); no custom filename). Keys are flat under [spawning] (CommonConfig: push("spawning"); buildInt ignores its category argument). A partial file gets corrected and re-saved by NeoForge.
  • Changed (weight, 0–1000; group sizes are hard-coded in AMWorldRegistry): gazelle 40→20 (herds of 7), capuchinMonkey 28→14 (groups of 9–16), elephant 30→15, straddler 70→35, rockyRoller 60→30, underminer 50→25, blobfish 30→15, mudskipper 28→14, caiman 29→15. Everything rare is untouched.
  • Issue #62 on Raguto/AlexsMobs-1.21.1 ("tons of monsters" / inflated vanilla spawns) is open, unexplained, and no config addresses it. If it shows up, A/B test a world without Alex's Mobs.

Fowl Play 1.2.3: config/fowlplay.json5

  • Format: YACL v3 JSON5 (YACLIntegration: fowlplay.json5). YACL 3.8.2 (GsonConfigSerializer.loadSafely) keeps defaults for missing fields and re-saves; a bad value is logged and left at its default, not a crash.
  • Changed (default → new): duck weight 4→2, max group 6→4 · goose 4→2, 4→3 · gull 5→3, 8→5 · sparrow 20→12, 6→4. Songbirds and raptors are untouched.
  • Context: #214 (~400 ducks on rivers) is open. 1.2.1 added a 200-tick spawn gate. The category caps (fowlplay_birds 20, fowlplay_ambient_birds 15) scale with loaded chunks like vanilla, and only became configurable after 1.2.3. If counts are still high, the next lever is a Paxi datapack that narrows #fowlplay:spawns_ducks (currently includes forest tags), added through analysis/audit/gen_fixes.py.

Critters and Companions 2.7.0: config/crittersandcompanions-common.json5

  • It does have a spawn config (contrary to LEVERS' "no config"): YACL JSON5, nested spawning object, one List<SpawnEntry> per mob. SpawnEntry is a record {biomeSpec, weight, min, max} with no custom type adapter, so it serialises as plain Gson record JSON. The jar has no biome-modifier JSON, so a datapack cannot reduce these spawns.
  • A listed mob's list replaces its defaults, so each changed mob lists all its default biomes. "configVersion": 2 is required, otherwise the v1→v2 migration runs.
  • Changed: sea bunny (the worst: warm ocean 32 × groups ≤4 → 20 × ≤3; other oceans 16 → 10, max 4 → 3), leaf insect jungle 14→8 / forest 6→4, dragonfly lush 10→6, and the ladybug / stag beetle / roly poly / snail / stick bug / weevil rules about −40 %. Unchanged: jumping spider, red panda, ferret, dumbo octopus, otter, koi, shima enaga.

Verify on first boot (part of BENCH-MATRIX §0)

  • latest.log has no YACL "Failed to deserialize" lines for fowlplay or crittersandcompanions.
  • After the first launch, each file has been re-saved in full with our values intact. (In the repo working tree that shows up as a diff: don't commit the expanded files unless you mean to.)

B14: measure it (P2, singleplayer, Creative, doMobSpawning true)

Fresh world onionspawn, at a river/forest edge (ducks), a jungle (capuchins, leaf insects) and a warm ocean (sea bunnies). Stand still 10 minutes at each, then count with /execute if entity @e[type=<id>,distance=..128] for fowlplay:duck, fowlplay:gull, alexsmobs:capuchin_monkey, crittersandcompanions:sea_bunny, and in total (@e[type=!player,distance=..128]). Compare against the same world with these three config files removed (defaults). Keep the tuning if totals drop and every species still appears; back it off if a species effectively disappears. Spot-check that vanilla passives (cows, sheep) still spawn normally.