@zhin.js/plugin-tic-tac-toe 1.0.1 → 1.0.2

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.
Files changed (60) hide show
  1. package/commands/ttt/[action:string=].ts +15 -0
  2. package/lib/board-view.d.ts +2 -3
  3. package/lib/board-view.js +1 -1
  4. package/lib/board-view.js.map +1 -1
  5. package/lib/engine.d.ts +0 -1
  6. package/lib/game-flow.d.ts +6 -7
  7. package/lib/game-flow.js +24 -14
  8. package/lib/game-flow.js.map +1 -1
  9. package/lib/index.d.ts +8 -2
  10. package/lib/index.js +6 -34
  11. package/lib/index.js.map +1 -1
  12. package/lib/memory-db.d.ts +6 -0
  13. package/lib/memory-db.js +18 -0
  14. package/lib/memory-db.js.map +1 -0
  15. package/lib/models.d.ts +5 -4
  16. package/lib/models.js +5 -5
  17. package/lib/models.js.map +1 -1
  18. package/lib/player-label.d.ts +1 -2
  19. package/lib/runtime-store.d.ts +6 -0
  20. package/lib/runtime-store.js +7 -0
  21. package/lib/runtime-store.js.map +1 -0
  22. package/lib/session-service.d.ts +1 -3
  23. package/lib/session-service.js +1 -4
  24. package/lib/session-service.js.map +1 -1
  25. package/lib/ttt-command.d.ts +4 -3
  26. package/lib/ttt-command.js +8 -3
  27. package/lib/ttt-command.js.map +1 -1
  28. package/middlewares/ttt-alias.ts +18 -0
  29. package/middlewares/ttt-choice.ts +71 -0
  30. package/package.json +36 -18
  31. package/plugin.ts +64 -0
  32. package/schema.json +6 -0
  33. package/src/board-view.ts +2 -2
  34. package/src/game-flow.ts +31 -24
  35. package/src/index.ts +7 -39
  36. package/src/memory-db.ts +22 -0
  37. package/src/models.ts +10 -10
  38. package/src/player-label.ts +1 -1
  39. package/src/runtime-store.ts +9 -0
  40. package/src/session-service.ts +2 -5
  41. package/src/ttt-command.ts +15 -5
  42. package/lib/board-view.d.ts.map +0 -1
  43. package/lib/commands.d.ts +0 -6
  44. package/lib/commands.d.ts.map +0 -1
  45. package/lib/commands.js +0 -129
  46. package/lib/commands.js.map +0 -1
  47. package/lib/engine.d.ts.map +0 -1
  48. package/lib/game-flow.d.ts.map +0 -1
  49. package/lib/hub-register.d.ts +0 -5
  50. package/lib/hub-register.d.ts.map +0 -1
  51. package/lib/hub-register.js +0 -30
  52. package/lib/hub-register.js.map +0 -1
  53. package/lib/index.d.ts.map +0 -1
  54. package/lib/models.d.ts.map +0 -1
  55. package/lib/player-label.d.ts.map +0 -1
  56. package/lib/session-service.d.ts.map +0 -1
  57. package/lib/ttt-command.d.ts.map +0 -1
  58. package/plugin.yml +0 -2
  59. package/src/commands.ts +0 -157
  60. package/src/hub-register.ts +0 -31
package/lib/commands.js DELETED
@@ -1,129 +0,0 @@
1
- import { MessageCommand, getActionFromMessage } from 'zhin.js';
2
- import { channelKey, normalizeTttAction, parseChoicePayload, registerGameTextMiddleware, resolveGameChoice, resolveGameTextPayload, } from '@zhin.js/game-shared';
3
- import { buildFallbackMap, TTT_PREFIX } from './board-view.js';
4
- import { parseBoard } from './engine.js';
5
- import { handleMove, restartFromTerminal } from './game-flow.js';
6
- import { runTttCommand } from './ttt-command.js';
7
- function actionPayload(message) {
8
- return getActionFromMessage(message)?.payload;
9
- }
10
- function parseTttPayload(payload) {
11
- const m = /^ttt:([^:]+):(\d)$/.exec(payload);
12
- if (!m)
13
- return null;
14
- return { sessionId: m[1], cell: Number(m[2]) };
15
- }
16
- function parseCellButtonId(id) {
17
- const m = /^c(\d)$/.exec(id);
18
- if (!m)
19
- return null;
20
- const cell = Number(m[1]);
21
- return cell >= 0 && cell <= 8 ? cell : null;
22
- }
23
- async function resolveTttAction(message, services) {
24
- const restart = await resolveGameChoice({
25
- message,
26
- gamePrefix: TTT_PREFIX,
27
- validChoiceIds: ['restart'],
28
- getById: (id) => services.session.getById(id),
29
- getActiveForUser: (ch, uid) => services.session.getActiveForUser(ch, uid),
30
- getByBoardMessageId: (mid) => services.session.getActiveByBoardMessageId(mid),
31
- });
32
- if (restart)
33
- return { kind: 'restart', sessionId: restart.sessionId };
34
- const action = getActionFromMessage(message);
35
- if (!action)
36
- return null;
37
- const fromPayload = parseTttPayload(action.payload);
38
- if (fromPayload)
39
- return { kind: 'move', ...fromPayload };
40
- const cell = parseCellButtonId(action.payload)
41
- ?? parseCellButtonId(action.id ?? '');
42
- if (cell == null)
43
- return null;
44
- const ch = channelKey(message);
45
- const session = await services.session.getActiveForUser(ch, message.$sender.id)
46
- ?? (action.sourceMessageId
47
- ? await services.session.getActiveByBoardMessageId(action.sourceMessageId)
48
- : null);
49
- if (!session || session.channel_key !== ch)
50
- return null;
51
- return { kind: 'move', sessionId: session.id, cell };
52
- }
53
- export function registerCommands(plugin, getServices) {
54
- registerTttPattern(plugin, '/ttt [action:word]', '井字棋(ttt)', getServices);
55
- registerTttPattern(plugin, '/井字棋 [action:word]', '井字棋(中文)', getServices);
56
- }
57
- function registerTttPattern(plugin, pattern, desc, getServices) {
58
- plugin.addCommand(new MessageCommand(pattern)
59
- .desc(desc)
60
- .action(async (message, result) => {
61
- const services = getServices();
62
- if (!services)
63
- return '井字棋需要启用 database 配置。';
64
- const raw = result.params.action ?? '';
65
- return runTttCommand(plugin, services, message, normalizeTttAction(raw));
66
- }));
67
- }
68
- async function handleTttAction(plugin, getServices, message) {
69
- const services = getServices();
70
- if (!services)
71
- return false;
72
- const action = await resolveTttAction(message, services);
73
- if (!action)
74
- return false;
75
- if (action.kind === 'restart') {
76
- const err = await restartFromTerminal(plugin, services, message, action.sessionId);
77
- if (err)
78
- await message.$reply?.(err);
79
- return true;
80
- }
81
- const err = await handleMove(plugin, services, message, action.sessionId, action.cell);
82
- if (err)
83
- await message.$reply?.(err);
84
- return true;
85
- }
86
- export function registerInteractive(plugin, getServices) {
87
- plugin.registerInteractiveHandler('ttt:', (message) => handleTttAction(plugin, getServices, message));
88
- plugin.registerInteractiveHandler('c', (message) => handleTttAction(plugin, getServices, message));
89
- }
90
- export function registerTextFallback(plugin, getServices) {
91
- registerGameTextMiddleware(plugin, async (message, next) => {
92
- const services = getServices();
93
- if (!services)
94
- return next();
95
- const inboundAction = actionPayload(message);
96
- if (inboundAction?.startsWith('ttt:'))
97
- return next();
98
- const raw = message.$raw?.trim() ?? '';
99
- const ch = channelKey(message);
100
- const payloadFromText = resolveGameTextPayload(raw);
101
- if (payloadFromText?.startsWith(`${TTT_PREFIX}:`)) {
102
- const parsed = parseChoicePayload(payloadFromText, TTT_PREFIX);
103
- if (parsed?.choiceId === 'restart') {
104
- const session = await services.session.getById(parsed.sessionId);
105
- if (session?.channel_key === ch) {
106
- const err = await restartFromTerminal(plugin, services, message, parsed.sessionId);
107
- if (err)
108
- await message.$reply?.(err);
109
- return;
110
- }
111
- }
112
- }
113
- const session = await services.session.getActiveForUser(ch, message.$sender.id);
114
- if (!session)
115
- return next();
116
- let cell = null;
117
- const map = buildFallbackMap(session.id, parseBoard(session.board));
118
- const payloadText = resolveGameTextPayload(raw, map);
119
- const p = payloadText ? parseTttPayload(payloadText) : null;
120
- if (p?.sessionId === session.id)
121
- cell = p.cell;
122
- if (cell == null)
123
- return next();
124
- const err = await handleMove(plugin, services, message, session.id, cell);
125
- if (err)
126
- await message.$reply?.(err);
127
- }, 'ttt:text');
128
- }
129
- //# sourceMappingURL=commands.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,CAAC,IAAI,CAAC;AACnB,eAAO,MAAM,CAAC,IAAI,CAAC;AAEnB,MAAM,MAAM,IAAI,GAAG,OAAO,KAAK,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtD,MAAM,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;AAE3B,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAQ/D,wBAAgB,UAAU,IAAI,KAAK,CAElC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAa3E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAI5C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAYrE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CASjF;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE5C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAKzE;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAE3C;AAED,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,GAAE,IAAQ,GAAG,MAAM,CAe3D;AA0BD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,IAAI,CAIvG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"game-flow.d.ts","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAejD,OAAO,EACL,MAAM,EAOP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAE5D;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,UAAQ,EAChB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,MAAM,CAAC,CAmCjB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AAUD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsFxB;AAqBD,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GACpB,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -1,5 +0,0 @@
1
- import { TTT_HELP } from './ttt-command.js';
2
- import type { SessionServices } from './session-service.js';
3
- export declare function registerTttHub(getServices: () => SessionServices | null): () => void;
4
- export { TTT_HELP };
5
- //# sourceMappingURL=hub-register.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hub-register.d.ts","sourceRoot":"","sources":["../src/hub-register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,eAAe,GAAG,IAAI,GAAG,MAAM,IAAI,CAuBpF;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1,30 +0,0 @@
1
- import { getPlugin } from 'zhin.js';
2
- import { ensureGameHubService } from '@zhin.js/game-shared';
3
- import { runTttCommand, TTT_HELP } from './ttt-command.js';
4
- export function registerTttHub(getServices) {
5
- const plugin = getPlugin();
6
- ensureGameHubService(plugin);
7
- return plugin.registerGame({
8
- id: 'ttt',
9
- title: '井字棋',
10
- icon: '♟️',
11
- description: '三子连珠,群聊排队或人机对战',
12
- commandPrefix: '/井字棋',
13
- quickStart: '人机',
14
- aliases: ['ttt'],
15
- menus: [
16
- { id: 'bot', label: '🤖 人机对战', style: 'primary' },
17
- { id: 'join', label: '👥 加入排队', groupOnly: true },
18
- { id: 'spectate', label: '👀 观战', groupOnly: true },
19
- { id: 'help', label: '📖 玩法说明' },
20
- ],
21
- runAction: async (actionId, ctx) => {
22
- const services = getServices();
23
- if (!services)
24
- return '井字棋需要启用 database 配置。';
25
- return runTttCommand(ctx.plugin, services, ctx.message, actionId);
26
- },
27
- });
28
- }
29
- export { TTT_HELP };
30
- //# sourceMappingURL=hub-register.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hub-register.js","sourceRoot":"","sources":["../src/hub-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG3D,MAAM,UAAU,cAAc,CAAC,WAAyC;IACtE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC;QACzB,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,gBAAgB;QAC7B,aAAa,EAAE,MAAM;QACrB,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,KAAK,EAAE;YACL,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACjD,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;YACjD,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;YACnD,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE;SACjC;QACD,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,sBAAsB,CAAC;YAC7C,OAAO,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACpE,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAErE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM;QACd,YAAY,EAAE;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,OAAO,EAAE,MAAM,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,EAAE,MAAM,CAAC;YACnB,WAAW,EAAE,MAAM,CAAC;YACpB,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;YACjB,aAAa,EAAE,MAAM,CAAC;YACtB,aAAa,EAAE,MAAM,CAAC;YACtB,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,gBAAgB,CAAC;YACzB,MAAM,EAAE,MAAM,CAAC;YACf,gBAAgB,EAAE,MAAM,CAAC;YACzB,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,SAAS,EAAE;YACT,EAAE,EAAE,MAAM,CAAC;YACX,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC;QACF,SAAS,EAAE;YACT,EAAE,EAAE,MAAM,CAAC;YACX,UAAU,EAAE,MAAM,CAAC;YACnB,SAAS,EAAE,MAAM,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,cAAc,EAAE;YACd,EAAE,EAAE,MAAM,CAAC;YACX,UAAU,EAAE,MAAM,CAAC;YACnB,OAAO,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC;KACH;CACF;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AACnD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAC9C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAC7C,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEvD,iBAAiB;AACjB,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAEzF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA6CnD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"player-label.d.ts","sourceRoot":"","sources":["../src/player-label.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAQ,KAAK,IAAI,EAAa,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,MAAM,gBAAgB,CAAC;AAEpC,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,MAAM,CAGpF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAI/E;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,IAAI,EAAE,GAAG,GAAG,GAAG,GACd,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE/D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAGlG;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM,CAG9E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-service.d.ts","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ttt-command.d.ts","sourceRoot":"","sources":["../src/ttt-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,eAAO,MAAM,QAAQ,QAQT,CAAC;AAEb,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsD7B"}
package/plugin.yml DELETED
@@ -1,2 +0,0 @@
1
- name: "@zhin.js/plugin-tic-tac-toe"
2
- description: "跨平台井字棋游戏"
package/src/commands.ts DELETED
@@ -1,157 +0,0 @@
1
- import { Message, MessageCommand, getActionFromMessage, type Plugin } from 'zhin.js';
2
- import {
3
- channelKey,
4
- normalizeTttAction,
5
- parseChoicePayload,
6
- registerGameTextMiddleware,
7
- resolveGameChoice,
8
- resolveGameTextPayload,
9
- } from '@zhin.js/game-shared';
10
- import { buildFallbackMap, TTT_PREFIX } from './board-view.js';
11
- import { parseBoard } from './engine.js';
12
- import { handleMove, restartFromTerminal } from './game-flow.js';
13
- import { runTttCommand } from './ttt-command.js';
14
- import type { SessionServices } from './session-service.js';
15
-
16
- function actionPayload(message: Message<any>): string | undefined {
17
- return getActionFromMessage(message)?.payload;
18
- }
19
-
20
- function parseTttPayload(payload: string): { sessionId: string; cell: number } | null {
21
- const m = /^ttt:([^:]+):(\d)$/.exec(payload);
22
- if (!m) return null;
23
- return { sessionId: m[1]!, cell: Number(m[2]) };
24
- }
25
-
26
- function parseCellButtonId(id: string): number | null {
27
- const m = /^c(\d)$/.exec(id);
28
- if (!m) return null;
29
- const cell = Number(m[1]);
30
- return cell >= 0 && cell <= 8 ? cell : null;
31
- }
32
-
33
- async function resolveTttAction(
34
- message: Message<any>,
35
- services: SessionServices,
36
- ): Promise<{ kind: 'move'; sessionId: string; cell: number } | { kind: 'restart'; sessionId: string } | null> {
37
- const restart = await resolveGameChoice({
38
- message,
39
- gamePrefix: TTT_PREFIX,
40
- validChoiceIds: ['restart'],
41
- getById: (id) => services.session.getById(id),
42
- getActiveForUser: (ch, uid) => services.session.getActiveForUser(ch, uid),
43
- getByBoardMessageId: (mid) => services.session.getActiveByBoardMessageId(mid),
44
- });
45
- if (restart) return { kind: 'restart', sessionId: restart.sessionId };
46
-
47
- const action = getActionFromMessage(message);
48
- if (!action) return null;
49
-
50
- const fromPayload = parseTttPayload(action.payload);
51
- if (fromPayload) return { kind: 'move', ...fromPayload };
52
-
53
- const cell =
54
- parseCellButtonId(action.payload)
55
- ?? parseCellButtonId(action.id ?? '');
56
- if (cell == null) return null;
57
-
58
- const ch = channelKey(message);
59
- const session =
60
- await services.session.getActiveForUser(ch, message.$sender.id)
61
- ?? (action.sourceMessageId
62
- ? await services.session.getActiveByBoardMessageId(action.sourceMessageId)
63
- : null);
64
- if (!session || session.channel_key !== ch) return null;
65
- return { kind: 'move', sessionId: session.id, cell };
66
- }
67
-
68
- export function registerCommands(
69
- plugin: Plugin,
70
- getServices: () => SessionServices | null,
71
- ): void {
72
- registerTttPattern(plugin, '/ttt [action:word]', '井字棋(ttt)', getServices);
73
- registerTttPattern(plugin, '/井字棋 [action:word]', '井字棋(中文)', getServices);
74
- }
75
-
76
- function registerTttPattern(
77
- plugin: Plugin,
78
- pattern: string,
79
- desc: string,
80
- getServices: () => SessionServices | null,
81
- ): void {
82
- plugin.addCommand(
83
- new MessageCommand(pattern)
84
- .desc(desc)
85
- .action(async (message, result) => {
86
- const services = getServices();
87
- if (!services) return '井字棋需要启用 database 配置。';
88
- const raw = (result.params.action as string | undefined) ?? '';
89
- return runTttCommand(plugin, services, message, normalizeTttAction(raw));
90
- }),
91
- );
92
- }
93
-
94
- async function handleTttAction(
95
- plugin: Plugin,
96
- getServices: () => SessionServices | null,
97
- message: Message<any>,
98
- ): Promise<boolean> {
99
- const services = getServices();
100
- if (!services) return false;
101
- const action = await resolveTttAction(message, services);
102
- if (!action) return false;
103
-
104
- if (action.kind === 'restart') {
105
- const err = await restartFromTerminal(plugin, services, message, action.sessionId);
106
- if (err) await message.$reply?.(err);
107
- return true;
108
- }
109
-
110
- const err = await handleMove(plugin, services, message, action.sessionId, action.cell);
111
- if (err) await message.$reply?.(err);
112
- return true;
113
- }
114
-
115
- export function registerInteractive(plugin: Plugin, getServices: () => SessionServices | null): void {
116
- plugin.registerInteractiveHandler('ttt:', (message) => handleTttAction(plugin, getServices, message));
117
- plugin.registerInteractiveHandler('c', (message) => handleTttAction(plugin, getServices, message));
118
- }
119
-
120
- export function registerTextFallback(plugin: Plugin, getServices: () => SessionServices | null): void {
121
- registerGameTextMiddleware(plugin, async (message, next) => {
122
- const services = getServices();
123
- if (!services) return next();
124
-
125
- const inboundAction = actionPayload(message);
126
- if (inboundAction?.startsWith('ttt:')) return next();
127
-
128
- const raw = message.$raw?.trim() ?? '';
129
- const ch = channelKey(message);
130
-
131
- const payloadFromText = resolveGameTextPayload(raw);
132
- if (payloadFromText?.startsWith(`${TTT_PREFIX}:`)) {
133
- const parsed = parseChoicePayload(payloadFromText, TTT_PREFIX);
134
- if (parsed?.choiceId === 'restart') {
135
- const session = await services.session.getById(parsed.sessionId);
136
- if (session?.channel_key === ch) {
137
- const err = await restartFromTerminal(plugin, services, message, parsed.sessionId);
138
- if (err) await message.$reply?.(err);
139
- return;
140
- }
141
- }
142
- }
143
-
144
- const session = await services.session.getActiveForUser(ch, message.$sender.id);
145
- if (!session) return next();
146
-
147
- let cell: number | null = null;
148
- const map = buildFallbackMap(session.id, parseBoard(session.board));
149
- const payloadText = resolveGameTextPayload(raw, map);
150
- const p = payloadText ? parseTttPayload(payloadText) : null;
151
- if (p?.sessionId === session.id) cell = p.cell;
152
- if (cell == null) return next();
153
-
154
- const err = await handleMove(plugin, services, message, session.id, cell);
155
- if (err) await message.$reply?.(err);
156
- }, 'ttt:text');
157
- }
@@ -1,31 +0,0 @@
1
- import { getPlugin } from 'zhin.js';
2
- import { ensureGameHubService } from '@zhin.js/game-shared';
3
- import { runTttCommand, TTT_HELP } from './ttt-command.js';
4
- import type { SessionServices } from './session-service.js';
5
-
6
- export function registerTttHub(getServices: () => SessionServices | null): () => void {
7
- const plugin = getPlugin();
8
- ensureGameHubService(plugin);
9
- return plugin.registerGame({
10
- id: 'ttt',
11
- title: '井字棋',
12
- icon: '♟️',
13
- description: '三子连珠,群聊排队或人机对战',
14
- commandPrefix: '/井字棋',
15
- quickStart: '人机',
16
- aliases: ['ttt'],
17
- menus: [
18
- { id: 'bot', label: '🤖 人机对战', style: 'primary' },
19
- { id: 'join', label: '👥 加入排队', groupOnly: true },
20
- { id: 'spectate', label: '👀 观战', groupOnly: true },
21
- { id: 'help', label: '📖 玩法说明' },
22
- ],
23
- runAction: async (actionId, ctx) => {
24
- const services = getServices();
25
- if (!services) return '井字棋需要启用 database 配置。';
26
- return runTttCommand(ctx.plugin, services, ctx.message, actionId);
27
- },
28
- });
29
- }
30
-
31
- export { TTT_HELP };