@zhin.js/plugin-text-adventure 1.0.0
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/README.md +92 -0
- package/lib/achievements.d.ts +24 -0
- package/lib/achievements.d.ts.map +1 -0
- package/lib/achievements.js +62 -0
- package/lib/achievements.js.map +1 -0
- package/lib/adv-command.d.ts +5 -0
- package/lib/adv-command.d.ts.map +1 -0
- package/lib/adv-command.js +55 -0
- package/lib/adv-command.js.map +1 -0
- package/lib/commands.d.ts +6 -0
- package/lib/commands.d.ts.map +1 -0
- package/lib/commands.js +96 -0
- package/lib/commands.js.map +1 -0
- package/lib/game-flow.d.ts +9 -0
- package/lib/game-flow.d.ts.map +1 -0
- package/lib/game-flow.js +134 -0
- package/lib/game-flow.js.map +1 -0
- package/lib/hub-register.d.ts +5 -0
- package/lib/hub-register.d.ts.map +1 -0
- package/lib/hub-register.js +25 -0
- package/lib/hub-register.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +37 -0
- package/lib/index.js.map +1 -0
- package/lib/models.d.ts +45 -0
- package/lib/models.d.ts.map +1 -0
- package/lib/models.js +37 -0
- package/lib/models.js.map +1 -0
- package/lib/profile-format.d.ts +6 -0
- package/lib/profile-format.d.ts.map +1 -0
- package/lib/profile-format.js +64 -0
- package/lib/profile-format.js.map +1 -0
- package/lib/profile-parse.d.ts +4 -0
- package/lib/profile-parse.d.ts.map +1 -0
- package/lib/profile-parse.js +21 -0
- package/lib/profile-parse.js.map +1 -0
- package/lib/profile-service.d.ts +17 -0
- package/lib/profile-service.d.ts.map +1 -0
- package/lib/profile-service.js +124 -0
- package/lib/profile-service.js.map +1 -0
- package/lib/scene-view.d.ts +4 -0
- package/lib/scene-view.d.ts.map +1 -0
- package/lib/scene-view.js +32 -0
- package/lib/scene-view.js.map +1 -0
- package/lib/session-service.d.ts +22 -0
- package/lib/session-service.d.ts.map +1 -0
- package/lib/session-service.js +100 -0
- package/lib/session-service.js.map +1 -0
- package/lib/story-catalog.d.ts +13 -0
- package/lib/story-catalog.d.ts.map +1 -0
- package/lib/story-catalog.js +104 -0
- package/lib/story-catalog.js.map +1 -0
- package/lib/story-items.d.ts +5 -0
- package/lib/story-items.d.ts.map +1 -0
- package/lib/story-items.js +23 -0
- package/lib/story-items.js.map +1 -0
- package/lib/story-path.d.ts +3 -0
- package/lib/story-path.d.ts.map +1 -0
- package/lib/story-path.js +66 -0
- package/lib/story-path.js.map +1 -0
- package/lib/story-scenes.d.ts +9 -0
- package/lib/story-scenes.d.ts.map +1 -0
- package/lib/story-scenes.js +478 -0
- package/lib/story-scenes.js.map +1 -0
- package/lib/story-transitions.d.ts +3 -0
- package/lib/story-transitions.d.ts.map +1 -0
- package/lib/story-transitions.js +193 -0
- package/lib/story-transitions.js.map +1 -0
- package/lib/story-types.d.ts +30 -0
- package/lib/story-types.d.ts.map +1 -0
- package/lib/story-types.js +3 -0
- package/lib/story-types.js.map +1 -0
- package/lib/story.d.ts +21 -0
- package/lib/story.d.ts.map +1 -0
- package/lib/story.js +91 -0
- package/lib/story.js.map +1 -0
- package/package.json +54 -0
- package/plugin.yml +2 -0
- package/src/achievements.ts +90 -0
- package/src/adv-command.ts +72 -0
- package/src/commands.ts +133 -0
- package/src/game-flow.ts +196 -0
- package/src/hub-register.ts +32 -0
- package/src/index.ts +47 -0
- package/src/models.ts +84 -0
- package/src/profile-format.ts +76 -0
- package/src/profile-parse.ts +19 -0
- package/src/profile-service.ts +151 -0
- package/src/scene-view.ts +46 -0
- package/src/session-service.ts +113 -0
- package/src/story-catalog.ts +110 -0
- package/src/story-items.ts +24 -0
- package/src/story-path.ts +75 -0
- package/src/story-scenes.ts +508 -0
- package/src/story-transitions.ts +198 -0
- package/src/story-types.ts +33 -0
- package/src/story.ts +104 -0
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAwB,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,mBAAmB,GAEpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;AAC3B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;AAE/C,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvB,IAAI,QAAQ,GAAwB,IAAI,CAAC;AAEzC,UAAU,CAAC,UAAU,EAAE,CAAC,SAA0B,EAAE,EAAE;IACpD,QAAQ,GAAG,cAAc,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEH,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC/B,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AACzC,mBAAmB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC5C,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;AAE7C,OAAO,CACL,IAAI,IAAI,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;IACpC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC7D,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC"}
|
package/lib/models.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Models, Plugin } from 'zhin.js';
|
|
2
|
+
export type AdvSessionStatus = 'active' | 'completed' | 'aborted';
|
|
3
|
+
declare module 'zhin.js' {
|
|
4
|
+
interface Models {
|
|
5
|
+
adv_sessions: {
|
|
6
|
+
id: string;
|
|
7
|
+
adapter: string;
|
|
8
|
+
endpoint: string;
|
|
9
|
+
channel_type: string;
|
|
10
|
+
channel_id: string;
|
|
11
|
+
channel_key: string;
|
|
12
|
+
player_id: string;
|
|
13
|
+
player_name: string;
|
|
14
|
+
scene_id: string;
|
|
15
|
+
hp: number;
|
|
16
|
+
inventory: string;
|
|
17
|
+
flags: string;
|
|
18
|
+
ending_id: string;
|
|
19
|
+
status: AdvSessionStatus;
|
|
20
|
+
board_message_id: string;
|
|
21
|
+
step_count: number;
|
|
22
|
+
updated_at: number;
|
|
23
|
+
created_at: number;
|
|
24
|
+
};
|
|
25
|
+
adv_profiles: {
|
|
26
|
+
player_id: string;
|
|
27
|
+
player_name: string;
|
|
28
|
+
visited_scenes: string;
|
|
29
|
+
endings_seen: string;
|
|
30
|
+
items_found: string;
|
|
31
|
+
achievements: string;
|
|
32
|
+
runs_started: number;
|
|
33
|
+
runs_completed: number;
|
|
34
|
+
total_steps: number;
|
|
35
|
+
best_step_count: number;
|
|
36
|
+
updated_at: number;
|
|
37
|
+
created_at: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export type AdvSessionRow = Models['adv_sessions'];
|
|
42
|
+
export type AdvProfileRow = Models['adv_profiles'];
|
|
43
|
+
export type AdvModelName = 'adv_sessions' | 'adv_profiles';
|
|
44
|
+
export declare function registerModels(plugin: Plugin): void;
|
|
45
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;AAElE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM;QACd,YAAY,EAAE;YACZ,EAAE,EAAE,MAAM,CAAC;YACX,OAAO,EAAE,MAAM,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,EAAE,MAAM,CAAC;YACnB,WAAW,EAAE,MAAM,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;YACpB,QAAQ,EAAE,MAAM,CAAC;YACjB,EAAE,EAAE,MAAM,CAAC;YACX,SAAS,EAAE,MAAM,CAAC;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,EAAE,gBAAgB,CAAC;YACzB,gBAAgB,EAAE,MAAM,CAAC;YACzB,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,YAAY,EAAE;YACZ,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;YACpB,cAAc,EAAE,MAAM,CAAC;YACvB,YAAY,EAAE,MAAM,CAAC;YACrB,WAAW,EAAE,MAAM,CAAC;YACpB,YAAY,EAAE,MAAM,CAAC;YACrB,YAAY,EAAE,MAAM,CAAC;YACrB,cAAc,EAAE,MAAM,CAAC;YACvB,WAAW,EAAE,MAAM,CAAC;YACpB,eAAe,EAAE,MAAM,CAAC;YACxB,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH;CACF;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AACnD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;AAE3D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAoCnD"}
|
package/lib/models.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function registerModels(plugin) {
|
|
2
|
+
plugin.defineModel('adv_sessions', {
|
|
3
|
+
id: { type: 'text', primary: true },
|
|
4
|
+
adapter: { type: 'text', nullable: false },
|
|
5
|
+
endpoint: { type: 'text', nullable: false },
|
|
6
|
+
channel_type: { type: 'text', nullable: false },
|
|
7
|
+
channel_id: { type: 'text', nullable: false },
|
|
8
|
+
channel_key: { type: 'text', nullable: false },
|
|
9
|
+
player_id: { type: 'text', nullable: false },
|
|
10
|
+
player_name: { type: 'text', default: '' },
|
|
11
|
+
scene_id: { type: 'text', default: 'start' },
|
|
12
|
+
hp: { type: 'integer', default: 100 },
|
|
13
|
+
inventory: { type: 'text', default: '[]' },
|
|
14
|
+
flags: { type: 'text', default: '{}' },
|
|
15
|
+
ending_id: { type: 'text', default: '' },
|
|
16
|
+
status: { type: 'text', default: 'active' },
|
|
17
|
+
board_message_id: { type: 'text', default: '' },
|
|
18
|
+
step_count: { type: 'integer', default: 0 },
|
|
19
|
+
updated_at: { type: 'integer', default: 0 },
|
|
20
|
+
created_at: { type: 'integer', default: 0 },
|
|
21
|
+
});
|
|
22
|
+
plugin.defineModel('adv_profiles', {
|
|
23
|
+
player_id: { type: 'text', primary: true },
|
|
24
|
+
player_name: { type: 'text', default: '' },
|
|
25
|
+
visited_scenes: { type: 'text', default: '[]' },
|
|
26
|
+
endings_seen: { type: 'text', default: '[]' },
|
|
27
|
+
items_found: { type: 'text', default: '[]' },
|
|
28
|
+
achievements: { type: 'text', default: '[]' },
|
|
29
|
+
runs_started: { type: 'integer', default: 0 },
|
|
30
|
+
runs_completed: { type: 'integer', default: 0 },
|
|
31
|
+
total_steps: { type: 'integer', default: 0 },
|
|
32
|
+
best_step_count: { type: 'integer', default: 0 },
|
|
33
|
+
updated_at: { type: 'integer', default: 0 },
|
|
34
|
+
created_at: { type: 'integer', default: 0 },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AA+CA,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE;QACjC,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,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;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;KAC5C,CAAC,CAAC;IAEH,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE;QACjC,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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AdvProfileRow } from './models.js';
|
|
2
|
+
export declare function formatProgressCompact(profile: AdvProfileRow): string;
|
|
3
|
+
export declare function formatMapProgress(profile: AdvProfileRow): string;
|
|
4
|
+
export declare function formatAchievements(profile: AdvProfileRow, showHidden?: boolean): string;
|
|
5
|
+
export declare function formatNewAchievements(ids: string[]): string;
|
|
6
|
+
//# sourceMappingURL=profile-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-format.d.ts","sourceRoot":"","sources":["../src/profile-format.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAOpE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA4BhE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,UAAQ,GAAG,MAAM,CAerF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ3D"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { achievementById, ACHIEVEMENTS, totalAchievements } from './achievements.js';
|
|
2
|
+
import { endingIds, endingLabel, MAP_ZONES, playableSceneIds, regionLabel, } from './story-catalog.js';
|
|
3
|
+
import { parseStringSet } from './profile-parse.js';
|
|
4
|
+
export function formatProgressCompact(profile) {
|
|
5
|
+
const visited = parseStringSet(profile.visited_scenes).size;
|
|
6
|
+
const endings = parseStringSet(profile.endings_seen).size;
|
|
7
|
+
const achievements = parseStringSet(profile.achievements).size;
|
|
8
|
+
const totalRegions = playableSceneIds().length;
|
|
9
|
+
const totalEndings = endingIds().length;
|
|
10
|
+
return `🗺️ ${visited}/${totalRegions} · 🎬 ${endings}/${totalEndings} · 🏅 ${achievements}/${totalAchievements()}`;
|
|
11
|
+
}
|
|
12
|
+
export function formatMapProgress(profile) {
|
|
13
|
+
const visited = parseStringSet(profile.visited_scenes);
|
|
14
|
+
const total = playableSceneIds().length;
|
|
15
|
+
const pct = total ? Math.round((visited.size / total) * 100) : 0;
|
|
16
|
+
const lines = [
|
|
17
|
+
`🗺️ **探索进度** ${visited.size}/${total}(${pct}%)`,
|
|
18
|
+
'',
|
|
19
|
+
];
|
|
20
|
+
for (const zone of MAP_ZONES) {
|
|
21
|
+
const parts = zone.sceneIds.map((id) => {
|
|
22
|
+
const mark = visited.has(id) ? '✅' : '⬜';
|
|
23
|
+
return `${mark} ${regionLabel(id)}`;
|
|
24
|
+
});
|
|
25
|
+
lines.push(`**${zone.name}**`);
|
|
26
|
+
lines.push(parts.join(' '));
|
|
27
|
+
lines.push('');
|
|
28
|
+
}
|
|
29
|
+
const endings = parseStringSet(profile.endings_seen);
|
|
30
|
+
const allEndings = endingIds();
|
|
31
|
+
lines.push(`**结局图鉴** ${endings.size}/${allEndings.length}`);
|
|
32
|
+
lines.push(allEndings
|
|
33
|
+
.map((id) => `${endings.has(id) ? '✅' : '⬜'} ${endingLabel(id)}`)
|
|
34
|
+
.join(' '));
|
|
35
|
+
return lines.join('\n').trimEnd();
|
|
36
|
+
}
|
|
37
|
+
export function formatAchievements(profile, showHidden = false) {
|
|
38
|
+
const unlocked = parseStringSet(profile.achievements);
|
|
39
|
+
const lines = [
|
|
40
|
+
`🏅 **成就** ${unlocked.size}/${totalAchievements()}`,
|
|
41
|
+
`完成局数:${profile.runs_completed} · 生涯步数:${profile.total_steps}`,
|
|
42
|
+
'',
|
|
43
|
+
];
|
|
44
|
+
for (const def of ACHIEVEMENTS) {
|
|
45
|
+
const got = unlocked.has(def.id);
|
|
46
|
+
if (def.hidden && !got && !showHidden)
|
|
47
|
+
continue;
|
|
48
|
+
const mark = got ? '✅' : '⬜';
|
|
49
|
+
lines.push(`${mark} ${def.icon} **${def.title}** — ${def.description}`);
|
|
50
|
+
}
|
|
51
|
+
return lines.join('\n');
|
|
52
|
+
}
|
|
53
|
+
export function formatNewAchievements(ids) {
|
|
54
|
+
if (!ids.length)
|
|
55
|
+
return '';
|
|
56
|
+
const lines = ['', '🏅 **新成就解锁!**'];
|
|
57
|
+
for (const id of ids) {
|
|
58
|
+
const def = achievementById(id);
|
|
59
|
+
if (def)
|
|
60
|
+
lines.push(`${def.icon} ${def.title} — ${def.description}`);
|
|
61
|
+
}
|
|
62
|
+
return lines.join('\n');
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=profile-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-format.js","sourceRoot":"","sources":["../src/profile-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-parse.d.ts","sourceRoot":"","sources":["../src/profile-parse.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAa9E;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAE3D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 解析 DB 中的 JSON 字符串集合(兼容 SQLite 已自动 parse 的数组) */
|
|
2
|
+
export function parseStringSet(value) {
|
|
3
|
+
if (Array.isArray(value)) {
|
|
4
|
+
return new Set(value.filter((x) => typeof x === 'string'));
|
|
5
|
+
}
|
|
6
|
+
if (typeof value !== 'string' || !value)
|
|
7
|
+
return new Set();
|
|
8
|
+
try {
|
|
9
|
+
const v = JSON.parse(value);
|
|
10
|
+
return Array.isArray(v)
|
|
11
|
+
? new Set(v.filter((x) => typeof x === 'string'))
|
|
12
|
+
: new Set();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return new Set();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function serializeStringSet(set) {
|
|
19
|
+
return JSON.stringify([...set].sort());
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=profile-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-parse.js","sourceRoot":"","sources":["../src/profile-parse.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,KAAkC;IAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACrB,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YAC9D,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAgB;IACjD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AdvProfileRow } from './models.js';
|
|
2
|
+
import type { AdvDatabase } from './session-service.js';
|
|
3
|
+
export declare class ProfileService {
|
|
4
|
+
private readonly db;
|
|
5
|
+
constructor(db: AdvDatabase);
|
|
6
|
+
get(playerId: string): Promise<AdvProfileRow | null>;
|
|
7
|
+
getOrCreate(playerId: string, playerName: string): Promise<AdvProfileRow>;
|
|
8
|
+
patch(playerId: string, patch: Partial<AdvProfileRow>): Promise<void>;
|
|
9
|
+
onRunStarted(playerId: string, playerName: string): Promise<AdvProfileRow>;
|
|
10
|
+
/** 记录进入场景、步数、背包变化;返回新解锁成就 ID */
|
|
11
|
+
onStep(playerId: string, playerName: string, sceneId: string, inventory: string[]): Promise<string[]>;
|
|
12
|
+
/** 局终:记录结局、完成数、最佳步数 */
|
|
13
|
+
onRunCompleted(playerId: string, playerName: string, endingId: string, stepCount: number, inventory: string[]): Promise<string[]>;
|
|
14
|
+
private unlockPending;
|
|
15
|
+
}
|
|
16
|
+
export declare function createProfileService(db: AdvDatabase): ProfileService;
|
|
17
|
+
//# sourceMappingURL=profile-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-service.d.ts","sourceRoot":"","sources":["../src/profile-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAC;AAG/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAYxD,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAEtC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIpD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA4BzE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAMhF,gCAAgC;IAC1B,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC;IA2BpB,uBAAuB;IACjB,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC;YAkBN,aAAa;CAuB5B;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,WAAW,GAAG,cAAc,CAEpE"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { evaluateAchievements } from './achievements.js';
|
|
2
|
+
import { parseStringSet, serializeStringSet } from './profile-parse.js';
|
|
3
|
+
import { playableSceneIds } from './story-catalog.js';
|
|
4
|
+
const PLAYABLE = new Set(playableSceneIds());
|
|
5
|
+
function getModel(db, name) {
|
|
6
|
+
const model = db.models.get(name);
|
|
7
|
+
if (!model)
|
|
8
|
+
throw new Error(`Model ${name} is not registered`);
|
|
9
|
+
return model;
|
|
10
|
+
}
|
|
11
|
+
export class ProfileService {
|
|
12
|
+
db;
|
|
13
|
+
constructor(db) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
}
|
|
16
|
+
async get(playerId) {
|
|
17
|
+
return getModel(this.db, 'adv_profiles').findOne({ player_id: playerId });
|
|
18
|
+
}
|
|
19
|
+
async getOrCreate(playerId, playerName) {
|
|
20
|
+
const existing = await this.get(playerId);
|
|
21
|
+
if (existing) {
|
|
22
|
+
if (playerName && existing.player_name !== playerName) {
|
|
23
|
+
await this.patch(playerId, { player_name: playerName });
|
|
24
|
+
return (await this.get(playerId));
|
|
25
|
+
}
|
|
26
|
+
return existing;
|
|
27
|
+
}
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const row = {
|
|
30
|
+
player_id: playerId,
|
|
31
|
+
player_name: playerName || playerId,
|
|
32
|
+
visited_scenes: '[]',
|
|
33
|
+
endings_seen: '[]',
|
|
34
|
+
items_found: '[]',
|
|
35
|
+
achievements: '[]',
|
|
36
|
+
runs_started: 0,
|
|
37
|
+
runs_completed: 0,
|
|
38
|
+
total_steps: 0,
|
|
39
|
+
best_step_count: 0,
|
|
40
|
+
updated_at: now,
|
|
41
|
+
created_at: now,
|
|
42
|
+
};
|
|
43
|
+
await getModel(this.db, 'adv_profiles').create(row);
|
|
44
|
+
return row;
|
|
45
|
+
}
|
|
46
|
+
async patch(playerId, patch) {
|
|
47
|
+
await getModel(this.db, 'adv_profiles').updateWhere({ player_id: playerId }, { ...patch, updated_at: Date.now() });
|
|
48
|
+
}
|
|
49
|
+
async onRunStarted(playerId, playerName) {
|
|
50
|
+
const profile = await this.getOrCreate(playerId, playerName);
|
|
51
|
+
await this.patch(playerId, { runs_started: profile.runs_started + 1 });
|
|
52
|
+
return (await this.get(playerId));
|
|
53
|
+
}
|
|
54
|
+
/** 记录进入场景、步数、背包变化;返回新解锁成就 ID */
|
|
55
|
+
async onStep(playerId, playerName, sceneId, inventory) {
|
|
56
|
+
const profile = await this.getOrCreate(playerId, playerName);
|
|
57
|
+
const visited = parseStringSet(profile.visited_scenes);
|
|
58
|
+
const items = parseStringSet(profile.items_found);
|
|
59
|
+
let changed = false;
|
|
60
|
+
if (PLAYABLE.has(sceneId) && !visited.has(sceneId)) {
|
|
61
|
+
visited.add(sceneId);
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
for (const item of inventory) {
|
|
65
|
+
if (!items.has(item)) {
|
|
66
|
+
items.add(item);
|
|
67
|
+
changed = true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const patch = {
|
|
71
|
+
total_steps: profile.total_steps + 1,
|
|
72
|
+
};
|
|
73
|
+
if (changed) {
|
|
74
|
+
patch.visited_scenes = serializeStringSet(visited);
|
|
75
|
+
patch.items_found = serializeStringSet(items);
|
|
76
|
+
}
|
|
77
|
+
await this.patch(playerId, patch);
|
|
78
|
+
const updated = (await this.get(playerId));
|
|
79
|
+
return this.unlockPending(updated);
|
|
80
|
+
}
|
|
81
|
+
/** 局终:记录结局、完成数、最佳步数 */
|
|
82
|
+
async onRunCompleted(playerId, playerName, endingId, stepCount, inventory) {
|
|
83
|
+
const profile = await this.getOrCreate(playerId, playerName);
|
|
84
|
+
const endings = parseStringSet(profile.endings_seen);
|
|
85
|
+
const items = parseStringSet(profile.items_found);
|
|
86
|
+
if (endingId)
|
|
87
|
+
endings.add(endingId);
|
|
88
|
+
for (const item of inventory)
|
|
89
|
+
items.add(item);
|
|
90
|
+
await this.patch(playerId, {
|
|
91
|
+
endings_seen: serializeStringSet(endings),
|
|
92
|
+
items_found: serializeStringSet(items),
|
|
93
|
+
runs_completed: profile.runs_completed + 1,
|
|
94
|
+
best_step_count: Math.max(profile.best_step_count, stepCount),
|
|
95
|
+
});
|
|
96
|
+
const updated = (await this.get(playerId));
|
|
97
|
+
return this.unlockPending(updated, { stepCount, inventory, endingId });
|
|
98
|
+
}
|
|
99
|
+
async unlockPending(profile, lastRun) {
|
|
100
|
+
const ctx = {
|
|
101
|
+
visited: parseStringSet(profile.visited_scenes),
|
|
102
|
+
endings: parseStringSet(profile.endings_seen),
|
|
103
|
+
itemsFound: parseStringSet(profile.items_found),
|
|
104
|
+
runsCompleted: profile.runs_completed,
|
|
105
|
+
bestStepCount: profile.best_step_count,
|
|
106
|
+
lastRun,
|
|
107
|
+
};
|
|
108
|
+
const current = [...parseStringSet(profile.achievements)];
|
|
109
|
+
const newly = evaluateAchievements(current, ctx);
|
|
110
|
+
if (!newly.length)
|
|
111
|
+
return [];
|
|
112
|
+
const merged = new Set(current);
|
|
113
|
+
for (const id of newly)
|
|
114
|
+
merged.add(id);
|
|
115
|
+
await this.patch(profile.player_id, {
|
|
116
|
+
achievements: serializeStringSet(merged),
|
|
117
|
+
});
|
|
118
|
+
return newly;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export function createProfileService(db) {
|
|
122
|
+
return new ProfileService(db);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=profile-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-service.js","sourceRoot":"","sources":["../src/profile-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SendContent } from 'zhin.js';
|
|
2
|
+
import type { AdvProfileRow, AdvSessionRow } from './models.js';
|
|
3
|
+
export declare function buildSceneInteractive(session: AdvSessionRow, extraNarrative?: string, profile?: AdvProfileRow): SendContent | null;
|
|
4
|
+
//# sourceMappingURL=scene-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-view.d.ts","sourceRoot":"","sources":["../src/scene-view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAUhE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,cAAc,SAAK,EACnB,OAAO,CAAC,EAAE,aAAa,GACtB,WAAW,GAAG,IAAI,CA6BpB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { buildChoiceKeyboard } from '@zhin.js/game-shared';
|
|
2
|
+
import { formatProgressCompact } from './profile-format.js';
|
|
3
|
+
import { ADV_PREFIX, getScene, sceneNarrative, stateFromSession, visibleChoices, } from './story.js';
|
|
4
|
+
export function buildSceneInteractive(session, extraNarrative = '', profile) {
|
|
5
|
+
const scene = getScene(session.scene_id);
|
|
6
|
+
if (!scene)
|
|
7
|
+
return null;
|
|
8
|
+
const state = stateFromSession(session);
|
|
9
|
+
const choices = visibleChoices(scene, state);
|
|
10
|
+
const terminal = scene.terminal || session.status !== 'active';
|
|
11
|
+
let narrative = sceneNarrative(scene, state);
|
|
12
|
+
if (profile && !terminal) {
|
|
13
|
+
narrative = `${formatProgressCompact(profile)}\n\n${narrative}`;
|
|
14
|
+
}
|
|
15
|
+
if (extraNarrative) {
|
|
16
|
+
narrative += extraNarrative;
|
|
17
|
+
}
|
|
18
|
+
return buildChoiceKeyboard({
|
|
19
|
+
gamePrefix: ADV_PREFIX,
|
|
20
|
+
sessionId: session.id,
|
|
21
|
+
narrative,
|
|
22
|
+
choices: choices.map((c) => ({
|
|
23
|
+
id: c.id,
|
|
24
|
+
label: c.label,
|
|
25
|
+
style: c.style,
|
|
26
|
+
})),
|
|
27
|
+
terminal,
|
|
28
|
+
buttonsPerRow: 2,
|
|
29
|
+
fallbackHint: '回复数字选择(仅编号)',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=scene-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-view.js","sourceRoot":"","sources":["../src/scene-view.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,MAAM,UAAU,qBAAqB,CACnC,OAAsB,EACtB,cAAc,GAAG,EAAE,EACnB,OAAuB;IAEvB,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC;IAE/D,IAAI,SAAS,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7C,IAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,SAAS,GAAG,GAAG,qBAAqB,CAAC,OAAO,CAAC,OAAO,SAAS,EAAE,CAAC;IAClE,CAAC;IACD,IAAI,cAAc,EAAE,CAAC;QACnB,SAAS,IAAI,cAAc,CAAC;IAC9B,CAAC;IAED,OAAO,mBAAmB,CAAC;QACzB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,SAAS;QACT,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC;QACH,QAAQ;QACR,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,aAAa;KAC5B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Database, DatabaseFeature, Message, Models } from 'zhin.js';
|
|
2
|
+
import type { AdvSessionRow } from './models.js';
|
|
3
|
+
import { ProfileService } from './profile-service.js';
|
|
4
|
+
export type AdvDatabase = Database<unknown, Models, string>;
|
|
5
|
+
export interface GameServices {
|
|
6
|
+
sessions: SessionService;
|
|
7
|
+
profiles: ProfileService;
|
|
8
|
+
}
|
|
9
|
+
export declare class SessionService {
|
|
10
|
+
private readonly db;
|
|
11
|
+
constructor(db: AdvDatabase);
|
|
12
|
+
getActiveByChannel(channel: string): Promise<AdvSessionRow | null>;
|
|
13
|
+
getActiveForUser(channel: string, userId: string): Promise<AdvSessionRow | null>;
|
|
14
|
+
getById(id: string): Promise<AdvSessionRow | null>;
|
|
15
|
+
getActiveByBoardMessageId(messageId: string): Promise<AdvSessionRow | null>;
|
|
16
|
+
createSession(message: Message<any>): Promise<AdvSessionRow>;
|
|
17
|
+
updateSession(id: string, patch: Partial<AdvSessionRow>): Promise<void>;
|
|
18
|
+
abortStale(idleMs: number): Promise<number>;
|
|
19
|
+
}
|
|
20
|
+
export declare function createServices(db: AdvDatabase): GameServices;
|
|
21
|
+
export declare function resolveGameDatabase(feature: DatabaseFeature): AdvDatabase;
|
|
22
|
+
//# sourceMappingURL=session-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.d.ts","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAgB,MAAM,SAAS,CAAC;AAExF,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAwB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE5E,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAS5D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAEtC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAQlE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAMhF,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIlD,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAc3E,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IA2B5D,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAalD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,WAAW,GAAG,YAAY,CAK5D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAEzE"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { channelKey, generateSessionId } from '@zhin.js/game-shared';
|
|
2
|
+
import { createProfileService } from './profile-service.js';
|
|
3
|
+
function getModel(db, name) {
|
|
4
|
+
const model = db.models.get(name);
|
|
5
|
+
if (!model)
|
|
6
|
+
throw new Error(`Model ${name} is not registered`);
|
|
7
|
+
return model;
|
|
8
|
+
}
|
|
9
|
+
export class SessionService {
|
|
10
|
+
db;
|
|
11
|
+
constructor(db) {
|
|
12
|
+
this.db = db;
|
|
13
|
+
}
|
|
14
|
+
async getActiveByChannel(channel) {
|
|
15
|
+
const rows = await getModel(this.db, 'adv_sessions').findAll({
|
|
16
|
+
channel_key: channel,
|
|
17
|
+
status: 'active',
|
|
18
|
+
});
|
|
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({ status: 'active' });
|
|
34
|
+
for (const row of rows) {
|
|
35
|
+
const stored = row.board_message_id;
|
|
36
|
+
if (!stored)
|
|
37
|
+
continue;
|
|
38
|
+
if (stored === messageId)
|
|
39
|
+
return row;
|
|
40
|
+
if (stored.endsWith(`:${messageId}`))
|
|
41
|
+
return row;
|
|
42
|
+
const tail = stored.split(':').pop();
|
|
43
|
+
if (tail && messageId.endsWith(tail))
|
|
44
|
+
return row;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
async createSession(message) {
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const id = generateSessionId();
|
|
51
|
+
const row = {
|
|
52
|
+
id,
|
|
53
|
+
adapter: String(message.$adapter),
|
|
54
|
+
endpoint: message.$endpoint,
|
|
55
|
+
channel_type: message.$channel.type,
|
|
56
|
+
channel_id: message.$channel.id,
|
|
57
|
+
channel_key: channelKey(message),
|
|
58
|
+
player_id: message.$sender.id,
|
|
59
|
+
player_name: message.$sender.name?.trim() || message.$sender.id,
|
|
60
|
+
scene_id: 'start',
|
|
61
|
+
hp: 100,
|
|
62
|
+
inventory: '[]',
|
|
63
|
+
flags: '{}',
|
|
64
|
+
ending_id: '',
|
|
65
|
+
status: 'active',
|
|
66
|
+
board_message_id: '',
|
|
67
|
+
step_count: 0,
|
|
68
|
+
updated_at: now,
|
|
69
|
+
created_at: now,
|
|
70
|
+
};
|
|
71
|
+
await getModel(this.db, 'adv_sessions').create(row);
|
|
72
|
+
return row;
|
|
73
|
+
}
|
|
74
|
+
async updateSession(id, patch) {
|
|
75
|
+
await getModel(this.db, 'adv_sessions').updateWhere({ id }, { ...patch, updated_at: Date.now() });
|
|
76
|
+
}
|
|
77
|
+
async abortStale(idleMs) {
|
|
78
|
+
const cutoff = Date.now() - idleMs;
|
|
79
|
+
const sessions = getModel(this.db, 'adv_sessions');
|
|
80
|
+
const rows = await sessions.findAll({ status: 'active' });
|
|
81
|
+
let n = 0;
|
|
82
|
+
for (const row of rows) {
|
|
83
|
+
if (row.updated_at < cutoff) {
|
|
84
|
+
await sessions.updateWhere({ id: row.id }, { status: 'aborted', updated_at: Date.now() });
|
|
85
|
+
n++;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return n;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function createServices(db) {
|
|
92
|
+
return {
|
|
93
|
+
sessions: new SessionService(db),
|
|
94
|
+
profiles: createProfileService(db),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export function resolveGameDatabase(feature) {
|
|
98
|
+
return feature.db;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=session-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 区域中文名(用于地图 / 成就展示) */
|
|
2
|
+
export declare const REGION_LABELS: Record<string, string>;
|
|
3
|
+
export declare const ENDING_LABELS: Record<string, string>;
|
|
4
|
+
/** 地图分区(便于 adv map 分组展示) */
|
|
5
|
+
export declare const MAP_ZONES: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
sceneIds: string[];
|
|
8
|
+
}>;
|
|
9
|
+
export declare function playableSceneIds(): string[];
|
|
10
|
+
export declare function endingIds(): string[];
|
|
11
|
+
export declare function regionLabel(id: string): string;
|
|
12
|
+
export declare function endingLabel(id: string): string;
|
|
13
|
+
//# sourceMappingURL=story-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story-catalog.d.ts","sourceRoot":"","sources":["../src/story-catalog.ts"],"names":[],"mappings":"AAEA,yBAAyB;AACzB,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgChD,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBhD,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAiCjE,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAI3C;AAED,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAIpC;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|