@zhin.js/game-kit 1.0.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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/lib/board-sender.d.ts +14 -0
  4. package/lib/board-sender.d.ts.map +1 -0
  5. package/lib/board-sender.js +7 -0
  6. package/lib/board-sender.js.map +1 -0
  7. package/lib/choice-keyboard.d.ts +44 -0
  8. package/lib/choice-keyboard.d.ts.map +1 -0
  9. package/lib/choice-keyboard.js +67 -0
  10. package/lib/choice-keyboard.js.map +1 -0
  11. package/lib/command-alias.d.ts +21 -0
  12. package/lib/command-alias.d.ts.map +1 -0
  13. package/lib/command-alias.js +22 -0
  14. package/lib/command-alias.js.map +1 -0
  15. package/lib/command-help.d.ts +19 -0
  16. package/lib/command-help.d.ts.map +1 -0
  17. package/lib/command-help.js +91 -0
  18. package/lib/command-help.js.map +1 -0
  19. package/lib/command-message.d.ts +25 -0
  20. package/lib/command-message.d.ts.map +1 -0
  21. package/lib/command-message.js +58 -0
  22. package/lib/command-message.js.map +1 -0
  23. package/lib/game-action-alias.d.ts +8 -0
  24. package/lib/game-action-alias.d.ts.map +1 -0
  25. package/lib/game-action-alias.js +117 -0
  26. package/lib/game-action-alias.js.map +1 -0
  27. package/lib/game-commands.d.ts +3 -0
  28. package/lib/game-commands.d.ts.map +1 -0
  29. package/lib/game-commands.js +5 -0
  30. package/lib/game-commands.js.map +1 -0
  31. package/lib/game-hub-feature.d.ts +58 -0
  32. package/lib/game-hub-feature.d.ts.map +1 -0
  33. package/lib/game-hub-feature.js +100 -0
  34. package/lib/game-hub-feature.js.map +1 -0
  35. package/lib/game-hub-flow.d.ts +9 -0
  36. package/lib/game-hub-flow.d.ts.map +1 -0
  37. package/lib/game-hub-flow.js +90 -0
  38. package/lib/game-hub-flow.js.map +1 -0
  39. package/lib/game-hub-menu-context.d.ts +25 -0
  40. package/lib/game-hub-menu-context.d.ts.map +1 -0
  41. package/lib/game-hub-menu-context.js +64 -0
  42. package/lib/game-hub-menu-context.js.map +1 -0
  43. package/lib/game-hub-menu.d.ts +37 -0
  44. package/lib/game-hub-menu.d.ts.map +1 -0
  45. package/lib/game-hub-menu.js +162 -0
  46. package/lib/game-hub-menu.js.map +1 -0
  47. package/lib/game-hub-mount.d.ts +9 -0
  48. package/lib/game-hub-mount.d.ts.map +1 -0
  49. package/lib/game-hub-mount.js +108 -0
  50. package/lib/game-hub-mount.js.map +1 -0
  51. package/lib/game-interactive.d.ts +25 -0
  52. package/lib/game-interactive.d.ts.map +1 -0
  53. package/lib/game-interactive.js +62 -0
  54. package/lib/game-interactive.js.map +1 -0
  55. package/lib/game-middleware.d.ts +6 -0
  56. package/lib/game-middleware.d.ts.map +1 -0
  57. package/lib/game-middleware.js +9 -0
  58. package/lib/game-middleware.js.map +1 -0
  59. package/lib/game-onboarding.d.ts +8 -0
  60. package/lib/game-onboarding.d.ts.map +1 -0
  61. package/lib/game-onboarding.js +66 -0
  62. package/lib/game-onboarding.js.map +1 -0
  63. package/lib/game-records.d.ts +52 -0
  64. package/lib/game-records.d.ts.map +1 -0
  65. package/lib/game-records.js +206 -0
  66. package/lib/game-records.js.map +1 -0
  67. package/lib/game-session.d.ts +64 -0
  68. package/lib/game-session.d.ts.map +1 -0
  69. package/lib/game-session.js +44 -0
  70. package/lib/game-session.js.map +1 -0
  71. package/lib/grid-keyboard.d.ts +67 -0
  72. package/lib/grid-keyboard.d.ts.map +1 -0
  73. package/lib/grid-keyboard.js +104 -0
  74. package/lib/grid-keyboard.js.map +1 -0
  75. package/lib/help-card.d.ts +12 -0
  76. package/lib/help-card.d.ts.map +1 -0
  77. package/lib/help-card.js +129 -0
  78. package/lib/help-card.js.map +1 -0
  79. package/lib/index.d.ts +29 -0
  80. package/lib/index.d.ts.map +1 -0
  81. package/lib/index.js +29 -0
  82. package/lib/index.js.map +1 -0
  83. package/lib/interaction-profiles.d.ts +16 -0
  84. package/lib/interaction-profiles.d.ts.map +1 -0
  85. package/lib/interaction-profiles.js +35 -0
  86. package/lib/interaction-profiles.js.map +1 -0
  87. package/lib/memory-db.d.ts +41 -0
  88. package/lib/memory-db.d.ts.map +1 -0
  89. package/lib/memory-db.js +92 -0
  90. package/lib/memory-db.js.map +1 -0
  91. package/lib/random.d.ts +6 -0
  92. package/lib/random.d.ts.map +1 -0
  93. package/lib/random.js +29 -0
  94. package/lib/random.js.map +1 -0
  95. package/lib/runtime-hub.d.ts +28 -0
  96. package/lib/runtime-hub.d.ts.map +1 -0
  97. package/lib/runtime-hub.js +66 -0
  98. package/lib/runtime-hub.js.map +1 -0
  99. package/lib/send-content-text.d.ts +5 -0
  100. package/lib/send-content-text.d.ts.map +1 -0
  101. package/lib/send-content-text.js +24 -0
  102. package/lib/send-content-text.js.map +1 -0
  103. package/package.json +49 -0
  104. package/src/board-sender.ts +16 -0
  105. package/src/choice-keyboard.ts +117 -0
  106. package/src/command-alias.ts +45 -0
  107. package/src/command-help.ts +117 -0
  108. package/src/command-message.ts +76 -0
  109. package/src/game-action-alias.ts +129 -0
  110. package/src/game-commands.ts +4 -0
  111. package/src/game-hub-feature.ts +151 -0
  112. package/src/game-hub-flow.ts +114 -0
  113. package/src/game-hub-menu-context.ts +94 -0
  114. package/src/game-hub-menu.ts +223 -0
  115. package/src/game-hub-mount.ts +172 -0
  116. package/src/game-interactive.ts +88 -0
  117. package/src/game-middleware.ts +14 -0
  118. package/src/game-onboarding.ts +67 -0
  119. package/src/game-records.ts +287 -0
  120. package/src/game-session.ts +97 -0
  121. package/src/grid-keyboard.ts +180 -0
  122. package/src/help-card.ts +188 -0
  123. package/src/index.ts +29 -0
  124. package/src/interaction-profiles.ts +56 -0
  125. package/src/memory-db.ts +128 -0
  126. package/src/random.ts +32 -0
  127. package/src/runtime-hub.ts +86 -0
  128. package/src/send-content-text.ts +21 -0
@@ -0,0 +1,162 @@
1
+ import { segment } from '@zhin.js/core';
2
+ import { buildChoiceKeyboard } from './choice-keyboard.js';
3
+ import { slashCommandPrefix } from './game-commands.js';
4
+ import { formatHubOpenCommandLines, formatSupplementaryCommandsHelp, } from './command-help.js';
5
+ import { buildBotHelpHtml, buildHubHelpHtml, HELP_CARD_CANVAS, HELP_CARD_WIDTH, } from './help-card.js';
6
+ export const HUB_PREFIX = 'hub';
7
+ export function hubGameChoiceId(gameId) {
8
+ return `g_${gameId}`;
9
+ }
10
+ export function hubActionChoiceId(gameId, actionId) {
11
+ return `a_${gameId}_${actionId}`;
12
+ }
13
+ export function parseHubChoiceId(choiceId) {
14
+ if (choiceId === 'back')
15
+ return { kind: 'back' };
16
+ if (choiceId.startsWith('g_'))
17
+ return { kind: 'game', gameId: choiceId.slice(2) };
18
+ if (choiceId.startsWith('a_')) {
19
+ const rest = choiceId.slice(2);
20
+ const sep = rest.indexOf('_');
21
+ if (sep <= 0)
22
+ return null;
23
+ return {
24
+ kind: 'action',
25
+ gameId: rest.slice(0, sep),
26
+ actionId: rest.slice(sep + 1),
27
+ };
28
+ }
29
+ return null;
30
+ }
31
+ export function buildMainHubMenu(scopeId, games, channelType) {
32
+ const cmdHint = formatCommandPrefixHint(games);
33
+ const lines = [
34
+ '🎮 **游戏大厅**',
35
+ '',
36
+ cmdHint,
37
+ '',
38
+ '_同频道均可浏览;开局后仅对局玩家可操作棋盘。_',
39
+ '',
40
+ ];
41
+ for (const g of games) {
42
+ lines.push(`• ${g.icon} **${g.title}** — ${g.description}`);
43
+ }
44
+ return buildChoiceKeyboard({
45
+ gamePrefix: HUB_PREFIX,
46
+ sessionId: scopeId,
47
+ narrative: lines.join('\n'),
48
+ choices: games.map((g) => ({
49
+ id: hubGameChoiceId(g.id),
50
+ label: `${g.icon} ${g.title}`,
51
+ style: 'primary',
52
+ })),
53
+ buttonsPerRow: 2,
54
+ fallbackHint: '回复数字进入对应游戏',
55
+ interactionProfile: 'menu',
56
+ channelType,
57
+ });
58
+ }
59
+ export function buildGameHubMenu(scopeId, game, channelType) {
60
+ const isGroup = channelType !== 'private';
61
+ const menus = game.menus.filter((m) => {
62
+ if (m.groupOnly && !isGroup)
63
+ return false;
64
+ if (m.privateOnly && isGroup)
65
+ return false;
66
+ return true;
67
+ });
68
+ return buildChoiceKeyboard({
69
+ gamePrefix: HUB_PREFIX,
70
+ sessionId: scopeId,
71
+ narrative: `${game.icon} **${game.title}**\n\n${game.description}\n\n请选择:`,
72
+ choices: [
73
+ ...menus.map((m) => ({
74
+ id: hubActionChoiceId(game.id, m.id),
75
+ label: m.label,
76
+ style: m.style,
77
+ })),
78
+ { id: 'back', label: '↩️ 返回大厅' },
79
+ ],
80
+ buttonsPerRow: 2,
81
+ fallbackHint: '回复数字选择操作',
82
+ interactionProfile: 'menu',
83
+ channelType,
84
+ });
85
+ }
86
+ /** 大厅主菜单:命令前缀提示 */
87
+ export function formatCommandPrefixHint(games) {
88
+ if (!games.length)
89
+ return '暂无可用游戏。';
90
+ const sample = games.slice(0, 5).map((g) => slashCommandPrefix(g.commandPrefix.replace(/^\//, '')));
91
+ const tail = games.length > sample.length ? '等' : '';
92
+ return `选择想玩的游戏(也可直接发送斜杠命令,如「${sample.join('」「')}」${tail}):`;
93
+ }
94
+ /** 游戏大厅帮助文案(随 registerGame 动态生成) */
95
+ export function formatHubHelp(games, commands) {
96
+ const lines = [
97
+ '🎮 **游戏大厅**',
98
+ '',
99
+ ...formatHubOpenCommandLines(commands),
100
+ ];
101
+ if (!games.length) {
102
+ lines.push('', '当前暂无已注册游戏。', '请安装任意游戏插件(registerGame 会自动挂载大厅)。');
103
+ return lines.join('\n');
104
+ }
105
+ lines.push('', `当前已注册 **${games.length}** 款游戏:`, '');
106
+ for (const g of games) {
107
+ const quick = g.quickStart ?? '开始';
108
+ const alias = g.aliases?.length ? ` · ${g.aliases.join(' / ')}` : '';
109
+ lines.push(`• ${g.icon} **${g.title}**${alias}`);
110
+ lines.push(` 命令:\`${slashCommandPrefix(g.commandPrefix.replace(/^\//, ''))} ${quick}\` — ${g.description}`);
111
+ }
112
+ return lines.join('\n');
113
+ }
114
+ /** 顶层 /帮助:游戏大厅 + 已注册命令自动汇总 */
115
+ export function formatBotHelp(games, options) {
116
+ const commands = options?.commands;
117
+ const sections = [formatHubHelp(games, commands)];
118
+ const other = commands?.length
119
+ ? formatSupplementaryCommandsHelp(commands, games)
120
+ : '';
121
+ if (other) {
122
+ sections.push('', '---', '', other);
123
+ }
124
+ if (options?.channelType === 'group') {
125
+ sections.push('', '**QQ 群用法**', '• 公域群需 **@ 机器人** 后发送命令,或直接 **点击消息按钮**', '• 发送 `/游戏` 打开大厅,同群成员均可点击按钮');
126
+ }
127
+ return sections.join('\n');
128
+ }
129
+ /** 顶层 /帮助:HTML 卡片(QQ 等出站 policy 为 image 时渲染为 PNG;无 renderer 时回退文本) */
130
+ export function buildBotHelpReply(games, options) {
131
+ const text = formatBotHelp(games, options);
132
+ return segment.html({
133
+ html: buildBotHelpHtml({
134
+ games,
135
+ commands: options?.commands,
136
+ channelType: options?.channelType,
137
+ }),
138
+ text,
139
+ width: HELP_CARD_WIDTH,
140
+ backgroundColor: HELP_CARD_CANVAS,
141
+ fileName: 'bot-help.png',
142
+ });
143
+ }
144
+ /** /游戏 帮助:大厅专用卡片 */
145
+ export function buildHubHelpReply(games, commands) {
146
+ const text = formatHubHelp(games, commands);
147
+ return segment.html({
148
+ html: buildHubHelpHtml(games, commands),
149
+ text,
150
+ width: HELP_CARD_WIDTH,
151
+ backgroundColor: HELP_CARD_CANVAS,
152
+ fileName: 'game-hub-help.png',
153
+ });
154
+ }
155
+ /** 无游戏时的提示 */
156
+ export function formatHubEmptyMessage() {
157
+ return [
158
+ '游戏大厅暂无可用游戏。',
159
+ '请安装任意游戏插件;首个游戏 registerGame 时会自动挂载大厅命令。',
160
+ ].join('');
161
+ }
162
+ //# sourceMappingURL=game-hub-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-hub-menu.js","sourceRoot":"","sources":["../src/game-hub-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAoB,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EACL,yBAAyB,EACzB,+BAA+B,GAEhC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC;AAEhC,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,KAAK,MAAM,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAgB;IAChE,OAAO,KAAK,MAAM,IAAI,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAgB;IAMhB,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACjD,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YAC1B,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;SAC9B,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,KAAgC,EAChC,WAAmB;IAEnB,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG;QACZ,aAAa;QACb,EAAE;QACF,OAAO;QACP,EAAE;QACF,0BAA0B;QAC1B,EAAE;KACH,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,mBAAmB,CAAC;QACzB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3B,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzB,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE;YAC7B,KAAK,EAAE,SAAkB;SAC1B,CAAC,CAAC;QACH,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,YAAY;QAC1B,kBAAkB,EAAE,MAAM;QAC1B,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,IAAoB,EACpB,WAAmB;IAEnB,MAAM,OAAO,GAAG,WAAW,KAAK,SAAS,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC1C,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,OAAO,mBAAmB,CAAC;QACzB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,GAAG,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,WAAW,UAAU;QAC1E,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnB,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;gBACpC,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK;aACf,CAAC,CAAC;YACH,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE;SACjC;QACD,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,UAAU;QACxB,kBAAkB,EAAE,MAAM;QAC1B,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAED,mBAAmB;AACnB,MAAM,UAAU,uBAAuB,CAAC,KAAgC;IACtE,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACpG,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,OAAO,wBAAwB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAC/D,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,QAAuC;IAEvC,MAAM,KAAK,GAAG;QACZ,aAAa;QACb,EAAE;QACF,GAAG,yBAAyB,CAAC,QAAQ,CAAC;KACvC,CAAC;IAEF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,kCAAkC,CAAC,CAAC;QACjE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,KAAK,CAAC,MAAM,SAAS,EAAE,EAAE,CAAC,CAAC;IAErD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;QACnC,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,UAAU,kBAAkB,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/G,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,OAGC;IAED,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IACnC,MAAM,QAAQ,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAElD,MAAM,KAAK,GAAG,QAAQ,EAAE,MAAM;QAC5B,CAAC,CAAC,+BAA+B,CAAC,QAAQ,EAAE,KAAK,CAAC;QAClD,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,OAAO,EAAE,WAAW,KAAK,OAAO,EAAE,CAAC;QACrC,QAAQ,CAAC,IAAI,CACX,EAAE,EACF,YAAY,EACZ,uCAAuC,EACvC,4BAA4B,CAC7B,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,iBAAiB,CAC/B,KAAgC,EAChC,OAGC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,IAAI,EAAE,gBAAgB,CAAC;YACrB,KAAK;YACL,QAAQ,EAAE,OAAO,EAAE,QAAQ;YAC3B,WAAW,EAAE,OAAO,EAAE,WAAW;SAClC,CAAC;QACF,IAAI;QACJ,KAAK,EAAE,eAAe;QACtB,eAAe,EAAE,gBAAgB;QACjC,QAAQ,EAAE,cAAc;KACzB,CAAC,CAAC;AACL,CAAC;AAED,oBAAoB;AACpB,MAAM,UAAU,iBAAiB,CAC/B,KAAgC,EAChC,QAAuC;IAEvC,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,IAAI,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC;QACvC,IAAI;QACJ,KAAK,EAAE,eAAe;QACtB,eAAe,EAAE,gBAAgB;QACjC,QAAQ,EAAE,mBAAmB;KAC9B,CAAC,CAAC;AACL,CAAC;AAED,cAAc;AACd,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,aAAa;QACb,yCAAyC;KAC1C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type Plugin } from '@zhin.js/core';
2
+ /**
3
+ * 在 root 上挂载「游戏 / game」大厅命令,返回 dispose 列表。
4
+ */
5
+ export declare function mountGameHubUi(root: Plugin): (() => void)[];
6
+ export declare function isGameHubMounted(): boolean;
7
+ export declare function markGameHubUiMounted(): void;
8
+ export declare function resetGameHubMountForTests(): void;
9
+ //# sourceMappingURL=game-hub-mount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-hub-mount.d.ts","sourceRoot":"","sources":["../src/game-hub-mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,eAAe,CAAC;AAwBvB;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAkH3D;AAcD,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -0,0 +1,108 @@
1
+ import { MessageCommand, getActionFromMessage, resolvePayloadFromText, } from '@zhin.js/core';
2
+ import { buildChoiceFallbackMap, parseChoicePayload } from './choice-keyboard.js';
3
+ import { formatHubEmptyMessage, buildBotHelpReply, buildHubHelpReply, HUB_PREFIX, } from './game-hub-menu.js';
4
+ import { getLastHubMenu } from './game-hub-menu-context.js';
5
+ import { handleHubChoice, openMainMenu, parseHubPayload } from './game-hub-flow.js';
6
+ import { getRegisteredGames } from './game-hub-feature.js';
7
+ import { mountGameRecordCommands } from './game-records.js';
8
+ import { mountFirstAtHintMiddleware } from './game-onboarding.js';
9
+ import { filterHelpCommands } from './command-help.js';
10
+ function resolveRegisteredCommands(root) {
11
+ const commandService = root.inject('command');
12
+ return commandService?.items ?? [];
13
+ }
14
+ async function resolveHelpCommands(root, message) {
15
+ return filterHelpCommands(resolveRegisteredCommands(root), message, root);
16
+ }
17
+ /**
18
+ * 在 root 上挂载「游戏 / game」大厅命令,返回 dispose 列表。
19
+ */
20
+ export function mountGameHubUi(root) {
21
+ const disposers = [];
22
+ const openHandler = async (message) => {
23
+ const games = getRegisteredGames();
24
+ if (!games.length) {
25
+ return formatHubEmptyMessage();
26
+ }
27
+ const menu = openMainMenu(message);
28
+ if (typeof menu === 'string')
29
+ return menu;
30
+ await message.$reply?.(menu);
31
+ return undefined;
32
+ };
33
+ disposers.push(root.addCommand(new MessageCommand('/游戏')
34
+ .desc('游戏大厅:选择游戏并开始')
35
+ .action(openHandler)), root.addCommand(new MessageCommand('/game')
36
+ .desc('Game lobby (English alias)')
37
+ .action(openHandler)), root.addCommand(new MessageCommand('游戏')
38
+ .desc('游戏大厅(无斜杠兼容)')
39
+ .action(openHandler)), root.addCommand(new MessageCommand('game')
40
+ .desc('Game lobby (legacy alias)')
41
+ .action(openHandler)));
42
+ disposers.push(root.addCommand(new MessageCommand('/游戏 帮助')
43
+ .desc('游戏大厅帮助')
44
+ .action(async (message) => buildHubHelpReply(getRegisteredGames(), await resolveHelpCommands(root, message)))), root.addCommand(new MessageCommand('/帮助')
45
+ .desc('机器人帮助:游戏列表与 QQ 群用法')
46
+ .action(async (message) => buildBotHelpReply(getRegisteredGames(), {
47
+ channelType: message.$channel.type,
48
+ commands: await resolveHelpCommands(root, message),
49
+ }))), root.addCommand(new MessageCommand('/help')
50
+ .desc('Bot help (English alias)')
51
+ .action(async (message) => buildBotHelpReply(getRegisteredGames(), {
52
+ channelType: message.$channel.type,
53
+ commands: await resolveHelpCommands(root, message),
54
+ }))), root.addCommand(new MessageCommand('帮助')
55
+ .desc('帮助(无斜杠兼容)')
56
+ .action(async (message) => buildBotHelpReply(getRegisteredGames(), {
57
+ channelType: message.$channel.type,
58
+ commands: await resolveHelpCommands(root, message),
59
+ }))));
60
+ disposers.push(mountGameRecordCommands(root));
61
+ disposers.push(mountFirstAtHintMiddleware(root));
62
+ root.registerInteractiveHandler(`${HUB_PREFIX}:`, (message) => handleHubInteractive(root, message));
63
+ disposers.push(root.addMiddleware(async (message, next) => {
64
+ const action = getActionFromMessage(message);
65
+ if (action?.payload.startsWith(`${HUB_PREFIX}:`))
66
+ return next();
67
+ const raw = message.$raw?.trim() ?? '';
68
+ // QQ 指令预填等:payload 自包含 hub:scope:choice,不依赖 opener 的菜单缓存
69
+ const directPayload = resolvePayloadFromText(raw);
70
+ if (directPayload?.startsWith(`${HUB_PREFIX}:`)) {
71
+ const direct = parseChoicePayload(directPayload, HUB_PREFIX);
72
+ if (direct) {
73
+ await handleHubChoice(root, message, direct.sessionId, direct.choiceId);
74
+ return;
75
+ }
76
+ }
77
+ const last = getLastHubMenu(message);
78
+ if (!last)
79
+ return next();
80
+ const map = buildChoiceFallbackMap(HUB_PREFIX, last.scopeId, last.choices);
81
+ const payload = resolvePayloadFromText(raw, map);
82
+ const parsed = payload ? parseChoicePayload(payload, HUB_PREFIX) : null;
83
+ if (!parsed || parsed.sessionId !== last.scopeId)
84
+ return next();
85
+ await handleHubChoice(root, message, parsed.sessionId, parsed.choiceId);
86
+ }));
87
+ return disposers;
88
+ }
89
+ async function handleHubInteractive(root, message) {
90
+ const action = getActionFromMessage(message);
91
+ if (!action)
92
+ return false;
93
+ const fromPayload = parseHubPayload(action.payload);
94
+ if (!fromPayload)
95
+ return false;
96
+ return handleHubChoice(root, message, fromPayload.scopeId, fromPayload.choiceId);
97
+ }
98
+ let hubUiMounted = false;
99
+ export function isGameHubMounted() {
100
+ return hubUiMounted;
101
+ }
102
+ export function markGameHubUiMounted() {
103
+ hubUiMounted = true;
104
+ }
105
+ export function resetGameHubMountForTests() {
106
+ hubUiMounted = false;
107
+ }
108
+ //# sourceMappingURL=game-hub-mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-hub-mount.js","sourceRoot":"","sources":["../src/game-hub-mount.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type Message } from '@zhin.js/core';
2
+ export declare const GAME_RESTART_CHOICE_IDS: Set<string>;
3
+ export declare function isRestartChoice(choiceId: string): boolean;
4
+ /** 从 QQ 指令预填 / 数字 fallback 解析游戏 payload */
5
+ export declare function resolveGameTextPayload(raw: string, map?: Record<string, string>): string | undefined;
6
+ export interface GameSessionRef {
7
+ id: string;
8
+ channel_key: string;
9
+ }
10
+ export interface ResolveGameChoiceOptions {
11
+ message: Message<any>;
12
+ gamePrefix: string;
13
+ validChoiceIds: readonly string[];
14
+ getById: (sessionId: string) => Promise<GameSessionRef | null>;
15
+ getActiveForUser: (channel: string, userId: string) => Promise<GameSessionRef | null>;
16
+ getByBoardMessageId?: (messageId: string) => Promise<GameSessionRef | null>;
17
+ }
18
+ /**
19
+ * 解析按钮/选项回调:优先 payload;终局「再来一局」允许已结束 session。
20
+ */
21
+ export declare function resolveGameChoice(opts: ResolveGameChoiceOptions): Promise<{
22
+ sessionId: string;
23
+ choiceId: string;
24
+ } | null>;
25
+ //# sourceMappingURL=game-interactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-interactive.d.ts","sourceRoot":"","sources":["../src/game-interactive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAK3F,eAAO,MAAM,uBAAuB,aAKlC,CAAC;AAEH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,2CAA2C;AAC3C,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,MAAM,GAAG,SAAS,CAEpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/D,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACtF,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA4CzD"}
@@ -0,0 +1,62 @@
1
+ import { getActionFromMessage, resolvePayloadFromText } from '@zhin.js/core';
2
+ import { channelKey } from './board-sender.js';
3
+ import { parseChoicePayload } from './choice-keyboard.js';
4
+ export const GAME_RESTART_CHOICE_IDS = new Set([
5
+ 'restart',
6
+ 'restart_char',
7
+ 'restart_idiom',
8
+ 'restart_bot',
9
+ ]);
10
+ export function isRestartChoice(choiceId) {
11
+ return GAME_RESTART_CHOICE_IDS.has(choiceId) || choiceId.startsWith('restart_');
12
+ }
13
+ /** 从 QQ 指令预填 / 数字 fallback 解析游戏 payload */
14
+ export function resolveGameTextPayload(raw, map) {
15
+ return resolvePayloadFromText(raw, map);
16
+ }
17
+ /**
18
+ * 解析按钮/选项回调:优先 payload;终局「再来一局」允许已结束 session。
19
+ */
20
+ export async function resolveGameChoice(opts) {
21
+ const action = getActionFromMessage(opts.message);
22
+ if (!action)
23
+ return null;
24
+ const ch = channelKey(opts.message);
25
+ const userId = opts.message.$sender.id;
26
+ const fromPayload = parseChoicePayload(action.payload, opts.gamePrefix);
27
+ if (fromPayload && opts.validChoiceIds.includes(fromPayload.choiceId)) {
28
+ const session = await opts.getById(fromPayload.sessionId);
29
+ if (session?.channel_key === ch) {
30
+ return { sessionId: fromPayload.sessionId, choiceId: fromPayload.choiceId };
31
+ }
32
+ }
33
+ const choiceId = action.id || action.payload;
34
+ if (!choiceId || !opts.validChoiceIds.includes(choiceId))
35
+ return null;
36
+ if (isRestartChoice(choiceId)) {
37
+ if (fromPayload) {
38
+ const session = await opts.getById(fromPayload.sessionId);
39
+ if (session?.channel_key === ch) {
40
+ return { sessionId: fromPayload.sessionId, choiceId };
41
+ }
42
+ }
43
+ if (action.sourceMessageId && opts.getByBoardMessageId) {
44
+ const byBoard = await opts.getByBoardMessageId(action.sourceMessageId);
45
+ if (byBoard && byBoard.channel_key === ch) {
46
+ return { sessionId: byBoard.id, choiceId };
47
+ }
48
+ }
49
+ const active = await opts.getActiveForUser(ch, userId);
50
+ if (active)
51
+ return { sessionId: active.id, choiceId };
52
+ return null;
53
+ }
54
+ const session = (await opts.getActiveForUser(ch, userId))
55
+ ?? (action.sourceMessageId && opts.getByBoardMessageId
56
+ ? await opts.getByBoardMessageId(action.sourceMessageId)
57
+ : null);
58
+ if (!session || session.channel_key !== ch)
59
+ return null;
60
+ return { sessionId: session.id, choiceId };
61
+ }
62
+ //# sourceMappingURL=game-interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-interactive.js","sourceRoot":"","sources":["../src/game-interactive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { MessageMiddleware, Plugin, RegisteredAdapter } from '@zhin.js/core';
2
+ /**
3
+ * 在 root 插件上注册游戏文本中间件(入站管线只走 root.middleware)。
4
+ */
5
+ export declare function registerGameTextMiddleware(plugin: Plugin, middleware: MessageMiddleware<RegisteredAdapter>, name?: string): () => void;
6
+ //# sourceMappingURL=game-middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-middleware.d.ts","sourceRoot":"","sources":["../src/game-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElF;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,EAChD,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,IAAI,CAIZ"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 在 root 插件上注册游戏文本中间件(入站管线只走 root.middleware)。
3
+ */
4
+ export function registerGameTextMiddleware(plugin, middleware, name) {
5
+ const dispose = plugin.root.addMiddleware(middleware, name);
6
+ plugin.onDispose(dispose);
7
+ return dispose;
8
+ }
9
+ //# sourceMappingURL=game-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-middleware.js","sourceRoot":"","sources":["../src/game-middleware.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAc,EACd,UAAgD,EAChD,IAAa;IAEb,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type Plugin } from '@zhin.js/core';
2
+ /**
3
+ * 群聊首次 @ 且非命令时提示 /游戏 /帮助(每频道 24h 最多一次)
4
+ */
5
+ export declare function mountFirstAtHintMiddleware(root: Plugin): () => void;
6
+ /** 测试专用 */
7
+ export declare function resetOnboardingForTests(): void;
8
+ //# sourceMappingURL=game-onboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-onboarding.d.ts","sourceRoot":"","sources":["../src/game-onboarding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAuChF;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,CAkBnE;AAED,WAAW;AACX,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C"}
@@ -0,0 +1,66 @@
1
+ import { getActionFromMessage } from '@zhin.js/core';
2
+ const hintedChannels = new Set();
3
+ const TTL_MS = 24 * 60 * 60 * 1000;
4
+ const channelHintAt = new Map();
5
+ function channelHintKey(message) {
6
+ return `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
7
+ }
8
+ function pruneHintCache() {
9
+ const now = Date.now();
10
+ for (const [key, at] of channelHintAt) {
11
+ if (now - at > TTL_MS) {
12
+ channelHintAt.delete(key);
13
+ hintedChannels.delete(key);
14
+ }
15
+ }
16
+ }
17
+ function messageMentionsBot(message) {
18
+ const raw = message.$raw ?? '';
19
+ if (/@(?:everyone|all)/i.test(raw))
20
+ return false;
21
+ const botId = message.$bot?.id;
22
+ if (botId && raw.includes(String(botId)))
23
+ return true;
24
+ for (const item of message.$content ?? []) {
25
+ if (typeof item === 'string')
26
+ continue;
27
+ if (item.type === 'at' && (!item.data.user_id || item.data.user_id === botId || item.data.user_id === 'all')) {
28
+ if (item.data.user_id !== 'all')
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+ function looksLikeCommand(raw) {
35
+ const t = raw.trim();
36
+ return t.startsWith('/') || /^(游戏|game|帮助|help|签到|stats)\b/i.test(t);
37
+ }
38
+ /**
39
+ * 群聊首次 @ 且非命令时提示 /游戏 /帮助(每频道 24h 最多一次)
40
+ */
41
+ export function mountFirstAtHintMiddleware(root) {
42
+ return root.addMiddleware(async (message, next) => {
43
+ if (message.$channel.type !== 'group')
44
+ return next();
45
+ if (getActionFromMessage(message))
46
+ return next();
47
+ if (!messageMentionsBot(message))
48
+ return next();
49
+ const raw = message.$raw?.trim() ?? '';
50
+ if (looksLikeCommand(raw))
51
+ return next();
52
+ pruneHintCache();
53
+ const key = channelHintKey(message);
54
+ if (hintedChannels.has(key))
55
+ return next();
56
+ hintedChannels.add(key);
57
+ channelHintAt.set(key, Date.now());
58
+ return next();
59
+ });
60
+ }
61
+ /** 测试专用 */
62
+ export function resetOnboardingForTests() {
63
+ hintedChannels.clear();
64
+ channelHintAt.clear();
65
+ }
66
+ //# sourceMappingURL=game-onboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-onboarding.js","sourceRoot":"","sources":["../src/game-onboarding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type DatabaseFeature, type Message, type Models, type Plugin } from '@zhin.js/core';
2
+ import { type HostGameDbSource } from './memory-db.js';
3
+ export type GameRecordResult = 'won' | 'lost' | 'draw' | 'aborted';
4
+ declare module '@zhin.js/core' {
5
+ interface Models {
6
+ game_records: {
7
+ id: string;
8
+ user_id: string;
9
+ user_name: string;
10
+ channel_key: string;
11
+ game_id: string;
12
+ result: GameRecordResult;
13
+ score: number;
14
+ created_at: number;
15
+ };
16
+ }
17
+ }
18
+ export type GameRecordRow = Models['game_records'];
19
+ export declare function registerGameRecordModels(plugin: Plugin): void;
20
+ export declare function initGameRecordDatabase(dbFeature: DatabaseFeature): void;
21
+ /** Plugin Runtime DatabaseHost 的最小结构(与 @zhin.js/plugin-runtime 的 DatabaseHost 结构对齐) */
22
+ export interface GameRecordDatabaseHost extends HostGameDbSource {
23
+ define(name: string, definition: Record<string, unknown>): void;
24
+ }
25
+ /**
26
+ * Plugin Runtime 下用 databaseHostToken 初始化战绩库。
27
+ * 幂等:多个游戏插件 setup 都会调用,只建一次;无 token 时保持跳过(内存/静默)。
28
+ */
29
+ export declare function initGameRecordHost(host: GameRecordDatabaseHost): () => void;
30
+ /** 对局结束时写入战绩(database 未就绪时静默跳过) */
31
+ export declare function recordGameOutcome(message: Message<any>, gameId: string, result: GameRecordResult, score?: number): Promise<void>;
32
+ export interface UserGameStats {
33
+ gameId: string;
34
+ wins: number;
35
+ losses: number;
36
+ draws: number;
37
+ totalScore: number;
38
+ games: number;
39
+ }
40
+ export declare function getUserGameStats(userId: string, channelKeyFilter?: string): Promise<UserGameStats[]>;
41
+ export interface LeaderboardEntry {
42
+ userId: string;
43
+ userName: string;
44
+ wins: number;
45
+ totalScore: number;
46
+ games: number;
47
+ }
48
+ export declare function getGameLeaderboard(gameId: string, channelKeyFilter: string, limit?: number): Promise<LeaderboardEntry[]>;
49
+ export declare function mountGameRecordCommands(root: Plugin): () => void;
50
+ /** 测试专用 */
51
+ export declare function resetGameRecordsForTests(): void;
52
+ //# sourceMappingURL=game-records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-records.d.ts","sourceRoot":"","sources":["../src/game-records.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGzE,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEnE,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,MAAM;QACd,YAAY,EAAE;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,OAAO,EAAE,MAAM,CAAC;YAChB,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,EAAE,MAAM,CAAC;YAChB,MAAM,EAAE,gBAAgB,CAAC;YACzB,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH;CACF;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAoBnD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAW7D;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAEvE;AAaD,uFAAuF;AACvF,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAa3E;AAMD,mCAAmC;AACnC,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,gBAAgB,EACxB,KAAK,SAAI,GACR,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,aAAa,EAAE,CAAC,CA4B1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,KAAK,SAAK,GACT,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2B7B;AA2BD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,CA0ChE;AAED,WAAW;AACX,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C"}