Switch item definitions to a JSON-driven runtime registry

Replaces the build-time item.json/tools.item.py code generator with a
single item_t ITEM registry populated at runtime by parsing
assets/items.jsonc, so items/types can grow without a rebuild. Adds
itemGetDefById/itemGetTypeById/itemGetIdByName/itemTypeGetOrCreate,
updates inventory/backpack to size off the new *_DEF_COUNT_MAX caps
and look up types dynamically, and reorders engine init so rpgInit
(which loads items) runs before uiInit (which needs the item type
count to size the backpack's tabs).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-09-13 11:36:50 -05:00
co-authored by Claude Sonnet 5
parent 804f8aa1fa
commit 109ddc9e1e
15 changed files with 216 additions and 174 deletions
-114
View File
@@ -1,114 +0,0 @@
import argparse
import json
import os
parser = argparse.ArgumentParser(description="Item JSON to .h defines")
parser.add_argument("--json", required=True, help="Path to item JSON file")
parser.add_argument("--output", required=True, help="Path to output .h file")
args = parser.parse_args()
def type_enum(name):
return "ITEM_TYPE_" + name.upper()
def id_enum(name):
return "ITEM_ID_" + name.upper()
# Load JSON
item_ids = []
item_types = []
rows = {}
with open(args.json, encoding="utf-8") as f:
entries = json.load(f)
if not all(
"id" in row and "type" in row and "name" in row for row in entries
):
raise ValueError("Each item must have 'id', 'type', and 'name' fields")
for row in entries:
item_id, item_type = row["id"], row["type"]
if item_id not in item_ids:
item_ids.append(item_id)
if item_type not in item_types:
item_types.append(item_type)
rows[item_id] = row
# Assign enum values: types and IDs each start from 1 with NULL = 0.
type_values = {}
type_count = 1
for t in item_types:
type_values[t] = type_count
type_count += 1
id_values = {}
id_count = 1
for i in item_ids:
id_values[i] = id_count
id_count += 1
# Count items per type
type_item_counts = { t: 0 for t in item_types }
for i in item_ids:
type_item_counts[rows[i]["type"]] += 1
# Build output
out = [
"#pragma once",
'#include "dusk.h"',
"",
"typedef enum {",
" ITEM_TYPE_NULL = 0,",
]
for t in item_types:
out.append(f" {type_enum(t)} = {type_values[t]},")
out += [
f" ITEM_TYPE_COUNT = {type_count}",
"} itemtype_t;",
"",
"typedef enum {",
" ITEM_ID_NULL = 0,",
]
for i in item_ids:
out.append(f" {id_enum(i)} = {id_values[i]},")
out += [
f" ITEM_ID_COUNT = {id_count}",
"} itemid_t;",
"",
"typedef struct {",
" itemid_t id;",
" itemtype_t type;",
" const char_t *name;",
"} item_t;",
"",
"static const item_t ITEMS[] = {",
]
for i in item_ids:
row = rows[i]
out += [
f" [{id_enum(i)}] = {{",
f" .id = {id_enum(i)},",
f" .type = {type_enum(row['type'])},",
f" .name = \"item.{row['name']}.name\",",
" },",
]
out += [
"};",
"",
"static const uint8_t ITEM_TYPE_COUNTS[] = {",
]
for t in item_types:
out.append(f" [{type_enum(t)}] = {type_item_counts[t]},")
out += [
"};",
"",
]
max_type_count = max(type_item_counts.values()) if type_item_counts else 0
out += [
f"#define ITEM_TYPE_COUNT_MAX {max_type_count}",
"",
]
os.makedirs(os.path.dirname(args.output), exist_ok=True)
with open(args.output, "w", encoding="utf-8") as f:
f.write("\n".join(out))