@zhin.js/plugin-game-hub 1.1.14 → 1.1.16

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.
@@ -1,19 +1,27 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import { gameFeatureId } from '@zhin.js/game-kit';
4
+ import { createMessages } from 'zhin.js/i18n';
5
+ const messages = createMessages({
6
+ start: { 'zh-CN': '发送 `{command}` 开始 {title}', en: 'Send `{command}` to start {title}' },
7
+ });
4
8
  export default defineCommand({
5
9
  description: 'Game hub — list loaded games',
6
10
  params: { action: { type: 'string', default: '' } },
7
- async execute({ params, project }) {
11
+ async execute({ params, project, locale, formatCommand }) {
8
12
  const games = project(gameFeatureId);
9
13
  const action = String(params.action ?? '').trim();
10
14
  if (action) {
11
15
  const game = games.get(action);
12
16
  if (game) {
13
- const start = game.quickStart ? ` ${game.quickStart}` : '';
14
- return `发送 \`${game.commandPrefix}${start}\` 开始 ${game.title}`;
17
+ const command = games.formatCommand(game.id, formatCommand);
18
+ const quickStart = game.quickStartI18n?.[locale] ?? game.quickStart;
19
+ const start = quickStart ? ` ${quickStart}` : '';
20
+ if (command)
21
+ return messages(locale, 'start', { command: command + start,
22
+ title: game.titleI18n?.[locale] ?? game.title });
15
23
  }
16
24
  }
17
- return games.formatHelp();
25
+ return games.formatHelp(locale, formatCommand);
18
26
  },
19
27
  });
@@ -1,19 +1,27 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import { gameFeatureId, type GameIndex } from '@zhin.js/game-kit';
3
+ import { createMessages } from 'zhin.js/i18n';
4
+
5
+ const messages = createMessages({
6
+ start: { 'zh-CN': '发送 `{command}` 开始 {title}', en: 'Send `{command}` to start {title}' },
7
+ });
3
8
 
4
9
  export default defineCommand({
5
10
  description: 'Game hub — list loaded games',
6
11
  params: { action: { type: 'string', default: '' } },
7
- async execute({ params, project }) {
12
+ async execute({ params, project, locale, formatCommand }) {
8
13
  const games = project<GameIndex>(gameFeatureId);
9
14
  const action = String(params.action ?? '').trim();
10
15
  if (action) {
11
16
  const game = games.get(action);
12
17
  if (game) {
13
- const start = game.quickStart ? ` ${game.quickStart}` : '';
14
- return `发送 \`${game.commandPrefix}${start}\` 开始 ${game.title}`;
18
+ const command = games.formatCommand(game.id, formatCommand);
19
+ const quickStart = game.quickStartI18n?.[locale] ?? game.quickStart;
20
+ const start = quickStart ? ` ${quickStart}` : '';
21
+ if (command) return messages(locale, 'start', { command: command + start,
22
+ title: game.titleI18n?.[locale] ?? game.title });
15
23
  }
16
24
  }
17
- return games.formatHelp();
25
+ return games.formatHelp(locale, formatCommand);
18
26
  },
19
27
  });
@@ -1,22 +1,32 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { createMessages } from 'zhin.js/i18n';
2
3
  import { defineCommand } from 'zhin.js/command';
3
4
  import { channelKey, gameFeatureId, messageFromCommandInput, } from '@zhin.js/game-kit';
4
- function formatStats(index, stats) {
5
+ function formatStats(index, stats, locale, menu) {
5
6
  if (!stats.length)
6
- return '暂无战绩记录,快去 `/游戏` 开一局吧!';
7
+ return messages(locale, 'empty') + (menu ? messages(locale, 'menu', { command: menu }) : '');
7
8
  const lines = stats.map((s) => {
8
9
  const g = index.get(s.gameId);
9
- const title = g ? `${g.icon} ${g.title}` : s.gameId;
10
- return `• ${title}:${s.wins} 胜 ${s.losses} 负${s.draws ? ` ${s.draws} 平` : ''}(${s.games} 局,得分 ${s.totalScore})`;
10
+ const title = g ? `${g.icon} ${g.titleI18n?.[locale] ?? g.title}` : s.gameId;
11
+ return messages(locale, 'record', { title, wins: s.wins, losses: s.losses, draws: s.draws ? messages(locale, 'draws', { count: s.draws }) : '', games: s.games, score: s.totalScore });
11
12
  });
12
- return ['📊 **你的战绩**', '', ...lines].join('\n');
13
+ return [messages(locale, 'title'), '', ...lines].join('\n');
13
14
  }
14
15
  export default defineCommand({
15
- description: '查看本人在本群的游戏战绩',
16
- async execute({ input, project }) {
16
+ alias: ['game-stats'],
17
+ preferredAliasI18n: { en: 'game-stats' },
18
+ description: '查看本人在本群的游戏战绩', descriptionI18n: { en: "View your game statistics in this group" },
19
+ async execute({ input, project, locale, formatCommand }) {
17
20
  const index = project(gameFeatureId);
18
- const message = messageFromCommandInput(input);
21
+ const message = messageFromCommandInput(input, { locale, formatCommand });
19
22
  const stats = await index.getUserStats(message.$sender.id, channelKey(message));
20
- return formatStats(index, stats);
23
+ return formatStats(index, stats, locale, formatCommand?.('games'));
21
24
  },
22
25
  });
26
+ const messages = createMessages({
27
+ empty: { 'zh-CN': '暂无战绩记录。', en: 'No game statistics yet.' },
28
+ menu: { 'zh-CN': '发送 `{command}` 查看游戏。', en: ' Send `{command}` to browse games.' },
29
+ title: { 'zh-CN': '📊 **你的战绩**', en: '📊 **Your statistics**' },
30
+ draws: { 'zh-CN': ' {count} 平', en: ' {count} draws' },
31
+ record: { 'zh-CN': '• {title}:{wins} 胜 {losses} 负{draws}({games} 局,得分 {score})', en: '• {title}: {wins} wins, {losses} losses{draws} ({games} games, score {score})' },
32
+ });
@@ -1,3 +1,4 @@
1
+ import { createMessages, type Locale } from 'zhin.js/i18n';
1
2
  import { defineCommand } from 'zhin.js/command';
2
3
  import {
3
4
  channelKey,
@@ -7,22 +8,32 @@ import {
7
8
  type UserGameStats,
8
9
  } from '@zhin.js/game-kit';
9
10
 
10
- function formatStats(index: GameIndex, stats: UserGameStats[]): string {
11
- if (!stats.length) return '暂无战绩记录,快去 `/游戏` 开一局吧!';
11
+ function formatStats(index: GameIndex, stats: UserGameStats[], locale: Locale, menu?: string): string {
12
+ if (!stats.length) return messages(locale, 'empty') + (menu ? messages(locale, 'menu', { command: menu }) : '');
12
13
  const lines = stats.map((s) => {
13
14
  const g = index.get(s.gameId);
14
- const title = g ? `${g.icon} ${g.title}` : s.gameId;
15
- return `• ${title}:${s.wins} 胜 ${s.losses} 负${s.draws ? ` ${s.draws} 平` : ''}(${s.games} 局,得分 ${s.totalScore})`;
15
+ const title = g ? `${g.icon} ${g.titleI18n?.[locale] ?? g.title}` : s.gameId;
16
+ return messages(locale, 'record', { title, wins: s.wins, losses: s.losses, draws: s.draws ? messages(locale, 'draws', { count: s.draws }) : '', games: s.games, score: s.totalScore });
16
17
  });
17
- return ['📊 **你的战绩**', '', ...lines].join('\n');
18
+ return [messages(locale, 'title'), '', ...lines].join('\n');
18
19
  }
19
20
 
20
21
  export default defineCommand({
21
- description: '查看本人在本群的游戏战绩',
22
- async execute({ input, project }) {
22
+ alias: ['game-stats'],
23
+ preferredAliasI18n: { en: 'game-stats' },
24
+ description: '查看本人在本群的游戏战绩', descriptionI18n: { en: "View your game statistics in this group" },
25
+ async execute({ input, project, locale, formatCommand }) {
23
26
  const index = project<GameIndex>(gameFeatureId);
24
- const message = messageFromCommandInput(input);
27
+ const message = messageFromCommandInput(input, { locale, formatCommand });
25
28
  const stats = await index.getUserStats(message.$sender.id, channelKey(message));
26
- return formatStats(index, stats);
29
+ return formatStats(index, stats, locale, formatCommand?.('games'));
27
30
  },
28
31
  });
32
+
33
+ const messages = createMessages({
34
+ empty: { 'zh-CN': '暂无战绩记录。', en: 'No game statistics yet.' },
35
+ menu: { 'zh-CN': '发送 `{command}` 查看游戏。', en: ' Send `{command}` to browse games.' },
36
+ title: { 'zh-CN': '📊 **你的战绩**', en: '📊 **Your statistics**' },
37
+ draws: { 'zh-CN': ' {count} 平', en: ' {count} draws' },
38
+ record: { 'zh-CN': '• {title}:{wins} 胜 {losses} 负{draws}({games} 局,得分 {score})', en: '• {title}: {wins} wins, {losses} losses{draws} ({games} games, score {score})' },
39
+ });
@@ -1,41 +1,52 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { createMessages } from 'zhin.js/i18n';
2
3
  import { defineCommand } from 'zhin.js/command';
3
4
  import { channelKey, gameFeatureId, messageFromCommandInput, } from '@zhin.js/game-kit';
4
- function formatLeaderboard(index, gameId, entries) {
5
+ function formatLeaderboard(index, gameId, entries, locale, menu) {
5
6
  const g = index.get(gameId);
6
- const title = g ? `${g.icon} ${g.title}` : gameId;
7
+ const title = g ? `${g.icon} ${g.titleI18n?.[locale] ?? g.title}` : gameId;
7
8
  if (!entries.length) {
8
- return `${title} 在本群暂无排行,发送 \`/游戏\` 开始第一局!`;
9
+ return messages(locale, 'empty', { title }) + (menu ? messages(locale, 'menu', { command: menu }) : '');
9
10
  }
10
- const lines = entries.map((e, i) => `${i + 1}. ${e.userName} — ${e.wins} 胜 / ${e.games} 局(得分 ${e.totalScore})`);
11
- return [`🏆 **${title} 本群排行**`, '', ...lines].join('\n');
11
+ const lines = entries.map((e, i) => messages(locale, 'entry', { rank: i + 1, name: e.userName, wins: e.wins, games: e.games, score: e.totalScore }));
12
+ return [messages(locale, 'title', { title }), '', ...lines].join('\n');
12
13
  }
13
14
  export default defineCommand({
14
- description: '查看本群某游戏排行榜',
15
+ alias: ['game-ranking'],
16
+ preferredAliasI18n: { en: 'game-ranking' },
17
+ description: '查看本群某游戏排行榜', descriptionI18n: { en: "View this group's leaderboard for a game" },
15
18
  params: { query: { type: 'string', default: '' } },
16
- async execute({ input, params, project }) {
19
+ async execute({ input, params, project, locale, formatCommand }) {
17
20
  const index = project(gameFeatureId);
18
21
  const query = String(params.query ?? '').trim();
19
22
  const games = index.list();
20
23
  if (!games.length)
21
- return '暂无已注册游戏。';
24
+ return messages(locale, 'noGames');
22
25
  const firstGame = games[0];
23
26
  if (!firstGame)
24
- return '暂无已注册游戏。';
27
+ return messages(locale, 'noGames');
25
28
  let gameId = firstGame.id;
26
29
  if (query) {
27
30
  const hit = games.find((g) => g.id === query
28
- || g.title.includes(query)
31
+ || (g.titleI18n?.[locale] ?? g.title).includes(query)
29
32
  || g.commandPrefix.includes(query)
30
33
  || g.aliases?.some((a) => a.includes(query)));
31
34
  if (!hit) {
32
- const names = games.map((g) => g.title).join('、');
33
- return `未找到游戏「${query}」。可选:${names}`;
35
+ const names = games.map((g) => g.titleI18n?.[locale] ?? g.title).join(locale === 'en' ? ', ' : '、');
36
+ return messages(locale, 'missing', { query, names });
34
37
  }
35
38
  gameId = hit.id;
36
39
  }
37
- const message = messageFromCommandInput(input);
40
+ const message = messageFromCommandInput(input, { locale, formatCommand });
38
41
  const board = await index.getLeaderboard(gameId, channelKey(message));
39
- return formatLeaderboard(index, gameId, board);
42
+ return formatLeaderboard(index, gameId, board, locale, formatCommand?.('games'));
40
43
  },
41
44
  });
45
+ const messages = createMessages({
46
+ empty: { 'zh-CN': '{title} 在本群暂无排行。', en: 'No {title} leaderboard in this group yet.' },
47
+ menu: { 'zh-CN': '发送 `{command}` 查看游戏。', en: ' Send `{command}` to browse games.' },
48
+ entry: { 'zh-CN': '{rank}. {name} — {wins} 胜 / {games} 局(得分 {score})', en: '{rank}. {name} — {wins} wins / {games} games (score {score})' },
49
+ title: { 'zh-CN': '🏆 **{title} 本群排行**', en: '🏆 **{title} group leaderboard**' },
50
+ noGames: { 'zh-CN': '暂无已注册游戏。', en: 'No games are registered.' },
51
+ missing: { 'zh-CN': '未找到游戏「{query}」。可选:{names}', en: 'Game “{query}” was not found. Available: {names}' },
52
+ });
@@ -1,3 +1,4 @@
1
+ import { createMessages, type Locale } from 'zhin.js/i18n';
1
2
  import { defineCommand } from 'zhin.js/command';
2
3
  import {
3
4
  channelKey,
@@ -7,44 +8,55 @@ import {
7
8
  type GameIndex,
8
9
  } from '@zhin.js/game-kit';
9
10
 
10
- function formatLeaderboard(index: GameIndex, gameId: string, entries: LeaderboardEntry[]): string {
11
+ function formatLeaderboard(index: GameIndex, gameId: string, entries: LeaderboardEntry[], locale: Locale, menu?: string): string {
11
12
  const g = index.get(gameId);
12
- const title = g ? `${g.icon} ${g.title}` : gameId;
13
+ const title = g ? `${g.icon} ${g.titleI18n?.[locale] ?? g.title}` : gameId;
13
14
  if (!entries.length) {
14
- return `${title} 在本群暂无排行,发送 \`/游戏\` 开始第一局!`;
15
+ return messages(locale, 'empty', { title }) + (menu ? messages(locale, 'menu', { command: menu }) : '');
15
16
  }
16
17
  const lines = entries.map((e, i) =>
17
- `${i + 1}. ${e.userName} — ${e.wins} 胜 / ${e.games} 局(得分 ${e.totalScore})`,
18
+ messages(locale, 'entry', { rank: i + 1, name: e.userName, wins: e.wins, games: e.games, score: e.totalScore }),
18
19
  );
19
- return [`🏆 **${title} 本群排行**`, '', ...lines].join('\n');
20
+ return [messages(locale, 'title', { title }), '', ...lines].join('\n');
20
21
  }
21
22
 
22
23
  export default defineCommand({
23
- description: '查看本群某游戏排行榜',
24
+ alias: ['game-ranking'],
25
+ preferredAliasI18n: { en: 'game-ranking' },
26
+ description: '查看本群某游戏排行榜', descriptionI18n: { en: "View this group's leaderboard for a game" },
24
27
  params: { query: { type: 'string', default: '' } },
25
- async execute({ input, params, project }) {
28
+ async execute({ input, params, project, locale, formatCommand }) {
26
29
  const index = project<GameIndex>(gameFeatureId);
27
30
  const query = String(params.query ?? '').trim();
28
31
  const games = index.list();
29
- if (!games.length) return '暂无已注册游戏。';
32
+ if (!games.length) return messages(locale, 'noGames');
30
33
  const firstGame = games[0];
31
- if (!firstGame) return '暂无已注册游戏。';
34
+ if (!firstGame) return messages(locale, 'noGames');
32
35
  let gameId = firstGame.id;
33
36
  if (query) {
34
37
  const hit = games.find(
35
38
  (g) => g.id === query
36
- || g.title.includes(query)
39
+ || (g.titleI18n?.[locale] ?? g.title).includes(query)
37
40
  || g.commandPrefix.includes(query)
38
41
  || g.aliases?.some((a) => a.includes(query)),
39
42
  );
40
43
  if (!hit) {
41
- const names = games.map((g) => g.title).join('、');
42
- return `未找到游戏「${query}」。可选:${names}`;
44
+ const names = games.map((g) => g.titleI18n?.[locale] ?? g.title).join(locale === 'en' ? ', ' : '、');
45
+ return messages(locale, 'missing', { query, names });
43
46
  }
44
47
  gameId = hit.id;
45
48
  }
46
- const message = messageFromCommandInput(input);
49
+ const message = messageFromCommandInput(input, { locale, formatCommand });
47
50
  const board = await index.getLeaderboard(gameId, channelKey(message));
48
- return formatLeaderboard(index, gameId, board);
51
+ return formatLeaderboard(index, gameId, board, locale, formatCommand?.('games'));
49
52
  },
50
53
  });
54
+
55
+ const messages = createMessages({
56
+ empty: { 'zh-CN': '{title} 在本群暂无排行。', en: 'No {title} leaderboard in this group yet.' },
57
+ menu: { 'zh-CN': '发送 `{command}` 查看游戏。', en: ' Send `{command}` to browse games.' },
58
+ entry: { 'zh-CN': '{rank}. {name} — {wins} 胜 / {games} 局(得分 {score})', en: '{rank}. {name} — {wins} wins / {games} games (score {score})' },
59
+ title: { 'zh-CN': '🏆 **{title} 本群排行**', en: '🏆 **{title} group leaderboard**' },
60
+ noGames: { 'zh-CN': '暂无已注册游戏。', en: 'No games are registered.' },
61
+ missing: { 'zh-CN': '未找到游戏「{query}」。可选:{names}', en: 'Game “{query}” was not found. Available: {names}' },
62
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-game-hub",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "description": "Zhin.js 游戏大厅 — 列出已加载的游戏插件 (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -22,12 +22,12 @@
22
22
  ],
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@zhin.js/game-kit": "1.1.14"
25
+ "@zhin.js/game-kit": "1.1.16"
26
26
  },
27
27
  "devDependencies": {
28
28
  "typescript": "^6.0.3",
29
29
  "vitest": "^4.1.10",
30
- "zhin.js": "1.1.14"
30
+ "zhin.js": "1.1.16"
31
31
  },
32
32
  "repository": {
33
33
  "type": "git",
@@ -60,8 +60,8 @@
60
60
  "plugins": []
61
61
  },
62
62
  "peerDependencies": {
63
- "@zhin.js/command": "^1.1.9",
64
- "zhin.js": "^1.1.14"
63
+ "@zhin.js/command": "^1.1.11",
64
+ "zhin.js": "^1.1.16"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "@zhin.js/command": {