@zhin.js/plugin-rps 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.
- package/commands/rps/[action:string=].ts +15 -0
- package/lib/engine.d.ts +0 -1
- package/lib/engine.js +1 -1
- package/lib/engine.js.map +1 -1
- package/lib/game-flow.d.ts +6 -7
- package/lib/game-flow.js +12 -8
- package/lib/game-flow.js.map +1 -1
- package/lib/index.d.ts +8 -2
- package/lib/index.js +8 -25
- package/lib/index.js.map +1 -1
- package/lib/memory-db.d.ts +6 -0
- package/lib/memory-db.js +18 -0
- package/lib/memory-db.js.map +1 -0
- package/lib/models.d.ts +5 -4
- package/lib/models.js +2 -2
- package/lib/models.js.map +1 -1
- package/lib/rps-command.d.ts +4 -3
- package/lib/rps-command.js +5 -1
- package/lib/rps-command.js.map +1 -1
- package/lib/runtime-store.d.ts +6 -0
- package/lib/runtime-store.js +7 -0
- package/lib/runtime-store.js.map +1 -0
- package/lib/session-service.d.ts +1 -3
- package/lib/session-service.js +1 -4
- package/lib/session-service.js.map +1 -1
- package/lib/view.d.ts +1 -2
- package/lib/view.js +1 -1
- package/lib/view.js.map +1 -1
- package/middlewares/rps-alias.ts +18 -0
- package/middlewares/rps-choice.ts +66 -0
- package/package.json +36 -10
- package/plugin.ts +63 -0
- package/schema.json +6 -0
- package/src/engine.ts +1 -1
- package/src/game-flow.ts +17 -14
- package/src/index.ts +9 -34
- package/src/memory-db.ts +22 -0
- package/src/models.ts +7 -4
- package/src/rps-command.ts +12 -3
- package/src/runtime-store.ts +9 -0
- package/src/session-service.ts +2 -5
- package/src/view.ts +2 -2
- package/lib/commands.d.ts +0 -6
- package/lib/commands.d.ts.map +0 -1
- package/lib/commands.js +0 -85
- package/lib/commands.js.map +0 -1
- package/lib/engine.d.ts.map +0 -1
- package/lib/game-flow.d.ts.map +0 -1
- package/lib/hub-register.d.ts +0 -5
- package/lib/hub-register.d.ts.map +0 -1
- package/lib/hub-register.js +0 -29
- package/lib/hub-register.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/models.d.ts.map +0 -1
- package/lib/rps-command.d.ts.map +0 -1
- package/lib/session-service.d.ts.map +0 -1
- package/lib/view.d.ts.map +0 -1
- package/plugin.yml +0 -2
- package/src/commands.ts +0 -105
- package/src/hub-register.ts +0 -30
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineCommand } from '@zhin.js/command';
|
|
2
|
+
import { messageFromCommandInput, normalizeRpsAction } from '@zhin.js/game-kit';
|
|
3
|
+
import { RPS_HELP, runRpsCommandText } from '../../src/rps-command.js';
|
|
4
|
+
import { resolveGameServices } from '../../src/runtime-store.js';
|
|
5
|
+
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
description: 'RPS',
|
|
8
|
+
async execute({ params, input, use, owner }) {
|
|
9
|
+
const action = normalizeRpsAction(String(params.action ?? ''));
|
|
10
|
+
if (!action || action === 'help') return RPS_HELP;
|
|
11
|
+
const services = resolveGameServices({ use, owner });
|
|
12
|
+
const message = messageFromCommandInput(input);
|
|
13
|
+
return runRpsCommandText(services, message, action);
|
|
14
|
+
},
|
|
15
|
+
});
|
package/lib/engine.d.ts
CHANGED
package/lib/engine.js
CHANGED
package/lib/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC;AAIhC,MAAM,CAAC,MAAM,WAAW,GAA4B;IAClD,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,KAAK;IACZ,QAAQ,EAAE,OAAO;CAClB,CAAC;AAEF,MAAM,KAAK,GAA6B;IACtC,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,OAAO;CAClB,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAc,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACvD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,wBAAwB;AACxB,MAAM,UAAU,YAAY,CAAC,MAAe,EAAE,GAAY;IACxD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,GAAG,GAA4B;QACnC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE,UAAU;QACpB,EAAE,EAAE,MAAM;QACV,CAAC,EAAE,OAAO;QACV,EAAE,EAAE,UAAU;QACd,CAAC,EAAE,MAAM;QACT,CAAC,EAAE,OAAO;QACV,CAAC,EAAE,UAAU;KACd,CAAC;IACF,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC"}
|
package/lib/game-flow.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type { Message, Plugin } from 'zhin.js';
|
|
1
|
+
import type { Message, Plugin } from '@zhin.js/core';
|
|
2
2
|
import type { RpsSessionRow } from './models.js';
|
|
3
3
|
import { RPS_PREFIX, type RpsMove } from './engine.js';
|
|
4
4
|
import type { SessionService } from './session-service.js';
|
|
5
|
-
export declare function sendOrEditView(plugin: Plugin, services: SessionService, message: Message<any>, session: RpsSessionRow, lastRound?: {
|
|
5
|
+
export declare function sendOrEditView(plugin: Plugin | null, services: SessionService, message: Message<any>, session: RpsSessionRow, lastRound?: {
|
|
6
6
|
player: RpsMove;
|
|
7
7
|
bot: RpsMove;
|
|
8
8
|
result: 0 | 1 | 2;
|
|
9
|
-
}): Promise<void>;
|
|
10
|
-
export declare function startGame(plugin: Plugin, services: SessionService, message: Message<any>): Promise<string | undefined>;
|
|
11
|
-
export declare function handleChoice(plugin: Plugin, services: SessionService, message: Message<any>, sessionId: string, choiceId: string): Promise<string | null>;
|
|
12
|
-
export declare function continueGame(plugin: Plugin, services: SessionService, message: Message<any>): Promise<string>;
|
|
9
|
+
}): Promise<string | void>;
|
|
10
|
+
export declare function startGame(plugin: Plugin | null, services: SessionService, message: Message<any>): Promise<string | undefined>;
|
|
11
|
+
export declare function handleChoice(plugin: Plugin | null, services: SessionService, message: Message<any>, sessionId: string, choiceId: string): Promise<string | null>;
|
|
12
|
+
export declare function continueGame(plugin: Plugin | null, services: SessionService, message: Message<any>): Promise<string>;
|
|
13
13
|
export { RPS_PREFIX };
|
|
14
|
-
//# sourceMappingURL=game-flow.d.ts.map
|
package/lib/game-flow.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { recordGameOutcome } from '@zhin.js/game-
|
|
1
|
+
import { plainTextFromSendContent, recordGameOutcome } from '@zhin.js/game-kit';
|
|
2
2
|
import { RPS_PREFIX, WIN_TARGET, randomBotMove, resolveRound, } from './engine.js';
|
|
3
3
|
import { buildRpsView } from './view.js';
|
|
4
4
|
export async function sendOrEditView(plugin, services, message, session, lastRound) {
|
|
5
5
|
const content = buildRpsView(session, lastRound, message.$channel.type);
|
|
6
|
+
if (!plugin)
|
|
7
|
+
return plainTextFromSendContent(content);
|
|
6
8
|
const adapter = plugin.root.inject(message.$adapter);
|
|
7
9
|
if (session.board_message_id) {
|
|
8
10
|
const msgId = await adapter.editMessage({
|
|
@@ -32,8 +34,8 @@ export async function startGame(plugin, services, message) {
|
|
|
32
34
|
return `本频道 ${active.player_name} 正在猜拳对决中。`;
|
|
33
35
|
}
|
|
34
36
|
const session = await services.createSession(message);
|
|
35
|
-
await sendOrEditView(plugin, services, message, session);
|
|
36
|
-
return undefined;
|
|
37
|
+
const text = await sendOrEditView(plugin, services, message, session);
|
|
38
|
+
return typeof text === 'string' ? text : undefined;
|
|
37
39
|
}
|
|
38
40
|
export async function handleChoice(plugin, services, message, sessionId, choiceId) {
|
|
39
41
|
const session = await services.getById(sessionId);
|
|
@@ -46,8 +48,8 @@ export async function handleChoice(plugin, services, message, sessionId, choiceI
|
|
|
46
48
|
return '这是别人的对局。';
|
|
47
49
|
if (choiceId === 'restart') {
|
|
48
50
|
await services.updateSession(session.id, { status: 'aborted' });
|
|
49
|
-
|
|
50
|
-
return null;
|
|
51
|
+
// text-only 模式(plugin===null)下 startGame 的唯一输出就是返回文本
|
|
52
|
+
return (await startGame(plugin, services, message)) ?? null;
|
|
51
53
|
}
|
|
52
54
|
const player = choiceId;
|
|
53
55
|
if (!['rock', 'paper', 'scissors'].includes(player))
|
|
@@ -76,14 +78,16 @@ export async function handleChoice(plugin, services, message, sessionId, choiceI
|
|
|
76
78
|
void recordGameOutcome(message, 'rps', 'won', playerWins * 10);
|
|
77
79
|
else if (status === 'lost')
|
|
78
80
|
void recordGameOutcome(message, 'rps', 'lost');
|
|
79
|
-
await sendOrEditView(plugin, services, message, updated, { player, bot, result });
|
|
80
|
-
return null;
|
|
81
|
+
const text = await sendOrEditView(plugin, services, message, updated, { player, bot, result });
|
|
82
|
+
return typeof text === 'string' ? text : null;
|
|
81
83
|
}
|
|
82
84
|
export async function continueGame(plugin, services, message) {
|
|
83
85
|
const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
|
|
84
86
|
if (!session)
|
|
85
87
|
return '你没有进行中的猜拳,发送「猜拳 开始」。';
|
|
86
|
-
await sendOrEditView(plugin, services, message, session);
|
|
88
|
+
const text = await sendOrEditView(plugin, services, message, session);
|
|
89
|
+
if (typeof text === 'string')
|
|
90
|
+
return text;
|
|
87
91
|
return '已刷新猜拳界面。';
|
|
88
92
|
}
|
|
89
93
|
export { RPS_PREFIX };
|
package/lib/game-flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
|
|
1
|
+
export { RPS_HELP } from './rps-command.js';
|
|
2
|
+
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
+
export { createInMemoryRpsDb, mountRpsMemoryServices } from './memory-db.js';
|
|
4
|
+
/**
|
|
5
|
+
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
|
+
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
|
7
|
+
* host DatabaseHost(databaseHostToken)。仍未接:interactive 按钮回调。
|
|
8
|
+
*/
|
package/lib/index.js
CHANGED
|
@@ -1,26 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let services = null;
|
|
10
|
-
useContext('database', (dbFeature) => {
|
|
11
|
-
services = createServices(resolveGameDatabase(dbFeature));
|
|
12
|
-
logger.debug(formatCompact({ 模块: '猜拳', 数据模型: '已就绪' }));
|
|
13
|
-
});
|
|
14
|
-
registerRpsHub(() => services);
|
|
15
|
-
registerCommands(plugin, () => services);
|
|
16
|
-
registerInteractive(plugin, () => services);
|
|
17
|
-
registerTextFallback(plugin, () => services);
|
|
18
|
-
addSchedule({ kind: 'solar', cron: '0 */15 * * * *' }, async () => {
|
|
19
|
-
if (!services)
|
|
20
|
-
return;
|
|
21
|
-
const n = await services.abortStale(30 * 60 * 1000);
|
|
22
|
-
if (n > 0)
|
|
23
|
-
logger.debug(formatCompact({ 猜拳: '清理超时局', count: n }));
|
|
24
|
-
});
|
|
25
|
-
logger.debug(formatCompact({ 模块: '猜拳', 状态: '已加载' }));
|
|
1
|
+
export { RPS_HELP } from './rps-command.js';
|
|
2
|
+
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
+
export { createInMemoryRpsDb, mountRpsMemoryServices } from './memory-db.js';
|
|
4
|
+
/**
|
|
5
|
+
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
|
+
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
|
7
|
+
* host DatabaseHost(databaseHostToken)。仍未接:interactive 按钮回调。
|
|
8
|
+
*/
|
|
26
9
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;GAIG"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import { type RpsDatabase, type SessionService } from './session-service.js';
|
|
3
|
+
/** In-memory rps_sessions for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
4
|
+
export declare function createInMemoryRpsDb(): RpsDatabase;
|
|
5
|
+
export declare function mountRpsMemoryServices(): SessionService;
|
|
6
|
+
export declare function mountRpsHostServices(host: DatabaseHost): SessionService;
|
package/lib/memory-db.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createHostGameDb, createInMemoryGameDb } from '@zhin.js/game-kit';
|
|
2
|
+
import { defineHostTables } from './models.js';
|
|
3
|
+
import { createServices } from './session-service.js';
|
|
4
|
+
const RPS_TABLES = ['rps_sessions'];
|
|
5
|
+
/** In-memory rps_sessions for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
6
|
+
export function createInMemoryRpsDb() {
|
|
7
|
+
return createInMemoryGameDb(RPS_TABLES);
|
|
8
|
+
}
|
|
9
|
+
export function mountRpsMemoryServices() {
|
|
10
|
+
const services = createServices(createInMemoryRpsDb());
|
|
11
|
+
return services;
|
|
12
|
+
}
|
|
13
|
+
export function mountRpsHostServices(host) {
|
|
14
|
+
defineHostTables(host);
|
|
15
|
+
const services = createServices(createHostGameDb(host, RPS_TABLES));
|
|
16
|
+
return services;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=memory-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAyC,MAAM,sBAAsB,CAAC;AAE7F,MAAM,UAAU,GAAG,CAAC,cAAc,CAAU,CAAC;AAE7C,8EAA8E;AAC9E,MAAM,UAAU,mBAAmB;IACjC,OAAO,oBAAoB,CAAC,UAAU,CAA2B,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,mBAAmB,EAAE,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IACrD,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAA2B,CAAC,CAAC;IAC9F,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/lib/models.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Models
|
|
1
|
+
import type { Models } from '@zhin.js/core';
|
|
2
2
|
export type RpsSessionStatus = 'active' | 'won' | 'lost' | 'aborted';
|
|
3
|
-
declare module 'zhin.js' {
|
|
3
|
+
declare module '@zhin.js/core' {
|
|
4
4
|
interface Models {
|
|
5
5
|
rps_sessions: {
|
|
6
6
|
id: string;
|
|
@@ -22,5 +22,6 @@ declare module 'zhin.js' {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
export type RpsSessionRow = Models['rps_sessions'];
|
|
25
|
-
export declare function
|
|
26
|
-
|
|
25
|
+
export declare function defineHostTables(db: {
|
|
26
|
+
define: (name: string, definition: Record<string, unknown>) => void;
|
|
27
|
+
}): void;
|
package/lib/models.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function
|
|
2
|
-
|
|
1
|
+
export function defineHostTables(db) {
|
|
2
|
+
db.define('rps_sessions', {
|
|
3
3
|
id: { type: 'text', primary: true },
|
|
4
4
|
adapter: { type: 'text', nullable: false },
|
|
5
5
|
endpoint: { type: 'text', nullable: false },
|
package/lib/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,gBAAgB,CAC9B,EAA2E;IAE3E,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE;QACxB,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC/C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC7C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC9C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACzC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC/C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;KAC5C,CAAC,CAAC;AACL,CAAC"}
|
package/lib/rps-command.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Message, Plugin } from 'zhin.js';
|
|
1
|
+
import type { Message, Plugin } from '@zhin.js/core';
|
|
2
2
|
import type { SessionService } from './session-service.js';
|
|
3
3
|
export declare const RPS_HELP: string;
|
|
4
|
-
export declare function runRpsCommand(plugin: Plugin, services: SessionService, message: Message<any>, action: string): Promise<string | undefined>;
|
|
5
|
-
|
|
4
|
+
export declare function runRpsCommand(plugin: Plugin | null, services: SessionService, message: Message<any>, action: string): Promise<string | undefined>;
|
|
5
|
+
/** Plugin Runtime / smoke: text-only, no Adapter.editMessage. */
|
|
6
|
+
export declare function runRpsCommandText(services: SessionService, message: Message<any>, action: string): Promise<string>;
|
package/lib/rps-command.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { channelKey } from '@zhin.js/game-
|
|
1
|
+
import { channelKey } from '@zhin.js/game-kit';
|
|
2
2
|
import { continueGame, startGame } from './game-flow.js';
|
|
3
3
|
export const RPS_HELP = [
|
|
4
4
|
'✊✋✌️ 猜拳对决(三局两胜)',
|
|
@@ -34,4 +34,8 @@ export async function runRpsCommand(plugin, services, message, action) {
|
|
|
34
34
|
}
|
|
35
35
|
return `未知子命令:${action}\n\n${RPS_HELP}`;
|
|
36
36
|
}
|
|
37
|
+
/** Plugin Runtime / smoke: text-only, no Adapter.editMessage. */
|
|
38
|
+
export async function runRpsCommandText(services, message, action) {
|
|
39
|
+
return (await runRpsCommand(null, services, message, action)) ?? '';
|
|
40
|
+
}
|
|
37
41
|
//# sourceMappingURL=rps-command.js.map
|
package/lib/rps-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rps-command.js","sourceRoot":"","sources":["../src/rps-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"rps-command.js","sourceRoot":"","sources":["../src/rps-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGzD,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,iBAAiB;IACjB,eAAe;IACf,aAAa;IACb,cAAc;IACd,cAAc;CACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAqB,EACrB,QAAwB,EACxB,OAAqB,EACrB,MAAc;IAEd,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAElC,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC7B,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpE,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE1E,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,CAAC;QAC9B,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,SAAS,MAAM,OAAO,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAwB,EACxB,OAAqB,EACrB,MAAc;IAEd,OAAO,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SessionService } from './session-service.js';
|
|
2
|
+
/** Owner-scoped service consumed by discovered commands and middleware. */
|
|
3
|
+
export declare const gameServicesToken: import("@zhin.js/plugin-runtime").Token<SessionService>;
|
|
4
|
+
export declare function resolveGameServices(context: {
|
|
5
|
+
use<T>(token: typeof gameServicesToken): T;
|
|
6
|
+
}): SessionService;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
/** Owner-scoped service consumed by discovered commands and middleware. */
|
|
3
|
+
export const gameServicesToken = createToken('zhin.game.rps.services');
|
|
4
|
+
export function resolveGameServices(context) {
|
|
5
|
+
return context.use(gameServicesToken);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=runtime-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-store.js","sourceRoot":"","sources":["../src/runtime-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAiB,wBAAwB,CAAC,CAAC;AAEvF,MAAM,UAAU,mBAAmB,CAAC,OAAuD;IACzF,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAmB,CAAC;AAC1D,CAAC"}
|
package/lib/session-service.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Database,
|
|
1
|
+
import type { Database, Message, Models } from '@zhin.js/core';
|
|
2
2
|
import type { RpsSessionRow } from './models.js';
|
|
3
3
|
export type RpsDatabase = Database<unknown, Models, string>;
|
|
4
4
|
export declare class SessionService {
|
|
@@ -13,5 +13,3 @@ export declare class SessionService {
|
|
|
13
13
|
abortStale(idleMs: number): Promise<number>;
|
|
14
14
|
}
|
|
15
15
|
export declare function createServices(db: RpsDatabase): SessionService;
|
|
16
|
-
export declare function resolveGameDatabase(feature: DatabaseFeature): RpsDatabase;
|
|
17
|
-
//# sourceMappingURL=session-service.d.ts.map
|
package/lib/session-service.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { channelKey, generateSessionId, boardMessageMatches } from '@zhin.js/game-
|
|
1
|
+
import { channelKey, generateSessionId, boardMessageMatches } from '@zhin.js/game-kit';
|
|
2
2
|
function getModel(db) {
|
|
3
3
|
const model = db.models.get('rps_sessions');
|
|
4
4
|
if (!model)
|
|
@@ -75,7 +75,4 @@ export class SessionService {
|
|
|
75
75
|
export function createServices(db) {
|
|
76
76
|
return new SessionService(db);
|
|
77
77
|
}
|
|
78
|
-
export function resolveGameDatabase(feature) {
|
|
79
|
-
return feature.db;
|
|
80
|
-
}
|
|
81
78
|
//# sourceMappingURL=session-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAKvF,SAAS,QAAQ,CAAC,EAAe;IAC/B,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC3D,OAAO,KAAsD,CAAC;AAChE,CAAC;AAED,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,EAAe;QAAf,OAAE,GAAF,EAAE,CAAa;IAAG,CAAC;IAEhD,KAAK,CAAC,kBAAkB,CAAC,OAAe;QACtC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzF,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAe,EAAE,MAAc;QACpD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAClD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,SAAiB;QAC/C,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,mBAAmB,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,EAAE,SAAS,CAAC;gBAAE,OAAO,GAAG,CAAC;QAC7E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAqB;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAkB;YACzB,EAAE,EAAE,iBAAiB,EAAE;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjC,QAAQ,EAAE,OAAO,CAAC,SAAS;YAC3B,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YACnC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC/B,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC;YAChC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC/D,WAAW,EAAE,CAAC;YACd,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,QAAQ;YAChB,gBAAgB,EAAE,EAAE;YACpB,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,KAA6B;QAC3D,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;QACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;gBAC5B,MAAM,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACvF,CAAC,EAAE,CAAC;YACN,CAAC;QACH,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAe;IAC5C,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
|
package/lib/view.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SendContent } from 'zhin.js';
|
|
1
|
+
import type { SendContent } from '@zhin.js/core';
|
|
2
2
|
import type { RpsSessionRow } from './models.js';
|
|
3
3
|
import { type RpsMove } from './engine.js';
|
|
4
4
|
export declare function buildRpsView(session: RpsSessionRow, lastRound?: {
|
|
@@ -6,4 +6,3 @@ export declare function buildRpsView(session: RpsSessionRow, lastRound?: {
|
|
|
6
6
|
bot: RpsMove;
|
|
7
7
|
result: 0 | 1 | 2;
|
|
8
8
|
}, channelType?: string): SendContent;
|
|
9
|
-
//# sourceMappingURL=view.d.ts.map
|
package/lib/view.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildChoiceKeyboard } from '@zhin.js/game-
|
|
1
|
+
import { buildChoiceKeyboard } from '@zhin.js/game-kit';
|
|
2
2
|
import { MOVE_LABELS, RPS_PREFIX, WIN_TARGET } from './engine.js';
|
|
3
3
|
export function buildRpsView(session, lastRound, channelType) {
|
|
4
4
|
const terminal = session.status !== 'active';
|
package/lib/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAEhF,MAAM,UAAU,YAAY,CAC1B,OAAsB,EACtB,SAAgE,EAChE,WAAoB;IAEpB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC;IAC7C,MAAM,KAAK,GAAG;QACZ,eAAe;QACf,EAAE;QACF,YAAY,OAAO,CAAC,WAAW,UAAU,OAAO,CAAC,QAAQ,YAAY,UAAU,KAAK;KACrF,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrF,KAAK,CAAC,IAAI,CACR,SAAS,CAAC,MAAM,KAAK,CAAC;YACpB,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;gBACtB,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,cAAc,CACrB,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;aACrD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACpE,CAAC;SAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ;QACtB,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAkB,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC;QACjG,CAAC,CAAE,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvD,EAAE,EAAE,CAAC;YACL,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;YACrB,KAAK,EAAE,WAAoB;SAC5B,CAAC,CAAC,CAAC;IAER,OAAO,mBAAmB,CAAC;QACzB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3B,OAAO;QACP,QAAQ;QACR,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,oBAAoB;QAClC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;QACtD,WAAW;KACZ,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineGameCommandAliasMiddleware,
|
|
3
|
+
messageFromCommandInput,
|
|
4
|
+
normalizeRpsAction,
|
|
5
|
+
} from '@zhin.js/game-kit';
|
|
6
|
+
import { RPS_HELP, runRpsCommandText } from '../src/rps-command.js';
|
|
7
|
+
import { resolveGameServices } from '../src/runtime-store.js';
|
|
8
|
+
|
|
9
|
+
export default defineGameCommandAliasMiddleware({
|
|
10
|
+
aliases: ['猜拳', 'rps'],
|
|
11
|
+
async run(action, input, context) {
|
|
12
|
+
const normalized = normalizeRpsAction(String(action ?? ''));
|
|
13
|
+
if (!normalized || normalized === 'help') return RPS_HELP;
|
|
14
|
+
const services = resolveGameServices(context);
|
|
15
|
+
const message = messageFromCommandInput(input);
|
|
16
|
+
return runRpsCommandText(services, message, normalized);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { defineMiddleware } from '@zhin.js/middleware';
|
|
2
|
+
import type { Message } from '@zhin.js/core/runtime';
|
|
3
|
+
import {
|
|
4
|
+
buildChoiceFallbackMap,
|
|
5
|
+
channelKey,
|
|
6
|
+
messageFromCommandInput,
|
|
7
|
+
parseChoicePayload,
|
|
8
|
+
resolveGameTextPayload,
|
|
9
|
+
} from '@zhin.js/game-kit';
|
|
10
|
+
import { resolveGameServices } from '../src/runtime-store.js';
|
|
11
|
+
import { handleChoice, RPS_PREFIX } from '../src/game-flow.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 文本入口:按钮 payload(`rps:session:rock|paper|scissors|restart`)与数字 fallback
|
|
15
|
+
* (『1石头 2布 3剪刀』,对应 view 的 fallbackHint)。
|
|
16
|
+
*/
|
|
17
|
+
export default defineMiddleware<Message>({
|
|
18
|
+
target: 'inbound',
|
|
19
|
+
async handle(context, next) {
|
|
20
|
+
const raw = context.input.content?.trim() ?? '';
|
|
21
|
+
if (!raw) {
|
|
22
|
+
await next();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const services = resolveGameServices(context);
|
|
26
|
+
const message = messageFromCommandInput(context.input);
|
|
27
|
+
const ch = channelKey(message);
|
|
28
|
+
|
|
29
|
+
// 直接 payload(QQ 指令预填 / Sandbox action→text)
|
|
30
|
+
const payloadFromText = resolveGameTextPayload(raw);
|
|
31
|
+
if (payloadFromText?.startsWith(`${RPS_PREFIX}:`)) {
|
|
32
|
+
const parsed = parseChoicePayload(payloadFromText, RPS_PREFIX);
|
|
33
|
+
if (parsed) {
|
|
34
|
+
const session = await services.getById(parsed.sessionId);
|
|
35
|
+
if (session?.channel_key === ch) {
|
|
36
|
+
const reply = await handleChoice(null, services, message, parsed.sessionId, parsed.choiceId);
|
|
37
|
+
if (reply) await context.input.$reply(reply);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
await next();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const session = await services.getActiveForUser(ch, message.$sender.id);
|
|
46
|
+
if (!session || session.status !== 'active') {
|
|
47
|
+
await next();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const map = buildChoiceFallbackMap(RPS_PREFIX, session.id, [
|
|
52
|
+
{ id: 'rock', label: '石头' },
|
|
53
|
+
{ id: 'paper', label: '布' },
|
|
54
|
+
{ id: 'scissors', label: '剪刀' },
|
|
55
|
+
]);
|
|
56
|
+
const payload = resolveGameTextPayload(raw, map);
|
|
57
|
+
const parsed = payload ? parseChoicePayload(payload, RPS_PREFIX) : null;
|
|
58
|
+
if (!parsed || parsed.sessionId !== session.id) {
|
|
59
|
+
await next();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const reply = await handleChoice(null, services, message, session.id, parsed.choiceId);
|
|
64
|
+
if (reply) await context.input.$reply(reply);
|
|
65
|
+
},
|
|
66
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-rps",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Zhin.js 猜拳游戏 — 石头剪刀布三局两胜",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Zhin.js 猜拳游戏 — 石头剪刀布三局两胜 (Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -14,21 +14,25 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
+
"plugin.ts",
|
|
18
|
+
"schema.json",
|
|
19
|
+
"commands",
|
|
20
|
+
"middlewares",
|
|
17
21
|
"src",
|
|
18
22
|
"lib",
|
|
19
|
-
"plugin.yml",
|
|
20
23
|
"README.md"
|
|
21
24
|
],
|
|
22
25
|
"license": "MIT",
|
|
23
|
-
"peerDependencies": {
|
|
24
|
-
"zhin.js": "4.1.2"
|
|
25
|
-
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@zhin.js/
|
|
27
|
+
"@zhin.js/command": "1.0.1",
|
|
28
|
+
"@zhin.js/core": "1.3.5",
|
|
29
|
+
"@zhin.js/game-kit": "1.0.2",
|
|
30
|
+
"@zhin.js/middleware": "1.0.1",
|
|
31
|
+
"@zhin.js/plugin-runtime": "1.0.1"
|
|
28
32
|
},
|
|
29
33
|
"devDependencies": {
|
|
30
34
|
"typescript": "^6.0.3",
|
|
31
|
-
"
|
|
35
|
+
"vitest": "^4.1.10"
|
|
32
36
|
},
|
|
33
37
|
"repository": {
|
|
34
38
|
"type": "git",
|
|
@@ -39,8 +43,30 @@
|
|
|
39
43
|
"access": "public",
|
|
40
44
|
"registry": "https://registry.npmjs.org"
|
|
41
45
|
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
48
|
+
},
|
|
49
|
+
"zhin": {
|
|
50
|
+
"protocol": 1,
|
|
51
|
+
"type": "plugin",
|
|
52
|
+
"entry": "./plugin.ts",
|
|
53
|
+
"engine": "^1.0.0",
|
|
54
|
+
"runtime": "trusted",
|
|
55
|
+
"features": [
|
|
56
|
+
{
|
|
57
|
+
"package": "@zhin.js/command",
|
|
58
|
+
"api": "^1.0.0"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"package": "@zhin.js/middleware",
|
|
62
|
+
"api": "^1.0.0"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"plugins": []
|
|
66
|
+
},
|
|
42
67
|
"scripts": {
|
|
43
|
-
"build": "tsc
|
|
44
|
-
"clean": "rimraf lib"
|
|
68
|
+
"build": "tsc",
|
|
69
|
+
"clean": "rimraf lib",
|
|
70
|
+
"test": "NODE_OPTIONS=--experimental-strip-types vitest run --root ../../.. plugins/games/rps/tests"
|
|
45
71
|
}
|
|
46
72
|
}
|
package/plugin.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { definePlugin, databaseHostToken, scheduleHostToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import {
|
|
3
|
+
registerRuntimeGame,
|
|
4
|
+
initGameRecordHost,
|
|
5
|
+
DEFAULT_GAME_STALE_CRON,
|
|
6
|
+
DEFAULT_GAME_STALE_IDLE_MS,
|
|
7
|
+
} from '@zhin.js/game-kit';
|
|
8
|
+
import { mountRpsHostServices, mountRpsMemoryServices } from './src/memory-db.js';
|
|
9
|
+
import { gameServicesToken } from './src/runtime-store.js';
|
|
10
|
+
import type { SessionService } from './src/session-service.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Plugin Runtime:
|
|
14
|
+
* - Commands under `commands/` are authoritative (help + start/continue/quit via in-memory DB).
|
|
15
|
+
* - DB: prefer databaseHostToken; else in-memory SessionService.
|
|
16
|
+
* - Choice middleware under `middlewares/` handles RPS choice payloads (Sandbox action→text).
|
|
17
|
+
*/
|
|
18
|
+
export default definePlugin({
|
|
19
|
+
name: 'rps',
|
|
20
|
+
metadata: {
|
|
21
|
+
displayName: 'RPS',
|
|
22
|
+
},
|
|
23
|
+
setup(context) {
|
|
24
|
+
let services: SessionService;
|
|
25
|
+
if (context.resources.has(databaseHostToken)) {
|
|
26
|
+
const host = context.resources.use(databaseHostToken);
|
|
27
|
+
services = mountRpsHostServices(host);
|
|
28
|
+
context.lifecycle.add(initGameRecordHost(host));
|
|
29
|
+
} else {
|
|
30
|
+
services = mountRpsMemoryServices();
|
|
31
|
+
}
|
|
32
|
+
context.resources.provide(gameServicesToken, services);
|
|
33
|
+
const disposeHub = registerRuntimeGame({
|
|
34
|
+
id: 'rps',
|
|
35
|
+
title: '猜拳对决',
|
|
36
|
+
icon: '✊',
|
|
37
|
+
description: '石头剪刀布,三局两胜',
|
|
38
|
+
commandPrefix: '/猜拳',
|
|
39
|
+
quickStart: '开始',
|
|
40
|
+
aliases: ['rps'],
|
|
41
|
+
menus: [
|
|
42
|
+
{ id: 'start', label: '🎮 开始对局' },
|
|
43
|
+
{ id: 'continue', label: '🔄 继续' },
|
|
44
|
+
{ id: 'help', label: '📖 玩法说明' },
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
context.lifecycle.add(disposeHub);
|
|
48
|
+
|
|
49
|
+
if (context.resources.has(scheduleHostToken)) {
|
|
50
|
+
const schedule = context.resources.use(scheduleHostToken);
|
|
51
|
+
const disposeCron = schedule.register({
|
|
52
|
+
id: 'rps/abort-stale',
|
|
53
|
+
cron: DEFAULT_GAME_STALE_CRON,
|
|
54
|
+
description: 'Abort stale rps sessions',
|
|
55
|
+
async execute() {
|
|
56
|
+
if (!services.abortStale) return;
|
|
57
|
+
await services.abortStale(DEFAULT_GAME_STALE_IDLE_MS);
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
context.lifecycle.add(disposeCron);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|