koishi-plugin-game-mini 0.2.5 → 0.2.7

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.
Files changed (4) hide show
  1. package/lib/index.d.ts +137 -11
  2. package/lib/index.js +808 -598
  3. package/package.json +2 -4
  4. package/readme.md +121 -106
package/lib/index.js CHANGED
@@ -11,76 +11,303 @@ const path_1 = __importDefault(require("path"));
11
11
  const yaml_1 = __importDefault(require("yaml"));
12
12
  const axios_1 = __importDefault(require("axios"));
13
13
  exports.name = 'game-mini';
14
- exports.using = ['i18n'];
14
+ exports.using = ['i18n', 'database'];
15
15
  exports.inject = ['console'];
16
- exports.Config = koishi_1.Schema.object({
17
- enableNumberGuess: koishi_1.Schema.boolean().default(true).description('启用猜数字游戏'),
18
- enableWzHero: koishi_1.Schema.boolean().default(true).description('启用王者英雄猜谜游戏'),
19
- enableChengyuImage: koishi_1.Schema.boolean().default(true).description('启用看图猜成语游戏'),
20
- enableChengyuJielong: koishi_1.Schema.boolean().default(true).description('启用成语接龙游戏'),
21
- enableCalc24: koishi_1.Schema.boolean().default(true).description('启用算24点游戏'),
22
- enablePasswordLock: koishi_1.Schema.boolean().default(true).description('启用密码锁破解游戏'),
23
- enablePrivateGame: koishi_1.Schema.boolean().default(true).description('允许私聊玩游戏'),
24
- guessNumber: koishi_1.Schema.object({
25
- min: koishi_1.Schema.number().min(0).default(0).description('猜数字最小值'),
26
- max: koishi_1.Schema.number().min(1).default(100).description('猜数字最大值'),
27
- botParticipateInGroup: koishi_1.Schema.boolean().default(true).description('群聊中机器人参与猜数字'),
28
- totalRounds: koishi_1.Schema.number().min(1).default(10).description('猜数字总回合数'),
29
- showRank: koishi_1.Schema.boolean().default(true).description('猜数字显示排行榜'),
30
- autoPlayDelay: koishi_1.Schema.number().min(0).default(10).description('机器人自动操作延迟(秒)'),
31
- autoPlayMaxCount: koishi_1.Schema.number().min(1).default(5).description('机器人最大自动操作次数'),
32
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
33
- }).description('猜数字游戏配置'),
34
- wzHero: koishi_1.Schema.object({
35
- totalRounds: koishi_1.Schema.number().min(1).default(10).description('王者英雄猜谜总回合数'),
36
- showRank: koishi_1.Schema.boolean().default(true).description('王者英雄猜谜显示排行榜'),
37
- defaultDifficulty: koishi_1.Schema.union(['简单', '中等', '困难']).default('简单').description('默认难度'),
38
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
39
- }).description('王者英雄猜谜游戏配置'),
40
- chengyuImage: koishi_1.Schema.object({
41
- totalRounds: koishi_1.Schema.number().min(1).default(10).description('看图猜成语总回合数'),
42
- showRank: koishi_1.Schema.boolean().default(true).description('看图猜成语显示排行榜'),
43
- defaultHintLevel: koishi_1.Schema.union([1, 2, 3, 4, 5]).default(1).description('默认提示级别(1-5)'),
44
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
45
- }).description('看图猜成语游戏配置'),
46
- chengyuJielong: koishi_1.Schema.object({
47
- botParticipateInGroup: koishi_1.Schema.boolean().default(true).description('群聊中机器人参与成语接龙'),
48
- totalRounds: koishi_1.Schema.number().min(1).default(10).description('成语接龙总回合数'),
49
- showRank: koishi_1.Schema.boolean().default(true).description('成语接龙显示排行榜'),
50
- autoPlayDelay: koishi_1.Schema.number().min(0).default(10).description('机器人自动操作延迟(秒)'),
51
- autoPlayMaxCount: koishi_1.Schema.number().min(1).default(5).description('机器人最大自动操作次数'),
52
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
53
- }).description('成语接龙游戏配置'),
54
- calc24: koishi_1.Schema.object({
55
- totalRounds: koishi_1.Schema.number().min(1).default(5).description('算24点总回合数'),
56
- showRank: koishi_1.Schema.boolean().default(true).description('算24点显示排行榜'),
57
- defaultDifficulty: koishi_1.Schema.union(['简单', '中等', '困难']).default('中等').description('默认难度'),
58
- difficultyLevels: koishi_1.Schema.object({
59
- easy: koishi_1.Schema.object({
60
- min: koishi_1.Schema.number().default(1).description('最小值'),
61
- max: koishi_1.Schema.number().default(8).description('最大值'),
62
- }).description('简单难度'),
63
- medium: koishi_1.Schema.object({
64
- min: koishi_1.Schema.number().default(1).description('最小值'),
65
- max: koishi_1.Schema.number().default(10).description('最大值'),
66
- }).description('中等难度'),
67
- hard: koishi_1.Schema.object({
68
- min: koishi_1.Schema.number().default(1).description('最小值'),
69
- max: koishi_1.Schema.number().default(13).description('最大值'),
70
- }).description('困难难度'),
71
- }).description('难度等级配置'),
72
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
73
- }).description('算24点游戏配置'),
74
- passwordLock: koishi_1.Schema.object({
75
- maxGuessTimes: koishi_1.Schema.number().min(1).default(10).description('密码锁最大猜测次数'),
76
- showHint: koishi_1.Schema.boolean().default(true).description('密码锁显示提示'),
77
- showRank: koishi_1.Schema.boolean().default(true).description('密码锁显示排行榜'),
78
- autoStopInactiveTime: koishi_1.Schema.number().min(0).default(30).description('游戏无操作自动停止时间(秒)'),
79
- }).description('密码锁破解游戏配置'),
80
- apiConfig: koishi_1.Schema.object({
81
- timeout: koishi_1.Schema.number().default(5000).description('API请求超时时间(毫秒)'),
82
- }).description('API接口配置'),
83
- });
16
+ const defaultMessages = {
17
+ guessNumber: {
18
+ usage: "用法错误!正确用法:猜数字 开始 | [数字] | 猜数字 结束",
19
+ start: "猜数字比赛开始!本次共 {0} 回合~",
20
+ stop: "猜数字比赛已停止",
21
+ outOfRange: "数字超出当前范围 [{0}-{1}],请重新输入!",
22
+ tooSmall: "猜小啦!当前范围更新为 [{0}-{1}]",
23
+ tooBig: "猜大啦!当前范围更新为 [{0}-{1}]",
24
+ correct: "恭喜你猜中数字!",
25
+ roundEnd: "第 {0} 回合结束!剩余回合:{1}",
26
+ gameEnd: "🎉 猜数字比赛结束!🎉",
27
+ rankTitle: "🏆 本局排行榜 🏆",
28
+ rankEmpty: "暂无参与记录~",
29
+ disabled: "猜数字功能已关闭,请联系管理员开启",
30
+ autoStop: "太久没人玩啦,比赛自动结束~"
31
+ },
32
+ wzHero: {
33
+ start: "猜王者英雄开始!本次共 {0} 回合~当前难度:{1}",
34
+ startUsage: "用法错误!正确用法:猜王者英雄 开始 | [答案] | 提示 | 结束",
35
+ stop: "猜王者英雄比赛已停止",
36
+ notStarted: "猜王者英雄比赛尚未开始,请输入 猜王者英雄 开始 开始游戏",
37
+ hint: "提示",
38
+ apiError: "API请求失败,请稍后再试",
39
+ correct: "答对啦!你获得1分~",
40
+ wrong: "答错啦~正确答案是:{0},你不得分",
41
+ roundEnd: "第 {0} 回合结束!剩余回合:{1}",
42
+ gameEnd: "🎉 猜王者英雄比赛结束!🎉",
43
+ rankTitle: "🏆 本局排行榜 🏆",
44
+ rankEmpty: "暂无参与记录~",
45
+ disabled: "猜王者英雄功能已关闭,请联系管理员开启",
46
+ autoStop: "太久没人玩啦,比赛自动结束~"
47
+ },
48
+ chengyuImage: {
49
+ start: "看图猜成语比赛开始!本次共 {0} 回合~当前提示级别:{1}",
50
+ stop: "看图猜成语比赛已停止",
51
+ submitUsage: "请直接输入 [答案],或输入 提示 获取线索",
52
+ notStarted: "看图猜成语比赛尚未开始,请输入 看图猜成语 开始 开始游戏",
53
+ next: "第 {0} 题来啦!",
54
+ hintGet: "【提示】{0}",
55
+ hintError: "获取提示失败,请稍后再试",
56
+ apiError: "API请求失败,请稍后再试",
57
+ correct: "答对啦!你获得1分~",
58
+ wrong: "答错啦~正确答案是:{0},你不得分",
59
+ roundEnd: "第 {0} 回合结束!剩余回合:{1}",
60
+ gameEnd: "🎉 看图猜成语比赛结束!🎉",
61
+ rankTitle: "🏆 本局排行榜 🏆",
62
+ rankEmpty: "暂无参与记录~",
63
+ disabled: "看图猜成语功能已关闭,请联系管理员开启",
64
+ autoStop: "太久没人玩啦,比赛自动结束~"
65
+ },
66
+ chengyuJielong: {
67
+ start: "成语接龙比赛开始!本次共 {0} 回合~我先来~",
68
+ stop: "成语接龙比赛已停止",
69
+ notStarted: "成语接龙比赛尚未开始,请输入 成语接龙 开始 开始游戏",
70
+ joinUsage: "请直接发送成语参与接龙",
71
+ apiError: "API请求失败,请稍后再试",
72
+ botTurn: "该我了!我接:{0}",
73
+ botWin: "哈哈我接不上了!本轮结束~",
74
+ autoPlayTooMany: "自动参与次数已达上限 {0}",
75
+ notIdiom: "请输入4字成语",
76
+ correct: "接龙成功!",
77
+ wrong: "接龙失败!",
78
+ roundEnd: "第 {0} 回合结束!剩余回合:{1}",
79
+ gameEnd: "🎉 成语接龙比赛结束!🎉",
80
+ rankTitle: "🏆 本局排行榜 🏆",
81
+ rankEmpty: "暂无参与记录~",
82
+ disabled: "成语接龙功能已关闭,请联系管理员开启",
83
+ autoStop: "太久没人玩啦,比赛自动结束~"
84
+ },
85
+ calc24: {
86
+ start: "算24点游戏开始!本次共 {0} 回合~当前难度:{1}",
87
+ stop: "算24点游戏已停止",
88
+ notStarted: "算24点游戏尚未开始,请输入 算24点 开始 开始游戏",
89
+ generate: "📝 第 {0} 题({1}):用 {2} 通过加减乘除和括号算出24!",
90
+ correct: "答对啦!你获得1分~",
91
+ wrong: "答错啦~",
92
+ solved: "这组数已经被答对啦,换一组数字~",
93
+ roundEnd: "第 {0} 回合结束!剩余回合:{1}",
94
+ gameEnd: "🎉 算24点游戏结束!🎉",
95
+ rankTitle: "🏆 本局排行榜 🏆",
96
+ rankEmpty: "暂无参与记录~",
97
+ disabled: "算24点功能已关闭,请联系管理员开启",
98
+ autoStop: "太久没人玩啦,比赛自动结束~"
99
+ },
100
+ rank: {
101
+ title: "📊 群游戏总排行榜",
102
+ empty: "暂无玩家数据",
103
+ playerInfo: "{0}. {1} - 得分:{2}分 | 答对:{3}题 | 游玩:{4}次",
104
+ totalStats: "\n📈 总统计:共 {0} 位玩家 | 总得分:{1} | 总答对:{2} | 总游玩:{3}",
105
+ noPermission: "❌ 你没有权限执行此操作",
106
+ clearSuccess: "✅ 本群所有玩家数据已清零"
107
+ },
108
+ common: {
109
+ gameRunning: "当前已有游戏在运行中,请先结束当前游戏后再开始新游戏!",
110
+ gameStoppedByInactive: "太久没人玩啦,比赛自动结束~",
111
+ paramError: "❌ 参数错误!请检查输入格式"
112
+ }
113
+ };
114
+ exports.Config = koishi_1.Schema.intersect([
115
+ koishi_1.Schema.object({
116
+ enableNumberGuess: koishi_1.Schema.boolean().default(true).description('🎲 启用猜数字游戏'),
117
+ enableWzHero: koishi_1.Schema.boolean().default(true).description('⚔️ 启用王者英雄猜谜'),
118
+ enableChengyuImage: koishi_1.Schema.boolean().default(true).description('🖼️ 启用看图猜成语'),
119
+ enableChengyuJielong: koishi_1.Schema.boolean().default(true).description('🐉 启用成语接龙'),
120
+ enableCalc24: koishi_1.Schema.boolean().default(true).description('🧮 启用算24点'),
121
+ }).description('⚙️ 游戏开关'),
122
+ koishi_1.Schema.object({
123
+ privateGame: koishi_1.Schema.object({
124
+ enableNumberGuess: koishi_1.Schema.boolean().default(true).description('🎲 允许私聊玩猜数字'),
125
+ enableWzHero: koishi_1.Schema.boolean().default(true).description('⚔️ 允许私聊玩王者英雄'),
126
+ enableChengyuImage: koishi_1.Schema.boolean().default(true).description('🖼️ 允许私聊玩看图猜成语'),
127
+ enableChengyuJielong: koishi_1.Schema.boolean().default(true).description('🐉 允许私聊玩成语接龙'),
128
+ enableCalc24: koishi_1.Schema.boolean().default(true).description('🧮 允许私聊玩算24点'),
129
+ }).description('💬 私聊游戏开关'),
130
+ }),
131
+ koishi_1.Schema.object({
132
+ rank: koishi_1.Schema.object({
133
+ enableCommand: koishi_1.Schema.boolean().default(true).description('📊 启用排行榜指令'),
134
+ maxDisplay: koishi_1.Schema.number().min(1).max(100).default(10).description('📋 排行榜最多显示人数'),
135
+ clearDataPermission: koishi_1.Schema.number().default(5).description('🔑 清零数据所需权限等级'),
136
+ messages: koishi_1.Schema.object({
137
+ title: koishi_1.Schema.string().default(defaultMessages.rank.title).description('排行榜标题'),
138
+ empty: koishi_1.Schema.string().default(defaultMessages.rank.empty).description('排行榜为空提示'),
139
+ playerInfo: koishi_1.Schema.string().default(defaultMessages.rank.playerInfo).description('玩家信息格式\n{0}-排名, {1}-玩家名, {2}-得分, {3}-答对题数, {4}-游玩次数'),
140
+ totalStats: koishi_1.Schema.string().default(defaultMessages.rank.totalStats).description('总统计信息\n{0}-总玩家数, {1}-总得分, {2}-总答对, {3}-总游玩'),
141
+ noPermission: koishi_1.Schema.string().default(defaultMessages.rank.noPermission).description('无权限提示'),
142
+ clearSuccess: koishi_1.Schema.string().default(defaultMessages.rank.clearSuccess).description('清零成功提示'),
143
+ showTotalStats: koishi_1.Schema.boolean().default(true).description('是否显示总统计数据'),
144
+ }).description('📊 排行榜消息配置'),
145
+ }).description('📊 排行榜配置'),
146
+ }),
147
+ koishi_1.Schema.object({
148
+ guessNumber: koishi_1.Schema.object({
149
+ min: koishi_1.Schema.number().min(0).default(0).description('最小值'),
150
+ max: koishi_1.Schema.number().min(1).default(100).description('最大值'),
151
+ botParticipateInGroup: koishi_1.Schema.boolean().default(true).description('群聊中机器人是否参与'),
152
+ totalRounds: koishi_1.Schema.number().min(1).default(10).description('总回合数'),
153
+ showRank: koishi_1.Schema.boolean().default(true).description('游戏结束后显示本局排行榜'),
154
+ autoPlayDelay: koishi_1.Schema.number().min(0).default(10).description('机器人自动操作延迟(秒)'),
155
+ autoPlayMaxCount: koishi_1.Schema.number().min(1).default(5).description('机器人最大自动操作次数'),
156
+ autoStopInactiveTime: koishi_1.Schema.number().min(0).default(60).description('游戏无操作自动停止时间(秒)'),
157
+ enablePenalty: koishi_1.Schema.boolean().default(true).description('启用惩罚机制'),
158
+ rewardScore: koishi_1.Schema.number().min(0).default(1).description('猜中者奖励分数'),
159
+ penaltyScore: koishi_1.Schema.number().max(0).default(-1).description('其他人扣除分数'),
160
+ messages: koishi_1.Schema.object({
161
+ usage: koishi_1.Schema.string().default(defaultMessages.guessNumber.usage).description('用法错误提示\n{0}-最小值, {1}-最大值'),
162
+ start: koishi_1.Schema.string().default(defaultMessages.guessNumber.start).description('游戏开始提示\n{0}-总回合数'),
163
+ stop: koishi_1.Schema.string().default(defaultMessages.guessNumber.stop).description('游戏停止提示'),
164
+ outOfRange: koishi_1.Schema.string().default(defaultMessages.guessNumber.outOfRange).description('数字超出范围提示\n{0}-最小值, {1}-最大值'),
165
+ tooSmall: koishi_1.Schema.string().default(defaultMessages.guessNumber.tooSmall).description('猜小了提示\n{0}-新最小值, {1}-新最大值'),
166
+ tooBig: koishi_1.Schema.string().default(defaultMessages.guessNumber.tooBig).description('猜大了提示\n{0}-新最小值, {1}-新最大值'),
167
+ correct: koishi_1.Schema.string().default(defaultMessages.guessNumber.correct).description('猜中提示'),
168
+ roundEnd: koishi_1.Schema.string().default(defaultMessages.guessNumber.roundEnd).description('回合结束提示\n{0}-当前回合, {1}-剩余回合'),
169
+ gameEnd: koishi_1.Schema.string().default(defaultMessages.guessNumber.gameEnd).description('游戏结束提示'),
170
+ rankTitle: koishi_1.Schema.string().default(defaultMessages.guessNumber.rankTitle).description('本局排行榜标题'),
171
+ rankEmpty: koishi_1.Schema.string().default(defaultMessages.guessNumber.rankEmpty).description('本局排行榜为空提示'),
172
+ disabled: koishi_1.Schema.string().default(defaultMessages.guessNumber.disabled).description('功能禁用提示'),
173
+ autoStop: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('自动停止提示'),
174
+ }).description('💬 猜数字消息配置'),
175
+ }).description('🎲 猜数字游戏配置'),
176
+ }),
177
+ koishi_1.Schema.object({
178
+ wzHero: koishi_1.Schema.object({
179
+ totalRounds: koishi_1.Schema.number().min(1).default(10).description('总回合数'),
180
+ showRank: koishi_1.Schema.boolean().default(true).description('游戏结束后显示本局排行榜'),
181
+ defaultDifficulty: koishi_1.Schema.union(['简单', '中等', '困难']).default('简单').description('默认难度'),
182
+ autoStopInactiveTime: koishi_1.Schema.number().min(0).default(60).description('游戏无操作自动停止时间(秒)'),
183
+ rewardScore: koishi_1.Schema.number().min(0).default(1).description('答对奖励分数'),
184
+ messages: koishi_1.Schema.object({
185
+ start: koishi_1.Schema.string().default(defaultMessages.wzHero.start).description('游戏开始提示\n{0}-总回合数, {1}-难度'),
186
+ startUsage: koishi_1.Schema.string().default(defaultMessages.wzHero.startUsage).description('开始用法提示'),
187
+ stop: koishi_1.Schema.string().default(defaultMessages.wzHero.stop).description('游戏停止提示'),
188
+ notStarted: koishi_1.Schema.string().default(defaultMessages.wzHero.notStarted).description('游戏未开始提示'),
189
+ hint: koishi_1.Schema.string().default(defaultMessages.wzHero.hint).description('提示命令'),
190
+ apiError: koishi_1.Schema.string().default(defaultMessages.wzHero.apiError).description('API错误提示'),
191
+ correct: koishi_1.Schema.string().default(defaultMessages.wzHero.correct).description('答对提示\n{0}-当前得分'),
192
+ wrong: koishi_1.Schema.string().default(defaultMessages.wzHero.wrong).description('答错提示\n{0}-正确答案'),
193
+ roundEnd: koishi_1.Schema.string().default(defaultMessages.wzHero.roundEnd).description('回合结束提示\n{0}-当前回合, {1}-剩余回合'),
194
+ gameEnd: koishi_1.Schema.string().default(defaultMessages.wzHero.gameEnd).description('游戏结束提示'),
195
+ rankTitle: koishi_1.Schema.string().default(defaultMessages.wzHero.rankTitle).description('本局排行榜标题'),
196
+ rankEmpty: koishi_1.Schema.string().default(defaultMessages.wzHero.rankEmpty).description('本局排行榜为空提示'),
197
+ disabled: koishi_1.Schema.string().default(defaultMessages.wzHero.disabled).description('功能禁用提示'),
198
+ autoStop: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('自动停止提示'),
199
+ }).description('💬 王者英雄猜谜消息配置'),
200
+ }).description('⚔️ 王者英雄猜谜配置'),
201
+ }),
202
+ koishi_1.Schema.object({
203
+ chengyuImage: koishi_1.Schema.object({
204
+ totalRounds: koishi_1.Schema.number().min(1).default(10).description('总回合数'),
205
+ showRank: koishi_1.Schema.boolean().default(true).description('游戏结束后显示本局排行榜'),
206
+ defaultHintLevel: koishi_1.Schema.union([1, 2, 3, 4, 5]).default(1).description('默认提示级别'),
207
+ autoStopInactiveTime: koishi_1.Schema.number().min(0).default(60).description('游戏无操作自动停止时间(秒)'),
208
+ rewardScore: koishi_1.Schema.number().min(0).default(1).description('答对奖励分数'),
209
+ messages: koishi_1.Schema.object({
210
+ start: koishi_1.Schema.string().default(defaultMessages.chengyuImage.start).description('游戏开始提示\n{0}-总回合数, {1}-提示级别'),
211
+ stop: koishi_1.Schema.string().default(defaultMessages.chengyuImage.stop).description('游戏停止提示'),
212
+ submitUsage: koishi_1.Schema.string().default(defaultMessages.chengyuImage.submitUsage).description('提交答案用法提示'),
213
+ notStarted: koishi_1.Schema.string().default(defaultMessages.chengyuImage.notStarted).description('游戏未开始提示'),
214
+ next: koishi_1.Schema.string().default(defaultMessages.chengyuImage.next).description('下一题提示\n{0}-当前回合'),
215
+ hintGet: koishi_1.Schema.string().default(defaultMessages.chengyuImage.hintGet).description('获取提示成功\n{0}-提示内容'),
216
+ hintError: koishi_1.Schema.string().default(defaultMessages.chengyuImage.hintError).description('获取提示失败'),
217
+ apiError: koishi_1.Schema.string().default(defaultMessages.chengyuImage.apiError).description('API错误提示'),
218
+ correct: koishi_1.Schema.string().default(defaultMessages.chengyuImage.correct).description('答对提示\n{0}-当前得分'),
219
+ wrong: koishi_1.Schema.string().default(defaultMessages.chengyuImage.wrong).description('答错提示\n{0}-正确答案, {1}-当前得分'),
220
+ roundEnd: koishi_1.Schema.string().default(defaultMessages.chengyuImage.roundEnd).description('回合结束提示\n{0}-当前回合, {1}-剩余回合'),
221
+ gameEnd: koishi_1.Schema.string().default(defaultMessages.chengyuImage.gameEnd).description('游戏结束提示'),
222
+ rankTitle: koishi_1.Schema.string().default(defaultMessages.chengyuImage.rankTitle).description('本局排行榜标题'),
223
+ rankEmpty: koishi_1.Schema.string().default(defaultMessages.chengyuImage.rankEmpty).description('本局排行榜为空提示'),
224
+ disabled: koishi_1.Schema.string().default(defaultMessages.chengyuImage.disabled).description('功能禁用提示'),
225
+ autoStop: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('自动停止提示'),
226
+ }).description('💬 看图猜成语消息配置'),
227
+ }).description('🖼️ 看图猜成语配置'),
228
+ }),
229
+ koishi_1.Schema.object({
230
+ chengyuJielong: koishi_1.Schema.object({
231
+ totalRounds: koishi_1.Schema.number().min(1).default(10).description('总回合数'),
232
+ showRank: koishi_1.Schema.boolean().default(true).description('游戏结束后显示本局排行榜'),
233
+ autoPlayDelay: koishi_1.Schema.number().min(0).default(10).description('机器人自动操作延迟(秒)'),
234
+ autoPlayMaxCount: koishi_1.Schema.number().min(1).default(5).description('机器人最大自动操作次数'),
235
+ autoStopInactiveTime: koishi_1.Schema.number().min(0).default(60).description('游戏无操作自动停止时间(秒)'),
236
+ maxRounds: koishi_1.Schema.number().min(0).default(10).description('最大接龙回合数(0为无限)'),
237
+ botParticipate: koishi_1.Schema.boolean().default(false).description('机器人是否参与接龙'),
238
+ rewardScore: koishi_1.Schema.number().min(0).default(1).description('接龙成功奖励分数'),
239
+ messages: koishi_1.Schema.object({
240
+ start: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.start).description('游戏开始提示\n{0}-总回合数'),
241
+ stop: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.stop).description('游戏停止提示'),
242
+ notStarted: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.notStarted).description('游戏未开始提示'),
243
+ joinUsage: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.joinUsage).description('参与用法提示'),
244
+ apiError: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.apiError).description('API错误提示'),
245
+ botTurn: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.botTurn).description('机器人回合提示\n{0}-成语'),
246
+ botWin: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.botWin).description('机器人赢提示'),
247
+ autoPlayTooMany: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.autoPlayTooMany).description('自动参与次数过多提示\n{0}-最大次数'),
248
+ notIdiom: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.notIdiom).description('非成语提示'),
249
+ correct: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.correct).description('接龙成功提示'),
250
+ wrong: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.wrong).description('接龙失败提示'),
251
+ roundEnd: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.roundEnd).description('回合结束提示\n{0}-当前回合, {1}-剩余回合'),
252
+ gameEnd: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.gameEnd).description('游戏结束提示'),
253
+ rankTitle: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.rankTitle).description('本局排行榜标题'),
254
+ rankEmpty: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.rankEmpty).description('本局排行榜为空提示'),
255
+ disabled: koishi_1.Schema.string().default(defaultMessages.chengyuJielong.disabled).description('功能禁用提示'),
256
+ autoStop: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('自动停止提示'),
257
+ }).description('💬 成语接龙消息配置'),
258
+ }).description('🐉 成语接龙配置'),
259
+ }),
260
+ koishi_1.Schema.object({
261
+ calc24: koishi_1.Schema.object({
262
+ totalRounds: koishi_1.Schema.number().min(1).default(5).description('总回合数'),
263
+ showRank: koishi_1.Schema.boolean().default(true).description('游戏结束后显示本局排行榜'),
264
+ defaultDifficulty: koishi_1.Schema.union(['简单', '中等', '困难']).default('中等').description('默认难度'),
265
+ difficultyLevels: koishi_1.Schema.object({
266
+ easy: koishi_1.Schema.object({
267
+ min: koishi_1.Schema.number().default(1).description('最小值'),
268
+ max: koishi_1.Schema.number().default(8).description('最大值'),
269
+ }).description('简单难度数字范围'),
270
+ medium: koishi_1.Schema.object({
271
+ min: koishi_1.Schema.number().default(1).description('最小值'),
272
+ max: koishi_1.Schema.number().default(10).description('最大值'),
273
+ }).description('中等难度数字范围'),
274
+ hard: koishi_1.Schema.object({
275
+ min: koishi_1.Schema.number().default(1).description('最小值'),
276
+ max: koishi_1.Schema.number().default(13).description('最大值'),
277
+ }).description('困难难度数字范围'),
278
+ }).description('各难度数字范围配置'),
279
+ autoStopInactiveTime: koishi_1.Schema.number().min(0).default(60).description('游戏无操作自动停止时间(秒)'),
280
+ rewardScore: koishi_1.Schema.number().min(0).default(1).description('答对奖励分数'),
281
+ messages: koishi_1.Schema.object({
282
+ start: koishi_1.Schema.string().default(defaultMessages.calc24.start).description('游戏开始提示\n{0}-总回合数, {1}-难度'),
283
+ stop: koishi_1.Schema.string().default(defaultMessages.calc24.stop).description('游戏停止提示'),
284
+ notStarted: koishi_1.Schema.string().default(defaultMessages.calc24.notStarted).description('游戏未开始提示'),
285
+ generate: koishi_1.Schema.string().default(defaultMessages.calc24.generate).description('生成题目提示\n{0}-当前回合, {1}-难度, {2}-数字列表'),
286
+ correct: koishi_1.Schema.string().default(defaultMessages.calc24.correct).description('答对提示'),
287
+ wrong: koishi_1.Schema.string().default(defaultMessages.calc24.wrong).description('答错提示'),
288
+ solved: koishi_1.Schema.string().default(defaultMessages.calc24.solved).description('已解决提示'),
289
+ roundEnd: koishi_1.Schema.string().default(defaultMessages.calc24.roundEnd).description('回合结束提示\n{0}-当前回合, {1}-剩余回合'),
290
+ gameEnd: koishi_1.Schema.string().default(defaultMessages.calc24.gameEnd).description('游戏结束提示'),
291
+ rankTitle: koishi_1.Schema.string().default(defaultMessages.calc24.rankTitle).description('本局排行榜标题'),
292
+ rankEmpty: koishi_1.Schema.string().default(defaultMessages.calc24.rankEmpty).description('本局排行榜为空提示'),
293
+ disabled: koishi_1.Schema.string().default(defaultMessages.calc24.disabled).description('功能禁用提示'),
294
+ autoStop: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('自动停止提示'),
295
+ }).description('💬 算24点消息配置'),
296
+ }).description('🧮 算24点配置'),
297
+ }),
298
+ koishi_1.Schema.object({
299
+ apiConfig: koishi_1.Schema.object({
300
+ timeout: koishi_1.Schema.number().default(5000).description('API请求超时时间(毫秒)'),
301
+ }).description('🌐 API接口配置'),
302
+ }),
303
+ koishi_1.Schema.object({
304
+ commonMessages: koishi_1.Schema.object({
305
+ gameRunning: koishi_1.Schema.string().default(defaultMessages.common.gameRunning).description('游戏运行中提示'),
306
+ gameStoppedByInactive: koishi_1.Schema.string().default("太久没人玩啦,比赛自动结束~").description('无操作停止提示'),
307
+ paramError: koishi_1.Schema.string().default("❌ 参数错误!请检查输入格式").description('参数错误提示'),
308
+ }).description('💬 通用消息配置'),
309
+ }),
310
+ ]);
84
311
  const logger = new koishi_1.Logger('game-mini');
85
312
  const gameStates = new Map();
86
313
  const getSessionKey = (s) => s.channelId ? `g:${s.channelId}` : `p:${s.userId}`;
@@ -89,372 +316,30 @@ const getIntUserId = (session) => {
89
316
  const hash = userIdStr.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
90
317
  return hash || 1000000;
91
318
  };
92
- const getPlayerData = (session) => {
93
- const safeUserId = session.userId || 'unknown_user';
94
- return {
95
- platform: session.platform,
96
- userId: safeUserId,
97
- name: session.username || safeUserId || '未知用户',
98
- score: 0,
99
- correctCount: 0
100
- };
101
- };
102
- const checkGameRunning = (s, t) => {
103
- if (t !== 'guessNumber' && s.guessNumber.started)
104
- return true;
105
- if (t !== 'wzHero' && s.wzHero.started)
106
- return true;
107
- if (t !== 'chengyuImage' && s.chengyuImage.started)
108
- return true;
109
- if (t !== 'chengyuJielong' && s.chengyuJielong.started)
110
- return true;
111
- if (t !== 'calc24' && s.calc24.started)
112
- return true;
113
- if (t !== 'passwordLock' && s.passwordLock.started)
114
- return true;
115
- return false;
116
- };
117
- const clearGameTimer = (state) => {
118
- if (state.stopTimer)
119
- clearTimeout(state.stopTimer);
120
- if (state.autoPlayTimer)
121
- clearTimeout(state.autoPlayTimer);
122
- };
123
- const clearAllTimers = (st) => {
124
- clearGameTimer(st.guessNumber);
125
- clearGameTimer(st.wzHero);
126
- clearGameTimer(st.chengyuImage);
127
- clearGameTimer(st.chengyuJielong);
128
- clearGameTimer(st.calc24);
129
- clearGameTimer(st.passwordLock);
130
- };
131
- const initState = (key, c) => {
132
- const s = {
133
- guessNumber: {
134
- started: false,
135
- totalRounds: c.guessNumber.totalRounds,
136
- currentRound: 0,
137
- players: {},
138
- participants: [],
139
- target: 0,
140
- currentMin: c.guessNumber.min,
141
- currentMax: c.guessNumber.max,
142
- botGuess: []
143
- },
144
- wzHero: {
145
- started: false,
146
- totalRounds: c.wzHero.totalRounds,
147
- currentRound: 0,
148
- players: {},
149
- participants: [],
150
- difficulty: c.wzHero.defaultDifficulty,
151
- botAnswered: false,
152
- lastHint: '',
153
- currentHeroId: '',
154
- currentAnswer: ''
155
- },
156
- chengyuImage: {
157
- started: false,
158
- totalRounds: c.chengyuImage.totalRounds,
159
- currentRound: 0,
160
- players: {},
161
- participants: [],
162
- currentId: '',
163
- currentPage: 1,
164
- options: [],
165
- answer: ''
166
- },
167
- chengyuJielong: {
168
- started: false,
169
- totalRounds: c.chengyuJielong.totalRounds,
170
- currentRound: 0,
171
- players: {},
172
- participants: [],
173
- lastChar: '',
174
- botTurn: true,
175
- autoPlayCount: 0,
176
- hasTriggeredAutoPlay: false,
177
- lastActiveTime: Date.now()
178
- },
179
- calc24: {
180
- started: false,
181
- totalRounds: c.calc24.totalRounds,
182
- currentRound: 0,
183
- players: {},
184
- participants: [],
185
- difficulty: c.calc24.defaultDifficulty,
186
- numbers: [],
187
- playerAnswer: '',
188
- solved: false,
189
- availableNumbers: []
190
- },
191
- passwordLock: {
192
- started: false,
193
- totalRounds: 1,
194
- currentRound: 0,
195
- players: {},
196
- participants: [],
197
- password: '',
198
- playerGuess: '',
199
- guessTimes: 0,
200
- maxGuessTimes: c.passwordLock.maxGuessTimes,
201
- hints: [],
202
- solved: false
203
- }
204
- };
205
- gameStates.set(key, s);
206
- return s;
207
- };
208
- const isFourCharIdiom = (text) => {
209
- const t = text.trim();
210
- return /^[\u4e00-\u9fa5]{4}$/.test(t);
211
- };
212
- const generateRankText = (players) => {
213
- const playerList = Object.values(players);
214
- if (playerList.length === 0) {
215
- return '🏆 排行榜 🏆\n暂无参与记录~';
216
- }
217
- const sortedPlayers = playerList.sort((a, b) => b.score - a.score);
218
- let rankText = '🏆 排行榜 🏆\n';
219
- sortedPlayers.forEach((player, index) => {
220
- rankText += `${index + 1}. ${player.name} - 得分:${player.score}分(答对${player.correctCount}题)\n`;
221
- });
222
- return rankText.trim();
223
- };
224
- const clearGameData = (gameState) => {
225
- gameState.players = {};
226
- gameState.participants = [];
227
- gameState.currentRound = 0;
228
- gameState.started = false;
229
- clearGameTimer(gameState);
230
- };
231
- const addScoreToOthers = (players, excludePlayerKey) => {
232
- Object.keys(players).forEach(playerKey => {
233
- if (playerKey !== excludePlayerKey) {
234
- players[playerKey].score += 1;
235
- }
319
+ async function apply(ctx, cfg) {
320
+ ctx.model.extend('game_mini_player', {
321
+ id: 'unsigned',
322
+ guildId: 'string',
323
+ platform: 'string',
324
+ userId: 'string',
325
+ name: 'string',
326
+ score: 'integer',
327
+ correctCount: 'integer',
328
+ playCount: 'integer',
329
+ lastGameTime: 'unsigned'
330
+ }, {
331
+ primary: 'id',
332
+ autoInc: true,
333
+ unique: [['guildId', 'platform', 'userId']]
236
334
  });
237
- };
238
- const setupAutoStop = (session, state, cfg, gameType, endMsg, showRank) => {
239
- clearGameTimer(state);
240
- let inactiveTime = 30;
241
- if (gameType === 'guessNumber')
242
- inactiveTime = cfg.guessNumber.autoStopInactiveTime;
243
- else if (gameType === 'wzHero')
244
- inactiveTime = cfg.wzHero.autoStopInactiveTime;
245
- else if (gameType === 'chengyuImage')
246
- inactiveTime = cfg.chengyuImage.autoStopInactiveTime;
247
- else if (gameType === 'chengyuJielong')
248
- inactiveTime = cfg.chengyuJielong.autoStopInactiveTime;
249
- else if (gameType === 'calc24')
250
- inactiveTime = cfg.calc24.autoStopInactiveTime;
251
- else if (gameType === 'passwordLock')
252
- inactiveTime = cfg.passwordLock.autoStopInactiveTime;
253
- if (inactiveTime <= 0)
254
- return;
255
- state.stopTimer = setTimeout(() => {
256
- clearGameData(state);
257
- session.send(endMsg);
258
- if (showRank && session.channelId) {
259
- session.send(generateRankText(state.players));
260
- }
261
- }, inactiveTime * 1000);
262
- };
263
- const calculate24 = (numbers) => {
264
- if (numbers.length === 1)
265
- return Math.abs(numbers[0] - 24) < 0.001;
266
- for (let i = 0; i < numbers.length; i++) {
267
- for (let j = 0; j < numbers.length; j++) {
268
- if (i === j)
269
- continue;
270
- const rest = [];
271
- for (let k = 0; k < numbers.length; k++) {
272
- if (k !== i && k !== j)
273
- rest.push(numbers[k]);
274
- }
275
- const a = numbers[i];
276
- const b = numbers[j];
277
- if (calculate24([...rest, a + b]))
278
- return true;
279
- if (calculate24([...rest, a - b]))
280
- return true;
281
- if (calculate24([...rest, b - a]))
282
- return true;
283
- if (calculate24([...rest, a * b]))
284
- return true;
285
- if (b !== 0 && calculate24([...rest, a / b]))
286
- return true;
287
- if (a !== 0 && calculate24([...rest, b / a]))
288
- return true;
289
- }
290
- }
291
- return false;
292
- };
293
- const generateSolvable24Numbers = (min, max) => {
294
- const maxAttempts = 1000;
295
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
296
- const numbers = [
297
- koishi_1.Random.int(min, max + 1),
298
- koishi_1.Random.int(min, max + 1),
299
- koishi_1.Random.int(min, max + 1),
300
- koishi_1.Random.int(min, max + 1)
301
- ];
302
- if (calculate24([...numbers])) {
303
- return numbers;
304
- }
305
- }
306
- return [6, 4, 3, 1];
307
- };
308
- const generatePasswordHint = (password, guess) => {
309
- let correctPos = 0;
310
- let correctNum = 0;
311
- const passwordArr = password.split('');
312
- const guessArr = guess.split('');
313
- const passwordUsed = [false, false, false, false];
314
- const guessUsed = [false, false, false, false];
315
- for (let i = 0; i < 4; i++) {
316
- if (passwordArr[i] === guessArr[i]) {
317
- correctPos++;
318
- passwordUsed[i] = true;
319
- guessUsed[i] = true;
320
- }
321
- }
322
- for (let i = 0; i < 4; i++) {
323
- if (guessUsed[i])
324
- continue;
325
- for (let j = 0; j < 4; j++) {
326
- if (!passwordUsed[j] && passwordArr[j] === guessArr[i]) {
327
- correctNum++;
328
- passwordUsed[j] = true;
329
- break;
330
- }
331
- }
332
- }
333
- return `提示:${correctPos}个数字位置正确,${correctNum}个数字正确但位置错误`;
334
- };
335
- const evaluateExpression = (expr) => {
336
- try {
337
- const cleanExpr = expr.replace(/[^\d\+\-\*\/\(\)\[\]\{\}\s]/g, '');
338
- const normalizedExpr = cleanExpr.replace(/[\[\{]/g, '(').replace(/[\]\}]/g, ')');
339
- const func = new Function('return ' + normalizedExpr);
340
- const result = func();
341
- if (typeof result === 'number' && isFinite(result)) {
342
- return result;
343
- }
344
- return null;
345
- }
346
- catch {
347
- return null;
348
- }
349
- };
350
- function apply(ctx, cfg) {
351
335
  const d = {
352
- guessNumber: {
353
- usage: "用法错误!正确用法:猜数字 开始 | 猜数字 [数字] | 猜数字 结束",
354
- start: "猜数字比赛开始!本次共 {0} 回合~",
355
- stop: "猜数字比赛已停止",
356
- outOfRange: "数字超出当前范围 [{0}-{1}],请重新输入!",
357
- tooSmall: "猜小啦!当前范围更新为 [{0}-{1}]",
358
- tooBig: "猜大啦!当前范围更新为 [{0}-{1}]",
359
- correct: "恭喜你猜中数字!本轮你不得分,其他参与者各得1分~",
360
- roundEnd: "第 {0} 回合结束!剩余回合:{1}",
361
- gameEnd: "🎉 猜数字比赛结束!🎉",
362
- rankTitle: "🏆 排行榜 🏆",
363
- rankEmpty: "暂无参与记录~",
364
- disabled: "猜数字功能已关闭,请联系管理员开启",
365
- autoStop: "游戏因长时间无人操作,已自动结束"
366
- },
367
- wzHero: {
368
- start: "猜王者英雄开始!本次共 {0} 回合~当前难度:{1}",
369
- startUsage: "用法错误!正确用法:猜王者英雄 开始 | 猜王者英雄 [答案] | 猜王者英雄 提示 | 猜王者英雄 结束",
370
- stop: "猜王者英雄比赛已停止",
371
- notStarted: "猜王者英雄比赛尚未开始,请输入 猜王者英雄 开始 开始游戏",
372
- hint: "提示",
373
- apiError: "API请求失败,请稍后再试",
374
- correct: "答对啦!你获得1分~",
375
- wrong: "答错啦~正确答案是:{0},你不得分",
376
- roundEnd: "第 {0} 回合结束!剩余回合:{1}",
377
- gameEnd: "🎉 猜王者英雄比赛结束!🎉",
378
- rankTitle: "🏆 排行榜 🏆",
379
- rankEmpty: "暂无参与记录~",
380
- disabled: "猜王者英雄功能已关闭,请联系管理员开启",
381
- autoStop: "游戏因长时间无人操作,已自动结束"
382
- },
383
- chengyuImage: {
384
- start: "看图猜成语比赛开始!本次共 {0} 回合~当前提示级别:{1}",
385
- stop: "看图猜成语比赛已停止",
386
- submitUsage: "请直接输入 看图猜成语 [答案],或输入 看图猜成语 提示 获取线索",
387
- notStarted: "看图猜成语比赛尚未开始,请输入 看图猜成语 开始 开始游戏",
388
- next: "第 {0} 题来啦!",
389
- hintGet: "【提示】{0}",
390
- hintError: "获取提示失败,请稍后再试",
391
- apiError: "API请求失败,请稍后再试",
392
- correct: "答对啦!你获得1分~",
393
- wrong: "答错啦~正确答案是:{0},你不得分",
394
- roundEnd: "第 {0} 回合结束!剩余回合:{1}",
395
- gameEnd: "🎉 看图猜成语比赛结束!🎉",
396
- rankTitle: "🏆 排行榜 🏆",
397
- rankEmpty: "暂无参与记录~",
398
- disabled: "看图猜成语功能已关闭,请联系管理员开启",
399
- autoStop: "游戏因长时间无人操作,已自动结束"
400
- },
401
- chengyuJielong: {
402
- start: "成语接龙比赛开始!本次共 {0} 回合~我先来~",
403
- stop: "成语接龙比赛已停止",
404
- notStarted: "成语接龙比赛尚未开始,请输入 成语接龙 开始 开始游戏",
405
- joinUsage: "请直接发送 成语接龙 [成语] 参与接龙",
406
- apiError: "API请求失败,请稍后再试",
407
- botTurn: "该我了!我接:{0}({1})\n释义:{2}",
408
- botWin: "哈哈我接不上了!本轮结束~",
409
- autoPlayTooMany: "我已经主动参与 {0} 次啦,不再主动接啦~",
410
- gameInactiveStop: "太久没人玩啦,比赛自动结束~",
411
- notIdiom: "请发送四字成语参与游戏~",
412
- correct: "接龙成功!你获得1分~",
413
- wrong: "接龙失败!你不得分,其他参与者各得1分~",
414
- roundEnd: "第 {0} 回合结束!剩余回合:{1}",
415
- gameEnd: "🎉 成语接龙比赛结束!🎉",
416
- rankTitle: "🏆 排行榜 🏆",
417
- rankEmpty: "暂无参与记录~",
418
- disabled: "成语接龙功能已关闭,请联系管理员开启",
419
- autoStop: "游戏因长时间无人操作,已自动结束"
420
- },
421
- calc24: {
422
- start: "算24点游戏开始!本次共 {0} 回合~当前难度:{1}",
423
- stop: "算24点游戏已停止",
424
- notStarted: "算24点游戏尚未开始,请输入 算24点 开始 开始游戏",
425
- generate: "📝 第 {0} 题({1}):用 {2} 通过加减乘除和括号算出24!",
426
- correct: "答对啦!你获得1分~",
427
- wrong: "答错啦~",
428
- impossible: "这组数无法算出24!本题作废,换一组数字~",
429
- solved: "这组数已经被答对啦,换一组数字~",
430
- roundEnd: "第 {0} 回合结束!剩余回合:{1}",
431
- gameEnd: "🎉 算24点游戏结束!🎉",
432
- rankTitle: "🏆 排行榜 🏆",
433
- rankEmpty: "暂无参与记录~",
434
- disabled: "算24点功能已关闭,请联系管理员开启",
435
- autoStop: "游戏因长时间无人操作,已自动结束"
436
- },
437
- passwordLock: {
438
- start: "猜密码游戏开始!密码为4位数字,你有 {0} 次猜测机会~",
439
- stop: "猜密码游戏已停止",
440
- notStarted: "猜密码游戏尚未开始,请输入 猜密码 开始 开始游戏",
441
- guess: "你猜测的密码是:{0},这是第 {1} 次猜测",
442
- correct: "🎉 恭喜!你猜对了密码 {0}!总共猜测了 {1} 次,获得10分~",
443
- wrong: "密码错误!{0}",
444
- solved: "密码已经被猜出来啦,游戏结束~",
445
- noChance: "❌ 没有猜测机会了!正确密码是:{0}~",
446
- invalidPassword: "无效的密码!请输入4位数字",
447
- gameEnd: "🎉 猜密码游戏结束!🎉",
448
- rankTitle: "🏆 排行榜 🏆",
449
- rankEmpty: "暂无参与记录~",
450
- disabled: "猜密码功能已关闭,请联系管理员开启",
451
- autoStop: "游戏因长时间无人操作,已自动结束"
452
- },
453
- common: {
454
- gameRunning: "当前已有游戏在运行中,请先结束当前游戏后再开始新游戏!",
455
- gameStoppedByInactive: "游戏因长时间无人操作,已自动结束",
456
- paramError: "参数错误!请检查输入格式"
457
- }
336
+ guessNumber: cfg.guessNumber.messages,
337
+ wzHero: cfg.wzHero.messages,
338
+ chengyuImage: cfg.chengyuImage.messages,
339
+ chengyuJielong: cfg.chengyuJielong.messages,
340
+ calc24: cfg.calc24.messages,
341
+ rank: cfg.rank.messages,
342
+ common: cfg.commonMessages
458
343
  };
459
344
  try {
460
345
  const p = path_1.default.join(__dirname, './locales/zh-CN.yml');
@@ -467,6 +352,318 @@ function apply(ctx, cfg) {
467
352
  ctx.i18n.define('zh-CN', d);
468
353
  }
469
354
  const isPrivate = (s) => !s.channelId;
355
+ const canPlayPrivate = (game) => {
356
+ if (game === 'guessNumber')
357
+ return cfg.privateGame.enableNumberGuess;
358
+ if (game === 'wzHero')
359
+ return cfg.privateGame.enableWzHero;
360
+ if (game === 'chengyuImage')
361
+ return cfg.privateGame.enableChengyuImage;
362
+ if (game === 'chengyuJielong')
363
+ return cfg.privateGame.enableChengyuJielong;
364
+ if (game === 'calc24')
365
+ return cfg.privateGame.enableCalc24;
366
+ return false;
367
+ };
368
+ const getPlayerData = async (session) => {
369
+ if (!session.channelId) {
370
+ return {
371
+ platform: session.platform,
372
+ userId: session.userId || 'unknown_user',
373
+ name: session.username || session.userId || '未知用户',
374
+ score: 0,
375
+ correctCount: 0,
376
+ playCount: 0,
377
+ lastGameTime: 0
378
+ };
379
+ }
380
+ const guildId = session.channelId;
381
+ const platform = session.platform;
382
+ const userId = session.userId || 'unknown_user';
383
+ const name = session.username || userId;
384
+ let player = await ctx.database.get('game_mini_player', {
385
+ guildId,
386
+ platform,
387
+ userId
388
+ });
389
+ if (!player.length) {
390
+ const newPlayer = {
391
+ guildId,
392
+ platform,
393
+ userId,
394
+ name,
395
+ score: 0,
396
+ correctCount: 0,
397
+ playCount: 0,
398
+ lastGameTime: 0
399
+ };
400
+ const id = await ctx.database.create('game_mini_player', newPlayer);
401
+ return {
402
+ guildId,
403
+ platform,
404
+ userId,
405
+ name,
406
+ score: 0,
407
+ correctCount: 0,
408
+ playCount: 0,
409
+ lastGameTime: 0
410
+ };
411
+ }
412
+ return player[0];
413
+ };
414
+ const savePlayerData = async (session, playerData) => {
415
+ if (!session.channelId)
416
+ return;
417
+ await ctx.database.set('game_mini_player', { guildId: session.channelId, platform: session.platform, userId: session.userId }, {
418
+ name: playerData.name,
419
+ score: playerData.score,
420
+ correctCount: playerData.correctCount,
421
+ playCount: playerData.playCount,
422
+ lastGameTime: playerData.lastGameTime
423
+ });
424
+ };
425
+ const updatePlayerPlayCount = async (session) => {
426
+ if (!session.channelId)
427
+ return;
428
+ const player = await getPlayerData(session);
429
+ player.playCount += 1;
430
+ player.lastGameTime = Date.now();
431
+ await savePlayerData(session, player);
432
+ };
433
+ const generateTotalRankText = async (session) => {
434
+ if (!session.channelId)
435
+ return cfg.rank.messages.empty;
436
+ const players = await ctx.database.get('game_mini_player', { guildId: session.channelId });
437
+ if (players.length === 0) {
438
+ return cfg.rank.messages.empty;
439
+ }
440
+ const sortedPlayers = players.sort((a, b) => b.score - a.score);
441
+ let rankText = cfg.rank.messages.title + '\n';
442
+ const displayCount = Math.min(cfg.rank.maxDisplay, sortedPlayers.length);
443
+ for (let i = 0; i < displayCount; i++) {
444
+ const player = sortedPlayers[i];
445
+ rankText += cfg.rank.messages.playerInfo
446
+ .replace('{0}', String(i + 1))
447
+ .replace('{1}', player.name)
448
+ .replace('{2}', String(player.score))
449
+ .replace('{3}', String(player.correctCount))
450
+ .replace('{4}', String(player.playCount)) + '\n';
451
+ }
452
+ if (cfg.rank.messages.showTotalStats) {
453
+ const totalScore = players.reduce((sum, p) => sum + p.score, 0);
454
+ const totalCorrect = players.reduce((sum, p) => sum + p.correctCount, 0);
455
+ const totalPlay = players.reduce((sum, p) => sum + p.playCount, 0);
456
+ rankText += cfg.rank.messages.totalStats
457
+ .replace('{0}', String(players.length))
458
+ .replace('{1}', String(totalScore))
459
+ .replace('{2}', String(totalCorrect))
460
+ .replace('{3}', String(totalPlay));
461
+ }
462
+ return rankText;
463
+ };
464
+ const checkGameRunning = (s, t) => {
465
+ if (t !== 'guessNumber' && s.guessNumber.started)
466
+ return true;
467
+ if (t !== 'wzHero' && s.wzHero.started)
468
+ return true;
469
+ if (t !== 'chengyuImage' && s.chengyuImage.started)
470
+ return true;
471
+ if (t !== 'chengyuJielong' && s.chengyuJielong.started)
472
+ return true;
473
+ if (t !== 'calc24' && s.calc24.started)
474
+ return true;
475
+ return false;
476
+ };
477
+ const clearGameTimer = (state) => {
478
+ if (state.stopTimer)
479
+ clearTimeout(state.stopTimer);
480
+ if (state.autoPlayTimer)
481
+ clearTimeout(state.autoPlayTimer);
482
+ };
483
+ const clearAllTimers = (st) => {
484
+ clearGameTimer(st.guessNumber);
485
+ clearGameTimer(st.wzHero);
486
+ clearGameTimer(st.chengyuImage);
487
+ clearGameTimer(st.chengyuJielong);
488
+ clearGameTimer(st.calc24);
489
+ };
490
+ const initState = (key) => {
491
+ const s = {
492
+ guessNumber: {
493
+ started: false,
494
+ totalRounds: cfg.guessNumber.totalRounds,
495
+ currentRound: 0,
496
+ players: {},
497
+ participants: [],
498
+ target: 0,
499
+ currentMin: cfg.guessNumber.min,
500
+ currentMax: cfg.guessNumber.max,
501
+ botGuess: []
502
+ },
503
+ wzHero: {
504
+ started: false,
505
+ totalRounds: cfg.wzHero.totalRounds,
506
+ currentRound: 0,
507
+ players: {},
508
+ participants: [],
509
+ difficulty: cfg.wzHero.defaultDifficulty,
510
+ botAnswered: false,
511
+ lastHint: '',
512
+ currentHeroId: '',
513
+ currentAnswer: ''
514
+ },
515
+ chengyuImage: {
516
+ started: false,
517
+ totalRounds: cfg.chengyuImage.totalRounds,
518
+ currentRound: 0,
519
+ players: {},
520
+ participants: [],
521
+ currentId: '',
522
+ currentPage: 1,
523
+ options: [],
524
+ answer: ''
525
+ },
526
+ chengyuJielong: {
527
+ started: false,
528
+ totalRounds: cfg.chengyuJielong.totalRounds,
529
+ currentRound: 0,
530
+ players: {},
531
+ participants: [],
532
+ lastChar: '',
533
+ botTurn: true,
534
+ autoPlayCount: 0,
535
+ hasTriggeredAutoPlay: false,
536
+ lastActiveTime: Date.now(),
537
+ jielongCount: 0
538
+ },
539
+ calc24: {
540
+ started: false,
541
+ totalRounds: cfg.calc24.totalRounds,
542
+ currentRound: 0,
543
+ players: {},
544
+ participants: [],
545
+ difficulty: cfg.calc24.defaultDifficulty,
546
+ numbers: [],
547
+ playerAnswer: '',
548
+ solved: false,
549
+ availableNumbers: []
550
+ }
551
+ };
552
+ gameStates.set(key, s);
553
+ return s;
554
+ };
555
+ const isFourCharIdiom = (text) => {
556
+ const t = text.trim();
557
+ return /^[\u4e00-\u9fa5]{4}$/.test(t);
558
+ };
559
+ const generateGameRankText = (players, rankTitle, rankEmpty) => {
560
+ const playerList = Object.values(players);
561
+ if (playerList.length === 0) {
562
+ return `${rankTitle}\n${rankEmpty}`;
563
+ }
564
+ const sortedPlayers = playerList.sort((a, b) => b.score - a.score);
565
+ let rankText = `${rankTitle}\n`;
566
+ sortedPlayers.forEach((player, index) => {
567
+ rankText += `${index + 1}. ${player.name} - 得分:${player.score}分\n`;
568
+ });
569
+ return rankText.trim();
570
+ };
571
+ const clearGameData = (gameState, showRank = false, session, rankTitle, rankEmpty) => {
572
+ if (showRank && session && session.channelId && rankTitle && rankEmpty) {
573
+ session.send(generateGameRankText(gameState.players, rankTitle, rankEmpty));
574
+ }
575
+ gameState.players = {};
576
+ gameState.participants = [];
577
+ gameState.currentRound = 0;
578
+ gameState.started = false;
579
+ clearGameTimer(gameState);
580
+ };
581
+ const setupAutoStop = (session, state, gameType, endMsg, showRank, rankTitle, rankEmpty) => {
582
+ clearGameTimer(state);
583
+ let inactiveTime = 60;
584
+ if (gameType === 'guessNumber')
585
+ inactiveTime = cfg.guessNumber.autoStopInactiveTime;
586
+ else if (gameType === 'wzHero')
587
+ inactiveTime = cfg.wzHero.autoStopInactiveTime;
588
+ else if (gameType === 'chengyuImage')
589
+ inactiveTime = cfg.chengyuImage.autoStopInactiveTime;
590
+ else if (gameType === 'chengyuJielong')
591
+ inactiveTime = cfg.chengyuJielong.autoStopInactiveTime;
592
+ else if (gameType === 'calc24')
593
+ inactiveTime = cfg.calc24.autoStopInactiveTime;
594
+ if (inactiveTime <= 0)
595
+ return;
596
+ state.stopTimer = setTimeout(() => {
597
+ clearGameData(state, showRank, session, rankTitle, rankEmpty);
598
+ session.send(endMsg);
599
+ }, inactiveTime * 1000);
600
+ };
601
+ const calculate24 = (numbers) => {
602
+ if (numbers.length === 1)
603
+ return Math.abs(numbers[0] - 24) < 0.001;
604
+ for (let i = 0; i < numbers.length; i++) {
605
+ for (let j = 0; j < numbers.length; j++) {
606
+ if (i === j)
607
+ continue;
608
+ const rest = [];
609
+ for (let k = 0; k < numbers.length; k++) {
610
+ if (k !== i && k !== j)
611
+ rest.push(numbers[k]);
612
+ }
613
+ const a = numbers[i];
614
+ const b = numbers[j];
615
+ if (calculate24([...rest, a + b]))
616
+ return true;
617
+ if (calculate24([...rest, a - b]))
618
+ return true;
619
+ if (calculate24([...rest, b - a]))
620
+ return true;
621
+ if (calculate24([...rest, a * b]))
622
+ return true;
623
+ if (b !== 0 && calculate24([...rest, a / b]))
624
+ return true;
625
+ if (a !== 0 && calculate24([...rest, b / a]))
626
+ return true;
627
+ }
628
+ }
629
+ return false;
630
+ };
631
+ const generateSolvable24Numbers = (min, max) => {
632
+ const maxAttempts = 1000;
633
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
634
+ const numbers = [
635
+ koishi_1.Random.int(min, max + 1),
636
+ koishi_1.Random.int(min, max + 1),
637
+ koishi_1.Random.int(min, max + 1),
638
+ koishi_1.Random.int(min, max + 1)
639
+ ];
640
+ if (calculate24([...numbers])) {
641
+ return numbers;
642
+ }
643
+ }
644
+ return [6, 4, 3, 1];
645
+ };
646
+ const evaluateExpression = (expr) => {
647
+ try {
648
+ let cleanExpr = expr.replace(/\s+/g, '');
649
+ cleanExpr = cleanExpr.replace(/[×xX]/g, '*');
650
+ cleanExpr = cleanExpr.replace(/[÷/]/g, '/');
651
+ cleanExpr = cleanExpr.replace(/\/\//g, '/');
652
+ if (!/^[\d\+\-\*\/\(\)\[\]\{\}]+$/.test(cleanExpr)) {
653
+ return null;
654
+ }
655
+ const normalizedExpr = cleanExpr.replace(/[\[\{]/g, '(').replace(/[\]\}]/g, ')');
656
+ const func = new Function('return ' + normalizedExpr);
657
+ const result = func();
658
+ if (typeof result === 'number' && isFinite(result)) {
659
+ return result;
660
+ }
661
+ return null;
662
+ }
663
+ catch {
664
+ return null;
665
+ }
666
+ };
470
667
  const refreshActive = (st) => {
471
668
  st.chengyuJielong.lastActiveTime = Date.now();
472
669
  };
@@ -476,7 +673,7 @@ function apply(ctx, cfg) {
476
673
  doAutoPlay(session, key, st);
477
674
  return;
478
675
  }
479
- if (!cfg.chengyuJielong.botParticipateInGroup)
676
+ if (!cfg.chengyuJielong.botParticipate)
480
677
  return;
481
678
  if (st.chengyuJielong.hasTriggeredAutoPlay)
482
679
  return;
@@ -491,10 +688,9 @@ function apply(ctx, cfg) {
491
688
  if (st.chengyuJielong.hasTriggeredAutoPlay)
492
689
  return;
493
690
  if (st.chengyuJielong.autoPlayCount >= cfg.chengyuJielong.autoPlayMaxCount) {
494
- session.send(d.chengyuJielong.autoPlayTooMany.replace('{0}', String(cfg.chengyuJielong.autoPlayMaxCount)));
495
691
  st.chengyuJielong.hasTriggeredAutoPlay = true;
496
692
  gameStates.set(key, st);
497
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
693
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
498
694
  return;
499
695
  }
500
696
  st.chengyuJielong.hasTriggeredAutoPlay = true;
@@ -516,8 +712,9 @@ function apply(ctx, cfg) {
516
712
  let m = '';
517
713
  if (dt.code === 200 && dt.data?.system) {
518
714
  const sys = dt.data.system;
519
- m = d.chengyuJielong.botTurn.replace('{0}', sys.idiom).replace('{1}', sys.pinyin).replace('{2}', sys.meaning);
715
+ m = d.chengyuJielong.botTurn.replace('{0}', sys.idiom);
520
716
  st.chengyuJielong.lastChar = dt.data.current_char || '';
717
+ st.chengyuJielong.jielongCount += 1;
521
718
  }
522
719
  else {
523
720
  m = dt.msg || d.chengyuJielong.botWin;
@@ -528,7 +725,7 @@ function apply(ctx, cfg) {
528
725
  await session.send(m);
529
726
  await session.send(d.chengyuJielong.gameEnd);
530
727
  if (cfg.chengyuJielong.showRank && !isPrivate(session)) {
531
- const rankText = generateRankText(st.chengyuJielong.players);
728
+ const rankText = generateGameRankText(st.chengyuJielong.players, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
532
729
  await session.send(rankText);
533
730
  }
534
731
  clearGameData(st.chengyuJielong);
@@ -539,34 +736,63 @@ function apply(ctx, cfg) {
539
736
  m += '\n' + d.chengyuJielong.roundEnd.replace('{0}', st.chengyuJielong.currentRound.toString()).replace('{1}', (st.chengyuJielong.totalRounds - st.chengyuJielong.currentRound).toString());
540
737
  }
541
738
  }
739
+ if (cfg.chengyuJielong.maxRounds > 0 && st.chengyuJielong.jielongCount >= cfg.chengyuJielong.maxRounds) {
740
+ st.chengyuJielong.started = false;
741
+ clearAllTimers(st);
742
+ await session.send(m);
743
+ await session.send(d.chengyuJielong.gameEnd);
744
+ if (cfg.chengyuJielong.showRank && !isPrivate(session)) {
745
+ const rankText = generateGameRankText(st.chengyuJielong.players, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
746
+ await session.send(rankText);
747
+ }
748
+ clearGameData(st.chengyuJielong);
749
+ gameStates.set(key, st);
750
+ return;
751
+ }
542
752
  await session.send(m);
543
753
  }
544
754
  catch (error) {
545
755
  await session.send(d.chengyuJielong.apiError);
546
756
  }
547
757
  gameStates.set(key, st);
548
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
758
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
549
759
  };
550
760
  ctx.middleware(async (session, next) => {
551
761
  if (!session.content)
552
762
  return next();
553
763
  const key = getSessionKey(session);
554
- const st = gameStates.get(key) || initState(key, cfg);
555
- if (isPrivate(session) && !cfg.enablePrivateGame)
556
- return next();
764
+ const st = gameStates.get(key) || initState(key);
765
+ if (isPrivate(session)) {
766
+ const gameActive = st.guessNumber.started || st.wzHero.started || st.chengyuImage.started || st.chengyuJielong.started || st.calc24.started;
767
+ if (gameActive) {
768
+ if (st.guessNumber.started && !canPlayPrivate('guessNumber'))
769
+ return next();
770
+ if (st.wzHero.started && !canPlayPrivate('wzHero'))
771
+ return next();
772
+ if (st.chengyuImage.started && !canPlayPrivate('chengyuImage'))
773
+ return next();
774
+ if (st.chengyuJielong.started && !canPlayPrivate('chengyuJielong'))
775
+ return next();
776
+ if (st.calc24.started && !canPlayPrivate('calc24'))
777
+ return next();
778
+ }
779
+ }
557
780
  const content = session.content.trim();
558
781
  const playerKey = `${session.platform}_${session.userId || 'unknown'}`;
559
782
  if (cfg.enableChengyuJielong && st.chengyuJielong.started) {
560
783
  refreshActive(st);
561
784
  clearGameTimer(st.chengyuJielong);
562
785
  if (!st.chengyuJielong.players[playerKey]) {
563
- st.chengyuJielong.players[playerKey] = getPlayerData(session);
786
+ const playerData = await getPlayerData(session);
787
+ st.chengyuJielong.players[playerKey] = playerData;
564
788
  st.chengyuJielong.participants.push(playerKey);
789
+ await updatePlayerPlayCount(session);
565
790
  }
566
791
  if (!isFourCharIdiom(content)) {
567
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
792
+ await session.send(d.chengyuJielong.notIdiom);
793
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
568
794
  scheduleAutoPlay(session, key, st);
569
- return next();
795
+ return;
570
796
  }
571
797
  try {
572
798
  const intUserId = getIntUserId(session);
@@ -585,27 +811,41 @@ function apply(ctx, cfg) {
585
811
  if (dt.code === 200) {
586
812
  m = dt.msg + '\n';
587
813
  if (dt.data?.user) {
588
- st.chengyuJielong.players[playerKey].score += 1;
814
+ m += d.chengyuJielong.correct + '\n';
815
+ m += `你的成语:${dt.data.user.idiom}\n`;
816
+ st.chengyuJielong.players[playerKey].score += cfg.chengyuJielong.rewardScore;
589
817
  st.chengyuJielong.players[playerKey].correctCount += 1;
590
- m += d.chengyuJielong.correct.replace('{0}', st.chengyuJielong.players[playerKey].score.toString()) + '\n';
591
- m += `你的成语:${dt.data.user.idiom}(${dt.data.user.pinyin})\n释义:${dt.data.user.meaning}\n`;
818
+ await savePlayerData(session, st.chengyuJielong.players[playerKey]);
592
819
  }
593
820
  else {
594
- addScoreToOthers(st.chengyuJielong.players, playerKey);
595
- m += d.chengyuJielong.wrong.replace('{1}', st.chengyuJielong.players[playerKey].score.toString()) + '\n';
821
+ m += d.chengyuJielong.wrong + '\n';
596
822
  }
597
823
  if (dt.data?.system) {
598
- m += `我的接龙:${dt.data.system.idiom}(${dt.data.system.pinyin})\n释义:${dt.data.system.meaning}`;
824
+ m += `我的接龙:${dt.data.system.idiom}`;
599
825
  st.chengyuJielong.lastChar = dt.data.current_char || '';
826
+ st.chengyuJielong.jielongCount += 1;
600
827
  }
601
828
  st.chengyuJielong.currentRound += 1;
829
+ if (cfg.chengyuJielong.maxRounds > 0 && st.chengyuJielong.jielongCount >= cfg.chengyuJielong.maxRounds) {
830
+ st.chengyuJielong.started = false;
831
+ clearAllTimers(st);
832
+ await session.send(m);
833
+ await session.send(d.chengyuJielong.gameEnd);
834
+ if (cfg.chengyuJielong.showRank && !isPrivate(session)) {
835
+ const rankText = generateGameRankText(st.chengyuJielong.players, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
836
+ await session.send(rankText);
837
+ }
838
+ clearGameData(st.chengyuJielong);
839
+ gameStates.set(key, st);
840
+ return;
841
+ }
602
842
  if (st.chengyuJielong.currentRound > st.chengyuJielong.totalRounds) {
603
843
  st.chengyuJielong.started = false;
604
844
  clearAllTimers(st);
605
845
  await session.send(m);
606
846
  await session.send(d.chengyuJielong.gameEnd);
607
847
  if (cfg.chengyuJielong.showRank && !isPrivate(session)) {
608
- const rankText = generateRankText(st.chengyuJielong.players);
848
+ const rankText = generateGameRankText(st.chengyuJielong.players, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
609
849
  await session.send(rankText);
610
850
  }
611
851
  clearGameData(st.chengyuJielong);
@@ -614,20 +854,19 @@ function apply(ctx, cfg) {
614
854
  m += '\n' + d.chengyuJielong.roundEnd.replace('{0}', st.chengyuJielong.currentRound.toString()).replace('{1}', (st.chengyuJielong.totalRounds - st.chengyuJielong.currentRound).toString());
615
855
  await session.send(m);
616
856
  st.chengyuJielong.hasTriggeredAutoPlay = false;
617
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
857
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
618
858
  scheduleAutoPlay(session, key, st);
619
859
  }
620
860
  }
621
861
  else {
622
862
  m = dt.msg || '接龙失败';
623
- addScoreToOthers(st.chengyuJielong.players, playerKey);
624
- m += '\n' + d.chengyuJielong.wrong.replace('{1}', st.chengyuJielong.players[playerKey].score.toString());
863
+ m += '\n' + d.chengyuJielong.wrong;
625
864
  await session.send(m);
626
865
  }
627
866
  }
628
867
  catch (error) {
629
868
  await session.send(d.chengyuJielong.apiError);
630
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
869
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
631
870
  scheduleAutoPlay(session, key, st);
632
871
  }
633
872
  gameStates.set(key, st);
@@ -636,8 +875,10 @@ function apply(ctx, cfg) {
636
875
  if (cfg.enableChengyuImage && st.chengyuImage.started) {
637
876
  clearGameTimer(st.chengyuImage);
638
877
  if (!st.chengyuImage.players[playerKey]) {
639
- st.chengyuImage.players[playerKey] = getPlayerData(session);
878
+ const playerData = await getPlayerData(session);
879
+ st.chengyuImage.players[playerKey] = playerData;
640
880
  st.chengyuImage.participants.push(playerKey);
881
+ await updatePlayerPlayCount(session);
641
882
  }
642
883
  if (content === '提示') {
643
884
  try {
@@ -660,12 +901,13 @@ function apply(ctx, cfg) {
660
901
  catch (error) {
661
902
  await session.send(d.chengyuImage.hintError);
662
903
  }
663
- setupAutoStop(session, st.chengyuImage, cfg, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank);
904
+ setupAutoStop(session, st.chengyuImage, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
664
905
  return;
665
906
  }
666
907
  if (!isFourCharIdiom(content)) {
667
- setupAutoStop(session, st.chengyuImage, cfg, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank);
668
- return next();
908
+ await session.send('请输入4字成语');
909
+ setupAutoStop(session, st.chengyuImage, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
910
+ return;
669
911
  }
670
912
  try {
671
913
  const r = await axios_1.default.get('https://jcy.lvlong.xyz/api/api/chengyu.php', {
@@ -680,8 +922,9 @@ function apply(ctx, cfg) {
680
922
  if (dt.success) {
681
923
  let reply = '';
682
924
  if (dt.message.includes('正确') || dt.message.includes('答对')) {
683
- st.chengyuImage.players[playerKey].score += 1;
925
+ st.chengyuImage.players[playerKey].score += cfg.chengyuImage.rewardScore;
684
926
  st.chengyuImage.players[playerKey].correctCount += 1;
927
+ await savePlayerData(session, st.chengyuImage.players[playerKey]);
685
928
  reply = d.chengyuImage.correct.replace('{0}', st.chengyuImage.players[playerKey].score.toString());
686
929
  st.chengyuImage.currentRound += 1;
687
930
  if (st.chengyuImage.currentRound > st.chengyuImage.totalRounds) {
@@ -690,7 +933,7 @@ function apply(ctx, cfg) {
690
933
  await session.send(reply);
691
934
  await session.send(d.chengyuImage.gameEnd);
692
935
  if (cfg.chengyuImage.showRank && !isPrivate(session)) {
693
- const rankText = generateRankText(st.chengyuImage.players);
936
+ const rankText = generateGameRankText(st.chengyuImage.players, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
694
937
  await session.send(rankText);
695
938
  }
696
939
  clearGameData(st.chengyuImage);
@@ -720,7 +963,7 @@ function apply(ctx, cfg) {
720
963
  st.chengyuImage.started = false;
721
964
  clearGameTimer(st.chengyuImage);
722
965
  if (cfg.chengyuImage.showRank && !isPrivate(session)) {
723
- const rankText = generateRankText(st.chengyuImage.players);
966
+ const rankText = generateGameRankText(st.chengyuImage.players, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
724
967
  await session.send(rankText);
725
968
  }
726
969
  clearGameData(st.chengyuImage);
@@ -740,18 +983,20 @@ function apply(ctx, cfg) {
740
983
  catch (error) {
741
984
  await session.send(d.chengyuImage.apiError);
742
985
  }
743
- setupAutoStop(session, st.chengyuImage, cfg, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank);
986
+ setupAutoStop(session, st.chengyuImage, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
744
987
  gameStates.set(key, st);
745
988
  return;
746
989
  }
747
990
  if (cfg.enableWzHero && st.wzHero.started) {
748
991
  clearGameTimer(st.wzHero);
749
992
  if (!st.wzHero.players[playerKey]) {
750
- st.wzHero.players[playerKey] = getPlayerData(session);
993
+ const playerData = await getPlayerData(session);
994
+ st.wzHero.players[playerKey] = playerData;
751
995
  st.wzHero.participants.push(playerKey);
996
+ await updatePlayerPlayCount(session);
752
997
  }
753
998
  if (content === '结束') {
754
- clearGameData(st.wzHero);
999
+ clearGameData(st.wzHero, cfg.wzHero.showRank && !isPrivate(session), session, d.wzHero.rankTitle, d.wzHero.rankEmpty);
755
1000
  await session.send(d.wzHero.stop);
756
1001
  gameStates.set(key, st);
757
1002
  return;
@@ -765,8 +1010,9 @@ function apply(ctx, cfg) {
765
1010
  let text = `${dt.message || ''}\n${dt.hint || ''}\n剩余提示次数:${dt.remaining_hints}\n${dt.guide || ''}`;
766
1011
  text = text.replace(/\\n/g, '\n');
767
1012
  if (content !== '提示' && dt.message.includes('正确')) {
768
- st.wzHero.players[playerKey].score += 1;
1013
+ st.wzHero.players[playerKey].score += cfg.wzHero.rewardScore;
769
1014
  st.wzHero.players[playerKey].correctCount += 1;
1015
+ await savePlayerData(session, st.wzHero.players[playerKey]);
770
1016
  text += '\n' + d.wzHero.correct.replace('{0}', st.wzHero.players[playerKey].score.toString());
771
1017
  st.wzHero.currentRound += 1;
772
1018
  if (st.wzHero.currentRound > st.wzHero.totalRounds) {
@@ -775,7 +1021,7 @@ function apply(ctx, cfg) {
775
1021
  await session.send(text);
776
1022
  await session.send(d.wzHero.gameEnd);
777
1023
  if (cfg.wzHero.showRank && !isPrivate(session)) {
778
- const rankText = generateRankText(st.wzHero.players);
1024
+ const rankText = generateGameRankText(st.wzHero.players, d.wzHero.rankTitle, d.wzHero.rankEmpty);
779
1025
  await session.send(rankText);
780
1026
  }
781
1027
  clearGameData(st.wzHero);
@@ -808,37 +1054,55 @@ function apply(ctx, cfg) {
808
1054
  catch (error) {
809
1055
  await session.send(d.wzHero.apiError);
810
1056
  }
811
- setupAutoStop(session, st.wzHero, cfg, 'wzHero', d.wzHero.autoStop, cfg.wzHero.showRank);
1057
+ setupAutoStop(session, st.wzHero, 'wzHero', d.wzHero.autoStop, cfg.wzHero.showRank, d.wzHero.rankTitle, d.wzHero.rankEmpty);
812
1058
  gameStates.set(key, st);
813
1059
  return;
814
1060
  }
815
1061
  if (cfg.enableNumberGuess && st.guessNumber.started) {
816
1062
  clearGameTimer(st.guessNumber);
817
1063
  if (!st.guessNumber.players[playerKey]) {
818
- st.guessNumber.players[playerKey] = getPlayerData(session);
1064
+ const playerData = await getPlayerData(session);
1065
+ st.guessNumber.players[playerKey] = playerData;
819
1066
  st.guessNumber.participants.push(playerKey);
1067
+ await updatePlayerPlayCount(session);
820
1068
  }
821
1069
  if (content === '结束') {
822
- clearGameData(st.guessNumber);
1070
+ clearGameData(st.guessNumber, cfg.guessNumber.showRank && !isPrivate(session), session, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
823
1071
  await session.send(d.guessNumber.stop);
824
1072
  gameStates.set(key, st);
825
1073
  return;
826
1074
  }
827
1075
  const num = parseInt(content);
828
1076
  if (isNaN(num)) {
829
- setupAutoStop(session, st.guessNumber, cfg, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank);
1077
+ setupAutoStop(session, st.guessNumber, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
830
1078
  return next();
831
1079
  }
1080
+ if (num < st.guessNumber.currentMin || num > st.guessNumber.currentMax) {
1081
+ await session.send(d.guessNumber.outOfRange.replace('{0}', st.guessNumber.currentMin.toString()).replace('{1}', st.guessNumber.currentMax.toString()));
1082
+ setupAutoStop(session, st.guessNumber, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
1083
+ return;
1084
+ }
832
1085
  if (num === st.guessNumber.target) {
833
- await session.send(d.guessNumber.correct);
834
- addScoreToOthers(st.guessNumber.players, playerKey);
1086
+ st.guessNumber.players[playerKey].score += cfg.guessNumber.rewardScore;
1087
+ st.guessNumber.players[playerKey].correctCount += 1;
1088
+ await savePlayerData(session, st.guessNumber.players[playerKey]);
1089
+ let message = d.guessNumber.correct;
1090
+ if (cfg.guessNumber.enablePenalty) {
1091
+ Object.keys(st.guessNumber.players).forEach(key => {
1092
+ if (key !== playerKey) {
1093
+ st.guessNumber.players[key].score += cfg.guessNumber.penaltyScore;
1094
+ savePlayerData(session, st.guessNumber.players[key]);
1095
+ }
1096
+ });
1097
+ }
1098
+ await session.send(message);
835
1099
  st.guessNumber.currentRound += 1;
836
1100
  if (st.guessNumber.currentRound > st.guessNumber.totalRounds) {
837
1101
  st.guessNumber.started = false;
838
1102
  clearGameTimer(st.guessNumber);
839
1103
  await session.send(d.guessNumber.gameEnd);
840
1104
  if (cfg.guessNumber.showRank && !isPrivate(session)) {
841
- const rankText = generateRankText(st.guessNumber.players);
1105
+ const rankText = generateGameRankText(st.guessNumber.players, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
842
1106
  await session.send(rankText);
843
1107
  }
844
1108
  clearGameData(st.guessNumber);
@@ -857,18 +1121,20 @@ function apply(ctx, cfg) {
857
1121
  st.guessNumber.currentMax = num - 1;
858
1122
  await session.send(d.guessNumber.tooBig.replace('{0}', st.guessNumber.currentMin.toString()).replace('{1}', st.guessNumber.currentMax.toString()));
859
1123
  }
860
- setupAutoStop(session, st.guessNumber, cfg, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank);
1124
+ setupAutoStop(session, st.guessNumber, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
861
1125
  gameStates.set(key, st);
862
1126
  return;
863
1127
  }
864
1128
  if (cfg.enableCalc24 && st.calc24.started) {
865
1129
  clearGameTimer(st.calc24);
866
1130
  if (!st.calc24.players[playerKey]) {
867
- st.calc24.players[playerKey] = getPlayerData(session);
1131
+ const playerData = await getPlayerData(session);
1132
+ st.calc24.players[playerKey] = playerData;
868
1133
  st.calc24.participants.push(playerKey);
1134
+ await updatePlayerPlayCount(session);
869
1135
  }
870
1136
  if (content === '结束') {
871
- clearGameData(st.calc24);
1137
+ clearGameData(st.calc24, cfg.calc24.showRank && !isPrivate(session), session, d.calc24.rankTitle, d.calc24.rankEmpty);
872
1138
  await session.send(d.calc24.stop);
873
1139
  gameStates.set(key, st);
874
1140
  return;
@@ -883,19 +1149,20 @@ function apply(ctx, cfg) {
883
1149
  .replace('{1}', st.calc24.difficulty)
884
1150
  .replace('{2}', st.calc24.numbers.join('、')));
885
1151
  }
886
- setupAutoStop(session, st.calc24, cfg, 'calc24', d.calc24.autoStop, cfg.calc24.showRank);
1152
+ setupAutoStop(session, st.calc24, 'calc24', d.calc24.autoStop, cfg.calc24.showRank, d.calc24.rankTitle, d.calc24.rankEmpty);
887
1153
  return;
888
1154
  }
889
1155
  if (st.calc24.solved) {
890
1156
  await session.send(d.calc24.solved);
891
- setupAutoStop(session, st.calc24, cfg, 'calc24', d.calc24.autoStop, cfg.calc24.showRank);
1157
+ setupAutoStop(session, st.calc24, 'calc24', d.calc24.autoStop, cfg.calc24.showRank, d.calc24.rankTitle, d.calc24.rankEmpty);
892
1158
  return;
893
1159
  }
894
1160
  const result = evaluateExpression(content);
895
1161
  if (result !== null && Math.abs(result - 24) < 0.001) {
896
1162
  await session.send(d.calc24.correct);
897
- st.calc24.players[playerKey].score += 1;
1163
+ st.calc24.players[playerKey].score += cfg.calc24.rewardScore;
898
1164
  st.calc24.players[playerKey].correctCount += 1;
1165
+ await savePlayerData(session, st.calc24.players[playerKey]);
899
1166
  st.calc24.solved = true;
900
1167
  st.calc24.currentRound += 1;
901
1168
  if (st.calc24.currentRound > st.calc24.totalRounds) {
@@ -903,7 +1170,7 @@ function apply(ctx, cfg) {
903
1170
  clearGameTimer(st.calc24);
904
1171
  await session.send(d.calc24.gameEnd);
905
1172
  if (cfg.calc24.showRank && !isPrivate(session)) {
906
- const rankText = generateRankText(st.calc24.players);
1173
+ const rankText = generateGameRankText(st.calc24.players, d.calc24.rankTitle, d.calc24.rankEmpty);
907
1174
  await session.send(rankText);
908
1175
  }
909
1176
  clearGameData(st.calc24);
@@ -922,75 +1189,7 @@ function apply(ctx, cfg) {
922
1189
  else {
923
1190
  await session.send(d.calc24.wrong);
924
1191
  }
925
- setupAutoStop(session, st.calc24, cfg, 'calc24', d.calc24.autoStop, cfg.calc24.showRank);
926
- gameStates.set(key, st);
927
- return;
928
- }
929
- if (cfg.enablePasswordLock && st.passwordLock.started) {
930
- clearGameTimer(st.passwordLock);
931
- if (!st.passwordLock.players[playerKey]) {
932
- st.passwordLock.players[playerKey] = getPlayerData(session);
933
- st.passwordLock.participants.push(playerKey);
934
- }
935
- if (content === '结束') {
936
- clearGameData(st.passwordLock);
937
- await session.send(d.passwordLock.stop);
938
- gameStates.set(key, st);
939
- return;
940
- }
941
- if (st.passwordLock.solved) {
942
- await session.send(d.passwordLock.solved);
943
- setupAutoStop(session, st.passwordLock, cfg, 'passwordLock', d.passwordLock.autoStop, cfg.passwordLock.showRank);
944
- return;
945
- }
946
- if (!/^\d{4}$/.test(content)) {
947
- await session.send(d.passwordLock.invalidPassword);
948
- setupAutoStop(session, st.passwordLock, cfg, 'passwordLock', d.passwordLock.autoStop, cfg.passwordLock.showRank);
949
- return;
950
- }
951
- st.passwordLock.playerGuess = content;
952
- st.passwordLock.guessTimes += 1;
953
- await session.send(d.passwordLock.guess.replace('{0}', content).replace('{1}', st.passwordLock.guessTimes.toString()));
954
- if (content === st.passwordLock.password) {
955
- const score = 10 - (st.passwordLock.guessTimes - 1);
956
- await session.send(d.passwordLock.correct.replace('{0}', content).replace('{1}', st.passwordLock.guessTimes.toString()));
957
- st.passwordLock.players[playerKey].score += score > 0 ? score : 1;
958
- st.passwordLock.players[playerKey].correctCount += 1;
959
- st.passwordLock.solved = true;
960
- st.passwordLock.started = false;
961
- clearGameTimer(st.passwordLock);
962
- await session.send(d.passwordLock.gameEnd);
963
- if (cfg.passwordLock.showRank && !isPrivate(session)) {
964
- const rankText = generateRankText(st.passwordLock.players);
965
- await session.send(rankText);
966
- }
967
- clearGameData(st.passwordLock);
968
- }
969
- else {
970
- let hint = '';
971
- if (cfg.passwordLock.showHint) {
972
- hint = generatePasswordHint(st.passwordLock.password, content);
973
- await session.send(d.passwordLock.wrong.replace('{0}', hint));
974
- }
975
- else {
976
- await session.send(d.passwordLock.wrong.replace('{0}', ''));
977
- }
978
- if (st.passwordLock.guessTimes >= st.passwordLock.maxGuessTimes) {
979
- await session.send(d.passwordLock.noChance.replace('{0}', st.passwordLock.password));
980
- st.passwordLock.started = false;
981
- clearGameTimer(st.passwordLock);
982
- await session.send(d.passwordLock.gameEnd);
983
- if (cfg.passwordLock.showRank && !isPrivate(session)) {
984
- const rankText = generateRankText(st.passwordLock.players);
985
- await session.send(rankText);
986
- }
987
- clearGameData(st.passwordLock);
988
- }
989
- else {
990
- await session.send(`剩余猜测次数:${st.passwordLock.maxGuessTimes - st.passwordLock.guessTimes}`);
991
- }
992
- }
993
- setupAutoStop(session, st.passwordLock, cfg, 'passwordLock', d.passwordLock.autoStop, cfg.passwordLock.showRank);
1192
+ setupAutoStop(session, st.calc24, 'calc24', d.calc24.autoStop, cfg.calc24.showRank, d.calc24.rankTitle, d.calc24.rankEmpty);
994
1193
  gameStates.set(key, st);
995
1194
  return;
996
1195
  }
@@ -1001,8 +1200,12 @@ function apply(ctx, cfg) {
1001
1200
  const session = argv.session;
1002
1201
  if (!session)
1003
1202
  return;
1203
+ if (isPrivate(session) && !canPlayPrivate('guessNumber')) {
1204
+ await session.send('私聊已禁用猜数字游戏');
1205
+ return;
1206
+ }
1004
1207
  const key = getSessionKey(session);
1005
- const st = gameStates.get(key) || initState(key, cfg);
1208
+ const st = gameStates.get(key) || initState(key);
1006
1209
  if (checkGameRunning(st, 'guessNumber')) {
1007
1210
  await session.send(d.common.gameRunning);
1008
1211
  return;
@@ -1016,10 +1219,10 @@ function apply(ctx, cfg) {
1016
1219
  await session.send(d.guessNumber.start.replace('{0}', st.guessNumber.totalRounds.toString()));
1017
1220
  await session.send(`猜数字范围:${st.guessNumber.currentMin} - ${st.guessNumber.currentMax}`);
1018
1221
  gameStates.set(key, st);
1019
- setupAutoStop(session, st.guessNumber, cfg, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank);
1222
+ setupAutoStop(session, st.guessNumber, 'guessNumber', d.guessNumber.autoStop, cfg.guessNumber.showRank, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
1020
1223
  }
1021
1224
  else if (action === '结束') {
1022
- clearGameData(st.guessNumber);
1225
+ clearGameData(st.guessNumber, cfg.guessNumber.showRank && !isPrivate(session), session, d.guessNumber.rankTitle, d.guessNumber.rankEmpty);
1023
1226
  await session.send(d.guessNumber.stop);
1024
1227
  gameStates.set(key, st);
1025
1228
  }
@@ -1032,8 +1235,12 @@ function apply(ctx, cfg) {
1032
1235
  const session = argv.session;
1033
1236
  if (!session)
1034
1237
  return;
1238
+ if (isPrivate(session) && !canPlayPrivate('wzHero')) {
1239
+ await session.send('私聊已禁用王者英雄猜谜');
1240
+ return;
1241
+ }
1035
1242
  const key = getSessionKey(session);
1036
- const st = gameStates.get(key) || initState(key, cfg);
1243
+ const st = gameStates.get(key) || initState(key);
1037
1244
  if (checkGameRunning(st, 'wzHero')) {
1038
1245
  await session.send(d.common.gameRunning);
1039
1246
  return;
@@ -1058,10 +1265,10 @@ function apply(ctx, cfg) {
1058
1265
  await session.send(d.wzHero.apiError);
1059
1266
  }
1060
1267
  gameStates.set(key, st);
1061
- setupAutoStop(session, st.wzHero, cfg, 'wzHero', d.wzHero.autoStop, cfg.wzHero.showRank);
1268
+ setupAutoStop(session, st.wzHero, 'wzHero', d.wzHero.autoStop, cfg.wzHero.showRank, d.wzHero.rankTitle, d.wzHero.rankEmpty);
1062
1269
  }
1063
1270
  else if (action === '结束') {
1064
- clearGameData(st.wzHero);
1271
+ clearGameData(st.wzHero, cfg.wzHero.showRank && !isPrivate(session), session, d.wzHero.rankTitle, d.wzHero.rankEmpty);
1065
1272
  await session.send(d.wzHero.stop);
1066
1273
  gameStates.set(key, st);
1067
1274
  }
@@ -1074,8 +1281,12 @@ function apply(ctx, cfg) {
1074
1281
  const session = argv.session;
1075
1282
  if (!session)
1076
1283
  return;
1284
+ if (isPrivate(session) && !canPlayPrivate('chengyuImage')) {
1285
+ await session.send('私聊已禁用看图猜成语');
1286
+ return;
1287
+ }
1077
1288
  const key = getSessionKey(session);
1078
- const st = gameStates.get(key) || initState(key, cfg);
1289
+ const st = gameStates.get(key) || initState(key);
1079
1290
  if (checkGameRunning(st, 'chengyuImage')) {
1080
1291
  await session.send(d.common.gameRunning);
1081
1292
  return;
@@ -1106,15 +1317,15 @@ function apply(ctx, cfg) {
1106
1317
  await session.send(d.chengyuImage.apiError);
1107
1318
  }
1108
1319
  gameStates.set(key, st);
1109
- setupAutoStop(session, st.chengyuImage, cfg, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank);
1320
+ setupAutoStop(session, st.chengyuImage, 'chengyuImage', d.chengyuImage.autoStop, cfg.chengyuImage.showRank, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
1110
1321
  }
1111
1322
  else if (action === '结束') {
1112
- clearGameData(st.chengyuImage);
1323
+ clearGameData(st.chengyuImage, cfg.chengyuImage.showRank && !isPrivate(session), session, d.chengyuImage.rankTitle, d.chengyuImage.rankEmpty);
1113
1324
  await session.send(d.chengyuImage.stop);
1114
1325
  gameStates.set(key, st);
1115
1326
  }
1116
1327
  else {
1117
- await session.send(d.chengyuImage.submitUsage);
1328
+ await session.send('请直接输入答案或 提示');
1118
1329
  }
1119
1330
  });
1120
1331
  ctx.command('成语接龙 <action>', '成语接龙')
@@ -1122,8 +1333,12 @@ function apply(ctx, cfg) {
1122
1333
  const session = argv.session;
1123
1334
  if (!session)
1124
1335
  return;
1336
+ if (isPrivate(session) && !canPlayPrivate('chengyuJielong')) {
1337
+ await session.send('私聊已禁用成语接龙');
1338
+ return;
1339
+ }
1125
1340
  const key = getSessionKey(session);
1126
- const st = gameStates.get(key) || initState(key, cfg);
1341
+ const st = gameStates.get(key) || initState(key);
1127
1342
  if (checkGameRunning(st, 'chengyuJielong')) {
1128
1343
  await session.send(d.common.gameRunning);
1129
1344
  return;
@@ -1133,18 +1348,19 @@ function apply(ctx, cfg) {
1133
1348
  st.chengyuJielong.currentRound = 1;
1134
1349
  st.chengyuJielong.hasTriggeredAutoPlay = false;
1135
1350
  st.chengyuJielong.autoPlayCount = 0;
1351
+ st.chengyuJielong.jielongCount = 0;
1136
1352
  await session.send(d.chengyuJielong.start.replace('{0}', st.chengyuJielong.totalRounds.toString()));
1137
1353
  gameStates.set(key, st);
1138
1354
  scheduleAutoPlay(session, key, st);
1139
- setupAutoStop(session, st.chengyuJielong, cfg, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank);
1355
+ setupAutoStop(session, st.chengyuJielong, 'chengyuJielong', d.chengyuJielong.autoStop, cfg.chengyuJielong.showRank, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
1140
1356
  }
1141
1357
  else if (action === '结束') {
1142
- clearGameData(st.chengyuJielong);
1358
+ clearGameData(st.chengyuJielong, cfg.chengyuJielong.showRank && !isPrivate(session), session, d.chengyuJielong.rankTitle, d.chengyuJielong.rankEmpty);
1143
1359
  await session.send(d.chengyuJielong.stop);
1144
1360
  gameStates.set(key, st);
1145
1361
  }
1146
1362
  else {
1147
- await session.send(d.chengyuJielong.joinUsage);
1363
+ await session.send('请直接发送成语参与游戏');
1148
1364
  }
1149
1365
  });
1150
1366
  ctx.command('算24点 <action>', '算24点游戏')
@@ -1152,8 +1368,12 @@ function apply(ctx, cfg) {
1152
1368
  const session = argv.session;
1153
1369
  if (!session)
1154
1370
  return;
1371
+ if (isPrivate(session) && !canPlayPrivate('calc24')) {
1372
+ await session.send('私聊已禁用算24点');
1373
+ return;
1374
+ }
1155
1375
  const key = getSessionKey(session);
1156
- const st = gameStates.get(key) || initState(key, cfg);
1376
+ const st = gameStates.get(key) || initState(key);
1157
1377
  if (checkGameRunning(st, 'calc24')) {
1158
1378
  await session.send(d.common.gameRunning);
1159
1379
  return;
@@ -1171,10 +1391,10 @@ function apply(ctx, cfg) {
1171
1391
  .replace('{1}', st.calc24.difficulty)
1172
1392
  .replace('{2}', st.calc24.numbers.join('、')));
1173
1393
  gameStates.set(key, st);
1174
- setupAutoStop(session, st.calc24, cfg, 'calc24', d.calc24.autoStop, cfg.calc24.showRank);
1394
+ setupAutoStop(session, st.calc24, 'calc24', d.calc24.autoStop, cfg.calc24.showRank, d.calc24.rankTitle, d.calc24.rankEmpty);
1175
1395
  }
1176
1396
  else if (action === '结束') {
1177
- clearGameData(st.calc24);
1397
+ clearGameData(st.calc24, cfg.calc24.showRank && !isPrivate(session), session, d.calc24.rankTitle, d.calc24.rankEmpty);
1178
1398
  await session.send(d.calc24.stop);
1179
1399
  gameStates.set(key, st);
1180
1400
  }
@@ -1182,34 +1402,24 @@ function apply(ctx, cfg) {
1182
1402
  await session.send('请输入:算24点 开始 或 算24点 结束');
1183
1403
  }
1184
1404
  });
1185
- ctx.command('猜密码 <action>', '猜密码游戏')
1186
- .action(async (argv, action) => {
1187
- const session = argv.session;
1188
- if (!session)
1189
- return;
1190
- const key = getSessionKey(session);
1191
- const st = gameStates.get(key) || initState(key, cfg);
1192
- if (checkGameRunning(st, 'passwordLock')) {
1193
- await session.send(d.common.gameRunning);
1194
- return;
1195
- }
1196
- if (action === '开始') {
1197
- st.passwordLock.started = true;
1198
- st.passwordLock.currentRound = 1;
1199
- st.passwordLock.guessTimes = 0;
1200
- st.passwordLock.solved = false;
1201
- st.passwordLock.password = koishi_1.Random.int(1000, 9999).toString();
1202
- await session.send(d.passwordLock.start.replace('{0}', st.passwordLock.maxGuessTimes.toString()));
1203
- gameStates.set(key, st);
1204
- setupAutoStop(session, st.passwordLock, cfg, 'passwordLock', d.passwordLock.autoStop, cfg.passwordLock.showRank);
1205
- }
1206
- else if (action === '结束') {
1207
- clearGameData(st.passwordLock);
1208
- await session.send(d.passwordLock.stop);
1209
- gameStates.set(key, st);
1210
- }
1211
- else {
1212
- await session.send('请输入:猜密码 开始 或 猜密码 结束');
1213
- }
1214
- });
1405
+ if (cfg.rank.enableCommand) {
1406
+ ctx.command('排行榜', '查看本群游戏排行榜')
1407
+ .action(async ({ session }) => {
1408
+ if (!session || !session.channelId)
1409
+ return;
1410
+ const rankText = await generateTotalRankText(session);
1411
+ await session.send(rankText);
1412
+ });
1413
+ ctx.command('清零', '清零本群所有玩家数据')
1414
+ .action(async ({ session }) => {
1415
+ if (!session || !session.channelId)
1416
+ return;
1417
+ if (session.user?.authority < cfg.rank.clearDataPermission) {
1418
+ await session.send(d.rank.noPermission);
1419
+ return;
1420
+ }
1421
+ await ctx.database.remove('game_mini_player', { guildId: session.channelId });
1422
+ await session.send(d.rank.clearSuccess);
1423
+ });
1424
+ }
1215
1425
  }