@@ -3,10 +3,12 @@
 | 
			
		||||
import { plugin as pluginApi, server, task, constants, command } from '@ccms/api'
 | 
			
		||||
import { plugin, interfaces, cmd, tab, enable, config, disable, PluginConfig } from '@ccms/plugin'
 | 
			
		||||
import { ContainerInstance, Container, Autowired } from '@ccms/container'
 | 
			
		||||
import io, { Server as SocketIOServer, Socket as SocketIOSocket } from '@ccms/websocket'
 | 
			
		||||
import io from '@ccms/websocket'
 | 
			
		||||
import * as fs from '@ccms/common/dist/fs'
 | 
			
		||||
import * as reflect from '@ccms/common/dist/reflect'
 | 
			
		||||
 | 
			
		||||
import type { Namespace, Server as SocketIOServer, Socket as SocketIOSocket } from '@ccms/websocket'
 | 
			
		||||
 | 
			
		||||
const suffixMap = {
 | 
			
		||||
    ts: 'typescript',
 | 
			
		||||
    js: 'javascript',
 | 
			
		||||
@@ -58,7 +60,7 @@ export class MiaoConsole extends interfaces.Plugin {
 | 
			
		||||
            this.token = Java.type('java.util.UUID').randomUUID().toString()
 | 
			
		||||
            this.logger.console(`§6已生成随机Token: §3${this.token} §c重启后或重新生成后失效!`)
 | 
			
		||||
        }
 | 
			
		||||
        process.on('message', (msg) => {
 | 
			
		||||
        process.on('message', (msg: string) => {
 | 
			
		||||
            this.logCache.push(msg)
 | 
			
		||||
            if (this.logCache.length > 100) {
 | 
			
		||||
                this.logCache = this.logCache.slice(this.logCache.length - 100, this.logCache.length)
 | 
			
		||||
@@ -191,6 +193,7 @@ export class MiaoConsole extends interfaces.Plugin {
 | 
			
		||||
    disable() {
 | 
			
		||||
        if (this.socketIOServer) {
 | 
			
		||||
            this.socketIOServer.close()
 | 
			
		||||
            process.removeAllListeners('websocket.create')
 | 
			
		||||
            process.removeAllListeners('message')
 | 
			
		||||
        }
 | 
			
		||||
        if (this.container.isBound(io.Instance)) {
 | 
			
		||||
@@ -230,30 +233,43 @@ export class MiaoConsole extends interfaces.Plugin {
 | 
			
		||||
        this.socketIOServer = io(this.instance, {
 | 
			
		||||
            path: '/ws',
 | 
			
		||||
            root: fs.concat(root, 'wwwroot')
 | 
			
		||||
        })
 | 
			
		||||
        } as any)
 | 
			
		||||
        this.container.bind(io.Instance).toConstantValue(this.socketIOServer)
 | 
			
		||||
        process.emit('websocket.create', this.socketIOServer)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryWebSocketNamespace(namespace: string, initialization: (namespace: Namespace) => void) {
 | 
			
		||||
        if (this.socketIOServer) {
 | 
			
		||||
            initialization(this.socketIOServer.of(namespace))
 | 
			
		||||
        } else {
 | 
			
		||||
            process.once('websocket.create', (server) => initialization(server.of(namespace)))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    checkWebSocketClient(client: SocketIOSocket) {
 | 
			
		||||
        if (!this.token) {
 | 
			
		||||
            this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`)
 | 
			
		||||
            client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        if (this.token != client.handshake.query.token) {
 | 
			
		||||
            this.logger.console(`§6客户端 §b${client.id} §c无效请求 §4请提供正确Token后再次连接!`)
 | 
			
		||||
            client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    startSocketIOServer() {
 | 
			
		||||
        let namespace = this.socketIOServer.of('/MiaoConsole')
 | 
			
		||||
        process.on('message', (msg) => namespace.emit('log', msg))
 | 
			
		||||
        namespace.on('connection', (client: SocketIOSocket) => {
 | 
			
		||||
            if (!this.token) {
 | 
			
		||||
                this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`)
 | 
			
		||||
                client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            if (this.token != client.handshake.query.token) {
 | 
			
		||||
                this.logger.console(`§6客户端 §b${client.id} §c无效请求 §4请提供正确Token后再次连接!`)
 | 
			
		||||
                client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            if (this.checkWebSocketClient(client)) {
 | 
			
		||||
                this.initWebSocketClient(client)
 | 
			
		||||
                this.logCache.forEach(msg => client.emit('log', msg))
 | 
			
		||||
                this.logger.console(`§6客户端 §b${client.id} §a新建连接 ${this.rootLogger ? '启动日志转发' : '§4转发日志启动失败'}...`)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        process.emit('websocket.start', this.socketIOServer)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private initWebSocketClient(client: SocketIOSocket) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										303
									
								
								packages/plugins/src/MiaoDashboard.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								packages/plugins/src/MiaoDashboard.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,303 @@
 | 
			
		||||
/// <reference types="@javatypes/bungee-api" />
 | 
			
		||||
/// <reference types="@javatypes/bukkit-api" />
 | 
			
		||||
/// <reference types="@javatypes/sponge-api" />
 | 
			
		||||
 | 
			
		||||
import { plugin, server, task } from '@ccms/api'
 | 
			
		||||
import { Autowired } from '@ccms/container'
 | 
			
		||||
import { Config, interfaces, JSPlugin, PluginConfig } from '@ccms/plugin'
 | 
			
		||||
 | 
			
		||||
import http from '@ccms/common/dist/http'
 | 
			
		||||
 | 
			
		||||
import type { Socket as SocketIOSocket, Namespace } from '@ccms/websocket'
 | 
			
		||||
import type { MiaoConsole } from './MiaoConsole'
 | 
			
		||||
 | 
			
		||||
const defaultConfig = {
 | 
			
		||||
    statistics: {
 | 
			
		||||
        max: 300
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultDataConfig = {
 | 
			
		||||
    server_online: "%server_online%",
 | 
			
		||||
    server_tps: "%server_tps_1%",
 | 
			
		||||
    server_ram_used: "%server_ram_used%",
 | 
			
		||||
    server_total_chunks: "%server_total_chunks%",
 | 
			
		||||
    server_total_living_entities: "%server_total_living_entities%",
 | 
			
		||||
    server_total_entities: "%server_total_entities%",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@JSPlugin({ prefix: 'Dashboard', version: '1.0.0', author: 'MiaoWoo', source: __filename, depends: ['MiaoConsole'] })
 | 
			
		||||
export class MiaoDashboard extends interfaces.Plugin {
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private server: server.Server
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private nativePluginManager: server.NativePluginManager
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private pluginManager: plugin.PluginManager
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private taskManager: task.TaskManager
 | 
			
		||||
 | 
			
		||||
    private namespace: Namespace
 | 
			
		||||
 | 
			
		||||
    @Config()
 | 
			
		||||
    private config: PluginConfig & typeof defaultConfig = defaultConfig
 | 
			
		||||
    @Config()
 | 
			
		||||
    private dataConfig: PluginConfig & typeof defaultDataConfig = defaultDataConfig
 | 
			
		||||
    @Config({ autosave: true })
 | 
			
		||||
    private dataCache: { [key: string]: { time: string, value: Number }[] } = {}
 | 
			
		||||
    private statisticTimer: task.Task
 | 
			
		||||
 | 
			
		||||
    private PlaceholderAPI: { setPlaceholders: (player: any, str: string) => string }
 | 
			
		||||
 | 
			
		||||
    load() {
 | 
			
		||||
        for (const key of Object.keys(this.dataConfig)) {
 | 
			
		||||
            this.dataCache[key] = this.dataCache[key] ?? []
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enable() {
 | 
			
		||||
        let consolePlugin: MiaoConsole = this.pluginManager.getPlugin('MiaoConsole') as MiaoConsole
 | 
			
		||||
        consolePlugin.registryWebSocketNamespace('/MiaoDashboard', (namespace: Namespace) => {
 | 
			
		||||
            this.namespace = namespace
 | 
			
		||||
            this.namespace.on('connection', (client: SocketIOSocket) => {
 | 
			
		||||
                if (consolePlugin.checkWebSocketClient(client)) {
 | 
			
		||||
                    this.initWebSocketClient(client)
 | 
			
		||||
                    this.logger.console(`§6客户端 §b${client.id} §a新建连接...`)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        this.PlaceholderAPI = base.getClass("me.clip.placeholderapi.PlaceholderAPI").static
 | 
			
		||||
        this.statisticTimer = this.taskManager.create(() => {
 | 
			
		||||
            for (const key of Object.keys(this.dataConfig)) {
 | 
			
		||||
                let dataArray = this.dataCache[key]
 | 
			
		||||
                dataArray.push({
 | 
			
		||||
                    time: this.dateFormat('HH:MM:SS'),
 | 
			
		||||
                    value: parseFloat(this.taskManager.callSyncMethod(() => this.PlaceholderAPI['setPlaceholders(Player,String)'](null, this.dataConfig[key]))) ?? 0
 | 
			
		||||
                })
 | 
			
		||||
                if (dataArray.length > this.config.statistics.max) {
 | 
			
		||||
                    this.dataCache[key] = dataArray.slice(dataArray.length - this.config.statistics.max, dataArray.length)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, this).async().timer(20 * 10).submit()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private dateFormat(fmt: string, date = new Date()) {
 | 
			
		||||
        let ret: RegExpExecArray
 | 
			
		||||
        const opt = {
 | 
			
		||||
            "Y+": date.getFullYear().toString(),        // 年
 | 
			
		||||
            "m+": (date.getMonth() + 1).toString(),     // 月
 | 
			
		||||
            "d+": date.getDate().toString(),            // 日
 | 
			
		||||
            "H+": date.getHours().toString(),           // 时
 | 
			
		||||
            "M+": date.getMinutes().toString(),         // 分
 | 
			
		||||
            "S+": date.getSeconds().toString()          // 秒
 | 
			
		||||
            // 有其他格式化字符需求可以继续添加,必须转化成字符串
 | 
			
		||||
        }
 | 
			
		||||
        for (let k in opt) {
 | 
			
		||||
            ret = new RegExp("(" + k + ")").exec(fmt)
 | 
			
		||||
            if (ret) {
 | 
			
		||||
                fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
        return fmt
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    disable() {
 | 
			
		||||
        this.namespace?.close()
 | 
			
		||||
        this.statisticTimer.cancel()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private wrapper(fn, data) {
 | 
			
		||||
        fn({ status: 0, data })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private initWebSocketClient(client: SocketIOSocket) {
 | 
			
		||||
        client.on('message', (...args) => {
 | 
			
		||||
            console.log(args)
 | 
			
		||||
        })
 | 
			
		||||
        this.initStatistics(client)
 | 
			
		||||
        this.initPlayers(client)
 | 
			
		||||
        this.initPlugins(client)
 | 
			
		||||
        this.initServices(client)
 | 
			
		||||
        client.on('error', (error) => {
 | 
			
		||||
            this.logger.console(`§6客户端 §b${client.id} §c触发异常: ${error}`)
 | 
			
		||||
            this.logger.error(error)
 | 
			
		||||
        })
 | 
			
		||||
        client.on('disconnect', () => {
 | 
			
		||||
            this.logger.console(`§6客户端 §b${client.id} §c断开连接...`)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private initStatistics(client: SocketIOSocket) {
 | 
			
		||||
        client.on('statistics', (data, callback) => {
 | 
			
		||||
            let result = {}
 | 
			
		||||
            data.keys.map((key: string) => result[key] = this.dataCache[key])
 | 
			
		||||
            this.wrapper(callback, { time: Date.now(), data: result })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    private initPlayers(client: SocketIOSocket) {
 | 
			
		||||
        client.on('players', (callback) => {
 | 
			
		||||
            let players = Java.from(this.server.getOnlinePlayers()).map((player: org.bukkit.entity.Player) => {
 | 
			
		||||
                let loc = player.getLocation()
 | 
			
		||||
                return {
 | 
			
		||||
                    name: player.getName(),
 | 
			
		||||
                    location: {
 | 
			
		||||
                        world: loc.getWorld().getName(),
 | 
			
		||||
                        x: loc.getX().toFixed(0),
 | 
			
		||||
                        y: loc.getY().toFixed(0),
 | 
			
		||||
                        z: loc.getZ().toFixed(0)
 | 
			
		||||
                    },
 | 
			
		||||
                    health: player.getHealth().toFixed(0),
 | 
			
		||||
                    foodlevel: player.getFoodLevel().toFixed(0),
 | 
			
		||||
                    gamemode: player.getGameMode().name(),
 | 
			
		||||
                    ip: player.getAddress().getAddress().getHostAddress()
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            this.wrapper(callback, {
 | 
			
		||||
                items: players
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        this.initPlayerModify(client)
 | 
			
		||||
        client.on('players.heal', ({ name }, callback) => {
 | 
			
		||||
            let player: org.bukkit.entity.Player = this.server.getPlayer(name)
 | 
			
		||||
            if (!player) {
 | 
			
		||||
                return callback({
 | 
			
		||||
                    status: 1,
 | 
			
		||||
                    msg: '玩家 ' + name + ' 不在线!'
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            player.setHealth(player.getMaxHealth())
 | 
			
		||||
            player.setFoodLevel(20)
 | 
			
		||||
            player.sendMessage('§a您已被治疗 §7- 来自MiaoDashboard')
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: '操作成功!'
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        client.on('players.kick', ({ name, reason }, callback) => {
 | 
			
		||||
            let player: org.bukkit.entity.Player = this.server.getPlayer(name)
 | 
			
		||||
            if (!player) {
 | 
			
		||||
                return callback({
 | 
			
		||||
                    status: 1,
 | 
			
		||||
                    msg: '玩家 ' + name + ' 不在线!'
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            player.kickPlayer(reason)
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: '操作成功!'
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    private initPlayerModify(client: SocketIOSocket) {
 | 
			
		||||
        client.on('players.modify.gamemode', ({ name, gamemode }, callback) => {
 | 
			
		||||
            let player: org.bukkit.entity.Player = this.server.getPlayer(name)
 | 
			
		||||
            if (!player) {
 | 
			
		||||
                return callback({
 | 
			
		||||
                    status: 1,
 | 
			
		||||
                    msg: '玩家 ' + name + ' 不在线!'
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            let GameMode = Java.type('org.bukkit.GameMode')
 | 
			
		||||
            let mode = GameMode.valueOf(gamemode)
 | 
			
		||||
            this.taskManager.callSyncMethod(() => player.setGameMode(mode))
 | 
			
		||||
            player.sendMessage('§a您的游戏模式已被修改为 ' + gamemode + ' §7- 来自MiaoDashboard')
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: '操作成功!'
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    private initPlugins(client: SocketIOSocket) {
 | 
			
		||||
        this.initNativePlugins(client)
 | 
			
		||||
        this.initScriptPlugins(client)
 | 
			
		||||
    }
 | 
			
		||||
    private initServices(client: SocketIOSocket) {
 | 
			
		||||
        client.on('services.plugins', (callback) => {
 | 
			
		||||
            this.wrapper(callback, http.get('http://w.yumc.pw/api/free_plugin/find').data.map(plugin => {
 | 
			
		||||
                let installed = this.nativePluginManager.get(plugin.name)
 | 
			
		||||
                if (installed) {
 | 
			
		||||
                    plugin.installed = true
 | 
			
		||||
                    plugin.installedVersion = installed.version
 | 
			
		||||
                }
 | 
			
		||||
                plugin.installed = this.nativePluginManager.has(plugin.name)
 | 
			
		||||
                return plugin
 | 
			
		||||
            }))
 | 
			
		||||
        })
 | 
			
		||||
        client.on('services.plugins.install', ({ name }, callback) => {
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 安装成功!`
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        client.on('services.plugins.update', ({ name }, callback) => {
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 安装成功!`
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    private initNativePlugins(client: SocketIOSocket) {
 | 
			
		||||
        client.on('plugins.natives', callback => {
 | 
			
		||||
            this.wrapper(callback, this.nativePluginManager.list().map(plugin => {
 | 
			
		||||
                plugin.status = plugin.enable ? 1 : 0
 | 
			
		||||
                return plugin
 | 
			
		||||
            }))
 | 
			
		||||
        })
 | 
			
		||||
        client.on('plugins.natives.reload', ({ name }, callback) => {
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 不存在`
 | 
			
		||||
            })
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 安装完成`
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        client.on('plugins.natives.install', ({ name }, callback) => {
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 不存在`
 | 
			
		||||
            })
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 安装完成`
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private initScriptPlugins(client: SocketIOSocket) {
 | 
			
		||||
        client.on('plugins.scripts', (callback) => {
 | 
			
		||||
            let plugins = []
 | 
			
		||||
            this.pluginManager.getPlugins().forEach((plugin) => {
 | 
			
		||||
                plugins.push({
 | 
			
		||||
                    name: plugin.description.name,
 | 
			
		||||
                    version: plugin.description.version,
 | 
			
		||||
                    author: plugin.description.author,
 | 
			
		||||
                    source: plugin.description.source.toString().replace(root, ''),
 | 
			
		||||
                    type: plugin.description.type,
 | 
			
		||||
                    scanner: plugin.description.loadMetadata.scanner.type,
 | 
			
		||||
                    loader: plugin.description.loadMetadata.loader.type,
 | 
			
		||||
                    status: 1
 | 
			
		||||
                })
 | 
			
		||||
            })
 | 
			
		||||
            this.wrapper(callback, {
 | 
			
		||||
                items: plugins,
 | 
			
		||||
                total: plugins.length
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
        client.on('plugins.scripts.reload', ({ name }, callback) => {
 | 
			
		||||
            let plugin: any = this.pluginManager.getPlugin(name)
 | 
			
		||||
            if (!plugin) {
 | 
			
		||||
                return callback({
 | 
			
		||||
                    status: 404,
 | 
			
		||||
                    msg: `插件 ${name} 不存在`
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            this.pluginManager.reload(plugin)
 | 
			
		||||
            return callback({
 | 
			
		||||
                status: 0,
 | 
			
		||||
                msg: `插件 ${name} 重载完成`
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,6 +9,8 @@ import { Server as SocketIOServer, Socket as SocketIOSocket, Namespace } from '@
 | 
			
		||||
 | 
			
		||||
import * as fs from '@ccms/common/dist/fs'
 | 
			
		||||
 | 
			
		||||
import type { MiaoConsole } from './MiaoConsole'
 | 
			
		||||
 | 
			
		||||
const FileFilter = Java.type('java.io.FileFilter')
 | 
			
		||||
const ByteArrayInputStream = java.io.ByteArrayInputStream
 | 
			
		||||
const ByteArrayOutputStream = java.io.ByteArrayOutputStream
 | 
			
		||||
@@ -16,14 +18,13 @@ const StandardCharsets = Java.type("java.nio.charset.StandardCharsets")
 | 
			
		||||
const GZIPInputStream = Java.type('java.util.zip.GZIPInputStream')
 | 
			
		||||
const ByteArray = Java.type("byte[]")
 | 
			
		||||
 | 
			
		||||
@JSPlugin({ prefix: 'Explorer', version: '1.0.0', author: 'MiaoWoo', source: __filename })
 | 
			
		||||
@JSPlugin({ prefix: 'Explorer', version: '1.0.0', author: 'MiaoWoo', source: __filename, depends: ['MiaoConsole'] })
 | 
			
		||||
export class MiaoExplorer extends interfaces.Plugin {
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private Server: server.Server
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private pluginManager: plugin.PluginManager
 | 
			
		||||
 | 
			
		||||
    private token: string
 | 
			
		||||
    private namespace: any
 | 
			
		||||
    private chunkCacheMap: Map<string, Array<string>>
 | 
			
		||||
 | 
			
		||||
@@ -32,39 +33,20 @@ export class MiaoExplorer extends interfaces.Plugin {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enable() {
 | 
			
		||||
        let consolePlugin: any = this.pluginManager.getPlugin('MiaoConsole')
 | 
			
		||||
        if (consolePlugin.socketIOServer) {
 | 
			
		||||
            this.startWebSocketServer(consolePlugin.socketIOServer)
 | 
			
		||||
        } else {
 | 
			
		||||
            process.on('websocket.create', (server: SocketIOServer) => {
 | 
			
		||||
                this.startWebSocketServer(server)
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private startWebSocketServer(server: SocketIOServer) {
 | 
			
		||||
        let consolePlugin: any = this.pluginManager.getPlugin('MiaoConsole')
 | 
			
		||||
        this.token = consolePlugin.token
 | 
			
		||||
        this.namespace = server.of('/MiaoExplorer')
 | 
			
		||||
        let consolePlugin: MiaoConsole = this.pluginManager.getPlugin('MiaoConsole') as MiaoConsole
 | 
			
		||||
        consolePlugin.registryWebSocketNamespace('/MiaoExplorer', (namespace: Namespace) => {
 | 
			
		||||
            this.namespace = namespace
 | 
			
		||||
            this.namespace.on('connection', (client: SocketIOSocket) => {
 | 
			
		||||
            if (!this.token) {
 | 
			
		||||
                this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`)
 | 
			
		||||
                client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            if (this.token != client.handshake.query.token) {
 | 
			
		||||
                this.logger.console(`§6客户端 §b${client.id} §c无效请求 §4请提供正确Token后再次连接!`)
 | 
			
		||||
                client.emit('unauthorized', () => client.disconnect(true))
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
                if (consolePlugin.checkWebSocketClient(client)) {
 | 
			
		||||
                    this.initWebSocketClient(client)
 | 
			
		||||
                    this.logger.console(`§6客户端 §b${client.id} §a新建连接...`)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    disable() {
 | 
			
		||||
        this.namespace.removeAllListeners('connect')
 | 
			
		||||
        this.namespace.close()
 | 
			
		||||
        this.namespace?.close()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private readDir(dir) {
 | 
			
		||||
@@ -161,15 +143,4 @@ export class MiaoExplorer extends interfaces.Plugin {
 | 
			
		||||
            this.logger.console(`§6客户端 §b${client.id} §c断开连接...`)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Cmd()
 | 
			
		||||
    msme(sender: any, command: string, args: string[]) {
 | 
			
		||||
        this.logger.log(sender, command, args)
 | 
			
		||||
        sender.sendMessage(JSON.stringify({ command, ...args }))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Tab()
 | 
			
		||||
    tabmsme(_sender: any, _command: string, _args: string[]) {
 | 
			
		||||
        return ['world']
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ const defaultConfig = {
 | 
			
		||||
    joinTip: true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@JSPlugin({ prefix: 'MRD', version: '1.5.9', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], nativeDepends: ['ProtocolLib', 'PlaceholderAPI'], source: __filename })
 | 
			
		||||
@JSPlugin({ prefix: 'MRD', version: '1.6.0', author: 'MiaoWoo', servers: [constants.ServerType.Bukkit], nativeDepends: ['ProtocolLib', 'PlaceholderAPI'], source: __filename })
 | 
			
		||||
export class MiaoReward extends interfaces.Plugin {
 | 
			
		||||
    public serverInfo: ServerInfo
 | 
			
		||||
    private notifyError = true
 | 
			
		||||
@@ -79,6 +79,7 @@ export class MiaoReward extends interfaces.Plugin {
 | 
			
		||||
    private playerInfoCache = new Map<string, UserInfo>()
 | 
			
		||||
 | 
			
		||||
    private downgrade = false
 | 
			
		||||
    private subversion = 0
 | 
			
		||||
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private chat: chat.Chat
 | 
			
		||||
@@ -132,6 +133,7 @@ export class MiaoReward extends interfaces.Plugin {
 | 
			
		||||
        //@ts-ignore
 | 
			
		||||
        this.logger.prefix = this.config.prefix
 | 
			
		||||
        this.downgrade = this.Bukkit.server.class.name.split('.')[3] == "v1_7_R4"
 | 
			
		||||
        this.subversion = parseInt(this.Bukkit.server.class.name.split('.')[3].split('_')[1])
 | 
			
		||||
        this.updateServerInfo(null, () => this.updateOnlinePlayersInfo())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -248,29 +250,50 @@ export class MiaoReward extends interfaces.Plugin {
 | 
			
		||||
        if (!this.ProtocolLibrary) {
 | 
			
		||||
            return this.logger.console(`§4服务器未安装 ProtocolLib 无法扫码功能 请安装后重试!`)
 | 
			
		||||
        }
 | 
			
		||||
        this.adapter = this.createPacketAdapter((event) => {
 | 
			
		||||
            let integers = event.getPacket().getIntegers().getValues()
 | 
			
		||||
            let mapId = integers.get(0)
 | 
			
		||||
            let player = event.getPlayer()
 | 
			
		||||
            if (mapId == this.zeroMapView.getId() && this.playerImageCache.has(player.getName())) {
 | 
			
		||||
                let bytes = this.playerImageCache.get(player.getName())
 | 
			
		||||
                if (!this.downgrade) {
 | 
			
		||||
                    event.getPacket().getByteArrays().write(0, bytes)
 | 
			
		||||
                    event.getPacket().getIntegers().write(3, 128)
 | 
			
		||||
                    event.getPacket().getIntegers().write(4, 128)
 | 
			
		||||
                } else {
 | 
			
		||||
        let writer = undefined
 | 
			
		||||
        if (this.downgrade) {
 | 
			
		||||
            writer = (packet, bytes) => {
 | 
			
		||||
                // let xbytes = new Bytes(131)
 | 
			
		||||
                    let origin = event.getPacket().getByteArrays().read(0)
 | 
			
		||||
                let origin = packet.getByteArrays().read(0)
 | 
			
		||||
                // xbytes[1] = origin[1]
 | 
			
		||||
                // xbytes[2] = origin[2]
 | 
			
		||||
                for (let y = 0; y < 128; ++y) {
 | 
			
		||||
                    origin[y + 3] = bytes[y * 128 + origin[1]]
 | 
			
		||||
                }
 | 
			
		||||
                    event.getPacket().getByteArrays().write(0, origin)
 | 
			
		||||
                packet.getByteArrays().write(0, origin)
 | 
			
		||||
            }
 | 
			
		||||
        } else if (this.subversion < 17) {
 | 
			
		||||
            writer = (packet, bytes) => {
 | 
			
		||||
                packet.getByteArrays().write(0, bytes)
 | 
			
		||||
                packet.getIntegers().write(3, 128)
 | 
			
		||||
                packet.getIntegers().write(4, 128)
 | 
			
		||||
            }
 | 
			
		||||
        } else if (this.subversion > 16) {
 | 
			
		||||
            writer = (packet, bytes) => {
 | 
			
		||||
                let b = packet.getModifier().read(4)
 | 
			
		||||
                if (b) {
 | 
			
		||||
                    let bi = Java.type(b.class.name)
 | 
			
		||||
                    packet.getModifier().write(4, new bi(b.a, b.b, 128, 128, bytes))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        }
 | 
			
		||||
        if (writer) {
 | 
			
		||||
            this.adapter = this.createPacketAdapter(this.getPacketAdapter(writer))
 | 
			
		||||
            this.ProtocolLibrary.getProtocolManager().addPacketListener(this.adapter)
 | 
			
		||||
        } else {
 | 
			
		||||
            console.console('§4当前服务器不支持虚拟地图发包 将无法使用扫码功能!')
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private getPacketAdapter(writer: (packet: any, bytes: number[]) => void) {
 | 
			
		||||
        return (event) => {
 | 
			
		||||
            let integers = event.getPacket().getIntegers().getValues()
 | 
			
		||||
            let mapId = integers.get(0)
 | 
			
		||||
            let player = event.getPlayer()
 | 
			
		||||
            if (mapId == this.zeroMapView.getId() && this.playerImageCache.has(player.getName())) {
 | 
			
		||||
                writer(event.getPacket(), this.playerImageCache.get(player.getName()))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private sendWindowItems(player: org.bukkit.entity.Player, mapItem: any) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user