diff --git a/packages/plugins/src/MiaoChat.ts b/packages/plugins/src/MiaoChat.ts index 4c21696e..47c4b187 100644 --- a/packages/plugins/src/MiaoChat.ts +++ b/packages/plugins/src/MiaoChat.ts @@ -2,16 +2,16 @@ /// /// -import { server, plugin as pluginApi, channel, constants } from '@ccms/api' -import { inject, optional } from '@ccms/container'; +import { server, plugin as pluginApi, channel, constants, chat } from '@ccms/api' +import { inject, optional } from '@ccms/container' import { plugin, interfaces, cmd, listener, tab, config, enable } from '@ccms/plugin' import Tellraw from '@ccms/common/dist/tellraw' -const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream"); -const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream"); -const StandardCharsets = Java.type("java.nio.charset.StandardCharsets"); -const GZIPInputStream = Java.type("java.util.zip.GZIPInputStream"); -const GZIPOutputStream = Java.type("java.util.zip.GZIPOutputStream"); +const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream") +const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream") +const StandardCharsets = Java.type("java.nio.charset.StandardCharsets") +const GZIPInputStream = Java.type("java.util.zip.GZIPInputStream") +const GZIPOutputStream = Java.type("java.util.zip.GZIPOutputStream") const BiConsumer = Java.type('java.util.function.BiConsumer') const ByteArray = Java.type("byte[]") @@ -22,31 +22,31 @@ class MiaoMessage { private static MAX_MESSAGE_LENGTH = 32000; private static copy(input, output) { - let buffer = new ByteArray(1024); - let n: number; + let buffer = new ByteArray(1024) + let n: number while ((n = input.read(buffer)) != -1) { - output.write(buffer, 0, n); + output.write(buffer, 0, n) } - input.close(); - output.close(); + input.close() + output.close() } public static encode(input: any): any { - return new MiaoMessage(input).encode(); + return new MiaoMessage(input).encode() } public static decode(input: any): MiaoMessage { - let baos = new ByteArrayOutputStream(); - MiaoMessage.copy(new GZIPInputStream(new ByteArrayInputStream(input)), baos); - return new MiaoMessage(baos.toString(StandardCharsets.UTF_8.name())); + let baos = new ByteArrayOutputStream() + MiaoMessage.copy(new GZIPInputStream(new ByteArrayInputStream(input)), baos) + return new MiaoMessage(baos.toString(StandardCharsets.UTF_8.name())) } // private String json; constructor(public json: any) { } public encode(): any { - let baos = new ByteArrayOutputStream(); - MiaoMessage.copy(new ByteArrayInputStream(this.json.getBytes(StandardCharsets.UTF_8)), new GZIPOutputStream(baos)); - if (baos.size() > MiaoMessage.MAX_MESSAGE_LENGTH) { return null; } - return baos.toByteArray(); + let baos = new ByteArrayOutputStream() + MiaoMessage.copy(new ByteArrayInputStream(this.json.getBytes(StandardCharsets.UTF_8)), new GZIPOutputStream(baos)) + if (baos.size() > MiaoMessage.MAX_MESSAGE_LENGTH) { return null } + return baos.toByteArray() } } @@ -54,10 +54,12 @@ class MiaoMessage { export class MiaoChat extends interfaces.Plugin { @inject(server.Server) private Server: server.Server + @inject(chat.Chat) + private chat: chat.Chat @inject(channel.Channel) @optional() private Channel: channel.Channel - private channelOff: { off: () => void }; + private channelOff: { off: () => void } @config() private config = { @@ -129,34 +131,34 @@ export class MiaoChat extends interfaces.Plugin { } } - private chatFormats: any[]; - private styleFormats: any; + private chatFormats: any[] + private styleFormats: any // 用于匹配 '[xx]' 聊天格式 private FORMAT_PATTERN = /[\[]([^\[\]]+)[\]]/ig; - private PlaceholderAPI: { setPlaceholders: (player: any, str: string) => string }; + private PlaceholderAPI: { setPlaceholders: (player: any, str: string) => string } load() { - this.chatFormats = Object.values(this.config.ChatFormats); - this.chatFormats.sort(this.compare('index')); - this.initFormat(this.chatFormats); - this.styleFormats = this.config.StyleFormats; + this.chatFormats = Object.values(this.config.ChatFormats) + this.chatFormats.sort(this.compare('index')) + this.initFormat(this.chatFormats) + this.styleFormats = this.config.StyleFormats } private compare(prop: string) { - return function (obj1: { [x: string]: any; }, obj2: { [x: string]: any; }) { - var val1 = obj1[prop]; - var val2 = obj2[prop]; + return function (obj1: { [x: string]: any }, obj2: { [x: string]: any }) { + var val1 = obj1[prop] + var val2 = obj2[prop] if (!isNaN(Number(val1)) && !isNaN(Number(val2))) { - val1 = Number(val1); - val2 = Number(val2); + val1 = Number(val1) + val2 = Number(val2) } if (val1 < val2) { - return -1; + return -1 } else if (val1 > val2) { - return 1; + return 1 } else { - return 0; + return 0 } } } @@ -164,7 +166,7 @@ export class MiaoChat extends interfaces.Plugin { enable() { this.PlaceholderAPI = { setPlaceholders: (player: any, string: string) => { - return string; + return string } } } @@ -177,7 +179,7 @@ export class MiaoChat extends interfaces.Plugin { // 尝试加载 Bukkit 的 PlaceholderAPI try { //@ts-ignore - this.PlaceholderAPI = base.getClass("me.clip.placeholderapi.PlaceholderAPI").static; + this.PlaceholderAPI = base.getClass("me.clip.placeholderapi.PlaceholderAPI").static this.logger.log('[PAPI] Found Bukkit PlaceholderAPI Hooking...') } catch (ex) { this.logger.console("§cCan't found me.clip.placeholderapi.PlaceholderAPI variable will not be replaced! Err: " + ex) @@ -187,14 +189,14 @@ export class MiaoChat extends interfaces.Plugin { spongeenable() { // 尝试加载 Sponge 的 PlaceholderAPI try { - var spongePapi = this.Server.getService('me.rojo8399.placeholderapi.PlaceholderService'); - var s = org.spongepowered.api.text.serializer.TextSerializers.formattingCode('§'); + var spongePapi = this.Server.getService('me.rojo8399.placeholderapi.PlaceholderService') + var s = org.spongepowered.api.text.serializer.TextSerializers.formattingCode('§') if (spongePapi) { this.PlaceholderAPI = { setPlaceholders: (player: any, string: string) => { - return s.serialize(spongePapi.replacePlaceholders(string, player, player)); + return s.serialize(spongePapi.replacePlaceholders(string, player, player)) } - }; + } this.logger.log('[PAPI] Found Sponge PlaceholderAPI Hooking...') } } catch (ex) { @@ -213,7 +215,7 @@ export class MiaoChat extends interfaces.Plugin { this.channelOff = this.Channel?.listen(this, MiaoMessage.CHANNEL, (data, event: net.md_5.bungee.api.event.PluginMessageEvent) => { let bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy() if (event.getTag() == MiaoMessage.CHANNEL) { - let origin = event.getSender().getAddress(); + let origin = event.getSender().getAddress() bungee.getServers().forEach(new BiConsumer({ accept: (s, server) => { if (server.getAddress() != origin && server.getPlayers().size() > 0) { @@ -227,13 +229,13 @@ export class MiaoChat extends interfaces.Plugin { @cmd({ servers: ["bungee"] }) mct(sender: any, command: string, args: string[]) { - this.logger.log(sender, command, args); + this.logger.log(sender, command, args) sender.sendMessage(JSON.stringify({ command, ...args })) } @cmd({ servers: ["!bungee"] }) mchat(sender: any, command: string, args: string[]) { - this.logger.log(sender, command, args); + this.logger.log(sender, command, args) sender.sendMessage(JSON.stringify({ command, ...args })) } @@ -243,102 +245,97 @@ export class MiaoChat extends interfaces.Plugin { @listener({ servers: ['bukkit'] }) AsyncPlayerChatEvent(event: org.bukkit.event.player.AsyncPlayerChatEvent) { - this.sendChat(event.getPlayer(), event.getMessage(), function () { - event.setCancelled(true); - }); + this.sendChat(event.getPlayer(), event.getMessage(), () => event.setCancelled(true)) } @listener({ servers: ['sponge'] }) MessageChannelEvent$Chat(event: org.spongepowered.api.event.message.MessageChannelEvent.Chat) { //@ts-ignore - var player = event.getCause().first(org.spongepowered.api.entity.living.player.Player.class).orElse(null); + var player = event.getCause().first(org.spongepowered.api.entity.living.player.Player.class).orElse(null) if (player == null) { - return; + return } - var plain = event.getRawMessage().toPlain(); + var plain = event.getRawMessage().toPlain() if (plain.startsWith(Tellraw.duplicateChar)) { - return; + return } - this.sendChat(player, plain, function () { - event.setMessageCancelled(true) - }); + this.sendChat(player, plain, () => event.setMessageCancelled(true)) } initFormat(chatFormats: any[]) { chatFormats.forEach(chatFormat => { - var chat_format_str = chatFormat.format; - var temp = []; - var r: any[]; + var chat_format_str = chatFormat.format + var temp = [] + var r: any[] while (r = this.FORMAT_PATTERN.exec(chat_format_str)) { - temp.push(r[1]); + temp.push(r[1]) } - var format_list = []; + var format_list = [] temp.forEach(t => { - var arr = chat_format_str.split('[' + t + ']', 2); + var arr = chat_format_str.split('[' + t + ']', 2) if (arr[0]) { - format_list.push(arr[0]); + format_list.push(arr[0]) } - format_list.push(t); - chat_format_str = arr[1]; - }); + format_list.push(t) + chat_format_str = arr[1] + }) if (chat_format_str) { - format_list.push(chat_format_str); + format_list.push(chat_format_str) } - chatFormat.format_list = format_list; + chatFormat.format_list = format_list }) } - sendChat(player: any, plain: string, callback: { (): void; }) { - var chat_format = this.getChatFormat(player); + sendChat(player: any, plain: string, callback: { (): void }) { + var chat_format = this.getChatFormat(player) if (!chat_format) { - console.debug('未获得用户', player.getName(), '的 ChatRule 跳过执行...'); - return; + console.debug('未获得用户', player.getName(), '的 ChatRule 跳过执行...') + return } - callback(); - var tr = Tellraw.create(); + callback() + var tr = Tellraw.create() chat_format.format_list.forEach((format) => { - var style = this.styleFormats[format]; + var style = this.styleFormats[format] if (style) { - tr.then(this.replace(player, style.text.replace(/&(\w)/g, '§$1'))); + tr.then(this.replace(player, style.text.replace(/&(\w)/g, '§$1'))) if (style.hover) { - tr.tip(this.replace(player, style.hover.join('\n'))); + tr.tip(this.replace(player, style.hover.join('\n'))) } if (style.click && style.click.type && style.click.command) { - var command = this.replace(player, style.click.command); + var command = this.replace(player, style.click.command) switch (style.click.type.toUpperCase()) { case "COMMAND": - tr.command(command); - break; + tr.command(command) + break case "OPENURL": - tr.link(command); - break; + tr.link(command) + break case "SUGGEST": - tr.suggest(command); - break; + tr.suggest(command) + break default: } } } else { - tr.then(this.replace(player, format)); + tr.then(this.replace(player, format)) } - }); + }) let json = tr.then(this.replace(player, plain)).json() this.sendChatAll(json) this.Channel?.send(player, MiaoMessage.CHANNEL, MiaoMessage.encode(json)) } sendChatAll(json: string) { - this.Server.getOnlinePlayers().forEach(player => this.Server.sendJson(player, json)) + this.Server.getOnlinePlayers().forEach(player => this.chat.sendJson(player, json)) } getChatFormat(player: any) { - for (var i in this.chatFormats) { - var format = this.chatFormats[i]; + for (let format of this.chatFormats) { if (player.hasPermission(format.permission)) { - return format; + return format } } - return null; + return null } replace(player: any, target: string) { diff --git a/packages/plugins/src/MiaoCoin.ts b/packages/plugins/src/MiaoCoin.ts index 98b1891d..b06a86eb 100644 --- a/packages/plugins/src/MiaoCoin.ts +++ b/packages/plugins/src/MiaoCoin.ts @@ -81,6 +81,7 @@ export class MiaoCoin extends interfaces.Plugin { } disable() { + // {"app":"com.tencent.autoreply","desc":"","view":"autoreply","ver":"0.0.0.1","prompt":"[动画表情]","meta":{"metadata":{"title":"点击蓝色字体有惊喜","buttons":[{"slot":1,"action_data":"我是傻逼","name":"点我","action":"notify"}],"type":"guest","token":"LAcV49xqyE57S17B8ZT6FU7odBveNMYJzux288tBD3c="}},"config":{"forward":1,"showSender":1}} } @Cmd() diff --git a/packages/plugins/src/MiaoConsole.ts b/packages/plugins/src/MiaoConsole.ts index 4500562c..2a8d04ab 100644 --- a/packages/plugins/src/MiaoConsole.ts +++ b/packages/plugins/src/MiaoConsole.ts @@ -1,6 +1,6 @@ /// -import { plugin as pluginApi, server, task, constants } from '@ccms/api' +import { plugin as pluginApi, server, task, constants, command } from '@ccms/api' import { plugin, interfaces, cmd, tab, enable, config, disable } from '@ccms/plugin' import { inject, ContainerInstance, Container } from '@ccms/container' import io, { Server as SocketIOServer, Socket as SocketIOSocket } from '@ccms/websocket' @@ -27,6 +27,8 @@ export class MiaoConsole extends interfaces.Plugin { private serverType: string @inject(server.Server) private server: server.Server + @inject(command.Command) + private command: command.Command @inject(task.TaskManager) private task: task.TaskManager @inject(pluginApi.PluginManager) @@ -248,7 +250,7 @@ export class MiaoConsole extends interfaces.Plugin { client.emit('log', `§6命令: §b${cmd} §a执行成功!`) }) client.on('tabComplate', (input, index, callback) => { - callback && callback(this.server.tabComplete(this.server.getConsoleSender(), input, index)) + callback?.(this.command.tabComplete(this.server.getConsoleSender(), input, index)) }) client.on('exec', (code) => { try { diff --git a/packages/plugins/src/MiaoReward.ts b/packages/plugins/src/MiaoReward.ts index 78d1e6e3..9de063a1 100644 --- a/packages/plugins/src/MiaoReward.ts +++ b/packages/plugins/src/MiaoReward.ts @@ -3,7 +3,7 @@ import { JSPlugin, interfaces, Cmd, Tab, Listener, Config } from "@ccms/plugin" import { QRCode, QRErrorCorrectLevel } from '@ccms/common/dist/qrcode' -import { inject, JSClass, optional } from '@ccms/container' +import { Autowired, JSClass, optional, inject } from '@ccms/container' import http from '@ccms/common/dist/http' let MapView @@ -54,9 +54,9 @@ interface PlaceholderAPI { setPlaceholders: (player: any, str: string) => string } -@JSPlugin({ prefix: 'MRD', version: '1.2.0', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], source: __filename }) +@JSPlugin({ prefix: 'MRD', version: '1.2.3', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], source: __filename }) export class MiaoReward extends interfaces.Plugin { - private serverInfo + private serverInfo: any private cacheBindUuid = '' private zeroMapView = undefined private zeroMapRender: QRCodeRender = undefined @@ -67,14 +67,16 @@ export class MiaoReward extends interfaces.Plugin { private bindingNotify = new java.util.HashSet() private drawCooldown = new Map() - @inject(chat.Chat) + @Autowired() private chat: chat.Chat - @inject(server.Server) + @Autowired() private server: server.Server - @inject(task.TaskManager) + @Autowired() private taskManager: task.TaskManager - @inject(channel.Channel) - @optional() private Channel: channel.Channel + @Autowired() + private channel: channel.Channel + @Autowired() + private bungee: channel.proxy.BungeeCord @Config() private config = { @@ -97,6 +99,10 @@ export class MiaoReward extends interfaces.Plugin { this.config.prefix = this.config.prefix || '§6[§b广告系统§6]§r' this.config.drawCommand = this.config.drawCommand || 'p give %player_name% %amount%' this.config.drawCooldown = this.config.drawCooldown || 300 + this.updateServerInfo() + } + + private updateServerInfo(player?: any) { this.taskManager.create(() => { if (this.config.serverId) { let result = this.httpPost(`https://reward.yumc.pw/server/server`, { @@ -105,21 +111,61 @@ export class MiaoReward extends interfaces.Plugin { }) if (result.code == 200) { this.serverInfo = result.data + if (player) this.bungee.for(player).forward("ALL", "MiaoReward", { type: "updateServerInfo", data: result.data }).send() } } }).async().submit() } + @JSClass('com.google.common.io.ByteStreams') + private ByteStreams: any + enable() { this.initPlaceholderAPI() - this.channelOff = this.Channel?.listen(this, 'BungeeCord', () => { - this.isBungeeCord = true - this.PlayerJoinEvent['off']() - this.channelOff.off() + this.initBungeeCord() + this.initZeroMap() + } + + private initBungeeCord() { + this.channelOff = this.channel?.listen(this, 'BungeeCord', (data) => { + if (!this.isBungeeCord) { + this.isBungeeCord = true + this.PlayerJoinEvent['off']() + } + let input = this.ByteStreams.newDataInput(data) + let subChannel = input.readUTF() + switch (subChannel) { + case "GetServer": + this.isBungeeCord = true + let serverName = input.readUTF() + break + case "MiaoReward": + this.readForward(input) + break + } }) let players = this.server.getOnlinePlayers() if (players.length) this.bungeeCordDetect(players[0]) - this.initZeroMap() + } + + cmdrun(sender: any, ...args: any[]) { + try { + let tfunc = new Function(`return '§a返回结果: §r'+ eval(${JSON.stringify(args.join(' '))});`) + this.logger.sender(sender, tfunc.apply(this) + '') + } catch (ex) { + this.logger.sender(sender, this.logger.stack(ex)) + } + } + + private readForward(input) { + let message = JSON.parse(input.readUTF()) + console.log(message) + switch (message.type) { + case "updateServerInfo": + this.serverInfo = message.data + console.console(this.config.prefix, '§6兑换比例已更新为:§a', message.data.ratio) + break + } } private initPlaceholderAPI() { @@ -140,11 +186,13 @@ export class MiaoReward extends interfaces.Plugin { } private initZeroMap() { - this.zeroMapRender = new QRCodeRender() - this.zeroMapView = Bukkit.getMap(0) || Bukkit.createMap(Bukkit.getWorlds()[0]) - this.zeroMapView.setScale(MapView.Scale.FARTHEST) - this.zeroMapView.getRenderers().forEach(r => this.zeroMapView.removeRenderer(r)) - this.zeroMapView.addRenderer(this.zeroMapRender.getHandler()) + this.taskManager.create(() => { + this.zeroMapRender = new QRCodeRender() + this.zeroMapView = Bukkit.getMap(0) || Bukkit.createMap(Bukkit.getWorlds()[0]) + this.zeroMapView.setScale(MapView.Scale.FARTHEST) + this.zeroMapView.getRenderers().forEach(r => this.zeroMapView.removeRenderer(r)) + this.zeroMapView.addRenderer(this.zeroMapRender.getHandler()) + }).submit() } disable() { @@ -167,9 +215,10 @@ export class MiaoReward extends interfaces.Plugin { private scanAuth(sender: org.bukkit.entity.Player, scanType: string, scanObj: { title: string, content: string }, success: (token: string, user: any) => void, cancel?: () => void) { this.chat.sendTitle(sender, this.config.prefix, '§a正在获取授权二维码...') + this.logger.sender(sender, '§a正在获取授权二维码...') let scan = this.httpPost('https://reward.yumc.pw/auth/scan', { ...scanObj, type: scanType }) if (scan.code == 200) { - let sync = { scaned: false, timeout: false } + let sync = { scaned: false } this.taskManager.create(() => { let result = this.httpPost('https://reward.yumc.pw/auth/scanCheck', { token: scan.data.token, @@ -212,14 +261,19 @@ export class MiaoReward extends interfaces.Plugin { let bindUser = Bukkit.getPlayerExact(this.bindingUser) if (bindUser && bindUser.isOnline() && this.isQrCodeItem(bindUser.getItemInHand())[0]) { this.bindingNotify.add(sender) - this.logger.sender(sender, "§c当前 §a" + this.bindingUser + " §c玩家正在扫码 §6请稍候 §e" + this.bindingLeftTime + "秒 §6后重试...") + this.logger.sender(sender, [ + "§c当前 §a" + this.bindingUser + " §c玩家正在扫码", + "§6请等待 §e" + this.bindingLeftTime + "秒 §6后重试...", + "§a玩家操作完成后将会通知您继续操作..." + ]) return true } } - if (this.drawCooldown.has(sender.getName())) { + if (this.drawCooldown.has(sender.getName()) && !sender.isOp()) { let leftTime = cooldown - (Date.now() - this.drawCooldown.get(sender.getName())) / 1000 if (leftTime > 0) { - return this.logger.sender(sender, `§c扫码功能冷却中 剩余 ${leftTime} 秒!`) + this.logger.sender(sender, `§c扫码功能冷却中 剩余 ${leftTime} 秒!`) + return true } } this.drawCooldown.set(sender.getName(), Date.now()) @@ -253,7 +307,14 @@ export class MiaoReward extends interfaces.Plugin { this.scanAuth(sender, 'draw', { title: '兑换授权', - content: "是否授权 " + this.serverInfo.name + " 服务器\n兑换 " + amount + " 喵币 到 " + sender.getName() + content: [ + "是否授权 " + this.serverInfo.name + " 兑换喵币", + "兑换玩家: " + sender.getName(), + "兑换数量: " + amount, + "兑换比例: " + parseFloat(this.serverInfo.ratio), + "预计到帐: " + (amount * this.serverInfo.ratio).toFixed(0), + "注意: 数据可能更新不及时 请以实际到账金额为准!" + ].join('\n') }, (token: string) => { this.drawCoin(sender, amount, token) }) @@ -282,8 +343,8 @@ export class MiaoReward extends interfaces.Plugin { return this.sendError(sender, '§6执行命令 §3/' + command + ' §c可能存在异常') } this.logger.sender(sender, draw.msg.split('\n')) - this.sendBoardcast(sender, `${this.config.prefix}§6玩家 §b${sender.getName()} §6成功将 §a${amount}喵币 §6兑换成 §c${draw.data}点券!`) - this.sendBoardcast(sender, `${this.config.prefix}§c/mrd help §b查看广告系统帮助 §6快来一起看广告赚点券吧!`) + this.sendBroadcast(sender, `${this.config.prefix}§6玩家 §b${sender.getName()} §6成功将 §a${amount}喵币 §6兑换成 §c${draw.data}点券!`) + this.sendBroadcast(sender, `${this.config.prefix}§c/mrd help §b查看广告系统帮助 §6快来一起看广告赚点券吧!`) }).submit() } @@ -313,7 +374,7 @@ export class MiaoReward extends interfaces.Plugin { `§6====== ${this.config.prefix} §a喵币兑换排行 §6======`, ] if (boardcast) { - ranks.forEach(l => this.sendBoardcast(sender, l)) + ranks.forEach(l => this.sendBroadcast(sender, l)) } else { this.logger.sender(sender, ranks) } @@ -338,13 +399,13 @@ export class MiaoReward extends interfaces.Plugin { ]) } - cmdratio(sender: any, ratio: number, confirm: string) { + cmdratio(sender: any, ratioStr: string, confirm: string) { if (!sender.isOp()) { return this.logger.sender(sender, '§4你没有此命令的权限!') } - let mbr = (1 / ratio).toFixed(4) + let [ratio, mbr, msg] = this.ratio2string(ratioStr) if (!confirm) { return this.logger.sender(sender, [ '§4警告: 您正在设置服务器喵币/点券兑换比例 设置后将实时生效!', - `§6您设置的兑换比例为 §c${ratio} §6=> §a${mbr}喵币 §6兑换 §c1点券`, + `§6您设置的兑换比例为 ` + msg, `§6玩家至少需要 §a${mbr}喵币 §6才可以兑换点券!`, `§6请执行 §b/mrd ratio §c${ratio} §econfirm §c确认修改!` ]) @@ -359,22 +420,22 @@ export class MiaoReward extends interfaces.Plugin { return this.logger.sender(sender, `§4操作异常 §6服务器返回: §c${result.msg}`) } this.logger.sender(sender, `§a操作成功 §6服务器返回: §a${result.msg}`) - this.sendBoardcast(sender, `${this.config.prefix} §6当前兑换比例已调整为 §c${ratio} §6=> §a${mbr}喵币 §6兑换 §c1点券!`) + this.updateServerInfo(sender) + this.sendBroadcast(sender, `${this.config.prefix} §6当前兑换比例已调整为 ` + msg) } - @JSClass('java.io.ByteArrayOutputStream') - private ByteArrayOutputStream - @JSClass('java.io.DataOutputStream') - private DataOutputStream + private ratio2string(ratio) { + ratio = parseFloat(ratio) + if (ratio > 1) { + return [ratio, 1, `§c${ratio} §6就是 §a1喵币 §6=> §c${ratio}点券!`] + } + let mbr = Math.round(1 / ratio * 10000) / 10000 + return [ratio, mbr, `§c${ratio} §6就是 §a${mbr}喵币 §6=> §c1点券!`] + } - private sendBoardcast(player, message) { + private sendBroadcast(player, message) { if (!this.isBungeeCord) { return org.bukkit.Bukkit.broadcastMessage(message) } - let byteArray = new this.ByteArrayOutputStream() - let out = new this.DataOutputStream(byteArray) - out.writeUTF("Message") - out.writeUTF("ALL") - out.writeUTF(message) - player.sendPluginMessage(base.getInstance(), "BungeeCord", byteArray.toByteArray()) + this.bungee.for(player).broadcast(message).send() } private bindServer(sender: org.bukkit.entity.Player) { @@ -589,10 +650,7 @@ CAST TIME : ${Date.now() - startTime}`) private bungeeCordDetect(player) { if (this.isBungeeCord === undefined && player) { - let byteArray = new this.ByteArrayOutputStream() - let out = new this.DataOutputStream(byteArray) - out.writeUTF("GetServer") - player.sendPluginMessage(base.getInstance(), "BungeeCord", byteArray.toByteArray()) + this.bungee.for(player).getServer().send() } } @@ -606,7 +664,6 @@ CAST TIME : ${Date.now() - startTime}`) let [cancelled, id] = this.isQrCodeItem(event.getItemDrop().getItemStack()) if (id != null && id != undefined && cancelled) { event.getItemDrop().remove() - this.cancelTask(event.getPlayer()) } } @@ -616,7 +673,6 @@ CAST TIME : ${Date.now() - startTime}`) let [cancelled, id] = this.isQrCodeItem(inv.getItem(event.getPreviousSlot() as any)) if (id != null && id != undefined && cancelled) { inv.setItem(event.getPreviousSlot(), null) - this.cancelTask(event.getPlayer()) } } @@ -626,7 +682,6 @@ CAST TIME : ${Date.now() - startTime}`) let [cancelled, id] = this.isQrCodeItem(item) if (id != null && id != undefined && cancelled) { event.getInventory().setItem(event.getSlot(), null) - this.cancelTask(event.getWhoClicked()) event.setCancelled(true) } } @@ -637,9 +692,10 @@ CAST TIME : ${Date.now() - startTime}`) } private cancelTask(player) { - console.ex(new Error()) + if (!this.isBinding) return this.isBinding = false this.bindingTask.cancel() + this.bindingTask = undefined this.bindingUser = 'unknow' this.checkAndClear(player) this.chat.sendActionBar(player, "") diff --git a/packages/plugins/src/MiaoScriptPackageManager.ts b/packages/plugins/src/MiaoScriptPackageManager.ts index ad3f1956..96cb2553 100644 --- a/packages/plugins/src/MiaoScriptPackageManager.ts +++ b/packages/plugins/src/MiaoScriptPackageManager.ts @@ -27,25 +27,28 @@ let langMap = { 'main.command.help.tip': '§6请执行 §b/{command} §ahelp §6查看帮助!', 'main.command.no.permission': '§c你没有此命令的权限!', 'list.install.header': '§6当前 §bMiaoScript §6已安装下列插件:', - 'list.install.body': '§6插件名称: §b{name}\n§6版本: §a{version}\n§6作者: §3{author}\n§6来源: §c{from}', + 'list.install.body': '§6插件名称: §b{name} §6版本: §a{version}\n§6作者: §3{author} §6来源: §c{from}', 'list.header': '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:', - 'list.body': '§6插件名称: §b{name}\n§6版本: §a{version}\n§6作者: §3{author}\n§6更新时间: §9{updated_at}', + 'list.body': '§6插件名称: §b{name} §6版本: §a{version}\n§6作者: §3{author} §6更新时间: §9{updated_at}', 'plugin.not.exists': '§6插件 §b{name} §c不存在!', - 'plugin.unload.finish': '§6插件 §b{name} §a已卸载!', - 'plugin.reload.finish': '§6插件 §b{name} §a重载完成!', + 'plugin.unload.start': '§c开始卸载 §6插件 §b{name} §6版本 §3{version}!', + 'plugin.unload.finish': '§6插件 §b{name} §6版本 §3{version} §a已卸载!', + 'plugin.reload.start': '§a开始重载 §6插件 §b{name} §6版本 §3{version}!', + 'plugin.reload.finish': '§6插件 §b{name} §6版本 §3{version} §a重载完成!', 'plugin.name.empty': '§c请输入插件名称!', 'cloud.update.finish': '§6成功从 §aMiaoScriptPackageCenter §6获取到 §a{length} §6个插件!', 'cloud.not.exists': '§6当前 §aMiaoScriptPackageCenter §c不存在 §a{name} §c插件!', 'cloud.update.exists': '§6插件 §b{name} §a发现新版本 §3{new_version} §6当前版本 §3{old_version}!', - 'download.start': '§6开始下载插件: §b{name}', + 'download.start': '§6开始下载插件: §b{name} §6版本 §3{version}', 'download.url': '§6插件下载地址: §b{url}', - 'download.finish': '§6插件 §b{name} §a下载完毕 开始加载 ...', - 'install.finish': '§6插件 §b{name} §a安装成功!', - 'update.finish': '§6插件 §b{name} §a更新成功!', - 'upgrade.confirm': '§6您正在尝试升级 §bMiaoScript §c核心 §6请执行 §b/mpm §aupgrade §cconfirm §6确认执行!', + 'download.finish': '§6插件 §b{name} §6版本 §3{version} §a下载完毕 开始加载 ...', + 'install.finish': '§6插件 §b{name} §6版本 §3{version} §a安装成功!', + 'update.finish': '§6插件 §b{name} §6版本 §3{version} §a更新成功!', + 'upgrade.confirm': '§6您正在尝试更新 §bMiaoScript §c核心 §6请执行 §b/mpm §aupgrade §cconfirm §6确认执行!', + 'upgrade.failed': '§6尝试热更新 §bMiaoScript §c核心 §4失败! §6请重启服务器完成更新...', 'deploy.token.not.exists': '§4请先配置发布Token!', - 'deploy.success': '§6插件 §b{name} §a发布成功! §6服务器返回: §a{msg}', - 'deploy.fail': '§6插件 §b{name} §c发布失败! §6服务器返回: §c{msg}', + 'deploy.success': '§6插件 §b{name} §6版本 §3{version} §a发布成功! §6服务器返回: §a{msg}', + 'deploy.fail': '§6插件 §b{name} §6版本 §3{version} §c发布失败! §6服务器返回: §c{msg}', 'run.script': '§b运行脚本:§r {script}', 'run.result': '§a返回结果:§r {result}', 'run.noresult': '§4没有返回结果!', @@ -53,7 +56,26 @@ let langMap = { let fallbackMap = langMap -@JSPlugin({ prefix: 'PM', version: '1.2.0', author: 'MiaoWoo', source: __filename }) +class FakeSender { + private _proxy + private name: string + private plugin: MiaoScriptPackageManager + constructor(name: string, plugin: MiaoScriptPackageManager, superclass: any) { + this.name = name + this.plugin = plugin + let FakeSenderAdapter = Java.extend(superclass, { + getName: () => this.name, + isOp: () => true, + sendMessage: (message) => this.plugin.sendBungeeCordMessage(this.name, `§6[§3BPM§6][§a${this.plugin.serverName}§6] ${message}`) + }) + this._proxy = new FakeSenderAdapter() + } + getHandler() { + return this._proxy + } +} + +@JSPlugin({ prefix: 'PM', version: '1.3.0', author: 'MiaoWoo', source: __filename }) export class MiaoScriptPackageManager extends interfaces.Plugin { @inject(plugin.PluginManager) private pluginManager: pluginApi.PluginManager @@ -78,7 +100,8 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { private packageCache: any[] = []; private packageNameCache: string[] = []; - private serverName: string + private isBungeeCord = false + public serverName: string private translate: Translate private channelOff: { off: () => void } @@ -97,6 +120,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { let subChannel = input.readUTF() switch (subChannel) { case "GetServer": + this.isBungeeCord = true this.serverName = input.readUTF() break case "MiaoScriptPackageManager": @@ -134,8 +158,20 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { } private readForward(input) { let message = JSON.parse(input.readUTF()) - this.taskManager.create(() => this.main(this.server.getConsoleSender(), message.command, message.args)).async().submit() - this.sendBungeeCordMessage(message.sender, `§6[§cMS§6][§bPM§6] [§3BPM§6][§a${this.serverName}§6] §6命令 §b/mpm ${message.args?.join?.(' ')} §a执行成功!`) + let fakeSender = this.getProxySender(message.sender) + this.taskManager.create(() => this.main(fakeSender, message.command, message.args)).async().submit() + this.logger.sender(fakeSender, `§6命令 §b/mpm ${message.args?.join?.(' ')} §a执行成功!`) + } + + private getProxySender(name: string) { + switch (this.serverType) { + case constants.ServerType.Bukkit: + return new FakeSender(name, this, Java.type('org.bukkit.command.CommandSender')).getHandler() + case constants.ServerType.Sponge: + return new FakeSender(name, this, Java.type('org.spongepowered.api.command.CommandSource')).getHandler() + default: + return this.server.getConsoleSender() + } } @Listener({ servers: [constants.ServerType.Bukkit] }) @@ -154,7 +190,7 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { } } - private sendBungeeCordMessage(sender, message) { + sendBungeeCordMessage(sender, message) { let players = this.server.getOnlinePlayers() if (players.length) { let byteArray = new this.ByteArrayOutputStream() @@ -172,20 +208,22 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { @Cmd({ servers: [`!${constants.ServerType.Bungee}`] }) bmpm(sender: any, command: string, args: string[]) { - if (!sender.isOp()) { return this.i18n(sender, 'main.command.no.permission') } + if (!sender?.isOp()) { return this.i18n(sender, 'main.command.no.permission') } + if (!this.isBungeeCord) return this.logger.sender(sender, '§c当前服务器尚未检测到BungeeCord链接...') + this.taskManager.create(() => this.main(sender, command, args)).async().submit() this.bungeeCordForward(sender, { sender: sender.getName(), command, args }) this.logger.sender(sender, `§6[§3BPM§6][§a${this.serverName}§6] §6命令 §b/mpm ${args.join?.(' ')} §a发布成功!`) } @Cmd({ servers: [constants.ServerType.Bungee] }) mpmanager(sender: any, command: string, args: string[]) { - if (!sender.isOp()) { return this.i18n(sender, 'main.command.no.permission') } + if (!sender?.isOp()) { return this.i18n(sender, 'main.command.no.permission') } this.taskManager.create(() => this.main(sender, command, args)).async().submit() } @Cmd({ servers: [`!${constants.ServerType.Bungee}`] }) mpm(sender: any, command: string, args: string[]) { - if (!sender.isOp()) { return this.i18n(sender, 'main.command.no.permission') } + if (!sender?.isOp()) { return this.i18n(sender, 'main.command.no.permission') } this.taskManager.create(() => this.main(sender, command, args)).async().submit() } @@ -208,6 +246,12 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { this.logger.sender(sender, help) } + cmdinfo(sender: any) { + this.logger.sender(sender, [ + + ]) + } + cmdload(sender: any, name: string) { let pluginFile = fs.concat(__dirname + '', name) if (!fs.exists(pluginFile)) { @@ -237,7 +281,10 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { return } - this.download(sender, name) + this.download(sender, name, false, () => { + let plugin = this.pluginManager.loadFromFile(fs.concat(root, this.pluginFolder, name + '.js')) + this.i18n(sender, 'install.finish', { name, version: plugin.description.version }) + }) } cmdupdate(sender: any, name: string) { @@ -253,29 +300,46 @@ export class MiaoScriptPackageManager extends interfaces.Plugin { if (!confirm) { return this.i18n(sender, 'upgrade.confirm') } let enginePath = fs.path(fs.file(root, 'node_modules')) if (enginePath.startsWith(root)) { - base.delete(enginePath) - this.cmdrestart(sender) + try { + base.delete(enginePath) + this.cmdrestart(sender) + } catch (ex) { + if (global.debug) { + console.ex(ex) + } + if (fs.exists(enginePath)) { + this.i18n(sender, 'upgrade.failed') + fs.create(fs.file(root, 'upgrade')) + } + } } return } if (this.checkPlugin(sender, name)) { - this.update(sender, name) - this.pluginManager.reload(name) + this.update(sender, name, () => this.reload(sender, name)) } } cmdunload(sender: any, name: string) { if (this.checkPlugin(sender, name)) { - this.pluginManager.disable(name) - this.i18n(sender, 'plugin.unload.finish', { name }) + let plugin = this.pluginManager.getPlugins().get(name) + this.i18n(sender, 'plugin.unload.start', { name, version: plugin.description.version }) + this.pluginManager.disable(plugin) + this.i18n(sender, 'plugin.unload.finish', { name, version: plugin.description.version }) } } cmdreload(sender: any, name: string) { name = name || this.description.name + this.reload(sender, name) + } + + private reload(sender: any, name: string) { if (this.checkPlugin(sender, name)) { - this.pluginManager.reload(name) - this.i18n(sender, 'plugin.reload.finish', { name }) + let plugin = this.pluginManager.getPlugins().get(name) + this.i18n(sender, 'plugin.reload.start', { name, version: plugin.description.version }) + this.pluginManager.reload(plugin) + this.i18n(sender, 'plugin.reload.finish', { name, version: this.pluginManager.getPlugins().get(name).description.version }) } } @@ -360,13 +424,16 @@ return '§a返回结果: §r'+ eval(${JSON.stringify(code)});`) }).async().submit() } - update(sender: any, name: string) { + private update(sender: any, name: string, callback?: () => void) { if (this.checkCloudPlugin(sender, name)) { - this.download(sender, name, true) + this.download(sender, name, true, () => { + this.i18n(sender, 'update.finish', { name, version: this.packageCache[name].version }) + callback?.() + }) } } - @Tab() + @Tab({ alias: ['bmpm'] }) tabmpm(sender: any, command: any, args: string | any[]) { if (args.length === 1) { return ['list', 'install', 'update', 'upgrade', 'reload', 'restart', 'run', 'help', 'create', 'deploy'] } if (args.length > 1) { @@ -405,19 +472,15 @@ return '§a返回结果: §r'+ eval(${JSON.stringify(code)});`) }).async().submit() } - download(sender: any, name: string, update: boolean = false) { + download(sender: any, name: string, update: boolean, callback?: () => void) { this.taskManager.create(() => { - this.i18n(sender, 'download.start', { name }) - this.i18n(sender, 'download.url', { url: this.packageCache[name].url }) + let pluginPkg = this.packageCache[name] + this.i18n(sender, 'download.start', { name, version: pluginPkg.version }) + this.i18n(sender, 'download.url', { url: pluginPkg.url }) let pluginFile = update ? fs.concat(root, this.pluginFolder, 'update', name + '.js') : fs.concat(root, this.pluginFolder, name + '.js') - http.download(this.packageCache[name].url, pluginFile) - this.i18n(sender, 'download.finish', { name }) - if (!update) { - this.pluginManager.loadFromFile(fs.concat(root, this.pluginFolder, name + '.js')) - this.i18n(sender, 'install.finish', { name }) - } else { - this.i18n(sender, 'update.finish', { name }) - } + http.download(pluginPkg.url, pluginFile) + this.i18n(sender, 'download.finish', { name, version: pluginPkg.version }) + callback?.() }).async().submit() } }