@jgengine/react 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -2
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/actionHud.d.ts +174 -0
- package/dist/actionHud.js +294 -0
- package/dist/bars.d.ts +103 -0
- package/dist/bars.js +180 -0
- package/dist/barsPreview.d.ts +4 -0
- package/dist/barsPreview.js +47 -0
- package/dist/cards.d.ts +59 -0
- package/dist/cards.js +116 -0
- package/dist/chat.d.ts +3 -1
- package/dist/chat.js +2 -2
- package/dist/components.d.ts +28 -1
- package/dist/components.js +36 -1
- package/dist/display.d.ts +1 -0
- package/dist/display.js +1 -0
- package/dist/engineStore.d.ts +3 -0
- package/dist/engineStore.js +3 -0
- package/dist/fogOverlay.d.ts +3 -0
- package/dist/fogOverlay.js +3 -0
- package/dist/gameViewport.js +16 -0
- package/dist/hooks.d.ts +40 -0
- package/dist/hooks.js +69 -1
- package/dist/hud.d.ts +104 -0
- package/dist/hud.js +155 -0
- package/dist/hudFrame.d.ts +47 -0
- package/dist/hudFrame.js +80 -0
- package/dist/hudLayout.d.ts +31 -2
- package/dist/hudLayout.js +127 -10
- package/dist/hudLayoutPersist.d.ts +23 -0
- package/dist/hudLayoutPersist.js +19 -0
- package/dist/hudTheme.d.ts +76 -0
- package/dist/hudTheme.js +156 -0
- package/dist/hudThemePreview.d.ts +4 -0
- package/dist/hudThemePreview.js +37 -0
- package/dist/iconTreatment.d.ts +50 -0
- package/dist/iconTreatment.js +84 -0
- package/dist/iconsPreview.d.ts +4 -0
- package/dist/iconsPreview.js +29 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +17 -0
- package/dist/keyHint.d.ts +30 -0
- package/dist/keyHint.js +31 -0
- package/dist/map.d.ts +141 -11
- package/dist/map.js +138 -16
- package/dist/save.d.ts +25 -0
- package/dist/save.js +37 -0
- package/dist/selectSnapshot.d.ts +2 -0
- package/dist/selectSnapshot.js +2 -0
- package/dist/selectionHud.d.ts +139 -0
- package/dist/selectionHud.js +188 -0
- package/dist/skillCheckPaint.d.ts +2 -0
- package/dist/skillCheckPaint.js +2 -0
- package/dist/slots.d.ts +44 -0
- package/dist/slots.js +37 -0
- package/dist/startScreen.d.ts +62 -0
- package/dist/startScreen.js +62 -0
- package/dist/store.d.ts +24 -0
- package/dist/store.js +9 -0
- package/package.json +4 -4
- package/skills/jgengine/SKILL.md +54 -0
- package/skills/jgengine/api.md +527 -0
- package/skills/jgengine/capabilities.md +131 -0
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-ui/SKILL.md +41 -0
- package/skills/jgengine-ui/api.md +2007 -0
- package/skills/jgengine-ui/capabilities.md +211 -0
- package/skills/jgengine-ui/recipes/portable-minimap.md +150 -0
- package/skills/jgengine-ui/reference.md +513 -0
- package/skills/jgengine-ui/references/visual-scorecard.md +73 -0
- package/llms.txt +0 -1724
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<!-- GENERATED by scripts/gen-capability-index.ts — do not edit. Regenerate: bun run gen:capabilities -->
|
|
2
|
+
|
|
3
|
+
# jgengine — capability index
|
|
4
|
+
|
|
5
|
+
Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
|
|
6
|
+
|
|
7
|
+
## authored-spawn — read spawn points and markers from the editor document
|
|
8
|
+
|
|
9
|
+
- `authoredSpawnPosition` (function) · `import { authoredSpawnPosition } from "@jgengine/shell/gameKit"`
|
|
10
|
+
|
|
11
|
+
## authored-triggers — schema'd on/action vocabulary on volumes and markers with runtime dispatch
|
|
12
|
+
|
|
13
|
+
- `collectAuthoredTriggers` (function) · `import { collectAuthoredTriggers } from "@jgengine/shell/gameKit"`
|
|
14
|
+
|
|
15
|
+
## collider-autofit — hitboxes and physical bodies fit each kind's rendered model bounds automatically — no hand-tuned sizes
|
|
16
|
+
|
|
17
|
+
- `GameContextModels` (interface) · `import { GameContextModels } from "@jgengine/core/runtime/gameContext"`
|
|
18
|
+
|
|
19
|
+
## define-game — single public game-authoring path — compose systems, world, presentation, and authored scene in one definition
|
|
20
|
+
|
|
21
|
+
- `defineGame` (function) · `import { defineGame } from "@jgengine/shell/gameKit"`
|
|
22
|
+
|
|
23
|
+
## define-system — composable game behavior — pure data + hooks the engine schedules; pass via `defineGame({ systems })`
|
|
24
|
+
|
|
25
|
+
- `defineSystem` (function) · `import { defineSystem } from "@jgengine/shell/gameKit"`
|
|
26
|
+
|
|
27
|
+
## editor-catalogs — Export typed gameplay catalogs for in-editor tuning.
|
|
28
|
+
|
|
29
|
+
- `EditorCatalogDefinition` (interface) · `import { EditorCatalogDefinition } from "@jgengine/shell/gameKit"`
|
|
30
|
+
|
|
31
|
+
## game-system — declare a composable capability with its own schedule and lifecycle
|
|
32
|
+
|
|
33
|
+
- `SystemDefinition` (interface) · `import { SystemDefinition } from "@jgengine/shell/gameKit"`
|
|
34
|
+
|
|
35
|
+
## headless-runner — play a real game loop with no renderer — tick, feed input, read the world snapshot
|
|
36
|
+
|
|
37
|
+
- `HeadlessRunner` (interface) · `import { HeadlessRunner } from "@jgengine/core/runtime/headlessRunner"`
|
|
38
|
+
|
|
39
|
+
## host-join-code-gate — membership-or-code gate for private hosted servers
|
|
40
|
+
|
|
41
|
+
- `canJoinPrivateServer` (function) · `import { canJoinPrivateServer } from "@jgengine/core/runtime/hostPolicy"`
|
|
42
|
+
|
|
43
|
+
## host-listing-filter — exclude private sessions from public browse results
|
|
44
|
+
|
|
45
|
+
- `isListablePublicly` (function) · `import { isListablePublicly } from "@jgengine/core/runtime/hostPolicy"`
|
|
46
|
+
|
|
47
|
+
## hud-canvas — the HUD root surface — design-resolution scaling plus live panel-placement editing (F2+C)
|
|
48
|
+
|
|
49
|
+
- `HudCanvas` (function) · `import { HudCanvas } from "@jgengine/shell/gameKit"`
|
|
50
|
+
|
|
51
|
+
## hud-clock — in-game time-of-day readout bound to the sim clock
|
|
52
|
+
|
|
53
|
+
- `Clock` (function) · `import { Clock } from "@jgengine/shell/gameKit"`
|
|
54
|
+
|
|
55
|
+
## hud-coins — currency counter widget bound to a currency id
|
|
56
|
+
|
|
57
|
+
- `Coins` (function) · `import { Coins } from "@jgengine/shell/gameKit"`
|
|
58
|
+
|
|
59
|
+
## hud-hotbar — optional inventory hotbar building block — games own slot chrome
|
|
60
|
+
|
|
61
|
+
- `Hotbar` (function) · `import { Hotbar } from "@jgengine/shell/gameKit"`
|
|
62
|
+
|
|
63
|
+
## hud-layout — persistent, live-editable HUD panel layout state for `HudCanvas`
|
|
64
|
+
|
|
65
|
+
- `useHudLayout` (function) · `import { useHudLayout } from "@jgengine/shell/gameKit"`
|
|
66
|
+
|
|
67
|
+
## hud-panel — anchored HUD slot — drop any widget in a named, player-movable panel
|
|
68
|
+
|
|
69
|
+
- `HudPanel` (function) · `import { HudPanel } from "@jgengine/shell/gameKit"`
|
|
70
|
+
|
|
71
|
+
## hud-stat-bar — optional stat-bound bar building block (health, mana, stamina) — prefer game-owned chrome
|
|
72
|
+
|
|
73
|
+
- `StatBar` (function) · `import { StatBar } from "@jgengine/shell/gameKit"`
|
|
74
|
+
|
|
75
|
+
## loot-table — validate a loot table definition for use with the registry
|
|
76
|
+
|
|
77
|
+
- `lootTable` (function) · `import { lootTable } from "@jgengine/core/authoring"`
|
|
78
|
+
|
|
79
|
+
## mount-game — mount a defined game in the browser — `<GameHost playable={game} editor={() => import("@jgengine/editor")} />`
|
|
80
|
+
|
|
81
|
+
- `GameHost` (function) · `import { GameHost } from "@jgengine/shell/gameKit"`
|
|
82
|
+
|
|
83
|
+
## multiplayer-offline — explicit solo adapter — omit `multiplayer` instead; offline is the shell default
|
|
84
|
+
|
|
85
|
+
- `offline` (function) · `import { offline } from "@jgengine/shell/gameKit"`
|
|
86
|
+
|
|
87
|
+
## multiplayer-p2p — serverless co-op over WebRTC — `multiplayer: p2p({ room })`
|
|
88
|
+
|
|
89
|
+
- `p2p` (function) · `import { p2p } from "@jgengine/core/runtime/adapter"`
|
|
90
|
+
|
|
91
|
+
## multiplayer-ws — server-hosted shared world over WebSocket — `multiplayer: ws({ authority: "server" })`
|
|
92
|
+
|
|
93
|
+
- `ws` (function) · `import { ws } from "@jgengine/core/runtime/adapter"`
|
|
94
|
+
|
|
95
|
+
## render-fallback-diagnostics — Enable/disable the dev-only placeholder-fallback probe.
|
|
96
|
+
|
|
97
|
+
- `armFallbackSeams` (function) · `import { armFallbackSeams } from "@jgengine/core/devtools/fallbackSeams"`
|
|
98
|
+
- `fallbackSeamsSnapshot` (function) · `import { fallbackSeamsSnapshot } from "@jgengine/core/devtools/fallbackSeams"`
|
|
99
|
+
- `reportFallbackSeam` (function) · `import { reportFallbackSeam } from "@jgengine/core/devtools/fallbackSeams"`
|
|
100
|
+
|
|
101
|
+
## runtime-save — save/load the whole game world through a pluggable backend, autosave or save points
|
|
102
|
+
|
|
103
|
+
- `createRuntimeSave` (function) · `import { createRuntimeSave } from "@jgengine/core/runtime/runtimeSave"`
|
|
104
|
+
|
|
105
|
+
## scene-ownership — audit a whole ownership manifest for boundary violations
|
|
106
|
+
|
|
107
|
+
- `auditManifest` (function) · `import { auditManifest } from "@jgengine/core/authoring"`
|
|
108
|
+
- `classifyOwnership` (function) · `import { classifyOwnership } from "@jgengine/core/authoring"`
|
|
109
|
+
- `collectOwnershipDiagnostics` (function) · `import { collectOwnershipDiagnostics } from "@jgengine/core/authoring"`
|
|
110
|
+
- `isSceneOwnershipManifest` (function) · `import { isSceneOwnershipManifest } from "@jgengine/core/authoring"`
|
|
111
|
+
- `ownershipKey` (function) · `import { ownershipKey } from "@jgengine/core/authoring"`
|
|
112
|
+
|
|
113
|
+
## seeded-random — injected deterministic randomness for game logic — never `Math.random` in a simulation
|
|
114
|
+
|
|
115
|
+
- `seededRng` (function) · `import { seededRng } from "@jgengine/shell/gameKit"`
|
|
116
|
+
|
|
117
|
+
## typed-keyed-store — a cast-free typed handle onto a per-owner keyed family of reactive game-store slots, replayable and host-authoritative
|
|
118
|
+
|
|
119
|
+
- `defineKeyedStore` (function) · `import { defineKeyedStore } from "@jgengine/shell/gameKit"`
|
|
120
|
+
|
|
121
|
+
## typed-store — a cast-free typed handle onto one reactive game-store slot, replayable and host-authoritative
|
|
122
|
+
|
|
123
|
+
- `defineStore` (function) · `import { defineStore } from "@jgengine/shell/gameKit"`
|
|
124
|
+
|
|
125
|
+
## world-convergence — derive environment coordinate content from the scene document
|
|
126
|
+
|
|
127
|
+
- `environmentContentFromDocument` (function) · `import { environmentContentFromDocument } from "@jgengine/shell/gameKit"`
|
|
128
|
+
|
|
129
|
+
## world-environment — compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
|
|
130
|
+
|
|
131
|
+
- `environment` (function) · `import { environment } from "@jgengine/shell/gameKit"`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Recipe — minimal game (scaffold → authored scene → win)
|
|
2
|
+
|
|
3
|
+
**What this wires:** the default end-to-end path from nothing to a complete, genre-free
|
|
4
|
+
walk/interact/win game: a scaffold, one `defineGame` config off the happy-path kit, an
|
|
5
|
+
authored scene edited in the browser, one system, one store slot, an empty-canvas HUD,
|
|
6
|
+
and a win condition. Every new game starts here; add combat, multiplayer, or deeper
|
|
7
|
+
world features only after this loop plays.
|
|
8
|
+
|
|
9
|
+
## 1. Scaffold
|
|
10
|
+
|
|
11
|
+
`npx jgengine create <name>` (inside the engine monorepo: `bun run new:game "<id-or-title>"`).
|
|
12
|
+
The file set is thin and already runs:
|
|
13
|
+
|
|
14
|
+
- `src/main.tsx` — mounts `GameHost` with `editor={() => import("@jgengine/editor")}`; the
|
|
15
|
+
host owns the F2+E / `?mode=editor` editor summon and the dev save endpoint.
|
|
16
|
+
- `src/game.config.ts` — the whole game definition (below).
|
|
17
|
+
- `src/editor.scene.json` + `src/editorLayers.ts` — the authored scene document, normalized
|
|
18
|
+
with `normalizeEditorLayers`. All placement lives here, never as coordinates in code.
|
|
19
|
+
- `src/loop.ts` and `src/game/ui/GameUI.tsx` — systems and HUD.
|
|
20
|
+
|
|
21
|
+
## 2. Define the game — one import surface
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// game.config.ts — everything below comes from the kit; deeper paths are for outgrowing it.
|
|
25
|
+
import { defineGame } from "@jgengine/shell/gameKit";
|
|
26
|
+
|
|
27
|
+
import { editorLayers } from "./editorLayers";
|
|
28
|
+
import { GameUI } from "./game/ui/GameUI";
|
|
29
|
+
import { onNewPlayer, systems } from "./loop";
|
|
30
|
+
|
|
31
|
+
export const game = defineGame({
|
|
32
|
+
name: "my-game",
|
|
33
|
+
// Binding movement actions makes the shell drive the walk controller — the game walks day one.
|
|
34
|
+
input: { moveForward: ["KeyW"], moveBack: ["KeyS"], moveLeft: ["KeyA"], moveRight: ["KeyD"], interact: ["KeyE"] },
|
|
35
|
+
systems,
|
|
36
|
+
loop: { onNewPlayer },
|
|
37
|
+
GameUI,
|
|
38
|
+
editorLayers, // the authored scene auto-mounts; the player spawns at its player_spawn marker
|
|
39
|
+
});
|
|
40
|
+
// Solo game: omit `multiplayer` entirely — offline is the shell default.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**World is optional and thin.** Omitting `world` is valid — a pure UI/rules game is not a
|
|
44
|
+
spatial place. When the game *is* a place, declare only substrate + laws with `world()` from
|
|
45
|
+
`@jgengine/core/world/place` (e.g. `{ id, ground: { mode: "flat", size: { x: Infinity, z: Infinity } }, physics: { gravity: -24 } }`,
|
|
46
|
+
or `mode: "board"` for 2D). Never seed, sky, or vegetation in `world` — the engine renders its
|
|
47
|
+
default sky until you author one in the editor, and foliage is editor scatter over the ground.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// loop.ts — one store slot for run state, one system for the rules tick.
|
|
52
|
+
import { defineStore, defineSystem, authoredSpawnPosition, type GameContext } from "@jgengine/shell/gameKit";
|
|
53
|
+
|
|
54
|
+
import { editorLayers } from "./editorLayers";
|
|
55
|
+
|
|
56
|
+
export const run = defineStore("run", { collected: 0, won: false });
|
|
57
|
+
|
|
58
|
+
export const systems = [
|
|
59
|
+
defineSystem({
|
|
60
|
+
id: "rules",
|
|
61
|
+
tick: { type: "fixed" },
|
|
62
|
+
update(ctx: GameContext) {
|
|
63
|
+
// System-check win alternative: read/update `run` here (e.g. win at collected >= 3).
|
|
64
|
+
if (run.read(ctx).collected >= 3) run.update(ctx, (s) => ({ ...s, won: true }));
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
export function onNewPlayer(ctx: GameContext): void {
|
|
70
|
+
ctx.scene.entity.spawn("player", { id: ctx.player.userId, position: authoredSpawnPosition(editorLayers) ?? [0, 0, 0] });
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`GameUI` starts as an empty `HudCanvas` (`useHudLayout` + `HudCanvas` from the kit). That is
|
|
75
|
+
intentional: **every game owns its UI**. Write a short UI art direction, then build custom
|
|
76
|
+
panels for this pitch — do not ship stock drop-in widgets (`StatBar`, `Hotbar`, `Coins`, glass
|
|
77
|
+
frames) as the product face. Reach for engine pieces only as headless data, layout, or
|
|
78
|
+
interaction models under game-owned chrome (see `jgengine-ui`).
|
|
79
|
+
|
|
80
|
+
## 3. Author, play, win
|
|
81
|
+
|
|
82
|
+
1. `bun dev`, then F2+E opens the editor on `editor.scene.json` — move the spawn, place
|
|
83
|
+
props and trigger markers, Ctrl+S saves back to the document.
|
|
84
|
+
2. The starter scene ships a goal marker with `{ on: "enter", action: "win" }` — walking
|
|
85
|
+
into it wins with zero game code. Author more rules the same way (triggers in the
|
|
86
|
+
editor), or read volumes yourself via the kit's `collectAuthoredTriggers(editorLayers)`.
|
|
87
|
+
3. Prove it: `bun test` asserts the document (spawn, goal), and `jgengine-verify` covers
|
|
88
|
+
screenshot and gameplay evidence before any "it works" claim.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jgengine-ui
|
|
3
|
+
description: Build composable, accessible HUDs, menus, feedback, and responsive presentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JGengine UI
|
|
7
|
+
|
|
8
|
+
## Ownership
|
|
9
|
+
|
|
10
|
+
This skill owns player-facing presentation: HUDs, menus, overlays, layout, responsive behavior, accessibility, touch/controller presentation, feedback, previews, and UI chrome. World rendering belongs to `jgengine-world`; state ownership stays in gameplay/combat.
|
|
11
|
+
|
|
12
|
+
Search [capabilities.md](capabilities.md), use [api.md](api.md) for signatures, and open [reference.md](reference.md) for component recipes. Visual polish uses [references/visual-scorecard.md](references/visual-scorecard.md).
|
|
13
|
+
|
|
14
|
+
## Canonical workflow
|
|
15
|
+
|
|
16
|
+
1. Write the game's UI art direction first (see [reference.md](reference.md) §1) — fantasy, shape/material language, hierarchy, forbidden patterns. Stock glass widgets are not a stand-in for this step.
|
|
17
|
+
2. Define the real UI states: attract/menu, live play, pause, results, empty/error, and relevant overlays.
|
|
18
|
+
3. Read state through selectors/hooks; keep simulation mutation behind commands.
|
|
19
|
+
4. Compose custom markup for this game. Prefer headless data + game-owned chrome. When a second presentation is plausible, split data / renderer / chrome (minimap stack example: `useLiveMarkers` → track/renderer → game frame; see reference §6).
|
|
20
|
+
5. Make keyboard, pointer, touch, controller, focus, and screen-reader behavior explicit.
|
|
21
|
+
6. Add preview fixtures using the real components for fast deterministic capture.
|
|
22
|
+
7. Verify desktop and mobile layouts through `jgengine-verify`. A HUD that could pass for another game's default chrome fails visual review.
|
|
23
|
+
|
|
24
|
+
Existing React games keep their entity store and use the focused
|
|
25
|
+
[portable minimap recipe](recipes/portable-minimap.md); no `GameProvider`,
|
|
26
|
+
`MarkerSet`, Three.js, or React Three Fiber adoption is required.
|
|
27
|
+
|
|
28
|
+
## Product rules
|
|
29
|
+
|
|
30
|
+
- **Every game owns its UI end-to-end.** Custom composition, skin, placement, terminology, motion, and one main menu. The website/runner is a bare loader.
|
|
31
|
+
- Engine packages do not supply a finished game face. Shared UI is headless or unskinned building blocks: layout (`HudCanvas`/`HudPanel`), data hooks, interaction models, tokens. Optional styled widgets exist for previews and scaffolding only — shipping them unskinned as the product is out of policy (see [AGENTS.md](../../../AGENTS.md)).
|
|
32
|
+
- Never reach for genre HUD kits, theme presets, or "default RPG/FPS chrome" as the game's identity. Build the look this pitch needs.
|
|
33
|
+
- Layout and skin remain caller-controlled; shared primitives own reusable behavior, not product look.
|
|
34
|
+
- SSR-visible output is hydration-stable; round computed SVG values at the boundary.
|
|
35
|
+
|
|
36
|
+
## Traps
|
|
37
|
+
|
|
38
|
+
- Do not put environment beautification, authored-scene rendering, or world placement here.
|
|
39
|
+
- Do not duplicate inventory, combat, quest, or selection state inside components.
|
|
40
|
+
- A static facsimile preview does not test the real UI; compose production components with fixtures.
|
|
41
|
+
- Visual quality is judged from rendered evidence, not component counts or prose.
|