Files
cobblemon-survival-pack/docs/design.md
T
claudeandClaude Opus 5.5 56ffdd9f2e Phase 5: field moves from Cobblemon HMs
Adrian (2026-10-31): use Cobblemon HMs; mining ore is the one hard
requirement, furnaces get lit by a Pokemon inside a Phase 6 machine.

- Cobblemon HMs 4.1.0 in the pack (Modrinth), default config.
- Self-test rock_smash_mines_veins: HMs' Rock Smash breaks a
  regenerating vein, the ore drops and the vein becomes a regenerator.
- HMs' Trainer Ditto (a wild Ditto underneath) is exempt from the
  hostility scan and the stray despawn (world/SpecialPokemon.kt).
- Docs: licenses, addon status, design, balance, roadmap note,
  Phase 5 checklist with the open questions for Adrian.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 03:00:07 +01:00

48 KiB
Raw Blame History

Design notes

The roadmap (design pillars, phases, open decisions) is the source of truth for what to build. This file records how it was built and every decision taken on the way.

Decisions taken in Phase 0

Decision Why
Loader NeoForge 21.1.265 (latest 21.1 build on 2026-10-28) The roadmap's default. Not yet confirmed by Adrian
Cobblemon 1.8.4 instead of 1.8.3 1.8.4 came out 2026-10-27 (bug-fix release); every 1.8-aware addon accepts it
Companion mod builds with Cobblemon's official MDK (Architectury Loom), not the plain NeoForge MDK The roadmap says to take Cobblemon's coordinates from its official docs or addon template. That template is Loom-based and the coordinates (com.cobblemon:neoforge on artefacts.cobblemon.com) come from it
Kotlin 2.4.0 instead of the MDK's 2.2.20 Kotlin for Forge 5.12.0 ships stdlib 2.4.0, which the older compiler can't read
datapacks/core ships inside the companion mod as an always-on built-in data pack (top priority) Works in every world and on every server without copying files around. Its pack.mcmeta filter can later blank Cobblemon's base spawns (Phase 3). The data stays plain JSON in datapacks/core
Every mod .pw.toml carries both a Modrinth URL and CurseForge IDs where both exist (tools/crosslink.py) packwiz only records one source. Without the second one, an export to the other platform copies the jar into overrides/, which bundles a third-party jar
Mods hosted on one platform only are left out of the other platform's export Same rule: no bundling. See the platform split in docs/addon-status.md
Dev instance in Prism is synced with packwiz-installer from build/stage/full Gets every mod from both platforms, and re-syncing removes mods that left the pack. Prism is a Flatpak that can't read the repo folder, so the sync runs on the host
Companion mod id cobblesurvival, package dev.cobblesurvival Placeholder names, easy to rename while the mod is empty
No publishing for now (Adrian, 2026-10-28) The target is the Prism instance and a private server, which both get every mod. The platform split below only matters again for a public release (Phase 9). Mods may be chosen regardless of which platform hosts them

Decisions taken in Phase 1

Decision Why
World type cobblesurvival:island (our data pack) points WorldGen Editor at our own preset cobblesurvival_island Our preset is never confused with WorldGen Editor's bundled examples. Servers set level-type=cobblesurvival:island; the type is also listed in the singleplayer world-type button
Biome set = Adrian's list (2026-10-28): plains, forest, cherry grove, mangrove swamp, jungle, desert, badlands, "mountain edge", jagged peaks; caves: lush caves, dripstone caves, deep dark, basalt deltas Set in world/biomes.json. Ocean, deep ocean, lukewarm/warm ocean, river and beach stay, because an island needs a sea and a coast
The biome list is enforced by remapping vanilla's overworld biome table (from Minecraft's data generator) onto the list, written into the world type by tools/biome_layout.py Keeps vanilla's terrain–biome fit (peaks on peaks, swamps in lowlands) while only listed biomes can appear. Pure data. WorldGen Editor's own climate/exclusion options were rejected: they replace cave biomes with surface fallbacks such as snowy plains, and leak unlisted biomes
"Mountain edge" → windswept_hills (with snowy slopes and stony shore folded in) Mountain Edge was removed in 1.18; windswept hills is its successor. Flagged in case another biome was meant
Basalt deltas is an overworld cave biome under the hottest, driest land (where desert and badlands are), at cave depth like lush and dripstone caves Adrian's request. It keeps its own features (basalt columns, magma, lava deltas) and particles; its nether ores are removed with the rest
The Deep Dark no longer fills the deepslate layer (Adrian, 2026-10-30: "too much"; part of it should become basalt deltas). Vanilla puts it at depth 1.1 wherever erosion is low, at any temperature; world/biomes.json → split cuts it by the temperature of the land above: up to −0.1 Deep Dark, from 0.4 basalt deltas, in between ordinary caves of the land above Biome preview at y −52, share of land: Deep Dark 30 % → 14 %, basalt deltas 0 → 7 %, ordinary caves 9 %; at y −30 Deep Dark 18 % → 7 %. The deep basalt is part of the Basalt Furnace (Lv 55–70), so the deepest caves reach Lv 70 under hot land. The gaps between the pieces must be wide: Minecraft picks the nearest biome entry, and the land biome above is only 0.1 away in depth, so a narrow gap goes to the neighbouring piece
No Nether: the world type cobblesurvival:island defines only the overworld and the End Adrian's request. Portals can still be lit but lead nowhere. The smoke test checks that minecraft:the_nether is an unknown dimension
Island shaped like a Poké Ball (Adrian, 2026-10-28): a round island cut into top and bottom halves by a channel across the middle, with a ring channel around a round centre island where the spawn is. Written by tools/pokeball_preset.py (ball r 1,500, band 160, button r 280, ring 120 — placeholders) WorldGen Editor makes the round island; two flat-ended ocean entries cut the band and 36 overlapping ocean circles cut the ring. Entries have no climate or exclusions; biomes come from the remapped table
The seed is chosen by tools/seed_search.py, which scores many seeds with the op-only dev command /cobblesurvival biomepreview (samples the generator without generating chunks) With vanilla climate noise, which biomes land on a 1,500-block island depends on the seed. The search wants every listed biome at a useful share, few large patches, a gentle start area and all four cave biomes
Natural ore removed with data only, no extra mod: a NeoForge remove_features biome modifier for vanilla ores, zero-placement overrides for Cobblemon's evolution-stone ores, ore_veins_enabled: false in WorldGen Editor's noise settings Pillar 7 (data before code). Ore Generation Configuration was not needed. Cobblemon adds its ores from code as direct holders, which the biome modifier can't match, hence the overrides (found by the ore scan)
Structures and fossils place no ore either: tools/clean_structures.py appends a rule processor that turns ore into stone (raw ore blocks into tuff/terracotta, placeholders) to every processor list that places an ore-containing template or outputs ore Found by the ore scan of the first template: Cobblemon habitats/ruins have ore and raw ore blocks built into their templates, vanilla fossils have coal/diamond ore. Overriding the processor lists keeps the structures and only swaps those blocks
Nether fortresses and Nether ruined portals are kept out of the overworld: their biome tags list the Nether biomes except basalt deltas Basalt deltas is now an overworld cave biome, and these structures go wherever a Nether biome is. The first template had fortress pieces underground
Standard QOL mods (Adrian, 2026-10-28): JEI, Jade, Inventory Profiles Next, Mouse Tweaks, AppleSkin, Controlling, Xaero's Minimap + World Map; performance: Sodium, FerriteCore, ModernFix, ImmediatelyFast, Entity Culling JEI as the NEI successor, Jade as the block/mod probe, Inventory Profiles Next as the Inventory Tweaks successor. Flagged: a minimap and world map make exploring the island easier; drop them if exploration should stay harder. Xaero's radar can show mobs; restrict it in its config if that feels like cheating
The world template is generated by tools/make_world.py from world/world.json and kept out of git The world is several hundred MB. Seed + preset + mod versions reproduce it. Prism and the test server get it from build/world-template
Two test speeds (Adrian, 2026-10-28: 10 minutes was too long): tools/quick_check.py (one boot, smoke checks, /locate for removed structures, a sampled world around spawn and sample structures; about 75 s) for everyday changes, and tools/make_world.py (whole island, about 6 min) only when the island changes The template build pregenerates a circle that just covers the island instead of the whole square, and sets the border in the same server session
Chunky is used only while building the template; it is not in the pack It is a build tool. Pinned by URL and SHA-1 in world/world.json
Seed isle-26 approved (Adrian, 2026-10-28) Poké Ball, radius 1,500
No vanilla mobs, only Pokémon (Adrian, 2026-10-28): the companion mod (world/OnlyPokemon.kt) never lets a vanilla mob join a world unless it is loaded from a save (since Phase 3 any mob that isn't Cobblemon's, e.g. Cold Sweat's chameleons); exceptions go in the entity type tag cobblesurvival:allowed_vanilla_mobs (only the Ender Dragon for now). On top, every biome's vanilla spawn list is emptied (no_vanilla_spawns.json), infested stone doesn't generate (no_infested_stone.json) and the template has doMobSpawning false One rule covers mobs placed by structures during world generation (villagers, guardians, drowned, shulkers, ...), natural spawns, spawners and commands. Cobblemon spawns through its own spawner and isn't a vanilla mob, so Pokémon are unaffected. The data-pack and gamerule layers save the work of creating mobs only to block them. To undo: remove the listener, the two modifier files and the gamerule entry. A side effect: player-built golems and the Wither can't be summoned either
All structures stay, only their ore and vanilla mobs go (Adrian, 2026-10-28) Villages, ocean ruins, monuments, mineshafts, strongholds, trial chambers, ancient cities, Gimmighoul towers etc. generate as designed (igloos, witch huts and mansions can't, because their biomes are remapped away). Exception: ruined portals stay off, because Nether portals shouldn't generate at all
Mob sources in structures go when a chunk has just been generated (world/OnlyPokemon.kt): blocks in the tag cobblesurvival:removed_on_generation (spawner, trial spawner) become air, sculk shriekers can't summon the Warden, infested blocks become normal stone/bricks Stronghold, mineshaft and dungeon spawners and stronghold infested bricks are placed by game code, so data can't reach them. Chunks loaded from disk are never touched. The Deep Dark's own sculk patches can summon the Warden too, not only ancient cities. Trial chamber vaults stay but can't be opened, since trial keys come from trial spawners. tools/world_report.py fails a world that still has a spawner, trial spawner, infested block, summoning shrieker or vanilla mob
Nether portals don't form: the companion mod cancels portal creation while the server has no Nether dimension; ruined portals don't generate (their biome tags are empty) Adrian: portals formed but led nowhere. The check is on the dimension, so if the Nether ever comes back, portals work again. The smoke test lights an obsidian frame and expects no portal
Default keybinds without conflicts, shipped with Default Options (pack/config/defaultoptions/keybindings.txt) NeoForge's Controls screen flags any two keybinds on the same key, even a GUI-only one next to an in-game one. Changes: Cobblemon summary M→N and hide party O→Y; Xaero waypoints U→J, minimap settings unbound; Jade details Shift→V; JEI recipe R→G, bookmark A→K, search Ctrl+F→Ctrl+H, pause cycling Shift→Right Ctrl, search history unbound; KubeJS Kubedex unbound; FTB Quests: recenter Home, chapters ./,, search Ctrl+I, panning up/down and player prefs unbound, all quest-editor shortcuts unbound (pack authors rebind them in Controls → FTB Quests). JEI's mouse-click actions still share mouse buttons with attack/use by design. Check with tools/check_keybinds.py after adding a mod
Square vanilla world border around the land's bounding box, 96 blocks of sea margin (placeholder) The vanilla border can only be a square. On the island's shorter axis the gap to the coast is larger than 96 blocks. The border is measured from the large land masses only; icebergs, sea stacks and wrecks out at sea don't count

Decisions taken in Phase 2

Decision Why
Permadeath: CobbleHardcoreMon removes Pokémon that fainted in a battle when the battle ends; holding a Revival Charm (cobblesurvival:revival_charm, a KubeJS item) saves it once instead Roadmap pillar 2. The charm replaces the Totem of Undying (defaultconfigs/cobblehardcoremon/server.toml). Health Link off; Soul Link is opt-in per player and not used
The companion mod closes CobbleHardcoreMon's gaps (permadeath/Permadeath.kt): a Pokémon that faints outside a battle is settled at the end of the same tick; one that fainted in a battle and was revived before it ended is fainted again just before CobbleHardcoreMon looks; every second each online player's party and PC are swept for fainted Pokémon. A charm is any item in #cobblesurvival:revival_charms Found while writing the permadeath tests: CobbleHardcoreMon only looks once a second outside battles (time to heal a Pokémon or put it in the PC), waits 60 s for a Pokémon whose charm already saved it once, never looks at the PC, and skips a Pokémon that isn't fainted when the battle ends. With the companion mod's part switched off, charm_saves_once, fainted_in_pc and revived_during_battle fail (2026-10-29). Out-of-battle poison can knock a Pokémon out too (5 % HP now and then, no floor). Both mods use the same chat messages
A Revive used during a battle doesn't save a Pokémon that fainted in it (Adrian, 2026-10-29): it is gone when the battle ends Roadmap: a fainted Pokémon is deleted. Revives, Max Revives and Revival Blessing only help within that battle; Revives are mainly Revival Charm material. Adrian may later disable revive items in battles completely
No remote PC access: Cobblemon's /pc needs cheats (operator level 2) and is left as an admin tool; a PC opened at a block closes once the player is more than 10 blocks from it. No remote-PC mod is installed Roadmap Phase 2. Checked by the self-test no_remote_pc. Players on a server never have level 2; single-player worlds only with cheats on
Free movement in battle stays: nothing in the pack stops breaking, placing or walking during a battle Phase 7 boss fights need it. The self-test free_movement_in_battle checks the server side; Cobblemon's own key for leaving the battle screen is a manual check. A wild battle still ends if the player gets too far from the wild Pokémon (Cobblemon's flee distance)
In-game self-tests (/cobblesurvival selftest, tools/selftest.py, also run by tools/quick_check.py) on Minecraft's GameTest framework NeoForge only runs GameTests in a development environment, so the companion mod starts and ticks them itself on the real pack server. Fake players get a connection that accepts every mod channel. The command only exists with -Dcobblesurvival.selftest=true. Tests run in barrier-walled boxes 15×12×15 on a platform at y 200 above spawn; a wild Pokémon must have ticked once before a battle with it starts, or its side never picks a move
Cobblemon's faint timer is effectively infinite (defaultFaintTimer 1,000,000,000 s) Otherwise a fainted Pokémon wakes up on its own after 5 minutes, and staying in a battle that long would let it escape permadeath
No healing while sleeping: Cobblemon healPercent 0 Cobblemon only uses healPercent/healTimer while the player sleeps
Healing Machines are expensive (roadmap): a dearer recipe (gold, iron, a Max Revive and a diamond) and a four times slower recharge; values in docs/balance.md With loot chests handing out ingots (Adrian, 2026-10-29), Cobblemon's copper-and-iron recipe would be cheap early on. The recipe is replaced by KubeJS under the id cobblesurvival:healing_machine
Fight or Flight Reborn and TP-Pastures installed with default settings Tuning comes with the zones (Phase 3) and pastures (Phase 4)
Chest loot keeps its ore and ingots; every loot container refills with a new roll 1 hour after it was first opened (Adrian, 2026-10-29). Tiering loot by structure/biome comes later (lower priority) Done with Lootr (config/lootr-common.toml: refresh_all, refresh_value 72,000 ticks of game time). Loot is shared by all players (Adrian, 2026-10-30): every player joins the scoreboard team islanders (world/SharedLoot.kt) and Lootr's team_loot is on, so a container has one inventory for everybody. Cobblemon's gilded chests (Gimmighoul's hiding spots) aren't Lootr containers: their loot is rolled once, shared, and doesn't come back. This changes the roadmap's Phase 2 item "remove loot tables that hand out ore or ingots": chests are a second, renewable ore source next to the veins (pillar 3)
Lootr converts a vanilla loot chest once the 5×5 chunks around it are loaded, i.e. when a player is near, not during pregeneration So the template keeps vanilla loot chests until then. tools/quick_check.py force-loads the area around a sampled village and checks that its chests became Lootr chests
Matthiesen Core's usage statistics are off by default A pack shouldn't send data for its players without asking; players can switch it on in config/matthiesen_core/metrics.properties

Phase 3 zone plan (approved by Adrian, 2026-10-29)

Source of truth: world/zones.json; tools/zone_layout.py lays it onto the island and draws build/zone-map.png. The model is decided; levels, drops and guardians below are still placeholders (docs/balance.md).

A zone decides which Pokémon spawn and at what levels: Cobblemon's own spawn lists are switched off and each zone gets its own list, drawn from Cobblemon's spawn data for the zone's biomes.

Model. Zones are regions that follow the island's biome clusters. A biome with a hazard (jagged peaks, desert/badlands, mangrove swamp) or its own character (jungle) is its own zone wherever it lies, with small specks dropped. The forest and plains that fill the rest (65 % of the land) are split into regions by position. Rivers belong to the zone they run through; only the coast and the open sea are sea zones. Caves are zones by cave biome, everywhere under the island. Cold Sweat's heat and cold follow the biome anyway, so hazards and zones line up. Cobblemon spawn files can't express these shapes, so the companion mod will add a spawn condition "zone": "<id>" (Cobblemon's appendage API) that looks up a grid generated from this plan.

Zone Where Biomes Levels Hazard (gate) Signature drops (examples) Alpha guardian (example)
Button Isle the start island inside the ring channel (3.6 % of land) forest, plains, a little cherry grove and desert 2–10 none feathers, berries (Pidgey, Sentret, Bidoof) Pidgeotto, Lv 14
Southwold south half, west of the jungle and swamp (30 %) forest, plains, windswept hills 8–18 none wool (Wooloo, Mareep) for cold insulation later; bones, honey Dubwool, Lv 22
Westmarch north-west (18 %) forest, windswept hills 15–25 none raw copper (Cufant), charcoal (Vulpix) Ursaring, Lv 30
Verdant Jungle east, both sides of the band (9 %) jungle 18–30 none (warm and humid, below Cold Sweat's damage) vines, Big Root (Tangela), food (Tropius) Tangrowth, Lv 34
Mangrove Mire south-east (10 %) mangrove swamp 25–38 poison while in the swamp (companion mod area effect); Pecha berries, milk and potions help Black Sludge (Croagunk, Grimer), Pecha berries Toxicroak, Lv 42
Highland Meadows north-east around the peaks (20 %) plains, forest, cherry grove 25–35 none leather (Ponyta) for heat insulation, Hard Stone (Larvitar) Rapidash, Lv 40
Sunscorch the desert and badlands pockets: north of the ring channel, the north-east and north-west coasts (3.4 %) desert, badlands 30–45 heat (Cold Sweat): heat insulation, Fire Resistance potions armadillo scutes (Sandshrew), Soft Sand, magma cream (Numel) Hippowdon, Lv 50
Frostpeak Range the jagged peaks plus the windswept hills and cherry groves right next to them (6 %) jagged peaks 40–55 cold (Cold Sweat): wool insulation; warming food and potions Never-Melt Ice (Snover), Razor Claw (Sneasel) Abomasnow, Lv 60
Shallows coast and beaches ocean, lukewarm and warm ocean, beach 5–20 none fish, kelp none
Deep Sea ring and band channels, outer sea deep ocean 30–50 none Heart Scale-type rarities Lapras or Wailord, Lv 55
Lush Caves under the whole island lush caves 12–28 none glow berries, mushrooms (Paras) none
Dripstone Depths under the whole island dripstone caves 22–38 none Dragon Fang (Bagon, Gible) none
Deep Dark under the cold and temperate land, deep (since 2026-10-30) deep dark 45–60 darkness (vanilla sculk; no Warden) Sableye or Spiritomb, Lv 62
Basalt Furnace under the hottest land, at cave depth and (since 2026-10-30) down to the bottom basalt deltas 55–70 heat (Cold Sweat) raw iron (Durant), coal (Torkoal), blaze powder (Heatmor) Heatran-like boss later (Phase 7)

Order of play the bands suggest: Button Isle → Southwold → Westmarch or Jungle → Mire or Highlands → Sunscorch (heat) → Frostpeak (cold) → the deep caves.

What helps with a zone drops from the boss fight of the zone before it (Adrian, 2026-10-29). Wild Pokémon keep their normal drops (the "signature drops" column); the items a zone's hazard asks for come from the previous zone's Alpha guardian, so beating it is the way forward. Never a hard unlock: potions and golden apples still get a player through. Placeholder chain:

Boss of Helps with Drops (placeholder)
Button Isle Southwold Poké Balls, Potions
Southwold Westmarch, Verdant Jungle Great Balls, Exp. Candy
Westmarch, Verdant Jungle Mangrove Mire (poison) the material for wading gear that keeps the swamp's poison off, Pecha berries
Mangrove Mire, Highland Meadows Sunscorch (heat) Cold Sweat heat-insulation material
Sunscorch Frostpeak Range (cold) Cold Sweat cold-insulation material (the recipe also takes wool)
Frostpeak Range Deep Dark, Basalt Furnace Night Vision potions, more heat insulation

Decided with the plan (Adrian, 2026-10-29): the Sunscorch pocket just north of the start and the hot desert spots on Button Isle stay as an early taste of the heat; caves follow the cave biome everywhere, so the Deep Dark under the start island is Lv 45–60 too; the straight Westmarch/Highland Meadows border (x = −250) stays.

How zones are built (Phase 3, step 2):

  • tools/zone_layout.py writes the zone grid to datapacks/core/data/cobblesurvival/zones/island.json (24-block cells; caves by cave biome). The companion mod loads it (zone/Zones.kt) and adds the spawn-condition field "zone"/"zones" to every Cobblemon spawn condition. /cobblesurvival zone (operators) names the zone you stand in.
  • Cobblemon's own spawn files are switched off by a filter in datapacks/core/pack.mcmeta. tools/zone_spawns.py writes one spawn pool per zone (datapacks/core/data/cobblesurvival/spawn_pool_world/<zone>.json) from Cobblemon's spawn data: every evolution line that can spawn on the island gets one home zone (none is lost; legendaries, mythicals, Ultra Beasts and Paradox Pokémon stay out), and its levels are clamped into the zone's band, which picks the evolution stages; every stage that reaches the band spawns up to its top (Adrian, 2026-10-31; Cobblemon's own ranges stop where the next stage takes over, which left Dusclops at Lv 45–46 in the Deep Dark and the zone topping out at Lv 54). Wild Pokémon never evolve; a caught one past its evolution level evolves on its next level-up. Placement weighs how much of the zone is the line's habitat, how much of the line's range the zone covers, and the line's strength (base-stat total of its strongest form) against the zone's band. Lines that Cobblemon lets spawn nearly everywhere first fill the cave zones, which take those whose first stage's primary type fits the cave (world/zones.json → caves → types; Adrian, 2026-10-30: the deep caves' tables were too small), then are shared out over the land zones by strength. The result per zone is in docs/zone-species.md; world/zones.json → species pins a line by hand.
  • Cave zones: every entry spawns in the cave's biome, and sky-light minimums, "can see sky", time of day, excluded biomes and the "natural" ground preset are dropped; otherwise the Deep Dark (fed by Cobblemon's surface "spooky" spawns, many of them night-only) would barely spawn anything, and lush caves' moss floors would barely count.
  • Strays (Adrian, 2026-10-30: a Lv 61 from the Basalt Furnace turned up in the Lush Caves): every 5 seconds a wild Pokémon near a player that stands in a zone whose band it tops by more than 10 levels despawns, unless it is in a battle, angry at someone or a guardian (zone/Wanderers.kt, world/zones.json → wanderers). Tested: strays_despawn.
  • Basalt Furnace got Durant, Torkoal and Heatmor pinned to it: its own lines were all big (Charizard, Turtonator, Centiskorch, …) and Cobblemon only spawns a Pokémon where its body fits, so cramped basalt caves stayed empty.
  • Tested: spawn_pools_are_zoned (no Cobblemon default spawn is left; every entry has a zone and spawns within its band) and spawn_survey (a player at a point deep inside each zone is offered only that zone's spawns, and at least one), both in tools/quick_check.py.

The Mire's poison (Phase 3, step 5): while a player is in the Mangrove Mire without Mire Waders on, the companion mod gives them Poison every 5 seconds (zone/ZoneHazards.kt, data in datapacks/core/data/cobblesurvival/zone_hazards/mire.json, protection tag #cobblesurvival:mire_protection); the first time they walk in unprotected they get a warning. Vanilla Poison never kills, but it pins a player at half a heart, so a fall or a Pokémon's hit becomes deadly; milk, potions and golden apples still help. Mire Waders (leather boots, a KubeJS item) drop from the guardians of Westmarch and the Verdant Jungle, the zones before the Mire. Tested: mire_poisons_without_waders.

Soft level pressure (Phase 3, step 6; no hard level caps): a Pokémon more than 5 levels above the band of the zone its trainer is in gets 10 % less experience per extra level, down to 10 % (zone/LevelPressure.kt, values in world/zones.json → level_pressure). It counts battle experience and anything else except Exp. Candy and commands. The roadmap also offered a disobedience chance; experience alone is gentler and Cobblemon has nothing to build disobedience on. Tested: level_pressure_cuts_xp.

Flyers (Phase 3, step 7): strong flyers only spawn in high-level zones. A species you can ride through the air with a top flying speed of 60 or a top stamina of 85 (Cobblemon's ride stats) never spawns in a zone whose band starts below Lv 30; its weaker pre-evolutions still do, and a line that starts as a strong flyer is only placed in such zones (tools/zone_spawns.py, which refuses to write pools that break this). So Drampa lives in Sunscorch, Togekiss, Staraptor and Braviary in Frostpeak, Charizard in the Basalt Furnace; Salamence never spawns (Bagon and Shelgon stay in the Dripstone caves), and Aerodactyl only comes from fossils. Ride stats stay Cobblemon's for now: they can be overridden per species with a species_additions file replacing riding, best tuned after play-testing how far a flyer takes you on a 3 km island. Nothing blocks mounting.

Alpha guardians (Phase 3, step 4; Adrian, 2026-10-29: fixed spots, back 5 hours after being beaten):

  • One per zone except the Shallows, Lush Caves and Dripstone; the Basalt Furnace gets its boss in Phase 7. Each stands at its zone's sample point (deep inside the zone; a cave floor for the Deep Dark) and only appears while a player is within 96 blocks; it wanders no further than 24 blocks.
  • The guardian is the strongest Pokémon that spawns walking (or, at sea, swimming) in its zone, five levels above the band, half again as big, and uncatchable: Pachirisu (Button Isle), Sigilyph (Southwold), Carbink (Westmarch), Tangrowth (Jungle), Arcanine (Mire), Cinderace (Highlands), Delphox (Sunscorch), Tyranitar (Frostpeak), Kingdra (Deep Sea), Dusknoir (Deep Dark). world/zones.json → guardian.species overrides the pick.
  • Beating it in a battle gives every player in that battle its drops (the chain above: Icy Rocks before Sunscorch, Heat Rocks before Frostpeak, ...). It returns after 5 hours of game time, which only passes while the server runs. Cobblemon's Habitat Blocks were the roadmap's idea, but they can't wait a set time after a defeat or carry custom drops, so the companion mod runs guardians (zone/Guardians.kt; state in the world save; /cobblesurvival guardians for operators). Definitions: datapacks/core/data/cobblesurvival/guardians/<zone>.json, written by tools/zone_spawns.py.
  • Tested: guardian_appears_and_returns (appears big and uncatchable at its level, beaten in a real battle, drops arrive, stays away, returns after its time).

Hazards (Phase 3, step 5), with Cold Sweat 2.4.4:

  • Cold and heat follow the biome: Frostpeak's jagged peaks freeze an unprotected player in about a minute even at noon, Sunscorch's desert and badlands overheat one in about two minutes at noon; deserts cool off at night. Cold Sweat's insulation doesn't move the comfortable range, it slows how fast the body drifts out of it.
  • Only Cold Sweat's fur set (cold) and hide set (heat) really insulate: about 14 minutes in Frostpeak at noon and 25 in Sunscorch, longer with extra fur or hide sewn in. Their materials need boss drops (Adrian's rule): Goat Fur from wool and a Heat Rock (Sunscorch's guardian), Hoglin Hide from leather and an Icy Rock (the Mire's and the Highlands' guardians), kubejs/server_scripts/insulation.js. Leather armour no longer insulates by itself; sewn-in leather and wool only a little. Fire Resistance and Cold Sweat's own potions and warm/cold food still work.
  • So the lowlands stay livable at night, the coldest comfortable temperature is lower (0.25 instead of 0.4) and windswept hills are milder (45–72 °F instead of 24–58 °F). New players keep Cold Sweat's 5-minute grace period.
  • Cold Sweat's own animals (chameleons) can't join, like vanilla mobs: the only-Pokémon rule now lets in Cobblemon's entities only.
  • Tested on the island itself (cold_needs_fur, heat_needs_hide, lowlands_are_mild in tools/quick_check.py): players stand at real spots in each zone, their body drift is turned into minutes until it hurts, and a frozen player without the grace period takes damage.

Phase 4: resources

Adrian's answers (2026-10-30): Cobblebase's skills look fun and stay in, gated behind progression; power comes from an existing mod, also gated (Cobblemon Poke Power); evolution stones as ores are fine for now; the balance values are fine for now and stay configurable, to tweak later.

Ore nodes and veins. Ore only comes from Regenerating Ore Veins (plus chest loot): a mined ore block turns into a regenerator and grows back after its time, which counts in real time, unlike the guardians' game time. Each ore tier lives in exactly one zone, higher tiers in higher zones (table in docs/balance.md). Adrian (2026-10-30): ore shows up mainly as small nodes on the surface, the larger veins underground are harder to find, and the cave zones' ores are nodes on the cave floor, not in the walls. tools/zone_ores.py writes the vein mod's config (pack/config/regenerating_ore_veins/) and the node table from world/zones.json → ores:

  • Surface nodes (every surface tier): 1–5 ore blocks lying in natural ground (grass, dirt, sand, stone, snow, ...; tag cobblesurvival:ore_node_ground), at most one block standing out, never in water or under leaves, a given chance per chunk of the tier's zone. Evolution stones are single blocks and rarer.
  • Cave nodes (Lush Caves, Dripstone Depths, Deep Dark, Basalt Furnace): a lump on a cave floor in the tier's cave biome, at the depths where that biome lies (the Deep Dark mostly below y −24, the others between 0 and 40). Cave tiers have no veins inside the rock.
  • The companion mod places the nodes (ore/OreNodes.kt, table datapacks/core/data/cobblesurvival/ore_nodes/island.json) in every new overworld chunk, through the vein mod's own placement, so they are veins like any other and grow back.
  • Underground veins (surface tiers): larger (radius 2–4) and fewer than the nodes, generated by the vein mod inside the rock under their zone. A surface zone is a set of boxes cut from the zone grid; the mod checks every vein block against them, so no vein block lies outside its zone; cave biomes are zones of their own, which the veins keep out of (the mod checks the biome at a vein's centre, so an edge can reach a little over a cave border). Tiers with an ordinary and a deepslate ore get two veins: the ordinary ore from y 0 up, the deepslate one below.
  • Vein Locator: attuned in the crafting grid with an ore block (needs Silk Touch), it finds the nearest vein or node of exactly that block and throws a signal toward it like an Eye of Ender; 75 % chance to break per use. Attuned to the deepslate ore it only finds the deep half of the veins.
  • Cobblemon's evolution stones are tiers too (approved for now, 2026-10-30): their natural ores have been off since Phase 1, so stones had no source. Each stone lives in one zone that fits it (Leaf Stone in the jungle, Water Stone in the Mire, Ice and Dawn Stone on Frostpeak, ...).
  • Players can't break regenerators (allow_breaking false), so nobody removes a vein for good, and explosions don't hurt veins. The Vein Locator is crafted from a compass and a copper ingot instead of netherite.
  • Both mods fill a new chunk only while it is loaded, a few chunks a tick, and the vein mod forgets the rest when the server stops. Pregeneration is faster than that, so tools/make_world.py loads the island again row by row until every chunk has its veins and nodes (/cobblesurvival veins unfilled counts what's left), and the world report fails on any chunk without them. On a live server new chunks fill as players load them.
  • Checked: the world report (ore only in tracked veins and nodes inside their tier's zone, every tier with nodes and every surface tier with veins, every chunk filled) and the self-tests surface_nodes_lie_in_the_ground, cave_nodes_lie_on_the_cave_floor, vein_regrows_after_unload and vein_regrows_after_restart (a second server start in tools/selftest.py and tools/quick_check.py).

Unique drops. Only Pokémon live on the island, so a mob's drop needs another source. tools/drop_audit.py checks every item a Pokémon or a vanilla mob drops that a recipe or brewing consumes, and writes docs/pokemon-drops.md (item, wild Pokémon with zone and chance, other sources, consumers). Gaps it found, filled through Cobblemon species additions (datapacks/core/data/cobblesurvival/species_additions/, placeholders): Blaze Rod (Carkol in Westmarch, Torkoal in the Basalt Furnace; needed for brewing stands, blaze powder and Eyes of Ender), Ghast Tear (Drifloon, Dusclops), Breeze Rod (Whimsicott), Shulker Shell (Shuckle, Cloyster), Nether Star (Charizard). The tide armour trim and the wither skeleton skull stay without a source (cosmetic here). A zone spawn with its own drops overrides the species' drops, so the audit also fails if an addition targets such a spawn (Magmortar's and Centiskorch's did). Self-test: drop_additions_apply.

Base jobs and power, gated behind progression. A player's progression is the zones whose Alpha guardian they have helped beat (progress/Progress.kt, saved with the world; the guardian win records it for every player in the battle and lists what it unlocked). The gate table is data, datapacks/core/data/cobblesurvival/progression_gates/base.json:

  • Cobblebase (Pokémon in a pasture work: harvesting, producing, finding, buffs, ...): each of its 44 skills works for a pastured Pokémon only once the Pokémon's owner has beaten the skill's zone. From the start: gathering, farming, producing, fuel, guarding, scouting; then step by step through the zones, with mining and the ore finder after Westmarch, the evolution-item finder after the Jungle, the player buffs after Highland Meadows and the Mire, the recruiter after Sunscorch and the healer after Frostpeak (table in docs/balance.md). The companion mod puts every Cobblebase skill executor behind the gate, by reflection, when the server starts (progress/CobblebaseGate.kt); a skill missing from the table stays off, so an update can't add ungated skills. Cobbreeding is not installed, so Breeder and Egg Hatcher do nothing.
  • Cobblemon Poke Power (Electric-type Pokémon in a Power Block make Forge Energy): a survival player can place a Power Block only after beating the Verdant Jungle's guardian (the zone with the redstone its recipe needs). Its recipe is the mod's own (iron blocks, redstone blocks, an Electirizer); nothing in the pack uses the energy yet (Phase 6 machines).
  • Operators: /cobblesurvival progress <player>, ... grant|revoke <player> <zone>.
  • Self-tests: gates_cover_every_cobblebase_skill (every skill has a gate, every gate zone has a guardian, every executor is gated), cobblebase_skills_wait_for_guardians and power_block_waits_for_guardian; guardian_appears_and_returns checks that the win counts as progress.

Catching high-level Pokémon (Adrian, 2026-10-30). Measured against the trainer's strongest party Pokémon (catching/Catching.kt, values in datapacks/core/data/cobblesurvival/catching/rules.json):

  • The catch rate falls with the level gap: full at the trainer's level, then linearly down to 2 % of the normal rate at 20 levels above and beyond ("20+ levels higher should be very improbable"). Applied to the rate Cobblemon's catch formula uses (its catch-rate event), so balls, status and HP still count.
  • A failed catch angers the Pokémon: it attacks the thrower instead of fleeing.
  • A wild Pokémon above the strongest Pokémon in a nearby player's party (16 blocks) is hostile to that player.
  • The fighting is Fight or Flight Reborn's: an angry Pokémon gets the aspect cobblesurvival_enraged, which the pack's config/fightorflight.json5 lists in always_aggro_aspects (so it fights rather than flees), and its target is set through Fight or Flight's own "caught by" mark, by reflection. While an angry Pokémon has a target, thrown balls don't catch it (Fight or Flight's aggressive_pokemon_catchable false, its default): it has to be battled. Pokémon below Lv 5 never fight back (its minimum_attack_level).
  • Self-tests: catch_rate_falls_with_level_gap, failed_catch_enrages, strong_wild_pokemon_hunt_weak_trainers, wild_pokemon_ignore_stronger_trainers.

Bee nests (found by Adrian in the Phase 4 world): a nest whose bee the island turns away kept the bee and tried to let it out every tick, with its sound each time. The companion mod now empties such a nest (world/OnlyPokemon.kt); honey still comes from Combee and shearing nests that have honey.

The field guide learned two things on the way: vanilla mobs count as absent (the companion mod lets only Cobblemon's entities join a world), and species additions replace the drops they set. The veins come in as sources from world/vein-sources.json.

Notes for Phase 5

  • Shoulder Pokémon (Adrian, 2026-10-30): Cobblemon lets a player carry a small Pokémon on their shoulder (96 species are shoulderMountable: Pidgey, Pikachu, Eevee, Zubat, Squirtle, ...). It has a shoulder-effect system with one type, potion_effect (effect, amplifier, particles, icon), but no species uses it in 1.8. Party passives can start there, as data: species additions giving shoulder Pokémon an effect while carried (e.g. Pidgey slow falling, Zubat night vision, a Fire type warmth against Frostpeak's cold), maybe gated behind progression like Cobblebase's skills. To check first: that species additions can set shoulderEffects, and how the effect behaves when the Pokémon faints or goes back in its ball.

Phase 5: existing mods checked first (2026-10-31)

The roadmap lists four mods as prior art; on Cobblemon 1.8 / NeoForge 1.21.1 today:

  • Cobblemon HMs 4.1.0 (NeoForge, Cobblemon ≥ 1.8.0, Kotlin for Forge): send out a Pokémon that knows the move, pick it on Cobblemon's interaction wheel, and your fist uses it. 39 abilities: Cut, Rock Smash, Dig, Strength, Teleport, Leafage, Growth, Flash, Dive, Rock Climb, Magnet Rise, Sweet Scent, weather moves (Rain Dance, Sunny Day, Thunder, Sandstorm, Snowscape, Blizzard), riding boosts (Surf, Tailwind, Agility, ...), Camouflage. Each ability has an on/off switch, cooldown, power, a minimum Pokémon level and a fullness/friendship cost (config/cobblemon_hms.json). Tried with the pack: loads, all self-tests pass. License "shiero's Mods License": free, also in a free modpack; anything that earns money (paid pack, paid server perks) needs an agreement with the author. Missing from the roadmap's first set: ignite (Ember/Flamethrower), freeze water (Ice Beam), extinguish and fill cauldrons (Water Gun).
  • Cobblemon Environment Interactions 3.1.0 (NeoForge, Apache-2.0, Cobblemon ≥ 1.7.3): type-based mining and utilities while riding or commanding one companion; not move-based.
  • Cobblemon Field Moves (Fabric, Cobblemon 1.6), Cobblemon Map Kit (Fabric), SceneBlocks (special blocks, custom license), CobbleStrike (real-time attacks): no fit.

Phase 5: field moves from Cobblemon HMs (Adrian, 2026-10-31)

Adrian: use Cobblemon HMs. Mining ore is the one hard requirement; the other field moves are nice to have, and Flamethrower in the roadmap was only an example. Furnaces are not lit by a field move: a Pokémon goes inside a Phase 6 multiblock instead. So the companion mod doesn't build the roadmap's own field_moves system for now; HMs replaces it.

  • Mining is HMs' Rock Smash: with a Pokémon that knows it sent out, the player's fist breaks the ore it hits and the ore connected to it, up to 32 blocks (power 32). HMs breaks each block as the player with a netherite pickaxe, through the normal break event, so Regenerating Ore Veins turns mined vein blocks into regenerators and the vein grows back. Automated: rock_smash_mines_veins (fires HMs' own Rock Smash handler at a vein).
  • Trainer Ditto. HMs sends a visiting Trainer Ditto that sells TMs; underneath it is a wild Cobblemon Ditto. The island's wild-Pokémon rules (hunting weaker trainers, strays despawning) leave it alone, like guardians (world/SpecialPokemon.kt).
  • Config: HMs' defaults for now (config/cobblemon_hms.json is written by the mod on first start; the pack ships none). Every ability can be switched off or tuned there.

Open, for Adrian (docs/checklists/phase-5.md): whether HMs' abilities wait for progression like Cobblebase's skills, what to do about the ones that get around zone hazards, and whether party passives (shoulder Pokémon) are still wanted.

Notes for Phase 6 (researched 2026-10-31)

Adrian asked for existing mods for the multiblocks, or at least their logic. Phase 6's machines need a pattern-checked structure with a controller, a Pokémon stored inside (keeping its data, visible), safe return when the structure breaks, and state that survives unload and restart. Power is already Poke Power's (Phase 4), so the first machine is the Large Furnace. Nothing on NeoForge 1.21.1 puts a Pokémon into a multiblock; the structure part has several options:

Option What it is License, size Fit
Vanilla BlockPattern / BlockPatternBuilder Minecraft's own pattern matcher (iron golems, withers, end portals): layered aisles, block predicates, finds the structure in any rotation built in Enough for checking a fixed shape around a controller; no previews or editor. Recommended for the companion mod
Patchouli multiblock API Pattern definition and validation with rotation, plus in-world "visualize" previews from a guide book CC BY-NC-SA 3.0, very widely installed Good add-on to the above if players should see how to build a machine (e.g. a field-guide page)
Multiblocked2 Full multiblock framework: in-game 3D editor, controller, recipes, GUIs, machine effects, KubeJS; a Java API for custom traits and recipe capabilities (where a "Pokémon slot" would plug in) LGPL-3.0; needs LDLib2 and KilaGraph (MIT); the companion mod would compile against a snapshot Maven Most powerful, if many machines with recipes and GUIs are wanted; heavy, and the Pokémon part stays custom code
Custom Machinery Data-driven machines for pack makers; recipes can require a structure around the machine and entities nearby (check, hurt, kill) LGPL-3.0, KubeJS optional Poor fit: no stored Pokémon, only nearby entities
Modular Machinery Reborn JSON multiblocks with item/fluid/energy hatches LGPL-3.0; needs ExperienceLib and Athena (GPL) Poor fit: hatches and recipes, nothing for Pokémon
Tiny Multiblock Lib, CTMLib, ZeroCore bed/door-style big blocks; connected textures; an old All Rights Reserved API Not useful

For the Pokémon inside, the best prior art is already in the pack: Poke Power's Power Block (MIT, source) stores Pokémon with their owner, returns them on break, saves and syncs them, and renders the model in the block. Study it (and Cobblemon's Pasture Block, as the roadmap says); don't depend on it.

Open decisions for Adrian (proceeding with the default, flagged)

Decision Default used for now
Roadmap's open decisions table (loader, island size, safety net, boss AoE, etc.) Roadmap defaults, unchanged
Platform split (deferred until a public release; not publishing for now) No platform hosts the full mod list (FTB Quests is CurseForge-only; CobbleHardcoreMon is Modrinth-only). Both mods stay; the exports keep listing what they leave out. Options for release: (a) publish one platform's pack, or both with the gaps listed; (b) ask the authors to cross-post (CobbleHardcoreMon, Matthiesen Core, Regenerating Ore Veins and Ore Generation Configuration are MIT); (c) a quest mod on both platforms; (d) permadeath in the companion mod
No CI (Adrian, 2026-10-30): no Actions runners on the Gitea server, which is too weak; a push that started the old .github/workflows/ci.yml crashed it. The workflow is removed (still in the git history) The roadmap's "CI smoke test" runs locally instead: tools/smoke_test.py, tools/selftest.py, tools/quick_check.py. Adrian accepted the Minecraft EULA for the local test server on 2026-10-28
License for the companion mod and pack content MIT for the companion mod (placeholder); nothing chosen for the rest
Pack name and mod id "Cobblemon Survival Pack" / cobblesurvival (working titles)
Basalt deltas keeps the vanilla Nether biome's mobs and features: ghasts, magma cubes and striders can spawn in those caves, glowstone generates, and Cobblemon's Nether-themed habitats appear there (found by the field guide) Settled by Phase 2: no vanilla mob can join (world/OnlyPokemon.kt), so no ghasts, magma cubes or striders; glowstone and Cobblemon's Nether-themed habitats stay
Items that need the Nether have no source: Choice Band, Choice Specs (Nether Quartz, Blaze Rod), Master Ball (Netherite) Phase 4 adds sources (veins, drops or recipe changes); listed by the field guide
End portals stay openable; the Ender Dragon will be replaced by a Pokémon boss fight (Adrian, 2026-10-28; Phase 7) Eyes of ender are obtainable: ender pearls drop from Abra, Kadabra and Alakazam (and trial chamber loot), blaze powder from Magmar, Magby, Houndour and others. The dragon is on the allowed list until its replacement exists; End city shulkers are blocked like every vanilla mob
End access depends on the seed: a stronghold must start inside the border isle-26 has two; tools/world_report.py now fails a world without one