@genex-ai/multiplayer 0.16.1 → 0.17.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/dist/schema.d.ts CHANGED
@@ -1,75 +1,129 @@
1
1
  import * as _colyseus_schema from '@colyseus/schema';
2
- import { SchemaType, MapSchema } from '@colyseus/schema';
2
+ import { SchemaType } from '@colyseus/schema';
3
3
 
4
4
  declare const PlayerState: _colyseus_schema.SchemaWithExtendsConstructor<{
5
- name: "string";
6
- data: "string";
7
- epoch: "number";
8
- connected: "boolean";
9
- avatarUrl: "string";
10
- }, _colyseus_schema.AssignableProps<_colyseus_schema.InferSchemaInstanceType<{
11
- name: "string";
12
- data: "string";
13
- epoch: "number";
14
- connected: "boolean";
15
- avatarUrl: "string";
16
- }>>, typeof _colyseus_schema.Schema>;
5
+ name: _colyseus_schema.FieldBuilder<string, true, false>;
6
+ data: _colyseus_schema.FieldBuilder<string, true, false>;
7
+ epoch: _colyseus_schema.FieldBuilder<number, true, false>;
8
+ connected: _colyseus_schema.FieldBuilder<boolean, true, false>;
9
+ avatarUrl: _colyseus_schema.FieldBuilder<string, true, false>;
10
+ uid: _colyseus_schema.FieldBuilder<string, true, false>;
11
+ team: _colyseus_schema.FieldBuilder<number, true, false>;
12
+ x: _colyseus_schema.FieldBuilder<number, true, false>;
13
+ y: _colyseus_schema.FieldBuilder<number, true, false>;
14
+ z: _colyseus_schema.FieldBuilder<number, true, false>;
15
+ yaw: _colyseus_schema.FieldBuilder<number, true, false>;
16
+ vx: _colyseus_schema.FieldBuilder<number, true, false>;
17
+ vy: _colyseus_schema.FieldBuilder<number, true, false>;
18
+ vz: _colyseus_schema.FieldBuilder<number, true, false>;
19
+ anim: _colyseus_schema.FieldBuilder<string, true, false>;
20
+ poseT: _colyseus_schema.FieldBuilder<number, true, false>;
21
+ posed: _colyseus_schema.FieldBuilder<boolean, true, false>;
22
+ }, _colyseus_schema.BuilderInitProps<{
23
+ name: _colyseus_schema.FieldBuilder<string, true, false>;
24
+ data: _colyseus_schema.FieldBuilder<string, true, false>;
25
+ epoch: _colyseus_schema.FieldBuilder<number, true, false>;
26
+ connected: _colyseus_schema.FieldBuilder<boolean, true, false>;
27
+ avatarUrl: _colyseus_schema.FieldBuilder<string, true, false>;
28
+ uid: _colyseus_schema.FieldBuilder<string, true, false>;
29
+ team: _colyseus_schema.FieldBuilder<number, true, false>;
30
+ x: _colyseus_schema.FieldBuilder<number, true, false>;
31
+ y: _colyseus_schema.FieldBuilder<number, true, false>;
32
+ z: _colyseus_schema.FieldBuilder<number, true, false>;
33
+ yaw: _colyseus_schema.FieldBuilder<number, true, false>;
34
+ vx: _colyseus_schema.FieldBuilder<number, true, false>;
35
+ vy: _colyseus_schema.FieldBuilder<number, true, false>;
36
+ vz: _colyseus_schema.FieldBuilder<number, true, false>;
37
+ anim: _colyseus_schema.FieldBuilder<string, true, false>;
38
+ poseT: _colyseus_schema.FieldBuilder<number, true, false>;
39
+ posed: _colyseus_schema.FieldBuilder<boolean, true, false>;
40
+ }>, typeof _colyseus_schema.Schema>;
17
41
  type PlayerState = SchemaType<typeof PlayerState>;
42
+ declare const ObjectState: _colyseus_schema.SchemaWithExtendsConstructor<{
43
+ owner: _colyseus_schema.FieldBuilder<string, true, false>;
44
+ seq: _colyseus_schema.FieldBuilder<number, true, false>;
45
+ epoch: _colyseus_schema.FieldBuilder<number, true, false>;
46
+ t: _colyseus_schema.FieldBuilder<number, true, false>;
47
+ d: _colyseus_schema.FieldBuilder<string, true, false>;
48
+ }, _colyseus_schema.BuilderInitProps<{
49
+ owner: _colyseus_schema.FieldBuilder<string, true, false>;
50
+ seq: _colyseus_schema.FieldBuilder<number, true, false>;
51
+ epoch: _colyseus_schema.FieldBuilder<number, true, false>;
52
+ t: _colyseus_schema.FieldBuilder<number, true, false>;
53
+ d: _colyseus_schema.FieldBuilder<string, true, false>;
54
+ }>, typeof _colyseus_schema.Schema>;
55
+ type ObjectState = SchemaType<typeof ObjectState>;
18
56
  declare const RoomState: _colyseus_schema.SchemaWithExtendsConstructor<{
19
- players: {
20
- map: _colyseus_schema.SchemaWithExtendsConstructor<{
21
- name: "string";
22
- data: "string";
23
- epoch: "number";
24
- connected: "boolean";
25
- avatarUrl: "string";
26
- }, _colyseus_schema.AssignableProps<_colyseus_schema.InferSchemaInstanceType<{
27
- name: "string";
28
- data: "string";
29
- epoch: "number";
30
- connected: "boolean";
31
- avatarUrl: "string";
32
- }>>, typeof _colyseus_schema.Schema>;
33
- default: MapSchema<_colyseus_schema.InferSchemaInstanceType<{
34
- name: "string";
35
- data: "string";
36
- epoch: "number";
37
- connected: "boolean";
38
- avatarUrl: "string";
39
- }>, string>;
40
- };
41
- shared: {
42
- map: "string";
43
- default: MapSchema<string, string>;
44
- };
45
- }, _colyseus_schema.AssignableProps<_colyseus_schema.InferSchemaInstanceType<{
46
- players: {
47
- map: _colyseus_schema.SchemaWithExtendsConstructor<{
48
- name: "string";
49
- data: "string";
50
- epoch: "number";
51
- connected: "boolean";
52
- avatarUrl: "string";
53
- }, _colyseus_schema.AssignableProps<_colyseus_schema.InferSchemaInstanceType<{
54
- name: "string";
55
- data: "string";
56
- epoch: "number";
57
- connected: "boolean";
58
- avatarUrl: "string";
59
- }>>, typeof _colyseus_schema.Schema>;
60
- default: MapSchema<_colyseus_schema.InferSchemaInstanceType<{
61
- name: "string";
62
- data: "string";
63
- epoch: "number";
64
- connected: "boolean";
65
- avatarUrl: "string";
66
- }>, string>;
67
- };
68
- shared: {
69
- map: "string";
70
- default: MapSchema<string, string>;
71
- };
72
- }>>, typeof _colyseus_schema.Schema>;
57
+ players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
58
+ name: string;
59
+ data: string;
60
+ epoch: number;
61
+ connected: boolean;
62
+ avatarUrl: string;
63
+ uid: string;
64
+ team: number;
65
+ x: number;
66
+ y: number;
67
+ z: number;
68
+ yaw: number;
69
+ vx: number;
70
+ vy: number;
71
+ vz: number;
72
+ anim: string;
73
+ poseT: number;
74
+ posed: boolean;
75
+ } & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
76
+ shared: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<string, string>, true, false>;
77
+ objects: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
78
+ owner: string;
79
+ seq: number;
80
+ epoch: number;
81
+ t: number;
82
+ d: string;
83
+ } & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
84
+ host: _colyseus_schema.FieldBuilder<string, true, false>;
85
+ match: _colyseus_schema.FieldBuilder<string, true, false>;
86
+ voice: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<boolean, string>, true, false>;
87
+ clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
88
+ }, _colyseus_schema.BuilderInitProps<{
89
+ players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
90
+ name: string;
91
+ data: string;
92
+ epoch: number;
93
+ connected: boolean;
94
+ avatarUrl: string;
95
+ uid: string;
96
+ team: number;
97
+ x: number;
98
+ y: number;
99
+ z: number;
100
+ yaw: number;
101
+ vx: number;
102
+ vy: number;
103
+ vz: number;
104
+ anim: string;
105
+ poseT: number;
106
+ posed: boolean;
107
+ } & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
108
+ shared: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<string, string>, true, false>;
109
+ objects: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
110
+ owner: string;
111
+ seq: number;
112
+ epoch: number;
113
+ t: number;
114
+ d: string;
115
+ } & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
116
+ host: _colyseus_schema.FieldBuilder<string, true, false>;
117
+ match: _colyseus_schema.FieldBuilder<string, true, false>;
118
+ voice: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<boolean, string>, true, false>;
119
+ clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
120
+ }>, typeof _colyseus_schema.Schema>;
73
121
  type RoomState = SchemaType<typeof RoomState>;
122
+ declare const HeartbeatInput: _colyseus_schema.SchemaWithExtendsConstructor<{
123
+ n: _colyseus_schema.FieldBuilder<number, true, false>;
124
+ }, _colyseus_schema.BuilderInitProps<{
125
+ n: _colyseus_schema.FieldBuilder<number, true, false>;
126
+ }>, typeof _colyseus_schema.Schema>;
127
+ type HeartbeatInput = SchemaType<typeof HeartbeatInput>;
74
128
 
75
- export { PlayerState, RoomState };
129
+ export { HeartbeatInput, ObjectState, PlayerState, RoomState };
package/dist/schema.js CHANGED
@@ -1,31 +1,110 @@
1
1
  // src/schema.ts
2
- import { schema, MapSchema } from "@colyseus/schema";
2
+ import { schema, t } from "@colyseus/schema";
3
3
  var PlayerState = schema(
4
4
  {
5
- name: "string",
6
- data: "string",
7
- // Relay-owned discontinuity epoch. Ordinary state updates keep it stable;
8
- // state:snap increments it so new SDKs discard interpolation history.
9
- epoch: "number",
10
- // Seat presence is distinct from connectivity: a dropped player keeps the
11
- // seat during reconnection grace but flips connected=false immediately.
12
- connected: "boolean",
13
- // The player's verified VRM avatar URL (AG-804) — set by the relay from the
14
- // embed token, never client-writable. '' = none (old API / empty library).
15
- // NEW FIELDS GO AFTER THIS ONE: @colyseus/schema keeps old clients decoding
16
- // only when fields are appended at the end, never inserted or reordered.
17
- avatarUrl: "string"
5
+ // Display name: the verified identity's name, else the `name` join option, ≤64 chars.
6
+ name: t.string().default(""),
7
+ // The player's own JSON object, replaced wholesale by `state` / `__state:snap` (≤16 KiB). Free
8
+ // form — the game decides what to sync. Carries `__t`, the sender's clock stamp in ms that
9
+ // remote interpolation runs on (PROTOCOL.md §10); SDKs strip it before a game sees the state.
10
+ data: t.string().default("{}"),
11
+ // Deliberate-discontinuity counter: `__state:snap` increments it in the same patch as the new
12
+ // data, so receivers drop interpolation history instead of easing across a teleport/respawn.
13
+ epoch: t.number().default(0),
14
+ // Transport liveness. False while the seat is held only by reconnection grace.
15
+ connected: t.boolean().default(true),
16
+ // Verified VRM avatar URL from the embed token (never a join option), ≤512 chars. '' = none.
17
+ avatarUrl: t.string().default(""),
18
+ // Stable per-game player id, stamped by the relay from the verified identity (PROTOCOL.md §3.3).
19
+ // The same person gets the same uid in this game across reloads, devices and rooms, and a
20
+ // different one in every other game. Opaque, ≤64 chars — key scores, colors and saves by it,
21
+ // never by the session id (which changes on every reload).
22
+ uid: t.string().default(""),
23
+ // Team index assigned by the relay: the open preset's `teams: N` (assigned at join, never
24
+ // reshuffled, remembered by uid) or the team preset's current round. -1 = no team.
25
+ team: t.number().default(-1),
26
+ // ---- Optional typed pose (PROTOCOL.md §6.6), appended in protocol 3. Written only from the
27
+ // seat's own `__pose` / `__pose:snap` messages. A game that never sends a pose leaves all of
28
+ // these at their defaults and keeps its whole state in `data`, exactly as before. Positions are
29
+ // plain float32 (never quantized: world sizes vary by orders of magnitude); the relay rounds
30
+ // with Math.fround before writing, so an unchanged float32 value never re-sends.
31
+ // Receivers interpolate x..vz (yaw along the shortest arc) and SNAP anim (§10.1).
32
+ x: t.float32().default(0),
33
+ y: t.float32().default(0),
34
+ z: t.float32().default(0),
35
+ // Heading in radians, any finite value; receivers wrap it (never lerp across ±π the long way).
36
+ yaw: t.float32().default(0),
37
+ // Velocity in world units per second: the sender's own, used for extrapolation past the newest
38
+ // sample. Not derived by the relay.
39
+ vx: t.float32().default(0),
40
+ vy: t.float32().default(0),
41
+ vz: t.float32().default(0),
42
+ // Current animation/state name (≤64 chars). Discrete: never interpolated. '' = none.
43
+ anim: t.string().default(""),
44
+ // The sender's clock stamp (ms, same clock as `__t`) of the pose above, written in the same
45
+ // patch as the pose. 0 = no pose published yet.
46
+ poseT: t.float64().default(0),
47
+ // True from this seat's first accepted pose until the seat is gone (a reconnect keeps it).
48
+ // While true, x..anim are this player's pose and `data` is snapped, not blended (§10.1).
49
+ posed: t.boolean().default(false)
18
50
  },
19
51
  "PlayerState"
20
52
  );
53
+ var ObjectState = schema(
54
+ {
55
+ // Owner session id, or '' when unowned (released, or its owner left an empty room).
56
+ owner: t.string().default(""),
57
+ // Ownership sequence: +1 on EVERY owner change (claim, release, orphan reassignment, host
58
+ // failover). Never changes on a state publish. Control results report it as `sequence`.
59
+ seq: t.number().default(0),
60
+ // Deliberate-discontinuity counter, incremented by `__object:snap` (a reset/teleport).
61
+ epoch: t.number().default(0),
62
+ // The CURRENT owner's send-clock stamp (ms) for `d`, preserved from the owner's message. The
63
+ // relay resets it to 0 on every owner change, so a nonzero `t` is always on the current owner's
64
+ // clock and 0 means "this `d` was not stamped by the current owner" (a handoff bridge pose).
65
+ t: t.float64().default(0),
66
+ // The object's JSON state object (≤64 KiB), as last published. '' until the first publish.
67
+ // Survives owner changes untouched. A plain field on purpose — never .patchOnly(), or a late
68
+ // joiner's full state would not carry it.
69
+ d: t.string().default("")
70
+ },
71
+ "ObjectState"
72
+ );
21
73
  var RoomState = schema(
22
74
  {
23
- players: { map: PlayerState, default: new MapSchema() },
24
- shared: { map: "string", default: new MapSchema() }
75
+ // Seated players by session id.
76
+ players: t.map(PlayerState),
77
+ // Game-writable room key -> JSON text (≤256 keys of ≤256 chars, values ≤64 KiB). Only game keys
78
+ // live here; the `__` key prefix is refused, and nothing the relay owns is mirrored into it.
79
+ shared: t.map("string"),
80
+ // Shared objects by id (≤128 per room).
81
+ objects: t.map(ObjectState),
82
+ // Session id of the elected host, or '' while the room has none.
83
+ host: t.string().default(""),
84
+ // Match rooms only: the match state as one JSON text (phase, players, teams, scores, cfg, …;
85
+ // PROTOCOL.md §9). '' in a plain play room. A single string until native decoders are shown to
86
+ // handle the nested team rosters a typed MatchState would need.
87
+ match: t.string().default(""),
88
+ // Voice roster: session id -> true for each participant (≤6). Membership is key presence;
89
+ // the value carries nothing. A map rather than a set — see the header.
90
+ voice: t.map("boolean"),
91
+ // The relay's wall clock (epoch ms) at room-clock zero: `clock.currentTime − clock.elapsedTime`,
92
+ // written once in onCreate and never again. Maps relay epoch stamps (match `startsAt`/`endsBy`,
93
+ // chat `at`) onto the room clock that TIMED frames carry: `serverClockMs = epochMs − clockOrigin`
94
+ // (PROTOCOL.md §16). 0 = the relay does not publish its clock.
95
+ clockOrigin: t.float64().default(0)
25
96
  },
26
97
  "RoomState"
27
98
  );
99
+ var HeartbeatInput = schema(
100
+ {
101
+ n: t.number().default(0)
102
+ },
103
+ "HeartbeatInput"
104
+ );
28
105
  export {
106
+ HeartbeatInput,
107
+ ObjectState,
29
108
  PlayerState,
30
109
  RoomState
31
110
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/multiplayer",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "The multiplayer client wrapper + shared room schema for genex.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,42 +15,59 @@
15
15
  "@genex-ai/source": "./src/schema.ts",
16
16
  "types": "./dist/schema.d.ts",
17
17
  "import": "./dist/schema.js"
18
- }
18
+ },
19
+ "./protocol": {
20
+ "@genex-ai/source": "./src/protocol.ts",
21
+ "types": "./dist/protocol.d.ts",
22
+ "import": "./dist/protocol.js"
23
+ },
24
+ "./bridge": {
25
+ "@genex-ai/source": "./src/bridge.ts",
26
+ "types": "./dist/bridge.d.ts",
27
+ "import": "./dist/bridge.js"
28
+ },
29
+ "./bridge.global.js": "./dist/bridge.global.js"
19
30
  },
20
31
  "files": [
21
- "dist"
32
+ "dist",
33
+ "PROTOCOL.md"
22
34
  ],
23
35
  "scripts": {
24
36
  "build": "tsup",
25
37
  "typecheck": "tsc --noEmit",
26
- "test": "node --test test/*.test.ts",
27
- "check": "pnpm build && publint && attw --pack . --profile esm-only",
38
+ "test": "node --conditions=@genex-ai/source --test test/*.test.ts",
39
+ "check": "pnpm build && publint && attw --pack . --profile esm-only --exclude-entrypoints ./bridge.global.js",
28
40
  "prepack": "pnpm build && publint"
29
41
  },
30
42
  "publishConfig": {
31
43
  "access": "public"
32
44
  },
33
45
  "dependencies": {
34
- "@colyseus/schema": "^4.0.27",
35
- "@colyseus/sdk": "^0.17.43"
46
+ "@colyseus/schema": "^5.0.40",
47
+ "@colyseus/sdk": "^0.18.5"
36
48
  },
37
49
  "peerDependencies": {
38
- "three": ">=0.160.0"
50
+ "three": ">=0.160.0",
51
+ "@genex-ai/embed-sdk": ">=0.33.0"
39
52
  },
40
53
  "peerDependenciesMeta": {
41
54
  "three": {
42
55
  "optional": true
56
+ },
57
+ "@genex-ai/embed-sdk": {
58
+ "optional": true
43
59
  }
44
60
  },
45
61
  "devDependencies": {
46
62
  "@arethetypeswrong/cli": "^0.18.0",
63
+ "@genex-ai/embed-sdk": "workspace:*",
47
64
  "publint": "^0.3.0",
48
65
  "tsup": "^8.0.0",
49
66
  "typescript": "^5.8.0"
50
67
  },
51
68
  "repository": {
52
- "type": "git",
53
- "url": "git+https://github.com/genex-games/genex.git"
69
+ "type": "git",
70
+ "url": "git+https://github.com/genex-games/genex.git"
54
71
  },
55
72
  "license": "MIT"
56
73
  }