@thegeem/protocol 0.1.1 → 0.1.3
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/index.cjs +19 -6
- package/dist/index.d.cts +87 -3
- package/dist/index.d.ts +87 -3
- package/dist/index.js +19 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,15 +52,25 @@ var HelpType = import_zod.z.enum([
|
|
|
52
52
|
]);
|
|
53
53
|
var Pv = import_zod.z.number().int().min(1).max(1e6).optional();
|
|
54
54
|
var IdToken = import_zod.z.string().max(4096).optional();
|
|
55
|
+
var Avatar = import_zod.z.object({
|
|
56
|
+
emoji: import_zod.z.string().min(1).max(16).transform((s) => s.replace(UNSAFE_CHARS, "")).refine((s) => s.length >= 1, "empty emoji"),
|
|
57
|
+
color: import_zod.z.string().regex(/^#[0-9a-fA-F]{6}$/, "color must be #rrggbb")
|
|
58
|
+
});
|
|
55
59
|
var ClientMsg = import_zod.z.discriminatedUnion("t", [
|
|
56
60
|
// room / lobby
|
|
57
|
-
import_zod.z.object({ t: import_zod.z.literal("createRoom"), name: DisplayName.optional(), pv: Pv, idToken: IdToken }),
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
import_zod.z.object({ t: import_zod.z.literal("createRoom"), name: DisplayName.optional(), avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
62
|
+
// Host sets/changes their display name AFTER createRoom (for anonymous one-tap
|
|
63
|
+
// hosts who started nameless). Host-only; the relay re-broadcasts the lobby.
|
|
64
|
+
import_zod.z.object({ t: import_zod.z.literal("renameHost"), name: DisplayName }),
|
|
65
|
+
import_zod.z.object({ t: import_zod.z.literal("joinRoom"), code: RoomCode, name: DisplayName, avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
66
|
+
import_zod.z.object({ t: import_zod.z.literal("resume"), code: RoomCode, token: import_zod.z.string().max(120), avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
60
67
|
import_zod.z.object({ t: import_zod.z.literal("leaveRoom") }),
|
|
61
68
|
import_zod.z.object({ t: import_zod.z.literal("approve"), playerId: PlayerId }),
|
|
62
69
|
import_zod.z.object({ t: import_zod.z.literal("reject"), playerId: PlayerId }),
|
|
63
70
|
import_zod.z.object({ t: import_zod.z.literal("kick"), playerId: PlayerId }),
|
|
71
|
+
// Host's IN-PROGRESS category selection in the lobby — a live preview for waiting
|
|
72
|
+
// players. Distinct from startGame.categoryIds, which COMMITS the board. Empty = cleared.
|
|
73
|
+
import_zod.z.object({ t: import_zod.z.literal("setCategories"), categoryIds: import_zod.z.array(import_zod.z.string().max(60)).max(12) }),
|
|
64
74
|
// host game actions
|
|
65
75
|
import_zod.z.object({
|
|
66
76
|
t: import_zod.z.literal("startGame"),
|
|
@@ -75,14 +85,17 @@ var ClientMsg = import_zod.z.discriminatedUnion("t", [
|
|
|
75
85
|
// host: after a game ends, return the SAME players to the lobby
|
|
76
86
|
import_zod.z.object({ t: import_zod.z.literal("markOpen"), correct: import_zod.z.boolean() }),
|
|
77
87
|
import_zod.z.object({ t: import_zod.z.literal("revealNoHost") }),
|
|
78
|
-
import_zod.z.object({ t: import_zod.z.literal("awardNoHost"), teamIndex: import_zod.z.number().int().min(0).max(LIMITS.MAX_PLAYERS) }),
|
|
88
|
+
import_zod.z.object({ t: import_zod.z.literal("awardNoHost"), teamIndex: import_zod.z.number().int().min(0).max(LIMITS.MAX_PLAYERS - 1) }),
|
|
89
|
+
// 0-based team index
|
|
79
90
|
import_zod.z.object({ t: import_zod.z.literal("noHostNobody") }),
|
|
80
91
|
// player actions
|
|
81
92
|
import_zod.z.object({ t: import_zod.z.literal("buzz") }),
|
|
82
|
-
import_zod.z.object({ t: import_zod.z.literal("answer"), index: import_zod.z.number().int().min(0).max(
|
|
93
|
+
import_zod.z.object({ t: import_zod.z.literal("answer"), index: import_zod.z.number().int().min(0).max(3) }),
|
|
94
|
+
// trivia is 4-option (0–3)
|
|
83
95
|
import_zod.z.object({ t: import_zod.z.literal("useHelp"), helpType: HelpType }),
|
|
84
96
|
// sabotage a rival (active team only): spend a sabotage help to debuff targetTeam's next question
|
|
85
|
-
import_zod.z.object({ t: import_zod.z.literal("sabotage"), helpType: HelpType, targetTeam: import_zod.z.number().int().min(0).max(LIMITS.MAX_PLAYERS) })
|
|
97
|
+
import_zod.z.object({ t: import_zod.z.literal("sabotage"), helpType: HelpType, targetTeam: import_zod.z.number().int().min(0).max(LIMITS.MAX_PLAYERS - 1) })
|
|
98
|
+
// 0-based team index
|
|
86
99
|
]);
|
|
87
100
|
// Annotate the CommonJS export names for ESM import in node:
|
|
88
101
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -43,52 +43,115 @@ declare const HelpType: z.ZodEnum<["removeTwoAnswers", "changeQuestion", "extraT
|
|
|
43
43
|
declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
44
44
|
t: z.ZodLiteral<"createRoom">;
|
|
45
45
|
name: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
46
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
47
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
48
|
+
color: z.ZodString;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
emoji: string;
|
|
51
|
+
color: string;
|
|
52
|
+
}, {
|
|
53
|
+
emoji: string;
|
|
54
|
+
color: string;
|
|
55
|
+
}>>;
|
|
46
56
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
47
57
|
idToken: z.ZodOptional<z.ZodString>;
|
|
48
58
|
}, "strip", z.ZodTypeAny, {
|
|
49
59
|
t: "createRoom";
|
|
50
60
|
name?: string | undefined;
|
|
61
|
+
avatar?: {
|
|
62
|
+
emoji: string;
|
|
63
|
+
color: string;
|
|
64
|
+
} | undefined;
|
|
51
65
|
pv?: number | undefined;
|
|
52
66
|
idToken?: string | undefined;
|
|
53
67
|
}, {
|
|
54
68
|
t: "createRoom";
|
|
55
69
|
name?: string | undefined;
|
|
70
|
+
avatar?: {
|
|
71
|
+
emoji: string;
|
|
72
|
+
color: string;
|
|
73
|
+
} | undefined;
|
|
56
74
|
pv?: number | undefined;
|
|
57
75
|
idToken?: string | undefined;
|
|
76
|
+
}>, z.ZodObject<{
|
|
77
|
+
t: z.ZodLiteral<"renameHost">;
|
|
78
|
+
name: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
79
|
+
}, "strip", z.ZodTypeAny, {
|
|
80
|
+
t: "renameHost";
|
|
81
|
+
name: string;
|
|
82
|
+
}, {
|
|
83
|
+
t: "renameHost";
|
|
84
|
+
name: string;
|
|
58
85
|
}>, z.ZodObject<{
|
|
59
86
|
t: z.ZodLiteral<"joinRoom">;
|
|
60
87
|
code: z.ZodString;
|
|
61
88
|
name: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
89
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
91
|
+
color: z.ZodString;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
emoji: string;
|
|
94
|
+
color: string;
|
|
95
|
+
}, {
|
|
96
|
+
emoji: string;
|
|
97
|
+
color: string;
|
|
98
|
+
}>>;
|
|
62
99
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
63
100
|
idToken: z.ZodOptional<z.ZodString>;
|
|
64
101
|
}, "strip", z.ZodTypeAny, {
|
|
65
102
|
code: string;
|
|
66
103
|
t: "joinRoom";
|
|
67
104
|
name: string;
|
|
105
|
+
avatar?: {
|
|
106
|
+
emoji: string;
|
|
107
|
+
color: string;
|
|
108
|
+
} | undefined;
|
|
68
109
|
pv?: number | undefined;
|
|
69
110
|
idToken?: string | undefined;
|
|
70
111
|
}, {
|
|
71
112
|
code: string;
|
|
72
113
|
t: "joinRoom";
|
|
73
114
|
name: string;
|
|
115
|
+
avatar?: {
|
|
116
|
+
emoji: string;
|
|
117
|
+
color: string;
|
|
118
|
+
} | undefined;
|
|
74
119
|
pv?: number | undefined;
|
|
75
120
|
idToken?: string | undefined;
|
|
76
121
|
}>, z.ZodObject<{
|
|
77
122
|
t: z.ZodLiteral<"resume">;
|
|
78
123
|
code: z.ZodString;
|
|
79
124
|
token: z.ZodString;
|
|
125
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
126
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
127
|
+
color: z.ZodString;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
emoji: string;
|
|
130
|
+
color: string;
|
|
131
|
+
}, {
|
|
132
|
+
emoji: string;
|
|
133
|
+
color: string;
|
|
134
|
+
}>>;
|
|
80
135
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
81
136
|
idToken: z.ZodOptional<z.ZodString>;
|
|
82
137
|
}, "strip", z.ZodTypeAny, {
|
|
83
138
|
code: string;
|
|
84
139
|
t: "resume";
|
|
85
140
|
token: string;
|
|
141
|
+
avatar?: {
|
|
142
|
+
emoji: string;
|
|
143
|
+
color: string;
|
|
144
|
+
} | undefined;
|
|
86
145
|
pv?: number | undefined;
|
|
87
146
|
idToken?: string | undefined;
|
|
88
147
|
}, {
|
|
89
148
|
code: string;
|
|
90
149
|
t: "resume";
|
|
91
150
|
token: string;
|
|
151
|
+
avatar?: {
|
|
152
|
+
emoji: string;
|
|
153
|
+
color: string;
|
|
154
|
+
} | undefined;
|
|
92
155
|
pv?: number | undefined;
|
|
93
156
|
idToken?: string | undefined;
|
|
94
157
|
}>, z.ZodObject<{
|
|
@@ -124,6 +187,15 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
124
187
|
}, {
|
|
125
188
|
t: "kick";
|
|
126
189
|
playerId: string;
|
|
190
|
+
}>, z.ZodObject<{
|
|
191
|
+
t: z.ZodLiteral<"setCategories">;
|
|
192
|
+
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
193
|
+
}, "strip", z.ZodTypeAny, {
|
|
194
|
+
t: "setCategories";
|
|
195
|
+
categoryIds: string[];
|
|
196
|
+
}, {
|
|
197
|
+
t: "setCategories";
|
|
198
|
+
categoryIds: string[];
|
|
127
199
|
}>, z.ZodObject<{
|
|
128
200
|
t: z.ZodLiteral<"startGame">;
|
|
129
201
|
game: z.ZodOptional<z.ZodEnum<["trivia"]>>;
|
|
@@ -131,13 +203,13 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
131
203
|
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
132
204
|
}, "strip", z.ZodTypeAny, {
|
|
133
205
|
t: "startGame";
|
|
134
|
-
totalRounds: number;
|
|
135
206
|
categoryIds: string[];
|
|
207
|
+
totalRounds: number;
|
|
136
208
|
game?: "trivia" | undefined;
|
|
137
209
|
}, {
|
|
138
210
|
t: "startGame";
|
|
139
|
-
totalRounds: number;
|
|
140
211
|
categoryIds: string[];
|
|
212
|
+
totalRounds: number;
|
|
141
213
|
game?: "trivia" | undefined;
|
|
142
214
|
}>, z.ZodObject<{
|
|
143
215
|
t: z.ZodLiteral<"pickLevel">;
|
|
@@ -231,11 +303,20 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
231
303
|
targetTeam: number;
|
|
232
304
|
}>]>;
|
|
233
305
|
type ClientMsg = z.infer<typeof ClientMsg>;
|
|
306
|
+
/** A player's privacy-safe avatar (emoji + circle color) for in-room display. */
|
|
307
|
+
interface AvatarView {
|
|
308
|
+
emoji: string;
|
|
309
|
+
color: string;
|
|
310
|
+
}
|
|
234
311
|
interface LobbyPlayer {
|
|
235
312
|
id: string;
|
|
236
313
|
name: string;
|
|
237
314
|
approved: boolean;
|
|
238
315
|
connected: boolean;
|
|
316
|
+
/** Privacy-safe avatar (emoji + color); absent if the player didn't set one. */
|
|
317
|
+
avatar?: AvatarView;
|
|
318
|
+
/** Team index once the game has started; null/absent in the lobby. */
|
|
319
|
+
teamIndex?: number | null;
|
|
239
320
|
}
|
|
240
321
|
/** Per-recipient context attached to lobby/state pushes. */
|
|
241
322
|
interface YouContext {
|
|
@@ -271,6 +352,8 @@ interface TeamView {
|
|
|
271
352
|
type: HelpName;
|
|
272
353
|
isUsed: boolean;
|
|
273
354
|
}[];
|
|
355
|
+
/** The seated player's privacy-safe avatar (relay-enriched; engine view omits it). */
|
|
356
|
+
avatar?: AvatarView;
|
|
274
357
|
}
|
|
275
358
|
interface QuestionView {
|
|
276
359
|
text: string;
|
|
@@ -381,6 +464,7 @@ type ServerMsg = {
|
|
|
381
464
|
hostName: string;
|
|
382
465
|
players: LobbyPlayer[];
|
|
383
466
|
categories: CategoryView[];
|
|
467
|
+
selectedCategoryIds: string[];
|
|
384
468
|
you: YouContext;
|
|
385
469
|
} | {
|
|
386
470
|
t: 'state';
|
|
@@ -397,4 +481,4 @@ type ServerMsg = {
|
|
|
397
481
|
message: string;
|
|
398
482
|
};
|
|
399
483
|
|
|
400
|
-
export { type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAME_IDS, type GameId, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamView, type YouContext };
|
|
484
|
+
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAME_IDS, type GameId, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamView, type YouContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -43,52 +43,115 @@ declare const HelpType: z.ZodEnum<["removeTwoAnswers", "changeQuestion", "extraT
|
|
|
43
43
|
declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
44
44
|
t: z.ZodLiteral<"createRoom">;
|
|
45
45
|
name: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
46
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
47
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
48
|
+
color: z.ZodString;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
emoji: string;
|
|
51
|
+
color: string;
|
|
52
|
+
}, {
|
|
53
|
+
emoji: string;
|
|
54
|
+
color: string;
|
|
55
|
+
}>>;
|
|
46
56
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
47
57
|
idToken: z.ZodOptional<z.ZodString>;
|
|
48
58
|
}, "strip", z.ZodTypeAny, {
|
|
49
59
|
t: "createRoom";
|
|
50
60
|
name?: string | undefined;
|
|
61
|
+
avatar?: {
|
|
62
|
+
emoji: string;
|
|
63
|
+
color: string;
|
|
64
|
+
} | undefined;
|
|
51
65
|
pv?: number | undefined;
|
|
52
66
|
idToken?: string | undefined;
|
|
53
67
|
}, {
|
|
54
68
|
t: "createRoom";
|
|
55
69
|
name?: string | undefined;
|
|
70
|
+
avatar?: {
|
|
71
|
+
emoji: string;
|
|
72
|
+
color: string;
|
|
73
|
+
} | undefined;
|
|
56
74
|
pv?: number | undefined;
|
|
57
75
|
idToken?: string | undefined;
|
|
76
|
+
}>, z.ZodObject<{
|
|
77
|
+
t: z.ZodLiteral<"renameHost">;
|
|
78
|
+
name: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
79
|
+
}, "strip", z.ZodTypeAny, {
|
|
80
|
+
t: "renameHost";
|
|
81
|
+
name: string;
|
|
82
|
+
}, {
|
|
83
|
+
t: "renameHost";
|
|
84
|
+
name: string;
|
|
58
85
|
}>, z.ZodObject<{
|
|
59
86
|
t: z.ZodLiteral<"joinRoom">;
|
|
60
87
|
code: z.ZodString;
|
|
61
88
|
name: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
89
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
91
|
+
color: z.ZodString;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
emoji: string;
|
|
94
|
+
color: string;
|
|
95
|
+
}, {
|
|
96
|
+
emoji: string;
|
|
97
|
+
color: string;
|
|
98
|
+
}>>;
|
|
62
99
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
63
100
|
idToken: z.ZodOptional<z.ZodString>;
|
|
64
101
|
}, "strip", z.ZodTypeAny, {
|
|
65
102
|
code: string;
|
|
66
103
|
t: "joinRoom";
|
|
67
104
|
name: string;
|
|
105
|
+
avatar?: {
|
|
106
|
+
emoji: string;
|
|
107
|
+
color: string;
|
|
108
|
+
} | undefined;
|
|
68
109
|
pv?: number | undefined;
|
|
69
110
|
idToken?: string | undefined;
|
|
70
111
|
}, {
|
|
71
112
|
code: string;
|
|
72
113
|
t: "joinRoom";
|
|
73
114
|
name: string;
|
|
115
|
+
avatar?: {
|
|
116
|
+
emoji: string;
|
|
117
|
+
color: string;
|
|
118
|
+
} | undefined;
|
|
74
119
|
pv?: number | undefined;
|
|
75
120
|
idToken?: string | undefined;
|
|
76
121
|
}>, z.ZodObject<{
|
|
77
122
|
t: z.ZodLiteral<"resume">;
|
|
78
123
|
code: z.ZodString;
|
|
79
124
|
token: z.ZodString;
|
|
125
|
+
avatar: z.ZodOptional<z.ZodObject<{
|
|
126
|
+
emoji: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
127
|
+
color: z.ZodString;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
emoji: string;
|
|
130
|
+
color: string;
|
|
131
|
+
}, {
|
|
132
|
+
emoji: string;
|
|
133
|
+
color: string;
|
|
134
|
+
}>>;
|
|
80
135
|
pv: z.ZodOptional<z.ZodNumber>;
|
|
81
136
|
idToken: z.ZodOptional<z.ZodString>;
|
|
82
137
|
}, "strip", z.ZodTypeAny, {
|
|
83
138
|
code: string;
|
|
84
139
|
t: "resume";
|
|
85
140
|
token: string;
|
|
141
|
+
avatar?: {
|
|
142
|
+
emoji: string;
|
|
143
|
+
color: string;
|
|
144
|
+
} | undefined;
|
|
86
145
|
pv?: number | undefined;
|
|
87
146
|
idToken?: string | undefined;
|
|
88
147
|
}, {
|
|
89
148
|
code: string;
|
|
90
149
|
t: "resume";
|
|
91
150
|
token: string;
|
|
151
|
+
avatar?: {
|
|
152
|
+
emoji: string;
|
|
153
|
+
color: string;
|
|
154
|
+
} | undefined;
|
|
92
155
|
pv?: number | undefined;
|
|
93
156
|
idToken?: string | undefined;
|
|
94
157
|
}>, z.ZodObject<{
|
|
@@ -124,6 +187,15 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
124
187
|
}, {
|
|
125
188
|
t: "kick";
|
|
126
189
|
playerId: string;
|
|
190
|
+
}>, z.ZodObject<{
|
|
191
|
+
t: z.ZodLiteral<"setCategories">;
|
|
192
|
+
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
193
|
+
}, "strip", z.ZodTypeAny, {
|
|
194
|
+
t: "setCategories";
|
|
195
|
+
categoryIds: string[];
|
|
196
|
+
}, {
|
|
197
|
+
t: "setCategories";
|
|
198
|
+
categoryIds: string[];
|
|
127
199
|
}>, z.ZodObject<{
|
|
128
200
|
t: z.ZodLiteral<"startGame">;
|
|
129
201
|
game: z.ZodOptional<z.ZodEnum<["trivia"]>>;
|
|
@@ -131,13 +203,13 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
131
203
|
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
132
204
|
}, "strip", z.ZodTypeAny, {
|
|
133
205
|
t: "startGame";
|
|
134
|
-
totalRounds: number;
|
|
135
206
|
categoryIds: string[];
|
|
207
|
+
totalRounds: number;
|
|
136
208
|
game?: "trivia" | undefined;
|
|
137
209
|
}, {
|
|
138
210
|
t: "startGame";
|
|
139
|
-
totalRounds: number;
|
|
140
211
|
categoryIds: string[];
|
|
212
|
+
totalRounds: number;
|
|
141
213
|
game?: "trivia" | undefined;
|
|
142
214
|
}>, z.ZodObject<{
|
|
143
215
|
t: z.ZodLiteral<"pickLevel">;
|
|
@@ -231,11 +303,20 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
231
303
|
targetTeam: number;
|
|
232
304
|
}>]>;
|
|
233
305
|
type ClientMsg = z.infer<typeof ClientMsg>;
|
|
306
|
+
/** A player's privacy-safe avatar (emoji + circle color) for in-room display. */
|
|
307
|
+
interface AvatarView {
|
|
308
|
+
emoji: string;
|
|
309
|
+
color: string;
|
|
310
|
+
}
|
|
234
311
|
interface LobbyPlayer {
|
|
235
312
|
id: string;
|
|
236
313
|
name: string;
|
|
237
314
|
approved: boolean;
|
|
238
315
|
connected: boolean;
|
|
316
|
+
/** Privacy-safe avatar (emoji + color); absent if the player didn't set one. */
|
|
317
|
+
avatar?: AvatarView;
|
|
318
|
+
/** Team index once the game has started; null/absent in the lobby. */
|
|
319
|
+
teamIndex?: number | null;
|
|
239
320
|
}
|
|
240
321
|
/** Per-recipient context attached to lobby/state pushes. */
|
|
241
322
|
interface YouContext {
|
|
@@ -271,6 +352,8 @@ interface TeamView {
|
|
|
271
352
|
type: HelpName;
|
|
272
353
|
isUsed: boolean;
|
|
273
354
|
}[];
|
|
355
|
+
/** The seated player's privacy-safe avatar (relay-enriched; engine view omits it). */
|
|
356
|
+
avatar?: AvatarView;
|
|
274
357
|
}
|
|
275
358
|
interface QuestionView {
|
|
276
359
|
text: string;
|
|
@@ -381,6 +464,7 @@ type ServerMsg = {
|
|
|
381
464
|
hostName: string;
|
|
382
465
|
players: LobbyPlayer[];
|
|
383
466
|
categories: CategoryView[];
|
|
467
|
+
selectedCategoryIds: string[];
|
|
384
468
|
you: YouContext;
|
|
385
469
|
} | {
|
|
386
470
|
t: 'state';
|
|
@@ -397,4 +481,4 @@ type ServerMsg = {
|
|
|
397
481
|
message: string;
|
|
398
482
|
};
|
|
399
483
|
|
|
400
|
-
export { type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAME_IDS, type GameId, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamView, type YouContext };
|
|
484
|
+
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAME_IDS, type GameId, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamView, type YouContext };
|
package/dist/index.js
CHANGED
|
@@ -24,15 +24,25 @@ var HelpType = z.enum([
|
|
|
24
24
|
]);
|
|
25
25
|
var Pv = z.number().int().min(1).max(1e6).optional();
|
|
26
26
|
var IdToken = z.string().max(4096).optional();
|
|
27
|
+
var Avatar = z.object({
|
|
28
|
+
emoji: z.string().min(1).max(16).transform((s) => s.replace(UNSAFE_CHARS, "")).refine((s) => s.length >= 1, "empty emoji"),
|
|
29
|
+
color: z.string().regex(/^#[0-9a-fA-F]{6}$/, "color must be #rrggbb")
|
|
30
|
+
});
|
|
27
31
|
var ClientMsg = z.discriminatedUnion("t", [
|
|
28
32
|
// room / lobby
|
|
29
|
-
z.object({ t: z.literal("createRoom"), name: DisplayName.optional(), pv: Pv, idToken: IdToken }),
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
z.object({ t: z.literal("createRoom"), name: DisplayName.optional(), avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
34
|
+
// Host sets/changes their display name AFTER createRoom (for anonymous one-tap
|
|
35
|
+
// hosts who started nameless). Host-only; the relay re-broadcasts the lobby.
|
|
36
|
+
z.object({ t: z.literal("renameHost"), name: DisplayName }),
|
|
37
|
+
z.object({ t: z.literal("joinRoom"), code: RoomCode, name: DisplayName, avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
38
|
+
z.object({ t: z.literal("resume"), code: RoomCode, token: z.string().max(120), avatar: Avatar.optional(), pv: Pv, idToken: IdToken }),
|
|
32
39
|
z.object({ t: z.literal("leaveRoom") }),
|
|
33
40
|
z.object({ t: z.literal("approve"), playerId: PlayerId }),
|
|
34
41
|
z.object({ t: z.literal("reject"), playerId: PlayerId }),
|
|
35
42
|
z.object({ t: z.literal("kick"), playerId: PlayerId }),
|
|
43
|
+
// Host's IN-PROGRESS category selection in the lobby — a live preview for waiting
|
|
44
|
+
// players. Distinct from startGame.categoryIds, which COMMITS the board. Empty = cleared.
|
|
45
|
+
z.object({ t: z.literal("setCategories"), categoryIds: z.array(z.string().max(60)).max(12) }),
|
|
36
46
|
// host game actions
|
|
37
47
|
z.object({
|
|
38
48
|
t: z.literal("startGame"),
|
|
@@ -47,14 +57,17 @@ var ClientMsg = z.discriminatedUnion("t", [
|
|
|
47
57
|
// host: after a game ends, return the SAME players to the lobby
|
|
48
58
|
z.object({ t: z.literal("markOpen"), correct: z.boolean() }),
|
|
49
59
|
z.object({ t: z.literal("revealNoHost") }),
|
|
50
|
-
z.object({ t: z.literal("awardNoHost"), teamIndex: z.number().int().min(0).max(LIMITS.MAX_PLAYERS) }),
|
|
60
|
+
z.object({ t: z.literal("awardNoHost"), teamIndex: z.number().int().min(0).max(LIMITS.MAX_PLAYERS - 1) }),
|
|
61
|
+
// 0-based team index
|
|
51
62
|
z.object({ t: z.literal("noHostNobody") }),
|
|
52
63
|
// player actions
|
|
53
64
|
z.object({ t: z.literal("buzz") }),
|
|
54
|
-
z.object({ t: z.literal("answer"), index: z.number().int().min(0).max(
|
|
65
|
+
z.object({ t: z.literal("answer"), index: z.number().int().min(0).max(3) }),
|
|
66
|
+
// trivia is 4-option (0–3)
|
|
55
67
|
z.object({ t: z.literal("useHelp"), helpType: HelpType }),
|
|
56
68
|
// sabotage a rival (active team only): spend a sabotage help to debuff targetTeam's next question
|
|
57
|
-
z.object({ t: z.literal("sabotage"), helpType: HelpType, targetTeam: z.number().int().min(0).max(LIMITS.MAX_PLAYERS) })
|
|
69
|
+
z.object({ t: z.literal("sabotage"), helpType: HelpType, targetTeam: z.number().int().min(0).max(LIMITS.MAX_PLAYERS - 1) })
|
|
70
|
+
// 0-based team index
|
|
58
71
|
]);
|
|
59
72
|
export {
|
|
60
73
|
ClientMsg,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thegeem/protocol",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Geem's wire protocol — shared zod schemas + TypeScript types for talking to the Geem game server over Socket.IO. The source of truth all clients implement against.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://geem.tv",
|