@origingame/engine 0.0.0-stage → 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.
Files changed (158) hide show
  1. package/bin/og.mjs +25 -0
  2. package/dist/web/origin-engine.d.ts +1233 -0
  3. package/dist/web/origin-engine.js +8628 -0
  4. package/dist/web/origin-engine_bg.wasm +0 -0
  5. package/dist/web/origin-engine_bg.wasm.d.ts +366 -0
  6. package/dist/web-publish/origin-engine-lanes.js +8509 -0
  7. package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
  8. package/dist/web-publish/origin-engine.d.ts +1176 -0
  9. package/dist/web-publish/origin-engine.js +8313 -0
  10. package/dist/web-publish/origin-engine_bg.wasm +0 -0
  11. package/dist/web-publish/origin-engine_bg.wasm.d.ts +347 -0
  12. package/dist/web-publish/snippets/wasm-bindgen-rayon-38edf6e439f6d70d/src/workerHelpers.no-bundler.js +77 -0
  13. package/dist/web-publish-2d/origin-engine-lanes.js +8509 -0
  14. package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
  15. package/dist/web-publish-2d/origin-engine.d.ts +1176 -0
  16. package/dist/web-publish-2d/origin-engine.js +8313 -0
  17. package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
  18. package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +347 -0
  19. package/dist/web-publish-2d/snippets/wasm-bindgen-rayon-38edf6e439f6d70d/src/workerHelpers.no-bundler.js +77 -0
  20. package/knowledge/README.md +31 -0
  21. package/knowledge/knowledge.json +13 -0
  22. package/knowledge/looks/catalogue.json +1871 -0
  23. package/knowledge/package.json +33 -0
  24. package/knowledge/rules/platform.json +329 -0
  25. package/knowledge/scaffold/README.md +27 -0
  26. package/knowledge/scaffold/distribution.json +48 -0
  27. package/knowledge/scaffold/origin-engine.json +19 -0
  28. package/knowledge/scaffold/template/.origin/setup +14 -0
  29. package/knowledge/scaffold/template/LICENSES.md +23 -0
  30. package/knowledge/scaffold/template/README.md +37 -0
  31. package/knowledge/scaffold/template/assets/ai/guard.ogt +48 -0
  32. package/knowledge/scaffold/template/assets/audio/click.ogt +9 -0
  33. package/knowledge/scaffold/template/assets/fonts/NotoSansSC-Regular-subset.ttf.ogt +12 -0
  34. package/knowledge/scaffold/template/assets/fonts/OFL.txt +93 -0
  35. package/knowledge/scaffold/template/assets/looks/origin-game.ogt +12 -0
  36. package/knowledge/scaffold/template/assets/nav/yard.ogt +27 -0
  37. package/knowledge/scaffold/template/assets/scenes/main.ogt +34 -0
  38. package/knowledge/scaffold/template/assets/strings/en.ogt +14 -0
  39. package/knowledge/scaffold/template/assets/textures/stone_n.png.ogt +7 -0
  40. package/knowledge/scaffold/template/gitattributes +22 -0
  41. package/knowledge/scaffold/template/package.json +18 -0
  42. package/knowledge/scaffold/template/project.ogt +25 -0
  43. package/knowledge/scaffold/template/src/main.ts +246 -0
  44. package/knowledge/scaffold/template/tests/guard.og.ts +67 -0
  45. package/knowledge/scaffold/template/tests/smoke.og.ts +43 -0
  46. package/knowledge/scaffold/template/tsconfig.json +17 -0
  47. package/knowledge/scripts/lib.ts +203 -0
  48. package/knowledge/scripts/mount.ts +210 -0
  49. package/knowledge/scripts/pack.ts +24 -0
  50. package/knowledge/scripts/scaffold.ts +72 -0
  51. package/knowledge/scripts/validate.ts +749 -0
  52. package/knowledge/skills/og-ai/SKILL.md +386 -0
  53. package/knowledge/skills/og-audio/SKILL.md +191 -0
  54. package/knowledge/skills/og-build/SKILL.md +330 -0
  55. package/knowledge/skills/og-core/SKILL.md +285 -0
  56. package/knowledge/skills/og-feel/SKILL.md +385 -0
  57. package/knowledge/skills/og-game/SKILL.md +1479 -0
  58. package/knowledge/skills/og-i18n/SKILL.md +220 -0
  59. package/knowledge/skills/og-platform-sdk/SKILL.md +199 -0
  60. package/knowledge/skills/og-taste/SKILL.md +537 -0
  61. package/knowledge/skills/og-ui/SKILL.md +444 -0
  62. package/knowledge/wiki/ai.md +627 -0
  63. package/knowledge/wiki/anim.md +1187 -0
  64. package/knowledge/wiki/atmosphere.md +636 -0
  65. package/knowledge/wiki/audio.md +732 -0
  66. package/knowledge/wiki/camera.md +711 -0
  67. package/knowledge/wiki/commands.md +357 -0
  68. package/knowledge/wiki/game.md +220 -0
  69. package/knowledge/wiki/i18n.md +213 -0
  70. package/knowledge/wiki/index.md +1027 -0
  71. package/knowledge/wiki/input.md +1714 -0
  72. package/knowledge/wiki/load.md +1280 -0
  73. package/knowledge/wiki/math.md +166 -0
  74. package/knowledge/wiki/nav.md +1154 -0
  75. package/knowledge/wiki/physics.md +3142 -0
  76. package/knowledge/wiki/platform.md +857 -0
  77. package/knowledge/wiki/probe.md +1692 -0
  78. package/knowledge/wiki/reflect.md +285 -0
  79. package/knowledge/wiki/render.md +3511 -0
  80. package/knowledge/wiki/rng.md +393 -0
  81. package/knowledge/wiki/stream.md +376 -0
  82. package/knowledge/wiki/system.md +197 -0
  83. package/knowledge/wiki/systems.md +43 -0
  84. package/knowledge/wiki/terrain.md +727 -0
  85. package/knowledge/wiki/tilemap.md +422 -0
  86. package/knowledge/wiki/time.md +150 -0
  87. package/knowledge/wiki/transform.md +230 -0
  88. package/knowledge/wiki/tween.md +580 -0
  89. package/knowledge/wiki/ui.md +8000 -0
  90. package/knowledge/wiki/world.md +909 -0
  91. package/package.json +68 -4
  92. package/schema/api.schema.json +29675 -0
  93. package/shell/README.md +22 -0
  94. package/shell/brand/README.md +23 -0
  95. package/shell/brand/icon-192.png +0 -0
  96. package/shell/brand/icon-512.png +0 -0
  97. package/shell/brand/mark-on-paper.svg +6 -0
  98. package/shell/brand/origin-mark.svg +5 -0
  99. package/shell/brand/origin-motion.css +251 -0
  100. package/shell/brand/tokens.css +20 -0
  101. package/shell/brand.ts +132 -0
  102. package/shell/page.ts +715 -0
  103. package/shell/platform.ts +203 -0
  104. package/shell/player.ts +238 -0
  105. package/shell/shell.css +185 -0
  106. package/shell/sw.ts +177 -0
  107. package/shell/transport.ts +515 -0
  108. package/shell/wire.ts +369 -0
  109. package/src/e6.ts +69 -0
  110. package/src/env.d.ts +100 -0
  111. package/src/generated/abi.ts +980 -0
  112. package/src/index.ts +193 -0
  113. package/src/node/audio.ts +86 -0
  114. package/src/node/build.ts +109 -0
  115. package/src/node/device.ts +981 -0
  116. package/src/node/doctor.ts +60 -0
  117. package/src/node/index.ts +102 -0
  118. package/src/node/platform.ts +24 -0
  119. package/src/node/playtest-run.ts +249 -0
  120. package/src/node/png.ts +130 -0
  121. package/src/node/polish.ts +976 -0
  122. package/src/node/run.ts +373 -0
  123. package/src/node/web-build.ts +808 -0
  124. package/src/p2.ts +35 -0
  125. package/src/platform-local.ts +211 -0
  126. package/src/playtest.ts +131 -0
  127. package/src/runtime.ts +1509 -0
  128. package/src/systems/cameras.ts +247 -0
  129. package/src/ui-kit/bind.ts +141 -0
  130. package/src/ui-kit/huds.ts +303 -0
  131. package/src/ui-kit/index.ts +36 -0
  132. package/src/ui-kit/menus.ts +187 -0
  133. package/src/ui-kit/settings.ts +131 -0
  134. package/src/ui-kit/store.ts +222 -0
  135. package/src/ui-kit/story.ts +89 -0
  136. package/src/ui-kit/util.ts +106 -0
  137. package/src/web/a11y.ts +429 -0
  138. package/src/web/audio-worklet.ts +193 -0
  139. package/src/web/audio.ts +307 -0
  140. package/src/web/basis.ts +239 -0
  141. package/src/web/gamepad.ts +123 -0
  142. package/src/web/host.ts +166 -0
  143. package/src/web/input.ts +237 -0
  144. package/src/web/lanes.ts +21 -0
  145. package/src/web/play.ts +20 -0
  146. package/src/web/rpc-ring.ts +110 -0
  147. package/src/web/settle.ts +122 -0
  148. package/src/web/shell.ts +643 -0
  149. package/src/web/text-input.ts +248 -0
  150. package/src/web/worker.ts +1002 -0
  151. package/types/bindings.json +13654 -0
  152. package/types/index.d.ts +20090 -0
  153. package/vendor/basis/LICENSE +201 -0
  154. package/vendor/basis/NOTICE +15 -0
  155. package/vendor/basis/README.md +18 -0
  156. package/vendor/basis/basis_transcoder.js +19 -0
  157. package/vendor/basis/basis_transcoder.wasm +0 -0
  158. package/README.md +0 -3
package/src/index.ts ADDED
@@ -0,0 +1,193 @@
1
+ // @origingame/engine: the runtime implementation of the generated
2
+ // declarations. Every export is typed by types/index.d.ts (the contract
3
+ // generated from crates/og-api/api.ogt), so a runtime member that drifts
4
+ // from the IDL fails `bun run typecheck`.
5
+
6
+ import type * as Api from "@origingame/engine";
7
+ import {
8
+ anim,
9
+ BUILTINS,
10
+ commands,
11
+ defineGame,
12
+ defineRecord,
13
+ defineSystem as defineSystemImpl,
14
+ load,
15
+ physics,
16
+ atmosphere,
17
+ audio,
18
+ render,
19
+ transform,
20
+ ui,
21
+ time,
22
+ camera,
23
+ tween,
24
+ tilemap,
25
+ type FieldSpec,
26
+ } from "./runtime.ts";
27
+ import { cameras } from "./systems/cameras.ts";
28
+ import { ai, i18n, nav, platform } from "./e6.ts";
29
+ import { stream, terrain } from "./p2.ts";
30
+ import { uiKit } from "./ui-kit/index.ts";
31
+
32
+ const spec = (kind: string, value: unknown, options: unknown): FieldSpec =>
33
+ Object.freeze({ kind, default: value, options: Object.freeze({ ...((options as object | undefined) ?? {}) }) });
34
+
35
+ const vector2 = () => ({ x: 0, y: 0 });
36
+ const vector3 = () => ({ x: 0, y: 0, z: 0 });
37
+ const identity = (): Api.Matrix4["elements"] => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
38
+
39
+ export const f32 = ((value = 0, options) => spec("f32", value, options)) as typeof Api.f32;
40
+ export const f64 = ((value = 0, options) => spec("f64", value, options)) as typeof Api.f64;
41
+ export const u32 = ((value = 0, options) => spec("u32", value, options)) as typeof Api.u32;
42
+ export const i32 = ((value = 0, options) => spec("i32", value, options)) as typeof Api.i32;
43
+ export const bool = ((value = false, options) => spec("bool", value, options)) as typeof Api.bool;
44
+ export const Vector2 = ((value = vector2(), options) => spec("Vector2", value, options)) as typeof Api.Vector2;
45
+ export const Vector3 = ((value = vector3(), options) => spec("Vector3", value, options)) as typeof Api.Vector3;
46
+ export const Quaternion = ((value = { x: 0, y: 0, z: 0, w: 1 }, options) => spec("Quaternion", value, options)) as typeof Api.Quaternion;
47
+ export const Matrix4 = ((value = { elements: identity() }, options) => spec("Matrix4", value, options)) as typeof Api.Matrix4;
48
+ export const Color = ((value = { r: 0, g: 0, b: 0 }, options) => spec("Color", value, options)) as typeof Api.Color;
49
+ // The capacity crosses with the spec; the engine refuses one outside 1 to 4096 at declaration.
50
+ export const str = ((capacity, value = "", options) => Object.freeze({ ...spec("str", value, options), capacity })) as typeof Api.str;
51
+ export const Entity = ((value = 0 as Api.Entity, options) => spec("Entity", value, options)) as typeof Api.Entity;
52
+ export const Geometry = ((value = 0 as Api.Geometry, options) => spec("Geometry", value, options)) as typeof Api.Geometry;
53
+ export const Material = ((value = 0 as Api.Material, options) => spec("Material", value, options)) as typeof Api.Material;
54
+ export const ToneMapping = ((value = "aces" as Api.ToneMapping, options) => spec("ToneMapping", value, options)) as typeof Api.ToneMapping;
55
+ export const Texture = ((value = 0 as Api.Texture, options) => spec("Texture", value, options)) as typeof Api.Texture;
56
+ export const Lut = ((value = 0 as Api.Lut, options) => spec("Lut", value, options)) as typeof Api.Lut;
57
+ export const EnvironmentMap = ((value = 0 as Api.EnvironmentMap, options) => spec("EnvironmentMap", value, options)) as typeof Api.EnvironmentMap;
58
+ export const ParticleEmitter = ((value = 0 as Api.ParticleEmitter, options) => spec("ParticleEmitter", value, options)) as typeof Api.ParticleEmitter;
59
+ export const AoMethod = ((value = "auto" as Api.AoMethod, options) => spec("AoMethod", value, options)) as typeof Api.AoMethod;
60
+ export const DofQuality = ((value = "low" as Api.DofQuality, options) => spec("DofQuality", value, options)) as typeof Api.DofQuality;
61
+ export const SpriteBlend = ((value = "alpha" as Api.SpriteBlend, options) => spec("SpriteBlend", value, options)) as typeof Api.SpriteBlend;
62
+ export const StripBlend = ((value = "additive" as Api.StripBlend, options) => spec("StripBlend", value, options)) as typeof Api.StripBlend;
63
+ export const Palette = ((value = 0 as Api.Palette, options) => spec("Palette", value, options)) as typeof Api.Palette;
64
+ export const DitherPattern = ((value = "none" as Api.DitherPattern, options) => spec("DitherPattern", value, options)) as typeof Api.DitherPattern;
65
+ export const StyliseSpace = ((value = "screen" as Api.StyliseSpace, options) => spec("StyliseSpace", value, options)) as typeof Api.StyliseSpace;
66
+ export const TextureArray = ((value = 0 as Api.TextureArray, options) => spec("TextureArray", value, options)) as typeof Api.TextureArray;
67
+ export const Asset = ((value = 0 as Api.Asset, options) => spec("Asset", value, options)) as typeof Api.Asset;
68
+ export const Sound = ((value = 0 as Api.Sound, options) => spec("Sound", value, options)) as typeof Api.Sound;
69
+ export const SkeletonAsset = ((value = 0 as Api.SkeletonAsset, options) => spec("SkeletonAsset", value, options)) as typeof Api.SkeletonAsset;
70
+ export const ClipAsset = ((value = 0 as Api.ClipAsset, options) => spec("ClipAsset", value, options)) as typeof Api.ClipAsset;
71
+ export const GraphAsset = ((value = 0 as Api.GraphAsset, options) => spec("GraphAsset", value, options)) as typeof Api.GraphAsset;
72
+ export const FlipbookSheet = ((value = 0 as Api.FlipbookSheet, options) => spec("FlipbookSheet", value, options)) as typeof Api.FlipbookSheet;
73
+ export const Tween = ((value = 0 as Api.Tween, options) => spec("Tween", value, options)) as typeof Api.Tween;
74
+ export const TilemapAsset = ((value = 0 as Api.TilemapAsset, options) => spec("TilemapAsset", value, options)) as typeof Api.TilemapAsset;
75
+ export const TerrainData = ((value = 0 as Api.TerrainData, options) => spec("TerrainData", value, options)) as typeof Api.TerrainData;
76
+ export const RootMotion = ((value = "off" as Api.RootMotion, options) => spec("RootMotion", value, options)) as typeof Api.RootMotion;
77
+ export const BlendshapeSource = ((value = "component" as Api.BlendshapeSource, options) => spec("BlendshapeSource", value, options)) as typeof Api.BlendshapeSource;
78
+ export const IkSolver = ((value = "twoBone" as Api.IkSolver, options) => spec("IkSolver", value, options)) as typeof Api.IkSolver;
79
+ export const IkSpace = ((value = "world" as Api.IkSpace, options) => spec("IkSpace", value, options)) as typeof Api.IkSpace;
80
+ export const AudioBus = ((value = "master" as Api.AudioBus, options) => spec("AudioBus", value, options)) as typeof Api.AudioBus;
81
+ export const Navigation = ((value = 0 as Api.Navigation, options) => spec("Navigation", value, options)) as typeof Api.Navigation;
82
+ export const Behaviour = ((value = 0 as Api.Behaviour, options) => spec("Behaviour", value, options)) as typeof Api.Behaviour;
83
+
84
+ export const defineComponent: typeof Api.defineComponent = (name, fields) =>
85
+ defineRecord("component", name, fields as unknown as Record<string, FieldSpec>) as never;
86
+
87
+ export const defineResource: typeof Api.defineResource = (name, fields) =>
88
+ defineRecord("resource", name, fields as unknown as Record<string, FieldSpec>) as never;
89
+
90
+ export const defineSystem: typeof Api.defineSystem = (name, desc, run) =>
91
+ defineSystemImpl(name, desc as never, run) as never;
92
+
93
+ export const PROBE_GLOBAL: typeof Api.PROBE_GLOBAL = "__runtime_probe__";
94
+ export const PROBE_VERSION: typeof Api.PROBE_VERSION = 5;
95
+ export const PROBE_WIRE_VERSION: typeof Api.PROBE_WIRE_VERSION = 1;
96
+ export const REPLAY_SEED_PARAM: typeof Api.REPLAY_SEED_PARAM = "replay-seed";
97
+ export const PLAYTEST_MAX_TICKS: typeof Api.PLAYTEST_MAX_TICKS = 3600;
98
+ export const PROBE_PROGRAM_MAX_OPERATIONS: typeof Api.PROBE_PROGRAM_MAX_OPERATIONS = 256;
99
+ export const MAX_POINTERS: typeof Api.MAX_POINTERS = 5;
100
+ export const MAX_GAMEPADS: typeof Api.MAX_GAMEPADS = 4;
101
+ export const MAX_LIGHTS: typeof Api.MAX_LIGHTS = 256;
102
+ export const MAX_CLUSTER_LIGHTS: typeof Api.MAX_CLUSTER_LIGHTS = 64;
103
+ export const UI_LAYER: typeof Api.UI_LAYER = 1000;
104
+ export const BODY_DYNAMIC: typeof Api.BODY_DYNAMIC = 0;
105
+ export const BODY_STATIC: typeof Api.BODY_STATIC = 1;
106
+ export const BODY_KINEMATIC: typeof Api.BODY_KINEMATIC = 2;
107
+ export const LOCK_TRANSLATION_X: typeof Api.LOCK_TRANSLATION_X = 1;
108
+ export const LOCK_TRANSLATION_Y: typeof Api.LOCK_TRANSLATION_Y = 2;
109
+ export const LOCK_TRANSLATION_Z: typeof Api.LOCK_TRANSLATION_Z = 4;
110
+ export const LOCK_ROTATION_X: typeof Api.LOCK_ROTATION_X = 8;
111
+ export const LOCK_ROTATION_Y: typeof Api.LOCK_ROTATION_Y = 16;
112
+ export const LOCK_ROTATION_Z: typeof Api.LOCK_ROTATION_Z = 32;
113
+ export const SHAPE_BOX: typeof Api.SHAPE_BOX = 0;
114
+ export const SHAPE_SPHERE: typeof Api.SHAPE_SPHERE = 1;
115
+ export const SHAPE_CAPSULE: typeof Api.SHAPE_CAPSULE = 2;
116
+ export const SHAPE_CYLINDER: typeof Api.SHAPE_CYLINDER = 3;
117
+ export const SHAPE_CONVEX: typeof Api.SHAPE_CONVEX = 4;
118
+ export const SHAPE_TRIMESH: typeof Api.SHAPE_TRIMESH = 5;
119
+ export const SHAPE_HEIGHTFIELD: typeof Api.SHAPE_HEIGHTFIELD = 6;
120
+ export const PROFILE_2D: typeof Api.PROFILE_2D = 2;
121
+ export const PROFILE_3D: typeof Api.PROFILE_3D = 3;
122
+ export const SOUND_FINISHED: typeof Api.SOUND_FINISHED = 0;
123
+ export const SOUND_STOPPED: typeof Api.SOUND_STOPPED = 1;
124
+ export const SOUND_REMOVED: typeof Api.SOUND_REMOVED = 2;
125
+ export const SOUND_REPLACED: typeof Api.SOUND_REPLACED = 3;
126
+ export const SOUND_CULLED: typeof Api.SOUND_CULLED = 4;
127
+ export const NAV_IDLE: typeof Api.NAV_IDLE = 0;
128
+ export const NAV_MOVING: typeof Api.NAV_MOVING = 1;
129
+ export const NAV_ARRIVED: typeof Api.NAV_ARRIVED = 2;
130
+ export const NAV_UNREACHABLE: typeof Api.NAV_UNREACHABLE = 3;
131
+ export const NAV_PARTIAL: typeof Api.NAV_PARTIAL = 4;
132
+ export const AI_RUNNING: typeof Api.AI_RUNNING = 1;
133
+ export const AI_SUCCESS: typeof Api.AI_SUCCESS = 2;
134
+ export const AI_FAILURE: typeof Api.AI_FAILURE = 3;
135
+
136
+ // The E5 round: physics beyond rigid bodies and the atmosphere.
137
+ export const WEATHER_NONE: typeof Api.WEATHER_NONE = 0;
138
+ export const WEATHER_RAIN: typeof Api.WEATHER_RAIN = 1;
139
+ export const WEATHER_SNOW: typeof Api.WEATHER_SNOW = 2;
140
+ export const WEATHER_DUST: typeof Api.WEATHER_DUST = 3;
141
+ export const WEATHER_MIST: typeof Api.WEATHER_MIST = 4;
142
+ export const JOINT_FIXED: typeof Api.JOINT_FIXED = 0;
143
+ export const JOINT_REVOLUTE: typeof Api.JOINT_REVOLUTE = 1;
144
+ export const JOINT_PRISMATIC: typeof Api.JOINT_PRISMATIC = 2;
145
+ export const JOINT_SPRING: typeof Api.JOINT_SPRING = 3;
146
+ export const JOINT_ROPE: typeof Api.JOINT_ROPE = 4;
147
+ export const JOINT_BALL: typeof Api.JOINT_BALL = 5;
148
+ export const MOTOR_NONE: typeof Api.MOTOR_NONE = 0;
149
+ export const MOTOR_VELOCITY: typeof Api.MOTOR_VELOCITY = 1;
150
+ export const MOTOR_POSITION: typeof Api.MOTOR_POSITION = 2;
151
+ export const CHARACTER_JUMPED: typeof Api.CHARACTER_JUMPED = 1;
152
+ export const CHARACTER_LANDED: typeof Api.CHARACTER_LANDED = 2;
153
+ export const CHARACTER_WALL_JUMPED: typeof Api.CHARACTER_WALL_JUMPED = 3;
154
+ export const CHARACTER_AIR_JUMPED: typeof Api.CHARACTER_AIR_JUMPED = 4;
155
+ export const CHARACTER_LEFT_GROUND: typeof Api.CHARACTER_LEFT_GROUND = 5;
156
+ export const CHARACTER_BUMPED: typeof Api.CHARACTER_BUMPED = 6;
157
+ export const DRIVE_REAR: typeof Api.DRIVE_REAR = 0;
158
+ export const DRIVE_FRONT: typeof Api.DRIVE_FRONT = 1;
159
+ export const DRIVE_ALL: typeof Api.DRIVE_ALL = 2;
160
+ export const PIN_TOP: typeof Api.PIN_TOP = 1;
161
+ export const PIN_TOP_CORNERS: typeof Api.PIN_TOP_CORNERS = 2;
162
+ export const PIN_LEFT: typeof Api.PIN_LEFT = 4;
163
+ export const PIN_TOP_RINGS: typeof Api.PIN_TOP_RINGS = 8;
164
+ export const STREAM_UNLOADED: typeof Api.STREAM_UNLOADED = 0;
165
+ export const STREAM_QUEUED: typeof Api.STREAM_QUEUED = 1;
166
+ export const STREAM_LOADING: typeof Api.STREAM_LOADING = 2;
167
+ export const STREAM_RESIDENT: typeof Api.STREAM_RESIDENT = 3;
168
+ export const STREAM_FAILED: typeof Api.STREAM_FAILED = 4;
169
+
170
+ export const og: typeof Api.og = Object.freeze({
171
+ ...BUILTINS,
172
+ game: (desc?: Api.GameDesc) => defineGame(desc as never),
173
+ transform,
174
+ render,
175
+ load,
176
+ commands,
177
+ physics,
178
+ atmosphere,
179
+ audio,
180
+ anim,
181
+ time,
182
+ camera,
183
+ tween,
184
+ tilemap,
185
+ nav,
186
+ ai,
187
+ platform,
188
+ i18n,
189
+ terrain,
190
+ stream,
191
+ ui: Object.freeze({ ...ui, ...uiKit }),
192
+ systems: Object.freeze({ cameras }),
193
+ }) as unknown as typeof Api.og;
@@ -0,0 +1,86 @@
1
+ // Audio on the native host (crates/og-audio/README.md §Host contract): one
2
+ // sink per engine over the addon's og_node_audio_* members. `null` drains
3
+ // the command stream and renders nothing (headless runs stay deterministic
4
+ // and their queue empty); `capture` renders it up to the world's tick for a
5
+ // WAV; `device` plays it on the default output (an addon built with the
6
+ // `native-audio` feature, cpal). Pump after every advance or frame.
7
+
8
+ import { native } from "./index.ts";
9
+ import type { Result } from "../runtime.ts";
10
+
11
+ /** The addon's audio members (crates/og-host-node/src/audio.rs). */
12
+ export interface NativeAudio {
13
+ og_node_audio_open(engine: number, mode: string, sampleRate?: number): string;
14
+ og_node_audio_pump(engine: number): string;
15
+ og_node_audio_stats(engine: number): string;
16
+ og_node_audio_wav(engine: number): Uint8Array;
17
+ og_node_audio_close(engine: number): boolean;
18
+ og_node_audio_insert_qoa(engine: number, id: string, qoa: Uint8Array): string;
19
+ }
20
+
21
+ export type AudioMode = "null" | "capture" | "device";
22
+
23
+ /** What a sink has done (fields present depend on the mode). */
24
+ export interface AudioStats {
25
+ readonly mode: AudioMode;
26
+ readonly sampleRate: number;
27
+ /** Interleaved stereo frames rendered (0 for null). */
28
+ readonly frames: number;
29
+ /** Commands consumed. */
30
+ readonly commands: number;
31
+ /** Voices sounding now. */
32
+ readonly voices: number;
33
+ readonly voicesPeak: number;
34
+ /** Packets a slow sink lost (each forces a resync). */
35
+ readonly dropped: number;
36
+ /** FNV-1a of every packet received, hex (null and capture). */
37
+ readonly receivedHash?: string;
38
+ readonly packets?: number;
39
+ readonly resyncs?: number;
40
+ readonly device?: string;
41
+ }
42
+
43
+ export interface AudioSink {
44
+ readonly mode: AudioMode;
45
+ /** Drain the command stream (and render, for capture) up to the world's tick. */
46
+ pump(): AudioStats;
47
+ stats(): AudioStats;
48
+ /** The captured audio as a 16-bit stereo WAV (empty unless capture). */
49
+ wav(): Uint8Array;
50
+ close(): void;
51
+ }
52
+
53
+ function audio(): NativeAudio {
54
+ return native() as unknown as NativeAudio;
55
+ }
56
+
57
+ function unwrap<T>(text: string): Result<T> {
58
+ return JSON.parse(text) as Result<T>;
59
+ }
60
+
61
+ /** Open the engine's audio sink. `sampleRate` applies to capture (default 48000). */
62
+ export function openAudio(engine: number, mode: AudioMode = "null", sampleRate?: number): Result<AudioSink> {
63
+ const a = audio();
64
+ const opened = unwrap<string>(sampleRate === undefined ? a.og_node_audio_open(engine, mode) : a.og_node_audio_open(engine, mode, sampleRate));
65
+ if (!opened.ok) return opened;
66
+ const read = (text: string): AudioStats => {
67
+ const r = unwrap<AudioStats>(text);
68
+ if (!r.ok) throw new Error(r.reason);
69
+ return r.value;
70
+ };
71
+ return {
72
+ ok: true,
73
+ value: {
74
+ mode,
75
+ pump: () => read(a.og_node_audio_pump(engine)),
76
+ stats: () => read(a.og_node_audio_stats(engine)),
77
+ wav: () => a.og_node_audio_wav(engine),
78
+ close: () => void a.og_node_audio_close(engine),
79
+ },
80
+ };
81
+ }
82
+
83
+ /** Add a sound (a QOA file: a cooked sound's `qoa` section) to the engine's bank; its handle is what AudioSource.sound takes. */
84
+ export function insertSound(engine: number, id: string, qoa: Uint8Array): Result<number> {
85
+ return unwrap<number>(audio().og_node_audio_insert_qoa(engine, id, qoa));
86
+ }
@@ -0,0 +1,109 @@
1
+ // Bundles a game for a host (`og build`, `og run`, `og dev` call it):
2
+ //
3
+ // native the game's own code in one module, `@origingame/engine` left
4
+ // external and pointed at this package's files, so the game and the
5
+ // native host share one runtime instance (and a re-imported bundle
6
+ // re-registers into the same engine on hot reload);
7
+ // web the engine Worker: `startWorker(game)`, the runtime and the game in
8
+ // one module, as the play page's shell starts it.
9
+ //
10
+ // bun src/node/build.ts --entry <src/main.ts> --out <file.js> [--target native|web] [--json]
11
+
12
+ import { readFileSync } from "node:fs";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ declare const Bun: {
17
+ build(o: {
18
+ entrypoints: string[];
19
+ outdir?: string;
20
+ target: string;
21
+ format: string;
22
+ minify?: boolean;
23
+ naming?: string;
24
+ plugins?: unknown[];
25
+ }): Promise<{ success: boolean; logs: unknown[]; outputs: Array<{ path: string; size: number; text(): Promise<string> }> }>;
26
+ write(path: string, data: string): Promise<number>;
27
+ };
28
+
29
+ const here = dirname(fileURLToPath(import.meta.url));
30
+ export const ENGINE_ROOT = resolve(here, "..", "..");
31
+
32
+ type Exports = Record<string, string | { default?: string; types?: string }>;
33
+ const exports = (JSON.parse(readFileSync(join(ENGINE_ROOT, "package.json"), "utf8")) as { exports: Exports }).exports;
34
+
35
+ /** The file `@origingame/engine[/sub]` names in this package's exports. */
36
+ export function engineFile(specifier: string): string | null {
37
+ const sub = specifier.slice("@origingame/engine".length);
38
+ const target = exports[sub === "" ? "." : `.${sub}`];
39
+ const file = typeof target === "string" ? target : target?.default;
40
+ return file ? join(ENGINE_ROOT, file) : null;
41
+ }
42
+
43
+ export interface Bundled {
44
+ readonly ok: boolean;
45
+ readonly out: string;
46
+ readonly bytes: number;
47
+ readonly ms: number;
48
+ readonly reason?: string;
49
+ }
50
+
51
+ /** Bundle `entry` (whose default export is `og.game(...)`) into `out`. */
52
+ export async function bundleGame(entry: string, out: string, target: "native" | "web" = "native", minify = false): Promise<Bundled> {
53
+ const t0 = performance.now();
54
+ const absEntry = resolve(entry);
55
+ const engine = {
56
+ name: "origin-engine",
57
+ setup(build: {
58
+ onResolve(o: { filter: RegExp; namespace?: string }, f: (a: { path: string }) => unknown): void;
59
+ onLoad(o: { filter: RegExp; namespace: string }, f: (a: { path: string }) => unknown): void;
60
+ }) {
61
+ build.onResolve({ filter: /^@origingame\/engine(\/.*)?$/ }, (a) => {
62
+ const file = engineFile(a.path);
63
+ if (!file) throw new Error(`${a.path} is not an export of @origingame/engine`);
64
+ return { path: file, external: target === "native" };
65
+ });
66
+ build.onResolve({ filter: /^og:worker$/ }, () => ({ path: "worker", namespace: "og" }));
67
+ build.onLoad({ filter: /.*/, namespace: "og" }, () => ({
68
+ contents: `import { startWorker } from "@origingame/engine/web/worker";\nimport game from ${JSON.stringify(absEntry)};\nstartWorker(game);\n`,
69
+ loader: "ts",
70
+ }));
71
+ },
72
+ };
73
+ const r = await Bun.build({
74
+ entrypoints: [target === "web" ? "og:worker" : absEntry],
75
+ target: target === "web" ? "browser" : "bun",
76
+ format: "esm",
77
+ minify,
78
+ plugins: [engine],
79
+ });
80
+ if (!r.success || r.outputs.length === 0) {
81
+ const reason = r.logs.map((l) => String((l as { message?: string }).message ?? l)).join("\n") || "bun build failed";
82
+ return { ok: false, out, bytes: 0, ms: performance.now() - t0, reason };
83
+ }
84
+ const text = await r.outputs[0]!.text();
85
+ await Bun.write(out, text);
86
+ return { ok: true, out, bytes: new TextEncoder().encode(text).length, ms: +(performance.now() - t0).toFixed(1) };
87
+ }
88
+
89
+ if (import.meta.main) {
90
+ const argv = process.argv.slice(2);
91
+ const opt = (name: string) => {
92
+ const i = argv.indexOf(name);
93
+ return i >= 0 ? argv[i + 1] : undefined;
94
+ };
95
+ const entry = opt("--entry");
96
+ const out = opt("--out");
97
+ const target = (opt("--target") ?? "native") as "native" | "web";
98
+ if (!entry || !out || (target !== "native" && target !== "web")) {
99
+ process.stderr.write("usage: bun src/node/build.ts --entry <src/main.ts> --out <file.js> [--target native|web] [--minify] [--json]\n");
100
+ process.exit(2);
101
+ }
102
+ const r = await bundleGame(entry, out, target, argv.includes("--minify"));
103
+ if (argv.includes("--json")) process.stdout.write(JSON.stringify(r) + "\n");
104
+ else if (r.ok) process.stdout.write(`bundled ${entry} -> ${out} (${r.bytes} bytes, ${r.ms} ms)\n`);
105
+ if (!r.ok) {
106
+ process.stderr.write(`og build: ${entry}: ${r.reason}\n`);
107
+ process.exit(1);
108
+ }
109
+ }