@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.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/lib/board-sender.d.ts +14 -0
- package/lib/board-sender.d.ts.map +1 -0
- package/lib/board-sender.js +7 -0
- package/lib/board-sender.js.map +1 -0
- package/lib/choice-keyboard.d.ts +44 -0
- package/lib/choice-keyboard.d.ts.map +1 -0
- package/lib/choice-keyboard.js +67 -0
- package/lib/choice-keyboard.js.map +1 -0
- package/lib/command-alias.d.ts +21 -0
- package/lib/command-alias.d.ts.map +1 -0
- package/lib/command-alias.js +22 -0
- package/lib/command-alias.js.map +1 -0
- package/lib/command-help.d.ts +19 -0
- package/lib/command-help.d.ts.map +1 -0
- package/lib/command-help.js +91 -0
- package/lib/command-help.js.map +1 -0
- package/lib/command-message.d.ts +25 -0
- package/lib/command-message.d.ts.map +1 -0
- package/lib/command-message.js +58 -0
- package/lib/command-message.js.map +1 -0
- package/lib/game-action-alias.d.ts +8 -0
- package/lib/game-action-alias.d.ts.map +1 -0
- package/lib/game-action-alias.js +117 -0
- package/lib/game-action-alias.js.map +1 -0
- package/lib/game-commands.d.ts +3 -0
- package/lib/game-commands.d.ts.map +1 -0
- package/lib/game-commands.js +5 -0
- package/lib/game-commands.js.map +1 -0
- package/lib/game-hub-feature.d.ts +58 -0
- package/lib/game-hub-feature.d.ts.map +1 -0
- package/lib/game-hub-feature.js +100 -0
- package/lib/game-hub-feature.js.map +1 -0
- package/lib/game-hub-flow.d.ts +9 -0
- package/lib/game-hub-flow.d.ts.map +1 -0
- package/lib/game-hub-flow.js +90 -0
- package/lib/game-hub-flow.js.map +1 -0
- package/lib/game-hub-menu-context.d.ts +25 -0
- package/lib/game-hub-menu-context.d.ts.map +1 -0
- package/lib/game-hub-menu-context.js +64 -0
- package/lib/game-hub-menu-context.js.map +1 -0
- package/lib/game-hub-menu.d.ts +37 -0
- package/lib/game-hub-menu.d.ts.map +1 -0
- package/lib/game-hub-menu.js +162 -0
- package/lib/game-hub-menu.js.map +1 -0
- package/lib/game-hub-mount.d.ts +9 -0
- package/lib/game-hub-mount.d.ts.map +1 -0
- package/lib/game-hub-mount.js +108 -0
- package/lib/game-hub-mount.js.map +1 -0
- package/lib/game-interactive.d.ts +25 -0
- package/lib/game-interactive.d.ts.map +1 -0
- package/lib/game-interactive.js +62 -0
- package/lib/game-interactive.js.map +1 -0
- package/lib/game-middleware.d.ts +6 -0
- package/lib/game-middleware.d.ts.map +1 -0
- package/lib/game-middleware.js +9 -0
- package/lib/game-middleware.js.map +1 -0
- package/lib/game-onboarding.d.ts +8 -0
- package/lib/game-onboarding.d.ts.map +1 -0
- package/lib/game-onboarding.js +66 -0
- package/lib/game-onboarding.js.map +1 -0
- package/lib/game-records.d.ts +52 -0
- package/lib/game-records.d.ts.map +1 -0
- package/lib/game-records.js +206 -0
- package/lib/game-records.js.map +1 -0
- package/lib/game-session.d.ts +64 -0
- package/lib/game-session.d.ts.map +1 -0
- package/lib/game-session.js +44 -0
- package/lib/game-session.js.map +1 -0
- package/lib/grid-keyboard.d.ts +67 -0
- package/lib/grid-keyboard.d.ts.map +1 -0
- package/lib/grid-keyboard.js +104 -0
- package/lib/grid-keyboard.js.map +1 -0
- package/lib/help-card.d.ts +12 -0
- package/lib/help-card.d.ts.map +1 -0
- package/lib/help-card.js +129 -0
- package/lib/help-card.js.map +1 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +29 -0
- package/lib/index.js.map +1 -0
- package/lib/interaction-profiles.d.ts +16 -0
- package/lib/interaction-profiles.d.ts.map +1 -0
- package/lib/interaction-profiles.js +35 -0
- package/lib/interaction-profiles.js.map +1 -0
- package/lib/memory-db.d.ts +41 -0
- package/lib/memory-db.d.ts.map +1 -0
- package/lib/memory-db.js +92 -0
- package/lib/memory-db.js.map +1 -0
- package/lib/random.d.ts +6 -0
- package/lib/random.d.ts.map +1 -0
- package/lib/random.js +29 -0
- package/lib/random.js.map +1 -0
- package/lib/runtime-hub.d.ts +28 -0
- package/lib/runtime-hub.d.ts.map +1 -0
- package/lib/runtime-hub.js +66 -0
- package/lib/runtime-hub.js.map +1 -0
- package/lib/send-content-text.d.ts +5 -0
- package/lib/send-content-text.d.ts.map +1 -0
- package/lib/send-content-text.js +24 -0
- package/lib/send-content-text.js.map +1 -0
- package/package.json +49 -0
- package/src/board-sender.ts +16 -0
- package/src/choice-keyboard.ts +117 -0
- package/src/command-alias.ts +45 -0
- package/src/command-help.ts +117 -0
- package/src/command-message.ts +76 -0
- package/src/game-action-alias.ts +129 -0
- package/src/game-commands.ts +4 -0
- package/src/game-hub-feature.ts +151 -0
- package/src/game-hub-flow.ts +114 -0
- package/src/game-hub-menu-context.ts +94 -0
- package/src/game-hub-menu.ts +223 -0
- package/src/game-hub-mount.ts +172 -0
- package/src/game-interactive.ts +88 -0
- package/src/game-middleware.ts +14 -0
- package/src/game-onboarding.ts +67 -0
- package/src/game-records.ts +287 -0
- package/src/game-session.ts +97 -0
- package/src/grid-keyboard.ts +180 -0
- package/src/help-card.ts +188 -0
- package/src/index.ts +29 -0
- package/src/interaction-profiles.ts +56 -0
- package/src/memory-db.ts +128 -0
- package/src/random.ts +32 -0
- package/src/runtime-hub.ts +86 -0
- package/src/send-content-text.ts +21 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 凉菜
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @zhin.js/game-kit
|
|
2
|
+
|
|
3
|
+
Zhin.js Plugin Runtime 游戏工具包。它提供交互键盘、游戏会话、战绩、Runtime 游戏大厅、
|
|
4
|
+
DatabaseHost 适配和文本 fallback,不依赖 `zhin.js` facade。
|
|
5
|
+
|
|
6
|
+
## 安装
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add @zhin.js/game-kit @zhin.js/command @zhin.js/middleware
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Runtime 插件
|
|
13
|
+
|
|
14
|
+
游戏包通过 `plugin.ts` 在 generation 生命周期登记大厅元数据,并由约定目录暴露交互:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { definePlugin } from '@zhin.js/plugin-runtime';
|
|
18
|
+
import { registerRuntimeGame } from '@zhin.js/game-kit';
|
|
19
|
+
|
|
20
|
+
export default definePlugin({
|
|
21
|
+
name: 'my-game',
|
|
22
|
+
setup(context) {
|
|
23
|
+
const services = createMyGameServices();
|
|
24
|
+
context.resources.provide(myGameServicesToken, services);
|
|
25
|
+
const dispose = registerRuntimeGame({
|
|
26
|
+
id: 'my-game',
|
|
27
|
+
title: 'My Game',
|
|
28
|
+
icon: 'GAME',
|
|
29
|
+
description: 'A turn-based game',
|
|
30
|
+
commandPrefix: '/my-game',
|
|
31
|
+
quickStart: 'start',
|
|
32
|
+
});
|
|
33
|
+
context.lifecycle.add(dispose);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- `commands/<name>/[action:string=].ts` 定义命令。
|
|
39
|
+
- `middlewares/` 处理按钮 payload、裸文本答案和旧命令别名。
|
|
40
|
+
- `registerRuntimeGame()` / `getRuntimeGames()` 是大厅 SSOT,dispose 时对称移除。
|
|
41
|
+
- `DEFAULT_GAME_STALE_CRON` 与 `scheduleHostToken` 用于清理超时会话。
|
|
42
|
+
- 每个游戏包定义自己的 typed service token;`plugin.ts` 提供资源,command/middleware
|
|
43
|
+
通过 Capability Context 的 `use(token)` 消费。禁止以模块变量保存当前 SessionService。
|
|
44
|
+
|
|
45
|
+
## 交互消息
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { buildChoiceKeyboard, buildGridKeyboard } from '@zhin.js/game-kit';
|
|
49
|
+
|
|
50
|
+
const menu = buildChoiceKeyboard({
|
|
51
|
+
gamePrefix: 'adv',
|
|
52
|
+
sessionId: 's123',
|
|
53
|
+
narrative: 'Choose a path',
|
|
54
|
+
choices: [
|
|
55
|
+
{ id: 'enter', label: 'Enter' },
|
|
56
|
+
{ id: 'leave', label: 'Leave', style: 'danger' },
|
|
57
|
+
],
|
|
58
|
+
interactionProfile: 'gameplay',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const board = buildGridKeyboard({
|
|
62
|
+
gamePrefix: 'ttt',
|
|
63
|
+
sessionId: 's123',
|
|
64
|
+
rows: 3,
|
|
65
|
+
cols: 3,
|
|
66
|
+
cells: Array.from({ length: 9 }, () => ({ state: 0, label: '.', disabled: false })),
|
|
67
|
+
statusLine: 'Your turn',
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`plainTextFromSendContent()` 会在无编辑能力或 text-only 路径移除按钮并保留正文;平台差异
|
|
72
|
+
仍由 Adapter 出站链处理。`messageFromCommandInput()` 把 Runtime `Message` 转成游戏引擎使用
|
|
73
|
+
的稳定 message-like 结构。
|
|
74
|
+
|
|
75
|
+
## 数据
|
|
76
|
+
|
|
77
|
+
- `createInMemoryGameDb()`:测试与无数据库配置时的完整内存实现。
|
|
78
|
+
- `createHostGameDb()`:把 generation-owned `DatabaseHost` 转成 SessionService 所需接口。
|
|
79
|
+
- `initGameRecordHost()` / `recordGameOutcome()`:统一战绩表与结果写入。
|
|
80
|
+
- `channelKey()` / `generateSessionId()`:稳定会话身份。
|
|
81
|
+
|
|
82
|
+
游戏包应优先使用 `databaseHostToken`,缺失时为每个插件实例创建独立内存库。数据库、
|
|
83
|
+
SessionService、cron 闭包都属于同一个 owner generation;热更卸载旧代不会覆盖新代状态。
|
|
84
|
+
|
|
85
|
+
## 验证
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pnpm --filter @zhin.js/game-kit build
|
|
89
|
+
pnpm vitest run plugins/games/*/tests
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
交互 profile 见 [ADR 0022](../../docs/adr/0022-interactive-button-modes.md),Plugin Runtime
|
|
93
|
+
迁移边界见 [ADR 0050](../../docs/adr/0050-plugin-runtime-migration-boundary.md)。
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 游戏棋盘消息辅助工具
|
|
3
|
+
* 提供会话键生成和消息 ID 更新回调封装
|
|
4
|
+
*
|
|
5
|
+
* 注意:实际的发送/编辑逻辑由 Adapter.editMessage 统一处理
|
|
6
|
+
* - 支持编辑的平台:调用平台 API 编辑
|
|
7
|
+
* - 不支持编辑的平台:自动 fallback 到发送新消息
|
|
8
|
+
*/
|
|
9
|
+
import type { Message } from '@zhin.js/core';
|
|
10
|
+
/**
|
|
11
|
+
* 构建频道唯一键(用于会话查找)
|
|
12
|
+
*/
|
|
13
|
+
export declare function channelKey(message: Message<any>): string;
|
|
14
|
+
//# sourceMappingURL=board-sender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-sender.d.ts","sourceRoot":"","sources":["../src/board-sender.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-sender.js","sourceRoot":"","sources":["../src/board-sender.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC9C,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;AACpG,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 选项式交互键盘(文字冒险、问答、剧情分支等)
|
|
3
|
+
*/
|
|
4
|
+
import { type SendContent } from '@zhin.js/core';
|
|
5
|
+
import { type InteractionProfile } from './interaction-profiles.js';
|
|
6
|
+
export interface ChoiceOption {
|
|
7
|
+
/** 选项 ID,写入 payload */
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
style?: 'primary' | 'danger' | 'secondary';
|
|
12
|
+
/** 终局菜单(如「再来一局」)保持可点 */
|
|
13
|
+
keepEnabledWhenTerminal?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ChoiceKeyboardOptions {
|
|
16
|
+
gamePrefix: string;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
/** 剧情/题干正文 */
|
|
19
|
+
narrative: string;
|
|
20
|
+
choices: ChoiceOption[];
|
|
21
|
+
terminal?: boolean;
|
|
22
|
+
/** 文本 fallback 提示 */
|
|
23
|
+
fallbackHint?: string;
|
|
24
|
+
/** 每行最多几个按钮(默认全部一行) */
|
|
25
|
+
buttonsPerRow?: number;
|
|
26
|
+
/** 交互 profile:menu→command,gameplay→callback,terminal→command */
|
|
27
|
+
interactionProfile?: InteractionProfile;
|
|
28
|
+
/** terminal profile 私聊 auto-enter 用 */
|
|
29
|
+
channelType?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function buildChoiceFallbackMap(gamePrefix: string, sessionId: string, choices: ChoiceOption[]): Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* 构建选项键盘消息:正文 + 一行或多行按钮
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildChoiceKeyboard(options: ChoiceKeyboardOptions): SendContent;
|
|
36
|
+
/**
|
|
37
|
+
* 解析选项 payload:`{prefix}:{sessionId}:{choiceId}`
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseChoicePayload(payload: string, expectedPrefix?: string): {
|
|
40
|
+
prefix: string;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
choiceId: string;
|
|
43
|
+
} | null;
|
|
44
|
+
//# sourceMappingURL=choice-keyboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-keyboard.d.ts","sourceRoot":"","sources":["../src/choice-keyboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE7F,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC3C,wBAAwB;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxB;AAWD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAyC/E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMhE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 选项式交互键盘(文字冒险、问答、剧情分支等)
|
|
3
|
+
*/
|
|
4
|
+
import { segment } from '@zhin.js/core';
|
|
5
|
+
import { applyInteractionProfile } from './interaction-profiles.js';
|
|
6
|
+
export function buildChoiceFallbackMap(gamePrefix, sessionId, choices) {
|
|
7
|
+
const map = {};
|
|
8
|
+
let n = 1;
|
|
9
|
+
for (const choice of choices) {
|
|
10
|
+
if (!choice.disabled) {
|
|
11
|
+
map[String(n)] = `${gamePrefix}:${sessionId}:${choice.id}`;
|
|
12
|
+
n++;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return map;
|
|
16
|
+
}
|
|
17
|
+
function chunkChoices(items, size) {
|
|
18
|
+
if (size <= 0 || items.length <= size)
|
|
19
|
+
return [items];
|
|
20
|
+
const rows = [];
|
|
21
|
+
for (let i = 0; i < items.length; i += size) {
|
|
22
|
+
rows.push(items.slice(i, i + size));
|
|
23
|
+
}
|
|
24
|
+
return rows;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 构建选项键盘消息:正文 + 一行或多行按钮
|
|
28
|
+
*/
|
|
29
|
+
export function buildChoiceKeyboard(options) {
|
|
30
|
+
const { gamePrefix, sessionId, narrative, choices, terminal, fallbackHint, buttonsPerRow, interactionProfile, channelType, } = options;
|
|
31
|
+
const enabled = choices.filter((c) => !c.disabled);
|
|
32
|
+
const buttonRows = chunkChoices(enabled, buttonsPerRow ?? enabled.length).map((row) => row.map((choice) => {
|
|
33
|
+
const base = segment.button({
|
|
34
|
+
id: choice.id,
|
|
35
|
+
label: choice.label,
|
|
36
|
+
payload: `${gamePrefix}:${sessionId}:${choice.id}`,
|
|
37
|
+
disabled: choice.disabled || (terminal && !choice.keepEnabledWhenTerminal),
|
|
38
|
+
style: choice.style ?? 'secondary',
|
|
39
|
+
});
|
|
40
|
+
const data = base.data;
|
|
41
|
+
if (!interactionProfile)
|
|
42
|
+
return base;
|
|
43
|
+
return segment.button(applyInteractionProfile(data, { profile: interactionProfile, channelType }));
|
|
44
|
+
}));
|
|
45
|
+
const fallback = buildChoiceFallbackMap(gamePrefix, sessionId, choices);
|
|
46
|
+
return [
|
|
47
|
+
segment.text(narrative),
|
|
48
|
+
segment.keyboard(buttonRows, {
|
|
49
|
+
fallback: fallbackHint && Object.keys(fallback).length > 0
|
|
50
|
+
? { hint: fallbackHint, map: fallback }
|
|
51
|
+
: undefined,
|
|
52
|
+
}).toElement(),
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 解析选项 payload:`{prefix}:{sessionId}:{choiceId}`
|
|
57
|
+
*/
|
|
58
|
+
export function parseChoicePayload(payload, expectedPrefix) {
|
|
59
|
+
const m = /^([a-z0-9_]+):([^:]+):([a-z0-9_-]+)$/i.exec(payload);
|
|
60
|
+
if (!m)
|
|
61
|
+
return null;
|
|
62
|
+
const prefix = m[1];
|
|
63
|
+
if (expectedPrefix && prefix !== expectedPrefix)
|
|
64
|
+
return null;
|
|
65
|
+
return { prefix, sessionId: m[2], choiceId: m[3] };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=choice-keyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-keyboard.js","sourceRoot":"","sources":["../src/choice-keyboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MiddlewareContext } from '@zhin.js/middleware';
|
|
2
|
+
import type { Message } from '@zhin.js/core/runtime';
|
|
3
|
+
/**
|
|
4
|
+
* 游戏 legacy 命令别名路由。
|
|
5
|
+
*
|
|
6
|
+
* 插件运行时迁移后,约定式命令以 `<instanceKey> <localName>` 限定名注册(ADR 0043),
|
|
7
|
+
* 旧的短命令(如 `/21点 开始`、`/猜数 开始`)在 runtime 中不存在。
|
|
8
|
+
* 各游戏插件用本 helper 在 `middlewares/` 下注册一个入站中间件,
|
|
9
|
+
* 把命中别名的首词消息转发到与限定名命令完全相同的处理逻辑。
|
|
10
|
+
*/
|
|
11
|
+
export interface GameCommandAliasRoute {
|
|
12
|
+
/** 首词命中即接管(不含前导 `/`),如 `['21点', 'bj']`。 */
|
|
13
|
+
readonly aliases: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* 与 `commands/<cmd>/[action:string=].ts` 的 execute 逻辑保持一致:
|
|
16
|
+
* action 为别名后剩余文本(无参数时为 '');返回回复文本,null/undefined 表示放行。
|
|
17
|
+
*/
|
|
18
|
+
run(action: string, input: unknown, context: MiddlewareContext<Message>): Promise<string | null | undefined>;
|
|
19
|
+
}
|
|
20
|
+
export declare function defineGameCommandAliasMiddleware(route: GameCommandAliasRoute): Readonly<import("@zhin.js/middleware").MiddlewareDefinition<Message, unknown>>;
|
|
21
|
+
//# sourceMappingURL=command-alias.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-alias.d.ts","sourceRoot":"","sources":["../src/command-alias.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,GAAG,CACD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAClC,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACvC;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,qBAAqB,kFAmB5E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineMiddleware } from '@zhin.js/middleware';
|
|
2
|
+
export function defineGameCommandAliasMiddleware(route) {
|
|
3
|
+
return defineMiddleware({
|
|
4
|
+
target: 'inbound',
|
|
5
|
+
async handle(context, next) {
|
|
6
|
+
const raw = context.input.content?.trim() ?? '';
|
|
7
|
+
const text = raw.startsWith('/') ? raw.slice(1) : raw;
|
|
8
|
+
const [head, ...rest] = text.split(/\s+/).filter(Boolean);
|
|
9
|
+
if (!head || !route.aliases.includes(head)) {
|
|
10
|
+
await next();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const reply = await route.run(rest.join(' '), context.input, context);
|
|
14
|
+
if (reply) {
|
|
15
|
+
await context.input.$reply(reply);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
await next();
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=command-alias.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-alias.js","sourceRoot":"","sources":["../src/command-alias.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA0B,MAAM,qBAAqB,CAAC;AAyB/E,MAAM,UAAU,gCAAgC,CAAC,KAA4B;IAC3E,OAAO,gBAAgB,CAAU;QAC/B,MAAM,EAAE,SAAS;QACjB,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI;YACxB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YACtD,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1D,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACtE,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YACD,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Message, MessageCommand, Plugin } from '@zhin.js/core';
|
|
2
|
+
import type { RegisteredGame } from './game-hub-feature.js';
|
|
3
|
+
export interface CommandHelpSource {
|
|
4
|
+
pattern: string;
|
|
5
|
+
helpInfo: {
|
|
6
|
+
desc: string[];
|
|
7
|
+
usage?: string[];
|
|
8
|
+
examples?: string[];
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function commandToHelpSource(cmd: Pick<MessageCommand, 'pattern' | 'helpInfo'>): CommandHelpSource;
|
|
12
|
+
/** 按 MessageCommand.permit 与当前消息上下文过滤(与 handle 一致) */
|
|
13
|
+
export declare function filterHelpCommands(commands: readonly MessageCommand[], message: Message<any>, plugin: Plugin): Promise<CommandHelpSource[]>;
|
|
14
|
+
/** 从 command 服务收集应在 /帮助 中展示的命令(去重、排除已在游戏大厅列出的项) */
|
|
15
|
+
export declare function collectSupplementaryCommandHelp(commands: readonly CommandHelpSource[], games: readonly RegisteredGame[]): CommandHelpSource[];
|
|
16
|
+
export declare function formatSupplementaryCommandsHelp(commands: readonly CommandHelpSource[], games: readonly RegisteredGame[]): string;
|
|
17
|
+
/** 大厅入口行:从已注册命令的 .desc() 生成 */
|
|
18
|
+
export declare function formatHubOpenCommandLines(commands: readonly CommandHelpSource[] | undefined): string[];
|
|
19
|
+
//# sourceMappingURL=command-help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../src/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,iBAAiB,CAExG;AAED,sDAAsD;AACtD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAQ9B;AA+CD,mDAAmD;AACnD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,KAAK,EAAE,SAAS,cAAc,EAAE,GAC/B,iBAAiB,EAAE,CAWrB;AAED,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,KAAK,EAAE,SAAS,cAAc,EAAE,GAC/B,MAAM,CAKR;AAED,+BAA+B;AAC/B,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,GACjD,MAAM,EAAE,CAUV"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export function commandToHelpSource(cmd) {
|
|
2
|
+
return { pattern: cmd.pattern, helpInfo: cmd.helpInfo };
|
|
3
|
+
}
|
|
4
|
+
/** 按 MessageCommand.permit 与当前消息上下文过滤(与 handle 一致) */
|
|
5
|
+
export async function filterHelpCommands(commands, message, plugin) {
|
|
6
|
+
const out = [];
|
|
7
|
+
for (const cmd of commands) {
|
|
8
|
+
if (await cmd.checkPermits(message, plugin)) {
|
|
9
|
+
out.push(commandToHelpSource(cmd));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
function commandLeadingToken(pattern) {
|
|
15
|
+
return pattern.split(/\s/)[0] ?? '';
|
|
16
|
+
}
|
|
17
|
+
function normalizeToken(token) {
|
|
18
|
+
return token.replace(/^\//, '').toLowerCase();
|
|
19
|
+
}
|
|
20
|
+
/** 不在「其他命令」中重复展示的 pattern(大厅入口 / 帮助自身) */
|
|
21
|
+
const HELP_EXCLUDE_EXACT = new Set([
|
|
22
|
+
'/帮助',
|
|
23
|
+
'/help',
|
|
24
|
+
'帮助',
|
|
25
|
+
'/游戏 帮助',
|
|
26
|
+
'/游戏',
|
|
27
|
+
'/game',
|
|
28
|
+
'游戏',
|
|
29
|
+
'game',
|
|
30
|
+
]);
|
|
31
|
+
function isHubListedGameCommand(pattern, games) {
|
|
32
|
+
const lead = normalizeToken(commandLeadingToken(pattern));
|
|
33
|
+
return games.some((g) => normalizeToken(g.commandPrefix) === lead);
|
|
34
|
+
}
|
|
35
|
+
function comparePatterns(a, b) {
|
|
36
|
+
const leadDiff = commandLeadingToken(b).length - commandLeadingToken(a).length;
|
|
37
|
+
if (leadDiff !== 0)
|
|
38
|
+
return leadDiff;
|
|
39
|
+
return b.length - a.length;
|
|
40
|
+
}
|
|
41
|
+
function formatPatternDisplay(pattern) {
|
|
42
|
+
return `\`${pattern}\``;
|
|
43
|
+
}
|
|
44
|
+
function formatCommandHelpLine(cmd) {
|
|
45
|
+
const [label = '', detail = ''] = cmd.helpInfo.desc;
|
|
46
|
+
const display = formatPatternDisplay(cmd.pattern);
|
|
47
|
+
const summary = detail || label || cmd.pattern;
|
|
48
|
+
if (label && label !== commandLeadingToken(cmd.pattern) && !cmd.pattern.startsWith(label)) {
|
|
49
|
+
return `• ${display}(${label})— ${summary}`;
|
|
50
|
+
}
|
|
51
|
+
return `• ${display} — ${summary}`;
|
|
52
|
+
}
|
|
53
|
+
/** 从 command 服务收集应在 /帮助 中展示的命令(去重、排除已在游戏大厅列出的项) */
|
|
54
|
+
export function collectSupplementaryCommandHelp(commands, games) {
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const cmd of [...commands].sort((a, b) => comparePatterns(a.pattern, b.pattern))) {
|
|
58
|
+
if (HELP_EXCLUDE_EXACT.has(cmd.pattern))
|
|
59
|
+
continue;
|
|
60
|
+
if (isHubListedGameCommand(cmd.pattern, games))
|
|
61
|
+
continue;
|
|
62
|
+
if (seen.has(cmd.pattern))
|
|
63
|
+
continue;
|
|
64
|
+
seen.add(cmd.pattern);
|
|
65
|
+
out.push(cmd);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
export function formatSupplementaryCommandsHelp(commands, games) {
|
|
70
|
+
const items = collectSupplementaryCommandHelp(commands, games);
|
|
71
|
+
if (!items.length)
|
|
72
|
+
return '';
|
|
73
|
+
const lines = items.map(formatCommandHelpLine);
|
|
74
|
+
return ['**其他命令**', '', ...lines].join('\n');
|
|
75
|
+
}
|
|
76
|
+
/** 大厅入口行:从已注册命令的 .desc() 生成 */
|
|
77
|
+
export function formatHubOpenCommandLines(commands) {
|
|
78
|
+
if (!commands?.length)
|
|
79
|
+
return [];
|
|
80
|
+
const lines = [];
|
|
81
|
+
for (const pattern of ['/游戏', '/game']) {
|
|
82
|
+
const cmd = commands.find((c) => c.pattern === pattern);
|
|
83
|
+
if (!cmd)
|
|
84
|
+
continue;
|
|
85
|
+
const desc = cmd.helpInfo.desc[0] ?? cmd.helpInfo.desc[1] ?? '';
|
|
86
|
+
if (desc)
|
|
87
|
+
lines.push(`${pattern} — ${desc}`);
|
|
88
|
+
}
|
|
89
|
+
return lines;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=command-help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-help.js","sourceRoot":"","sources":["../src/command-help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map Plugin Runtime CommandContext.input → classic Message-like shape used by game SessionService.
|
|
3
|
+
*
|
|
4
|
+
* Runtime Message: { adapter, target, sender?, metadata? }
|
|
5
|
+
* Classic Message: { $adapter, $endpoint, $channel, $sender }
|
|
6
|
+
*/
|
|
7
|
+
export interface GameMessageLike {
|
|
8
|
+
$adapter: string;
|
|
9
|
+
$endpoint: string;
|
|
10
|
+
$channel: {
|
|
11
|
+
type: string;
|
|
12
|
+
id: string;
|
|
13
|
+
};
|
|
14
|
+
$sender: {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Smoke message when CommandContext has no usable input (unit tests / CLI). */
|
|
20
|
+
export declare function smokeGameMessage(): GameMessageLike;
|
|
21
|
+
/**
|
|
22
|
+
* Convert CommandContext.input to a Message-like object for game-flow / *-command.
|
|
23
|
+
*/
|
|
24
|
+
export declare function messageFromCommandInput(input: unknown): GameMessageLike;
|
|
25
|
+
//# sourceMappingURL=command-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-message.d.ts","sourceRoot":"","sources":["../src/command-message.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AA8BD,gFAAgF;AAChF,wBAAgB,gBAAgB,IAAI,eAAe,CAOlD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAoBvE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map Plugin Runtime CommandContext.input → classic Message-like shape used by game SessionService.
|
|
3
|
+
*
|
|
4
|
+
* Runtime Message: { adapter, target, sender?, metadata? }
|
|
5
|
+
* Classic Message: { $adapter, $endpoint, $channel, $sender }
|
|
6
|
+
*/
|
|
7
|
+
function isClassicMessage(input) {
|
|
8
|
+
if (!input || typeof input !== 'object')
|
|
9
|
+
return false;
|
|
10
|
+
const m = input;
|
|
11
|
+
return (typeof m.$adapter === 'string' &&
|
|
12
|
+
m.$channel != null &&
|
|
13
|
+
typeof m.$channel === 'object' &&
|
|
14
|
+
m.$sender != null &&
|
|
15
|
+
typeof m.$sender === 'object');
|
|
16
|
+
}
|
|
17
|
+
function isRuntimeMessage(input) {
|
|
18
|
+
if (!input || typeof input !== 'object')
|
|
19
|
+
return false;
|
|
20
|
+
const m = input;
|
|
21
|
+
return ('adapter' in m ||
|
|
22
|
+
'target' in m ||
|
|
23
|
+
'sender' in m ||
|
|
24
|
+
(m.metadata != null && typeof m.metadata === 'object'));
|
|
25
|
+
}
|
|
26
|
+
/** Smoke message when CommandContext has no usable input (unit tests / CLI). */
|
|
27
|
+
export function smokeGameMessage() {
|
|
28
|
+
return {
|
|
29
|
+
$adapter: 'runtime',
|
|
30
|
+
$endpoint: 'default',
|
|
31
|
+
$channel: { type: 'private', id: 'smoke' },
|
|
32
|
+
$sender: { id: 'smoke', name: 'smoke' },
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convert CommandContext.input to a Message-like object for game-flow / *-command.
|
|
37
|
+
*/
|
|
38
|
+
export function messageFromCommandInput(input) {
|
|
39
|
+
if (isClassicMessage(input))
|
|
40
|
+
return input;
|
|
41
|
+
if (isRuntimeMessage(input)) {
|
|
42
|
+
const meta = input.metadata ?? {};
|
|
43
|
+
const adapter = String(input.adapter ?? meta.adapter ?? 'runtime');
|
|
44
|
+
const endpoint = String(meta.endpoint ?? meta.endpointId ?? 'default');
|
|
45
|
+
const channelType = String(meta.type ?? meta.channelType ?? 'private');
|
|
46
|
+
const channelId = String(input.target ?? meta.channelId ?? 'smoke');
|
|
47
|
+
const senderId = String(input.sender ?? meta.senderId ?? 'smoke');
|
|
48
|
+
const senderName = String(meta.senderName ?? meta.name ?? senderId);
|
|
49
|
+
return {
|
|
50
|
+
$adapter: adapter,
|
|
51
|
+
$endpoint: endpoint,
|
|
52
|
+
$channel: { type: channelType, id: channelId },
|
|
53
|
+
$sender: { id: senderId, name: senderName },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return smokeGameMessage();
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=command-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-message.js","sourceRoot":"","sources":["../src/command-message.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,CAAC,CAAC,QAAQ,IAAI,IAAI;QAClB,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,CAAC,CAAC,OAAO,IAAI,IAAI;QACjB,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAC9B,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IAMtC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,SAAS,IAAI,CAAC;QACd,QAAQ,IAAI,CAAC;QACb,QAAQ,IAAI,CAAC;QACb,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CACvD,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,SAAS;QACpB,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE;QAC1C,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;KACxC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,IAAI,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1C,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;QACvE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC;QACpE,OAAO;YACL,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE;YAC9C,OAAO,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE;SAC5C,CAAC;IACJ,CAAC;IAED,OAAO,gBAAgB,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function normalizeTttAction(raw: string): string;
|
|
2
|
+
export declare function normalizeAdvAction(raw: string): string;
|
|
3
|
+
export declare function normalizeRpsAction(raw: string): string;
|
|
4
|
+
export declare function normalizeGuessAction(raw: string): string;
|
|
5
|
+
export declare function normalizeDiceAction(raw: string): string;
|
|
6
|
+
export declare function normalizeChainAction(raw: string): string;
|
|
7
|
+
export declare function normalizeRiddleAction(raw: string): string;
|
|
8
|
+
//# sourceMappingURL=game-action-alias.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game-action-alias.d.ts","sourceRoot":"","sources":["../src/game-action-alias.ts"],"names":[],"mappings":"AAsEA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAkCD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|