#!/usr/bin/env python3 """Generate a MediaWiki Items page from the authoritative item registry. Source = items_registry.json, built from CheatItemDefinitionsData.Items (List). An entry exists iff the game defines it as a carriable item (it has an ItemDefinition / StorageStack). Damage-type name variants (_Ranged/_Melee) and world objects are NOT in this list, by design. """ import json, os EX = '/home/downloadpizza/sand_tools/extracted' WIKI = '/home/downloadpizza/sand_tools/wiki' OUT = os.path.join(WIKI, 'Items.mediawiki') reg = json.load(open(os.path.join(EX, 'items_registry.json')))['items'] CAT_LABEL = { 'WEAPON': 'Weapon', 'AMMO': 'Ammo', 'TURRET_AMMO': 'Turret Ammo', 'RESOURCE_T1': 'Resource (T1)', 'RESOURCE_T2': 'Resource (T2)', 'RESOURCE_T3': 'Resource (T3)', 'ARMOR': 'Armor', 'BACKPACK': 'Backpack', 'ENERGY': 'Energy', 'FOOD': 'Food', 'MONEY': 'Money', 'KEY': 'Key', 'SMALL_VALUABLE': 'Small Valuable', 'LARGE_VALUABLE': 'Large Valuable', 'RAID_EXPLOSIVES': 'Raid Explosive', 'WEAPON_BELT': 'Weapon Belt', 'UTILITY_CONSUMABLE': 'Utility Consumable', 'ATTACK_CONSUMABLE': 'Attack Consumable', } def esc(s): return (s or '').replace('\n', ' ').replace('|', '|').strip() def stack(n): return '—' if n >= 100000 else str(n) # 100000/1000000 = effectively unlimited def main(): out = [] out.append("Complete list of carriable '''items''' in '''SAND''' — everything the game defines as an " "actual inventory item (i.e. it has an item definition). Names and descriptions are the " "in-game English text.") out.append('') out.append(f"{len(reg)} items. The table is sortable — click a header to group by category. " "(Damage-type name variants and world objects are intentionally excluded; this is the " "real pickup-able item set.)") out.append('') out.append('__TOC__') out.append('') out.append('== Items ==') out.append('{| class="wikitable sortable"') out.append('! Category !! Name !! Item ID !! data-sort-type="number" | Stack !! Short description') rows = sorted(reg.items(), key=lambda kv: (kv[1]['type'], kv[1]['name'].lower())) for iid, info in rows: cat = CAT_LABEL.get(info['type'], info['type'].title()) out.append('|-') out.append(f"| {cat} || [[{info['name']}]] || {iid} " f"|| {stack(info['storageStack'])} || {esc(info['shortDescription'])}") out.append('|}') out.append('') out.append('== Notes ==') out.append('* The item set comes from the game\'s item-definition registry ' '(CheatItemDefinitionsData.Items): an entry is included only if the game ' 'defines it as a carriable item. This deliberately excludes damage-type name variants ' '(_Ranged/_Melee) and world objects, which merely have ' 'display names but are not inventory items.') out.append('* "Stack" is the item\'s storage stack limit; "—" means effectively unlimited.') out.append('* Full long-form descriptions exist for most items and can be added per page.') out.append('') out.append('[[Category:Items]]') text = '\n'.join(out) os.makedirs(WIKI, exist_ok=True) open(OUT, 'w').write(text) from collections import Counter c = Counter(CAT_LABEL.get(v['type'], v['type']) for v in reg.values()) print(f"wrote {OUT} ({len(text)} chars, {len(reg)} items)") for k, v in c.most_common(): print(f" {v:3d} {k}") if __name__ == '__main__': main()