Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
354 changes: 283 additions & 71 deletions GDD.md

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions TextAssets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Text Assets

## V1 decision

We start with a minimal text asset system for scene and object descriptions.

Text assets are stored separately from scene and prefab JSON files:

- `public/text/scenes/<scene-id>.json`
- `public/text/objects/<object-id>.json`

Since scene/object IDs according to GDD can contain paths like "building\room", which means that the 'room.json scene' is located in the 'building' folder, there may be subfolders inside these folders.

## Main rules

- Scene text asset is created automatically when a scene is created or first saved, if it does not exist yet.
- Object text asset is stored independently from scenes and prefabs, because objects may exist outside a scene or move between scenes.
- Missing text asset files are not errors; runtime falls back to existing built-in fields.
- Text assets contain only data, not code.
- Dynamic text changes are controlled by scripts through runtime properties of scenes and objects.

## Minimal fields

Scene asset:

- `title`
- `description`

Object asset:

- `title`
- `description`

## Custom text variants

Text assets may also contain custom named fields in the same JSON file, for example:

- `description_morning`
- `description_evening`
- `title_locked`

These are alternative text values that can be activated at runtime.

## Runtime redirection

The redirection table does not live inside text asset JSON files.

Instead, each scene and object may have a runtime property such as `textRedirects` that remaps standard text fields to custom fields from the same text asset.

Example:

```json
{
"description": "description_evening"
}
```

Meaning:

- when runtime asks for `description`, it should use `description_evening` from the text asset;
- if no redirect is set, the default `description` field is used;
- if redirect points to a missing field, runtime should fall back to the standard field.

Scripts do not generate text themselves. They only change which named text field is currently active.

## Runtime integration

- `title` maps to the user-facing object or scene name.
- `description` maps to the basic text used by parser/runtime for `look` or `look around`.
- Existing runtime fields remain as fallback and for backward compatibility.
- Parser and UI should read only the resolved standard fields, not custom variant names directly.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@
"prettier --write",
"eslint --max-warnings=0 --fix"
],
"*.{json,md,css,scss}": "prettier --write"
"*.{json,css,scss}": "prettier --write"
}
}
94 changes: 76 additions & 18 deletions public/scenes/home/room.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"id": "home\\room",
"name": "Test Room",
"description": "You are in Test Room.",
"textRedirects": {},
"filename": "home/room",
"walkbox": [
{
Expand All @@ -10,6 +12,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
Expand Down Expand Up @@ -41,6 +44,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
Expand Down Expand Up @@ -106,6 +110,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand Down Expand Up @@ -159,6 +164,7 @@
"disabled": true,
"groupID": "#D ",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand All @@ -171,7 +177,7 @@
"sound2": "drawer_close.wav"
}
],
"layer": 0,
"layer": 1,
"visible": true,
"poly": [
{
Expand Down Expand Up @@ -200,6 +206,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
Expand All @@ -214,6 +221,7 @@
"disabled": true,
"groupID": "#D ",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand All @@ -226,7 +234,7 @@
"sound2": "drawer_close.wav"
}
],
"layer": 0,
"layer": 1,
"visible": true,
"poly": [
{
Expand Down Expand Up @@ -264,6 +272,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": -2,
Expand Down Expand Up @@ -294,6 +303,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": -1,
Expand Down Expand Up @@ -324,6 +334,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
Expand Down Expand Up @@ -354,31 +365,32 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
"visible": true,
"x": 249.76314957424822,
"y": 295.45481146309464,
"width": 119.88,
"height": 289.34,
"baseWidth": 162,
"baseHeight": 391,
"x": 241.58710837405346,
"y": 236.58147331007746,
"width": 119.33276583023533,
"height": 278.4431202705491,
"baseWidth": 168,
"baseHeight": 392,
"colliderWidth": 88,
"colliderHeight": 4,
"spriteName": "miles_ds-idle-down.json",
"spriteName": "miles_ds-idle-up.json",
"color": "#00ffff",
"scale": 0.74,
"scale": 0.7103140823228293,
"modelScale": 0.74,
"parallax": 1.0715390924595392,
"parallax": 1.033097301991213,
"ignoreScaling": false,
"animationSpeed": 30,
"opacity": 1,
"blendMode": "source-over",
"blur": 0,
"isPlayer": true,
"speed": 0.24,
"direction": "down",
"direction": "up",
"animSets": {
"idle": {
"id": "idle",
Expand All @@ -403,6 +415,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
Expand Down Expand Up @@ -433,9 +446,10 @@
"disabled": true,
"groupID": "#D",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 3,
"layer": 0,
"visible": true,
"x": 135,
"y": 310,
Expand Down Expand Up @@ -463,8 +477,14 @@
"disabled": true,
"groupID": "#D2",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"components": [
{
"type": "Subtrigger",
"target": "sub_sw_d2"
}
],
"layer": 4,
"visible": true,
"x": 134,
Expand Down Expand Up @@ -493,9 +513,10 @@
"disabled": true,
"groupID": "#D1",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 5,
"layer": 4,
"visible": true,
"x": 136,
"y": -4,
Expand Down Expand Up @@ -523,6 +544,7 @@
"disabled": true,
"groupID": "#D1",
"customName": "your ID card",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand Down Expand Up @@ -558,6 +580,7 @@
"disabled": true,
"groupID": "#D1",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 5,
Expand Down Expand Up @@ -588,6 +611,7 @@
"disabled": true,
"groupID": "#D",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 6,
Expand Down Expand Up @@ -618,6 +642,7 @@
"disabled": true,
"groupID": "#D1",
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand Down Expand Up @@ -653,6 +678,7 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [
{
Expand Down Expand Up @@ -706,12 +732,13 @@
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
"visible": true,
"x": 222.90433731748038,
"y": 306.92845155295413,
"x": 222.90433731748033,
"y": 306.928451552954,
"width": 1008.8000000000001,
"height": 90.39999999999999,
"baseWidth": 1261,
Expand All @@ -722,7 +749,7 @@
"color": "#36d87fff",
"scale": 0.8,
"modelScale": 0.8,
"parallax": 1.079038203629382,
"parallax": 1.0790382036293817,
"ignoreScaling": false,
"animationSpeed": 150,
"opacity": 1,
Expand All @@ -732,6 +759,37 @@
"speed": 0.1,
"direction": "down",
"animSets": {}
},
{
"name": "boombox",
"type": "Entity",
"locked": false,
"disabled": false,
"groupID": null,
"customName": "",
"textRedirects": {},
"interactions": {},
"components": [],
"layer": 0,
"visible": true,
"x": -152,
"y": -11,
"width": 112,
"height": 47,
"baseWidth": 123.07692307692307,
"baseHeight": 51.64835164835165,
"colliderWidth": 0,
"colliderHeight": 0,
"spriteName": null,
"color": "#AAAAAA",
"scale": 0.91,
"modelScale": 1,
"parallax": 1,
"ignoreScaling": false,
"animationSpeed": 150,
"opacity": 0,
"blendMode": "source-over",
"blur": 0
}
],
"camera": {
Expand Down
Loading