@series-inc/rundot-kinetix 0.0.0-bootstrap.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 (58) hide show
  1. package/README.md +77 -0
  2. package/authoring.d.ts +30 -0
  3. package/index.d.ts +221 -0
  4. package/native/component_runtime.cpp +341 -0
  5. package/native/component_runtime.hpp +112 -0
  6. package/native/deterministic_math.cpp +594 -0
  7. package/native/deterministic_math.hpp +21 -0
  8. package/native/kinetix-f64-native-profile.cpp +406 -0
  9. package/native/kinetix-f64-native-profile.hpp +5 -0
  10. package/native/kinetix-fixed1000-native-profile.cpp +777 -0
  11. package/native/kinetix-fixed1000-native-profile.hpp +58 -0
  12. package/native/kinetix-fixed1000-physics.cpp +887 -0
  13. package/native/kinetix-fixed1000-physics.hpp +28 -0
  14. package/native/kinetix-installed-f64-renderer.cpp +344 -0
  15. package/native/kinetix-installed-f64-renderer.hpp +35 -0
  16. package/native/kinetix-installed-f64-runtime.cpp +1085 -0
  17. package/native/kinetix-installed-f64-runtime.hpp +141 -0
  18. package/native/kinetix-installed-fixed1000-data.hpp +77 -0
  19. package/native/kinetix-native-main.cpp +37 -0
  20. package/native/kinetix-native-runtime.cpp +20 -0
  21. package/native/kinetix-native-runtime.hpp +25 -0
  22. package/native/kinetix-render-projection.cpp +20 -0
  23. package/native/kinetix-render-projection.hpp +14 -0
  24. package/package.json +65 -0
  25. package/runtime.d.ts +76 -0
  26. package/scripts/build-native.mjs +67 -0
  27. package/scripts/emit-product-digests.mjs +33 -0
  28. package/scripts/preflight.mjs +76 -0
  29. package/src/index.mjs +57 -0
  30. package/src/kinetix-authoring.mjs +69 -0
  31. package/src/kinetix-baker.mjs +587 -0
  32. package/src/kinetix-deterministic-math.mjs +1044 -0
  33. package/src/kinetix-fixed1000-runtime-adapter.mjs +33 -0
  34. package/src/kinetix-fixed1000-runtime.mjs +954 -0
  35. package/src/kinetix-installed-f64-reference.mjs +157 -0
  36. package/src/kinetix-installed-f64-render-frames.mjs +53 -0
  37. package/src/kinetix-installed-f64-renderer.mjs +240 -0
  38. package/src/kinetix-installed-f64-runtime-adapter.mjs +68 -0
  39. package/src/kinetix-installed-f64-runtime.mjs +607 -0
  40. package/src/kinetix-installed-mechanics.mjs +377 -0
  41. package/src/kinetix-installed-systems.mjs +181 -0
  42. package/src/kinetix-native-product.mjs +72 -0
  43. package/src/kinetix-product-contract.mjs +121 -0
  44. package/src/kinetix-project-compiler.mjs +1017 -0
  45. package/src/kinetix-render-projection.mjs +28 -0
  46. package/src/kinetix-runtime-adapter-utils.mjs +168 -0
  47. package/src/kinetix-runtime-contract.mjs +54 -0
  48. package/src/kinetix-session-config.mjs +170 -0
  49. package/src/kinetix-source-snapshot.mjs +24 -0
  50. package/src/kinetix-survival-runtime-adapter.mjs +305 -0
  51. package/src/kinetix-survival-runtime.generated.mjs +1 -0
  52. package/src/kinetix-world-kernel.mjs +580 -0
  53. package/src/kinetix-world-runtime.mjs +171 -0
  54. package/src/runtime.mjs +14 -0
  55. package/src/shared/f64-bits.mjs +14 -0
  56. package/src/shared/kinetix-envelope-v1.mjs +589 -0
  57. package/src/shared/render-records-v1.mjs +168 -0
  58. package/src/shared/sha256.mjs +73 -0
@@ -0,0 +1,171 @@
1
+ import { assertKinetixRuntimeIdentity } from './kinetix-runtime-contract.mjs';
2
+ import { kinetixSessionConfigDigest } from './kinetix-session-config.mjs';
3
+ import { sha256Hex } from './shared/sha256.mjs';
4
+
5
+ const textEncoder = new TextEncoder();
6
+ const textDecoder = new TextDecoder('utf-8', { fatal: true });
7
+
8
+ function fail(code) {
9
+ throw new Error(code);
10
+ }
11
+
12
+ function isPlainObject(value) {
13
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
14
+ }
15
+
16
+ function canonicalize(value) {
17
+ if (Array.isArray(value)) return value.map(canonicalize);
18
+ if (isPlainObject(value)) {
19
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
20
+ }
21
+ return value;
22
+ }
23
+
24
+ function snapshotBytes(snapshot) {
25
+ return textEncoder.encode(JSON.stringify(canonicalize(snapshot)));
26
+ }
27
+
28
+ function assertWorld(world) {
29
+ if (!isPlainObject(world)
30
+ || typeof world.step !== 'function'
31
+ || typeof world.snapshot !== 'function'
32
+ || typeof world.restore !== 'function'
33
+ || typeof world.canonicalStateBytes !== 'function') {
34
+ fail('KINETIX_WORLD_INVALID');
35
+ }
36
+ }
37
+
38
+ function assertSnapshot(snapshot) {
39
+ if (!isPlainObject(snapshot) || !Number.isSafeInteger(snapshot.tick) || snapshot.tick < 0) {
40
+ fail('KINETIX_SNAPSHOT_INVALID');
41
+ }
42
+ }
43
+
44
+ export function createKinetixWorldRuntime({ world, identity, sessionConfigBytes = new TextEncoder().encode('{}') }) {
45
+ assertWorld(world);
46
+ assertKinetixRuntimeIdentity(identity);
47
+ if (!(sessionConfigBytes instanceof Uint8Array)
48
+ || sessionConfigBytes.byteLength < 1
49
+ || sessionConfigBytes.byteLength > 65_536) {
50
+ fail('KINETIX_SESSION_CONFIG_INVALID');
51
+ }
52
+ const checkpoints = new WeakMap();
53
+
54
+ function makeCheckpoint(snapshot) {
55
+ assertSnapshot(snapshot);
56
+ const copy = structuredClone(snapshot);
57
+ const checkpoint = Object.freeze({ frame: copy.tick });
58
+ checkpoints.set(checkpoint, {
59
+ frame: copy.tick,
60
+ snapshot: copy,
61
+ bytes: snapshotBytes(copy),
62
+ });
63
+ return checkpoint;
64
+ }
65
+
66
+ function checkpointData(checkpoint) {
67
+ const data = isPlainObject(checkpoint) ? checkpoints.get(checkpoint) : undefined;
68
+ if (!data) fail('KINETIX_RUNTIME_CHECKPOINT_INVALID');
69
+ return data;
70
+ }
71
+
72
+ const initialSnapshot = world.snapshot();
73
+ assertSnapshot(initialSnapshot);
74
+ let currentCheckpoint = makeCheckpoint(initialSnapshot);
75
+ const canonicalSessionConfig = sessionConfigBytes.slice();
76
+
77
+ const runtime = {
78
+ identity: Object.freeze(structuredClone(identity)),
79
+ sessionConfigDigest: kinetixSessionConfigDigest(canonicalSessionConfig),
80
+ get currentFrame() {
81
+ return checkpointData(currentCheckpoint).frame;
82
+ },
83
+ sessionConfigBytes() {
84
+ return canonicalSessionConfig.slice();
85
+ },
86
+ capture() {
87
+ return makeCheckpoint(checkpointData(currentCheckpoint).snapshot);
88
+ },
89
+ advance(requests) {
90
+ if (!Array.isArray(requests)) fail('KINETIX_RUNTIME_BATCH_INVALID');
91
+ let expectedFrame = this.currentFrame + 1;
92
+ for (const request of requests) {
93
+ if (!isPlainObject(request)
94
+ || request.frame !== expectedFrame
95
+ || !Array.isArray(request.inputs)
96
+ || !Array.isArray(request.commands)
97
+ || typeof request.checksum !== 'boolean') {
98
+ fail('KINETIX_RUNTIME_FRAME_MISMATCH');
99
+ }
100
+ expectedFrame += 1;
101
+ }
102
+
103
+ const starting = checkpointData(currentCheckpoint);
104
+ const results = [];
105
+ try {
106
+ for (const request of requests) {
107
+ world.step({
108
+ frame: request.frame,
109
+ inputs: structuredClone(request.inputs),
110
+ commands: structuredClone(request.commands),
111
+ });
112
+ const snapshot = world.snapshot();
113
+ assertSnapshot(snapshot);
114
+ if (snapshot.tick !== request.frame) fail('KINETIX_RUNTIME_FRAME_MISMATCH');
115
+ currentCheckpoint = makeCheckpoint(snapshot);
116
+ const result = {
117
+ frame: request.frame,
118
+ checkpoint: currentCheckpoint,
119
+ };
120
+ if (request.checksum) result.checksum = this.checksum(currentCheckpoint);
121
+ results.push(result);
122
+ }
123
+ return results;
124
+ } catch (error) {
125
+ world.restore(structuredClone(starting.snapshot));
126
+ currentCheckpoint = makeCheckpoint(starting.snapshot);
127
+ throw error;
128
+ }
129
+ },
130
+ restore(checkpoint) {
131
+ const data = checkpointData(checkpoint);
132
+ world.restore(structuredClone(data.snapshot));
133
+ const restored = world.snapshot();
134
+ assertSnapshot(restored);
135
+ if (restored.tick !== data.frame) fail('KINETIX_RUNTIME_FRAME_MISMATCH');
136
+ currentCheckpoint = makeCheckpoint(restored);
137
+ },
138
+ inspect(checkpoint) {
139
+ return structuredClone(checkpointData(checkpoint).snapshot);
140
+ },
141
+ serializeCheckpoint(checkpoint) {
142
+ return checkpointData(checkpoint).bytes.slice();
143
+ },
144
+ hydrateCheckpoint(frame, bytes) {
145
+ if (!Number.isSafeInteger(frame) || frame < 0 || !(bytes instanceof Uint8Array)) {
146
+ fail('KINETIX_RUNTIME_CHECKPOINT_INVALID');
147
+ }
148
+ let snapshot;
149
+ try {
150
+ snapshot = JSON.parse(textDecoder.decode(bytes));
151
+ } catch {
152
+ fail('KINETIX_RUNTIME_CHECKPOINT_INVALID');
153
+ }
154
+ assertSnapshot(snapshot);
155
+ if (snapshot.tick !== frame) fail('KINETIX_RUNTIME_FRAME_MISMATCH');
156
+ if (!snapshotBytes(snapshot).every((byte, index) => byte === bytes[index])
157
+ || snapshotBytes(snapshot).length !== bytes.length) {
158
+ fail('KINETIX_RUNTIME_CHECKPOINT_INVALID');
159
+ }
160
+ return makeCheckpoint(snapshot);
161
+ },
162
+ checksum(checkpoint) {
163
+ return sha256Hex(checkpointData(checkpoint).bytes);
164
+ },
165
+ wireChecksum(checkpoint) {
166
+ return sha256Hex(checkpointData(checkpoint).bytes);
167
+ },
168
+ release(_checkpoint) {},
169
+ };
170
+ return Object.freeze(runtime);
171
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ assertKinetixRuntime,
3
+ assertKinetixRuntimeIdentity,
4
+ kinetixRuntimeAbiVersion,
5
+ } from './kinetix-runtime-contract.mjs';
6
+ export { createKinetixWorldRuntime } from './kinetix-world-runtime.mjs';
7
+ export { createInstalledF64Runtime } from './kinetix-installed-f64-runtime-adapter.mjs';
8
+ export { createInstalledSurvivalRuntime } from './kinetix-survival-runtime-adapter.mjs';
9
+ export { createFixed1000Runtime } from './kinetix-fixed1000-runtime-adapter.mjs';
10
+ export {
11
+ decodeKinetixSessionConfig,
12
+ encodeKinetixSessionConfig,
13
+ kinetixSessionConfigDigest,
14
+ } from './kinetix-session-config.mjs';
@@ -0,0 +1,14 @@
1
+ // Exact f64 <-> u64-bit-pattern hex helpers. Browser-safe (no node imports);
2
+ // the single source for pack v2 scalar encoding.
3
+
4
+ const scratch = new DataView(new ArrayBuffer(8));
5
+
6
+ export function f64FromHex(hex) {
7
+ scratch.setBigUint64(0, BigInt(hex), true);
8
+ return scratch.getFloat64(0, true);
9
+ }
10
+
11
+ export function hexFromF64(value) {
12
+ scratch.setFloat64(0, value, true);
13
+ return `0x${scratch.getBigUint64(0, true).toString(16).padStart(16, '0')}`;
14
+ }