@realnation/builder-shared-sdk 1.0.4 → 1.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 +6 -0
- package/dist/events.d.ts +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +1 -3
- package/dist/flow.d.ts.map +1 -1
- package/dist/flow.js +12 -4
- package/dist/http.d.ts +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/oss.d.ts.map +1 -1
- package/dist/oss.js +7 -4
- package/dist/runtime/capability.d.ts +45 -0
- package/dist/runtime/capability.d.ts.map +1 -0
- package/dist/runtime/capability.js +59 -0
- package/dist/runtime/connection.d.ts +92 -0
- package/dist/runtime/connection.d.ts.map +1 -0
- package/dist/runtime/connection.js +247 -0
- package/dist/runtime/decode.d.ts +40 -0
- package/dist/runtime/decode.d.ts.map +1 -0
- package/dist/runtime/decode.js +106 -0
- package/dist/runtime/facade.d.ts +165 -0
- package/dist/runtime/facade.d.ts.map +1 -0
- package/dist/runtime/facade.js +354 -0
- package/dist/runtime/index.d.ts +42 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +70 -0
- package/dist/runtime/mock.d.ts +58 -0
- package/dist/runtime/mock.d.ts.map +1 -0
- package/dist/runtime/mock.js +276 -0
- package/dist/runtime/protocol.d.ts +231 -0
- package/dist/runtime/protocol.d.ts.map +1 -0
- package/dist/runtime/protocol.js +19 -0
- package/dist/runtime/vue/index.d.ts +26 -0
- package/dist/runtime/vue/index.d.ts.map +1 -0
- package/dist/runtime/vue/index.js +47 -0
- package/dist/runtime/vue/player.d.ts +49 -0
- package/dist/runtime/vue/player.d.ts.map +1 -0
- package/dist/runtime/vue/player.js +95 -0
- package/package.json +24 -3
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { CreateRuntimeOptions, Runtime } from '../index.js';
|
|
3
|
+
import type { ConnectStatus } from '../capability.js';
|
|
4
|
+
import type { ReactivePlayer } from './player.js';
|
|
5
|
+
export { createPlayerHandle, PLAYER_JOINTS } from './player.js';
|
|
6
|
+
export type { ReactivePlayer, ReactiveJoint, PlayerHandle } from './player.js';
|
|
7
|
+
/**
|
|
8
|
+
* Attaches a reactive player facade to an existing runtime and disposes it when
|
|
9
|
+
* the component unmounts. Call inside setup().
|
|
10
|
+
*/
|
|
11
|
+
export declare function useRuntimePlayer(runtime: Runtime): ReactivePlayer;
|
|
12
|
+
export interface UseRuntimeResult {
|
|
13
|
+
runtime: Runtime;
|
|
14
|
+
/** Null until connect() resolves; then the runtime's verdict. */
|
|
15
|
+
status: Ref<ConnectStatus | null>;
|
|
16
|
+
player: ReactivePlayer;
|
|
17
|
+
connect: () => Promise<ConnectStatus>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a runtime, a player facade, and ties both to the component lifetime.
|
|
21
|
+
*
|
|
22
|
+
* `status` is a shallowRef because it is replaced wholesale on each handshake —
|
|
23
|
+
* unlike the player, whose deep fields are mutated in place every frame.
|
|
24
|
+
*/
|
|
25
|
+
export declare function useRuntime(options?: CreateRuntimeOptions): UseRuntimeResult;
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/vue/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAIjE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAClC,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CAoB/E"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue 3 adapter for the runtime SDK.
|
|
3
|
+
*
|
|
4
|
+
* Import from '@realnation/builder-shared-sdk/runtime/vue'. The core SDK at
|
|
5
|
+
* '/runtime' has no framework dependency; everything Vue-specific is here.
|
|
6
|
+
*
|
|
7
|
+
* `vue` is an optional peerDependency — consumers that never import this
|
|
8
|
+
* subpath do not need it installed.
|
|
9
|
+
*/
|
|
10
|
+
import { onUnmounted, shallowRef } from 'vue';
|
|
11
|
+
import { createRuntime } from '../index.js';
|
|
12
|
+
import { createPlayerHandle } from './player.js';
|
|
13
|
+
export { createPlayerHandle, PLAYER_JOINTS } from './player.js';
|
|
14
|
+
/**
|
|
15
|
+
* Attaches a reactive player facade to an existing runtime and disposes it when
|
|
16
|
+
* the component unmounts. Call inside setup().
|
|
17
|
+
*/
|
|
18
|
+
export function useRuntimePlayer(runtime) {
|
|
19
|
+
const handle = createPlayerHandle(runtime);
|
|
20
|
+
onUnmounted(() => handle.dispose());
|
|
21
|
+
return handle.primary();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Creates a runtime, a player facade, and ties both to the component lifetime.
|
|
25
|
+
*
|
|
26
|
+
* `status` is a shallowRef because it is replaced wholesale on each handshake —
|
|
27
|
+
* unlike the player, whose deep fields are mutated in place every frame.
|
|
28
|
+
*/
|
|
29
|
+
export function useRuntime(options = {}) {
|
|
30
|
+
const runtime = createRuntime(options);
|
|
31
|
+
const status = shallowRef(null);
|
|
32
|
+
const handle = createPlayerHandle(runtime);
|
|
33
|
+
onUnmounted(() => {
|
|
34
|
+
handle.dispose();
|
|
35
|
+
runtime.close();
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
runtime,
|
|
39
|
+
status,
|
|
40
|
+
player: handle.primary(),
|
|
41
|
+
connect: async () => {
|
|
42
|
+
const s = await runtime.connect();
|
|
43
|
+
status.value = s;
|
|
44
|
+
return s;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { RuntimeFacade } from '../facade.js';
|
|
2
|
+
export interface ReactiveJoint {
|
|
3
|
+
position: {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
z: number;
|
|
7
|
+
};
|
|
8
|
+
confidence: number;
|
|
9
|
+
valid: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ReactivePlayer {
|
|
12
|
+
isTracked: boolean;
|
|
13
|
+
/** Which runtime player index this facade currently follows. */
|
|
14
|
+
index: number;
|
|
15
|
+
center: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
};
|
|
19
|
+
depth: number;
|
|
20
|
+
ts: number;
|
|
21
|
+
head: ReactiveJoint;
|
|
22
|
+
neck: ReactiveJoint;
|
|
23
|
+
leftShoulder: ReactiveJoint;
|
|
24
|
+
rightShoulder: ReactiveJoint;
|
|
25
|
+
leftElbow: ReactiveJoint;
|
|
26
|
+
rightElbow: ReactiveJoint;
|
|
27
|
+
leftHand: ReactiveJoint;
|
|
28
|
+
rightHand: ReactiveJoint;
|
|
29
|
+
leftHip: ReactiveJoint;
|
|
30
|
+
rightHip: ReactiveJoint;
|
|
31
|
+
leftKnee: ReactiveJoint;
|
|
32
|
+
rightKnee: ReactiveJoint;
|
|
33
|
+
leftFoot: ReactiveJoint;
|
|
34
|
+
rightFoot: ReactiveJoint;
|
|
35
|
+
[joint: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
export declare const PLAYER_JOINTS: readonly ["head", "neck", "leftShoulder", "rightShoulder", "leftElbow", "rightElbow", "leftHand", "rightHand", "leftHip", "rightHip", "leftKnee", "rightKnee", "leftFoot", "rightFoot"];
|
|
38
|
+
export interface PlayerHandle {
|
|
39
|
+
/**
|
|
40
|
+
* The primary player. A STABLE reference: when the tracked player changes,
|
|
41
|
+
* the same object is repointed in place, so a component that captured it at
|
|
42
|
+
* setup() keeps working without re-fetching.
|
|
43
|
+
*/
|
|
44
|
+
primary(): ReactivePlayer;
|
|
45
|
+
/** Stops updating the facade. */
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
export declare function createPlayerHandle(runtime: RuntimeFacade): PlayerHandle;
|
|
49
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../../src/runtime/vue/player.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,cAAc,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,YAAY,EAAE,aAAa,CAAC;IAC5B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,aAAa,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,aAAa,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,yLAIhB,CAAC;AAmDX,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,IAAI,cAAc,CAAC;IAC1B,iCAAiC;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAgCvE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Game API: a reactive player facade.
|
|
3
|
+
*
|
|
4
|
+
* This is the ONLY file in the runtime SDK that imports 'vue'. Everything under
|
|
5
|
+
* src/runtime/ outside this directory is framework-free, so Canvas/WebGL games,
|
|
6
|
+
* tooling and non-Vue hosts can use the SDK without a reactivity system.
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ This facade is for UI — scores, status text, debug panels. A game loop
|
|
9
|
+
* rendering at 30–60fps should subscribe to runtime.body.onUpdate() and draw
|
|
10
|
+
* from the raw data instead. Binding a skeleton into a Vue template makes Vue
|
|
11
|
+
* run dependency tracking and patching every frame, which is a natural but
|
|
12
|
+
* expensive mistake.
|
|
13
|
+
*/
|
|
14
|
+
import { reactive } from 'vue';
|
|
15
|
+
export const PLAYER_JOINTS = [
|
|
16
|
+
'head', 'neck', 'leftShoulder', 'rightShoulder', 'leftElbow', 'rightElbow',
|
|
17
|
+
'leftHand', 'rightHand', 'leftHip', 'rightHip', 'leftKnee', 'rightKnee',
|
|
18
|
+
'leftFoot', 'rightFoot',
|
|
19
|
+
];
|
|
20
|
+
function blankJoint() {
|
|
21
|
+
return { position: { x: 0, y: 0, z: 0 }, confidence: 0, valid: false };
|
|
22
|
+
}
|
|
23
|
+
function blankPlayer() {
|
|
24
|
+
const p = {
|
|
25
|
+
isTracked: false,
|
|
26
|
+
index: -1,
|
|
27
|
+
center: { x: 0.5, y: 0.5 },
|
|
28
|
+
depth: 0,
|
|
29
|
+
ts: 0,
|
|
30
|
+
};
|
|
31
|
+
for (const name of PLAYER_JOINTS)
|
|
32
|
+
p[name] = blankJoint();
|
|
33
|
+
return p;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Copies a frame into the existing reactive tree.
|
|
37
|
+
*
|
|
38
|
+
* Assigns leaf fields only. Replacing `player.leftHand = {...}` would make Vue
|
|
39
|
+
* rebuild that proxy subtree every frame; at 60fps that is the difference
|
|
40
|
+
* between a facade you can leave mounted and one that shows up in a profile.
|
|
41
|
+
*/
|
|
42
|
+
function applyBody(player, body) {
|
|
43
|
+
player.isTracked = true;
|
|
44
|
+
player.index = body.player;
|
|
45
|
+
player.ts = body.ts;
|
|
46
|
+
if (body.center) {
|
|
47
|
+
player.center.x = body.center.x ?? player.center.x;
|
|
48
|
+
player.center.y = body.center.y ?? player.center.y;
|
|
49
|
+
}
|
|
50
|
+
if (typeof body.depth === 'number')
|
|
51
|
+
player.depth = body.depth;
|
|
52
|
+
for (const name of PLAYER_JOINTS) {
|
|
53
|
+
const target = player[name];
|
|
54
|
+
const src = body.skeleton?.[name];
|
|
55
|
+
if (!src) {
|
|
56
|
+
target.valid = false;
|
|
57
|
+
target.confidence = 0;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
target.position.x = src.x;
|
|
61
|
+
target.position.y = src.y;
|
|
62
|
+
target.position.z = src.z;
|
|
63
|
+
target.confidence = src.c;
|
|
64
|
+
target.valid = src.valid;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function createPlayerHandle(runtime) {
|
|
68
|
+
const player = reactive(blankPlayer());
|
|
69
|
+
let primaryIndex = null;
|
|
70
|
+
const disposers = [];
|
|
71
|
+
disposers.push(runtime.body.onUpdate((body) => {
|
|
72
|
+
// First body seen wins; it stays primary until the player is lost, so a
|
|
73
|
+
// second person walking through frame cannot steal control mid-game.
|
|
74
|
+
if (primaryIndex === null)
|
|
75
|
+
primaryIndex = body.player;
|
|
76
|
+
if (body.player !== primaryIndex)
|
|
77
|
+
return;
|
|
78
|
+
applyBody(player, body);
|
|
79
|
+
}));
|
|
80
|
+
disposers.push(runtime.device.onPlayerLost(() => {
|
|
81
|
+
primaryIndex = null;
|
|
82
|
+
player.isTracked = false;
|
|
83
|
+
for (const name of PLAYER_JOINTS) {
|
|
84
|
+
player[name].valid = false;
|
|
85
|
+
}
|
|
86
|
+
}));
|
|
87
|
+
return {
|
|
88
|
+
primary: () => player,
|
|
89
|
+
dispose: () => {
|
|
90
|
+
for (const d of disposers)
|
|
91
|
+
d();
|
|
92
|
+
disposers.length = 0;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realnation/builder-shared-sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"exports": {
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
".": {
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./runtime": {
|
|
13
|
+
"types": "./dist/runtime/index.d.ts",
|
|
14
|
+
"import": "./dist/runtime/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./runtime/vue": {
|
|
17
|
+
"types": "./dist/runtime/vue/index.d.ts",
|
|
18
|
+
"import": "./dist/runtime/vue/index.js"
|
|
11
19
|
}
|
|
12
20
|
},
|
|
13
21
|
"files": [
|
|
@@ -16,16 +24,29 @@
|
|
|
16
24
|
"scripts": {
|
|
17
25
|
"build": "tsc -p tsconfig.json",
|
|
18
26
|
"clean": "rimraf dist",
|
|
19
|
-
"
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"prepublishOnly": "npm run clean && npm run test && npm run build",
|
|
20
30
|
"prepare": "npm run clean && npm run build"
|
|
21
31
|
},
|
|
22
32
|
"dependencies": {
|
|
23
33
|
"ali-oss": "^6.23.0",
|
|
24
34
|
"axios": "^1.7.7"
|
|
25
35
|
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"vue": "^3.4.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"vue": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
26
44
|
"devDependencies": {
|
|
27
45
|
"@types/ali-oss": "^6.16.11",
|
|
46
|
+
"@types/node": "^26.1.2",
|
|
28
47
|
"rimraf": "^5.0.5",
|
|
29
|
-
"typescript": "^5.4.5"
|
|
48
|
+
"typescript": "^5.4.5",
|
|
49
|
+
"vitest": "^2.1.0",
|
|
50
|
+
"vue": "^3.4.0"
|
|
30
51
|
}
|
|
31
52
|
}
|