- Button Isle is peaceful: wild Pokémon only fight a player who hit them first (tuning/server.json peaceful_zones); its apricorns and coal make Poké Balls (4 apricorns + coal or charcoal), and the world report checks it has enough. - Quest book: no boilerplate; each zone page says what is particular to it, and every zone that needs gear or a field move to be safe has its own quest. New page on the bigger mods (Cold Sweat, Fight or Flight, Cobblebase, breeding, veins, shared loot, maps and info). - The Mire's poison stops 10 blocks below the surface. - Player battles never cost a Pokémon (CobbleHardcoreMon config, mixins, and the companion mod's own permadeath). - tools/item_audit.py: every item with a use has a source on the island; new sources for the gaps it found (species additions, three recipes). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
3.8 KiB
Python
Executable File
65 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Every item in the pack that has a use can be had on the island (Adrian, 2026-11-10).
|
|
|
|
Reads the field guide (build/field-guide/fieldguide.json; run tools/fieldguide/build.py first), which works out what
|
|
the island can provide from the pack's data: worldgen, loot, recipes, Pokémon drops, and what Minecraft and the
|
|
pack's own rules give in code (tools/fieldguide/manual_sources.json). Every item still without a source must be listed
|
|
in NO_USE below, with the reason it needs none; anything else fails.
|
|
|
|
Usage: tools/item_audit.py
|
|
"""
|
|
import fnmatch
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
GUIDE = ROOT / "build/field-guide/fieldguide.json"
|
|
|
|
# Items that may stay without a source, and why (fnmatch patterns).
|
|
NO_USE = {
|
|
"cobblemon_hms:hm_*": "left over from Cobblemon HMs before 4.0: the items do nothing now (the HM Case has a source)",
|
|
"lootr:*": "Lootr's own containers: structures place them, nobody uses them as items",
|
|
"regenerating_ore_veins:regenerator_block": "the block a mined vein turns into; it can't be broken",
|
|
"cold_sweat:chameleon_spawn_egg": "a creative-mode spawn egg",
|
|
"minecraft:infested_*": "silverfish blocks; the island has no silverfish",
|
|
"minecraft:crimson_*": "Nether wood for decoration; the island has no Nether",
|
|
"cobblemon:*tumblestone_cluster": "tumblestone itself comes from the ruins; clusters are decoration",
|
|
"cobblemon:*_budding_*tumblestone": "tumblestone itself comes from the ruins; buds are decoration",
|
|
"cobblemon:damaged_monitor": "a decoration block in Cobblemon's ruins",
|
|
"cobblemon:gimmighoul_chest": "the chest Gimmighoul hides in",
|
|
"cobblemon:lectern": "Cobblemon's decorative lectern, with no recipe in Cobblemon",
|
|
"cobblemon:bugwort": "a decoration plant with no recipe, seasoning or other use in Cobblemon",
|
|
"cobblemon:poke_puff": "Cobblemon 1.8.4 has no way to make Poké Puffs yet",
|
|
"cobblemon:shalour_sable": "Cobblemon 1.8.4 has no way to make it yet",
|
|
"cobblemon:scroll_of_*": "they evolve Kubfu, which Cobblemon 1.8.4 doesn't have",
|
|
"cobblemon:saccharine_log_slathered": "only gives planks and charcoal, which other logs give too",
|
|
"cobblemon:nether_fire_stone_ore": "an ore the island's veins don't use; Fire Stones come from Sunscorch's veins",
|
|
"cobblemon:terracotta_sun_stone_ore": "an ore the island's veins don't use; Sun Stones come from the Highlands' veins",
|
|
"cobblemon:dusk_stone_ore": "an ore the island's veins don't use; Dusk Stones come from the Deep Dark's veins",
|
|
"cold_sweat:slush_bucket": "slush is a cold fuel for the Hearth and Icebox; ice and snow do the same",
|
|
}
|
|
|
|
|
|
def main():
|
|
if not GUIDE.exists():
|
|
sys.exit(f"{GUIDE} is missing: run tools/fieldguide/build.py first")
|
|
guide = json.loads(GUIDE.read_text())
|
|
entries = {**guide["vanilla"], **guide["items"]}
|
|
missing = sorted(k for k, v in entries.items() if v.get("status") != "available" and not v.get("technical"))
|
|
unexplained = [k for k in missing if not any(fnmatch.fnmatch(k, pattern) for pattern in NO_USE)]
|
|
stale = [p for p in NO_USE if not any(fnmatch.fnmatch(k, p) for k in missing)]
|
|
print(f"{len(entries)} items, {len(missing)} without a source on the island, {len(missing) - len(unexplained)} of them with no use")
|
|
for pattern in stale:
|
|
print(f" note: nothing matches NO_USE {pattern!r} any more; remove it")
|
|
if unexplained:
|
|
for k in unexplained:
|
|
uses = ", ".join(u.get("text", "") for u in entries[k].get("uses", [])[:3]) or "no recipe uses"
|
|
print(f" - {k}: {entries[k].get('reason', '')} (uses: {uses})")
|
|
sys.exit("ITEM AUDIT FAILED: give these a source, or list them in NO_USE with the reason they need none")
|
|
print("ITEM AUDIT PASSED")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|