@downdraft/cli 0.0.0 → 0.1.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/README.md +11 -0
- package/package.json +36 -3
- package/scripts/package-mobile.mjs +779 -0
- package/scripts/package-native.mjs +616 -0
- package/src/args.ts +333 -0
- package/src/assets.ts +523 -0
- package/src/blob-store-s3.ts +145 -0
- package/src/build-games.ts +45 -0
- package/src/build.ts +40 -0
- package/src/bun-env.d.ts +6 -0
- package/src/debug.ts +56 -0
- package/src/dev.ts +231 -0
- package/src/dist.ts +36 -0
- package/src/export.ts +38 -0
- package/src/index.ts +131 -0
- package/src/list-games.ts +37 -0
- package/src/mcp.ts +320 -0
- package/src/new.ts +63 -0
- package/src/paths.ts +101 -0
- package/src/plugin-command.ts +214 -0
- package/src/process-utils.ts +179 -0
- package/src/release.ts +374 -0
- package/src/scaffold-plugin.ts +280 -0
- package/src/scaffold.ts +207 -0
- package/src/test.ts +187 -0
- package/src/usage.ts +255 -0
- package/templates/_shared/ai-companion/devin-config.eta +11 -0
- package/templates/_shared/ai-companion/engine-prompt.eta +155 -0
- package/templates/_shared/ai-companion/logging-rule.eta +3 -0
- package/templates/_shared/ai-companion/loops-rule.eta +3 -0
- package/templates/_shared/partials/config-json-fields.eta +3 -0
- package/templates/_shared/partials/dev-deps.eta +8 -0
- package/templates/_shared/partials/package-json-fields.eta +12 -0
- package/templates/_shared/partials/tsconfig.eta +16 -0
- package/templates/_shared/partials/vscode-extensions.eta +11 -0
- package/templates/_shared/partials/vscode-settings.eta +29 -0
- package/templates/_shared/partials/vscode-tasks.eta +93 -0
- package/templates/full/.gitignore.eta +5 -0
- package/templates/full/.vscode/extensions.json.eta +1 -0
- package/templates/full/.vscode/settings.json.eta +1 -0
- package/templates/full/.vscode/tasks.json.eta +1 -0
- package/templates/full/README.md.eta +45 -0
- package/templates/full/assets/shaders/.eta +0 -0
- package/templates/full/downdraft.config.json.eta +10 -0
- package/templates/full/package.json.eta +9 -0
- package/templates/full/src/entities/.eta +0 -0
- package/templates/full/src/game-module.ts.eta +30 -0
- package/templates/full/src/native-entry.ts.eta +14 -0
- package/templates/full/src/sim-host.ts.eta +19 -0
- package/templates/full/src/sim-worker.ts.eta +99 -0
- package/templates/full/src/systems/.eta +0 -0
- package/templates/full/tsconfig.json.eta +1 -0
- package/templates/gamemodule/README.md.eta +32 -0
- package/templates/gamemodule/downdraft.config.json.eta +3 -0
- package/templates/gamemodule/package.json.eta +9 -0
- package/templates/gamemodule/src/game-module.ts.eta +63 -0
- package/templates/gamemodule/src/native-entry.ts.eta +14 -0
- package/templates/gamemodule/src/sim-host.ts.eta +25 -0
- package/templates/gamemodule/src/sim-worker.ts.eta +24 -0
- package/templates/gamemodule/tsconfig.json.eta +1 -0
- package/templates/minimal/.gitignore.eta +5 -0
- package/templates/minimal/.vscode/extensions.json.eta +1 -0
- package/templates/minimal/.vscode/settings.json.eta +1 -0
- package/templates/minimal/.vscode/tasks.json.eta +1 -0
- package/templates/minimal/README.md.eta +32 -0
- package/templates/minimal/downdraft.config.json.eta +3 -0
- package/templates/minimal/package.json.eta +9 -0
- package/templates/minimal/src/game-module.ts.eta +44 -0
- package/templates/minimal/src/native-entry.ts.eta +14 -0
- package/templates/minimal/tsconfig.json.eta +1 -0
- package/templates/physics/.gitignore.eta +5 -0
- package/templates/physics/.vscode/extensions.json.eta +1 -0
- package/templates/physics/.vscode/settings.json.eta +1 -0
- package/templates/physics/.vscode/tasks.json.eta +1 -0
- package/templates/physics/README.md.eta +36 -0
- package/templates/physics/downdraft.config.json.eta +6 -0
- package/templates/physics/package.json.eta +9 -0
- package/templates/physics/src/game-module.ts.eta +29 -0
- package/templates/physics/src/native-entry.ts.eta +14 -0
- package/templates/physics/src/sim-host.ts.eta +19 -0
- package/templates/physics/src/sim-worker.ts.eta +155 -0
- package/templates/physics/tsconfig.json.eta +1 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# DownDraft Engine — API Reference for AI Companions
|
|
2
|
+
|
|
3
|
+
## Architecture
|
|
4
|
+
|
|
5
|
+
DownDraft is a TypeScript-first game engine built on winit + wgpu (a single native process, hosted under Bun, Node, or Deno — Bun is the default) + WebGPU, with an MCP server enabling AI agents to design, build, debug, and manage games via natural language.
|
|
6
|
+
|
|
7
|
+
**Execution contexts:**
|
|
8
|
+
1. **Native host (main thread)** — Game module, renderer, render loop, engine orchestrator, MCP server, asset manager
|
|
9
|
+
2. **Sim worker** — ECS world, game systems, physics, AI, modules (SharedArrayBuffer channels for frame sync)
|
|
10
|
+
3. **DB worker** — Persistence layer with schema versioning
|
|
11
|
+
|
|
12
|
+
## ECS (Entity Component System)
|
|
13
|
+
|
|
14
|
+
- **Entity**: `{ index: u32, generation: u32 }` — generational indices prevent stale-handle corruption
|
|
15
|
+
- **Component**: Plain data class implementing `Component` interface, registered with `ComponentId`
|
|
16
|
+
- **Archetype**: Set of component types, SoA column storage for cache-friendly iteration
|
|
17
|
+
- **Query**: Declares read/write access to component types, returns matching archetypes
|
|
18
|
+
- **System**: Function `(query, resources, commands) => void`
|
|
19
|
+
- **Schedule**: Single-threaded by default, dependency-ordered. Multi-threading via module/SAB.
|
|
20
|
+
- **Events**: Double-buffered channels (written this tick, readable next tick)
|
|
21
|
+
- **Commands**: Deferred operations (spawn/despawn, add/remove component) applied at stage boundaries
|
|
22
|
+
|
|
23
|
+
### Hierarchy
|
|
24
|
+
- Parent/child tree stored in side table (not archetype columns) — avoids archetype moves on reparenting
|
|
25
|
+
- Dirty-flag propagation: parent Transform change marks children dirty (O(depth))
|
|
26
|
+
- Lazy world matrix: computed on read when dirty
|
|
27
|
+
|
|
28
|
+
### Change Detection
|
|
29
|
+
- Per-component `lastChanged` tick counter — O(1) check for consumers
|
|
30
|
+
- Cross-thread: `Atomics` on SAB headers for frame sync
|
|
31
|
+
|
|
32
|
+
## Core API
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { World, Camera, MeshBuilder, Component, system, createLogger } from "@downdraft/engine";
|
|
36
|
+
|
|
37
|
+
// Define components
|
|
38
|
+
const Health = Component.register<{ current: number; max: number }>("Health", { current: 100, max: 100 });
|
|
39
|
+
|
|
40
|
+
// Define a system
|
|
41
|
+
const damageSystem = system(
|
|
42
|
+
(w: World, dt: number) => {
|
|
43
|
+
const view = w.view([Health]);
|
|
44
|
+
for (const ent of view) {
|
|
45
|
+
const health = w.getComponent(ent, Health);
|
|
46
|
+
if (health && health.data.current <= 0) {
|
|
47
|
+
w.despawn(ent);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Setup
|
|
54
|
+
const world = new World();
|
|
55
|
+
const camera = new Camera();
|
|
56
|
+
camera.setAspect(16, 9);
|
|
57
|
+
world.setResource("camera", camera);
|
|
58
|
+
|
|
59
|
+
// Spawn entities
|
|
60
|
+
const entity = world.spawn();
|
|
61
|
+
world.addComponent(entity, Health.create({ current: 50, max: 100 }));
|
|
62
|
+
|
|
63
|
+
// Procedural meshes
|
|
64
|
+
const cube = MeshBuilder.cube(1);
|
|
65
|
+
const sphere = MeshBuilder.sphere(0.5, 16, 16);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Module System
|
|
69
|
+
|
|
70
|
+
Modules are loadable packages that register systems, components, resources, and assets.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { Module } from "@downdraft/engine";
|
|
74
|
+
|
|
75
|
+
const myModule: Module = {
|
|
76
|
+
name: "my-module",
|
|
77
|
+
register(ctx: ModuleContext) {
|
|
78
|
+
// Register components, systems, resources
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
world.registerModule(myModule);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Engine Libraries (`@downdraft/engine/libraries/*`)
|
|
86
|
+
- `@downdraft/engine/libraries/water` — Gerstner waves, refraction, reflection
|
|
87
|
+
- `@downdraft/engine/libraries/physics-rapier` — Rapier physics backend
|
|
88
|
+
- `@downdraft/engine/libraries/physics-native` — Pure-TS physics backend
|
|
89
|
+
- `@downdraft/engine/libraries/marching-cubes` — Volumetric deformable terrain
|
|
90
|
+
- `@downdraft/engine/libraries/surface-nets` — Surface nets mesh extraction
|
|
91
|
+
- `@downdraft/engine/libraries/models` — GLTF/GLB/PLY/3DS model loading
|
|
92
|
+
- `@downdraft/engine/libraries/audio-kira` — Kira audio backend
|
|
93
|
+
- `@downdraft/engine/libraries/entities` — Generic model renderer
|
|
94
|
+
- `@downdraft/engine/libraries/lighting` — Lighting system
|
|
95
|
+
- `@downdraft/engine/libraries/weather` — Weather simulation
|
|
96
|
+
- `@downdraft/engine/libraries/weatherfx` — Cloud particle effects
|
|
97
|
+
- `@downdraft/engine/libraries/navmesh` — Navigation meshes
|
|
98
|
+
- `@downdraft/engine/libraries/persistence` — Save system (OPFS, File, IndexedDB)
|
|
99
|
+
- `@downdraft/engine/libraries/networking` — Multiplayer networking
|
|
100
|
+
- `@downdraft/engine/libraries/gaussian-splats` — Gaussian splat rendering
|
|
101
|
+
- `@downdraft/engine/libraries/sand` — Falling-sand simulation
|
|
102
|
+
- `@downdraft/engine/libraries/stickman` — Stickman skeleton rendering
|
|
103
|
+
|
|
104
|
+
### Engine Modules (`@downdraft/engine/modules/*`)
|
|
105
|
+
- `@downdraft/engine/modules/devtools` — DevTools panel, scene inspector, GPU debugging
|
|
106
|
+
- `@downdraft/engine/modules/camera-controls` — Camera input handling
|
|
107
|
+
- `@downdraft/engine/modules/terrain` — Terrain composition (marching-cubes + LOD)
|
|
108
|
+
- `@downdraft/engine/modules/movement-3d` — 3D player movement
|
|
109
|
+
- `@downdraft/engine/modules/movement-2d` — 2D grid-based movement
|
|
110
|
+
- `@downdraft/engine/modules/sailing` — Sailing mechanics (wind, buoyancy, steering)
|
|
111
|
+
- `@downdraft/engine/modules/mcp` — MCP automation server
|
|
112
|
+
- `@downdraft/engine/modules/xr` — WebXR support
|
|
113
|
+
|
|
114
|
+
### Game Modules (to-the-ocean example: `@to-the-ocean/module-*`)
|
|
115
|
+
- `@to-the-ocean/module-crafting` — Crafting recipes and system
|
|
116
|
+
- `@to-the-ocean/module-inventory` — Inventory system
|
|
117
|
+
- `@to-the-ocean/module-wildlife` — Wildlife AI (fish, sharks, eels, etc.)
|
|
118
|
+
- `@to-the-ocean/module-buoyancy` — Water buoyancy physics
|
|
119
|
+
- `@to-the-ocean/module-collision` — Entity collision detection
|
|
120
|
+
|
|
121
|
+
### Game Libraries (to-the-ocean example: `@to-the-ocean/library-*`)
|
|
122
|
+
- `@to-the-ocean/library-items` — Item definitions and management
|
|
123
|
+
- `@to-the-ocean/library-fishing` — Fishing mechanics
|
|
124
|
+
- `@to-the-ocean/library-economy` — Market/trading system
|
|
125
|
+
- `@to-the-ocean/library-survival` — Survival stats (hunger, thirst, oxygen)
|
|
126
|
+
- `@to-the-ocean/library-boats` — Boat building and piloting
|
|
127
|
+
|
|
128
|
+
## Builder Modes
|
|
129
|
+
|
|
130
|
+
| Mode | Use case |
|
|
131
|
+
|---|---|
|
|
132
|
+
| **dev** | Full DevTools, hot-reload, telemetry. Fastest iteration. |
|
|
133
|
+
| **debug** | Local verification on the production native runtime. |
|
|
134
|
+
| **prod** | Optimized production build. No devtools/debug overhead. |
|
|
135
|
+
|
|
136
|
+
## CLI Commands
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
draft new [path] [options] Scaffold a new game project
|
|
140
|
+
draft dev [options] Start dev server with HMR
|
|
141
|
+
draft debug [options] Run engine in debug mode
|
|
142
|
+
draft release [options] Unified build + package + sign pipeline
|
|
143
|
+
(--stage=build|package|release, --target=win|linux|mac|all)
|
|
144
|
+
draft assets <cmd> Manage remote asset packs
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## MCP Tools (for AI agents)
|
|
148
|
+
|
|
149
|
+
The MCP server exposes tools for scene management, entity operations, component manipulation, material/shader editing, mesh import, animation, lighting, camera, physics, audio, scripting, asset management, debugging, checkpoints, and build/export.
|
|
150
|
+
|
|
151
|
+
## Conventions
|
|
152
|
+
|
|
153
|
+
- **Logging**: No manual `[module]` prefixes — automatic source attribution
|
|
154
|
+
- **Loops**: Prefer indexed `for` loops over `for..of`
|
|
155
|
+
- **Package manager**: Bun (workspace protocol for internal deps)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"version": "<%= it.version %>",<% if (it.description) { %>
|
|
2
|
+
"description": "<%= it.description %>",<% } %><% if (it.author) { %>
|
|
3
|
+
"author": { "name": "<%= it.author %>" },<% } %>
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "draft dev",
|
|
7
|
+
"build": "draft release --stage=build",
|
|
8
|
+
"release": "draft release",
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"lint": "oxlint",
|
|
11
|
+
"test": "npm test"
|
|
12
|
+
},
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
7
|
+
"types": ["@webgpu/types", "node", "vite/client"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"explorer.fileNesting.enabled": true,
|
|
3
|
+
"explorer.fileNesting.expand": false,
|
|
4
|
+
"explorer.fileNesting.patterns": {
|
|
5
|
+
"*.ts": "${capture}.js, ${capture}.spec.ts, ${capture}.*.spec.ts, ${capture}.test.ts",
|
|
6
|
+
"*.tsx": "${capture}.spec.ts, ${capture}.*.spec.ts, ${capture}.test.ts",
|
|
7
|
+
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.wasm, ${capture}.wasm.map",
|
|
8
|
+
"tsconfig.json": "tsconfig.*.json",
|
|
9
|
+
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lock"
|
|
10
|
+
},
|
|
11
|
+
"editor.codeActionsOnSave": {
|
|
12
|
+
"source.organizeImports": "explicit"
|
|
13
|
+
},
|
|
14
|
+
"files.associations": {
|
|
15
|
+
"*.wgsl": "wgsl"
|
|
16
|
+
},
|
|
17
|
+
"files.watcherExclude": {
|
|
18
|
+
"**/node_modules/**": true,
|
|
19
|
+
"**/dist/**": true,
|
|
20
|
+
"**/export/**": true,
|
|
21
|
+
"**/tmp/**": true
|
|
22
|
+
},
|
|
23
|
+
"search.exclude": {
|
|
24
|
+
"**/node_modules/**": true,
|
|
25
|
+
"**/dist/**": true,
|
|
26
|
+
"**/export/**": true,
|
|
27
|
+
"**/tmp/**": true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"label": "Dev",
|
|
6
|
+
"detail": "Start the game in dev mode with hot reload",
|
|
7
|
+
"type": "shell",
|
|
8
|
+
"command": "draft dev",
|
|
9
|
+
"options": {
|
|
10
|
+
"cwd": "${workspaceFolder}"
|
|
11
|
+
},
|
|
12
|
+
"isBackground": true,
|
|
13
|
+
"problemMatcher": [],
|
|
14
|
+
"group": {
|
|
15
|
+
"kind": "build",
|
|
16
|
+
"isDefault": true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"label": "Release",
|
|
21
|
+
"detail": "Build + package for a desktop target",
|
|
22
|
+
"type": "shell",
|
|
23
|
+
"command": "draft release --target=${input:releaseTarget} --mode=${input:buildMode}",
|
|
24
|
+
"options": {
|
|
25
|
+
"cwd": "${workspaceFolder}"
|
|
26
|
+
},
|
|
27
|
+
"presentation": {
|
|
28
|
+
"echo": true,
|
|
29
|
+
"reveal": "always",
|
|
30
|
+
"panel": "dedicated",
|
|
31
|
+
"clear": true,
|
|
32
|
+
"showReuseMessage": false
|
|
33
|
+
},
|
|
34
|
+
"problemMatcher": []
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"label": "Build Only",
|
|
38
|
+
"detail": "Bundle the game with Vite (no packaging)",
|
|
39
|
+
"type": "shell",
|
|
40
|
+
"command": "draft release --stage=build --mode=${input:buildMode}",
|
|
41
|
+
"options": {
|
|
42
|
+
"cwd": "${workspaceFolder}"
|
|
43
|
+
},
|
|
44
|
+
"problemMatcher": []
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"label": "Typecheck",
|
|
48
|
+
"detail": "Run tsc --noEmit",
|
|
49
|
+
"type": "shell",
|
|
50
|
+
"command": "npm run typecheck",
|
|
51
|
+
"options": {
|
|
52
|
+
"cwd": "${workspaceFolder}"
|
|
53
|
+
},
|
|
54
|
+
"problemMatcher": ["$tsc"]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"label": "Lint",
|
|
58
|
+
"detail": "Run oxlint",
|
|
59
|
+
"type": "shell",
|
|
60
|
+
"command": "npm run lint",
|
|
61
|
+
"options": {
|
|
62
|
+
"cwd": "${workspaceFolder}"
|
|
63
|
+
},
|
|
64
|
+
"problemMatcher": []
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"label": "Test",
|
|
68
|
+
"detail": "Run tests",
|
|
69
|
+
"type": "shell",
|
|
70
|
+
"command": "npm test",
|
|
71
|
+
"options": {
|
|
72
|
+
"cwd": "${workspaceFolder}"
|
|
73
|
+
},
|
|
74
|
+
"problemMatcher": []
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"inputs": [
|
|
78
|
+
{
|
|
79
|
+
"id": "releaseTarget",
|
|
80
|
+
"type": "pickString",
|
|
81
|
+
"options": ["all", "win", "linux", "mac"],
|
|
82
|
+
"default": "all",
|
|
83
|
+
"description": "Target platform(s)"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "buildMode",
|
|
87
|
+
"type": "pickString",
|
|
88
|
+
"options": ["prod", "dev", "debug"],
|
|
89
|
+
"default": "prod",
|
|
90
|
+
"description": "Build mode"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%~ include("_shared/partials/vscode-extensions", it) %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%~ include("_shared/partials/vscode-settings", it) %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%~ include("_shared/partials/vscode-tasks", it) %>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# <%= it.name %>
|
|
2
|
+
|
|
3
|
+
<% if (it.description) { %><%= it.description %><% } else { %>A full-featured game built with the DownDraft Engine.<% } %>
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
bun install
|
|
10
|
+
|
|
11
|
+
# Start dev server (includes DevTools panel)
|
|
12
|
+
npm run dev
|
|
13
|
+
|
|
14
|
+
# Build for production
|
|
15
|
+
npm run build
|
|
16
|
+
|
|
17
|
+
# Export for distribution
|
|
18
|
+
npm run export
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Project Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
src/ Game source code
|
|
25
|
+
native-entry.ts Native runtime entry (draft dev)
|
|
26
|
+
systems/ Game systems (ECS)
|
|
27
|
+
entities/ Entity definitions and prefabs
|
|
28
|
+
assets/ Game assets
|
|
29
|
+
shaders/ Custom WGSL shaders
|
|
30
|
+
models/ 3D models (GLTF, PLY, 3DS)
|
|
31
|
+
textures/ Textures (PNG, WebP, KTX2, DDS, HDR)
|
|
32
|
+
downdraft.config.json Engine configuration
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Plugins
|
|
36
|
+
|
|
37
|
+
- **@downdraft/engine/libraries/water** — Gerstner wave simulation, refraction, reflection
|
|
38
|
+
- **@downdraft/engine/libraries/physics-rapier** — Rapier physics backend
|
|
39
|
+
- **@downdraft/engine/libraries/marching-cubes** — Volumetric deformable terrain
|
|
40
|
+
- **@downdraft/engine/libraries/models** — Model loading (GLTF/GLB, PLY, 3DS)
|
|
41
|
+
- **@downdraft/engine/modules/devtools** — DevTools panel with scene inspector, GPU debugging
|
|
42
|
+
|
|
43
|
+
## Engine
|
|
44
|
+
|
|
45
|
+
Built with [DownDraft Engine](https://github.com/downdraft-engine) — a TypeScript-first game engine on WebGPU — native runtime (Bun + SDL + wgpu).
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { GameRenderer } from "@downdraft/engine";
|
|
2
|
+
import type { GameModule } from "@downdraft/engine/app/renderer";
|
|
3
|
+
import { SimHost } from "./sim-host";
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Full template — ECS sim worker + GameRenderer + engine libraries
|
|
7
|
+
//
|
|
8
|
+
// The sim runs in sim-worker.ts (a Web Worker): an ECS World with a rotation
|
|
9
|
+
// system. The SAME module drives both entry points:
|
|
10
|
+
// src/native-entry.ts — Bun + SDL + wgpu-native (draft dev, the default)
|
|
11
|
+
// Engine libraries can be declared via GameModule.libraries[] for automatic
|
|
12
|
+
// SAB allocation + DI wiring.
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export const gameModule: GameModule = {
|
|
16
|
+
// ── Renderer + Sim ──
|
|
17
|
+
renderer: (canvas) => new GameRenderer(canvas),
|
|
18
|
+
sim: () => new SimHost(),
|
|
19
|
+
simConfig: { seed: 12345 },
|
|
20
|
+
|
|
21
|
+
// ── Post-init wiring ──
|
|
22
|
+
onReady: (ctx) => {
|
|
23
|
+
console.log("[game] ready", { simSAB: ctx.simSAB, inputSAB: ctx.inputSAB });
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// ── Cleanup ──
|
|
27
|
+
onDispose: () => {
|
|
28
|
+
console.log("[game] disposed");
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { runNativeGameModule } from "@downdraft/platform-native";
|
|
2
|
+
import { gameModule } from "./game-module";
|
|
3
|
+
|
|
4
|
+
// Native entry — `draft dev`/`draft release` runtime (winit + wgpu under Bun, Node, or Deno).
|
|
5
|
+
// Saves, MCP, display info, and screenshots work through the in-process
|
|
6
|
+
// HostAPI bridge.
|
|
7
|
+
|
|
8
|
+
await runNativeGameModule(gameModule, {
|
|
9
|
+
title: "<%= it.name %> — Native",
|
|
10
|
+
appId: "downdraft-<%= it.name %>",
|
|
11
|
+
}).catch((e) => {
|
|
12
|
+
console.error("[native-entry] Fatal:", e);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SimWorkerHost } from "@downdraft/engine";
|
|
2
|
+
|
|
3
|
+
// Sim worker host — spawns sim-worker.ts on the main (renderer) thread and
|
|
4
|
+
// exposes the sim SAB + event stream to startGame().
|
|
5
|
+
export class SimHost extends SimWorkerHost {
|
|
6
|
+
constructor() {
|
|
7
|
+
// Replace with your game's sim-buffer allocation (see the SAB APIs in
|
|
8
|
+
// @downdraft/engine, e.g. defineRecordBuffer/allocateSimBuffer).
|
|
9
|
+
super(new SharedArrayBuffer(4096));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
protected createWorker(): Worker {
|
|
13
|
+
return new Worker(new URL("./sim-worker.ts", import.meta.url), { type: "module" });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
protected async onInit(): Promise<void> {
|
|
17
|
+
await this.getProxy()!.proxy.init(this.getSimBuffer());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
c,
|
|
3
|
+
Component,
|
|
4
|
+
createLogger,
|
|
5
|
+
createSimWorker,
|
|
6
|
+
Query,
|
|
7
|
+
q,
|
|
8
|
+
spawn,
|
|
9
|
+
Stage,
|
|
10
|
+
systemWithParams,
|
|
11
|
+
World,
|
|
12
|
+
} from "@downdraft/engine";
|
|
13
|
+
|
|
14
|
+
const log = createLogger();
|
|
15
|
+
|
|
16
|
+
// Full template sim worker — an ECS World with a rotation system.
|
|
17
|
+
// createSimWorker owns the tick loop, worker protocol, and stats;
|
|
18
|
+
// this file provides onInit + onTick.
|
|
19
|
+
|
|
20
|
+
// --- Components ---
|
|
21
|
+
|
|
22
|
+
type TransformData = {
|
|
23
|
+
position: [number, number, number];
|
|
24
|
+
rotation: [number, number, number];
|
|
25
|
+
scale: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const Transform = Component.register<TransformData>("Transform", {
|
|
29
|
+
position: [0, 0, 0],
|
|
30
|
+
rotation: [0, 0, 0],
|
|
31
|
+
scale: 1,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
type RenderableData = {
|
|
35
|
+
mesh: string;
|
|
36
|
+
color: [number, number, number];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const Renderable = Component.register<RenderableData>("Renderable", {
|
|
40
|
+
mesh: "cube",
|
|
41
|
+
color: [1, 1, 1],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// --- Queries ---
|
|
45
|
+
|
|
46
|
+
const rotateQuery = new Query([Transform.id, Renderable.id]);
|
|
47
|
+
|
|
48
|
+
let world: World;
|
|
49
|
+
|
|
50
|
+
createSimWorker({
|
|
51
|
+
fixedDt: 1 / 60,
|
|
52
|
+
|
|
53
|
+
onInit() {
|
|
54
|
+
world = new World();
|
|
55
|
+
|
|
56
|
+
// Spawn ground entity
|
|
57
|
+
spawn(world,
|
|
58
|
+
c(Transform, { position: [0, -0.5, 0], scale: 10 }),
|
|
59
|
+
c(Renderable, { mesh: "cube", color: [0.3, 0.5, 0.3] }),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Spawn rotating entities
|
|
63
|
+
for (let i = 0; i < 5; i++) {
|
|
64
|
+
spawn(world,
|
|
65
|
+
c(Transform, { position: [(i - 2) * 2, 0.5, 0] }),
|
|
66
|
+
c(Renderable, {
|
|
67
|
+
mesh: i % 2 === 0 ? "cube" : "sphere",
|
|
68
|
+
color: [Math.random(), Math.random(), Math.random()],
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Register system using systemWithParams for typed dependency injection
|
|
74
|
+
const rotateSystem = systemWithParams(
|
|
75
|
+
"rotate-entities",
|
|
76
|
+
Stage.Update,
|
|
77
|
+
[q(Transform, Renderable)],
|
|
78
|
+
(ctx, entities) => {
|
|
79
|
+
entities.iterate(ctx.tick, (_entity, comps) => {
|
|
80
|
+
const transform = comps[0] as TransformData;
|
|
81
|
+
const [rx, ry, rz] = transform.rotation;
|
|
82
|
+
transform.rotation = [rx, ry + ctx.dt * 0.5, rz];
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
world.schedule.addSystem(rotateSystem);
|
|
88
|
+
|
|
89
|
+
log.info("sim", "full demo initialized — 5 entities on a ground plane");
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
onTick(dt) {
|
|
93
|
+
world.step(dt);
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
onShutdown() {
|
|
97
|
+
log.info("sim", "sim worker shutdown");
|
|
98
|
+
},
|
|
99
|
+
});
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%~ include("_shared/partials/tsconfig", it) %>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# <%= it.name %>
|
|
2
|
+
|
|
3
|
+
<% if (it.description) { %><%= it.description %><% } else { %>A game built with the DownDraft Engine.<% } %>
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
bun install
|
|
10
|
+
|
|
11
|
+
# Start dev server
|
|
12
|
+
npm run dev
|
|
13
|
+
|
|
14
|
+
# Build for production
|
|
15
|
+
npm run build
|
|
16
|
+
|
|
17
|
+
# Export for distribution
|
|
18
|
+
npm run export
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Project Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
src/ Game source code
|
|
25
|
+
native-entry.ts Native runtime entry (draft dev)
|
|
26
|
+
assets/ Game assets (models, textures, shaders)
|
|
27
|
+
downdraft.config.json Engine configuration
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Engine
|
|
31
|
+
|
|
32
|
+
Built with [DownDraft Engine](https://github.com/downdraft-engine) — a TypeScript-first game engine on WebGPU — native runtime (Bun + SDL + wgpu).
|