@zhin.js/plugin-text-adventure 1.0.4 → 1.0.5
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/adv/[action:string=].js +16 -0
- package/lib/adv-command.d.ts +2 -2
- package/lib/adv-command.js +1 -1
- package/lib/adv-command.js.map +1 -1
- package/lib/game-flow.d.ts +5 -5
- package/lib/game-flow.js +1 -3
- package/lib/game-flow.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/models.d.ts +0 -1
- package/lib/models.js +0 -1
- package/lib/models.js.map +1 -1
- package/lib/session-service.d.ts +2 -9
- package/lib/session-service.js +7 -48
- package/lib/session-service.js.map +1 -1
- package/middlewares/adv-alias.js +18 -0
- package/middlewares/adv-choice.js +61 -0
- package/package.json +7 -7
- package/plugin.js +38 -0
- package/src/adv-command.ts +6 -2
- package/src/game-flow.ts +6 -7
- package/src/index.ts +0 -1
- package/src/models.ts +0 -2
- package/src/session-service.ts +14 -53
- package/lib/memory-db.d.ts +0 -6
- package/lib/memory-db.js +0 -18
- package/lib/memory-db.js.map +0 -1
- package/plugin.ts +0 -65
- package/src/memory-db.ts +0 -22
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineCommand } from '@zhin.js/command';
|
|
3
|
+
import { messageFromCommandInput, normalizeAdvAction } from '@zhin.js/game-kit';
|
|
4
|
+
import { ADV_HELP, runAdvCommand } from "../../lib/adv-command.js";
|
|
5
|
+
import { resolveGameServices } from "../../lib/runtime-store.js";
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
description: 'Text Adventure',
|
|
8
|
+
async execute({ params, input, use, owner }) {
|
|
9
|
+
const action = normalizeAdvAction(String(params.action ?? ''));
|
|
10
|
+
if (!action || action === 'help')
|
|
11
|
+
return ADV_HELP;
|
|
12
|
+
const services = resolveGameServices({ use, owner });
|
|
13
|
+
const message = messageFromCommandInput(input);
|
|
14
|
+
return runAdvCommand(services, message, action);
|
|
15
|
+
},
|
|
16
|
+
});
|
package/lib/adv-command.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type GameMessageLike } from '@zhin.js/game-kit';
|
|
1
|
+
import { type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
|
|
2
2
|
import type { GameServices } from './session-service.js';
|
|
3
3
|
export declare const ADV_HELP: string;
|
|
4
|
-
export declare function runAdvCommand(services: GameServices, message: GameMessageLike, action: string): Promise<
|
|
4
|
+
export declare function runAdvCommand(services: GameServices, message: GameMessageLike, action: string): Promise<GameReply>;
|
package/lib/adv-command.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { channelKey } from '@zhin.js/game-kit';
|
|
1
|
+
import { channelKey, } from '@zhin.js/game-kit';
|
|
2
2
|
import { continueAdventure, sessionSummary, startAdventure, } from './game-flow.js';
|
|
3
3
|
import { formatAchievements, formatMapProgress, formatProgressCompact } from './profile-format.js';
|
|
4
4
|
export const ADV_HELP = [
|
package/lib/adv-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adv-command.js","sourceRoot":"","sources":["../src/adv-command.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"adv-command.js","sourceRoot":"","sources":["../src/adv-command.ts"],"names":[],"mappings":"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"}
|
package/lib/game-flow.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
|
|
2
2
|
import type { AdvProfileRow, AdvSessionRow } from './models.js';
|
|
3
3
|
import type { GameServices } from './session-service.js';
|
|
4
|
-
export declare function sendOrEditScene(services: GameServices, message: GameMessageLike, session: AdvSessionRow, extraNarrative?: string, profile?: AdvProfileRow): Promise<
|
|
5
|
-
export declare function startAdventure(services: GameServices, message: GameMessageLike): Promise<
|
|
6
|
-
export declare function handleChoice(services: GameServices, message: GameMessageLike, sessionId: string, choiceId: string): Promise<
|
|
7
|
-
export declare function continueAdventure(services: GameServices, message: GameMessageLike): Promise<
|
|
4
|
+
export declare function sendOrEditScene(services: GameServices, message: GameMessageLike, session: AdvSessionRow, extraNarrative?: string, profile?: AdvProfileRow): Promise<GameReply>;
|
|
5
|
+
export declare function startAdventure(services: GameServices, message: GameMessageLike): Promise<GameReply | undefined>;
|
|
6
|
+
export declare function handleChoice(services: GameServices, message: GameMessageLike, sessionId: string, choiceId: string): Promise<GameReply | null>;
|
|
7
|
+
export declare function continueAdventure(services: GameServices, message: GameMessageLike): Promise<GameReply>;
|
|
8
8
|
export declare function sessionSummary(session: AdvSessionRow): string;
|
package/lib/game-flow.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { plainTextFromSendContent } from '@zhin.js/game-kit';
|
|
2
1
|
import { formatNewAchievements } from './profile-format.js';
|
|
3
2
|
import { buildSceneInteractive } from './scene-view.js';
|
|
4
3
|
import { applyChoiceResult, getScene, resolveChoice, stateFromSession, visibleChoices, } from './story.js';
|
|
@@ -9,7 +8,7 @@ export async function sendOrEditScene(services, message, session, extraNarrative
|
|
|
9
8
|
if (!content) {
|
|
10
9
|
return '场景数据异常,请 adv quit 后重新开始。';
|
|
11
10
|
}
|
|
12
|
-
return
|
|
11
|
+
return content;
|
|
13
12
|
}
|
|
14
13
|
export async function startAdventure(services, message) {
|
|
15
14
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
@@ -50,7 +49,6 @@ export async function handleChoice(services, message, sessionId, choiceId) {
|
|
|
50
49
|
ending_id: '',
|
|
51
50
|
status: 'active',
|
|
52
51
|
step_count: 0,
|
|
53
|
-
board_message_id: '',
|
|
54
52
|
});
|
|
55
53
|
const updated = (await services.sessions.getById(session.id));
|
|
56
54
|
await services.profiles.onRunStarted(updated.player_id, updated.player_name);
|
package/lib/game-flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"
|
|
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,6 +1,5 @@
|
|
|
1
1
|
export { ADV_HELP } from './adv-command.js';
|
|
2
2
|
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
-
export { createInMemoryAdvDb, mountAdvMemoryServices } from './memory-db.js';
|
|
4
3
|
/**
|
|
5
4
|
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
5
|
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { ADV_HELP } from './adv-command.js';
|
|
2
2
|
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
-
export { createInMemoryAdvDb, mountAdvMemoryServices } from './memory-db.js';
|
|
4
3
|
/**
|
|
5
4
|
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
5
|
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAE5E;;;;GAIG"}
|
package/lib/models.d.ts
CHANGED
package/lib/models.js
CHANGED
|
@@ -14,7 +14,6 @@ export function defineHostTables(db) {
|
|
|
14
14
|
flags: { type: 'text', default: '{}' },
|
|
15
15
|
ending_id: { type: 'text', default: '' },
|
|
16
16
|
status: { type: 'text', default: 'active' },
|
|
17
|
-
board_message_id: { type: 'text', default: '' },
|
|
18
17
|
step_count: { type: 'integer', default: 0 },
|
|
19
18
|
updated_at: { type: 'integer', default: 0 },
|
|
20
19
|
created_at: { type: 'integer', default: 0 },
|
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":"AA+CA,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,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;QAC5C,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE;QACrC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1C,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACtC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACxC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,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;IACH,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE;QACxB,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC/C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC5C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7C,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC7C,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC/C,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,eAAe,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAChD,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/session-service.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Database, Models } from '@zhin.js/core';
|
|
2
|
-
import { type GameMessageLike } from '@zhin.js/game-kit';
|
|
2
|
+
import { BaseSessionService, type GameMessageLike } from '@zhin.js/game-kit';
|
|
3
3
|
import type { AdvSessionRow } from './models.js';
|
|
4
4
|
import { ProfileService } from './profile-service.js';
|
|
5
5
|
export type AdvDatabase = Database<unknown, Models, string>;
|
|
@@ -7,15 +7,8 @@ export interface GameServices {
|
|
|
7
7
|
sessions: SessionService;
|
|
8
8
|
profiles: ProfileService;
|
|
9
9
|
}
|
|
10
|
-
export declare class SessionService {
|
|
11
|
-
private readonly db;
|
|
10
|
+
export declare class SessionService extends BaseSessionService<AdvSessionRow> {
|
|
12
11
|
constructor(db: AdvDatabase);
|
|
13
|
-
getActiveByChannel(channel: string): Promise<AdvSessionRow | null>;
|
|
14
|
-
getActiveForUser(channel: string, userId: string): Promise<AdvSessionRow | null>;
|
|
15
|
-
getById(id: string): Promise<AdvSessionRow | null>;
|
|
16
|
-
getActiveByBoardMessageId(messageId: string): Promise<AdvSessionRow | null>;
|
|
17
12
|
createSession(message: GameMessageLike): Promise<AdvSessionRow>;
|
|
18
|
-
updateSession(id: string, patch: Partial<AdvSessionRow>): Promise<void>;
|
|
19
|
-
abortStale(idleMs: number): Promise<number>;
|
|
20
13
|
}
|
|
21
14
|
export declare function createServices(db: AdvDatabase): GameServices;
|
package/lib/session-service.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { channelKey, generateSessionId,
|
|
1
|
+
import { BaseSessionService, channelKey, generateSessionId, } from '@zhin.js/game-kit';
|
|
2
2
|
import { createProfileService } from './profile-service.js';
|
|
3
3
|
function getModel(db, name) {
|
|
4
4
|
const model = db.models.get(name);
|
|
@@ -6,36 +6,13 @@ function getModel(db, name) {
|
|
|
6
6
|
throw new Error(`Model ${name} is not registered`);
|
|
7
7
|
return model;
|
|
8
8
|
}
|
|
9
|
-
export class SessionService {
|
|
10
|
-
db;
|
|
9
|
+
export class SessionService extends BaseSessionService {
|
|
11
10
|
constructor(db) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
channel_key: channel,
|
|
17
|
-
status: 'active',
|
|
11
|
+
super(db, {
|
|
12
|
+
gameId: 'adv',
|
|
13
|
+
table: 'adv_sessions',
|
|
14
|
+
userFields: ['player_id'],
|
|
18
15
|
});
|
|
19
|
-
return rows[0] ?? null;
|
|
20
|
-
}
|
|
21
|
-
async getActiveForUser(channel, userId) {
|
|
22
|
-
const row = await this.getActiveByChannel(channel);
|
|
23
|
-
if (!row || row.player_id !== userId)
|
|
24
|
-
return null;
|
|
25
|
-
return row;
|
|
26
|
-
}
|
|
27
|
-
async getById(id) {
|
|
28
|
-
return getModel(this.db, 'adv_sessions').findOne({ id });
|
|
29
|
-
}
|
|
30
|
-
async getActiveByBoardMessageId(messageId) {
|
|
31
|
-
if (!messageId)
|
|
32
|
-
return null;
|
|
33
|
-
const rows = await getModel(this.db, 'adv_sessions').findAll({});
|
|
34
|
-
for (const row of rows) {
|
|
35
|
-
if (boardMessageMatches(row.board_message_id ?? '', messageId))
|
|
36
|
-
return row;
|
|
37
|
-
}
|
|
38
|
-
return null;
|
|
39
16
|
}
|
|
40
17
|
async createSession(message) {
|
|
41
18
|
const now = Date.now();
|
|
@@ -55,29 +32,11 @@ export class SessionService {
|
|
|
55
32
|
flags: '{}',
|
|
56
33
|
ending_id: '',
|
|
57
34
|
status: 'active',
|
|
58
|
-
board_message_id: '',
|
|
59
35
|
step_count: 0,
|
|
60
36
|
updated_at: now,
|
|
61
37
|
created_at: now,
|
|
62
38
|
};
|
|
63
|
-
|
|
64
|
-
return row;
|
|
65
|
-
}
|
|
66
|
-
async updateSession(id, patch) {
|
|
67
|
-
await getModel(this.db, 'adv_sessions').updateWhere({ id }, { ...patch, updated_at: Date.now() });
|
|
68
|
-
}
|
|
69
|
-
async abortStale(idleMs) {
|
|
70
|
-
const cutoff = Date.now() - idleMs;
|
|
71
|
-
const sessions = getModel(this.db, 'adv_sessions');
|
|
72
|
-
const rows = await sessions.findAll({ status: 'active' });
|
|
73
|
-
let n = 0;
|
|
74
|
-
for (const row of rows) {
|
|
75
|
-
if (row.updated_at < cutoff) {
|
|
76
|
-
await sessions.updateWhere({ id: row.id }, { status: 'aborted', updated_at: Date.now() });
|
|
77
|
-
n++;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return n;
|
|
39
|
+
return this.createRow(row);
|
|
81
40
|
}
|
|
82
41
|
}
|
|
83
42
|
export function createServices(db) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oBAAoB,EAAkB,MAAM,sBAAsB,CAAC;AAK5E,SAAS,QAAQ,CAAyB,EAAe,EAAE,IAAO;IAChE,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,oBAAoB,CAAC,CAAC;IAC/D,OAAO,KAAoB,CAAC;AAC9B,CAAC;AAOD,MAAM,OAAO,cAAe,SAAQ,kBAAiC;IACnE,YAAY,EAAe;QACzB,KAAK,CAAC,EAAmD,EAAE;YACzD,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,cAAc;YACrB,UAAU,EAAE,CAAC,WAAW,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAwB;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAkB;YACzB,EAAE;YACF,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,QAAQ,EAAE,OAAO;YACjB,EAAE,EAAE,GAAG;YACP,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAe;IAC5C,OAAO;QACL,QAAQ,EAAE,IAAI,cAAc,CAAC,EAAE,CAAC;QAChC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,CAAC;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineGameCommandAliasMiddleware, isAdvAction, messageFromCommandInput, normalizeAdvAction, } from '@zhin.js/game-kit';
|
|
3
|
+
import { ADV_HELP, runAdvCommand } from "../lib/adv-command.js";
|
|
4
|
+
import { resolveGameServices } from "../lib/runtime-store.js";
|
|
5
|
+
export default defineGameCommandAliasMiddleware({
|
|
6
|
+
aliases: ['冒险', 'adv', '秘境'],
|
|
7
|
+
async run(action, input, context) {
|
|
8
|
+
const normalized = normalizeAdvAction(String(action ?? ''));
|
|
9
|
+
if (normalized === 'help')
|
|
10
|
+
return ADV_HELP;
|
|
11
|
+
// action 无法识别:放行给后续中间件,避免劫持普通聊天
|
|
12
|
+
if (!isAdvAction(normalized))
|
|
13
|
+
return null;
|
|
14
|
+
const services = resolveGameServices(context);
|
|
15
|
+
const message = messageFromCommandInput(input);
|
|
16
|
+
return runAdvCommand(services, message, normalized);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineMiddleware } from '@zhin.js/middleware';
|
|
3
|
+
import { buildChoiceFallbackMap, channelKey, messageFromCommandInput, parseChoicePayload, resolveGameTextPayload, } from '@zhin.js/game-kit';
|
|
4
|
+
import { resolveGameServices } from "../lib/runtime-store.js";
|
|
5
|
+
import { handleChoice } from "../lib/game-flow.js";
|
|
6
|
+
import { ADV_PREFIX, getScene, stateFromSession, visibleChoices } from "../lib/story.js";
|
|
7
|
+
/**
|
|
8
|
+
* 文本入口:按钮 payload(`adv:session:choiceId`)与数字 fallback
|
|
9
|
+
* (按当前场景可见选项编号,对应视图提示用户回复数字选分支)。
|
|
10
|
+
*/
|
|
11
|
+
export default defineMiddleware({
|
|
12
|
+
target: 'inbound',
|
|
13
|
+
async handle(context, next) {
|
|
14
|
+
const raw = context.input.content?.trim() ?? '';
|
|
15
|
+
if (!raw) {
|
|
16
|
+
await next();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const services = resolveGameServices(context);
|
|
20
|
+
const message = messageFromCommandInput(context.input);
|
|
21
|
+
const ch = channelKey(message);
|
|
22
|
+
// 直接 payload(QQ 指令预填 / Sandbox action→text)
|
|
23
|
+
const payloadFromText = resolveGameTextPayload(raw);
|
|
24
|
+
if (payloadFromText?.startsWith(`${ADV_PREFIX}:`)) {
|
|
25
|
+
const parsed = parseChoicePayload(payloadFromText, ADV_PREFIX);
|
|
26
|
+
if (parsed) {
|
|
27
|
+
const session = await services.sessions.getById(parsed.sessionId);
|
|
28
|
+
if (session?.channel_key === ch) {
|
|
29
|
+
const reply = await handleChoice(services, message, parsed.sessionId, parsed.choiceId);
|
|
30
|
+
if (reply)
|
|
31
|
+
await context.input.$reply(reply);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
await next();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const session = await services.sessions.getActiveForUser(ch, message.$sender.id);
|
|
39
|
+
if (!session) {
|
|
40
|
+
await next();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const scene = getScene(session.scene_id);
|
|
44
|
+
if (!scene) {
|
|
45
|
+
await next();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const state = stateFromSession(session);
|
|
49
|
+
const choices = visibleChoices(scene, state);
|
|
50
|
+
const map = buildChoiceFallbackMap(ADV_PREFIX, session.id, choices);
|
|
51
|
+
const payload = resolveGameTextPayload(raw, map);
|
|
52
|
+
const parsed = payload ? parseChoicePayload(payload, ADV_PREFIX) : null;
|
|
53
|
+
if (!parsed || parsed.sessionId !== session.id) {
|
|
54
|
+
await next();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const reply = await handleChoice(services, message, session.id, parsed.choiceId);
|
|
58
|
+
if (reply)
|
|
59
|
+
await context.input.$reply(reply);
|
|
60
|
+
},
|
|
61
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-text-adventure",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Zhin.js 交互式文字冒险 (Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"plugin.
|
|
17
|
+
"plugin.js",
|
|
18
18
|
"schema.json",
|
|
19
19
|
"commands",
|
|
20
20
|
"middlewares",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
],
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@zhin.js/command": "1.0.
|
|
28
|
-
"@zhin.js/core": "1.4.
|
|
29
|
-
"@zhin.js/game-kit": "2.0.
|
|
30
|
-
"@zhin.js/middleware": "1.0.
|
|
27
|
+
"@zhin.js/command": "1.0.4",
|
|
28
|
+
"@zhin.js/core": "1.4.2",
|
|
29
|
+
"@zhin.js/game-kit": "2.0.2",
|
|
30
|
+
"@zhin.js/middleware": "1.0.4",
|
|
31
31
|
"@zhin.js/plugin-runtime": "1.1.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"zhin": {
|
|
50
50
|
"protocol": 1,
|
|
51
51
|
"type": "plugin",
|
|
52
|
-
"entry": "./plugin.
|
|
52
|
+
"entry": "./plugin.js",
|
|
53
53
|
"engine": "^1.0.0",
|
|
54
54
|
"runtime": "trusted",
|
|
55
55
|
"features": [
|
package/plugin.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineGamePlugin } from '@zhin.js/game-kit';
|
|
3
|
+
import { defineHostTables } from "./lib/models.js";
|
|
4
|
+
import { gameServicesToken } from "./lib/runtime-store.js";
|
|
5
|
+
import { createServices, } from "./lib/session-service.js";
|
|
6
|
+
/**
|
|
7
|
+
* Plugin Runtime:
|
|
8
|
+
* - Commands under `commands/` are authoritative (help + start/continue/…).
|
|
9
|
+
* - DB: prefer databaseHostToken; else in-memory GameServices.
|
|
10
|
+
* - Choice middleware under `middlewares/` handles adv choice payloads (Sandbox action→text).
|
|
11
|
+
*/
|
|
12
|
+
export default defineGamePlugin({
|
|
13
|
+
name: 'text-adventure',
|
|
14
|
+
metadata: {
|
|
15
|
+
displayName: 'Text Adventure',
|
|
16
|
+
},
|
|
17
|
+
game: {
|
|
18
|
+
id: 'adv',
|
|
19
|
+
title: '秘境探险',
|
|
20
|
+
icon: '🗺️',
|
|
21
|
+
description: '文字冒险,31 区域 · 15 结局 · 成就收集',
|
|
22
|
+
commandPrefix: '/冒险',
|
|
23
|
+
quickStart: '开始',
|
|
24
|
+
aliases: ['adv', '秘境'],
|
|
25
|
+
menus: [
|
|
26
|
+
{ id: 'start', label: '🚪 开始冒险' },
|
|
27
|
+
{ id: 'continue', label: '🔄 继续冒险' },
|
|
28
|
+
{ id: 'map', label: '🗺️ 探索进度' },
|
|
29
|
+
{ id: 'achievements', label: '🏅 成就' },
|
|
30
|
+
{ id: 'help', label: '📖 玩法说明' },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
tables: ['adv_sessions', 'adv_profiles'],
|
|
34
|
+
servicesToken: gameServicesToken,
|
|
35
|
+
defineHostTables,
|
|
36
|
+
createServices: (database) => createServices(database),
|
|
37
|
+
session: (services) => services.sessions,
|
|
38
|
+
});
|
package/src/adv-command.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
channelKey,
|
|
3
|
+
type GameMessageLike,
|
|
4
|
+
type GameReply,
|
|
5
|
+
} from '@zhin.js/game-kit';
|
|
2
6
|
import {
|
|
3
7
|
continueAdventure,
|
|
4
8
|
sessionSummary,
|
|
@@ -23,7 +27,7 @@ export async function runAdvCommand(
|
|
|
23
27
|
services: GameServices,
|
|
24
28
|
message: GameMessageLike,
|
|
25
29
|
action: string,
|
|
26
|
-
): Promise<
|
|
30
|
+
): Promise<GameReply> {
|
|
27
31
|
const ch = channelKey(message);
|
|
28
32
|
const userId = message.$sender.id;
|
|
29
33
|
const userName = message.$sender.name?.trim() || userId;
|
package/src/game-flow.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
|
|
2
2
|
import type { AdvProfileRow, AdvSessionRow } from './models.js';
|
|
3
3
|
import { formatNewAchievements } from './profile-format.js';
|
|
4
4
|
import { buildSceneInteractive } from './scene-view.js';
|
|
@@ -17,20 +17,20 @@ export async function sendOrEditScene(
|
|
|
17
17
|
session: AdvSessionRow,
|
|
18
18
|
extraNarrative = '',
|
|
19
19
|
profile?: AdvProfileRow,
|
|
20
|
-
): Promise<
|
|
20
|
+
): Promise<GameReply> {
|
|
21
21
|
const prof = profile
|
|
22
22
|
?? await services.profiles.getOrCreate(session.player_id, session.player_name);
|
|
23
23
|
const content = buildSceneInteractive(session, extraNarrative, prof, message.$channel.type);
|
|
24
24
|
if (!content) {
|
|
25
25
|
return '场景数据异常,请 adv quit 后重新开始。';
|
|
26
26
|
}
|
|
27
|
-
return
|
|
27
|
+
return content;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export async function startAdventure(
|
|
31
31
|
services: GameServices,
|
|
32
32
|
message: GameMessageLike,
|
|
33
|
-
): Promise<
|
|
33
|
+
): Promise<GameReply | undefined> {
|
|
34
34
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
35
35
|
const active = await services.sessions.getActiveByChannel(ch);
|
|
36
36
|
if (active) {
|
|
@@ -56,7 +56,7 @@ export async function handleChoice(
|
|
|
56
56
|
message: GameMessageLike,
|
|
57
57
|
sessionId: string,
|
|
58
58
|
choiceId: string,
|
|
59
|
-
): Promise<
|
|
59
|
+
): Promise<GameReply | null> {
|
|
60
60
|
const session = await services.sessions.getById(sessionId);
|
|
61
61
|
// 踏进 terminal 场景时 status 必为 completed,终局需放行「再玩一次」(restart)
|
|
62
62
|
if (!session || (session.status !== 'active' && !(session.status === 'completed' && choiceId === 'restart'))) {
|
|
@@ -83,7 +83,6 @@ export async function handleChoice(
|
|
|
83
83
|
ending_id: '',
|
|
84
84
|
status: 'active',
|
|
85
85
|
step_count: 0,
|
|
86
|
-
board_message_id: '',
|
|
87
86
|
});
|
|
88
87
|
const updated = (await services.sessions.getById(session.id))!;
|
|
89
88
|
await services.profiles.onRunStarted(updated.player_id, updated.player_name);
|
|
@@ -147,7 +146,7 @@ export async function handleChoice(
|
|
|
147
146
|
export async function continueAdventure(
|
|
148
147
|
services: GameServices,
|
|
149
148
|
message: GameMessageLike,
|
|
150
|
-
): Promise<
|
|
149
|
+
): Promise<GameReply> {
|
|
151
150
|
const session = await services.sessions.getActiveForUser(
|
|
152
151
|
`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
|
|
153
152
|
message.$sender.id,
|
package/src/index.ts
CHANGED
package/src/models.ts
CHANGED
|
@@ -19,7 +19,6 @@ declare module '@zhin.js/core' {
|
|
|
19
19
|
flags: string;
|
|
20
20
|
ending_id: string;
|
|
21
21
|
status: AdvSessionStatus;
|
|
22
|
-
board_message_id: string;
|
|
23
22
|
step_count: number;
|
|
24
23
|
updated_at: number;
|
|
25
24
|
created_at: number;
|
|
@@ -64,7 +63,6 @@ export function defineHostTables(
|
|
|
64
63
|
flags: { type: 'text', default: '{}' },
|
|
65
64
|
ending_id: { type: 'text', default: '' },
|
|
66
65
|
status: { type: 'text', default: 'active' },
|
|
67
|
-
board_message_id: { type: 'text', default: '' },
|
|
68
66
|
step_count: { type: 'integer', default: 0 },
|
|
69
67
|
updated_at: { type: 'integer', default: 0 },
|
|
70
68
|
created_at: { type: 'integer', default: 0 },
|
package/src/session-service.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Database, Models, RelatedModel } from '@zhin.js/core';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
BaseSessionService,
|
|
4
|
+
channelKey,
|
|
5
|
+
generateSessionId,
|
|
6
|
+
type GameMessageLike,
|
|
7
|
+
type GameSessionDatabase,
|
|
8
|
+
} from '@zhin.js/game-kit';
|
|
3
9
|
import type { AdvModelName, AdvSessionRow } from './models.js';
|
|
4
10
|
import { createProfileService, ProfileService } from './profile-service.js';
|
|
5
11
|
|
|
@@ -17,34 +23,13 @@ export interface GameServices {
|
|
|
17
23
|
profiles: ProfileService;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
export class SessionService {
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
status: 'active',
|
|
26
|
+
export class SessionService extends BaseSessionService<AdvSessionRow> {
|
|
27
|
+
constructor(db: AdvDatabase) {
|
|
28
|
+
super(db as unknown as GameSessionDatabase<AdvSessionRow>, {
|
|
29
|
+
gameId: 'adv',
|
|
30
|
+
table: 'adv_sessions',
|
|
31
|
+
userFields: ['player_id'],
|
|
27
32
|
});
|
|
28
|
-
return rows[0] ?? null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async getActiveForUser(channel: string, userId: string): Promise<AdvSessionRow | null> {
|
|
32
|
-
const row = await this.getActiveByChannel(channel);
|
|
33
|
-
if (!row || row.player_id !== userId) return null;
|
|
34
|
-
return row;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async getById(id: string): Promise<AdvSessionRow | null> {
|
|
38
|
-
return getModel(this.db, 'adv_sessions').findOne({ id });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async getActiveByBoardMessageId(messageId: string): Promise<AdvSessionRow | null> {
|
|
42
|
-
if (!messageId) return null;
|
|
43
|
-
const rows = await getModel(this.db, 'adv_sessions').findAll({});
|
|
44
|
-
for (const row of rows) {
|
|
45
|
-
if (boardMessageMatches(row.board_message_id ?? '', messageId)) return row;
|
|
46
|
-
}
|
|
47
|
-
return null;
|
|
48
33
|
}
|
|
49
34
|
|
|
50
35
|
async createSession(message: GameMessageLike): Promise<AdvSessionRow> {
|
|
@@ -65,34 +50,11 @@ export class SessionService {
|
|
|
65
50
|
flags: '{}',
|
|
66
51
|
ending_id: '',
|
|
67
52
|
status: 'active',
|
|
68
|
-
board_message_id: '',
|
|
69
53
|
step_count: 0,
|
|
70
54
|
updated_at: now,
|
|
71
55
|
created_at: now,
|
|
72
56
|
};
|
|
73
|
-
|
|
74
|
-
return row;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async updateSession(id: string, patch: Partial<AdvSessionRow>): Promise<void> {
|
|
78
|
-
await getModel(this.db, 'adv_sessions').updateWhere(
|
|
79
|
-
{ id },
|
|
80
|
-
{ ...patch, updated_at: Date.now() },
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async abortStale(idleMs: number): Promise<number> {
|
|
85
|
-
const cutoff = Date.now() - idleMs;
|
|
86
|
-
const sessions = getModel(this.db, 'adv_sessions');
|
|
87
|
-
const rows = await sessions.findAll({ status: 'active' });
|
|
88
|
-
let n = 0;
|
|
89
|
-
for (const row of rows) {
|
|
90
|
-
if (row.updated_at < cutoff) {
|
|
91
|
-
await sessions.updateWhere({ id: row.id }, { status: 'aborted', updated_at: Date.now() });
|
|
92
|
-
n++;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return n;
|
|
57
|
+
return this.createRow(row);
|
|
96
58
|
}
|
|
97
59
|
}
|
|
98
60
|
|
|
@@ -102,4 +64,3 @@ export function createServices(db: AdvDatabase): GameServices {
|
|
|
102
64
|
profiles: createProfileService(db),
|
|
103
65
|
};
|
|
104
66
|
}
|
|
105
|
-
|
package/lib/memory-db.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
2
|
-
import { type AdvDatabase, type GameServices } from './session-service.js';
|
|
3
|
-
/** In-memory adv tables for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
4
|
-
export declare function createInMemoryAdvDb(): AdvDatabase;
|
|
5
|
-
export declare function mountAdvMemoryServices(): GameServices;
|
|
6
|
-
export declare function mountAdvHostServices(host: DatabaseHost): GameServices;
|
package/lib/memory-db.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { createHostGameDb, createInMemoryGameDb } from '@zhin.js/game-kit';
|
|
2
|
-
import { defineHostTables } from './models.js';
|
|
3
|
-
import { createServices } from './session-service.js';
|
|
4
|
-
const ADV_TABLES = ['adv_sessions', 'adv_profiles'];
|
|
5
|
-
/** In-memory adv tables for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
6
|
-
export function createInMemoryAdvDb() {
|
|
7
|
-
return createInMemoryGameDb(ADV_TABLES);
|
|
8
|
-
}
|
|
9
|
-
export function mountAdvMemoryServices() {
|
|
10
|
-
const services = createServices(createInMemoryAdvDb());
|
|
11
|
-
return services;
|
|
12
|
-
}
|
|
13
|
-
export function mountAdvHostServices(host) {
|
|
14
|
-
defineHostTables(host);
|
|
15
|
-
const services = createServices(createHostGameDb(host, ADV_TABLES));
|
|
16
|
-
return services;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=memory-db.js.map
|
package/lib/memory-db.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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,EAAuC,MAAM,sBAAsB,CAAC;AAE3F,MAAM,UAAU,GAAG,CAAC,cAAc,EAAE,cAAc,CAAU,CAAC;AAE7D,4EAA4E;AAC5E,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/plugin.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
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 { mountAdvHostServices, mountAdvMemoryServices } from './src/memory-db.js';
|
|
9
|
-
import { gameServicesToken } from './src/runtime-store.js';
|
|
10
|
-
import type { GameServices } from './src/session-service.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Plugin Runtime:
|
|
14
|
-
* - Commands under `commands/` are authoritative (help + start/continue/…).
|
|
15
|
-
* - DB: prefer databaseHostToken; else in-memory GameServices.
|
|
16
|
-
* - Choice middleware under `middlewares/` handles adv choice payloads (Sandbox action→text).
|
|
17
|
-
*/
|
|
18
|
-
export default definePlugin({
|
|
19
|
-
name: 'text-adventure',
|
|
20
|
-
metadata: {
|
|
21
|
-
displayName: 'Text Adventure',
|
|
22
|
-
},
|
|
23
|
-
setup(context) {
|
|
24
|
-
let services: GameServices;
|
|
25
|
-
if (context.resources.has(databaseHostToken)) {
|
|
26
|
-
const host = context.resources.use(databaseHostToken);
|
|
27
|
-
services = mountAdvHostServices(host);
|
|
28
|
-
context.lifecycle.add(initGameRecordHost(host));
|
|
29
|
-
} else {
|
|
30
|
-
services = mountAdvMemoryServices();
|
|
31
|
-
}
|
|
32
|
-
context.resources.provide(gameServicesToken, services);
|
|
33
|
-
const disposeHub = registerRuntimeGame({
|
|
34
|
-
id: 'adv',
|
|
35
|
-
title: '秘境探险',
|
|
36
|
-
icon: '🗺️',
|
|
37
|
-
description: '文字冒险,31 区域 · 15 结局 · 成就收集',
|
|
38
|
-
commandPrefix: '/冒险',
|
|
39
|
-
quickStart: '开始',
|
|
40
|
-
aliases: ['adv', '秘境'],
|
|
41
|
-
menus: [
|
|
42
|
-
{ id: 'start', label: '🚪 开始冒险' },
|
|
43
|
-
{ id: 'continue', label: '🔄 继续冒险' },
|
|
44
|
-
{ id: 'map', label: '🗺️ 探索进度' },
|
|
45
|
-
{ id: 'achievements', label: '🏅 成就' },
|
|
46
|
-
{ id: 'help', label: '📖 玩法说明' },
|
|
47
|
-
],
|
|
48
|
-
});
|
|
49
|
-
context.lifecycle.add(disposeHub);
|
|
50
|
-
|
|
51
|
-
if (context.resources.has(scheduleHostToken)) {
|
|
52
|
-
const schedule = context.resources.use(scheduleHostToken);
|
|
53
|
-
const disposeCron = schedule.register({
|
|
54
|
-
id: 'adv/abort-stale',
|
|
55
|
-
cron: DEFAULT_GAME_STALE_CRON,
|
|
56
|
-
description: 'Abort stale text-adventure sessions',
|
|
57
|
-
async execute() {
|
|
58
|
-
if (!services.sessions.abortStale) return;
|
|
59
|
-
await services.sessions.abortStale(DEFAULT_GAME_STALE_IDLE_MS);
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
context.lifecycle.add(disposeCron);
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
});
|
package/src/memory-db.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createHostGameDb, createInMemoryGameDb } from '@zhin.js/game-kit';
|
|
2
|
-
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
3
|
-
import { defineHostTables } from './models.js';
|
|
4
|
-
import { createServices, type AdvDatabase, type GameServices } from './session-service.js';
|
|
5
|
-
|
|
6
|
-
const ADV_TABLES = ['adv_sessions', 'adv_profiles'] as const;
|
|
7
|
-
|
|
8
|
-
/** In-memory adv tables for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
9
|
-
export function createInMemoryAdvDb(): AdvDatabase {
|
|
10
|
-
return createInMemoryGameDb(ADV_TABLES) as unknown as AdvDatabase;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function mountAdvMemoryServices(): GameServices {
|
|
14
|
-
const services = createServices(createInMemoryAdvDb());
|
|
15
|
-
return services;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function mountAdvHostServices(host: DatabaseHost): GameServices {
|
|
19
|
-
defineHostTables(host);
|
|
20
|
-
const services = createServices(createHostGameDb(host, ADV_TABLES) as unknown as AdvDatabase);
|
|
21
|
-
return services;
|
|
22
|
-
}
|