Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| afb72a6794 | |||
| 40fb2869d5 | |||
| 8f3c0cc0bc | |||
| 2d281a13d1 | |||
| cf3016e27e | |||
| ba3ef49ee5 | |||
| 08b72cd05a | |||
| 6e38da18bc | |||
| 2957150096 | |||
| c13ff26971 | |||
| 104d1b18d6 | |||
| db9746b641 | |||
| 6f18fe0990 | |||
| b33358cf59 | |||
| bc29221b9c | |||
| dd88e63d1a | |||
| 99a264677a | |||
| 805f7ad521 | |||
| e6aba870da | |||
| 321cb18cb9 | |||
| 430edacd3f | |||
| ac88c15113 | |||
| 2185b1a2f8 | |||
| c14e20e269 | |||
| 45a1c43dd8 | |||
| 9226e1ab4f | |||
| 287585d8f5 |
@@ -20,3 +20,4 @@ wallaby.js
|
||||
.vscode
|
||||
.theia
|
||||
type_definitions
|
||||
tsconfig.tsbuildinfo
|
||||
|
||||
@@ -4,3 +4,8 @@
|
||||
- 更新日志 [](https://docs.yumc.pw/MiaoScript/CHANGELOG.html)
|
||||
- 安装文档 [](https://docs.yumc.pw/MiaoScript/1-user/1.1-check-env.html)
|
||||
- 开发文档 [](https://docs.yumc.pw/MiaoScript/2-develop/1.1-check-env.html)
|
||||
- 兼容服务端 Spigot CatServer Sponge BungeeCord Nukkit(没错 他还兼容Nukkit)
|
||||
|
||||
### 腐竹版本(开发中)
|
||||
|
||||
- 先上几张图
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"useWorkspaces": true,
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
"build": "lerna run build --scope=\"@ccms/!(plugins)\"",
|
||||
"build:plugins": "lerna run build --scope=\"@ccms/plugins\"",
|
||||
"ug": "yarn upgrade-interactive --latest",
|
||||
"np": "lerna exec \"npm publish --registry https://registry.npmjs.org\" --scope=\"@ccms/!(client|plugins|types)\"",
|
||||
"lp": "lerna publish"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"lerna": "^3.20.2"
|
||||
"lerna": "^3.21.0"
|
||||
}
|
||||
}
|
||||
1
packages/api/.npmignore
Symbolic link
1
packages/api/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/api",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -19,8 +19,8 @@
|
||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/container": "^0.6.0",
|
||||
"@ccms/ployfill": "^0.6.4",
|
||||
"@ccms/container": "^0.7.0",
|
||||
"@ccms/ployfill": "^0.7.0",
|
||||
"base64-js": "^1.3.1",
|
||||
"source-map-builder": "^0.0.7"
|
||||
},
|
||||
@@ -28,6 +28,6 @@
|
||||
"@types/base64-js": "^1.2.5",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ enum LogLevel {
|
||||
export class MiaoScriptConsole implements Console {
|
||||
Console: NodeJS.ConsoleConstructor;
|
||||
|
||||
private sourceMaps: { [key: string]: SourceMapBuilder } = {};
|
||||
private sourceFileMaps: { [key: string]: string } = {};
|
||||
private static sourceMaps: { [key: string]: SourceMapBuilder } = {};
|
||||
private static sourceFileMaps: { [key: string]: string } = {};
|
||||
private _name: string = '';
|
||||
private _level: LogLevel = LogLevel.INFO;
|
||||
|
||||
@@ -93,8 +93,8 @@ export class MiaoScriptConsole implements Console {
|
||||
readSourceMap(fileName: string, lineNumber: number) {
|
||||
try {
|
||||
if (fileName.endsWith('js')) {
|
||||
if (this.sourceMaps[fileName] === undefined) {
|
||||
this.sourceMaps[fileName] = null
|
||||
if (MiaoScriptConsole.sourceMaps[fileName] === undefined) {
|
||||
MiaoScriptConsole.sourceMaps[fileName] = null
|
||||
let sourceLine = base.read(fileName).split('\n');
|
||||
let lastLine = sourceLine[sourceLine.length - 1]
|
||||
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
||||
@@ -109,14 +109,14 @@ export class MiaoScriptConsole implements Console {
|
||||
if (file.exists()) { sourceContent = base.read(file) }
|
||||
}
|
||||
if (sourceContent) {
|
||||
this.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||
this.sourceFileMaps[fileName] = Paths.get(fileName, '..', this.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath();
|
||||
MiaoScriptConsole.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||
MiaoScriptConsole.sourceFileMaps[fileName] = Paths.get(fileName, '..', MiaoScriptConsole.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.sourceMaps[fileName]) {
|
||||
let sourceMapping = this.sourceMaps[fileName].getSource(lineNumber, 25, true, true);
|
||||
fileName = this.sourceFileMaps[fileName]
|
||||
if (MiaoScriptConsole.sourceMaps[fileName]) {
|
||||
let sourceMapping = MiaoScriptConsole.sourceMaps[fileName].getSource(lineNumber, 25, true, true);
|
||||
fileName = MiaoScriptConsole.sourceFileMaps[fileName]
|
||||
if (sourceMapping && lineNumber != sourceMapping.mapping.sourceLine) { lineNumber = sourceMapping.mapping.sourceLine; }
|
||||
}
|
||||
}
|
||||
@@ -136,11 +136,11 @@ export class MiaoScriptConsole implements Console {
|
||||
stack = Arrays.asList(stack)
|
||||
}
|
||||
stack.forEach(trace => {
|
||||
if (trace.fileName.startsWith('jar:file:')) { return }
|
||||
if (!trace.fileName || trace.fileName.startsWith('jar:file:')) { return }
|
||||
if (trace.className.startsWith('<')) {
|
||||
let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||
cache.push(` §e->§c ${fileName} => §4${trace.methodName}:${lineNumber}`)
|
||||
cache.push(` §e->§c ${fileName}:${lineNumber} => §4${trace.methodName}`)
|
||||
} else {
|
||||
let className = trace.className;
|
||||
var fileName = trace.fileName as string;
|
||||
|
||||
@@ -11,6 +11,7 @@ export namespace constants {
|
||||
Bukkit = 'bukkit',
|
||||
Sponge = 'sponge',
|
||||
Nukkit = 'nukkit',
|
||||
Bungee = 'bungee'
|
||||
Bungee = 'bungee',
|
||||
Spring = 'spring'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ export namespace server {
|
||||
getPluginsFolder(): string;
|
||||
getNativePluginManager(): NativePluginManager;
|
||||
getNettyPipeline(): any;
|
||||
getRootLogger(): any;
|
||||
sendJson(sender: string | any, json: object | string): void;
|
||||
tabComplete?(sender: string | any, input: string, index?: number);
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/bukkit/.npmignore
Symbolic link
1
packages/bukkit/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/bukkit",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript bukkit package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,11 +21,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/common": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ let Bukkit = org.bukkit.Bukkit;
|
||||
export class BukkitServer implements server.Server {
|
||||
private pluginsFolder: string;
|
||||
private pipeline: any;
|
||||
private rootLogger: any;
|
||||
|
||||
constructor() {
|
||||
this.pluginsFolder = Bukkit.getUpdateFolderFile().getParentFile().getCanonicalPath();
|
||||
this.reflectPipeline()
|
||||
this.reflect()
|
||||
}
|
||||
|
||||
getPlayer(name: string) {
|
||||
@@ -49,6 +50,9 @@ export class BukkitServer implements server.Server {
|
||||
getNettyPipeline() {
|
||||
return this.pipeline;
|
||||
}
|
||||
getRootLogger() {
|
||||
return this.rootLogger;
|
||||
}
|
||||
sendJson(sender: string | any, json: object | string): void {
|
||||
if (typeof sender === "string") {
|
||||
sender = this.getPlayer(sender)
|
||||
@@ -59,14 +63,20 @@ export class BukkitServer implements server.Server {
|
||||
}
|
||||
}
|
||||
|
||||
private reflectPipeline() {
|
||||
private reflect() {
|
||||
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
|
||||
this.reflectPipeline(consoleServer)
|
||||
this.reflectRootLogger(consoleServer)
|
||||
}
|
||||
|
||||
private reflectPipeline(consoleServer: any) {
|
||||
let connection: any;
|
||||
let promise: any;
|
||||
for (const method of constants.Reflect.Method.getServerConnection) {
|
||||
try {
|
||||
connection = reflect.on(consoleServer).call(method).get()
|
||||
if (connection.class.name.indexOf('ServerConnection') !== -1) { break; }
|
||||
if (connection.class.name.indexOf('ServerConnection') !== -1
|
||||
|| connection.class.name.indexOf('NetworkSystem') !== -1) { break; }
|
||||
connection = undefined;
|
||||
} catch (error) { }
|
||||
}
|
||||
@@ -81,4 +91,12 @@ export class BukkitServer implements server.Server {
|
||||
if (!promise) { console.error("Can't found listeningChannels!"); return }
|
||||
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
|
||||
}
|
||||
|
||||
private reflectRootLogger(consoleServer: any) {
|
||||
try {
|
||||
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
|
||||
} catch (error) {
|
||||
console.error("Can't found rootLogger!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/bungee/.npmignore
Symbolic link
1
packages/bungee/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/bungee",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript bungee package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,11 +21,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/common": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ let Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy();
|
||||
export class BungeeServer implements server.Server {
|
||||
private pluginsFolder: string;
|
||||
private pipeline: any;
|
||||
private rootLogger: any;
|
||||
|
||||
@inject(task.TaskManager)
|
||||
private task: task.TaskManager
|
||||
@@ -35,6 +36,11 @@ export class BungeeServer implements server.Server {
|
||||
}
|
||||
}
|
||||
}).later(10).timer(20).submit()
|
||||
try {
|
||||
this.rootLogger = Bungee.getLogger()
|
||||
} catch (error) {
|
||||
console.error("Can't found rootLogger!")
|
||||
}
|
||||
}
|
||||
|
||||
getPlayer(name: string) {
|
||||
@@ -70,6 +76,9 @@ export class BungeeServer implements server.Server {
|
||||
getNettyPipeline() {
|
||||
return this.pipeline;
|
||||
}
|
||||
getRootLogger() {
|
||||
return this.rootLogger;
|
||||
}
|
||||
sendJson(sender: string | any, json: string): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
1
packages/client/.npmignore
Symbolic link
1
packages/client/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@ccms/client",
|
||||
"version": "0.6.3",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript client package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -26,6 +26,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/common/.npmignore
Symbolic link
1
packages/common/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/common",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,10 +21,10 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/nashorn": "^0.6.4"
|
||||
"@ccms/nashorn": "^0.7.0"
|
||||
},
|
||||
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
||||
}
|
||||
|
||||
1
packages/compile/.npmignore
Symbolic link
1
packages/compile/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/compile",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript compile package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,6 +21,6 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/container/.npmignore
Symbolic link
1
packages/container/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/container",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript container package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,7 +21,7 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"inversify": "^5.0.1",
|
||||
|
||||
1
packages/core/.npmignore
Symbolic link
1
packages/core/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/core",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,11 +21,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
},
|
||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { plugin, server, task, constants } from '@ccms/api'
|
||||
import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ccms/container'
|
||||
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
||||
import http from '@ccms/common/dist/http'
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
@provideSingleton(MiaoScriptCore)
|
||||
class MiaoScriptCore {
|
||||
@@ -25,6 +26,7 @@ class MiaoScriptCore {
|
||||
}
|
||||
|
||||
loadServerConsole() {
|
||||
global.setGlobal('eventCenter', new EventEmitter(), { writable: false, configurable: false });
|
||||
//@ts-ignore
|
||||
global.setGlobal('console', new this.Console(), { writable: false, configurable: false })
|
||||
}
|
||||
@@ -43,14 +45,14 @@ class MiaoScriptCore {
|
||||
console.i18n("ms.core.plugin.initialize")
|
||||
this.pluginManager.scan(this.pluginFolder)
|
||||
this.pluginManager.build()
|
||||
this.pluginManager.load()
|
||||
this.pluginManager.enable()
|
||||
this.pluginManager.load(this.pluginManager.getPlugins())
|
||||
this.pluginManager.enable(this.pluginManager.getPlugins())
|
||||
console.i18n("ms.core.plugin.completed", { time: (new Date().getTime() - loadPluginStartTime) / 1000 })
|
||||
}
|
||||
|
||||
disable() {
|
||||
console.i18n("ms.core.engine.disable")
|
||||
this.pluginManager.disable()
|
||||
this.pluginManager.disable(this.pluginManager.getPlugins())
|
||||
this.taskManager.disable()
|
||||
//@ts-ignore
|
||||
require.disable()
|
||||
@@ -78,6 +80,11 @@ function detectServer(): constants.ServerType {
|
||||
return constants.ServerType.Bungee
|
||||
} catch (ex) {
|
||||
}
|
||||
try {
|
||||
Java.type("org.springframework.boot.SpringApplication")
|
||||
return constants.ServerType.Spring
|
||||
} catch (ex) {
|
||||
}
|
||||
throw Error('Unknow Server Type...')
|
||||
}
|
||||
|
||||
|
||||
1
packages/i18n/.npmignore
Symbolic link
1
packages/i18n/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -43,4 +43,6 @@ ms.plugin.manager.build.error: "§6Load Plugin From §b{file} §6failed. §4Erro
|
||||
ms.plugin.manager.build.update: "Auto Update Plugin {name} ..."
|
||||
ms.plugin.manager.build.not.extends: "§4Found error plugin §b{source} §4it's not extends interfaces.Plugin, the plugin will be ignore!"
|
||||
ms.plugin.manager.build.exists: "§4Found duplicate plugin §b{exists} §4and §b{source}§4. the first plugin will be ignore!"
|
||||
ms.plugin.manager.config.load.error: "[{plugin}] config {name}.{format} load failed. Error: {error}"
|
||||
ms.plugin.manager.config.save.error: "[{plugin}] config {name}.{format} save failed. Error: {error}"
|
||||
ms.plugin.manager.config.save.default: "[{plugin}] config {name}.{format} not exists. auto create from default variable..."
|
||||
|
||||
@@ -43,4 +43,6 @@ ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4
|
||||
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
|
||||
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
|
||||
ms.plugin.manager.build.duplicate: "§4发现已存在插件 §b{exists} §4和 §b{source}§4 存在冲突. 已存在插件将会被替换!"
|
||||
ms.plugin.manager.config.load.error: "[{plugin}] 配置 {name}.{format} 加载失败. 错误: {error}"
|
||||
ms.plugin.manager.config.save.error: "[{plugin}] 配置 {name}.{format} 保存失败. 错误: {error}"
|
||||
ms.plugin.manager.config.save.default: "[{plugin}] 配置 {name}.{format} 不存在. 从默认值自动创建保存..."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/i18n",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript i18n package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -22,10 +22,10 @@
|
||||
"@types/js-yaml": "^3.12.3",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/nashorn": "^0.6.4",
|
||||
"@ccms/nashorn": "^0.7.0",
|
||||
"js-yaml": "^3.13.1"
|
||||
},
|
||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
test
|
||||
typings
|
||||
bundled
|
||||
build
|
||||
coverage
|
||||
docs
|
||||
wiki
|
||||
gulpfile.js
|
||||
bower.json
|
||||
karma.conf.js
|
||||
tsconfig.json
|
||||
typings.json
|
||||
CONTRIBUTING.md
|
||||
ISSUE_TEMPLATE.md
|
||||
PULL_REQUEST_TEMPLATE.md
|
||||
tslint.json
|
||||
wallaby.js
|
||||
.travis.yml
|
||||
.gitignore
|
||||
.vscode
|
||||
.theia
|
||||
type_definitions
|
||||
1
packages/nashorn/.npmignore
Symbolic link
1
packages/nashorn/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/nashorn",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -22,6 +22,6 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ declare global {
|
||||
logger: any;
|
||||
debug: boolean;
|
||||
level: string;
|
||||
eventCenter: EventEmitter;
|
||||
NashornEngineStartTime: number;
|
||||
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void;
|
||||
noop: () => void;
|
||||
@@ -70,6 +71,9 @@ declare global {
|
||||
console(...args: any): void;
|
||||
i18n(name: string, ...params: any[]): void;
|
||||
}
|
||||
interface ProxyConstructor {
|
||||
newProxy<T extends object>(target: T, handler: ProxyHandler<T>): T;
|
||||
}
|
||||
}
|
||||
|
||||
export { };
|
||||
|
||||
1
packages/nodejs/.npmignore
Symbolic link
1
packages/nodejs/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/nodejs",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript nodejs package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,10 +21,10 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/nashorn": "^0.6.4"
|
||||
"@ccms/nashorn": "^0.7.0"
|
||||
},
|
||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||
}
|
||||
|
||||
1
packages/nukkit/.npmignore
Symbolic link
1
packages/nukkit/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/nukkit",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript nukkit package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,11 +21,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/common": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ export class NukkitServer implements server.Server {
|
||||
getNettyPipeline() {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getRootLogger() {
|
||||
return Packages.org.apache.logging.log4j.LogManager.getRootLogger()
|
||||
}
|
||||
sendJson(sender: string | any, json: object | string): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
1
packages/ployfill/.npmignore
Symbolic link
1
packages/ployfill/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/ployfill",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript ployfill package",
|
||||
"author": "MiaoWoo <admin@yumc.pw>",
|
||||
"homepage": "https://github.com/circlecloud/ms.git",
|
||||
@@ -14,13 +14,13 @@
|
||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/i18n": "^0.6.4",
|
||||
"@ccms/nashorn": "^0.6.4",
|
||||
"core-js": "^3.6.4"
|
||||
"@ccms/i18n": "^0.7.0",
|
||||
"@ccms/nashorn": "^0.7.0",
|
||||
"core-js": "^3.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ i18n.initialize();
|
||||
console.i18n("ms.ployfill.initialize");
|
||||
require('./es5-ext');
|
||||
require('core-js');
|
||||
require('./node-shim');
|
||||
global.setGlobal('Proxy', require('./proxy').Proxy)
|
||||
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
|
||||
global.setGlobal('Blob', require('blob-polyfill').Blob)
|
||||
|
||||
8
packages/ployfill/src/node-shim.ts
Normal file
8
packages/ployfill/src/node-shim.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
global.setGlobal('process', {
|
||||
env: {
|
||||
__noSuchProperty__: (prop) => {
|
||||
return Packages.java.lang.System.getenv(prop)
|
||||
}
|
||||
},
|
||||
platform: Packages.java.lang.System.getProperty("os.name")
|
||||
}, {})
|
||||
@@ -82,10 +82,12 @@ export class XMLHttpRequest {
|
||||
private _url: string;
|
||||
private _async: boolean;
|
||||
private _mimeType: string;
|
||||
private _requestHeaders: HttpHeader = {};
|
||||
|
||||
private _status: number = 0;
|
||||
private _statusText: string = null;
|
||||
private _response: any;
|
||||
private _responseText: any;
|
||||
private _responseURL: string;
|
||||
private _responseHeaders: HttpHeader = {};
|
||||
|
||||
@@ -114,10 +116,10 @@ export class XMLHttpRequest {
|
||||
return this._statusText;
|
||||
}
|
||||
get response() {
|
||||
return this._response ? JSON.parse(this._response) : this._response;
|
||||
return this._response || this.get();
|
||||
}
|
||||
get responseText() {
|
||||
return this._response;
|
||||
return this._responseText;
|
||||
}
|
||||
get responseXML() {
|
||||
return this._response;
|
||||
@@ -126,17 +128,17 @@ export class XMLHttpRequest {
|
||||
return this._responseURL;
|
||||
}
|
||||
|
||||
onload() { }
|
||||
onerror(ex: Error) { }
|
||||
onabort() { }
|
||||
onprogress() { }
|
||||
ontimeout(ex: Error) { }
|
||||
onloadend() { }
|
||||
onloadstart() { }
|
||||
onreadystatechange() { }
|
||||
public onload: () => void;
|
||||
public onerror: (ex: Error) => void;
|
||||
public onabort: () => void;
|
||||
public onprogress: () => void;
|
||||
public ontimeout: (ex: Error) => void;
|
||||
public onloadend: () => void;
|
||||
public onloadstart: () => void;
|
||||
public onreadystatechange: () => void;
|
||||
|
||||
setRequestHeader(key: string, val: string) {
|
||||
this._connection.setRequestProperty(key, val);
|
||||
this._requestHeaders[key] = val;
|
||||
}
|
||||
getResponseHeader(key: string): string {
|
||||
return this._responseHeaders[key];
|
||||
@@ -171,30 +173,36 @@ export class XMLHttpRequest {
|
||||
this.setReadyState(ReadyState.OPENED);
|
||||
}
|
||||
send(body?: string | object): Future<string> {
|
||||
for (const header in this._requestHeaders) {
|
||||
this._connection.setRequestProperty(header, this._requestHeaders[header]);
|
||||
}
|
||||
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
|
||||
let future = executor.submit(new Callable({ call: () => this._send(body) }));
|
||||
if (!this._async) { future.get() }
|
||||
return future;
|
||||
}
|
||||
get() {
|
||||
if (this._response === undefined) {
|
||||
switch (this._responseType) {
|
||||
case "json":
|
||||
return this.response;
|
||||
return this._response = JSON.parse(this._responseText);
|
||||
case "text":
|
||||
return this.responseText;
|
||||
return this._response = this._responseText;
|
||||
default:
|
||||
throw Error(`Unsupport ResponseType: ${this._responseType} !`)
|
||||
}
|
||||
}
|
||||
return this._response;
|
||||
}
|
||||
abort() {
|
||||
this._connection.disconnect();
|
||||
this.onabort();
|
||||
this.onabort && this.onabort();
|
||||
}
|
||||
|
||||
private _send(body?: string | object) {
|
||||
try {
|
||||
this._connection.connect();
|
||||
this.onloadstart();
|
||||
this.onloadstart && this.onloadstart();
|
||||
if (body) {
|
||||
let bodyType = Object.prototype.toString.call(body);
|
||||
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string!`) }
|
||||
@@ -207,14 +215,14 @@ export class XMLHttpRequest {
|
||||
this._status = this._connection.getResponseCode();
|
||||
this._statusText = this._connection.getResponseMessage();
|
||||
if (this._status >= 0 && this._status < 300) {
|
||||
this._response = this.readOutput(this._connection.getInputStream());
|
||||
this._responseText = this.readOutput(this._connection.getInputStream());
|
||||
} else if (this._status >= 300 && this._status < 400) {
|
||||
this._responseURL = this.getResponseHeader('Location');
|
||||
} else {
|
||||
this._response = this.readOutput(this._connection.getErrorStream());
|
||||
this._responseText = this.readOutput(this._connection.getErrorStream());
|
||||
}
|
||||
this.setResponseHeaders(this._connection.getHeaderFields());
|
||||
this.onloadend();
|
||||
this.onloadend && this.onloadend();
|
||||
} catch (ex) {
|
||||
if (ex instanceof SocketTimeoutException && this.ontimeout) {
|
||||
return this.ontimeout(ex)
|
||||
@@ -236,7 +244,7 @@ export class XMLHttpRequest {
|
||||
|
||||
private setReadyState(state: ReadyState) {
|
||||
this._readyState = state;
|
||||
this.onreadystatechange();
|
||||
this.onreadystatechange && this.onreadystatechange();
|
||||
}
|
||||
|
||||
private readOutput(input: any) {
|
||||
|
||||
1
packages/plugin/.npmignore
Symbolic link
1
packages/plugin/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/plugin",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -22,13 +22,13 @@
|
||||
"@types/js-yaml": "^3.12.3",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/common": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0",
|
||||
"@ccms/i18n": "^0.6.4",
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0",
|
||||
"@ccms/i18n": "^0.7.0",
|
||||
"js-yaml": "^3.13.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export class YamlPluginConfig implements PluginConfigLoader {
|
||||
return yaml.safeLoad(content);
|
||||
}
|
||||
dump(variable: any): string {
|
||||
return yaml.safeDump(variable);
|
||||
return yaml.safeDump(variable, { skipInvalid: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { injectable, decorate } from "@ccms/container";
|
||||
import { injectable, decorate } from "@ccms/container"
|
||||
import { interfaces } from './interfaces'
|
||||
import { METADATA_KEY } from './constants'
|
||||
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources } from './utils'
|
||||
@@ -9,17 +9,17 @@ import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata
|
||||
*/
|
||||
export function plugin(metadata: interfaces.PluginMetadata) {
|
||||
return function (target: any) {
|
||||
metadata.target = target;
|
||||
metadata.type = "ioc";
|
||||
decorate(injectable(), target);
|
||||
Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target);
|
||||
const previousMetadata: Map<string, interfaces.PluginMetadata> = getPluginMetadatas();
|
||||
previousMetadata.set(metadata.name, metadata);
|
||||
Reflect.defineMetadata(METADATA_KEY.plugin, previousMetadata, Reflect);
|
||||
const previousSources: Map<string, interfaces.PluginMetadata> = getPluginSources();
|
||||
previousSources.set(metadata.source.toString(), metadata);
|
||||
Reflect.defineMetadata(METADATA_KEY.souece, previousSources, Reflect);
|
||||
};
|
||||
metadata.target = target
|
||||
metadata.type = "ioc"
|
||||
decorate(injectable(), target)
|
||||
Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target)
|
||||
const previousMetadata: Map<string, interfaces.PluginMetadata> = getPluginMetadatas()
|
||||
previousMetadata.set(metadata.name, metadata)
|
||||
Reflect.defineMetadata(METADATA_KEY.plugin, previousMetadata, Reflect)
|
||||
const previousSources: Map<string, interfaces.PluginMetadata> = getPluginSources()
|
||||
previousSources.set(metadata.source.toString(), metadata)
|
||||
Reflect.defineMetadata(METADATA_KEY.souece, previousSources, Reflect)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,13 +28,13 @@ export function plugin(metadata: interfaces.PluginMetadata) {
|
||||
*/
|
||||
export function cmd(metadata: interfaces.CommandMetadata = {}) {
|
||||
return function (target: any, key: string, value: any) {
|
||||
metadata.name = metadata.name || key;
|
||||
metadata.executor = key;
|
||||
metadata.name = metadata.name || key
|
||||
metadata.executor = key
|
||||
metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key)
|
||||
const previousMetadata: Map<string, interfaces.CommandMetadata> = getPluginCommandMetadata(target)
|
||||
previousMetadata.set(metadata.name, metadata);
|
||||
Reflect.defineMetadata(METADATA_KEY.cmd, previousMetadata, target.constructor);
|
||||
};
|
||||
previousMetadata.set(metadata.name, metadata)
|
||||
Reflect.defineMetadata(METADATA_KEY.cmd, previousMetadata, target.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,14 +43,14 @@ export function cmd(metadata: interfaces.CommandMetadata = {}) {
|
||||
*/
|
||||
export function tab(metadata: interfaces.CommandMetadata = {}) {
|
||||
return function (target: any, key: string, value: any) {
|
||||
metadata.name = metadata.name || (key.startsWith('tab') ? key.split('tab', 2)[1] : key);
|
||||
if (!metadata.name) { return; }
|
||||
metadata.executor = key;
|
||||
metadata.name = metadata.name || (key.startsWith('tab') ? key.split('tab', 2)[1] : key)
|
||||
if (!metadata.name) { return }
|
||||
metadata.executor = key
|
||||
metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key)
|
||||
const previousMetadata: Map<string, interfaces.CommandMetadata> = getPluginTabCompleterMetadata(target)
|
||||
previousMetadata.set(metadata.name, metadata)
|
||||
Reflect.defineMetadata(METADATA_KEY.tab, previousMetadata, target.constructor);
|
||||
};
|
||||
Reflect.defineMetadata(METADATA_KEY.tab, previousMetadata, target.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,30 +59,32 @@ export function tab(metadata: interfaces.CommandMetadata = {}) {
|
||||
*/
|
||||
export function listener(metadata: interfaces.ListenerMetadata = {}) {
|
||||
return function (target: any, key: string, value: any) {
|
||||
metadata.name = metadata.name || key;
|
||||
metadata.executor = key;
|
||||
metadata.name = metadata.name || key
|
||||
metadata.executor = key
|
||||
const previousMetadata: interfaces.ListenerMetadata[] = getPluginListenerMetadata(target)
|
||||
Reflect.defineMetadata(METADATA_KEY.listener, [metadata, ...previousMetadata], target.constructor);
|
||||
};
|
||||
Reflect.defineMetadata(METADATA_KEY.listener, [metadata, ...previousMetadata], target.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
export function config(metadata: interfaces.ConfigMetadata = { version: 1, format: 'yml' }) {
|
||||
export function config(metadata: interfaces.ConfigMetadata = {}) {
|
||||
return function (target: any, key: string) {
|
||||
metadata.name = metadata.name || key;
|
||||
metadata.variable = key;
|
||||
metadata.name = metadata.name || key
|
||||
metadata.variable = key
|
||||
metadata.version = metadata.version ?? 1
|
||||
metadata.format = metadata.format ?? 'yml'
|
||||
const previousMetadata: Map<string, interfaces.ConfigMetadata> = getPluginConfigMetadata(target)
|
||||
previousMetadata.set(metadata.name, metadata);
|
||||
Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor);
|
||||
previousMetadata.set(metadata.name, metadata)
|
||||
Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
function stage(metadata: interfaces.ExecMetadata = {}, stage: string) {
|
||||
return function (target: any, key: string, value: any) {
|
||||
metadata.name = metadata.name || key;
|
||||
metadata.executor = key;
|
||||
metadata.name = metadata.name || key
|
||||
metadata.executor = key
|
||||
const previousMetadata: interfaces.ExecMetadata[] = getPluginStageMetadata(target, stage)
|
||||
Reflect.defineMetadata(METADATA_KEY.stage[stage], [metadata, ...previousMetadata], target.constructor);
|
||||
};
|
||||
Reflect.defineMetadata(METADATA_KEY.stage[stage], [metadata, ...previousMetadata], target.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
export function load(metadata: interfaces.ExecMetadata = {}) {
|
||||
|
||||
@@ -100,6 +100,10 @@ export namespace interfaces {
|
||||
* 配置文件格式 默认 yml
|
||||
*/
|
||||
format?: string;
|
||||
/**
|
||||
* 是否为只读(关闭时将不会自动保存)
|
||||
*/
|
||||
readonly?: boolean;
|
||||
}
|
||||
export type PluginLike = Plugin | string;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
@inject(plugin.PluginInstance)
|
||||
private pluginInstance: any
|
||||
@inject(plugin.PluginFolder)
|
||||
private pluginFolder: string;
|
||||
private pluginFolder: string
|
||||
@inject(server.ServerType)
|
||||
private serverType: string
|
||||
@inject(command.Command)
|
||||
@@ -30,14 +30,14 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
private pluginMetadataMap: Map<string, interfaces.PluginMetadata>
|
||||
|
||||
initialize() {
|
||||
if (this.pluginInstance !== null && this.initialized !== true) {
|
||||
// 如果plugin不等于null 则代表是正式环境
|
||||
if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
|
||||
if (this.initialized !== true) {
|
||||
console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
|
||||
console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType });
|
||||
console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType })
|
||||
this.pluginRequireMap = new Map()
|
||||
this.pluginInstanceMap = new Map()
|
||||
this.pluginMetadataMap = getPluginSources();
|
||||
this.initialized = true;
|
||||
this.pluginMetadataMap = getPluginSources()
|
||||
this.initialized = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
* @param file java.io.File
|
||||
*/
|
||||
loadFromFile(file: string): interfaces.Plugin {
|
||||
let metadata = this.loadPlugin(file);
|
||||
let metadata = this.loadPlugin(file)
|
||||
let plugin = this.buildPlugin(metadata && metadata.description ? metadata.description : this.pluginMetadataMap.get(file.toString()))
|
||||
this.load(plugin)
|
||||
this.enable(plugin)
|
||||
return plugin;
|
||||
return plugin
|
||||
}
|
||||
|
||||
load(...args: any[]): void {
|
||||
@@ -96,6 +96,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
disable(...args: any[]): void {
|
||||
this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
|
||||
this.runPluginStage(plugin, 'disable', () => {
|
||||
this.saveConfig(plugin)
|
||||
this.unregistryCommand(plugin)
|
||||
this.unregistryListener(plugin)
|
||||
})
|
||||
@@ -123,7 +124,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
}
|
||||
|
||||
private checkAndGet(name: string | interfaces.Plugin | undefined | any): Map<string, interfaces.Plugin> | interfaces.Plugin[] {
|
||||
if (name == undefined) { return this.pluginInstanceMap }
|
||||
if (name == this.pluginInstanceMap) { return this.pluginInstanceMap }
|
||||
if (typeof name == 'string' && this.pluginInstanceMap.has(name)) { return [this.pluginInstanceMap.get(name)] }
|
||||
if (name instanceof interfaces.Plugin) { return [name as interfaces.Plugin] }
|
||||
if (name.description || name.description.name) { return [name as interfaces.Plugin] }
|
||||
@@ -197,14 +198,14 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
private createPlugin(file: string) {
|
||||
//@ts-ignore
|
||||
let instance = require(file, { cache: false })
|
||||
this.pluginRequireMap.set(file, instance);
|
||||
return instance;
|
||||
this.pluginRequireMap.set(file, instance)
|
||||
return instance
|
||||
}
|
||||
|
||||
private buildPlugins() {
|
||||
let metadatas = [];
|
||||
let metadatas = []
|
||||
let pluginMetadatas = getPluginMetadatas()
|
||||
for (const [_, metadata] of pluginMetadatas) { metadatas.push(metadata); }
|
||||
for (const [_, metadata] of pluginMetadatas) { metadatas.push(metadata) }
|
||||
for (const [_, instance] of this.pluginRequireMap) { if (instance.description) { this.buildPlugin(instance.description) } }
|
||||
for (const metadata of metadatas) {
|
||||
if (!this.allowProcess(metadata.servers)) { continue }
|
||||
@@ -213,7 +214,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
}
|
||||
|
||||
private buildPlugin(metadata: interfaces.PluginMetadata) {
|
||||
let pluginInstance: interfaces.Plugin;
|
||||
let pluginInstance: interfaces.Plugin
|
||||
switch (metadata.type) {
|
||||
case "ioc":
|
||||
try {
|
||||
@@ -227,15 +228,15 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
console.i18n("ms.plugin.manager.initialize.error", { name: metadata.name, ex })
|
||||
console.ex(ex)
|
||||
}
|
||||
break;
|
||||
break
|
||||
case "basic":
|
||||
pluginInstance = this.pluginRequireMap.get(metadata.source.toString())
|
||||
break;
|
||||
break
|
||||
default:
|
||||
throw new Error('§4不支持的插件类型 请检查加载器是否正常启用!')
|
||||
}
|
||||
this.pluginInstanceMap.set(metadata.name, pluginInstance)
|
||||
return pluginInstance;
|
||||
return pluginInstance
|
||||
}
|
||||
|
||||
private bindPlugin(metadata: interfaces.PluginMetadata) {
|
||||
@@ -251,15 +252,40 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
}
|
||||
|
||||
private loadConfig(plugin: interfaces.Plugin) {
|
||||
let configs = getPluginConfigMetadata(plugin);
|
||||
let configs = getPluginConfigMetadata(plugin)
|
||||
for (let [_, config] of configs) {
|
||||
try {
|
||||
let configFile = fs.concat(root, this.pluginFolder, plugin.description.name, config.name + '.' + config.format)
|
||||
let configFactory = getConfigLoader(config.format);
|
||||
let configFactory = getConfigLoader(config.format)
|
||||
if (!fs.exists(configFile)) {
|
||||
base.save(configFile, configFactory.dump(plugin[config.variable]))
|
||||
console.i18n("ms.plugin.manager.config.save.default", { plugin: plugin.description.name, name: config.name, format: config.format })
|
||||
} else {
|
||||
plugin[config.variable] = configFactory.load(base.read(configFile));
|
||||
plugin[config.variable] = configFactory.load(base.read(configFile))
|
||||
plugin[config.variable].save = () => {
|
||||
let result = configFactory.dump(plugin[config.variable])
|
||||
base.save(configFile, result)
|
||||
console.debug(`[${plugin.description.name}] Save Config ${config.variable} to file ${configFile} result ${result}`)
|
||||
}
|
||||
console.debug(`[${plugin.description.name}] Load Config ${config.variable} from file ${configFile} result ${JSON.stringify(plugin[config.variable])}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.i18n("ms.plugin.manager.config.load.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
|
||||
console.ex(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private saveConfig(plugin: interfaces.Plugin) {
|
||||
let configs = getPluginConfigMetadata(plugin)
|
||||
for (let [_, config] of configs) {
|
||||
try {
|
||||
let configFile = fs.concat(root, this.pluginFolder, plugin.description.name, config.name + '.' + config.format)
|
||||
let configFactory = getConfigLoader(config.format)
|
||||
if (!config.readonly) { base.save(configFile, configFactory.dump(plugin[config.variable])) }
|
||||
} catch (error) {
|
||||
console.i18n("ms.plugin.manager.config.save.error", { plugin: plugin.description.name, name: config.name, format: config.format, error })
|
||||
console.ex(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,7 +325,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
||||
}
|
||||
|
||||
private execPluginStage(pluginInstance: interfaces.Plugin, stageName: string) {
|
||||
let stages = getPluginStageMetadata(pluginInstance, stageName);
|
||||
let stages = getPluginStageMetadata(pluginInstance, stageName)
|
||||
for (const stage of stages) {
|
||||
if (!this.allowProcess(stage.servers)) { continue }
|
||||
console.i18n("ms.plugin.manager.stage.exec", { plugin: pluginInstance.description.name, name: stage.executor, stage: stageName, servers: stage.servers })
|
||||
|
||||
1
packages/plugins/.npmignore
Symbolic link
1
packages/plugins/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
60
packages/plugins/docs/MiaoConsole.md
Normal file
60
packages/plugins/docs/MiaoConsole.md
Normal file
@@ -0,0 +1,60 @@
|
||||
## 前言
|
||||
|
||||
> 各位开发 在调试Minecraft插件的时候 是不是经常面临下列情况
|
||||
- 编译等半天 重启等半天 测试找不到问题
|
||||
- 后台 IDE SCP/FTP 来回切换
|
||||
|
||||
### 什么是MiaoConsole
|
||||
- MiaoConsole 是 基于 MiaoScript 开发的 在线调试工具
|
||||
- 通过复用 Minecraft的Netty 通道 实现服务器端口 在线调试(并不是Java的调试哦)
|
||||
|
||||
### 工具动图
|
||||
|
||||

|
||||

|
||||
|
||||
### MiaoConsole 有哪些功能
|
||||
- 无需编译 上传等步骤 实时在线debug
|
||||
- 实时转发服务端日志 无需来回切换
|
||||
- 基于Nashorn的动态脚本语言
|
||||
- 基于TypeScript的自动补全逻辑(以实现BungeeCord Sponge Bukkit的API全自动补全)
|
||||
|
||||
### MiaoConsole 的兼容性
|
||||
- 跨端兼容 Sponge Bukkit BungeeCord
|
||||
- Bukkit 支持 1.12.2 +(由于1.12.2以下版本Netty版本过老需要适配 后续兼容到1.7.10)
|
||||
- Sponge 理论上全兼容
|
||||
- CatServer 暂未测试 理论上兼容 1.12.2
|
||||
- BungeeCord ~~终端转发暂未兼容~~ 已经能兼容了
|
||||
|
||||
### 安装教程
|
||||
- 安装MiaoScript [下载地址](http://w.yumc.pw/free.html#MiaoScript-download)
|
||||
- 首次启动 等待加载基础环境类库
|
||||
- 执行 `mpm i MiaoConsole`
|
||||
|
||||
### 使用教程
|
||||
- 执行 `mconsole token` 获得临时Token
|
||||
- 打开 `http://ms.yumc.pw/console.html`
|
||||
- 在地址栏输入服务器地址 需要带上端口
|
||||
- 在Token栏输入获取到的Token
|
||||
- 点击链接即可
|
||||
|
||||
### 终端使用
|
||||
- 支持实时传输服务器日志到终端
|
||||
- 直接在终端输入命令 会转发到服务器
|
||||
- 目前暂不支持命令自动补全
|
||||
- 支持命令历史
|
||||
|
||||
### 代码编辑器使用
|
||||
- 支持 Java 的 lang包和util包自动补全
|
||||
- 支持服务端所有代码补全
|
||||
- 注意 暂时不支持自动导入包 所以需要手动输入全类名
|
||||
- 快捷键说明(选中代码后 只会执行选中部分)
|
||||
- Ctrl + R 执行代码
|
||||
- Ctrl + E 执行命令
|
||||
- Ctrl + Q 切换代码页
|
||||
|
||||
### RoadMap
|
||||
- 支持命令自动补全
|
||||
- 支持常用的开发脚本
|
||||
- 支持快捷操作服务器数据
|
||||
- 支持在线编辑服务器文件(开发了一半)
|
||||
0
packages/plugins/docs/MiaoScript.md
Normal file
0
packages/plugins/docs/MiaoScript.md
Normal file
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@ccms/plugins",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript plugins package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -22,11 +22,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0",
|
||||
"@ccms/plugin": "^0.6.4"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0",
|
||||
"@ccms/plugin": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
/// <reference types="@ccms/types/dist/typings/sponge" />
|
||||
/// <reference types="@ccms/types/dist/typings/bungee" />
|
||||
|
||||
import { plugin as pluginApi, server, task } from '@ccms/api'
|
||||
import { plugin, interfaces, cmd } from '@ccms/plugin'
|
||||
import { plugin as pluginApi, server, task, constants } 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'
|
||||
import * as fs from '@ccms/common/dist/fs'
|
||||
import * as reflect from '@ccms/common/dist/reflect'
|
||||
|
||||
const suffixMap = {
|
||||
ts: 'typescript',
|
||||
@@ -14,7 +15,13 @@ const suffixMap = {
|
||||
yml: 'yaml'
|
||||
}
|
||||
|
||||
@plugin({ name: 'MiaoConsole', version: '1.0.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename })
|
||||
let help = [
|
||||
'§6========= §6[§aMiaoConsole§6] 帮助 §aBy §bMiaoWoo §6=========',
|
||||
'§6/mconsole §atoken [set] §e<Token> §6- §3生成/设置 登录Token',
|
||||
'§6/mconsole §areload §6- §3重载插件',
|
||||
]
|
||||
|
||||
@plugin({ name: 'MiaoConsole', prefix: 'Console', version: '1.0.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename })
|
||||
export class MiaoConsole extends interfaces.Plugin {
|
||||
@inject(ContainerInstance)
|
||||
private container: Container
|
||||
@@ -27,56 +34,191 @@ export class MiaoConsole extends interfaces.Plugin {
|
||||
@inject(pluginApi.PluginManager)
|
||||
private pluginManager: pluginApi.PluginManager
|
||||
@inject(pluginApi.PluginFolder)
|
||||
private pluginFolder: string;
|
||||
private pluginFolder: string
|
||||
|
||||
private pipeline: any;
|
||||
private socketIOServer: SocketIOServer;
|
||||
private token: string
|
||||
private instance: any
|
||||
private socketIOServer: SocketIOServer
|
||||
private rootLogger: any
|
||||
private appender: any
|
||||
private handler: any
|
||||
|
||||
@config()
|
||||
private secret = { token: undefined }
|
||||
|
||||
load() {
|
||||
if (this.secret.token) {
|
||||
this.token = this.secret.token
|
||||
this.logger.console(`§c已从配置文件加载永久Token §4请注意服务器安全!`)
|
||||
} else {
|
||||
this.token = Java.type('java.util.UUID').randomUUID().toString()
|
||||
this.logger.console(`§6已生成随机Token: §3${this.token} §c重启后或重新生成后失效!`)
|
||||
}
|
||||
}
|
||||
|
||||
@cmd()
|
||||
mconsole(sender: any, command: string, args: string[]) {
|
||||
if (args[0] == 'reload') {
|
||||
// @ts-ignore
|
||||
require.clear('websocket');
|
||||
this.pluginManager.reload(this);
|
||||
let cmdKey = 'cmd' + (args[0] || 'help')
|
||||
if (!this[cmdKey]) {
|
||||
console.sender(sender, '§4未知的子命令: §c' + cmdKey)
|
||||
console.sender(sender, `§6请执行 §b/${command} §ahelp §6查看帮助!`)
|
||||
return
|
||||
}
|
||||
let tfunc = new Function('pipeline', args.join(' '))
|
||||
tfunc.apply(this, [this.pipeline])
|
||||
args.shift()
|
||||
this[cmdKey](sender, ...args)
|
||||
}
|
||||
|
||||
cmdhelp(sender: any) {
|
||||
this.logger.sender(sender, help)
|
||||
}
|
||||
|
||||
cmdreload(sender: any) {
|
||||
// @ts-ignore
|
||||
require.clear('websocket')
|
||||
this.pluginManager.reload(this)
|
||||
return
|
||||
}
|
||||
|
||||
cmdtoken(sender: any, sub: string, token: string) {
|
||||
if (sub == "set") {
|
||||
this.secret.token = this.token = token
|
||||
this.logger.sender(sender, '§a已保存§6服务器登录Token:§3', this.token, '§4请勿分享给其他人 防止服务器被攻击!')
|
||||
return
|
||||
}
|
||||
this.token = Java.type('java.util.UUID').randomUUID().toString()
|
||||
this.logger.sender(sender, '§a已刷新§6服务器登录Token:§3', this.token, '§4请勿分享给其他人 防止服务器被攻击!')
|
||||
}
|
||||
|
||||
@tab()
|
||||
tabmconsole(sender: any, command: string, args: string[]) {
|
||||
if (args.length === 1) { return ["reload", "token"] }
|
||||
if (args[0] == "token") { return ["set"] }
|
||||
}
|
||||
|
||||
enable() {
|
||||
let count = 0;
|
||||
let count = 0
|
||||
let wait = this.task.create(() => {
|
||||
this.pipeline = this.server.getNettyPipeline()
|
||||
if (this.pipeline) {
|
||||
wait.cancel()
|
||||
this.instance = this.server.getNettyPipeline()
|
||||
if (this.instance) {
|
||||
wait?.cancel()
|
||||
this.createSocketIOServer()
|
||||
this.startSocketIOServer()
|
||||
}
|
||||
if (count > 30) { wait.cancel() }
|
||||
count++
|
||||
if (count++ > 30) {
|
||||
wait?.cancel()
|
||||
this.logger.console('§cNetty通道注入失败 §4所有功能将无法使用!')
|
||||
return
|
||||
}
|
||||
}).later(20).timer(40).submit()
|
||||
this.rootLogger = this.server.getRootLogger()
|
||||
}
|
||||
|
||||
@enable({ servers: [constants.ServerType.Bukkit, constants.ServerType.Sponge] })
|
||||
addLog4jForward() {
|
||||
if (this.rootLogger) {
|
||||
let AbstractAppender = Java.type('org.apache.logging.log4j.core.appender.AbstractAppender')
|
||||
let ProxyAppender = Java.extend(AbstractAppender, {
|
||||
append: (logEvent) => global.eventCenter.emit('log', logEvent.getMessage().getFormattedMessage())
|
||||
})
|
||||
this.appender = new ProxyAppender("ProxyLogger", null, null)
|
||||
this.appender.start()
|
||||
this.rootLogger.addAppender(this.appender)
|
||||
this.rootLogger.setAdditive(true)
|
||||
}
|
||||
}
|
||||
|
||||
@enable({ servers: [constants.ServerType.Bungee] })
|
||||
addLoggerForward() {
|
||||
if (this.rootLogger) {
|
||||
let AbstractHandler = Java.type('java.util.logging.Handler')
|
||||
let ProxyHandler = Java.extend(AbstractHandler, {
|
||||
publish: (record) => global.eventCenter.emit('log', record.getMessage()),
|
||||
flush: () => { },
|
||||
close: () => { }
|
||||
})
|
||||
this.handler = new ProxyHandler()
|
||||
this.rootLogger.addHandler(this.handler)
|
||||
}
|
||||
}
|
||||
|
||||
@enable({ servers: [constants.ServerType.Spring] })
|
||||
addLogbackForward() {
|
||||
if (this.rootLogger) {
|
||||
let AppenderBase = Java.type('ch.qos.logback.core.AppenderBase')
|
||||
let ProxyAppender = Java.extend(AppenderBase, {
|
||||
append: (logEvent) => global.eventCenter.emit('log', logEvent.getFormattedMessage())
|
||||
})
|
||||
this.appender = new ProxyAppender()
|
||||
this.appender.setName("NashornProxyAppender")
|
||||
this.appender.setContext(this.rootLogger.getLoggerContext())
|
||||
this.rootLogger.addAppender(this.appender)
|
||||
}
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.socketIOServer?.close()
|
||||
if (this.socketIOServer) {
|
||||
this.socketIOServer.close()
|
||||
global.eventCenter.removeAllListeners('log')
|
||||
}
|
||||
if (this.container.isBound(io.Instance)) {
|
||||
this.container.unbind(io.Instance)
|
||||
}
|
||||
}
|
||||
|
||||
@disable({ servers: [constants.ServerType.Bukkit, constants.ServerType.Sponge] })
|
||||
removeLog4jForward() {
|
||||
try {
|
||||
this.appender.stop()
|
||||
this.rootLogger.removeAppender(this.appender)
|
||||
} catch (error) {
|
||||
console.ex(error)
|
||||
}
|
||||
}
|
||||
|
||||
@disable({ servers: [constants.ServerType.Bungee] })
|
||||
removeLoggerForward() {
|
||||
try {
|
||||
this.rootLogger.removeHandler(this.handler)
|
||||
} catch (error) {
|
||||
console.ex(error)
|
||||
}
|
||||
}
|
||||
|
||||
@disable({ servers: [constants.ServerType.Spring] })
|
||||
removeLogbackForward() {
|
||||
try {
|
||||
this.rootLogger.detachAppender("NashornProxyAppender")
|
||||
} catch (error) {
|
||||
console.ex(error)
|
||||
}
|
||||
}
|
||||
|
||||
createSocketIOServer() {
|
||||
this.socketIOServer = io(this.pipeline, {
|
||||
this.socketIOServer = io(this.instance, {
|
||||
path: '/ws',
|
||||
root: '/home/project/TSWorkSpace/ms/packages/plugins/public'
|
||||
});
|
||||
root: fs.concat(root, 'wwwroot')
|
||||
})
|
||||
this.container.bind(io.Instance).toConstantValue(this.socketIOServer)
|
||||
}
|
||||
|
||||
startSocketIOServer() {
|
||||
let namespace = this.socketIOServer.of('/MiaoConsole')
|
||||
global.eventCenter.on('log', (msg) => namespace.emit('log', msg))
|
||||
namespace.on('connect', (client: SocketIOSocket) => {
|
||||
this.logger.console(`§6客户端 §b${client.id} §a新建连接...`)
|
||||
if (!this.token) {
|
||||
this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4服务器尚未设置 Token 无法连接!`)
|
||||
client.emit('unauthorized')
|
||||
client.disconnect(true)
|
||||
return
|
||||
}
|
||||
this.logger.console(`§6客户端 §b${client.id} §a请求连接 §4Token: §c********`)
|
||||
if (this.token != client.handshake.query.token) {
|
||||
this.logger.console(`§6客户端 §b${client.id} §4无效请求 请提供正确Token后再次连接!`)
|
||||
client.emit('unauthorized')
|
||||
client.disconnect(true)
|
||||
return
|
||||
}
|
||||
this.logger.console(`§6客户端 §b${client.id} §a新建连接 ${this.rootLogger ? '启动日志转发' : '§4转发日志启动失败'}...`)
|
||||
client.on('type', (fn) => {
|
||||
fn && fn(this.serverType)
|
||||
client.emit('log', `Currect Server Version is ${this.server.getVersion()}`)
|
||||
@@ -89,7 +231,7 @@ export class MiaoConsole extends interfaces.Plugin {
|
||||
try {
|
||||
client.emit('log', this.runCode(code, namespace, client))
|
||||
} catch (ex) {
|
||||
client.emit('log', '§4代码执行异常\n' + console.stack(ex).join('\n'))
|
||||
client.emit('log', `§4代码执行异常 错误: ${ex}\n${console.stack(ex).join('\n')}`)
|
||||
}
|
||||
})
|
||||
client.on('edit', (file: string, fn) => {
|
||||
@@ -101,14 +243,20 @@ export class MiaoConsole extends interfaces.Plugin {
|
||||
if (!fs.exists(file)) { return fn('§6插件 §a' + name + ' §6尚未安装 §c请先创建空文件 或安装插件!') }
|
||||
try {
|
||||
base.save(file, content)
|
||||
this.pluginManager.reload(name);
|
||||
this.pluginManager.reload(name)
|
||||
fn('§6插件 §a' + name + ' §6更新成功!')
|
||||
} catch (error) {
|
||||
this.logger.error(error)
|
||||
fn('§6插件 §a' + name + ' §4更新异常 错误: ' + error)
|
||||
|
||||
}
|
||||
})
|
||||
client.on('ls', (file: string, fn) => {
|
||||
let dir = fs.file(file);
|
||||
if (!dir.isDirectory()) {
|
||||
return fn(undefined, `${file} 不是一个目录!`)
|
||||
}
|
||||
fn(fs.list(dir))
|
||||
})
|
||||
client.on('error', (error) => {
|
||||
this.logger.console(`§6客户端 §b${client.id} §c触发异常: ${error}`)
|
||||
this.logger.error(error)
|
||||
@@ -117,7 +265,6 @@ export class MiaoConsole extends interfaces.Plugin {
|
||||
this.logger.console(`§6客户端 §b${client.id} §c断开连接...`)
|
||||
})
|
||||
})
|
||||
this.logger.info('Netty Channel Pipeline Inject MiaoDetectHandler Successful!')
|
||||
}
|
||||
|
||||
private runCode(code: string, namespace: any, client: any) {
|
||||
@@ -128,7 +275,7 @@ export class MiaoConsole extends interfaces.Plugin {
|
||||
tempconcent += text + "\\n"
|
||||
}
|
||||
var result = eval(${JSON.stringify(code)});
|
||||
return tempconcent + result
|
||||
return tempconcent + '§a返回结果: §r'+ result
|
||||
`)
|
||||
return this.task.callSyncMethod(() => tfunc.apply(this, [namespace, client])) + ''
|
||||
}
|
||||
|
||||
@@ -9,18 +9,21 @@ import http from '@ccms/common/dist/http'
|
||||
|
||||
let help = [
|
||||
'§6========= §6[§aMiaoScriptPackageManager§6] 帮助 §aBy §bMiaoWoo §6=========',
|
||||
'§6/mpm §ainstall §e<插件名称> §6- §3安装插件',
|
||||
'§6/mpm §auninstall §e<插件名称> §6- §3卸载插件',
|
||||
'§6/mpm §alist [install]§6- §3列出仓库插件[已安装的插件]',
|
||||
'§6/mpm §aupdate §e<插件名称> §6- §3更新插件(无插件名称则更新源)',
|
||||
'§6/mpm §aupgrade §e<插件名称> §6- §3及时更新插件(update需要重启生效)',
|
||||
'§6/mpm §areload §e<插件名称> §6- §3重载插件(无插件名称则重载自身)',
|
||||
'§6/mpm §ainstall §e<插件名称> §6- §3安装仓库插件',
|
||||
'§6/mpm §aload §e<插件名称> §6- §3安装本地插件',
|
||||
'§6/mpm §aunload §e<插件名称> §6- §3卸载已安装插件',
|
||||
'§6/mpm §areload §e<插件名称> §6- §3重载已安装插件(无名称则重载自身)',
|
||||
'§6/mpm §alist [i] §6- §3列出仓库插件[已安装的插件]',
|
||||
'§6/mpm §aupdate §e[插件名称] §6- §3更新插件(无名称则更新源)',
|
||||
'§6/mpm §aupgrade §e[插件名称] §6- §3升级插件/框架(§4无名称则升级框架§3)',
|
||||
'§6/mpm §arun §e<JS代码> §6- §3运行JS代码',
|
||||
'§6/mpm §adeploy §e<插件名称> §6- §3发布插件',
|
||||
'§6/mpm §crestart §6- §4重启MiaoScript脚本引擎'
|
||||
];
|
||||
|
||||
let langMap = {
|
||||
'main.command.not.exists': '§4未知的子命令: §c{command}',
|
||||
'main.command.help.tip': '§6请执行 §b/{command} §ahelp §6查看帮助!',
|
||||
'list.install.header': '§6当前 §bMiaoScript §6已安装下列插件:',
|
||||
'list.install.body': '§6插件名称: §b{name} §6版本: §a{version} §6作者: §3{author}',
|
||||
'list.header': '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:',
|
||||
@@ -36,13 +39,18 @@ let langMap = {
|
||||
'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确认执行!',
|
||||
'deploy.token.not.exists': '§4请先配置发布Token!',
|
||||
'deploy.success': '§6插件 §b{name} §a发布成功! §6服务器返回: §a{msg}',
|
||||
'deploy.fail': '§6插件 §b{name} §c发布失败! §6服务器返回: §c{msg}',
|
||||
'run.script': '§b运行脚本:§r {script}',
|
||||
'run.result': '§a返回结果:§r {result}',
|
||||
'run.noresult': '§4没有返回结果!',
|
||||
}
|
||||
|
||||
let fallbackMap = langMap
|
||||
|
||||
@plugin({ name: 'MiaoScriptPackageManager', prefix: 'PM', version: '1.0.0', author: 'MiaoWoo', source: __filename })
|
||||
@plugin({ name: 'MiaoScriptPackageManager', prefix: 'PM', version: '1.0.1', author: 'MiaoWoo', source: __filename })
|
||||
export class MiaoScriptPackageManager extends interfaces.Plugin {
|
||||
@inject(pluginApi.PluginManager)
|
||||
private pluginManager: pluginApi.PluginManager;
|
||||
@@ -78,31 +86,31 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
|
||||
}
|
||||
|
||||
main(sender: any, command: string, args: string[]) {
|
||||
let cmdKey = 'cmd' + args[0]
|
||||
let cmdKey = 'cmd' + (args[0] || 'help')
|
||||
if (!this[cmdKey]) {
|
||||
this.logger.sender(sender, '§4未知的子命令: §c' + args[0])
|
||||
this.logger.sender(sender, '§6请执行 §b/' + command + ' §ahelp §6查看帮助!')
|
||||
return;
|
||||
}
|
||||
if (args[0] === 'help') {
|
||||
this.logger.sender(sender, help);
|
||||
this.i18n(sender, 'main.command.not.exists', { command: args[0] })
|
||||
this.i18n(sender, 'main.command.help.tip', { command })
|
||||
return;
|
||||
}
|
||||
args.shift()
|
||||
this[cmdKey](sender, ...args);
|
||||
}
|
||||
|
||||
cmdhelp(sender: any) {
|
||||
this.logger.sender(sender, help);
|
||||
}
|
||||
|
||||
cmdload(sender: any, name: string) {
|
||||
let pluginFile = fs.concat(__dirname + '', name);
|
||||
if (!fs.exists(pluginFile)) {
|
||||
this.logger.sender(sender, '§4插件 §c' + pluginFile + ' §4不存在!')
|
||||
this.i18n(sender, 'plugin.not.exists', { name: `${name}(${pluginFile})` })
|
||||
return;
|
||||
}
|
||||
this.pluginManager.loadFromFile(fs.file(pluginFile));
|
||||
}
|
||||
|
||||
cmdlist(sender: any, type: string = 'cloud') {
|
||||
if (type == "install") {
|
||||
if (type == "i" || type == "install") {
|
||||
this.i18n(sender, 'list.install.header')
|
||||
this.pluginManager.getPlugins().forEach((plugin) => {
|
||||
this.i18n(sender, 'list.install.body', plugin.description);
|
||||
@@ -129,7 +137,8 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
|
||||
}
|
||||
|
||||
cmdupgrade(sender: any, name: string) {
|
||||
if (name == "system") {
|
||||
if (!name) { return this.i18n(sender, 'upgrade.confirm'); }
|
||||
if (name == "comfirm") {
|
||||
let enginePath = fs.path(fs.file(fs.concat(root, 'node_modules', '@ccms')))
|
||||
if (enginePath.startsWith(root)) {
|
||||
base.delete(enginePath);
|
||||
@@ -188,19 +197,21 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
|
||||
|
||||
cmdrun(sender: any, ...args: any[]) {
|
||||
try {
|
||||
var script = args.join(' ');
|
||||
this.logger.sender(sender, '§b运行脚本:§r', script);
|
||||
this.logger.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!');
|
||||
let script = args.join(' ');
|
||||
this.i18n(sender, 'run.script', { script })
|
||||
let result = eval(script);
|
||||
this.i18n(sender, 'run.result', { result: result == undefined ? this.translate.translate('run.noresult') : result + '' })
|
||||
} catch (ex) {
|
||||
this.logger.sender(sender, this.logger.stack(ex));
|
||||
}
|
||||
}
|
||||
|
||||
cmddeploy(sender: any, name: any) {
|
||||
if (!process.env.AccessToken) { return this.i18n(sender, 'deploy.token.not.exists') }
|
||||
this.taskManager.create(() => {
|
||||
if (this.checkPlugin(sender, name)) {
|
||||
let plugin: interfaces.Plugin = this.pluginManager.getPlugins().get(name);
|
||||
let result = http.post("http://ms.yumc.pw/api/plugin/deploy", {
|
||||
let result = http.post("http://ms.yumc.pw/api/plugin/deploy?access_token=" + process.env.AccessToken, {
|
||||
name,
|
||||
author: plugin.description.author,
|
||||
version: plugin.description.version,
|
||||
@@ -250,11 +261,15 @@ export class MiaoScriptPackageManager extends interfaces.Plugin {
|
||||
this.taskManager.create(() => {
|
||||
this.i18n(sender, 'download.start', { name })
|
||||
this.i18n(sender, 'download.url', { url: this.packageCache[name].url })
|
||||
let pluginFile = update ? fs.concat(this.pluginFolder, 'update', name + '.js') : fs.concat(this.pluginFolder, name + '.js')
|
||||
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 })
|
||||
this.pluginManager.loadFromFile(pluginFile)
|
||||
this.i18n(sender, update ? 'update.finish' : 'install.finish', { name })
|
||||
if (!update) {
|
||||
this.pluginManager.loadFromFile(fs.file(pluginFile))
|
||||
this.i18n(sender, 'install.finish', { name })
|
||||
} else {
|
||||
this.i18n(sender, 'update.finish', { name })
|
||||
}
|
||||
}).async().submit()
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/sponge/.npmignore
Symbolic link
1
packages/sponge/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/sponge",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript api package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,11 +21,11 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.6.4",
|
||||
"@ccms/common": "^0.6.4",
|
||||
"@ccms/container": "^0.6.0"
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,11 @@ const File = Java.type("java.io.File");
|
||||
export class SpongeServer implements server.Server {
|
||||
private pluginsFolder: string;
|
||||
private pipeline: any;
|
||||
private rootLogger: any;
|
||||
|
||||
constructor() {
|
||||
this.pluginsFolder = new File(base.getInstance().getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile().getCanonicalPath()
|
||||
this.reflectPipeline()
|
||||
this.reflect()
|
||||
}
|
||||
|
||||
getPlayer(name: string) {
|
||||
@@ -50,20 +51,27 @@ export class SpongeServer implements server.Server {
|
||||
getNettyPipeline() {
|
||||
return this.pipeline;
|
||||
}
|
||||
getRootLogger() {
|
||||
return this.rootLogger;
|
||||
}
|
||||
sendJson(sender: string | any, json: string): void {
|
||||
if (typeof sender === "string") {
|
||||
sender = this.getPlayer(sender)
|
||||
}
|
||||
sender.sendMessage(TextSerializers.JSON.deserialize(json))
|
||||
}
|
||||
private reflectPipeline() {
|
||||
private reflect() {
|
||||
let consoleServer = reflect.on(Sponge.getServer()).get()
|
||||
this.reflectPipeline(consoleServer)
|
||||
this.reflectRootLogger(consoleServer)
|
||||
}
|
||||
private reflectPipeline(consoleServer: any) {
|
||||
let connection: any;
|
||||
let promise: any;
|
||||
for (const method of constants.Reflect.Method.getServerConnection) {
|
||||
try {
|
||||
connection = reflect.on(consoleServer).call(method).get()
|
||||
if (connection.class.name.indexOf('ServerConnection') !== -1) { break; }
|
||||
if (connection.class.name.indexOf('NetworkSystem') !== -1) { break; }
|
||||
connection = undefined;
|
||||
} catch (error) { }
|
||||
}
|
||||
@@ -78,4 +86,11 @@ export class SpongeServer implements server.Server {
|
||||
if (!promise) { console.error("Can't found listeningChannels!"); return }
|
||||
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
|
||||
}
|
||||
private reflectRootLogger(consoleServer: any) {
|
||||
try {
|
||||
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
|
||||
} catch (error) {
|
||||
console.error("Can't found rootLogger!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/spring/.npmignore
Symbolic link
1
packages/spring/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
31
packages/spring/package.json
Normal file
31
packages/spring/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@ccms/spring",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript spring package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
"minecraft",
|
||||
"bukkit",
|
||||
"sponge"
|
||||
],
|
||||
"author": "MiaoWoo <admin@yumc.pw>",
|
||||
"homepage": "https://github.com/circlecloud/ms.git",
|
||||
"license": "ISC",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"watch": "tsc --watch",
|
||||
"build": "yarn clean && tsc",
|
||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/api": "^0.7.0",
|
||||
"@ccms/common": "^0.7.0",
|
||||
"@ccms/container": "^0.7.0"
|
||||
}
|
||||
}
|
||||
23
packages/spring/src/command.ts
Normal file
23
packages/spring/src/command.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import '@ccms/nashorn'
|
||||
|
||||
import { command, plugin } from '@ccms/api'
|
||||
import { inject, provideSingleton, postConstruct } from '@ccms/container'
|
||||
|
||||
@provideSingleton(command.Command)
|
||||
export class SpringCommand extends command.Command {
|
||||
@inject(plugin.PluginInstance)
|
||||
private pluginInstance: any
|
||||
|
||||
protected create(plugin: any, command: string) {
|
||||
console.console('§4Spring暂不支持create命令!')
|
||||
}
|
||||
protected remove(plugin: any, command: string) {
|
||||
console.console('§4Spring暂不支持remove命令!')
|
||||
}
|
||||
protected onCommand(plugin: any, command: any, executor: Function) {
|
||||
console.console('§4Spring暂不支持onCommand!')
|
||||
}
|
||||
protected onTabComplete(plugin: any, command: any, tabCompleter: Function) {
|
||||
console.console('§4Spring暂不支持onTabComplete!')
|
||||
}
|
||||
}
|
||||
41
packages/spring/src/console.ts
Normal file
41
packages/spring/src/console.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { MiaoScriptConsole } from '@ccms/api'
|
||||
|
||||
var colorMap = []
|
||||
colorMap['0'] = '38;5;0'
|
||||
colorMap['1'] = '38;5;4'
|
||||
colorMap['2'] = '38;5;2'
|
||||
colorMap['3'] = '38;5;6'
|
||||
colorMap['4'] = '38;5;1'
|
||||
colorMap['5'] = '38;5;5'
|
||||
colorMap['6'] = '38;5;3'
|
||||
colorMap['7'] = '38;5;7'
|
||||
colorMap['8'] = '38;5;8'
|
||||
colorMap['9'] = '38;5;12'
|
||||
colorMap['a'] = '38;5;10'
|
||||
colorMap['b'] = '38;5;14'
|
||||
colorMap['c'] = '38;5;9'
|
||||
colorMap['d'] = '38;5;13'
|
||||
colorMap['e'] = '38;5;11'
|
||||
colorMap['f'] = '38;5;15'
|
||||
colorMap['r'] = '0'
|
||||
colorMap['l'] = '1'
|
||||
colorMap['n'] = '4'
|
||||
var regexMap = []
|
||||
for (const c in colorMap) {
|
||||
regexMap[colorMap[c]] = new RegExp(`§${c}`, "g")
|
||||
}
|
||||
function mcColor2ANSI(str: string) {
|
||||
for (const regex in regexMap) {
|
||||
str = str.replace(regexMap[regex], `\u001b[${regex}m`)
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export class SpringConsole extends MiaoScriptConsole {
|
||||
sender(sender: any, ...args: any[]) {
|
||||
this.console(args.join(' '))
|
||||
}
|
||||
console(...args: string[]): void {
|
||||
this.logger.info(mcColor2ANSI(args.join(' ') + '§r'))
|
||||
}
|
||||
}
|
||||
24
packages/spring/src/event.ts
Normal file
24
packages/spring/src/event.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { event, plugin } from '@ccms/api'
|
||||
import { inject, provideSingleton } from '@ccms/container'
|
||||
|
||||
@provideSingleton(event.Event)
|
||||
export class SpringEvent extends event.Event {
|
||||
@inject(plugin.PluginInstance)
|
||||
private pluginInstance: any
|
||||
|
||||
constructor() {
|
||||
super('');
|
||||
}
|
||||
mapEventName() {
|
||||
return 0;
|
||||
}
|
||||
isValidEvent(clazz: any): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
register(eventCls: any, exec: Function, priority: any, ignoreCancel: boolean) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
unregister(event: any, listener: any): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
14
packages/spring/src/index.ts
Normal file
14
packages/spring/src/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { server, plugin } from '@ccms/api'
|
||||
import { Container } from '@ccms/container'
|
||||
|
||||
import { SpringConsole } from './console';
|
||||
import './event';
|
||||
import './server';
|
||||
import './command';
|
||||
import './task';
|
||||
|
||||
const BeanKit = Java.type('com.sixi.micro.common.kits.BeanKit')
|
||||
|
||||
export default function SpringImpl(container: Container) {
|
||||
container.bind(server.Console).toConstantValue(SpringConsole)
|
||||
}
|
||||
50
packages/spring/src/server.ts
Normal file
50
packages/spring/src/server.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { server } from '@ccms/api'
|
||||
import { provideSingleton } from '@ccms/container';
|
||||
import { NativePluginManager } from '@ccms/api/dist/interfaces/server/native_plugin';
|
||||
|
||||
@provideSingleton(server.Server)
|
||||
export class SpringServer implements server.Server {
|
||||
constructor() {
|
||||
}
|
||||
getVersion(): string {
|
||||
return "SpringFramework"
|
||||
}
|
||||
getPlayer(name: string) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getOnlinePlayers(): any[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getConsoleSender() {
|
||||
return undefined;
|
||||
}
|
||||
getService(service: string) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
dispatchCommand(sender: any, command: string): boolean {
|
||||
console.console('§4Spring暂不支持dispatchCommand!')
|
||||
return false;
|
||||
}
|
||||
dispatchConsoleCommand(command: string): boolean {
|
||||
console.console('§4Spring暂不支持dispatchConsoleCommand!')
|
||||
return false;
|
||||
}
|
||||
getPluginsFolder(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getNativePluginManager(): NativePluginManager {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getNettyPipeline() {
|
||||
return base.getInstance().getAutowireCapableBeanFactory()
|
||||
}
|
||||
getRootLogger() {
|
||||
return global.logger
|
||||
}
|
||||
sendJson(sender: any, json: string | object): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
tabComplete(sender: any, input: string, index?: number) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
88
packages/spring/src/task.ts
Normal file
88
packages/spring/src/task.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { task, plugin } from '@ccms/api'
|
||||
import { inject, provideSingleton } from '@ccms/container'
|
||||
|
||||
const AtomicBoolean = Java.type("java.util.concurrent.atomic.AtomicBoolean")
|
||||
const Thread = Java.type('java.lang.Thread')
|
||||
const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
|
||||
const ThreadPoolTaskExecutor = Java.type('org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor')
|
||||
|
||||
let executor: any
|
||||
let tasks: { [key: number]: task.Cancelable } = {}
|
||||
let taskId = 0
|
||||
|
||||
@provideSingleton(task.TaskManager)
|
||||
export class SpringTaskManager implements task.TaskManager {
|
||||
@inject(plugin.PluginInstance)
|
||||
private pluginInstance: any
|
||||
|
||||
constructor() {
|
||||
executor = new ThreadPoolTaskExecutor()
|
||||
executor.setCorePoolSize(10)
|
||||
executor.setMaxPoolSize(100)
|
||||
executor.setQueueCapacity(500)
|
||||
executor.setKeepAliveSeconds(60)
|
||||
executor.setThreadNamePrefix("@ccms/spring-")
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy())
|
||||
executor.initialize()
|
||||
}
|
||||
|
||||
create(func: Function): task.Task {
|
||||
if (Object.prototype.toString.call(func) !== "[object Function]") { throw TypeError('第一个参数 Task 必须为 function !') }
|
||||
return new SpringTask(this.pluginInstance, func)
|
||||
}
|
||||
callSyncMethod(func: Function): any {
|
||||
return func()
|
||||
}
|
||||
disable() {
|
||||
Object.values(tasks).forEach((task) => task.cancel())
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
export class SpringTask extends task.Task {
|
||||
public id = taskId++
|
||||
private running = new AtomicBoolean(true)
|
||||
|
||||
run() {
|
||||
if (this.laterTime > 0) {
|
||||
try {
|
||||
Thread.sleep(this.laterTime)
|
||||
} catch (ex) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
}
|
||||
while (this.running.get()) {
|
||||
try {
|
||||
this.func()
|
||||
} catch (t) {
|
||||
console.error("Task exec error:", t)
|
||||
console.ex(t)
|
||||
}
|
||||
// If we have a interval of 0 or less, only run once
|
||||
if (this.interval <= 0) { break }
|
||||
try {
|
||||
Thread.sleep(this.interval)
|
||||
} catch (ex) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
}
|
||||
this.cancel()
|
||||
}
|
||||
|
||||
cancel(): any {
|
||||
var wasRunning = this.running.getAndSet(false)
|
||||
if (wasRunning) {
|
||||
tasks[this.id] = undefined
|
||||
}
|
||||
}
|
||||
|
||||
submit(): task.Cancelable {
|
||||
tasks[this.id] = this
|
||||
executor.execute(this.run.bind(this))
|
||||
return {
|
||||
cancel: () => {
|
||||
return this.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
packages/spring/tsconfig.json
Normal file
7
packages/spring/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"outDir": "dist"
|
||||
}
|
||||
}
|
||||
22
packages/types/.npmignore
Normal file
22
packages/types/.npmignore
Normal file
@@ -0,0 +1,22 @@
|
||||
test
|
||||
bundled
|
||||
build
|
||||
coverage
|
||||
docs
|
||||
wiki
|
||||
gulpfile.js
|
||||
bower.json
|
||||
karma.conf.js
|
||||
tsconfig.json
|
||||
typings.json
|
||||
CONTRIBUTING.md
|
||||
ISSUE_TEMPLATE.md
|
||||
PULL_REQUEST_TEMPLATE.md
|
||||
tslint.json
|
||||
wallaby.js
|
||||
.travis.yml
|
||||
.gitignore
|
||||
.vscode
|
||||
.theia
|
||||
type_definitions
|
||||
tsconfig.tsbuildinfo
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/types",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript types package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
|
||||
1
packages/websocket/.npmignore
Symbolic link
1
packages/websocket/.npmignore
Symbolic link
@@ -0,0 +1 @@
|
||||
../../.npmignore
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ccms/websocket",
|
||||
"version": "0.6.4",
|
||||
"version": "0.7.0",
|
||||
"description": "MiaoScript websocket package",
|
||||
"keywords": [
|
||||
"miaoscript",
|
||||
@@ -21,9 +21,9 @@
|
||||
"devDependencies": {
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ccms/nashorn": "^0.6.4"
|
||||
"@ccms/nashorn": "^0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { SocketIO } from 'socket-io/interfaces';
|
||||
import { SocketIO } from '../socket-io/interfaces';
|
||||
import { AttributeKeys } from './constants';
|
||||
|
||||
const TextWebSocketFrame = Java.type('io.netty.handler.codec.http.websocketx.TextWebSocketFrame')
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
export enum ServerEvent {
|
||||
detect = 'detect',
|
||||
connect = 'connect',
|
||||
connection = 'connection',
|
||||
message = 'message',
|
||||
error = 'error',
|
||||
disconnect = 'disconnect'
|
||||
}
|
||||
|
||||
const AttributeKey = Java.type('io.netty.util.AttributeKey');
|
||||
|
||||
export enum Keys {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
import { NettyClient } from './client'
|
||||
import { ServerOptions } from '../socket-io'
|
||||
import { ServerEvent, Keys } from './constants'
|
||||
import { ServerEvent } from '../socket-io/constants'
|
||||
|
||||
import { NettyClient } from './client'
|
||||
import { Keys } from './constants'
|
||||
import { WebSocketDetect } from './websocket_detect'
|
||||
import { WebSocketHandler } from './websocket_handler'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { ServerEvent } from './constants'
|
||||
import { ServerOptions } from '../socket-io';
|
||||
import { ServerEvent } from '../socket-io/constants'
|
||||
import { TextWebSocketFrameHandlerAdapter } from '../netty'
|
||||
|
||||
export class TextWebSocketFrameHandler extends TextWebSocketFrameHandlerAdapter {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { WebSocketHandlerAdapter } from "../netty"
|
||||
import { ServerEvent } from './constants'
|
||||
import { ServerEvent } from '../socket-io/constants'
|
||||
|
||||
export class WebSocketDetect extends WebSocketHandlerAdapter {
|
||||
private event: EventEmitter;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
import { Keys, ServerEvent } from './constants'
|
||||
import { WebSocketHandlerAdapter } from "../netty"
|
||||
import { HttpRequestHandler } from './httprequest'
|
||||
import { TextWebSocketFrameHandler } from './text_websocket_frame'
|
||||
import { ServerOptions } from '../socket-io'
|
||||
import { ServerEvent } from '../socket-io/constants'
|
||||
|
||||
import { Keys } from './constants'
|
||||
import { HttpRequestHandler } from './httprequest'
|
||||
import { WebSocketHandlerAdapter } from "../netty"
|
||||
import { TextWebSocketFrameHandler } from './text_websocket_frame'
|
||||
|
||||
const CharsetUtil = Java.type('io.netty.util.CharsetUtil')
|
||||
|
||||
const HttpServerCodec = Java.type('io.netty.handler.codec.http.HttpServerCodec')
|
||||
const ChunkedWriteHandler = Java.type('io.netty.handler.stream.ChunkedWriteHandler')
|
||||
const HttpObjectAggregator = Java.type('io.netty.handler.codec.http.HttpObjectAggregator')
|
||||
|
||||
@@ -72,7 +72,7 @@ export class Adapter extends EventEmitter implements SocketIO.Adapter {
|
||||
var socket: Socket;
|
||||
|
||||
packet.nsp = this.nsp.name;
|
||||
// let encodedPackets = this.parser.encode(packet)
|
||||
let encodedPackets = this.parser.encode(packet)
|
||||
if (rooms.length) {
|
||||
for (var i = 0; i < rooms.length; i++) {
|
||||
var room = self.rooms[rooms[i]];
|
||||
@@ -83,7 +83,7 @@ export class Adapter extends EventEmitter implements SocketIO.Adapter {
|
||||
if (ids[id] || ~except.indexOf(id)) continue;
|
||||
socket = self.nsp.connected[id];
|
||||
if (socket) {
|
||||
socket.packet(packet, packetOpts);
|
||||
socket.packet(encodedPackets as any, packetOpts);
|
||||
ids[id] = true;
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,7 @@ export class Adapter extends EventEmitter implements SocketIO.Adapter {
|
||||
if (self.sids.hasOwnProperty(id)) {
|
||||
if (~except.indexOf(id)) continue;
|
||||
socket = self.nsp.connected[id];
|
||||
if (socket) socket.packet(packet, packetOpts);
|
||||
if (socket) socket.packet(encodedPackets as any, packetOpts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,34 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { Parser } from './parser'
|
||||
import { Packet } from './packet';
|
||||
import { NettyClient } from '../server';
|
||||
import { SocketIO } from './interfaces'
|
||||
import { Server, Socket } from './index';
|
||||
import { PacketTypes, SubPacketTypes } from './types';
|
||||
import { ServerEvent } from './constants';
|
||||
|
||||
const parser = new Parser();
|
||||
|
||||
export class Client extends EventEmitter implements SocketIO.Client {
|
||||
id: string;
|
||||
server: Server;
|
||||
conn: NettyClient;
|
||||
conn: SocketIO.EngineSocket;
|
||||
request: any;
|
||||
sockets: { [id: string]: Socket; };
|
||||
nsps: { [nsp: string]: SocketIO.Socket; };
|
||||
connectBuffer: any;
|
||||
|
||||
constructor(server: Server, nettyClient: NettyClient) {
|
||||
constructor(server: Server, engine: SocketIO.EngineSocket) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.conn = nettyClient;
|
||||
this.conn = engine;
|
||||
this.id = this.conn.id + '';
|
||||
this.request = nettyClient.request;
|
||||
this.request = engine.request;
|
||||
this.sockets = {};
|
||||
this.nsps = {};
|
||||
|
||||
this.conn.on(ServerEvent.disconnect, (reason) => {
|
||||
this.onclose(reason)
|
||||
})
|
||||
}
|
||||
connect(name, query) {
|
||||
if (this.server.nsps[name]) {
|
||||
@@ -62,8 +66,8 @@ export class Client extends EventEmitter implements SocketIO.Client {
|
||||
}
|
||||
});
|
||||
}
|
||||
packet(packet: Packet, opts?: any) {
|
||||
this.conn.send(parser.encode(packet))
|
||||
packet(packet: Packet, opts: any = { preEncoded: false }) {
|
||||
this.conn.send(opts.preEncoded ? packet as unknown as string : parser.encode(packet))
|
||||
}
|
||||
onclose(reason?: string) {
|
||||
// debug('client close with reason %s', reason);
|
||||
@@ -79,11 +83,11 @@ export class Client extends EventEmitter implements SocketIO.Client {
|
||||
// this.decoder.destroy(); // clean up decoder
|
||||
}
|
||||
disconnect() {
|
||||
// if ('open' == this.conn.readyState) {
|
||||
if ('open' == this.conn.readyState) {
|
||||
// debug('forcing transport close');
|
||||
this.conn.close();
|
||||
this.onclose('forced server close');
|
||||
// }
|
||||
}
|
||||
}
|
||||
remove(socket: Socket) {
|
||||
if (this.sockets.hasOwnProperty(socket.id)) {
|
||||
|
||||
8
packages/websocket/src/socket-io/constants.ts
Normal file
8
packages/websocket/src/socket-io/constants.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export enum ServerEvent {
|
||||
detect = 'detect',
|
||||
connect = 'connect',
|
||||
connection = 'connection',
|
||||
message = 'message',
|
||||
error = 'error',
|
||||
disconnect = 'disconnect'
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
import { NettyWebSocketServer, NettyClient } from '../server'
|
||||
import { ServerEvent } from '../server/constants';
|
||||
|
||||
import { ServerEvent } from './constants';
|
||||
import { Namespace } from './namespace';
|
||||
import { Client } from './client';
|
||||
import { SocketIO } from './interfaces'
|
||||
@@ -17,8 +15,12 @@ interface ServerOptions extends SocketIO.ServerOptions {
|
||||
root?: string;
|
||||
}
|
||||
|
||||
interface WebSocketServer extends EventEmitter {
|
||||
close(): void
|
||||
}
|
||||
|
||||
class Server implements SocketIO.Server {
|
||||
private nettyServer: NettyWebSocketServer;
|
||||
private websocketServer: WebSocketServer;
|
||||
private allClients: { [key: string]: Client };
|
||||
|
||||
engine: { ws: any; };
|
||||
@@ -31,17 +33,24 @@ class Server implements SocketIO.Server {
|
||||
_adapter: Adapter;
|
||||
options: ServerOptions;
|
||||
|
||||
constructor(pipeline: any, options: ServerOptions) {
|
||||
if (!pipeline) { throw new Error('Netty Pipeline can\'t be undefiend!') }
|
||||
constructor(instance: any, options: ServerOptions) {
|
||||
if (!instance) { throw new Error('instance can\'t be undefiend!') }
|
||||
this.allClients = {};
|
||||
this.nsps = {};
|
||||
this.sockets = new Namespace('/', this);
|
||||
this.nsps['/'] = this.sockets;
|
||||
this.initNettyServer(pipeline, Object.assign({
|
||||
if (instance.class.name.startsWith('io.netty.channel')) {
|
||||
let { NettyWebSocketServer } = require("../server")
|
||||
this.websocketServer = new NettyWebSocketServer(instance, Object.assign({
|
||||
event: new EventEmitter(),
|
||||
path: '/socket.io',
|
||||
root: root + '/wwwroot'
|
||||
}, options));
|
||||
} else {
|
||||
let { TomcatWebSocketServer } = require("../tomcat/server")
|
||||
this.websocketServer = new TomcatWebSocketServer(instance, options);
|
||||
}
|
||||
this.initServer()
|
||||
}
|
||||
|
||||
checkRequest(req: any, fn: (err: any, success: boolean) => void): void {
|
||||
@@ -114,7 +123,7 @@ class Server implements SocketIO.Server {
|
||||
for (let socket in this.sockets.sockets) {
|
||||
this.sockets.sockets[socket].onclose()
|
||||
}
|
||||
this.nettyServer.close();
|
||||
this.websocketServer.close();
|
||||
}
|
||||
on(event: "connection", listener: (socket: SocketIO.Socket) => void): SocketIO.Namespace;
|
||||
on(event: "connect", listener: (socket: SocketIO.Socket) => void): SocketIO.Namespace;
|
||||
@@ -152,17 +161,16 @@ class Server implements SocketIO.Server {
|
||||
fn(false);
|
||||
};
|
||||
|
||||
private initNettyServer(pipeline, options) {
|
||||
this.nettyServer = new NettyWebSocketServer(pipeline, options);
|
||||
this.nettyServer.on(ServerEvent.connect, (nettyClient: NettyClient) => {
|
||||
let client = new Client(this, nettyClient);
|
||||
private initServer() {
|
||||
this.websocketServer.on(ServerEvent.connect, (socket: SocketIO.EngineSocket) => {
|
||||
let client = new Client(this, socket);
|
||||
this.onconnection(client);
|
||||
})
|
||||
this.nettyServer.on(ServerEvent.message, (nettyClient: NettyClient, text) => {
|
||||
this.processPacket(this.parser.decode(text), this.allClients[nettyClient.id]);
|
||||
this.websocketServer.on(ServerEvent.message, (socket: SocketIO.EngineSocket, text) => {
|
||||
this.processPacket(this.parser.decode(text), this.allClients[socket.id]);
|
||||
})
|
||||
this.nettyServer.on(ServerEvent.error, (nettyClient: NettyClient, cause) => {
|
||||
console.error(`Client ${nettyClient.id} cause error: ` + cause)
|
||||
this.websocketServer.on(ServerEvent.error, (socket: SocketIO.EngineSocket, cause) => {
|
||||
console.error(`Client ${socket.id} cause error: ` + cause)
|
||||
console.ex(cause)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -727,6 +727,16 @@ export declare namespace SocketIO {
|
||||
*/
|
||||
del(id: string, room: string, callback?: (err?: any) => void): void;
|
||||
|
||||
/**
|
||||
* Adds a socket to a list of room.
|
||||
*
|
||||
* @param {String} socket id
|
||||
* @param {String} rooms
|
||||
* @param {Function} callback
|
||||
* @api public
|
||||
*/
|
||||
addAll(id: string, rooms: string | any[], fn: { (err?: any): void; bind?: any; });
|
||||
|
||||
/**
|
||||
* Removes a socket from all the rooms that it's joined
|
||||
* @param id The ID of the socket that we're removing
|
||||
@@ -820,5 +830,15 @@ export declare namespace SocketIO {
|
||||
* (Transport): transport reference
|
||||
*/
|
||||
transport: any;
|
||||
|
||||
/**
|
||||
* send
|
||||
*/
|
||||
send(text: string);
|
||||
|
||||
/**
|
||||
* close
|
||||
*/
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ import { EventEmitter } from 'events'
|
||||
|
||||
import { Client } from './client'
|
||||
import { SocketIO } from './interfaces';
|
||||
import { ServerEvent } from '../server';
|
||||
import { ServerEvent } from './constants';
|
||||
import { Socket } from './socket';
|
||||
import { Adapter } from './adapter';
|
||||
import { Server } from './index'
|
||||
import { Packet } from './packet';
|
||||
import { SubPacketTypes } from './types';
|
||||
import { PacketTypes, SubPacketTypes } from './types';
|
||||
|
||||
export class Namespace extends EventEmitter implements SocketIO.Namespace {
|
||||
name: string;
|
||||
@@ -78,7 +78,9 @@ export class Namespace extends EventEmitter implements SocketIO.Namespace {
|
||||
}
|
||||
// set up packet object
|
||||
var packet = {
|
||||
type: (this.flags.binary !== undefined ? this.flags.binary : this.hasBin(args)) ? SubPacketTypes.BINARY_EVENT : SubPacketTypes.EVENT,
|
||||
type: PacketTypes.MESSAGE,
|
||||
sub_type: (this.flags.binary !== undefined ? this.flags.binary : this.hasBin(args)) ? SubPacketTypes.BINARY_EVENT : SubPacketTypes.EVENT,
|
||||
name: event,
|
||||
data: args
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,11 @@ export class Parser {
|
||||
p.nsp = '/';
|
||||
}
|
||||
|
||||
// handle namespace query
|
||||
if (p.nsp.indexOf('?') !== -1) {
|
||||
p.nsp = p.nsp.split('?')[0];
|
||||
}
|
||||
|
||||
// look up id
|
||||
let next = str.charAt(i + 1);
|
||||
if ('' !== next && !isNaN(Number(next))) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Packet } from './packet';
|
||||
import { PacketTypes, SubPacketTypes } from './types';
|
||||
import { Client } from './client';
|
||||
import { Namespace } from './namespace';
|
||||
import * as querystring from 'querystring'
|
||||
|
||||
export class Socket extends EventEmitter implements SocketIO.Socket {
|
||||
nsp: Namespace;
|
||||
@@ -45,7 +46,7 @@ export class Socket extends EventEmitter implements SocketIO.Socket {
|
||||
this.acks = {};
|
||||
this.connected = true;
|
||||
this.disconnected = false;
|
||||
// this.handshake = this.buildHandshake(query);
|
||||
this.handshake = this.buildHandshake(query);
|
||||
this.fns = [];
|
||||
this.flags = {};
|
||||
this._rooms = [];
|
||||
@@ -97,6 +98,14 @@ export class Socket extends EventEmitter implements SocketIO.Socket {
|
||||
fn && fn(null);
|
||||
return this;
|
||||
}
|
||||
this.adapter.addAll(this.id, rooms, (err) => {
|
||||
if (err) return fn && fn(err);
|
||||
// debug('joined room %s', rooms);
|
||||
(rooms as Array<string>).forEach((room) => {
|
||||
this.rooms[room] = room;
|
||||
});
|
||||
fn && fn(null);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
leave(name: string, fn?: Function): SocketIO.Socket {
|
||||
@@ -127,16 +136,21 @@ export class Socket extends EventEmitter implements SocketIO.Socket {
|
||||
|
||||
// ==========================================
|
||||
buildHandshake(query): SocketIO.Handshake {
|
||||
let requestQuery = this.request.uri();
|
||||
let requestUri = this.request.uri();
|
||||
let headers = {};
|
||||
let nativeHeaders = this.request.headers();
|
||||
nativeHeaders.forEach(function (header) {
|
||||
headers[header.getKey()] = header.getValue();
|
||||
})
|
||||
return {
|
||||
headers: this.request.headers(),
|
||||
headers: headers,
|
||||
time: (new Date) + '',
|
||||
address: this.conn.remoteAddress,
|
||||
xdomain: !!this.request.headers.origin,
|
||||
secure: !!this.request.connection.encrypted,
|
||||
address: this.conn.remoteAddress + '',
|
||||
xdomain: !!headers['origin'],
|
||||
secure: false,
|
||||
issued: +(new Date),
|
||||
url: this.request.url,
|
||||
query: Object.assign(query, requestQuery)
|
||||
url: requestUri,
|
||||
query: Object.assign(query, querystring.parse(requestUri.indexOf('?') != -1 ? requestUri.split('?')[1] : ''))
|
||||
}
|
||||
}
|
||||
emit(event: string, ...args: any[]): boolean {
|
||||
@@ -183,10 +197,11 @@ export class Socket extends EventEmitter implements SocketIO.Socket {
|
||||
// @ts-ignore
|
||||
return this;
|
||||
}
|
||||
packet(packet: Packet, opts?: any) {
|
||||
packet(packet: Packet, opts: any = { preEncoded: false }) {
|
||||
if (!opts.preEncoded) {
|
||||
packet.nsp = this.nsp.name;
|
||||
opts = opts || {};
|
||||
opts.compress = false !== opts.compress;
|
||||
}
|
||||
this.client.packet(packet, opts);
|
||||
}
|
||||
onconnect() {
|
||||
|
||||
44
packages/websocket/src/tomcat/client.ts
Normal file
44
packages/websocket/src/tomcat/client.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { SocketIO } from '../socket-io/interfaces';
|
||||
|
||||
export class TomcatClient extends EventEmitter implements SocketIO.EngineSocket {
|
||||
private _id: string;
|
||||
private session: any
|
||||
|
||||
server: any;
|
||||
readyState: string;
|
||||
remoteAddress: string;
|
||||
upgraded: boolean;
|
||||
request: any;
|
||||
transport: any;
|
||||
|
||||
constructor(server: any, session: any) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.readyState = 'open';
|
||||
this.remoteAddress = session + ''
|
||||
this.upgraded = true;
|
||||
this.request = {
|
||||
uri: () => {
|
||||
return session.getRequestURI() + ''
|
||||
},
|
||||
headers: () => {
|
||||
return []
|
||||
}
|
||||
};
|
||||
this.transport = null;
|
||||
|
||||
this.session = session;
|
||||
this._id = session.getId();
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
}
|
||||
send(text: string) {
|
||||
this.session.getBasicRemote().sendText(text)
|
||||
}
|
||||
close() {
|
||||
this.session.close();
|
||||
}
|
||||
}
|
||||
1
packages/websocket/src/tomcat/constants.ts
Normal file
1
packages/websocket/src/tomcat/constants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const ProxyBeanName = "webSocketServerProxy"
|
||||
69
packages/websocket/src/tomcat/server.ts
Normal file
69
packages/websocket/src/tomcat/server.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
import { ServerOptions } from '../socket-io'
|
||||
import { ServerEvent } from '../socket-io/constants'
|
||||
import { SocketIO } from '../socket-io/interfaces'
|
||||
import { ProxyBeanName } from './constants'
|
||||
import { TomcatClient } from './client'
|
||||
|
||||
const WebSocketServerProxy = Java.type("com.sixi.framework.scriptservice.websocket.WebSocketServerProxy")
|
||||
const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
|
||||
const ThreadPoolTaskExecutor = Java.type('org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor')
|
||||
|
||||
interface TomcatWebSocketSession {
|
||||
getId: () => number
|
||||
}
|
||||
|
||||
class TomcatWebSocketServer extends EventEmitter {
|
||||
private beanFactory: any
|
||||
private executor: any
|
||||
private allClients: { [key: string]: SocketIO.EngineSocket }
|
||||
|
||||
constructor(beanFactory: any, options: ServerOptions) {
|
||||
super()
|
||||
this.allClients = {}
|
||||
this.beanFactory = beanFactory
|
||||
this.initThreadPool()
|
||||
try { this.beanFactory.destroySingleton(ProxyBeanName) } catch (error) { }
|
||||
let NashornWebSocketServerProxy = Java.extend(WebSocketServerProxy, {
|
||||
onOpen: (session: TomcatWebSocketSession) => {
|
||||
let tomcatClient = new TomcatClient(this, session)
|
||||
this.allClients[tomcatClient.id] = tomcatClient
|
||||
this.emit(ServerEvent.connect, tomcatClient)
|
||||
},
|
||||
onMessage: (message: any, session: TomcatWebSocketSession) => {
|
||||
this.executor.execute(() => {
|
||||
this.emit(ServerEvent.message, this.allClients[session.getId()], message)
|
||||
})
|
||||
},
|
||||
onClose: (session: TomcatWebSocketSession, reason: any) => {
|
||||
this.emit(ServerEvent.disconnect, this.allClients[session.getId()], reason)
|
||||
},
|
||||
onError: (session: TomcatWebSocketSession, error: any) => {
|
||||
this.emit(ServerEvent.error, this.allClients[session.getId()], error)
|
||||
},
|
||||
})
|
||||
this.beanFactory.registerSingleton(ProxyBeanName, new NashornWebSocketServerProxy())
|
||||
}
|
||||
private initThreadPool() {
|
||||
this.executor = new ThreadPoolTaskExecutor()
|
||||
this.executor.setCorePoolSize(10)
|
||||
this.executor.setMaxPoolSize(100)
|
||||
this.executor.setQueueCapacity(500)
|
||||
this.executor.setKeepAliveSeconds(60)
|
||||
this.executor.setThreadNamePrefix("@ccms/websocket-")
|
||||
this.executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy())
|
||||
this.executor.initialize()
|
||||
}
|
||||
close() {
|
||||
Object.values(this.allClients).forEach(client => client.close())
|
||||
this.beanFactory.destroySingleton(ProxyBeanName)
|
||||
this.executor.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
TomcatWebSocketServer,
|
||||
ServerEvent,
|
||||
TomcatClient
|
||||
}
|
||||
Reference in New Issue
Block a user