Adrian (2026-10-30): Cobblebase's skills stay in but gated behind progression, power from an existing mod (Poke Power) also gated, evolution stones as ores fine for now, balance fine and configurable. Progression is the zones whose Alpha guardian a player helped beat (Progress saved data; a guardian win records it and lists the unlocks). The gate table is data (progression_gates/base.json): each of Cobblebase's 44 skills needs a zone (or none), the Power Block needs the Verdant Jungle. The companion mod wraps every Cobblebase skill executor in a gate by reflection; a skill missing from the table stays off. Operator command /cobblesurvival progress. Cobblebase's and Poke Power's configs ship in the pack. Self-tests: gate coverage, a locked skill only runs after its guardian, the Power Block waits for the Jungle guardian, a guardian win counts as progress. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37 KiB
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 |
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). Lootr also makes loot per player. 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 whole island | deep dark | 45–60 | darkness (vanilla sculk; no Warden) | Sableye or Spiritomb, Lv 62 | |
| Basalt Furnace | under the whole island | 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.pywrites the zone grid todatapacks/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.pywrites 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. 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 are shared out over the land zones by strength. The result per zone is indocs/zone-species.md;world/zones.json→speciespins a line by hand. - Cave zones: sky-light minimums, "can see sky" and the "natural" ground preset are dropped from their entries; otherwise the Deep Dark (fed by Cobblemon's surface "spooky" spawns) could never spawn anything, and lush caves' moss floors would barely count.
- 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) andspawn_survey(a player at a point deep inside each zone is offered only that zone's spawns, and at least one), both intools/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.speciesoverrides 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 guardiansfor operators). Definitions:datapacks/core/data/cobblesurvival/guardians/<zone>.json, written bytools/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_mildintools/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 veins. Ore only comes from Regenerating Ore Veins (plus chest loot): a mined vein block turns into a regenerator and grows back after its time, which counts in real time, unlike the guardians' game time. Each ore tier has veins in exactly one zone, higher tiers in higher zones (table in docs/balance.md). tools/zone_ores.py writes the mod's config (pack/config/regenerating_ore_veins/) from world/zones.json → ores:
- A surface zone is a set of boxes cut from the zone grid; the mod checks every block of a vein against them, so no vein block lies outside its zone. Cave biomes are zones of their own, so surface tiers stay out of them; the mod checks the biome only at a vein's centre, so a vein's edge can reach up to two blocks over a cave border. Cave tiers are limited to their cave biome and the depths where it lies (the Deep Dark mostly below y −24, the others between 0 and 40).
- Tiers with an ordinary and a deepslate ore get two veins: the ordinary ore from y 0 up, the deepslate one below.
- 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_breakingfalse), 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. - The mod fills a new chunk with veins only while the chunk is loaded, 8 chunks a tick, and forgets the rest when the server stops. Pregeneration is faster than that, so
tools/make_world.pyloads the island again row by row until every chunk is filled (/cobblesurvival veins unfilledcounts what's left), and the world report fails on any unfilled chunk. On a live server new chunks fill as players load them. - One showcase vein per surface zone (its first tier) sticks out of the ground near the zone's sample point, so players see what a vein looks like before they dig.
- Checked: the world report (ore only in tracked veins inside their tier's zone, every tier present, every chunk filled) and the self-tests
vein_regrows_after_unloadandvein_regrows_after_restart(a second server start intools/selftest.pyandtools/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_guardiansandpower_block_waits_for_guardian;guardian_appears_and_returnschecks that the win counts as progress.
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.
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 |