@yyyu-star/arcade-kit 0.12.5 → 0.13.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
package/dist/testing.js CHANGED
@@ -9,6 +9,8 @@
9
9
  * 到期原样退回(`expired`)、client 模式每个游戏每天净赢最多 `WIN_UNITS` 份(`capped`);
10
10
  * - 结回带的小结 `stats` 按 5.10 的上限检查(JSON ≤ 256 字节、必填字段、称号和自定义数的格式),不合格回 `statsIgnored`、钱照常结;
11
11
  * 收下的记在 `FakeBank.stats` 里给测试核对;
12
+ * - `together`(0.13.0,15.19 搭子战绩):形状照平台的 parseTogether 查(op 格式、2–8 个人、userId 不重复、team 0–3 整数、win 布尔),
13
+ * 每个人的 `FakeBank.together` 记一笔给测试核对;同一个游戏的同一个 op 重报不加。假钱包不管好友关系(平台只记好友之间的对),报上来的两两都算一对;
12
14
  * - `walletHttp`:浏览器的 `GET /api/wallet`、`POST /api/wallet/relief`(15.9),认平台的会话 cookie,cookie 的值就当 userId。
13
15
  *
14
16
  * 平台改了钱包接口(参数、错误码、规则),平台 PR 的描述里写"影响 kit/testing",由维护者安排 kit 跟上;一个 PR 只改一个模块。
@@ -19,6 +21,7 @@
19
21
  */
20
22
  import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
21
23
  import { SESSION_COOKIE } from './internal.js';
24
+ import { TOGETHER_MAX } from './together.js';
22
25
  /** 新号送多少、补给补到多少、client 模式每天净赢最多几份:平台的默认值(5.9,管理员可调的那几个数按默认算) */
23
26
  export const NEW_BALANCE = 10_000;
24
27
  export const RELIEF_TO = 2_000;
@@ -37,6 +40,16 @@ export class FakeBank extends DurableObject {
37
40
  writes = 0;
38
41
  /** 结回带上来的小结,按先后记在内存里;不合格的记 ignored */
39
42
  stats = [];
43
+ /** 搭子战绩(0.13.0):报到这个人头上的每一场,按先后记在内存里(同一个游戏的同一个 op 只记一次) */
44
+ together = [];
45
+ /** 记一场;这个人这个 op 记过了回 false */
46
+ async addTogether(game, op, players) {
47
+ this.calls++;
48
+ if (this.together.some((t) => t.game === game && t.op === op))
49
+ return false;
50
+ this.together.push({ game, op, players });
51
+ return true;
52
+ }
40
53
  async load(now) {
41
54
  const s = (await this.ctx.storage.get('w')) ??
42
55
  { balance: NEW_BALANCE, stakes: {}, reliefDay: '', day: '', cin: {}, cout: {}, top: {}, ops: {}, expired: [], fresh: true };
@@ -197,6 +210,22 @@ export class WalletService extends WorkerEntrypoint {
197
210
  refund(req) {
198
211
  return this.op('refund', req);
199
212
  }
213
+ /** 搭子战绩(15.19){ op, players }:回记上了几对(假钱包里两两都算好友);形状不对 bad_request,没绑游戏 bad_game */
214
+ async together(req) {
215
+ const game = this.bound();
216
+ if (!game)
217
+ return { ok: false, error: 'bad_game' };
218
+ const q = parseTogether(req);
219
+ if (!q)
220
+ return { ok: false, error: 'bad_request' };
221
+ const fresh = await Promise.all(q.players.map((p) => bank(this.env, p.userId).addTogether(game, q.op, q.players)));
222
+ let pairs = 0;
223
+ for (let i = 0; i < fresh.length; i++)
224
+ for (let j = i + 1; j < fresh.length; j++)
225
+ if (fresh[i] && fresh[j])
226
+ pairs++;
227
+ return { ok: true, pairs };
228
+ }
200
229
  bound() {
201
230
  const g = this.ctx.props?.game;
202
231
  return typeof g === 'string' && g !== '' ? g : null;
@@ -223,6 +252,30 @@ export class WalletService extends WorkerEntrypoint {
223
252
  return bank(this.env, q.userId).run(cmd, Date.now());
224
253
  }
225
254
  }
255
+ /** 平台 parseTogether 的同一套检查(15.19):形状不对回 null */
256
+ export function parseTogether(raw) {
257
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
258
+ return null;
259
+ const b = raw;
260
+ if (typeof b.op !== 'string' || !ID.test(b.op))
261
+ return null;
262
+ if (!Array.isArray(b.players) || b.players.length < 2 || b.players.length > TOGETHER_MAX)
263
+ return null;
264
+ const players = [];
265
+ const seen = new Set();
266
+ for (const p of b.players) {
267
+ if (!p || typeof p !== 'object' || Array.isArray(p))
268
+ return null;
269
+ const { userId, team, win } = p;
270
+ if (typeof userId !== 'string' || !/^[A-Za-z0-9_-]{1,64}$/.test(userId) || seen.has(userId) || typeof win !== 'boolean')
271
+ return null;
272
+ if (team !== undefined && !(Number.isInteger(team) && team >= 0 && team <= 3))
273
+ return null;
274
+ seen.add(userId);
275
+ players.push(team === undefined ? { userId, win } : { userId, team: team, win });
276
+ }
277
+ return { op: b.op, players };
278
+ }
226
279
  /** 5.10 的检查:JSON 后 ≤ 256 字节;rounds、wins、best 非负整数;称号最多 5 个、格式;max + sum 最多 3 个 key、值是安全整数 */
227
280
  export function statsProblem(x) {
228
281
  if (JSON.stringify(x).length > 256)
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 搭子战绩上报(0.13.0,平台 0.19.0,docs/platform-backend.md 15.19):好友房打完一场,房间的服务端把同桌真人和各自输赢经钱包服务绑定的 `together()` 报给平台,
3
+ * 平台给其中已经是好友的每一对累计"一起打了几场、谁赢了几场、做搭档几场"。浏览器碰不到这条路(只有服务绑定),所以只在房间里调。
4
+ *
5
+ * 不依赖 `cloudflare:workers`(纯函数加一次 RPC),`arcade-kit/room` 转出;房间子类一般用 `GameRoom.reportMatch`,它按座位认人、拼 op。
6
+ */
7
+ /** 一个真人这一场:team 只有分队的游戏才带(同一个数字是一队,0–3);win 由游戏定,写进各自的 DESIGN */
8
+ export interface TogetherPlayer {
9
+ userId: string;
10
+ team?: number;
11
+ win: boolean;
12
+ }
13
+ export type TogetherReply = {
14
+ ok: true;
15
+ pairs: number;
16
+ } | {
17
+ ok: false;
18
+ error: string;
19
+ };
20
+ /** 平台一次最多收几个人(15.19:2–8 个真人) */
21
+ export declare const TOGETHER_MAX = 8;
22
+ /**
23
+ * 一场的编号:平台按它去重(同一对的同一个 op 再报不加),所以同一场重报要得到同一个 op,不同的场不能撞。
24
+ * 房间码会被别的房间重用,所以带上开房时刻:`<房间码>-<开房时刻 36 进制>-<第几场>`,不合格的字符换成 `_`,截到 64 位
25
+ */
26
+ export declare function togetherOp(code: string, createdAt: number, match: number | string): string;
27
+ /**
28
+ * 报一场。players 只放真人(电脑、游客不报),同一个 userId 只留第一个;少于 2 个、超过 TOGETHER_MAX 个、op 不合格,
29
+ * 或者没有 `env.WALLET`(单独部署)、它没有 `together`(平台还没上 0.19.0)时什么都不做,回 null。
30
+ * 平台的回话原样返回;RPC 抛错吞掉、只记错误类型(不记 userId),也回 null。**不重试**:平台忙时回 busy,少记一场不影响打牌。
31
+ * 只经服务绑定调,不用 setTimeout;房间在一场结束时交给 `ctx.waitUntil`(见 GameRoom.reportMatch)
32
+ */
33
+ export declare function reportTogether(env: unknown, op: string, players: readonly TogetherPlayer[]): Promise<TogetherReply | null>;
34
+ //# sourceMappingURL=together.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"together.d.ts","sourceRoot":"","sources":["../src/together.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,gCAAgC;AAChC,eAAO,MAAM,YAAY,IAAI,CAAC;AAQ9B;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE1F;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAiBhI"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 搭子战绩上报(0.13.0,平台 0.19.0,docs/platform-backend.md 15.19):好友房打完一场,房间的服务端把同桌真人和各自输赢经钱包服务绑定的 `together()` 报给平台,
3
+ * 平台给其中已经是好友的每一对累计"一起打了几场、谁赢了几场、做搭档几场"。浏览器碰不到这条路(只有服务绑定),所以只在房间里调。
4
+ *
5
+ * 不依赖 `cloudflare:workers`(纯函数加一次 RPC),`arcade-kit/room` 转出;房间子类一般用 `GameRoom.reportMatch`,它按座位认人、拼 op。
6
+ */
7
+ /** 平台一次最多收几个人(15.19:2–8 个真人) */
8
+ export const TOGETHER_MAX = 8;
9
+ const OP_RE = /^[A-Za-z0-9_-]{8,64}$/;
10
+ /**
11
+ * 一场的编号:平台按它去重(同一对的同一个 op 再报不加),所以同一场重报要得到同一个 op,不同的场不能撞。
12
+ * 房间码会被别的房间重用,所以带上开房时刻:`<房间码>-<开房时刻 36 进制>-<第几场>`,不合格的字符换成 `_`,截到 64 位
13
+ */
14
+ export function togetherOp(code, createdAt, match) {
15
+ return `${code}-${createdAt.toString(36)}-${match}`.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 64).padEnd(8, '_');
16
+ }
17
+ /**
18
+ * 报一场。players 只放真人(电脑、游客不报),同一个 userId 只留第一个;少于 2 个、超过 TOGETHER_MAX 个、op 不合格,
19
+ * 或者没有 `env.WALLET`(单独部署)、它没有 `together`(平台还没上 0.19.0)时什么都不做,回 null。
20
+ * 平台的回话原样返回;RPC 抛错吞掉、只记错误类型(不记 userId),也回 null。**不重试**:平台忙时回 busy,少记一场不影响打牌。
21
+ * 只经服务绑定调,不用 setTimeout;房间在一场结束时交给 `ctx.waitUntil`(见 GameRoom.reportMatch)
22
+ */
23
+ export async function reportTogether(env, op, players) {
24
+ const wallet = env?.WALLET;
25
+ if (!wallet || typeof wallet.together !== 'function')
26
+ return null;
27
+ const seen = new Set();
28
+ const list = [];
29
+ for (const p of players) {
30
+ if (!p.userId || seen.has(p.userId))
31
+ continue;
32
+ seen.add(p.userId);
33
+ list.push(p.team === undefined ? { userId: p.userId, win: p.win } : { userId: p.userId, team: p.team, win: p.win });
34
+ }
35
+ if (list.length < 2 || list.length > TOGETHER_MAX || !OP_RE.test(op))
36
+ return null;
37
+ try {
38
+ return (await wallet.together({ op, players: list }));
39
+ }
40
+ catch (e) {
41
+ console.error('together failed', e instanceof Error ? e.name : typeof e);
42
+ return null;
43
+ }
44
+ }
45
+ //# sourceMappingURL=together.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"together.js","sourceRoot":"","sources":["../src/together.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,gCAAgC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,MAAM,KAAK,GAAG,uBAAuB,CAAC;AAMtC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAE,KAAsB;IAChF,OAAO,GAAG,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAClH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAY,EAAE,EAAU,EAAE,OAAkC;IAC/F,MAAM,MAAM,GAAI,GAAsD,EAAE,MAAM,CAAC;IAC/E,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAqB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,SAAS;QAC9C,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACtH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,YAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAClF,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAkB,CAAC;IACzE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yyyu-star/arcade-kit",
3
- "version": "0.12.5",
3
+ "version": "0.13.1",
4
4
  "description": "Multiplayer toolkit for small Cloudflare Workers games: Durable Object game rooms, room create/join entry points, browser client, daily write quota, ChaCha20 RNG, platform or standalone (guest) identity. 小游戏共用的联机底座",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/client.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * 浏览器里的计时器(重连、心跳)可以用 setTimeout,"只用一个闹钟"是房间(Durable Object)那边的规矩。
18
18
  */
19
- import { CLOSE, CLOSE_REASON, type CreateError, type DownMsg, type EmotedMsg, isFinalClose, PING, PONG, PROTOCOL_VERSION, type UpMsg } from './protocol.js';
19
+ import { CLOSE, CLOSE_REASON, type CreateError, type DownMsg, type EmotedMsg, isFinalClose, PING, PONG, PROTOCOL_VERSION, type RoomInfo, type UpMsg } from './protocol.js';
20
20
 
21
21
  export type ClientStatus = 'connecting' | 'open' | 'reconnecting' | 'closed' | 'failed';
22
22
 
@@ -73,6 +73,13 @@ const HEARTBEAT_MS = 25_000;
73
73
  export const PONG_WAIT_MS = 8_000;
74
74
  /** 建连最多等多久(0.11.1):卡在 CONNECTING 的按一次失败算,重连 */
75
75
  export const CONNECT_MS = 10_000;
76
+ /**
77
+ * 看门狗(0.13.1):房间说的出手时限(或停顿的结束时间)过了 STALL_GRACE_MS 再加最多 STALL_JITTER_MS 的随机抖动,还没有新状态,
78
+ * 就当房间的闹钟没设上(存储出错、没人发消息时房间不会自己醒),重连一次把房间叫醒:进房是房间的一个入口,它会按 getAlarm() 重排闹钟、
79
+ * 把过期的那一手照常处理。同一个 seq 只踢一次;抖动让一桌人里先到的那个去踢,别人收到新状态就不踢了
80
+ */
81
+ export const STALL_GRACE_MS = 20_000;
82
+ export const STALL_JITTER_MS = 10_000;
76
83
  /** 快捷短语太快时最多排几个(多的丢最早的) */
77
84
  const EMOTE_QUEUE = 2;
78
85
 
@@ -97,6 +104,9 @@ export class RoomClient<A = unknown, V = unknown> {
97
104
  private probing = false;
98
105
  private probeTimer: unknown = null;
99
106
  private connectTimer: unknown = null;
107
+ /** 看门狗(0.13.1):到点还停在 watchSeq 就重连一次;kickedSeq 是踢过的,不再踢 */
108
+ private watchTimer: unknown = null;
109
+ private kickedSeq = -1;
100
110
  /** 没收到 ack 的操作:重连后按原 moveId 重发 */
101
111
  private pending = new Map<string, UpMsg<A>>();
102
112
  private moveCounter = 0;
@@ -254,11 +264,13 @@ export class RoomClient<A = unknown, V = unknown> {
254
264
  this.welcomed = true;
255
265
  this.attempt = 0;
256
266
  this.failures = 0;
267
+ this.watch(ws, msg);
257
268
  } else if (msg.t === 'state') {
258
269
  const mine = msg.ack !== undefined && this.pending.delete(msg.ack);
259
270
  // 旧的、重复的丢掉(ack 已经处理过了)。例外:别人看不出来的一步(0.7.1,quiet),房间只回给我、seq 不加,第一次收到要交给页面
260
271
  if (msg.seq < this.lastSeq || (msg.seq === this.lastSeq && !(mine && msg.quiet === true))) return;
261
272
  this.lastSeq = msg.seq;
273
+ this.watch(ws, msg);
262
274
  } else if (msg.t === 'error' && msg.moveId) {
263
275
  // 被拒的操作不再重发
264
276
  this.pending.delete(msg.moveId);
@@ -316,6 +328,25 @@ export class RoomClient<A = unknown, V = unknown> {
316
328
  }, PONG_WAIT_MS);
317
329
  }
318
330
 
331
+ /**
332
+ * 看门狗:按房间给的时间(now)算出手时限还剩多久,过了宽限还停在这个 seq,就扔掉连接重连一次(见 STALL_GRACE_MS)。
333
+ * 没在打、没有时限、旧房间不带 now 的不看;同一个 seq 踢过一次就不再踢(房间还是不动,就等真人出手或下一次进出)
334
+ */
335
+ private watch(ws: WebSocketLike, msg: { seq: number; room: RoomInfo; now?: number }): void {
336
+ if (this.watchTimer !== null) this.opts.clearTimer(this.watchTimer);
337
+ this.watchTimer = null;
338
+ const until = msg.room.turn?.deadline ?? msg.room.pause?.until;
339
+ if (msg.room.status !== 'playing' || until == null || typeof msg.now !== 'number' || msg.seq === this.kickedSeq) return;
340
+ const seq = msg.seq;
341
+ const wait = Math.max(0, until - msg.now) + STALL_GRACE_MS + Math.round(this.opts.random() * STALL_JITTER_MS);
342
+ this.watchTimer = this.opts.setTimer(() => {
343
+ this.watchTimer = null;
344
+ if (this.ws !== ws || this.lastSeq !== seq || ws.readyState !== OPEN) return;
345
+ this.kickedSeq = seq;
346
+ this.abandon(ws);
347
+ }, wait);
348
+ }
349
+
319
350
  /** 带上这次的关闭码:游戏据此区分"网络断了"(1006)和"平台有点忙"(1013)。 */
320
351
  private scheduleRetry(code: number): void {
321
352
  this.setStatus('reconnecting', code);
@@ -365,8 +396,8 @@ export class RoomClient<A = unknown, V = unknown> {
365
396
  }
366
397
 
367
398
  private clearTimers(): void {
368
- for (const t of [this.retryTimer, this.emoteTimer, this.beatTimer, this.probeTimer, this.connectTimer]) if (t !== null) this.opts.clearTimer(t);
369
- this.retryTimer = this.emoteTimer = this.beatTimer = this.probeTimer = this.connectTimer = null;
399
+ for (const t of [this.retryTimer, this.emoteTimer, this.beatTimer, this.probeTimer, this.connectTimer, this.watchTimer]) if (t !== null) this.opts.clearTimer(t);
400
+ this.retryTimer = this.emoteTimer = this.beatTimer = this.probeTimer = this.connectTimer = this.watchTimer = null;
370
401
  this.probing = false;
371
402
  }
372
403
 
package/src/protocol.ts CHANGED
@@ -185,6 +185,11 @@ export interface WelcomeMsg<V = unknown> {
185
185
  you: You;
186
186
  room: RoomInfo;
187
187
  view: V | null;
188
+ /**
189
+ * 房间发这条消息时的时间(毫秒,0.13.1):RoomClient 拿它和 room.turn.deadline 算"还剩多久",不用浏览器自己的钟(可能差几分钟)。
190
+ * 用来发现房间的闹钟没设上、到点了却没人推进(见 RoomClient 的看门狗)。旧房间不带
191
+ */
192
+ now?: number;
188
193
  /**
189
194
  * 快捷短语的节奏(0.7.0,游戏有短语时才带):每 ms 毫秒补 1 个令牌、最多攒 burst 个。RoomClient 按它在本地排队发,
190
195
  * 用户感觉不到限速;运维在 KIT_QUOTA 里改,不用发版
@@ -201,6 +206,8 @@ export interface StateMsg<V = unknown> {
201
206
  /** 至少一帧;最后一帧就是当前状态 */
202
207
  frames: Frame<V>[];
203
208
  ack?: string;
209
+ /** 同 WelcomeMsg.now(0.13.1) */
210
+ now?: number;
204
211
  /**
205
212
  * 别人看不出来的一步(0.7.1):不轮流的操作没改任何别人能看到的东西(比如声明窗口里真人答"碰"),房间只回给出手的人、seq 不加(和上一条一样)。
206
213
  * 只和 ack 一起出现;RoomClient 0.7.1 起认它(seq 一样也交给页面),旧的 RoomClient 当重复丢掉
package/src/room.ts CHANGED
@@ -35,8 +35,10 @@ import {
35
35
  type RoomStatus,
36
36
  type SeatInfo,
37
37
  } from './protocol.js';
38
+ import { reportTogether, togetherOp, type TogetherPlayer } from './together.js';
38
39
 
39
40
  export type { RoomEffect, RoomGame, RoomSetup } from './game.js';
41
+ export { TOGETHER_MAX, reportTogether, togetherOp, type TogetherPlayer, type TogetherReply } from './together.js';
40
42
  export type { Identity } from './internal.js';
41
43
 
42
44
  export interface RoomLimits {
@@ -117,6 +119,8 @@ export const DEFAULT_LIMITS: RoomLimits = {
117
119
 
118
120
  /** 闹钟里出错时,过这么久再醒来重试(不用"马上",免得每次都出错时连着计费)。 */
119
121
  const ALARM_RETRY_MS = 60_000;
122
+ /** setAlarm 一次最多试几回(0.13.1):存储一时出错当场再试一次,不等下一个入口 */
123
+ const SET_ALARM_TRIES = 2;
120
124
  /** 每个座位记住最近几个做成的 moveId(0.11.1):客户端断线时攒着没确认的操作,重连后原样补发 */
121
125
  const RECENT_MOVES = 8;
122
126
 
@@ -260,6 +264,27 @@ export abstract class GameRoom<S, A, V, Env = unknown, O = unknown, E extends Ro
260
264
  */
261
265
  protected onEmote(_from: number, _id: number, _to?: number): void {}
262
266
 
267
+ /**
268
+ * 搭子战绩(0.13.0,平台 15.19):一场打完时报一次同桌真人和各自输赢。players 按座位给(电脑座位直接放进来也行,这里按开打后绑的人认,
269
+ * 没绑真人的座位不报),match 是这一场在房间里的序号(同一场重报给同一个数,平台按 op 去重)。
270
+ * 交给 `ctx.waitUntil` 去办、不 await:一般在同步的 `onStep` 里看到一场结束时调,不能卡住广播和下一步;
271
+ * 也不走 `effects`/`perform`:那条路办不成会退避重试、要写状态,而这件事平台忙时少记一场就算了(不重试)。
272
+ * 单独部署没有 WALLET 时 reportTogether 自己跳过。返回报了几个人(0 = 没报)
273
+ */
274
+ protected reportMatch(players: readonly { seat: number; team?: number; win: boolean }[], match: number | string): number {
275
+ const st = this.st;
276
+ if (!st) return 0;
277
+ const list: TogetherPlayer[] = [];
278
+ for (const p of players) {
279
+ const userId = st.owners[p.seat];
280
+ if (typeof userId !== 'string' || userId === NOBODY) continue;
281
+ list.push(p.team === undefined ? { userId, win: p.win } : { userId, team: p.team, win: p.win });
282
+ }
283
+ if (list.length < 2) return 0;
284
+ this.ctx.waitUntil(reportTogether(this.env, togetherOp(st.code, st.createdAt, match), list));
285
+ return list.length;
286
+ }
287
+
263
288
  /**
264
289
  * 让电脑座位发一句快捷短语(0.10.0):广播的消息和真人发的一样({ t: 'emote', seat, id, to? }),多带 bot: true,客户端可以不管它。
265
290
  * 只有电脑在出手的座位能发:kind 是 ai,或者真人掉线后由电脑托管(auto)。id、to 的校验和真人一样,走同一个座位的令牌桶
@@ -438,26 +463,56 @@ export abstract class GameRoom<S, A, V, Env = unknown, O = unknown, E extends Ro
438
463
  this.totalWrites += this.writes;
439
464
  this.unmetered += this.writes;
440
465
  this.maxStepWrites = Math.max(this.maxStepWrites, this.writes);
441
- if (at !== null && !(await this.setAlarmSafely(at))) this.lastStepFailed = true;
466
+ if (at !== null && !(await this.setAlarmSafely(at))) {
467
+ this.lastStepFailed = true;
468
+ await this.recoverAlarm();
469
+ }
442
470
  await this.afterStep();
443
471
  return out;
444
472
  }
445
473
 
446
474
  /**
447
- * 设闹钟;失败了不往外抛(0.11.1)。planAlarm 已经把 alarmAt 改成了新时间,失败时它就是错的:
448
- * 留着的话以后 planAlarm 看"已经设了更早的"一直不重设,房间就没人收场。改回"不知道",下一个入口按 getAlarm() 重新读、照常重排
475
+ * 这一步要设的闹钟两次都没设上(0.13.1,第三轮审计):按 getAlarm() 核对存储里还有没有闹钟(以前设的更早的那个可能还在);
476
+ * 有就以它为准,没有而房间还在,就补一个 ALARM_RETRY_MS 后的,醒来时 onAlarm 按状态重新算(到点的照常处理)。
477
+ * 以前只靠下一个入口重排:全是电脑、大家都在等时限的房间没人发消息,就一直停着,不关房、结回也不重试。
478
+ * 补设也失败(存储一直坏着)就只剩浏览器的看门狗(RoomClient)重连来叫醒。读不了存储时不抛(入口里不往外抛)
449
479
  */
450
- private async setAlarmSafely(at: number): Promise<boolean> {
480
+ private async recoverAlarm(): Promise<void> {
451
481
  try {
452
- await this.ctx.storage.setAlarm(at);
453
- return true;
482
+ if (!this.load()) return;
483
+ const cur = await this.ctx.storage.getAlarm();
484
+ if (cur !== null) {
485
+ this.alarmAt = cur;
486
+ return;
487
+ }
488
+ // 不另记一行:这一步的那次 setAlarm 已经记过了,它没写成,补设的这次顶替它
489
+ this.alarmAt = Date.now() + ALARM_RETRY_MS;
490
+ await this.setAlarmSafely(this.alarmAt);
454
491
  } catch (e) {
455
- console.error('room setAlarm failed', e instanceof Error ? e.message : e);
492
+ console.error('room alarm recovery failed', e instanceof Error ? e.message : e);
456
493
  this.alarmAt = undefined;
457
- return false;
458
494
  }
459
495
  }
460
496
 
497
+ /**
498
+ * 设闹钟;失败了不往外抛(0.11.1)。存储一时出错大多下一次就好,所以当场再试一次(0.13.1);还不行:
499
+ * planAlarm 已经把 alarmAt 改成了新时间,失败时它就是错的,留着的话以后 planAlarm 看"已经设了更早的"一直不重设,房间就没人收场。
500
+ * 改回"不知道",下一个入口(任何消息、进房、闹钟)按 getAlarm() 重新读、照常重排。
501
+ * 一直没人发消息(全是电脑在打、大家都在等时限)时,下一个入口由浏览器的看门狗给(RoomClient:时限过了很久还没有新状态就重连一次)
502
+ */
503
+ private async setAlarmSafely(at: number): Promise<boolean> {
504
+ for (let i = 0; i < SET_ALARM_TRIES; i++) {
505
+ try {
506
+ await this.ctx.storage.setAlarm(at);
507
+ return true;
508
+ } catch (e) {
509
+ console.error('room setAlarm failed', i + 1, e instanceof Error ? e.message : e);
510
+ }
511
+ }
512
+ this.alarmAt = undefined;
513
+ return false;
514
+ }
515
+
461
516
  // ---------- 计量(0.2.0) ----------
462
517
 
463
518
  /**
@@ -1561,6 +1616,7 @@ export abstract class GameRoom<S, A, V, Env = unknown, O = unknown, E extends Ro
1561
1616
  you: { seat, bound },
1562
1617
  room: this.roomInfo(),
1563
1618
  view: st.game === null ? null : this.game.view(st.game, seat),
1619
+ now: Date.now(),
1564
1620
  // 有短语的游戏告诉页面限速的节奏(0.7.0),RoomClient 按它排队,用户感觉不到限速
1565
1621
  ...(hasEmotes(this.game.emotes) ? { emote: this.emoteRate() } : {}),
1566
1622
  };
@@ -1569,7 +1625,7 @@ export abstract class GameRoom<S, A, V, Env = unknown, O = unknown, E extends Ro
1569
1625
  private stateMsg(seat: number | null, bound: number | null, frames: { state: S | null; delay: number }[], ack?: string, quiet = false): DownMsg<V> {
1570
1626
  const st = this.st!;
1571
1627
  const out: Frame<V>[] = frames.map((f) => ({ view: (f.state === null ? null : this.game.view(f.state, seat)) as V, delay: f.delay }));
1572
- return { t: 'state', seq: st.seq, you: { seat, bound }, room: this.roomInfo(), frames: out, ...(ack ? { ack } : {}), ...(quiet ? { quiet: true as const } : {}) };
1628
+ return { t: 'state', seq: st.seq, you: { seat, bound }, room: this.roomInfo(), frames: out, now: Date.now(), ...(ack ? { ack } : {}), ...(quiet ? { quiet: true as const } : {}) };
1573
1629
  }
1574
1630
 
1575
1631
  /** 按座位过滤后广播:同一个座位(加上绑定的座位,没入座的人各自不同)的消息只算一次。只发给已经收到快照(有 attachment)的连接。 */
package/src/table-fun.ts CHANGED
@@ -49,8 +49,20 @@ export interface FunSeat {
49
49
  temper?: FunTemper;
50
50
  }
51
51
 
52
+ /**
53
+ * storageKey 的检查(0.13.1):它就是游戏 id,kit 拿它拼 `<id>.hint.fun`、`<id>.fun.blocked`。同站的几个游戏和平台只靠 `<id>.` 前缀分开存储,
54
+ * 所以只认游戏 id 的写法(小写字母、数字、连字符,字母或数字开头,最多 32 位);带点("guandan." 会拼出 "guandan..fun")、大写、空串、
55
+ * 平台自己的前缀 arcade 都不行。不合格直接抛错:同一个字符串每次都一样,开发时第一次打开牌桌就看得到,不会带到线上
56
+ */
57
+ export function checkStorageKey(key: unknown): string {
58
+ if (typeof key !== 'string' || !/^[a-z0-9][a-z0-9-]{0,31}$/.test(key) || key === 'arcade') {
59
+ throw new Error(`arcade-kit/table-fun: storageKey 要写游戏 id(比如 "mygame",存成 "mygame.hint.fun"),收到 ${JSON.stringify(key)}`);
60
+ }
61
+ return key;
62
+ }
63
+
52
64
  export interface TableFunOptions {
53
- /** 游戏 id:首次提示、屏蔽名单的存储 key 前缀(`<id>.hint.fun`、`<id>.fun.blocked`) */
65
+ /** 游戏 id:首次提示、屏蔽名单的存储 key 前缀(`<id>.hint.fun`、`<id>.fun.blocked`);不是游戏 id 的写法构造时就抛错(checkStorageKey) */
54
66
  storageKey: string;
55
67
  /** 本游戏的短语表(编号 0..P-1,见 fun-logic 的 funItem) */
56
68
  phrases: readonly string[];
@@ -165,6 +177,8 @@ export class TableFun {
165
177
  private readonly onResize = (): void => this.refresh();
166
178
 
167
179
  constructor(opts: TableFunOptions) {
180
+ // 先查 key 再碰 DOM:不合格的不留下半个界面
181
+ checkStorageKey(opts.storageKey);
168
182
  this.o = opts;
169
183
  this.P = opts.phrases.length;
170
184
  this.doc = document;
package/src/testing.ts CHANGED
@@ -9,6 +9,8 @@
9
9
  * 到期原样退回(`expired`)、client 模式每个游戏每天净赢最多 `WIN_UNITS` 份(`capped`);
10
10
  * - 结回带的小结 `stats` 按 5.10 的上限检查(JSON ≤ 256 字节、必填字段、称号和自定义数的格式),不合格回 `statsIgnored`、钱照常结;
11
11
  * 收下的记在 `FakeBank.stats` 里给测试核对;
12
+ * - `together`(0.13.0,15.19 搭子战绩):形状照平台的 parseTogether 查(op 格式、2–8 个人、userId 不重复、team 0–3 整数、win 布尔),
13
+ * 每个人的 `FakeBank.together` 记一笔给测试核对;同一个游戏的同一个 op 重报不加。假钱包不管好友关系(平台只记好友之间的对),报上来的两两都算一对;
12
14
  * - `walletHttp`:浏览器的 `GET /api/wallet`、`POST /api/wallet/relief`(15.9),认平台的会话 cookie,cookie 的值就当 userId。
13
15
  *
14
16
  * 平台改了钱包接口(参数、错误码、规则),平台 PR 的描述里写"影响 kit/testing",由维护者安排 kit 跟上;一个 PR 只改一个模块。
@@ -19,6 +21,7 @@
19
21
  */
20
22
  import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
21
23
  import { SESSION_COOKIE } from './internal.js';
24
+ import { TOGETHER_MAX, type TogetherPlayer } from './together.js';
22
25
 
23
26
  /** 新号送多少、补给补到多少、client 模式每天净赢最多几份:平台的默认值(5.9,管理员可调的那几个数按默认算) */
24
27
  export const NEW_BALANCE = 10_000;
@@ -92,6 +95,16 @@ export class FakeBank extends DurableObject {
92
95
  writes = 0;
93
96
  /** 结回带上来的小结,按先后记在内存里;不合格的记 ignored */
94
97
  stats: { game: string; ref: string; stats: unknown; ignored?: StatsProblem }[] = [];
98
+ /** 搭子战绩(0.13.0):报到这个人头上的每一场,按先后记在内存里(同一个游戏的同一个 op 只记一次) */
99
+ together: { game: string; op: string; players: TogetherPlayer[] }[] = [];
100
+
101
+ /** 记一场;这个人这个 op 记过了回 false */
102
+ async addTogether(game: string, op: string, players: TogetherPlayer[]): Promise<boolean> {
103
+ this.calls++;
104
+ if (this.together.some((t) => t.game === game && t.op === op)) return false;
105
+ this.together.push({ game, op, players });
106
+ return true;
107
+ }
95
108
 
96
109
  private async load(now: number): Promise<State> {
97
110
  const s =
@@ -240,6 +253,18 @@ export class WalletService extends WorkerEntrypoint<FakeEnv, { game?: string }>
240
253
  return this.op('refund', req);
241
254
  }
242
255
 
256
+ /** 搭子战绩(15.19){ op, players }:回记上了几对(假钱包里两两都算好友);形状不对 bad_request,没绑游戏 bad_game */
257
+ async together(req: unknown): Promise<{ ok: true; pairs: number } | { ok: false; error: string }> {
258
+ const game = this.bound();
259
+ if (!game) return { ok: false, error: 'bad_game' };
260
+ const q = parseTogether(req);
261
+ if (!q) return { ok: false, error: 'bad_request' };
262
+ const fresh = await Promise.all(q.players.map((p) => bank(this.env, p.userId).addTogether(game, q.op, q.players)));
263
+ let pairs = 0;
264
+ for (let i = 0; i < fresh.length; i++) for (let j = i + 1; j < fresh.length; j++) if (fresh[i] && fresh[j]) pairs++;
265
+ return { ok: true, pairs };
266
+ }
267
+
243
268
  private bound(): string | null {
244
269
  const g = this.ctx.props?.game;
245
270
  return typeof g === 'string' && g !== '' ? g : null;
@@ -262,6 +287,25 @@ export class WalletService extends WorkerEntrypoint<FakeEnv, { game?: string }>
262
287
  }
263
288
  }
264
289
 
290
+ /** 平台 parseTogether 的同一套检查(15.19):形状不对回 null */
291
+ export function parseTogether(raw: unknown): { op: string; players: TogetherPlayer[] } | null {
292
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;
293
+ const b = raw as Record<string, unknown>;
294
+ if (typeof b.op !== 'string' || !ID.test(b.op)) return null;
295
+ if (!Array.isArray(b.players) || b.players.length < 2 || b.players.length > TOGETHER_MAX) return null;
296
+ const players: TogetherPlayer[] = [];
297
+ const seen = new Set<string>();
298
+ for (const p of b.players as unknown[]) {
299
+ if (!p || typeof p !== 'object' || Array.isArray(p)) return null;
300
+ const { userId, team, win } = p as Record<string, unknown>;
301
+ if (typeof userId !== 'string' || !/^[A-Za-z0-9_-]{1,64}$/.test(userId) || seen.has(userId) || typeof win !== 'boolean') return null;
302
+ if (team !== undefined && !(Number.isInteger(team) && (team as number) >= 0 && (team as number) <= 3)) return null;
303
+ seen.add(userId);
304
+ players.push(team === undefined ? { userId, win } : { userId, team: team as number, win });
305
+ }
306
+ return { op: b.op, players };
307
+ }
308
+
265
309
  /** 5.10 的检查:JSON 后 ≤ 256 字节;rounds、wins、best 非负整数;称号最多 5 个、格式;max + sum 最多 3 个 key、值是安全整数 */
266
310
  export function statsProblem(x: unknown): StatsProblem | undefined {
267
311
  if (JSON.stringify(x).length > 256) return 'too_big';