@zhin.js/plugin-blackjack 1.1.15 → 1.1.17

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,7 +1,7 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import { messageFromCommandInput } from '@zhin.js/game-kit';
4
- import { BJ_HELP, runBjCommand } from "../../../lib/bj-command.js";
4
+ import { getBjHelp, runBjCommand } from "../../../lib/bj-command.js";
5
5
  import { resolveGameServices } from "../../../lib/runtime-store.js";
6
6
  function normalizeBjAction(raw) {
7
7
  const a = raw.trim().toLowerCase() || 'help';
@@ -16,12 +16,12 @@ function normalizeBjAction(raw) {
16
16
  export default defineCommand({
17
17
  description: 'Blackjack',
18
18
  params: { action: { type: 'string', default: '' } },
19
- async execute({ params, input, use, owner }) {
19
+ async execute({ params, input, use, locale, formatCommand }) {
20
20
  const action = normalizeBjAction(String(params.action ?? ''));
21
21
  if (!action || action === 'help')
22
- return BJ_HELP;
22
+ return getBjHelp({ locale, formatCommand });
23
23
  const services = resolveGameServices({ use });
24
- const message = messageFromCommandInput(input);
24
+ const message = messageFromCommandInput(input, { locale, formatCommand });
25
25
  return runBjCommand(services, message, action);
26
26
  },
27
27
  });
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import { messageFromCommandInput } from '@zhin.js/game-kit';
3
- import { BJ_HELP, runBjCommand } from '../../../src/bj-command.js';
3
+ import { getBjHelp, runBjCommand } from '../../../src/bj-command.js';
4
4
  import { resolveGameServices } from '../../../src/runtime-store.js';
5
5
 
6
6
  function normalizeBjAction(raw: string): string {
@@ -14,11 +14,11 @@ function normalizeBjAction(raw: string): string {
14
14
  export default defineCommand({
15
15
  description: 'Blackjack',
16
16
  params: { action: { type: 'string', default: '' } },
17
- async execute({ params, input, use, owner }) {
17
+ async execute({ params, input, use, locale, formatCommand }) {
18
18
  const action = normalizeBjAction(String(params.action ?? ''));
19
- if (!action || action === 'help') return BJ_HELP;
19
+ if (!action || action === 'help') return getBjHelp({ locale, formatCommand });
20
20
  const services = resolveGameServices({ use });
21
- const message = messageFromCommandInput(input);
21
+ const message = messageFromCommandInput(input, { locale, formatCommand });
22
22
  return runBjCommand(services, message, action);
23
23
  },
24
24
  });
@@ -1,4 +1,5 @@
1
- import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
1
+ import { type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
2
2
  import type { SessionService } from './session-service.js';
3
+ export declare function getBjHelp(message?: Pick<GameMessageLike, 'locale' | 'formatCommand'>): string;
3
4
  export declare const BJ_HELP: string;
4
5
  export declare function runBjCommand(services: SessionService, message: GameMessageLike, action: string): Promise<GameReply>;
package/lib/bj-command.js CHANGED
@@ -1,18 +1,13 @@
1
+ import { formatGameHelp, gameCommandFeedback } from '@zhin.js/game-kit';
1
2
  import { continueGame, handleChoice, startGame } from './game-flow.js';
2
- export const BJ_HELP = [
3
- '🃏 **21 点**',
4
- '',
5
- '尽量让手牌点数接近 21 且不超过,比庄家大即获胜。',
6
- '',
7
- '• `/21点 开始` — 新局',
8
- '• `/21点 继续` — 刷新界面',
9
- '• `/21点 放弃` — 结束本局',
10
- '• 对局中点击 **要牌** / **停牌**',
11
- ].join('\n');
3
+ export function getBjHelp(message = {}) {
4
+ return formatGameHelp(message, { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, 'bj', ['start', 'continue', 'quit'], { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." });
5
+ }
6
+ export const BJ_HELP = getBjHelp();
12
7
  export async function runBjCommand(services, message, action) {
13
8
  const a = action.trim().toLowerCase() || 'help';
14
9
  if (a === 'help' || a === '帮助')
15
- return BJ_HELP;
10
+ return getBjHelp(message);
16
11
  if (a === 'start' || a === '开始')
17
12
  return (await startGame(services, message)) ?? '';
18
13
  if (a === 'continue' || a === '继续')
@@ -20,9 +15,9 @@ export async function runBjCommand(services, message, action) {
20
15
  if (a === 'quit' || a === '放弃') {
21
16
  const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
22
17
  if (!session)
23
- return '你没有进行中的 21 点。';
18
+ return gameCommandFeedback(message, 'noGame');
24
19
  return (await handleChoice(services, message, session.id, 'quit')) ?? '';
25
20
  }
26
- return `未知操作「${action}」。发送 \`/21点 帮助\`。`;
21
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
27
22
  }
28
23
  //# sourceMappingURL=bj-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bj-command.js","sourceRoot":"","sources":["../src/bj-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGvE,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,aAAa;IACb,EAAE;IACF,4BAA4B;IAC5B,EAAE;IACF,kBAAkB;IAClB,oBAAoB;IACpB,oBAAoB;IACpB,yBAAyB;CAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAwB,EACxB,OAAwB,EACxB,MAAc;IAEd,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IAC/C,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACnF,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAC7C,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAC1F,OAAO,CAAC,OAAO,CAAC,EAAE,CACnB,CAAC;QACF,IAAI,CAAC,OAAO;YAAE,OAAO,eAAe,CAAC;QACrC,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"bj-command.js","sourceRoot":"","sources":["../src/bj-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAyD,MAAM,mBAAmB,CAAC;AAC/H,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGvE,MAAM,UAAU,SAAS,CAAC,UAA6D,EAAE;IACvF,OAAO,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EACpH,EAAE,OAAO,EAAE,uCAAuC,EAAE,EAAE,EAAE,0GAA0G,EAAE,CAAC,CAAC;AAC1K,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAwB,EACxB,OAAwB,EACxB,MAAc;IAEd,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACnF,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAC7C,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAC1F,OAAO,CAAC,OAAO,CAAC,EAAE,CACnB,CAAC;QACF,IAAI,CAAC,OAAO;YAAE,OAAO,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5D,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC"}
package/lib/game-flow.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages, resolveLocale } from 'zhin.js/i18n';
1
2
  import { BJ_PREFIX, compareHands, dealerShouldHit, handValue, TARGET, } from './engine.js';
2
3
  import { parseCards, parseDeck } from './session-service.js';
3
4
  import { buildBjView, naturalOutcome, playerBust } from './view.js';
@@ -27,11 +28,12 @@ async function dealerPlay(deck, dealer) {
27
28
  export async function startGame(services, message) {
28
29
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
29
30
  const active = await services.getActiveByChannel(ch);
31
+ const locale = resolveLocale(active ? active.locale : message.locale);
30
32
  if (active) {
31
33
  if (active.player_id === message.$sender.id) {
32
- return '你已有进行中的 21 点,发送「21点 继续」刷新。';
34
+ return messages(locale, 'text1');
33
35
  }
34
- return `本频道 ${active.player_name} 正在玩 21 点。`;
36
+ return messages(locale, 'text2', { p0: active.player_name });
35
37
  }
36
38
  const session = await services.createSession(message);
37
39
  const natural = naturalOutcome(session);
@@ -42,22 +44,24 @@ export async function startGame(services, message) {
42
44
  }
43
45
  export async function continueGame(services, message) {
44
46
  const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
47
+ const locale = resolveLocale(session ? session.locale : message.locale);
45
48
  if (!session)
46
- return '你没有进行中的 21 点,发送「21点 开始」。';
49
+ return messages(locale, 'text3');
47
50
  return renderView(session, message);
48
51
  }
49
52
  export async function handleChoice(services, message, sessionId, choiceId) {
50
53
  const session = await services.getById(sessionId);
54
+ const locale = resolveLocale(session ? session.locale : message.locale);
51
55
  if (!session)
52
- return '对局不存在。';
56
+ return messages(locale, 'text4');
53
57
  if (session.player_id !== message.$sender.id)
54
- return '这是别人的对局。';
58
+ return messages(locale, 'text5');
55
59
  if (session.status !== 'active' && choiceId === 'restart') {
56
60
  await services.updateSession(session.id, { status: 'aborted' });
57
61
  return (await startGame(services, message)) ?? null;
58
62
  }
59
63
  if (session.status !== 'active')
60
- return '对局已结束,请点击再来一局。';
64
+ return messages(locale, 'text6');
61
65
  if (choiceId === 'quit') {
62
66
  await services.updateSession(session.id, { status: 'aborted' });
63
67
  return renderView((await services.getById(session.id)), message, true, true);
@@ -68,7 +72,7 @@ export async function handleChoice(services, message, sessionId, choiceId) {
68
72
  if (choiceId === 'hit') {
69
73
  const card = deck.pop();
70
74
  if (!card)
71
- return '牌堆已空。';
75
+ return messages(locale, 'text7');
72
76
  player = [...player, card];
73
77
  await services.updateSession(session.id, {
74
78
  deck_json: JSON.stringify(deck),
@@ -81,7 +85,7 @@ export async function handleChoice(services, message, sessionId, choiceId) {
81
85
  return renderView(updated, message);
82
86
  }
83
87
  if (choiceId !== 'stand')
84
- return '无效操作。';
88
+ return messages(locale, 'text8');
85
89
  dealer = await dealerPlay(deck, dealer);
86
90
  await services.updateSession(session.id, {
87
91
  deck_json: JSON.stringify(deck),
@@ -92,4 +96,14 @@ export async function handleChoice(services, message, sessionId, choiceId) {
92
96
  return finishRound(services, message, session, status);
93
97
  }
94
98
  export { BJ_PREFIX, handValue, TARGET };
99
+ const messages = createMessages({
100
+ text1: { 'zh-CN': "你已有进行中的 21 点,请使用当前对局的操作入口。", en: "You already have an active blackjack game. Continue using its controls." },
101
+ text2: { 'zh-CN': "本频道 {p0} 正在玩 21 点。", en: "{p0} is playing blackjack in this channel." },
102
+ text3: { 'zh-CN': "你没有进行中的 21 点,请使用当前对局的操作入口。", en: "You have no active blackjack game." },
103
+ text4: { 'zh-CN': "对局不存在。", en: "This game no longer exists." },
104
+ text5: { 'zh-CN': "这是别人的对局。", en: "This game belongs to another player." },
105
+ text6: { 'zh-CN': "对局已结束,请点击再来一局。", en: "This game has ended. Choose Play again." },
106
+ text7: { 'zh-CN': "牌堆已空。", en: "The deck is empty." },
107
+ text8: { 'zh-CN': "无效操作。", en: "Invalid action." },
108
+ });
95
109
  //# sourceMappingURL=game-flow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
package/lib/models.d.ts CHANGED
@@ -4,6 +4,7 @@ declare module '@zhin.js/core' {
4
4
  interface Models {
5
5
  bj_sessions: {
6
6
  id: string;
7
+ locale?: 'zh-CN' | 'en' | null;
7
8
  adapter: string;
8
9
  endpoint: string;
9
10
  channel_type: string;
@@ -22,5 +23,7 @@ declare module '@zhin.js/core' {
22
23
  }
23
24
  export type BjSessionRow = Models['bj_sessions'];
24
25
  export declare function defineHostTables(db: {
25
- define: (name: string, definition: Record<string, unknown>) => void;
26
+ define: (name: string, definition: Record<string, unknown>, options?: {
27
+ readonly addColumns?: readonly string[];
28
+ }) => void;
26
29
  }): void;
package/lib/models.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export function defineHostTables(db) {
2
2
  db.define('bj_sessions', {
3
3
  id: { type: 'text', primary: true },
4
+ locale: { type: 'text', nullable: true },
4
5
  adapter: { type: 'text', nullable: false },
5
6
  endpoint: { type: 'text', nullable: false },
6
7
  channel_type: { type: 'text', nullable: false },
@@ -14,6 +15,6 @@ export function defineHostTables(db) {
14
15
  status: { type: 'text', default: 'active' },
15
16
  updated_at: { type: 'bigint', default: 0 },
16
17
  created_at: { type: 'bigint', default: 0 },
17
- });
18
+ }, { addColumns: ['locale'] });
18
19
  }
19
20
  //# sourceMappingURL=models.js.map
package/lib/models.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,gBAAgB,CAC9B,EAA2E;IAE3E,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE;QACvB,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,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1C,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAClD,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAClD,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KAC3C,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AA6BA,MAAM,UAAU,gBAAgB,CAC9B,EAAkI;IAElI,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE;QACvB,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;QACxC,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,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC1C,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAClD,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAClD,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KAC3C,EAAE,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjC,CAAC"}
@@ -26,6 +26,7 @@ export class SessionService extends BaseSessionService {
26
26
  const now = Date.now();
27
27
  const row = {
28
28
  id: generateSessionId(),
29
+ locale: message.locale ?? 'zh-CN',
29
30
  adapter: String(message.$adapter),
30
31
  endpoint: message.$endpoint,
31
32
  channel_type: message.$channel.type,
@@ -1 +1 @@
1
- {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
package/lib/view.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages } from 'zhin.js/i18n';
1
2
  import { buildChoiceKeyboard } from '@zhin.js/game-kit';
2
3
  import { BJ_PREFIX, formatHand, handValue, isBlackjack, TARGET } from './engine.js';
3
4
  import { parseCards } from './session-service.js';
@@ -5,32 +6,32 @@ export function buildBjView(session, terminal = false, revealDealer = false, cha
5
6
  const player = parseCards(session.player_cards_json);
6
7
  const dealer = parseCards(session.dealer_cards_json);
7
8
  const lines = [
8
- '🃏 **21 点**',
9
+ messages(session.locale ?? undefined, 'text1'),
9
10
  '',
10
- `你的牌:${formatHand(player)}`,
11
- `庄家:${revealDealer || terminal ? formatHand(dealer) : formatHand(dealer, true)}`,
11
+ messages(session.locale ?? undefined, 'text2', { p0: formatHand(player) }),
12
+ messages(session.locale ?? undefined, 'text3', { p0: revealDealer || terminal ? formatHand(dealer) : formatHand(dealer, true) }),
12
13
  '',
13
14
  ];
14
15
  if (terminal) {
15
16
  if (session.status === 'won')
16
- lines.push('🎉 **你赢了!**');
17
+ lines.push(messages(session.locale ?? undefined, 'text4'));
17
18
  else if (session.status === 'lost')
18
- lines.push('💀 **你输了**');
19
+ lines.push(messages(session.locale ?? undefined, 'text5'));
19
20
  else if (session.status === 'draw')
20
- lines.push('🤝 **平局**');
21
+ lines.push(messages(session.locale ?? undefined, 'text6'));
21
22
  else
22
- lines.push('🏳️ **本局已放弃。**');
23
- lines.push('', '点击「再来一局」或发送 `/21点 开始`');
23
+ lines.push(messages(session.locale ?? undefined, 'text7'));
24
+ lines.push('', messages(session.locale ?? undefined, 'text8'));
24
25
  }
25
26
  else {
26
- lines.push(`目标:尽量接近 ${TARGET} 且不超过。`);
27
+ lines.push(messages(session.locale ?? undefined, 'text9', { p0: TARGET }));
27
28
  }
28
29
  const choices = terminal
29
- ? [{ id: 'restart', label: '🔄 再来一局', style: 'primary', keepEnabledWhenTerminal: true }]
30
+ ? [{ id: 'restart', label: messages(session.locale ?? undefined, 'text10'), style: 'primary', keepEnabledWhenTerminal: true }]
30
31
  : [
31
- { id: 'hit', label: '➕ 要牌', style: 'primary' },
32
- { id: 'stand', label: '✋ 停牌', style: 'secondary' },
33
- { id: 'quit', label: '🏳️ 放弃', style: 'danger' },
32
+ { id: 'hit', label: messages(session.locale ?? undefined, 'text11'), style: 'primary' },
33
+ { id: 'stand', label: messages(session.locale ?? undefined, 'text12'), style: 'secondary' },
34
+ { id: 'quit', label: messages(session.locale ?? undefined, 'text13'), style: 'danger' },
34
35
  ];
35
36
  return buildChoiceKeyboard({
36
37
  gamePrefix: BJ_PREFIX,
@@ -38,7 +39,7 @@ export function buildBjView(session, terminal = false, revealDealer = false, cha
38
39
  narrative: lines.join('\n'),
39
40
  choices,
40
41
  terminal,
41
- fallbackHint: terminal ? '回复 1 再来一局' : '1 要牌 · 2 停牌 · 3 放弃',
42
+ fallbackHint: terminal ? messages(session.locale ?? undefined, 'text14') : messages(session.locale ?? undefined, 'text15'),
42
43
  interactionProfile: terminal ? 'terminal' : 'gameplay',
43
44
  channelType,
44
45
  });
@@ -64,4 +65,21 @@ export function naturalOutcome(session) {
64
65
  export function playerBust(session) {
65
66
  return handValue(parseCards(session.player_cards_json)) > TARGET;
66
67
  }
68
+ const messages = createMessages({
69
+ text1: { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" },
70
+ text2: { 'zh-CN': "你的牌:{p0}", en: "Your hand: {p0}" },
71
+ text3: { 'zh-CN': "庄家:{p0}", en: "Dealer: {p0}" },
72
+ text4: { 'zh-CN': "🎉 **你赢了!**", en: "🎉 **You won!**" },
73
+ text5: { 'zh-CN': "💀 **你输了**", en: "💀 **You lost**" },
74
+ text6: { 'zh-CN': "🤝 **平局**", en: "🤝 **Draw**" },
75
+ text7: { 'zh-CN': "🏳️ **本局已放弃。**", en: "🏳️ **You quit this game.**" },
76
+ text8: { 'zh-CN': "点击「再来一局」开始新局。", en: "Choose “Play again” to start a new game." },
77
+ text9: { 'zh-CN': "目标:尽量接近 {p0} 且不超过。", en: "Get as close to {p0} as possible without going over." },
78
+ text10: { 'zh-CN': "🔄 再来一局", en: "🔄 Play again" },
79
+ text11: { 'zh-CN': "➕ 要牌", en: "➕ Hit" },
80
+ text12: { 'zh-CN': "✋ 停牌", en: "✋ Stand" },
81
+ text13: { 'zh-CN': "🏳️ 放弃", en: "🏳️ Quit" },
82
+ text14: { 'zh-CN': "回复 1 再来一局", en: "Reply 1 to play again" },
83
+ text15: { 'zh-CN': "1 要牌 · 2 停牌 · 3 放弃", en: "1 Hit · 2 Stand · 3 Quit" },
84
+ });
67
85
  //# sourceMappingURL=view.js.map
package/lib/view.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineGameCommandAliasMiddleware, messageFromCommandInput } from '@zhin.js/game-kit';
3
- import { BJ_HELP, runBjCommand } from "../../lib/bj-command.js";
3
+ import { getBjHelp, runBjCommand } from "../../lib/bj-command.js";
4
4
  import { resolveGameServices } from "../../lib/runtime-store.js";
5
5
  function normalizeBjAction(raw) {
6
6
  const a = raw.trim().toLowerCase() || 'help';
@@ -15,11 +15,13 @@ function normalizeBjAction(raw) {
15
15
  export default defineGameCommandAliasMiddleware({
16
16
  aliases: ['21点', 'bj'],
17
17
  async run(action, input, context) {
18
+ const message = messageFromCommandInput(input, {
19
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
20
+ });
18
21
  const normalized = normalizeBjAction(String(action ?? ''));
19
22
  if (!normalized || normalized === 'help')
20
- return BJ_HELP;
23
+ return getBjHelp(message);
21
24
  const services = resolveGameServices(context);
22
- const message = messageFromCommandInput(input);
23
25
  return runBjCommand(services, message, normalized);
24
26
  },
25
27
  });
@@ -1,5 +1,5 @@
1
1
  import { defineGameCommandAliasMiddleware, messageFromCommandInput } from '@zhin.js/game-kit';
2
- import { BJ_HELP, runBjCommand } from '../../src/bj-command.js';
2
+ import { getBjHelp, runBjCommand } from '../../src/bj-command.js';
3
3
  import { resolveGameServices } from '../../src/runtime-store.js';
4
4
 
5
5
  function normalizeBjAction(raw: string): string {
@@ -13,10 +13,12 @@ function normalizeBjAction(raw: string): string {
13
13
  export default defineGameCommandAliasMiddleware({
14
14
  aliases: ['21点', 'bj'],
15
15
  async run(action, input, context) {
16
+ const message = messageFromCommandInput(input, {
17
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
18
+ });
16
19
  const normalized = normalizeBjAction(String(action ?? ''));
17
- if (!normalized || normalized === 'help') return BJ_HELP;
20
+ if (!normalized || normalized === 'help') return getBjHelp(message);
18
21
  const services = resolveGameServices(context);
19
- const message = messageFromCommandInput(input);
20
22
  return runBjCommand(services, message, normalized);
21
23
  },
22
24
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-blackjack",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Zhin.js 21 点(Blackjack)(Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -23,13 +23,13 @@
23
23
  ],
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@zhin.js/core": "1.1.50",
27
- "@zhin.js/game-kit": "1.1.15"
26
+ "@zhin.js/core": "1.1.52",
27
+ "@zhin.js/game-kit": "1.1.17"
28
28
  },
29
29
  "devDependencies": {
30
30
  "typescript": "^6.0.3",
31
31
  "vitest": "^4.1.10",
32
- "zhin.js": "1.1.15"
32
+ "zhin.js": "1.1.17"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",
@@ -66,9 +66,9 @@
66
66
  "plugins": []
67
67
  },
68
68
  "peerDependencies": {
69
- "@zhin.js/command": "^1.1.10",
70
- "@zhin.js/middleware": "^1.1.9",
71
- "zhin.js": "^1.1.15"
69
+ "@zhin.js/command": "^1.1.11",
70
+ "@zhin.js/middleware": "^1.1.10",
71
+ "zhin.js": "^1.1.17"
72
72
  },
73
73
  "peerDependenciesMeta": {
74
74
  "@zhin.js/command": {
package/plugin.js CHANGED
@@ -15,6 +15,10 @@ export default defineGamePlugin({
15
15
  displayName: 'Blackjack',
16
16
  },
17
17
  game: {
18
+ commandPath: 'bj',
19
+ titleI18n: { en: 'Blackjack' },
20
+ descriptionI18n: { en: 'Beat the dealer without going over 21' },
21
+ quickStartI18n: { en: 'start' },
18
22
  id: 'blackjack',
19
23
  title: '21 点',
20
24
  icon: '🃏',
package/src/bj-command.ts CHANGED
@@ -1,17 +1,13 @@
1
- import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
1
+ import { formatGameHelp, gameCommandFeedback, gameCommandHint, type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
2
2
  import { continueGame, handleChoice, startGame } from './game-flow.js';
3
3
  import type { SessionService } from './session-service.js';
4
4
 
5
- export const BJ_HELP = [
6
- '🃏 **21 点**',
7
- '',
8
- '尽量让手牌点数接近 21 且不超过,比庄家大即获胜。',
9
- '',
10
- '• `/21点 开始` — 新局',
11
- '• `/21点 继续` — 刷新界面',
12
- '• `/21点 放弃` — 结束本局',
13
- '• 对局中点击 **要牌** / **停牌**',
14
- ].join('\n');
5
+ export function getBjHelp(message: Pick<GameMessageLike, 'locale' | 'formatCommand'> = {}): string {
6
+ return formatGameHelp(message, { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, 'bj', ['start', 'continue', 'quit'],
7
+ { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." });
8
+ }
9
+
10
+ export const BJ_HELP = getBjHelp();
15
11
 
16
12
  export async function runBjCommand(
17
13
  services: SessionService,
@@ -19,7 +15,7 @@ export async function runBjCommand(
19
15
  action: string,
20
16
  ): Promise<GameReply> {
21
17
  const a = action.trim().toLowerCase() || 'help';
22
- if (a === 'help' || a === '帮助') return BJ_HELP;
18
+ if (a === 'help' || a === '帮助') return getBjHelp(message);
23
19
  if (a === 'start' || a === '开始') return (await startGame(services, message)) ?? '';
24
20
  if (a === 'continue' || a === '继续') return continueGame(services, message);
25
21
  if (a === 'quit' || a === '放弃') {
@@ -27,8 +23,8 @@ export async function runBjCommand(
27
23
  `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
28
24
  message.$sender.id,
29
25
  );
30
- if (!session) return '你没有进行中的 21 点。';
26
+ if (!session) return gameCommandFeedback(message, 'noGame');
31
27
  return (await handleChoice(services, message, session.id, 'quit')) ?? '';
32
28
  }
33
- return `未知操作「${action}」。发送 \`/21点 帮助\`。`;
29
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
34
30
  }
package/src/game-flow.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages, resolveLocale } from 'zhin.js/i18n';
1
2
  import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
2
3
  import {
3
4
  BJ_PREFIX,
@@ -55,11 +56,12 @@ export async function startGame(
55
56
  ): Promise<GameReply | undefined> {
56
57
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
57
58
  const active = await services.getActiveByChannel(ch);
59
+ const locale = resolveLocale(active ? active.locale : message.locale);
58
60
  if (active) {
59
61
  if (active.player_id === message.$sender.id) {
60
- return '你已有进行中的 21 点,发送「21点 继续」刷新。';
62
+ return messages(locale, 'text1');
61
63
  }
62
- return `本频道 ${active.player_name} 正在玩 21 点。`;
64
+ return messages(locale, 'text2', { p0: active.player_name });
63
65
  }
64
66
  const session = await services.createSession(message);
65
67
  const natural = naturalOutcome(session);
@@ -77,7 +79,8 @@ export async function continueGame(
77
79
  `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
78
80
  message.$sender.id,
79
81
  );
80
- if (!session) return '你没有进行中的 21 点,发送「21点 开始」。';
82
+ const locale = resolveLocale(session ? session.locale : message.locale);
83
+ if (!session) return messages(locale, 'text3');
81
84
  return renderView(session, message);
82
85
  }
83
86
 
@@ -88,15 +91,16 @@ export async function handleChoice(
88
91
  choiceId: string,
89
92
  ): Promise<GameReply | null> {
90
93
  const session = await services.getById(sessionId);
91
- if (!session) return '对局不存在。';
92
- if (session.player_id !== message.$sender.id) return '这是别人的对局。';
94
+ const locale = resolveLocale(session ? session.locale : message.locale);
95
+ if (!session) return messages(locale, 'text4');
96
+ if (session.player_id !== message.$sender.id) return messages(locale, 'text5');
93
97
 
94
98
  if (session.status !== 'active' && choiceId === 'restart') {
95
99
  await services.updateSession(session.id, { status: 'aborted' });
96
100
  return (await startGame(services, message)) ?? null;
97
101
  }
98
102
 
99
- if (session.status !== 'active') return '对局已结束,请点击再来一局。';
103
+ if (session.status !== 'active') return messages(locale, 'text6');
100
104
 
101
105
  if (choiceId === 'quit') {
102
106
  await services.updateSession(session.id, { status: 'aborted' });
@@ -109,7 +113,7 @@ export async function handleChoice(
109
113
 
110
114
  if (choiceId === 'hit') {
111
115
  const card = deck.pop();
112
- if (!card) return '牌堆已空。';
116
+ if (!card) return messages(locale, 'text7');
113
117
  player = [...player, card];
114
118
  await services.updateSession(session.id, {
115
119
  deck_json: JSON.stringify(deck),
@@ -122,7 +126,7 @@ export async function handleChoice(
122
126
  return renderView(updated, message);
123
127
  }
124
128
 
125
- if (choiceId !== 'stand') return '无效操作。';
129
+ if (choiceId !== 'stand') return messages(locale, 'text8');
126
130
 
127
131
  dealer = await dealerPlay(deck, dealer);
128
132
  await services.updateSession(session.id, {
@@ -136,3 +140,14 @@ export async function handleChoice(
136
140
  }
137
141
 
138
142
  export { BJ_PREFIX, handValue, TARGET };
143
+
144
+ const messages = createMessages({
145
+ text1: { 'zh-CN': "你已有进行中的 21 点,请使用当前对局的操作入口。", en: "You already have an active blackjack game. Continue using its controls." },
146
+ text2: { 'zh-CN': "本频道 {p0} 正在玩 21 点。", en: "{p0} is playing blackjack in this channel." },
147
+ text3: { 'zh-CN': "你没有进行中的 21 点,请使用当前对局的操作入口。", en: "You have no active blackjack game." },
148
+ text4: { 'zh-CN': "对局不存在。", en: "This game no longer exists." },
149
+ text5: { 'zh-CN': "这是别人的对局。", en: "This game belongs to another player." },
150
+ text6: { 'zh-CN': "对局已结束,请点击再来一局。", en: "This game has ended. Choose Play again." },
151
+ text7: { 'zh-CN': "牌堆已空。", en: "The deck is empty." },
152
+ text8: { 'zh-CN': "无效操作。", en: "Invalid action." },
153
+ });
package/src/models.ts CHANGED
@@ -6,6 +6,7 @@ declare module '@zhin.js/core' {
6
6
  interface Models {
7
7
  bj_sessions: {
8
8
  id: string;
9
+ locale?: 'zh-CN' | 'en' | null;
9
10
  adapter: string;
10
11
  endpoint: string;
11
12
  channel_type: string;
@@ -27,10 +28,11 @@ export type BjSessionRow = Models['bj_sessions'];
27
28
 
28
29
 
29
30
  export function defineHostTables(
30
- db: { define: (name: string, definition: Record<string, unknown>) => void },
31
+ db: { define: (name: string, definition: Record<string, unknown>, options?: { readonly addColumns?: readonly string[] }) => void },
31
32
  ): void {
32
33
  db.define('bj_sessions', {
33
34
  id: { type: 'text', primary: true },
35
+ locale: { type: 'text', nullable: true },
34
36
  adapter: { type: 'text', nullable: false },
35
37
  endpoint: { type: 'text', nullable: false },
36
38
  channel_type: { type: 'text', nullable: false },
@@ -44,5 +46,5 @@ export function defineHostTables(
44
46
  status: { type: 'text', default: 'active' },
45
47
  updated_at: { type: 'bigint', default: 0 },
46
48
  created_at: { type: 'bigint', default: 0 },
47
- });
49
+ }, { addColumns: ['locale'] });
48
50
  }
@@ -38,6 +38,7 @@ export class SessionService extends BaseSessionService<BjSessionRow> {
38
38
  const now = Date.now();
39
39
  const row: BjSessionRow = {
40
40
  id: generateSessionId(),
41
+ locale: message.locale ?? 'zh-CN',
41
42
  adapter: String(message.$adapter),
42
43
  endpoint: message.$endpoint,
43
44
  channel_type: message.$channel.type,
package/src/view.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages } from 'zhin.js/i18n';
1
2
  import { buildChoiceKeyboard } from '@zhin.js/game-kit';
2
3
  import type { SendContent } from '@zhin.js/core/runtime';
3
4
  import { BJ_PREFIX, formatHand, handValue, isBlackjack, TARGET } from './engine.js';
@@ -13,29 +14,29 @@ export function buildBjView(
13
14
  const player = parseCards(session.player_cards_json);
14
15
  const dealer = parseCards(session.dealer_cards_json);
15
16
  const lines = [
16
- '🃏 **21 点**',
17
+ messages(session.locale ?? undefined, 'text1'),
17
18
  '',
18
- `你的牌:${formatHand(player)}`,
19
- `庄家:${revealDealer || terminal ? formatHand(dealer) : formatHand(dealer, true)}`,
19
+ messages(session.locale ?? undefined, 'text2', { p0: formatHand(player) }),
20
+ messages(session.locale ?? undefined, 'text3', { p0: revealDealer || terminal ? formatHand(dealer) : formatHand(dealer, true) }),
20
21
  '',
21
22
  ];
22
23
 
23
24
  if (terminal) {
24
- if (session.status === 'won') lines.push('🎉 **你赢了!**');
25
- else if (session.status === 'lost') lines.push('💀 **你输了**');
26
- else if (session.status === 'draw') lines.push('🤝 **平局**');
27
- else lines.push('🏳️ **本局已放弃。**');
28
- lines.push('', '点击「再来一局」或发送 `/21点 开始`');
25
+ if (session.status === 'won') lines.push(messages(session.locale ?? undefined, 'text4'));
26
+ else if (session.status === 'lost') lines.push(messages(session.locale ?? undefined, 'text5'));
27
+ else if (session.status === 'draw') lines.push(messages(session.locale ?? undefined, 'text6'));
28
+ else lines.push(messages(session.locale ?? undefined, 'text7'));
29
+ lines.push('', messages(session.locale ?? undefined, 'text8'));
29
30
  } else {
30
- lines.push(`目标:尽量接近 ${TARGET} 且不超过。`);
31
+ lines.push(messages(session.locale ?? undefined, 'text9', { p0: TARGET }));
31
32
  }
32
33
 
33
34
  const choices = terminal
34
- ? [{ id: 'restart', label: '🔄 再来一局', style: 'primary' as const, keepEnabledWhenTerminal: true }]
35
+ ? [{ id: 'restart', label: messages(session.locale ?? undefined, 'text10'), style: 'primary' as const, keepEnabledWhenTerminal: true }]
35
36
  : [
36
- { id: 'hit', label: '➕ 要牌', style: 'primary' as const },
37
- { id: 'stand', label: '✋ 停牌', style: 'secondary' as const },
38
- { id: 'quit', label: '🏳️ 放弃', style: 'danger' as const },
37
+ { id: 'hit', label: messages(session.locale ?? undefined, 'text11'), style: 'primary' as const },
38
+ { id: 'stand', label: messages(session.locale ?? undefined, 'text12'), style: 'secondary' as const },
39
+ { id: 'quit', label: messages(session.locale ?? undefined, 'text13'), style: 'danger' as const },
39
40
  ];
40
41
 
41
42
  return buildChoiceKeyboard({
@@ -44,7 +45,7 @@ export function buildBjView(
44
45
  narrative: lines.join('\n'),
45
46
  choices,
46
47
  terminal,
47
- fallbackHint: terminal ? '回复 1 再来一局' : '1 要牌 · 2 停牌 · 3 放弃',
48
+ fallbackHint: terminal ? messages(session.locale ?? undefined, 'text14') : messages(session.locale ?? undefined, 'text15'),
48
49
  interactionProfile: terminal ? 'terminal' : 'gameplay',
49
50
  channelType,
50
51
  });
@@ -70,3 +71,21 @@ export function naturalOutcome(session: BjSessionRow): 'won' | 'lost' | 'draw' |
70
71
  export function playerBust(session: BjSessionRow): boolean {
71
72
  return handValue(parseCards(session.player_cards_json)) > TARGET;
72
73
  }
74
+
75
+ const messages = createMessages({
76
+ text1: { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" },
77
+ text2: { 'zh-CN': "你的牌:{p0}", en: "Your hand: {p0}" },
78
+ text3: { 'zh-CN': "庄家:{p0}", en: "Dealer: {p0}" },
79
+ text4: { 'zh-CN': "🎉 **你赢了!**", en: "🎉 **You won!**" },
80
+ text5: { 'zh-CN': "💀 **你输了**", en: "💀 **You lost**" },
81
+ text6: { 'zh-CN': "🤝 **平局**", en: "🤝 **Draw**" },
82
+ text7: { 'zh-CN': "🏳️ **本局已放弃。**", en: "🏳️ **You quit this game.**" },
83
+ text8: { 'zh-CN': "点击「再来一局」开始新局。", en: "Choose “Play again” to start a new game." },
84
+ text9: { 'zh-CN': "目标:尽量接近 {p0} 且不超过。", en: "Get as close to {p0} as possible without going over." },
85
+ text10: { 'zh-CN': "🔄 再来一局", en: "🔄 Play again" },
86
+ text11: { 'zh-CN': "➕ 要牌", en: "➕ Hit" },
87
+ text12: { 'zh-CN': "✋ 停牌", en: "✋ Stand" },
88
+ text13: { 'zh-CN': "🏳️ 放弃", en: "🏳️ Quit" },
89
+ text14: { 'zh-CN': "回复 1 再来一局", en: "Reply 1 to play again" },
90
+ text15: { 'zh-CN': "1 要牌 · 2 停牌 · 3 放弃", en: "1 Hit · 2 Stand · 3 Quit" },
91
+ });