Use CUTSCENE/INSERT item names as full asset paths directly

cutsceneCutsceneResolve/cutsceneInsertResolveAndSplice no longer inject
a "cutscenes/%s.jsonc" prefix/suffix around an item's "name" field -
matching cutsceneSystemLoad, which already takes a full path. Fixes a
latent double-prefix bug in initial.jsonc's CUTSCENE reference (also had
a "jsonsc" typo) that this change would otherwise have exposed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-09-19 21:38:09 -05:00
co-authored by Claude Sonnet 5
parent 5697f5c064
commit c1c8174b27
4 changed files with 27 additions and 36 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
"power": 12, "power": 12,
"mpCost": 4, "mpCost": 4,
"target": "SINGLE_ENEMY", "target": "SINGLE_ENEMY",
"cutscene": "battle/fire" "cutscene": "cutscenes/battle/fire.jsonc"
} }
} }
} }
+1 -1
View File
@@ -62,7 +62,7 @@
}, },
{ {
"type": "CUTSCENE", "type": "CUTSCENE",
"name": "main_menu" "name": "cutscenes/main_menu.jsonc"
} }
] ]
} }
+7 -13
View File
@@ -411,10 +411,7 @@ bool_t cutsceneCutsceneUpdate(
} }
cutscene_t * cutsceneCutsceneResolve(const char_t *name) { cutscene_t * cutsceneCutsceneResolve(const char_t *name) {
char_t path[ASSET_FILE_NAME_MAX]; assetentry_t *entry = assetLock(name, ASSET_LOADER_TYPE_JSON, NULL);
stringFormat(path, sizeof(path), "cutscenes/%s.jsonc", name);
assetentry_t *entry = assetLock(path, ASSET_LOADER_TYPE_JSON, NULL);
errorret_t result = assetRequireLoaded(entry); errorret_t result = assetRequireLoaded(entry);
if(errorIsNotOk(result)) { if(errorIsNotOk(result)) {
assetUnlockEntry(entry); assetUnlockEntry(entry);
@@ -459,11 +456,11 @@ errorret_t cutsceneCutsceneRefLoad(
errorThrow("Cutscene item (%s): missing 'name'", itemTypeLabel); errorThrow("Cutscene item (%s): missing 'name'", itemTypeLabel);
} }
// Only validate that the eventual "cutscenes/<name>.jsonc" path would // Only validate that name itself would fit - the reference itself is
// fit - the reference itself is not resolved/locked until this item // not resolved/locked until this item actually runs (see
// actually runs (see cutsceneCutsceneStart/cutsceneCutsceneResolve). // cutsceneCutsceneStart/cutsceneCutsceneResolve).
int32_t pathLen = stringFormat(NULL, 0, "cutscenes/%s.jsonc", name); int32_t nameLen = stringFormat(NULL, 0, "%s", name);
if(pathLen < 0 || (size_t)pathLen >= ASSET_FILE_NAME_MAX) { if(nameLen < 0 || (size_t)nameLen >= CUTSCENE_CUTSCENE_REF_NAME_MAX) {
errorThrow("Cutscene item (%s): 'name' too long", itemTypeLabel); errorThrow("Cutscene item (%s): 'name' too long", itemTypeLabel);
} }
@@ -492,10 +489,7 @@ bool_t cutsceneInsertUpdate(
} }
void cutsceneInsertResolveAndSplice(const char_t *name) { void cutsceneInsertResolveAndSplice(const char_t *name) {
char_t path[ASSET_FILE_NAME_MAX]; assetentry_t *entry = assetLock(name, ASSET_LOADER_TYPE_JSON, NULL);
stringFormat(path, sizeof(path), "cutscenes/%s.jsonc", name);
assetentry_t *entry = assetLock(path, ASSET_LOADER_TYPE_JSON, NULL);
errorret_t result = assetRequireLoaded(entry); errorret_t result = assetRequireLoaded(entry);
if(errorIsNotOk(result)) { if(errorIsNotOk(result)) {
assetUnlockEntry(entry); assetUnlockEntry(entry);
+18 -21
View File
@@ -60,9 +60,8 @@
typedef struct cutscene_s cutscene_t; typedef struct cutscene_s cutscene_t;
// Max length of a CUTSCENE/INSERT item's "name" field - bounded by what // Max length of a CUTSCENE/INSERT item's "name" field - it's the full
// fits in the "cutscenes/<name>.jsonc" path built from it (see // asset path to load, so this is bounded by ASSET_FILE_NAME_MAX directly.
// cutsceneCutsceneRefLoad), so this is never reached in practice.
#define CUTSCENE_CUTSCENE_REF_NAME_MAX ASSET_FILE_NAME_MAX #define CUTSCENE_CUTSCENE_REF_NAME_MAX ASSET_FILE_NAME_MAX
// A CUTSCENE (or INSERT) item's target. A C-authored cutscene_t* set // A CUTSCENE (or INSERT) item's target. A C-authored cutscene_t* set
@@ -230,7 +229,7 @@ void cutsceneCutsceneStart(
/** /**
* Resolves a JSON-authored CUTSCENE item's referenced cutscene by name: * Resolves a JSON-authored CUTSCENE item's referenced cutscene by name:
* locks+loads assets/cutscenes/<name>.jsonc, parses it into * locks+loads name as a plain ASSET_LOADER_TYPE_JSON asset, parses it into
* CUTSCENE_SYSTEM.loadedItems/loadedScene, then unlocks the asset entry * CUTSCENE_SYSTEM.loadedItems/loadedScene, then unlocks the asset entry
* like any other asset - the parsed items don't reference the doc past * like any other asset - the parsed items don't reference the doc past
* that (see cutsceneInsertResolveAndSplice's matching comment for why). * that (see cutsceneInsertResolveAndSplice's matching comment for why).
@@ -240,8 +239,7 @@ void cutsceneCutsceneStart(
* error overlay (matching cutsceneSystemLoad's runtime-failure handling) * error overlay (matching cutsceneSystemLoad's runtime-failure handling)
* and returns NULL. * and returns NULL.
* *
* @param name Bare cutscene name (without "cutscenes/" prefix or * @param name Full asset path to the referenced cutscene's JSON file.
* ".jsonc" suffix).
* @return The resolved cutscene, or NULL on failure. * @return The resolved cutscene, or NULL on failure.
*/ */
cutscene_t * cutsceneCutsceneResolve(const char_t *name); cutscene_t * cutsceneCutsceneResolve(const char_t *name);
@@ -265,10 +263,9 @@ bool_t cutsceneCutsceneUpdate(
* (rather than its own file) since it's tightly bound to the asset/loader * (rather than its own file) since it's tightly bound to the asset/loader
* system itself. Only stores the 'name' string (which points into the * system itself. Only stores the 'name' string (which points into the
* cutscene asset's still-alive yyjson doc, so no copy is needed) - * cutscene asset's still-alive yyjson doc, so no copy is needed) -
* resolving it to the referenced assets/cutscenes/<name>.jsonc asset is * resolving it to the referenced asset is deferred to cutsceneCutsceneStart,
* deferred to cutsceneCutsceneStart, the first time this item actually * the first time this item actually runs, so a cutscene referencing many
* runs, so a cutscene referencing many others doesn't pay to load every * others doesn't pay to load every one of them up front.
* one of them up front.
* *
* @param itemObj The item's JSON object. * @param itemObj The item's JSON object.
* @param item Destination item, already zeroed by the caller. * @param item Destination item, already zeroed by the caller.
@@ -281,9 +278,10 @@ errorret_t cutsceneCutsceneLoad(
/** /**
* Shared JSON parsing body for both CUTSCENE and INSERT items - both need * Shared JSON parsing body for both CUTSCENE and INSERT items - both need
* exactly a 'name' string field, validated to fit the eventual * exactly a 'name' string field, the full asset path to the referenced
* "cutscenes/<name>.jsonc" asset path. Only stores the name (see * cutscene's JSON file, validated to fit CUTSCENE_CUTSCENE_REF_NAME_MAX.
* cutsceneCutsceneLoad for why resolving is deferred). * Only stores the name (see cutsceneCutsceneLoad for why resolving is
* deferred).
* *
* @param itemObj The item's JSON object. * @param itemObj The item's JSON object.
* @param outRef Destination ref, already zeroed by the caller. * @param outRef Destination ref, already zeroed by the caller.
@@ -318,19 +316,18 @@ void cutsceneInsertStart(
/** /**
* Resolves a JSON-authored INSERT item's referenced cutscene by name and * Resolves a JSON-authored INSERT item's referenced cutscene by name and
* splices it into the running cutscene (CUTSCENE_SYSTEM.scene): locks+ * splices it into the running cutscene (CUTSCENE_SYSTEM.scene): locks+
* loads assets/cutscenes/<name>.jsonc as a plain ASSET_LOADER_TYPE_JSON * loads name as a plain ASSET_LOADER_TYPE_JSON asset, parses it into a
* asset, parses it into a small scratch buffer local to this call * small scratch buffer local to this call (capacity
* (capacity CUTSCENE_INSERT_ITEMS_MAX) straight out of the asset entry's * CUTSCENE_INSERT_ITEMS_MAX) straight out of the asset entry's own doc,
* own doc, then unlocks the entry like any other asset - nothing needs * then unlocks the entry like any other asset - nothing needs to keep the
* to keep the doc itself resident past the parse: every cutscene item * doc itself resident past the parse: every cutscene item field that could
* field that could reference it owns its string data by value (see * reference it owns its string data by value (see
* cutscenecutsceneref_t/cutscenemarker_t's doc comments), and * cutscenecutsceneref_t/cutscenemarker_t's doc comments), and
* cutsceneSystemInsertCutscene copies the scratch items into the running * cutsceneSystemInsertCutscene copies the scratch items into the running
* scene's own array right after. On failure, opens the fatal error * scene's own array right after. On failure, opens the fatal error
* overlay, matching cutsceneCutsceneResolve. * overlay, matching cutsceneCutsceneResolve.
* *
* @param name Bare cutscene name (without "cutscenes/" prefix or * @param name Full asset path to the referenced cutscene's JSON file.
* ".jsonc" suffix).
*/ */
void cutsceneInsertResolveAndSplice(const char_t *name); void cutsceneInsertResolveAndSplice(const char_t *name);