@thegeem/protocol 0.1.17 → 0.1.18
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 -4
- package/dist/index.d.cts +107 -6
- package/dist/index.d.ts +107 -6
- package/dist/index.js +19 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -41,12 +41,14 @@ var LIMITS = {
|
|
|
41
41
|
MAX_PLAYERS: 12,
|
|
42
42
|
MAX_MSG_PER_SEC: 8
|
|
43
43
|
};
|
|
44
|
-
var PROTOCOL_VERSION =
|
|
44
|
+
var PROTOCOL_VERSION = 3;
|
|
45
45
|
var MIN_SUPPORTED_PV = 1;
|
|
46
|
-
var GAME_IDS = ["seedha", "snag", "trivia"];
|
|
46
|
+
var GAME_IDS = ["seedha", "snag", "trivia", "dama"];
|
|
47
47
|
var GAMES = [
|
|
48
48
|
{ id: "seedha", label: "Seedha", minPv: 2 },
|
|
49
49
|
{ id: "snag", label: "Snag", minPv: 2 },
|
|
50
|
+
{ id: "dama", label: "Dama", minPv: 3 },
|
|
51
|
+
// engine #2 (D-027) — offered only to pv≥3 clients
|
|
50
52
|
{ id: "trivia", label: "Trivia", minPv: 1, deprecated: true }
|
|
51
53
|
];
|
|
52
54
|
var gamesForPv = (pv) => GAMES.filter((g) => !g.deprecated && g.minPv <= pv);
|
|
@@ -116,7 +118,8 @@ var ClientMsg = import_zod.z.discriminatedUnion("t", [
|
|
|
116
118
|
game: import_zod.z.enum(GAME_IDS).optional(),
|
|
117
119
|
// which game to play; defaults to 'trivia'
|
|
118
120
|
totalRounds: import_zod.z.number().int().min(1).max(50),
|
|
119
|
-
categoryIds: import_zod.z.array(import_zod.z.string().max(60)).min(
|
|
121
|
+
categoryIds: import_zod.z.array(import_zod.z.string().max(60)).min(0).max(12),
|
|
122
|
+
// empty for games without categories (Dama); trivia rejects empty in-handler
|
|
120
123
|
// PREFERRED: pick a mode from the registry (see MODES). The server maps it to the engine
|
|
121
124
|
// rules. Send this and omit buzzerMode/noHost. Falls back to the legacy flags below if omitted.
|
|
122
125
|
modeId: import_zod.z.enum(MODE_IDS).optional(),
|
|
@@ -153,7 +156,19 @@ var ClientMsg = import_zod.z.discriminatedUnion("t", [
|
|
|
153
156
|
// Report the CURRENT question as bad (wrong answer / typo / offensive). The relay resolves WHICH
|
|
154
157
|
// question from its authoritative room state — the client never sees the question id (anti-cheat),
|
|
155
158
|
// so it only sends an optional `reason`. Only meaningful while a question is on screen.
|
|
156
|
-
import_zod.z.object({ t: import_zod.z.literal("reportQuestion"), reason: import_zod.z.string().max(500).optional() })
|
|
159
|
+
import_zod.z.object({ t: import_zod.z.literal("reportQuestion"), reason: import_zod.z.string().max(500).optional() }),
|
|
160
|
+
// ── Dama slice (gameId 'dama', engine #2 — D-027) ──
|
|
161
|
+
// Make a Dama move: from → to (board coords, 0–7). The relay validates legality against the engine
|
|
162
|
+
// (Shape B) and rejects anything not in legalMoves. If two capture chains share from+to (rare), the
|
|
163
|
+
// relay picks the max-capture one; a client MAY send the full landing `path` to disambiguate.
|
|
164
|
+
import_zod.z.object({
|
|
165
|
+
t: import_zod.z.literal("damaMove"),
|
|
166
|
+
from: import_zod.z.object({ r: import_zod.z.number().int().min(0).max(7), c: import_zod.z.number().int().min(0).max(7) }),
|
|
167
|
+
to: import_zod.z.object({ r: import_zod.z.number().int().min(0).max(7), c: import_zod.z.number().int().min(0).max(7) }),
|
|
168
|
+
path: import_zod.z.array(import_zod.z.object({ r: import_zod.z.number().int().min(0).max(7), c: import_zod.z.number().int().min(0).max(7) })).max(12).optional()
|
|
169
|
+
}),
|
|
170
|
+
// Resign the current Dama game (concede) → opponent wins.
|
|
171
|
+
import_zod.z.object({ t: import_zod.z.literal("damaResign") })
|
|
157
172
|
]);
|
|
158
173
|
// Annotate the CommonJS export names for ESM import in node:
|
|
159
174
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -33,7 +33,7 @@ declare const LIMITS: {
|
|
|
33
33
|
* `seedha`/`snag`). Raise the floor SLOWLY to retire ancient builds. Unversioned clients (no `pv`,
|
|
34
34
|
* e.g. the legacy web harness) are treated as the floor and never rejected.
|
|
35
35
|
*/
|
|
36
|
-
declare const PROTOCOL_VERSION =
|
|
36
|
+
declare const PROTOCOL_VERSION = 3;
|
|
37
37
|
declare const MIN_SUPPORTED_PV = 1;
|
|
38
38
|
/**
|
|
39
39
|
* Geem is a PLATFORM of GAMES (jackbox-style). The trivia board split (D-023) into TWO player-facing
|
|
@@ -42,7 +42,7 @@ declare const MIN_SUPPORTED_PV = 1;
|
|
|
42
42
|
* pre-pv2 clients (they never saw seedha/snag), and what old clients send on startGame. Every room
|
|
43
43
|
* runs one game, identified by `gameId`.
|
|
44
44
|
*/
|
|
45
|
-
declare const GAME_IDS: readonly ["seedha", "snag", "trivia"];
|
|
45
|
+
declare const GAME_IDS: readonly ["seedha", "snag", "trivia", "dama"];
|
|
46
46
|
type GameId = (typeof GAME_IDS)[number];
|
|
47
47
|
/**
|
|
48
48
|
* The GAME REGISTRY — player-facing games + the version gating (D-024/D-025). A client renders a tile
|
|
@@ -286,7 +286,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
286
286
|
activity: "configuring" | "idle";
|
|
287
287
|
}>, z.ZodObject<{
|
|
288
288
|
t: z.ZodLiteral<"startGame">;
|
|
289
|
-
game: z.ZodOptional<z.ZodEnum<["seedha", "snag", "trivia"]>>;
|
|
289
|
+
game: z.ZodOptional<z.ZodEnum<["seedha", "snag", "trivia", "dama"]>>;
|
|
290
290
|
totalRounds: z.ZodNumber;
|
|
291
291
|
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
292
292
|
modeId: z.ZodOptional<z.ZodEnum<["solo", "oneDevice", "snag", "multiplayer"]>>;
|
|
@@ -297,7 +297,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
297
297
|
categoryIds: string[];
|
|
298
298
|
totalRounds: number;
|
|
299
299
|
modeId?: "snag" | "solo" | "oneDevice" | "multiplayer" | undefined;
|
|
300
|
-
game?: "seedha" | "snag" | "trivia" | undefined;
|
|
300
|
+
game?: "seedha" | "snag" | "trivia" | "dama" | undefined;
|
|
301
301
|
buzzerMode?: "solo" | "off" | "race" | "controller" | undefined;
|
|
302
302
|
noHost?: boolean | undefined;
|
|
303
303
|
}, {
|
|
@@ -305,7 +305,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
305
305
|
categoryIds: string[];
|
|
306
306
|
totalRounds: number;
|
|
307
307
|
modeId?: "snag" | "solo" | "oneDevice" | "multiplayer" | undefined;
|
|
308
|
-
game?: "seedha" | "snag" | "trivia" | undefined;
|
|
308
|
+
game?: "seedha" | "snag" | "trivia" | "dama" | undefined;
|
|
309
309
|
buzzerMode?: "solo" | "off" | "race" | "controller" | undefined;
|
|
310
310
|
noHost?: boolean | undefined;
|
|
311
311
|
}>, z.ZodObject<{
|
|
@@ -419,6 +419,72 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
419
419
|
}, {
|
|
420
420
|
t: "reportQuestion";
|
|
421
421
|
reason?: string | undefined;
|
|
422
|
+
}>, z.ZodObject<{
|
|
423
|
+
t: z.ZodLiteral<"damaMove">;
|
|
424
|
+
from: z.ZodObject<{
|
|
425
|
+
r: z.ZodNumber;
|
|
426
|
+
c: z.ZodNumber;
|
|
427
|
+
}, "strip", z.ZodTypeAny, {
|
|
428
|
+
r: number;
|
|
429
|
+
c: number;
|
|
430
|
+
}, {
|
|
431
|
+
r: number;
|
|
432
|
+
c: number;
|
|
433
|
+
}>;
|
|
434
|
+
to: z.ZodObject<{
|
|
435
|
+
r: z.ZodNumber;
|
|
436
|
+
c: z.ZodNumber;
|
|
437
|
+
}, "strip", z.ZodTypeAny, {
|
|
438
|
+
r: number;
|
|
439
|
+
c: number;
|
|
440
|
+
}, {
|
|
441
|
+
r: number;
|
|
442
|
+
c: number;
|
|
443
|
+
}>;
|
|
444
|
+
path: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
445
|
+
r: z.ZodNumber;
|
|
446
|
+
c: z.ZodNumber;
|
|
447
|
+
}, "strip", z.ZodTypeAny, {
|
|
448
|
+
r: number;
|
|
449
|
+
c: number;
|
|
450
|
+
}, {
|
|
451
|
+
r: number;
|
|
452
|
+
c: number;
|
|
453
|
+
}>, "many">>;
|
|
454
|
+
}, "strip", z.ZodTypeAny, {
|
|
455
|
+
t: "damaMove";
|
|
456
|
+
from: {
|
|
457
|
+
r: number;
|
|
458
|
+
c: number;
|
|
459
|
+
};
|
|
460
|
+
to: {
|
|
461
|
+
r: number;
|
|
462
|
+
c: number;
|
|
463
|
+
};
|
|
464
|
+
path?: {
|
|
465
|
+
r: number;
|
|
466
|
+
c: number;
|
|
467
|
+
}[] | undefined;
|
|
468
|
+
}, {
|
|
469
|
+
t: "damaMove";
|
|
470
|
+
from: {
|
|
471
|
+
r: number;
|
|
472
|
+
c: number;
|
|
473
|
+
};
|
|
474
|
+
to: {
|
|
475
|
+
r: number;
|
|
476
|
+
c: number;
|
|
477
|
+
};
|
|
478
|
+
path?: {
|
|
479
|
+
r: number;
|
|
480
|
+
c: number;
|
|
481
|
+
}[] | undefined;
|
|
482
|
+
}>, z.ZodObject<{
|
|
483
|
+
t: z.ZodLiteral<"damaResign">;
|
|
484
|
+
}, "strip", z.ZodTypeAny, {
|
|
485
|
+
t: "damaResign";
|
|
486
|
+
}, {
|
|
487
|
+
t: "damaResign";
|
|
422
488
|
}>]>;
|
|
423
489
|
type ClientMsg = z.infer<typeof ClientMsg>;
|
|
424
490
|
/** A player's privacy-safe avatar (emoji + circle color) for in-room display. */
|
|
@@ -574,6 +640,36 @@ type Effect = {
|
|
|
574
640
|
} | {
|
|
575
641
|
t: 'endGame';
|
|
576
642
|
};
|
|
643
|
+
/** A Dama piece as clients see it. */
|
|
644
|
+
interface DamaPieceView {
|
|
645
|
+
color: 'black' | 'white';
|
|
646
|
+
king: boolean;
|
|
647
|
+
}
|
|
648
|
+
/** A legal Dama move offered to the player to move (for highlighting). `captures` = pieces it takes. */
|
|
649
|
+
interface DamaMoveView {
|
|
650
|
+
from: {
|
|
651
|
+
r: number;
|
|
652
|
+
c: number;
|
|
653
|
+
};
|
|
654
|
+
to: {
|
|
655
|
+
r: number;
|
|
656
|
+
c: number;
|
|
657
|
+
};
|
|
658
|
+
captures: number;
|
|
659
|
+
path: {
|
|
660
|
+
r: number;
|
|
661
|
+
c: number;
|
|
662
|
+
}[];
|
|
663
|
+
}
|
|
664
|
+
/** The authoritative Dama board pushed to a client. `board[r][c]` is null on empty/light squares; r=0 is the top. */
|
|
665
|
+
interface DamaStateView {
|
|
666
|
+
board: (DamaPieceView | null)[][];
|
|
667
|
+
turn: 'black' | 'white';
|
|
668
|
+
winner: 'black' | 'white' | null;
|
|
669
|
+
yourColor: 'black' | 'white' | null;
|
|
670
|
+
legalMoves: DamaMoveView[];
|
|
671
|
+
moveCount: number;
|
|
672
|
+
}
|
|
577
673
|
type ServerMsg = {
|
|
578
674
|
t: 'roomCreated';
|
|
579
675
|
code: string;
|
|
@@ -618,6 +714,11 @@ type ServerMsg = {
|
|
|
618
714
|
view: GameStateView;
|
|
619
715
|
you: YouContext;
|
|
620
716
|
teamConnected: boolean[];
|
|
717
|
+
} | {
|
|
718
|
+
t: 'damaState';
|
|
719
|
+
gameId: 'dama';
|
|
720
|
+
view: DamaStateView;
|
|
721
|
+
you: YouContext;
|
|
621
722
|
} | {
|
|
622
723
|
t: 'fx';
|
|
623
724
|
effects: Effect[];
|
|
@@ -634,4 +735,4 @@ type ServerMsg = {
|
|
|
634
735
|
message: string;
|
|
635
736
|
};
|
|
636
737
|
|
|
637
|
-
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAMES, GAME_IDS, type GameId, type GameInfo, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, MIN_SUPPORTED_PV, MODES, MODE_IDS, type ModeId, type ModeInfo, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamSlotView, type TeamView, type YouContext, gameIdForPv, gamesForPv, modesForGame };
|
|
738
|
+
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type DamaMoveView, type DamaPieceView, type DamaStateView, type Effect, GAMES, GAME_IDS, type GameId, type GameInfo, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, MIN_SUPPORTED_PV, MODES, MODE_IDS, type ModeId, type ModeInfo, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamSlotView, type TeamView, type YouContext, gameIdForPv, gamesForPv, modesForGame };
|
package/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ declare const LIMITS: {
|
|
|
33
33
|
* `seedha`/`snag`). Raise the floor SLOWLY to retire ancient builds. Unversioned clients (no `pv`,
|
|
34
34
|
* e.g. the legacy web harness) are treated as the floor and never rejected.
|
|
35
35
|
*/
|
|
36
|
-
declare const PROTOCOL_VERSION =
|
|
36
|
+
declare const PROTOCOL_VERSION = 3;
|
|
37
37
|
declare const MIN_SUPPORTED_PV = 1;
|
|
38
38
|
/**
|
|
39
39
|
* Geem is a PLATFORM of GAMES (jackbox-style). The trivia board split (D-023) into TWO player-facing
|
|
@@ -42,7 +42,7 @@ declare const MIN_SUPPORTED_PV = 1;
|
|
|
42
42
|
* pre-pv2 clients (they never saw seedha/snag), and what old clients send on startGame. Every room
|
|
43
43
|
* runs one game, identified by `gameId`.
|
|
44
44
|
*/
|
|
45
|
-
declare const GAME_IDS: readonly ["seedha", "snag", "trivia"];
|
|
45
|
+
declare const GAME_IDS: readonly ["seedha", "snag", "trivia", "dama"];
|
|
46
46
|
type GameId = (typeof GAME_IDS)[number];
|
|
47
47
|
/**
|
|
48
48
|
* The GAME REGISTRY — player-facing games + the version gating (D-024/D-025). A client renders a tile
|
|
@@ -286,7 +286,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
286
286
|
activity: "configuring" | "idle";
|
|
287
287
|
}>, z.ZodObject<{
|
|
288
288
|
t: z.ZodLiteral<"startGame">;
|
|
289
|
-
game: z.ZodOptional<z.ZodEnum<["seedha", "snag", "trivia"]>>;
|
|
289
|
+
game: z.ZodOptional<z.ZodEnum<["seedha", "snag", "trivia", "dama"]>>;
|
|
290
290
|
totalRounds: z.ZodNumber;
|
|
291
291
|
categoryIds: z.ZodArray<z.ZodString, "many">;
|
|
292
292
|
modeId: z.ZodOptional<z.ZodEnum<["solo", "oneDevice", "snag", "multiplayer"]>>;
|
|
@@ -297,7 +297,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
297
297
|
categoryIds: string[];
|
|
298
298
|
totalRounds: number;
|
|
299
299
|
modeId?: "snag" | "solo" | "oneDevice" | "multiplayer" | undefined;
|
|
300
|
-
game?: "seedha" | "snag" | "trivia" | undefined;
|
|
300
|
+
game?: "seedha" | "snag" | "trivia" | "dama" | undefined;
|
|
301
301
|
buzzerMode?: "solo" | "off" | "race" | "controller" | undefined;
|
|
302
302
|
noHost?: boolean | undefined;
|
|
303
303
|
}, {
|
|
@@ -305,7 +305,7 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
305
305
|
categoryIds: string[];
|
|
306
306
|
totalRounds: number;
|
|
307
307
|
modeId?: "snag" | "solo" | "oneDevice" | "multiplayer" | undefined;
|
|
308
|
-
game?: "seedha" | "snag" | "trivia" | undefined;
|
|
308
|
+
game?: "seedha" | "snag" | "trivia" | "dama" | undefined;
|
|
309
309
|
buzzerMode?: "solo" | "off" | "race" | "controller" | undefined;
|
|
310
310
|
noHost?: boolean | undefined;
|
|
311
311
|
}>, z.ZodObject<{
|
|
@@ -419,6 +419,72 @@ declare const ClientMsg: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
|
|
|
419
419
|
}, {
|
|
420
420
|
t: "reportQuestion";
|
|
421
421
|
reason?: string | undefined;
|
|
422
|
+
}>, z.ZodObject<{
|
|
423
|
+
t: z.ZodLiteral<"damaMove">;
|
|
424
|
+
from: z.ZodObject<{
|
|
425
|
+
r: z.ZodNumber;
|
|
426
|
+
c: z.ZodNumber;
|
|
427
|
+
}, "strip", z.ZodTypeAny, {
|
|
428
|
+
r: number;
|
|
429
|
+
c: number;
|
|
430
|
+
}, {
|
|
431
|
+
r: number;
|
|
432
|
+
c: number;
|
|
433
|
+
}>;
|
|
434
|
+
to: z.ZodObject<{
|
|
435
|
+
r: z.ZodNumber;
|
|
436
|
+
c: z.ZodNumber;
|
|
437
|
+
}, "strip", z.ZodTypeAny, {
|
|
438
|
+
r: number;
|
|
439
|
+
c: number;
|
|
440
|
+
}, {
|
|
441
|
+
r: number;
|
|
442
|
+
c: number;
|
|
443
|
+
}>;
|
|
444
|
+
path: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
445
|
+
r: z.ZodNumber;
|
|
446
|
+
c: z.ZodNumber;
|
|
447
|
+
}, "strip", z.ZodTypeAny, {
|
|
448
|
+
r: number;
|
|
449
|
+
c: number;
|
|
450
|
+
}, {
|
|
451
|
+
r: number;
|
|
452
|
+
c: number;
|
|
453
|
+
}>, "many">>;
|
|
454
|
+
}, "strip", z.ZodTypeAny, {
|
|
455
|
+
t: "damaMove";
|
|
456
|
+
from: {
|
|
457
|
+
r: number;
|
|
458
|
+
c: number;
|
|
459
|
+
};
|
|
460
|
+
to: {
|
|
461
|
+
r: number;
|
|
462
|
+
c: number;
|
|
463
|
+
};
|
|
464
|
+
path?: {
|
|
465
|
+
r: number;
|
|
466
|
+
c: number;
|
|
467
|
+
}[] | undefined;
|
|
468
|
+
}, {
|
|
469
|
+
t: "damaMove";
|
|
470
|
+
from: {
|
|
471
|
+
r: number;
|
|
472
|
+
c: number;
|
|
473
|
+
};
|
|
474
|
+
to: {
|
|
475
|
+
r: number;
|
|
476
|
+
c: number;
|
|
477
|
+
};
|
|
478
|
+
path?: {
|
|
479
|
+
r: number;
|
|
480
|
+
c: number;
|
|
481
|
+
}[] | undefined;
|
|
482
|
+
}>, z.ZodObject<{
|
|
483
|
+
t: z.ZodLiteral<"damaResign">;
|
|
484
|
+
}, "strip", z.ZodTypeAny, {
|
|
485
|
+
t: "damaResign";
|
|
486
|
+
}, {
|
|
487
|
+
t: "damaResign";
|
|
422
488
|
}>]>;
|
|
423
489
|
type ClientMsg = z.infer<typeof ClientMsg>;
|
|
424
490
|
/** A player's privacy-safe avatar (emoji + circle color) for in-room display. */
|
|
@@ -574,6 +640,36 @@ type Effect = {
|
|
|
574
640
|
} | {
|
|
575
641
|
t: 'endGame';
|
|
576
642
|
};
|
|
643
|
+
/** A Dama piece as clients see it. */
|
|
644
|
+
interface DamaPieceView {
|
|
645
|
+
color: 'black' | 'white';
|
|
646
|
+
king: boolean;
|
|
647
|
+
}
|
|
648
|
+
/** A legal Dama move offered to the player to move (for highlighting). `captures` = pieces it takes. */
|
|
649
|
+
interface DamaMoveView {
|
|
650
|
+
from: {
|
|
651
|
+
r: number;
|
|
652
|
+
c: number;
|
|
653
|
+
};
|
|
654
|
+
to: {
|
|
655
|
+
r: number;
|
|
656
|
+
c: number;
|
|
657
|
+
};
|
|
658
|
+
captures: number;
|
|
659
|
+
path: {
|
|
660
|
+
r: number;
|
|
661
|
+
c: number;
|
|
662
|
+
}[];
|
|
663
|
+
}
|
|
664
|
+
/** The authoritative Dama board pushed to a client. `board[r][c]` is null on empty/light squares; r=0 is the top. */
|
|
665
|
+
interface DamaStateView {
|
|
666
|
+
board: (DamaPieceView | null)[][];
|
|
667
|
+
turn: 'black' | 'white';
|
|
668
|
+
winner: 'black' | 'white' | null;
|
|
669
|
+
yourColor: 'black' | 'white' | null;
|
|
670
|
+
legalMoves: DamaMoveView[];
|
|
671
|
+
moveCount: number;
|
|
672
|
+
}
|
|
577
673
|
type ServerMsg = {
|
|
578
674
|
t: 'roomCreated';
|
|
579
675
|
code: string;
|
|
@@ -618,6 +714,11 @@ type ServerMsg = {
|
|
|
618
714
|
view: GameStateView;
|
|
619
715
|
you: YouContext;
|
|
620
716
|
teamConnected: boolean[];
|
|
717
|
+
} | {
|
|
718
|
+
t: 'damaState';
|
|
719
|
+
gameId: 'dama';
|
|
720
|
+
view: DamaStateView;
|
|
721
|
+
you: YouContext;
|
|
621
722
|
} | {
|
|
622
723
|
t: 'fx';
|
|
623
724
|
effects: Effect[];
|
|
@@ -634,4 +735,4 @@ type ServerMsg = {
|
|
|
634
735
|
message: string;
|
|
635
736
|
};
|
|
636
737
|
|
|
637
|
-
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type Effect, GAMES, GAME_IDS, type GameId, type GameInfo, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, MIN_SUPPORTED_PV, MODES, MODE_IDS, type ModeId, type ModeInfo, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamSlotView, type TeamView, type YouContext, gameIdForPv, gamesForPv, modesForGame };
|
|
738
|
+
export { type AvatarView, type BuzzerGameMode, type CategoryView, ClientMsg, type DamaMoveView, type DamaPieceView, type DamaStateView, type Effect, GAMES, GAME_IDS, type GameId, type GameInfo, type GameStateView, type GameStatus, type GameplayFlow, type HelpName, LIMITS, type LobbyPlayer, MIN_SUPPORTED_PV, MODES, MODE_IDS, type ModeId, type ModeInfo, PROTOCOL_VERSION, type QuestionView, ROOM_ALPHABET, type ServerMsg, type SoundName, type TeamSlotView, type TeamView, type YouContext, gameIdForPv, gamesForPv, modesForGame };
|
package/dist/index.js
CHANGED
|
@@ -6,12 +6,14 @@ var LIMITS = {
|
|
|
6
6
|
MAX_PLAYERS: 12,
|
|
7
7
|
MAX_MSG_PER_SEC: 8
|
|
8
8
|
};
|
|
9
|
-
var PROTOCOL_VERSION =
|
|
9
|
+
var PROTOCOL_VERSION = 3;
|
|
10
10
|
var MIN_SUPPORTED_PV = 1;
|
|
11
|
-
var GAME_IDS = ["seedha", "snag", "trivia"];
|
|
11
|
+
var GAME_IDS = ["seedha", "snag", "trivia", "dama"];
|
|
12
12
|
var GAMES = [
|
|
13
13
|
{ id: "seedha", label: "Seedha", minPv: 2 },
|
|
14
14
|
{ id: "snag", label: "Snag", minPv: 2 },
|
|
15
|
+
{ id: "dama", label: "Dama", minPv: 3 },
|
|
16
|
+
// engine #2 (D-027) — offered only to pv≥3 clients
|
|
15
17
|
{ id: "trivia", label: "Trivia", minPv: 1, deprecated: true }
|
|
16
18
|
];
|
|
17
19
|
var gamesForPv = (pv) => GAMES.filter((g) => !g.deprecated && g.minPv <= pv);
|
|
@@ -81,7 +83,8 @@ var ClientMsg = z.discriminatedUnion("t", [
|
|
|
81
83
|
game: z.enum(GAME_IDS).optional(),
|
|
82
84
|
// which game to play; defaults to 'trivia'
|
|
83
85
|
totalRounds: z.number().int().min(1).max(50),
|
|
84
|
-
categoryIds: z.array(z.string().max(60)).min(
|
|
86
|
+
categoryIds: z.array(z.string().max(60)).min(0).max(12),
|
|
87
|
+
// empty for games without categories (Dama); trivia rejects empty in-handler
|
|
85
88
|
// PREFERRED: pick a mode from the registry (see MODES). The server maps it to the engine
|
|
86
89
|
// rules. Send this and omit buzzerMode/noHost. Falls back to the legacy flags below if omitted.
|
|
87
90
|
modeId: z.enum(MODE_IDS).optional(),
|
|
@@ -118,7 +121,19 @@ var ClientMsg = z.discriminatedUnion("t", [
|
|
|
118
121
|
// Report the CURRENT question as bad (wrong answer / typo / offensive). The relay resolves WHICH
|
|
119
122
|
// question from its authoritative room state — the client never sees the question id (anti-cheat),
|
|
120
123
|
// so it only sends an optional `reason`. Only meaningful while a question is on screen.
|
|
121
|
-
z.object({ t: z.literal("reportQuestion"), reason: z.string().max(500).optional() })
|
|
124
|
+
z.object({ t: z.literal("reportQuestion"), reason: z.string().max(500).optional() }),
|
|
125
|
+
// ── Dama slice (gameId 'dama', engine #2 — D-027) ──
|
|
126
|
+
// Make a Dama move: from → to (board coords, 0–7). The relay validates legality against the engine
|
|
127
|
+
// (Shape B) and rejects anything not in legalMoves. If two capture chains share from+to (rare), the
|
|
128
|
+
// relay picks the max-capture one; a client MAY send the full landing `path` to disambiguate.
|
|
129
|
+
z.object({
|
|
130
|
+
t: z.literal("damaMove"),
|
|
131
|
+
from: z.object({ r: z.number().int().min(0).max(7), c: z.number().int().min(0).max(7) }),
|
|
132
|
+
to: z.object({ r: z.number().int().min(0).max(7), c: z.number().int().min(0).max(7) }),
|
|
133
|
+
path: z.array(z.object({ r: z.number().int().min(0).max(7), c: z.number().int().min(0).max(7) })).max(12).optional()
|
|
134
|
+
}),
|
|
135
|
+
// Resign the current Dama game (concede) → opponent wins.
|
|
136
|
+
z.object({ t: z.literal("damaResign") })
|
|
122
137
|
]);
|
|
123
138
|
export {
|
|
124
139
|
ClientMsg,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thegeem/protocol",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
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",
|