Adrian, 2026-11-02/03: every item that can drop gets a JEI page naming its sources, alongside the Cobblemon Info add-on (which shows drops and biomes, not zones). The companion mod's JEI plugin (jei/DropSourcesJei.kt) adds: - Pokemon drops on the island: 794 species of lines that live on the island, with chances, amounts and the zones they spawn in (or where their line lives); spawns with their own drops (Beheeyem in the End). The Drop Synthesizer core is the catalyst. - Guardians and the End boss; Sacrifice Altar tiers and specials; Rebirth Chamber; zone ore veins with regrow times; Cobblebase pasture finds per skill and zone. JEI runs on the client, so the pages read assets/cobblesurvival/jei/ drop_sources.json inside the mod, written by tools/jei_sources.py from the pack's files. Self-tests drop_sources_match_the_server (file vs live server: drops, zones, own-drop spawns, guardians, End boss, altar) and jei_pages_build (every page builds, every item exists). The ore a vein gives moved into world/zones.json (ores -> item), shared with the quest book. JEI's API (19.64.0.455) is a compile-only dependency from JEI's own Maven. Self-tests and the island check pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
World template
The island world is generated, not hand-built. This folder holds the recipe. The world itself is a build output (several hundred MB of region files), so it stays out of git.
| File | What it sets |
|---|---|
world.json |
Seed, world type, pregeneration radius, border margin, pinned Chunky download |
biomes.json |
The biome list and how every vanilla biome maps onto it, plus extra entries (basalt deltas as a cave biome) |
../pack/config/worldgen_editor/presets/cobblesurvival_island.json |
The island's outline: a Poké Ball (round island, channel across the middle, ring channel around the centre island). Generated by tools/pokeball_preset.py |
../datapacks/core/data/cobblesurvival/worldgen/world_preset/island.json |
The world type cobblesurvival:island: overworld (island shape + remapped biome table) and the End, no Nether. Generated by tools/biome_layout.py from biomes.json; don't edit by hand |
Building it
python3 tools/biome_layout.py # only after changing biomes.json
python3 tools/seed_search.py # only to pick a new seed (add --apply to write it to world.json)
python3 tools/build.py && python3 tools/make_world.py
seed_search.py previews many seeds without generating chunks (op-only dev command /cobblesurvival biomepreview) and ranks them on biome coverage, patch size, a gentle start area and cave biomes. It writes build/seed-search/candidates.png and report.json.
make_world.py uses the local test server (its eula.txt must already accept the EULA). In one server session it creates the world, pregenerates a circle of pregen_radius with Chunky (the island and a strip of sea; the sea corners inside the square border generate when someone gets there), and puts a square world border border_margin blocks outside the outermost coast. It takes about 6 minutes and writes:
build/world-template/: the world, without player databuild/island-map.png: top-down biome map with zone outlines, border and spawnbuild/island-report.json: ore scan, land bounds, border gaps, biome shares
For checking a change without rebuilding the island, tools/quick_check.py samples a fresh world instead (about 1–2 minutes; structures to sample are listed under quick_check in world.json).
python3 tools/prism_instance.py installs the template into the Prism instance as the save Cobblemon Survival Island. tools/smoke_test.py boots the test server on it.
Same seed, preset and mod versions give the same island. After changing any of them, rebuild the template; existing chunks never change on their own.
Editing the island
Change the outline: python3 tools/pokeball_preset.py --radius 1500 --band 160 --button 280 --ring 120 (all in blocks), then search seeds again and rebuild the template. For other shapes, edit the preset JSON by hand (field reference: the WorldGen Editor wiki; the previewer shows outlines before generating). Keep temperature at standard and don't use exclude_biomes: both make WorldGen Editor swap cave biomes for surface fallbacks and let unlisted biomes in. If the ball gets bigger, raise pregen_radius in world.json too.
Change which biomes exist, or what replaces what: edit biomes.json, run tools/biome_layout.py, then search seeds again. Where a biome lands depends on the seed's climate noise, not on the lobes.
Hand edits on the finished world (paths, landmarks, a reshaped coast):
- WorldPainter (desktop): import
build/world-template(File → Import → Existing Minecraft map), edit, and export it back to a folder. Keep a copy first. WorldPainter rewrites chunks and may drop Cobblemon data in those chunks, so edit before anyone plays on the world. - In-game, in creative on the Prism save: build normally, or use a world-edit mod for larger changes. Then copy the save back over
build/world-templateand runpython3 tools/world_report.pyto re-check ore and border.
Hand edits are lost when the template is regenerated, so keep them few, or export them as structures.
Ore
There is no natural ore. NeoForge's remove_features biome modifier (datapacks/core/.../biome_modifier/no_natural_ores.json) removes vanilla ore features. Cobblemon's evolution-stone ores are added from code, so they are switched off by overriding their placed features with zero placements (tools/cobblemon_ore_overrides.py; re-run it after a Cobblemon update). The large copper/iron ore veins are turned off in the overridden WorldGen Editor noise settings (ore_veins_enabled: false). Structures and fossils that have ore built in (Cobblemon habitats and ruins, vanilla fossils) keep their shape, but tools/clean_structures.py makes their processors turn ore into stone (re-run it after a mod update). Nether fortresses and Nether ruined portals can't appear in the basalt-delta caves (their biome tags leave basalt deltas out). tools/world_report.py scans every block of every chunk for anything ending in _ore, ancient debris and raw ore blocks.
Mobs
Only Pokémon. The companion mod (mod/.../world/OnlyPokemon.kt) never lets a vanilla mob join a world unless it is loaded from a save (exceptions: entity type tag cobblesurvival:allowed_vanilla_mobs, for now the Ender Dragon). That covers mobs that structures place during generation, so all structures stay. When a chunk has just been generated it also removes spawners and trial spawners (block tag cobblesurvival:removed_on_generation), stops sculk shriekers from summoning the Warden, and turns infested blocks back into normal ones. Underneath, vanilla spawn lists are emptied (no_vanilla_spawns.json), infested stone doesn't generate (no_infested_stone.json) and the template has doMobSpawning false. tools/world_report.py fails if the world stores any vanilla mob or mob source.