Files
cobblemon-survival-pack/docs/field-guide.md
T
claudeandClaude Opus 5.5 1a1fb93da8 Phase 4: veins in every chunk, drops for the mobs the island lacks
Ore veins: make_world.py loads the island again row by row until
Regenerating Ore Veins has filled every chunk (/cobblesurvival veins
unfilled), cave tiers sit at their biome's depths, small zones get denser
veins, showcase veins are full size. The world report checks surface
tiers against the zone grid, cave tiers within two biome cells of their
cave, and fails on unfilled chunks; the template passes (37,689 chunks).

Drops: tools/drop_audit.py checks every creature drop a recipe or brewing
needs (docs/pokemon-drops.md). Blaze rods, ghast tears, breeze rods,
shulker shells and nether stars now drop from Pokemon through species
additions (self-test drop_additions_apply). The field guide counts vanilla
mobs as absent, applies species additions and reads the veins as sources.

Cobblebase tried (loads, self-tests pass) and left out until Adrian
decides its scope. Phase 4 checklist with the open questions.

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

12 KiB
Raw Blame History

Field guide

tools/fieldguide/ generates a field guide from the pack's own data: where every Pokémon lives on the island, how to get every item the mods add (and whether the island can provide it at all), and what each item is for. It also exports the same knowledge in two forms the game can show. Everything it writes goes to build/field-guide/; nothing is installed into pack/.

python3 tools/fieldguide/build.py            # about 10 s (+ ~25 s when pack recipes changed); open build/field-guide/index.html
python3 tools/fieldguide/build.py --no-icons # skip icon rendering
python3 tools/fieldguide/build.py --no-server   # never start Minecraft; use the last KubeJS recipe export as it is
python3 tools/fieldguide/kubejs_export.py       # only refresh the KubeJS recipe export (below)
python3 tools/fieldguide/build.py --from-json build/field-guide/fieldguide.json   # re-render only
python3 tools/fieldguide/build.py --extra my-sources.json                         # add sources (below)

It needs tools/build.py (for build/stage/full/mods) or a server under build/server to have run once, because it reads the downloaded jars and the vanilla data jar. The only time it starts Minecraft is to refresh the pack's KubeJS recipes (see Pack recipes).

Outputs

Path under build/field-guide/ What
fieldguide.json The single source. Every renderer reads only this file (schema in tools/fieldguide/guide.py). meta.kubejs_export says which KubeJS recipe export it used; hidden_spawns keeps the spawn entries a filter hides (below)
index.html Overview: counts, locations, items with no source on the island, structures, unresolved data
pokemon.html Pokémon by location (every island biome, caves and the End included), a page per species with the zones it lives in, and the species that are not wild here with the reason and the other ways to get them
items.html Every mod item with filters; the detail view shows recipe grids, all other sources with chances, and every use
icons/ Item icons rendered from the jars' models. Third-party assets: build output only, never commit them
ingame/ftbquests/ Three FTB Quests chapters ("Field Guide: Wild Pokémon", "Other Pokémon", "Items") and their lang/en_us.snbt. Install note in its README.md
ingame/kubejs/ assets/cobblemon/lang/en_us.json: Cobblemon's Pokédex descriptions with "Found in: …" appended. Install note in its README.md

The HTML works from disk (no server, no network) and follows the system's light or dark mode; the ◐ button switches by hand.

How it reads the data

The data stack mirrors Minecraft's pack order: vanilla server data, NeoForge, every jar named in pack/mods/*.pw.toml (plus the companion mod), then datapacks/core, then pack/kubejs on top (KubeJS serves its data/ as a data pack and its assets/ as a resource pack; the guide reads textures and lang from there). A higher layer replaces a file, tags merge across layers, and a pack.mcmeta filter block hides the matching files of the layers below, so now that datapacks/core filters out Cobblemon's spawn pools and adds the zone pools, spawns and every page show only the zone pools. Cobblemon's own entries stay in fieldguide.json under hidden_spawns, in the same shape and resolved against the island the same way (status is what the entry would have if it were active), because tools/zone_spawns.py plans the zones from them; they count for nothing else. Jars are copied to build/fieldguide-cache/jars/ first.

The island comes from world/biomes.json (allowed + water), the world preset named in world/world.json (which dimensions exist: overworld and the End, no Nether), structure and structure-set JSON (which structures can generate in the island's biomes), biome feature lists plus NeoForge biome modifiers (which blocks generate naturally, and which ores the pack switched off), and biome spawners plus structure spawn overrides (where vanilla mobs would spawn). The companion mod lets no mob but Cobblemon's join a world, apart from the entity tag cobblesurvival:allowed_vanilla_mobs (the Ender Dragon), so every other mob counts as absent and its drops need another source.

Spawns follow Cobblemon 1.8.4's rules: a spawn's conditions are alternatives, anticonditions veto, presets are merged into every condition (lists appended, single values kept), and a biome named in any anticondition never counts. A spawn that needs a structure is only listed in the biomes that structure generates in.

The companion mod's zone condition ("zone": "<id>", or "zones": [...], which wins; mod/.../zone/Zones.kt) is shown first in a spawn's conditions as the zone's name and level band from world/zones.json, e.g. "zone Southwold (Lv 8–18)". Each spawn entry in fieldguide.json carries its zone ids (zones), and each "Where to find it" row of a species names the zones (species[*].locations[*].zones; the FTB Quests text says "Badlands (Southwold)"). A zone id missing from world/zones.json is listed under unresolved data.

Statuses

Every way to get something is a source that may need other things (a recipe needs its ingredients and station, a Pokémon drop needs a wild spawn, a mob drop needs the mob, archaeology needs a brush, a fossil needs the fossil and the Fossil Analyzer parts, an evolution needs the pre-evolution and its item). A fixpoint over all items, blocks, mobs, spawns and species then marks each one:

  • available: obtainable on the island.
  • conditional: only with something that may not exist: the End (needs a stronghold portal) or strongholds themselves (their rings start 1,280 blocks out and may lie outside the world border).
  • unavailable: no source here. The guide says why: ore generation switched off, Nether only, a biome or structure the island lacks, or no source in the data at all.

Pack recipes (KubeJS)

The pack adds, replaces and removes recipes in pack/kubejs/server_scripts/ (Phase 2: the Revival Charm, and a Healing Machine that replaces Cobblemon's). Those scripts are code, so the guide does not parse them: it asks KubeJS what they did on the real server.

tools/fieldguide/kubejs_export.py prepares the test server in build/server like the other server tools (it syncs from build/stage/full), boots it on a throwaway void world, runs /kubejs export debug over RCON and stops it (about 25 s). KubeJS reloads the data and writes build/server/local/kubejs/export/; the exporter keeps three parts in build/fieldguide-cache/kubejs-export/export.json:

  • every recipe that carries KubeJS's _kubejs_changed_marker (added or changed by a script; the final recipe JSON plus the script and line),
  • every recipe id a script removed (removed_recipes/), whichever jar or data pack it came from,
  • the server's item registry, so items a KubeJS startup script registers (cobblesurvival:revival_charm) are listed although no jar has a model for them. Their icon is the texture under pack/kubejs/assets, as KubeJS's default item/generated model would show it.

build.py applies that export after reading the data stack: removed recipes disappear (with every source and use they gave), added or changed ones replace any recipe with the same id and are labelled "(pack recipe)" in the guide and the FTB Quests chapter, with script in fieldguide.json pointing at the script line.

The export stores a hash of what can change the recipe set: pack/kubejs/{server_scripts,startup_scripts,data}, pack/mods and datapacks/core. When that no longer matches, build.py refreshes the export by itself before building. So after editing a recipe script:

  1. Run tools/build.py (the server runs the staged copy of pack/kubejs; the exporter refuses to export a staged copy that differs from pack/kubejs).
  2. Run tools/fieldguide/build.py.

If the export cannot run (no EULA in build/server/eula.txt, a test server is already running there, a mod fails to load) or --no-server is given, the guide uses the last export, says so on the console and lists it under "unresolved data". Without any export it shows only the jars' recipes and says that too.

Adding sources: --extra

Sources the data cannot show yet (trades, code-only mechanics) can be fed in without touching the code. The Phase 4 ore veins come this way too: tools/zone_ores.py writes world/vein-sources.json, which the build always reads.

{
  "sources": [
    {"item": "minecraft:raw_iron", "how": "Regenerating iron vein (forest zone)", "kind": "ore vein", "needs": []},
    {"item": "cobblemon:tasty_tail", "how": "Shear a Slowpoke", "needs": [["species:cobblemon:slowpoke"], ["item:minecraft:shears"]]}
  ],
  "remove_recipes": ["cobblemon:poke_ball"]
}

needs is a list of groups; each group is met by any one of its keys (item:, block:, mob:, species:). remove_recipes drops recipes by id. Recipes from data (datapacks/core, pack/kubejs/data) and from KubeJS scripts are read without this file. A later runtime exporter can instead write fieldguide.json itself and render it with --from-json.

Known limits

  • Mechanics that live only in code are not in the data: villager trades (only emeralds are entered by hand), Poké Puffs, Slowpoke tail shearing (Tasty Tail), Oricorio's flowers, Gimmighoul chests, budding Tumblestone. Those items show "no source in the data". Hand-entered vanilla mechanics are in tools/fieldguide/manual_sources.json.
  • Code tables to re-check after a Cobblemon or Minecraft update: COBBLEMON_CODED_FEATURES, CODE_FEATURE_BLOCKS, CODE_LOOT, CODE_STRUCTURE_BLOCKS and SPECIAL_MOBS in tools/fieldguide/world.py, STATIONS and TECHNICAL in model.py. Each says where it comes from.
  • Loot chances are estimates (expected rolls × weight share × random-chance conditions). Spawn chances are Cobblemon's bucket chance plus the weight; the real rate also depends on what else can spawn at that spot.
  • A spawn that needs particular blocks nearby (concrete, pyramid blocks) is listed in every biome its tag allows, because players can build those blocks anywhere; the guide lists those spawns last and marks them.
  • The guide names a spawn's zone but does not know where the zones lie (that is the zone map the companion mod reads at runtime), so a zone pool entry is listed in every island biome its biome condition allows, also where its zone has none of that biome, and its status ignores the zone.
  • Mod item lists come from item models that have a name or appear in data, plus the server's item registry from the KubeJS export; a few creative-only items are marked as such.
  • What a KubeJS startup script sets in code (.displayName, .tooltip) is not in the export: such items are named from pack/kubejs/assets/*/lang if present, else from their id ("Revival Charm"), and have no tooltip in the guide.

In-game checks still needed

The exports follow the formats read from FTB Quests 2101.1.37's and Cobblemon 1.8.4's source, but nobody has loaded them in the game yet:

  1. FTB Quests: the three chapters appear, titles and descriptions show (not raw keys), Pokémon icons render as models (cobblemon:pokemon_model with the cobblemon:pokemon_item component), the quest grid is readable, nothing is locked, and &c/&6 colour codes in item descriptions render as colours.
  2. Pokédex override: KubeJS serves kubejs/assets on the client, the appended "Found in: …" sentence shows on a Pokédex page, long texts wrap or scroll inside the description box, and other languages are unaffected.
  3. Spot-check a few guide claims in a test world, e.g. Bulbasaur in jungle only, Nidoran absent (savanna is remapped to desert), Aron absent (it needs iron ore nearby), a Water Stone from a Gimmi Tower chest.