Compare commits
72 Commits
v0.18.0
...
v0.28.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
| e70c78a255 | |||
| 9cfac1672a | |||
| 9126ec8035 | |||
| 23bc6068b5 | |||
| 27b428fbe2 | |||
| c07f1131c4 | |||
| 002f2c47c6 | |||
| 8633d9ea95 | |||
| 07a5d0c8de | |||
| dd76e563c8 | |||
| 7b85ff5b7c | |||
| 359aeb9d63 | |||
| 3901d9fb5f | |||
| c2867da047 | |||
| 65832c9fae | |||
| d9dffa704d | |||
| b39f29de6a | |||
| 56334c6f6e | |||
| 72673b2a67 | |||
| 597bdb721a | |||
| 6e0456d777 | |||
| fb67b06230 | |||
| 203560dcf2 | |||
| 3f58f5992c | |||
| ac16754c9c | |||
| 42d637dd63 | |||
| df0d246136 | |||
| e563e1b507 | |||
| 3b822c613a | |||
| 2967c2a1fe | |||
| 1c579c9789 | |||
| 2fe9bce2ea | |||
| 496d278a93 | |||
| bdf674b678 | |||
| 67fe13deac | |||
| 30846cdc87 | |||
| d8d03149df | |||
| b6d7847a79 | |||
| 58f59f8260 | |||
| f3fa14990f | |||
| 15d1f8392b | |||
| b5fac23c5c | |||
| 148f6c28c4 | |||
| 880065495e | |||
| 7fc70a92d5 | |||
| df6da12a8a | |||
| 082f2b8f73 | |||
| 7cd85f3f34 | |||
| 073cf6aaac | |||
| 43aa39b86f | |||
| cb58fbdb6c | |||
| 86aacf1a1f | |||
| 47413c6766 | |||
| 4ee8fc9a20 | |||
| 8d0484eefb | |||
| 579d89ae89 | |||
| 010f561766 | |||
| 848aacd991 | |||
| ab5559b26f | |||
| 46729b9cf0 | |||
| 83cad2f52e | |||
| a5cb084767 | |||
| 16ab108186 | |||
| a1df719dc9 | |||
| 41e5754492 | |||
| 866d1dd62c | |||
| 8056d3060d | |||
| b8440b83de | |||
| b55e662f81 | |||
| db526e9444 | |||
| 1b0ea9fa05 | |||
| 143c960da5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.yarn*
|
||||||
.vscode
|
.vscode
|
||||||
.theia
|
.theia
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
src
|
||||||
test
|
test
|
||||||
typings
|
typings
|
||||||
bundled
|
bundled
|
||||||
|
|||||||
47
README.MD
47
README.MD
@@ -8,27 +8,28 @@
|
|||||||
|
|
||||||
```txt
|
```txt
|
||||||
└─packages
|
└─packages
|
||||||
├─api 全平台兼容的接口
|
├─api 全平台兼容的接口
|
||||||
├─core 核心代码 用于引导加载
|
├─core 核心代码 用于引导加载
|
||||||
├─common 公共类库代码 例如 http reflect 模块
|
├─common 公共类库代码 例如 http reflect 模块
|
||||||
├─client NodeJS的Minecraft客户端 用于调试插件
|
├─compile 编译器相关功能
|
||||||
├─container IOC容器 用于注入具体实现
|
├─client NodeJS 的 Minecraft 客户端 已迁移至 ms-client
|
||||||
├─ployfill Nashorn 的一些自定义增强
|
├─container IOC容器 用于注入具体实现
|
||||||
├─nashorn Nashorn 的类型定义
|
├─database 数据库相关功能
|
||||||
├─bungee BungeeCordAPI内部实现
|
├─protocol 协议处理相关功能
|
||||||
├─bukkit BukkitAPI内部实现
|
├─service 服务相关功能
|
||||||
├─sponge SpongeAPI内部实现
|
├─i18n 多语言环境相关支持
|
||||||
├─nukkit NukkitAPI内部实现
|
├─polyfill Nashorn 的一些自定义增强
|
||||||
├─plugin 插件管理器
|
├─nashorn Nashorn 的类型定义
|
||||||
├─websocket Netty的WebSocket注入
|
├─nodejs NodeJS 的部分 Java 实现
|
||||||
├─type Java的类型定义
|
├─bungee BungeeCordAPI 内部实现
|
||||||
| ├─bungee BungeeCord类型定义
|
├─bukkit BukkitAPI 内部实现
|
||||||
| ├─bukkit Bukkit类型定义
|
├─sponge SpongeAPI 内部实现
|
||||||
| ├─sponge Sponge类型定义
|
├─nukkit NukkitAPI 内部实现
|
||||||
| └─nukkit Nukkit类型定义
|
├─molang MoLang 解析库
|
||||||
└─plugins 这里当然是插件啦
|
├─qrcode 二维码相关类库
|
||||||
├─bungee 只兼容BungeeCord的插件
|
├─plugin 插件管理器
|
||||||
├─bukkit 只兼容Bukkit的插件
|
├─websocket WebSocket 相关实现
|
||||||
├─sponge 只兼容Sponge的插件
|
| ├─client 基于 Netty 的 WebSocket 客户端
|
||||||
└─nukkit 只兼容Nukkit的插件
|
| └─server 基于 Netty 的 WebSocket 服务端
|
||||||
|
└─type 类型定义 已迁移到 @javatypes
|
||||||
```
|
```
|
||||||
|
|||||||
26
lerna.json
26
lerna.json
@@ -1,17 +1,15 @@
|
|||||||
{
|
{
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"useWorkspaces": true,
|
"npmClient": "yarn",
|
||||||
"npmClient": "yarn",
|
"packages": [
|
||||||
"packages": [
|
"packages/*"
|
||||||
"packages/*"
|
],
|
||||||
],
|
"command": {
|
||||||
"command": {
|
"run": {
|
||||||
"run": {
|
"stream": true
|
||||||
"stream": true
|
|
||||||
},
|
|
||||||
"publish": {
|
|
||||||
"access": "public",
|
|
||||||
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -10,15 +10,19 @@
|
|||||||
"clean": "lerna run clean",
|
"clean": "lerna run clean",
|
||||||
"watch": "lerna run watch --parallel",
|
"watch": "lerna run watch --parallel",
|
||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"ug": "yarn upgrade-interactive --latest",
|
"ug": "yarn upgrade-interactive",
|
||||||
"np": "./script/push.sh",
|
"np": "./script/push.sh",
|
||||||
"lsp": "npm login --registry=https://registry.npmjs.org --scope=@ccms",
|
"lsp": "npm login -scope=@ccms",
|
||||||
"lp": "lerna publish --registry https://registry.npmjs.org"
|
"lp": "lerna publish --force-publish",
|
||||||
|
"lpb": "lerna publish --preid beta --dist-tag beta --force-publish",
|
||||||
|
"lpc": "lerna publish --canary --preid beta --pre-dist-tag beta --force-publish",
|
||||||
|
"lpf": "lerna publish from-package --yes",
|
||||||
|
"sync": "./script/sync.sh"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lerna": "^4.0.0"
|
"lerna": "^7.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/amqp",
|
"name": "@ccms/amqp",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript amqp package",
|
"description": "MiaoScript amqp package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,17 +19,17 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"@javatypes/amqp-client": "^0.0.3",
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
"@javatypes/spring-amqp": "^0.0.3",
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
"@javatypes/spring-rabbit": "^0.0.3",
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/api",
|
"name": "@ccms/api",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,16 +19,16 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0",
|
"@ccms/container": "^0.28.0-beta.2",
|
||||||
"@ccms/polyfill": "^0.18.0",
|
"@ccms/polyfill": "^0.28.0-beta.2",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"source-map-builder": "^0.0.7"
|
"source-map-builder": "^0.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/base64-js": "^1.3.0",
|
"@types/base64-js": "^1.3.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ import { plugin } from './plugin'
|
|||||||
export namespace command {
|
export namespace command {
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class Command {
|
export abstract class Command {
|
||||||
|
/**
|
||||||
|
* first time script engine need optimize jit code
|
||||||
|
* so ignore first slow exec notify
|
||||||
|
*/
|
||||||
|
private cacheSlowCommandKey = {};
|
||||||
|
private cacheSlowCompleteKey = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册插件命令
|
* 注册插件命令
|
||||||
* @param plugin 插件
|
* @param plugin 插件
|
||||||
@@ -44,12 +51,33 @@ export namespace command {
|
|||||||
protected setExecutor(plugin: plugin.Plugin, command: any, executor: Function) {
|
protected setExecutor(plugin: plugin.Plugin, command: any, executor: Function) {
|
||||||
return (sender: any, _: any, command: string, args: string[]) => {
|
return (sender: any, _: any, command: string, args: string[]) => {
|
||||||
try {
|
try {
|
||||||
return executor(sender, command, Java.from(args))
|
let time = Date.now()
|
||||||
|
let result = executor(sender, command, Java.from(args))
|
||||||
|
let cost = Date.now() - time
|
||||||
|
if (cost > global.ScriptSlowExecuteTime) {
|
||||||
|
let commandKey = `${plugin.description.name}-${command}-${sender.name}`
|
||||||
|
if (!this.cacheSlowCommandKey[commandKey]) { return this.cacheSlowCommandKey[commandKey] = cost }
|
||||||
|
console.i18n("ms.api.command.execute.slow", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
cost
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
console.i18n("ms.api.command.execute.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex })
|
let message = i18n.translate("ms.api.command.execute.error", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
})
|
||||||
|
console.console(message)
|
||||||
console.ex(ex)
|
console.ex(ex)
|
||||||
if (sender.name != 'CONSOLE') {
|
if (sender.name != 'CONSOLE') {
|
||||||
console.sender(sender, [i18n.translate("ms.api.command.execute.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex }), ...console.stack(ex)])
|
console.sender(sender, [message, ...console.stack(ex)])
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -58,13 +86,36 @@ export namespace command {
|
|||||||
protected setTabCompleter(plugin: plugin.Plugin, command: any, tabCompleter: Function) {
|
protected setTabCompleter(plugin: plugin.Plugin, command: any, tabCompleter: Function) {
|
||||||
return (sender: any, _: any, command: string, args: string[]) => {
|
return (sender: any, _: any, command: string, args: string[]) => {
|
||||||
try {
|
try {
|
||||||
|
let time = Date.now()
|
||||||
var token = args[args.length - 1]
|
var token = args[args.length - 1]
|
||||||
var complete = tabCompleter(sender, command, Java.from(args)) || []
|
var complete = tabCompleter(sender, command, Java.from(args)) || []
|
||||||
return this.copyPartialMatches(complete, token)
|
let result = this.copyPartialMatches(complete, token)
|
||||||
|
let cost = Date.now() - time
|
||||||
|
if (cost > global.ScriptSlowExecuteTime) {
|
||||||
|
let completerKey = `${plugin.description.name}-${command}-${sender.name}`
|
||||||
|
if (!this.cacheSlowCompleteKey[completerKey]) { return this.cacheSlowCompleteKey[completerKey] = cost }
|
||||||
|
console.i18n("ms.api.command.tab.completer.slow", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
cost
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
console.i18n("ms.api.command.tab.completer.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex })
|
let message = i18n.translate("ms.api.command.tab.completer.error", {
|
||||||
|
player: sender.name,
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
command,
|
||||||
|
args: Java.from(args).join(' '),
|
||||||
|
ex
|
||||||
|
})
|
||||||
|
console.console(message)
|
||||||
console.ex(ex)
|
console.ex(ex)
|
||||||
console.sender(sender, [i18n.translate("ms.api.command.tab.completer.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex }), ...console.stack(ex)])
|
if (sender.name != 'CONSOLE') {
|
||||||
|
console.sender(sender, [message, ...console.stack(ex)])
|
||||||
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as base64 from 'base64-js'
|
|||||||
const Arrays = Java.type('java.util.Arrays')
|
const Arrays = Java.type('java.util.Arrays')
|
||||||
const Level = Java.type('java.util.logging.Level')
|
const Level = Java.type('java.util.logging.Level')
|
||||||
const Paths = Java.type('java.nio.file.Paths')
|
const Paths = Java.type('java.nio.file.Paths')
|
||||||
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.internal.dynalink.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
ALL,
|
ALL,
|
||||||
@@ -18,12 +18,114 @@ enum LogLevel {
|
|||||||
OFF
|
OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
||||||
|
const sourceFileMaps: { [key: string]: string } = {}
|
||||||
|
|
||||||
|
global.setGlobal('MiaoScriptSourceMaps', sourceMaps)
|
||||||
|
global.setGlobal('MiaoScriptSourceFileMaps', sourceFileMaps)
|
||||||
|
|
||||||
|
export namespace jsconsole {
|
||||||
|
export function readSourceMap(fileName: string, lineNumber: any) {
|
||||||
|
try {
|
||||||
|
if (fileName.endsWith('js') || fileName.endsWith('ms')) {
|
||||||
|
if (sourceMaps[fileName] === undefined) {
|
||||||
|
sourceMaps[fileName] = null
|
||||||
|
let sourceLine = base.read(fileName).split('\n')
|
||||||
|
let lastLine = sourceLine[sourceLine.length - 1] || sourceLine[sourceLine.length - 2]
|
||||||
|
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
||||||
|
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
||||||
|
let sourceContent = null
|
||||||
|
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
||||||
|
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
||||||
|
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
||||||
|
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
||||||
|
if (file.exists()) {
|
||||||
|
sourceContent = base.read(file)
|
||||||
|
sourceFileMaps[fileName] = file.getCanonicalPath()
|
||||||
|
} else if (global.debug) {
|
||||||
|
console.debug('readSourceMap can\'t found', fileName, 'source map file', sourceMappingURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceContent) {
|
||||||
|
sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceMaps[fileName]) {
|
||||||
|
let sourceMapping = sourceMaps[fileName].getSource(lineNumber, 25, true, true)
|
||||||
|
if (sourceMapping) {
|
||||||
|
fileName = Paths.get(fileName, '..', sourceMapping.sourcePath).toFile().getCanonicalPath()
|
||||||
|
lineNumber = sourceMapping.mapping.sourceLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fileName,
|
||||||
|
lineNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStackTrace(ex: Error, color: boolean = true): string[] {
|
||||||
|
if (!ex) return []
|
||||||
|
let stack = ex.getStackTrace()
|
||||||
|
let cache = [(color ? '§c' : '') + ex]
|
||||||
|
//@ts-ignore
|
||||||
|
if (stack.class) {
|
||||||
|
stack = Arrays.asList(stack)
|
||||||
|
}
|
||||||
|
stack.forEach(trace => {
|
||||||
|
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
||||||
|
if (trace.className.startsWith('<')) {
|
||||||
|
let { fileName, lineNumber } = readSourceMap(trace.fileName, trace.lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${fileName}:${lineNumber}(${trace.lineNumber}) => §4${trace.methodName}`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${fileName}:${lineNumber}(${trace.lineNumber}) => ${trace.methodName}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let className = trace.className
|
||||||
|
var fileName = trace.fileName as string
|
||||||
|
var lineNumber = trace.lineNumber
|
||||||
|
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
||||||
|
className = className.substr(className.lastIndexOf('$') + 1)
|
||||||
|
var { fileName, lineNumber } = readSourceMap(fileName, lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
} else {
|
||||||
|
if (!global.debug) {
|
||||||
|
for (let prefix in ignoreLogPrefix) {
|
||||||
|
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (className.startsWith('jdk.nashorn.internal.') || className.startsWith('org.openjdk.nashorn.internal.')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cache
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MiaoScriptConsole implements Console {
|
export class MiaoScriptConsole implements Console {
|
||||||
Console: any
|
Console: any
|
||||||
memory: any
|
memory: any
|
||||||
|
|
||||||
private static sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
|
||||||
private static sourceFileMaps: { [key: string]: string } = {}
|
|
||||||
private _name: string = ''
|
private _name: string = ''
|
||||||
private _level: LogLevel = LogLevel.INFO
|
private _level: LogLevel = LogLevel.INFO
|
||||||
|
|
||||||
@@ -92,91 +194,8 @@ export class MiaoScriptConsole implements Console {
|
|||||||
ex(ex: Error) {
|
ex(ex: Error) {
|
||||||
this.stack(ex).forEach(line => this.console(line))
|
this.stack(ex).forEach(line => this.console(line))
|
||||||
}
|
}
|
||||||
readSourceMap(fileName: string, lineNumber: any) {
|
|
||||||
try {
|
|
||||||
if (fileName.endsWith('js')) {
|
|
||||||
if (MiaoScriptConsole.sourceMaps[fileName] === undefined) {
|
|
||||||
MiaoScriptConsole.sourceMaps[fileName] = null
|
|
||||||
let sourceLine = base.read(fileName).split('\n')
|
|
||||||
let lastLine = sourceLine[sourceLine.length - 1]
|
|
||||||
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
|
||||||
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
|
||||||
let sourceContent = null
|
|
||||||
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
|
||||||
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
|
||||||
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
|
||||||
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
|
||||||
// TODO
|
|
||||||
} else {
|
|
||||||
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
|
||||||
if (file.exists()) { sourceContent = base.read(file) }
|
|
||||||
}
|
|
||||||
if (sourceContent) {
|
|
||||||
MiaoScriptConsole.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
|
||||||
MiaoScriptConsole.sourceFileMaps[fileName] = Paths.get(fileName, '..', MiaoScriptConsole.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
fileName,
|
|
||||||
lineNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stack(ex: Error, color: boolean = true): string[] {
|
stack(ex: Error, color: boolean = true): string[] {
|
||||||
if (!ex) return []
|
return jsconsole.getStackTrace(ex, color)
|
||||||
let stack = ex.getStackTrace()
|
|
||||||
let cache = [(color ? '§c' : '') + ex]
|
|
||||||
//@ts-ignore
|
|
||||||
if (stack.class) {
|
|
||||||
stack = Arrays.asList(stack)
|
|
||||||
}
|
|
||||||
stack.forEach(trace => {
|
|
||||||
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
|
||||||
if (trace.className.startsWith('<')) {
|
|
||||||
let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${fileName}:${lineNumber} => §4${trace.methodName}`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${fileName}:${lineNumber} => ${trace.methodName}`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let className = trace.className
|
|
||||||
var fileName = trace.fileName as string
|
|
||||||
var lineNumber = trace.lineNumber
|
|
||||||
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
|
||||||
className = className.substr(className.lastIndexOf('$') + 1)
|
|
||||||
var { fileName, lineNumber } = this.readSourceMap(fileName, lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
} else {
|
|
||||||
if (!global.debug) {
|
|
||||||
for (let prefix in ignoreLogPrefix) {
|
|
||||||
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return cache
|
|
||||||
}
|
}
|
||||||
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
|
|||||||
@@ -11,10 +11,21 @@ export namespace constants {
|
|||||||
}
|
}
|
||||||
export namespace Reflect {
|
export namespace Reflect {
|
||||||
export const Method = {
|
export const Method = {
|
||||||
getServerConnection: [/*spigot 1.8.8*/'aq',/*spigot 1.12.2*/ 'an', /*spigot 1.14.4+*/'getServerConnection', /*catserver 1.12.2*/'func_147137_ag']
|
getServerConnection: [
|
||||||
|
/*spigot 1.8.8*/'aq',
|
||||||
|
/*spigot 1.12.2*/ 'an',
|
||||||
|
/*spigot 1.14.4+*/'getServerConnection',
|
||||||
|
/*spigot 1.19+*/'ad',
|
||||||
|
/*catserver 1.12.2*/'func_147137_ag'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
export const Field = {
|
export const Field = {
|
||||||
listeningChannels: [/*spigot 1.8.8-1.12.2*/'g', /*spigot 1.14.4*/'f', /*spigot 1.15.2+*/'listeningChannels', /*catserver 1.12.2*/'field_151274_e']
|
listeningChannels: [
|
||||||
|
/*spigot 1.8.8-1.12.2*/'g',
|
||||||
|
/*spigot 1.14.4*/'f',
|
||||||
|
/*spigot 1.15.2+*/'listeningChannels',
|
||||||
|
/*catserver 1.12.2*/'field_151274_e'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export enum ServerType {
|
export enum ServerType {
|
||||||
|
|||||||
@@ -1,5 +1,56 @@
|
|||||||
|
import { injectable } from "@ccms/container"
|
||||||
|
|
||||||
export namespace database {
|
export namespace database {
|
||||||
export const DataBaseManager = Symbol("DataBaseManager");
|
export const DataSource = Symbol("DataSource")
|
||||||
export const DataSource = Symbol("DataSource");
|
/**
|
||||||
export const DataBase = Symbol("DataBase");
|
* 数据库配置
|
||||||
|
*/
|
||||||
|
export interface DataBaseConfig {
|
||||||
|
/**
|
||||||
|
* 数据库类型
|
||||||
|
*/
|
||||||
|
type: 'h2' | 'mysql' | 'mongodb' | 'sqlite' | 'postgres' | 'redis'
|
||||||
|
/**
|
||||||
|
* 数据库连接串
|
||||||
|
*/
|
||||||
|
url: string | javax.sql.DataSource
|
||||||
|
/**
|
||||||
|
* 数据库驱动
|
||||||
|
*/
|
||||||
|
driverClassName?: string
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
username?: string
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
password?: string
|
||||||
|
/**
|
||||||
|
* 链接属性
|
||||||
|
*/
|
||||||
|
properties?: { [key: string]: any }
|
||||||
|
/**
|
||||||
|
* 调试模式
|
||||||
|
*/
|
||||||
|
debug?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export abstract class DataBaseManager {
|
||||||
|
abstract setMainDatabase(mainDatabase: DataBase): void
|
||||||
|
abstract getMainDatabase(): DataBase
|
||||||
|
abstract createDatabase(name: string, config: DataBaseConfig): DataBase
|
||||||
|
abstract removeDatabase(name: string): boolean
|
||||||
|
abstract getDatabase(name: string): DataBase
|
||||||
|
abstract startWebManager(...args: string[])
|
||||||
|
abstract stopWebManager()
|
||||||
|
abstract shutdown()
|
||||||
|
}
|
||||||
|
@injectable()
|
||||||
|
export abstract class DataBase {
|
||||||
|
abstract query<T>(sql: string, ...args: any[]): Array<T>
|
||||||
|
abstract update(sql: string, ...args: any[]): number
|
||||||
|
abstract execute(sql: string): void
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ export namespace event {
|
|||||||
public EventPriority = EventPriority;
|
public EventPriority = EventPriority;
|
||||||
|
|
||||||
private mapEvent = [];
|
private mapEvent = [];
|
||||||
private listenerMap = [];
|
private pluginEventMap = [];
|
||||||
|
private cacheSlowEventKey = {};
|
||||||
|
|
||||||
protected baseEventDir = '';
|
protected baseEventDir = '';
|
||||||
|
|
||||||
@@ -92,17 +93,23 @@ export namespace event {
|
|||||||
return eventCls
|
return eventCls
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(name, exec, eventCls) {
|
/**
|
||||||
|
* 创建命令执行器
|
||||||
|
* @param name 插件名称
|
||||||
|
* @param exec 执行方法
|
||||||
|
* @param eventCls 事件类
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
createExecute(name, exec, eventCls) {
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
|
let event = args[args.length - 1]
|
||||||
try {
|
try {
|
||||||
let event = args[args.length - 1]
|
if (!eventCls.isAssignableFrom(event.getClass())) { return }
|
||||||
if (eventCls.isAssignableFrom(event.getClass())) {
|
let time = Date.now(); exec(event); let cost = Date.now() - time
|
||||||
let time = Date.now()
|
if (cost > global.ScriptSlowExecuteTime && !event.async) {
|
||||||
exec(event)
|
let eventKey = `${name}-${this.class2Name(eventCls)}`
|
||||||
let cost = Date.now() - time
|
if (!this.cacheSlowEventKey[eventKey]) { return this.cacheSlowEventKey[eventKey] = cost }
|
||||||
if (cost > 20) {
|
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
||||||
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
||||||
@@ -113,17 +120,17 @@ export namespace event {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加事件监听
|
* 添加事件监听
|
||||||
* @param plugin {any}
|
* @param plugin {any} 插件
|
||||||
* @param event {string}
|
* @param event {string} 事件名称
|
||||||
* @param exec {function}
|
* @param exec {function} 事件执行器
|
||||||
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR]
|
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] 优先级
|
||||||
* @param ignoreCancel
|
* @param ignoreCancel 是否忽略已取消事件
|
||||||
*/
|
*/
|
||||||
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
||||||
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
||||||
var name = plugin.description.name
|
var name = plugin.description.name
|
||||||
var eventCls = this.name2Class(name, event)
|
var eventCls = this.name2Class(name, event)
|
||||||
if (!eventCls) { return }
|
if (!eventCls) { return () => { console.warn('event ' + event + ' not found ignore off listener.') } }
|
||||||
if (typeof priority === 'boolean') {
|
if (typeof priority === 'boolean') {
|
||||||
ignoreCancel = priority
|
ignoreCancel = priority
|
||||||
priority = EventPriority.NORMAL
|
priority = EventPriority.NORMAL
|
||||||
@@ -133,19 +140,33 @@ export namespace event {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let executor = exec.name || exec.executor || '[anonymous]'
|
let executor = exec.name || exec.executor || '[anonymous]'
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
var listener = this.register(eventCls, this.execute(name, exec, eventCls), priority, ignoreCancel)
|
let listener = this.register(
|
||||||
var listenerMap = this.listenerMap
|
eventCls,
|
||||||
|
this.createExecute(name, exec, eventCls),
|
||||||
|
priority,
|
||||||
|
ignoreCancel
|
||||||
|
)
|
||||||
// add to cache Be used for close plugin to close event
|
// add to cache Be used for close plugin to close event
|
||||||
if (!listenerMap[name]) listenerMap[name] = []
|
if (!this.pluginEventMap[name]) this.pluginEventMap[name] = []
|
||||||
var off = () => {
|
let off = () => {
|
||||||
if (off['offed']) return
|
if (off['offed']) return
|
||||||
off['offed'] = true
|
off['offed'] = true
|
||||||
this.unregister(eventCls, listener)
|
this.unregister(eventCls, listener)
|
||||||
console.debug(i18n.translate("ms.api.event.unregister", { name, event: this.class2Name(eventCls), exec: executor }))
|
console.debug(i18n.translate("ms.api.event.unregister", {
|
||||||
|
name,
|
||||||
|
event: this.class2Name(eventCls),
|
||||||
|
exec: executor
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
listenerMap[name].push(off)
|
this.pluginEventMap[name].push(off)
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
console.debug(i18n.translate("ms.api.event.register", { name, event: this.class2Name(eventCls), exec: executor }))
|
console.debug(i18n.translate("ms.api.event.register", {
|
||||||
|
name,
|
||||||
|
event: this.class2Name(eventCls),
|
||||||
|
exec: executor,
|
||||||
|
priority,
|
||||||
|
ignore: ignoreCancel
|
||||||
|
}))
|
||||||
return off
|
return off
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,10 +175,10 @@ export namespace event {
|
|||||||
* @param plugin 插件
|
* @param plugin 插件
|
||||||
*/
|
*/
|
||||||
disable(plugin: any) {
|
disable(plugin: any) {
|
||||||
var eventCache = this.listenerMap[plugin.description.name]
|
var eventCache = this.pluginEventMap[plugin.description.name]
|
||||||
if (eventCache) {
|
if (eventCache) {
|
||||||
eventCache.forEach(off => off())
|
eventCache.forEach((off: () => any) => off())
|
||||||
delete this.listenerMap[plugin.description.name]
|
delete this.pluginEventMap[plugin.description.name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ export * from './web'
|
|||||||
export * from './amqp'
|
export * from './amqp'
|
||||||
export * from './chat'
|
export * from './chat'
|
||||||
export * from './task'
|
export * from './task'
|
||||||
|
export * from './item'
|
||||||
export * from './event'
|
export * from './event'
|
||||||
export * from './proxy'
|
export * from './proxy'
|
||||||
export * from './plugin'
|
export * from './plugin'
|
||||||
export * from './server'
|
export * from './server'
|
||||||
export * from './console'
|
export * from './console'
|
||||||
|
export { jsconsole as console } from './console'
|
||||||
export * from './channel'
|
export * from './channel'
|
||||||
export * from './command'
|
export * from './command'
|
||||||
export * from './database'
|
export * from './database'
|
||||||
|
|||||||
20
packages/api/src/item.ts
Normal file
20
packages/api/src/item.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { injectable } from '@ccms/container'
|
||||||
|
|
||||||
|
export namespace item {
|
||||||
|
@injectable()
|
||||||
|
export abstract class Item {
|
||||||
|
abstract builder(): ItemBuilder
|
||||||
|
abstract toJson(item: any): string
|
||||||
|
abstract fromJson(json: string): any
|
||||||
|
}
|
||||||
|
export interface ItemBuilder {
|
||||||
|
from(item: any): ItemBuilder
|
||||||
|
create(type: string | number): ItemBuilder
|
||||||
|
name(name: string): ItemBuilder
|
||||||
|
lore(...lores: string[]): ItemBuilder
|
||||||
|
amount(amount: number): ItemBuilder
|
||||||
|
durability(durability: number): ItemBuilder
|
||||||
|
clone(): any
|
||||||
|
build(): any
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,12 @@ const UUID = Java.type('java.util.UUID')
|
|||||||
const Math = Java.type('java.lang.Math')
|
const Math = Java.type('java.lang.Math')
|
||||||
|
|
||||||
export namespace particle {
|
export namespace particle {
|
||||||
|
@injectable()
|
||||||
|
export abstract class ParticleSpawner {
|
||||||
|
abstract spawn(location: any, particle: Particle)
|
||||||
|
abstract spawnToPlayer(player: any, location: any, particle: Particle)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一个特效对象
|
* 表示一个特效对象
|
||||||
*
|
*
|
||||||
@@ -23,6 +29,11 @@ export namespace particle {
|
|||||||
private extra: number = 0;
|
private extra: number = 0;
|
||||||
private data: Object = null;
|
private data: Object = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only Show To Player
|
||||||
|
*/
|
||||||
|
private player: any
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.uuid = UUID.randomUUID().toString()
|
this.uuid = UUID.randomUUID().toString()
|
||||||
}
|
}
|
||||||
@@ -105,6 +116,15 @@ export namespace particle {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPlayer() {
|
||||||
|
return this.player
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlayer(player) {
|
||||||
|
this.player = player
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
||||||
*
|
*
|
||||||
@@ -112,9 +132,14 @@ export namespace particle {
|
|||||||
*/
|
*/
|
||||||
spawn(location: any) {
|
spawn(location: any) {
|
||||||
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
||||||
this.spawner.spawn(location, this)
|
if (this.player) {
|
||||||
|
this.spawner.spawnToPlayer(this.player, location, this)
|
||||||
|
} else {
|
||||||
|
this.spawner.spawn(location, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一条线
|
* 表示一条线
|
||||||
*
|
*
|
||||||
@@ -158,8 +183,7 @@ export namespace particle {
|
|||||||
|
|
||||||
show() {
|
show() {
|
||||||
for (let i = 0; i < this.length; i += this.step) {
|
for (let i = 0; i < this.length; i += this.step) {
|
||||||
let vectorTemp = this.vector.clone().multiply(i)
|
this.spawn(this.start.clone().add(this.vector.clone().multiply(i)))
|
||||||
this.spawn(this.start.clone().add(vectorTemp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,15 +258,6 @@ export namespace particle {
|
|||||||
this.length = this.vector.length()
|
this.length = this.vector.length()
|
||||||
this.vector.normalize()
|
this.vector.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static buildLine(locA: any, locB: any, step: number, particle: any) {
|
|
||||||
let vectorAB = locB.clone().subtract(locA).toVector()
|
|
||||||
let vectorLength = vectorAB.length()
|
|
||||||
vectorAB.normalize()
|
|
||||||
for (let i = 0; i < vectorLength; i += step) {
|
|
||||||
ParticleManager.globalSpawner.spawn(locA.clone().add(vectorAB.clone().multiply(i)), particle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 表示一个弧
|
* 表示一个弧
|
||||||
@@ -331,9 +346,10 @@ export namespace particle {
|
|||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ParticleManager {
|
export abstract class ParticleManager {
|
||||||
public static globalSpawner: ParticleSpawner = undefined
|
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private taskManager: task.TaskManager
|
private taskManager: task.TaskManager
|
||||||
|
@Autowired()
|
||||||
|
private particleSpawner: particle.ParticleSpawner
|
||||||
|
|
||||||
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
||||||
protected cacheTasks = new Map<string, ParticleTask>()
|
protected cacheTasks = new Map<string, ParticleTask>()
|
||||||
@@ -354,6 +370,10 @@ export namespace particle {
|
|||||||
return this.taskManager
|
return this.taskManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getParticleSpawner() {
|
||||||
|
return this.particleSpawner
|
||||||
|
}
|
||||||
|
|
||||||
public create(particle: Particle, plugin?: plugin.Plugin) {
|
public create(particle: Particle, plugin?: plugin.Plugin) {
|
||||||
let uuid = particle.getUUID()
|
let uuid = particle.getUUID()
|
||||||
if (this.cacheTasks.has(uuid)) {
|
if (this.cacheTasks.has(uuid)) {
|
||||||
@@ -389,14 +409,12 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
||||||
particle.setSpawner(this.getGlobalSpawner())
|
particle.setSpawner(this.getParticleSpawner())
|
||||||
return new ParticleTask(owner, particle, this)
|
return new ParticleTask(owner, particle, this)
|
||||||
}
|
}
|
||||||
protected abstract getGlobalSpawner(): ParticleSpawner
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParticleTask {
|
export class ParticleTask {
|
||||||
|
|
||||||
private particle: Particle
|
private particle: Particle
|
||||||
private isAsync: boolean = false
|
private isAsync: boolean = false
|
||||||
private interval: number = 0
|
private interval: number = 0
|
||||||
@@ -486,9 +504,4 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ParticleSpawner {
|
|
||||||
abstract spawnParticle(location: any, particle: any, count: number)
|
|
||||||
abstract spawn(location: any, particle: Particle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export namespace plugin {
|
|||||||
export abstract class PluginManager {
|
export abstract class PluginManager {
|
||||||
abstract scan(folder: string): void
|
abstract scan(folder: string): void
|
||||||
abstract build(): void
|
abstract build(): void
|
||||||
abstract loadFromFile(file: string, scanner?: plugin.PluginScanner): Plugin
|
abstract loadFromFile(file: string, ext?: any): Plugin
|
||||||
abstract load(...args: any[]): void
|
abstract load(...args: any[]): void
|
||||||
abstract enable(...args: any[]): void
|
abstract enable(...args: any[]): void
|
||||||
abstract disable(...args: any[]): void
|
abstract disable(...args: any[]): void
|
||||||
@@ -149,7 +149,19 @@ export namespace plugin {
|
|||||||
/**
|
/**
|
||||||
* 插件名称 不填默认为类名
|
* 插件名称 不填默认为类名
|
||||||
*/
|
*/
|
||||||
name?: string
|
name: string
|
||||||
|
/**
|
||||||
|
* 插件中文名称
|
||||||
|
*/
|
||||||
|
cname?: string
|
||||||
|
/**
|
||||||
|
* 付费插件ID
|
||||||
|
*/
|
||||||
|
pid?: number
|
||||||
|
/**
|
||||||
|
* 付费插件等级 付费插件自动注入
|
||||||
|
*/
|
||||||
|
level?: number
|
||||||
/**
|
/**
|
||||||
* 前缀
|
* 前缀
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export namespace server {
|
|||||||
origin: any
|
origin: any
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class NativePluginManager {
|
export abstract class NativePluginManager {
|
||||||
list(): NativePlugin[] {
|
list(): NativePlugin[] {
|
||||||
@@ -40,19 +41,20 @@ export namespace server {
|
|||||||
get(name: string): NativePlugin {
|
get(name: string): NativePlugin {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
load(name: string): boolean {
|
enable(name: string): NativePlugin {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
unload(name: string): boolean {
|
disable(name: string): NativePlugin {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
reload(name: string): boolean {
|
reload(name: string): NativePlugin {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
delete(name: string): boolean {
|
delete(name: string): boolean {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MiaoScript Server
|
* MiaoScript Server
|
||||||
*/
|
*/
|
||||||
@@ -98,6 +100,7 @@ export namespace server {
|
|||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ServerChecker {
|
export class ServerChecker {
|
||||||
@Autowired(ServerType)
|
@Autowired(ServerType)
|
||||||
@@ -116,6 +119,22 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class NativePluginChecker {
|
||||||
|
@Autowired(NativePluginManager)
|
||||||
|
private nativePluginManager: NativePluginManager
|
||||||
|
|
||||||
|
check(plugins: string[]) {
|
||||||
|
// Not set plugins -> allow
|
||||||
|
if (!plugins || !plugins.length) return true
|
||||||
|
for (const plugin of plugins) {
|
||||||
|
if (!this.nativePluginManager.has(plugin)) { return false }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ReflectServer extends server.Server {
|
export abstract class ReflectServer extends server.Server {
|
||||||
@Autowired(ContainerInstance)
|
@Autowired(ContainerInstance)
|
||||||
@@ -172,13 +191,23 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
protected reflectRootLogger(consoleServer: any) {
|
protected reflectRootLogger(consoleServer: any) {
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
|
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get()
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get(0).get().parent
|
this.rootLogger = reflect.on(consoleServer).get(0).get()
|
||||||
|
} catch (error: any) {
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.rootLogger.class.name.indexOf('slf4j') !== -1) {
|
||||||
|
try {
|
||||||
|
let LogManager = Java.type('org.apache.logging.log4j.LogManager')
|
||||||
|
this.rootLogger = LogManager.getLogger('ROOT')
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
@@ -189,11 +218,11 @@ export namespace server {
|
|||||||
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
||||||
this.rootLogger = undefined
|
this.rootLogger = undefined
|
||||||
}
|
}
|
||||||
|
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
||||||
// get root logger
|
// get root logger
|
||||||
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
||||||
this.rootLogger = this.rootLogger.parent
|
this.rootLogger = this.rootLogger.parent
|
||||||
}
|
}
|
||||||
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
|
||||||
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { plugin } from './index'
|
import { EventEmitter } from 'events'
|
||||||
import { injectable } from '@ccms/container'
|
import { injectable } from '@ccms/container'
|
||||||
|
|
||||||
|
import { plugin } from './index'
|
||||||
|
|
||||||
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
||||||
|
|
||||||
export namespace task {
|
export namespace task {
|
||||||
@@ -79,7 +81,7 @@ export namespace task {
|
|||||||
/**
|
/**
|
||||||
* 任务抽象
|
* 任务抽象
|
||||||
*/
|
*/
|
||||||
export abstract class Task implements Cancelable {
|
export abstract class Task extends EventEmitter implements Cancelable {
|
||||||
protected func: Function
|
protected func: Function
|
||||||
protected isAsync: boolean = false;
|
protected isAsync: boolean = false;
|
||||||
protected laterTime: number = 0;
|
protected laterTime: number = 0;
|
||||||
@@ -88,7 +90,10 @@ export namespace task {
|
|||||||
protected taskId: number
|
protected taskId: number
|
||||||
protected innerTask: any
|
protected innerTask: any
|
||||||
|
|
||||||
|
private cancelled: boolean = false
|
||||||
|
|
||||||
constructor(owner: plugin.Plugin, func: Function, id: number) {
|
constructor(owner: plugin.Plugin, func: Function, id: number) {
|
||||||
|
super()
|
||||||
this.owner = owner
|
this.owner = owner
|
||||||
this.func = func
|
this.func = func
|
||||||
this.taskId = id
|
this.taskId = id
|
||||||
@@ -134,20 +139,35 @@ export namespace task {
|
|||||||
*/
|
*/
|
||||||
cancel(): boolean {
|
cancel(): boolean {
|
||||||
let result = this.cancel0()
|
let result = this.cancel0()
|
||||||
process.emit('task.finish', this)
|
this.finish()
|
||||||
|
this.cancelled = true
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
protected run(...args: any[]): void {
|
protected run(...args: any[]): void {
|
||||||
try {
|
try {
|
||||||
|
this.emit('before', this)
|
||||||
|
if (this.cancelled) { return }
|
||||||
this.func(...args)
|
this.func(...args)
|
||||||
!this.interval && process.emit('task.finish', this)
|
this.emit('after', this)
|
||||||
} catch (ex: any) {
|
} catch (error: any) {
|
||||||
console.console('§4插件执行任务时发生错误', ex)
|
this.emit('error', error)
|
||||||
console.ex(ex)
|
if (!error.processed) {
|
||||||
|
console.console('§4插件执行任务时发生错误', error)
|
||||||
|
console.ex(error)
|
||||||
|
this.cancel()
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.emit('finally', this)
|
||||||
|
if (!this.interval && !this.cancelled) { this.finish() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected finish() {
|
||||||
|
process.emit('task.finish', this)
|
||||||
|
this.emit('finish', this)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交任务
|
* 提交任务
|
||||||
* @param args 任务参数
|
* @param args 任务参数
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bukkit",
|
"name": "@ccms/bukkit",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript bukkit package",
|
"description": "MiaoScript bukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spigot-api": "^0.0.3",
|
"@javatypes/spigot-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { channel, plugin } from '@ccms/api'
|
import { channel, plugin } from '@ccms/api'
|
||||||
import { inject, provideSingleton } from '@ccms/container'
|
import { inject, provideSingleton } from '@ccms/container'
|
||||||
|
|
||||||
const Bukkit = org.bukkit.Bukkit
|
const Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
const PluginMessageListener = Java.type("org.bukkit.plugin.messaging.PluginMessageListener")
|
const PluginMessageListener = Java.type("org.bukkit.plugin.messaging.PluginMessageListener")
|
||||||
const Messenger = Bukkit.getMessenger()
|
const Messenger = Bukkit.getMessenger()
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { chat } from '@ccms/api'
|
import { chat } from '@ccms/api'
|
||||||
import { provideSingleton } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
import bukkitChat from './enhance/chat'
|
import bukkitChat from './internal/chat'
|
||||||
|
|
||||||
@provideSingleton(chat.Chat)
|
@provideSingleton(chat.Chat)
|
||||||
export class BukkitChat extends chat.Chat {
|
export class BukkitChat extends chat.Chat {
|
||||||
|
get handle(): any {
|
||||||
|
return bukkitChat
|
||||||
|
}
|
||||||
sendJson(sender: any, json: string | object, type = 0) {
|
sendJson(sender: any, json: string | object, type = 0) {
|
||||||
bukkitChat.send(sender, typeof json === "string" ? json : JSON.stringify(json), type)
|
bukkitChat.send(sender, typeof json === "string" ? json : JSON.stringify(json), type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,38 @@
|
|||||||
import '@ccms/nashorn'
|
import '@ccms/nashorn'
|
||||||
|
|
||||||
import { command, plugin } from '@ccms/api'
|
import { command, plugin } from '@ccms/api'
|
||||||
import * as reflect from '@ccms/common/dist/reflect'
|
|
||||||
import { provideSingleton, postConstruct, inject } from '@ccms/container'
|
import { provideSingleton, postConstruct, inject } from '@ccms/container'
|
||||||
|
import * as reflect from '@ccms/common/dist/reflect'
|
||||||
|
|
||||||
let Bukkit = org.bukkit.Bukkit
|
const Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
let TabCompleter = Java.type('org.bukkit.command.TabCompleter')
|
const TabCompleter = Java.type('org.bukkit.command.TabCompleter')
|
||||||
let PluginCommand = Java.type('org.bukkit.command.PluginCommand')
|
const PluginCommand = Java.type('org.bukkit.command.PluginCommand')
|
||||||
let CommandExecutor = Java.type('org.bukkit.command.CommandExecutor')
|
const CommandExecutor = Java.type('org.bukkit.command.CommandExecutor')
|
||||||
|
|
||||||
@provideSingleton(command.Command)
|
@provideSingleton(command.Command)
|
||||||
export class BukkitCommand extends command.Command {
|
export class BukkitCommand extends command.Command {
|
||||||
@inject(plugin.PluginInstance)
|
@inject(plugin.PluginInstance)
|
||||||
private pluginInstance: any
|
private pluginInstance: any
|
||||||
private commandMap: any
|
private commandMap: any
|
||||||
|
private knownCommands: any
|
||||||
|
|
||||||
@postConstruct()
|
@postConstruct()
|
||||||
init() {
|
init() {
|
||||||
this.commandMap = reflect.on(Bukkit.getPluginManager()).get('commandMap').get()
|
this.commandMap = reflect.on(Bukkit.getPluginManager()).get('commandMap').get()
|
||||||
|
this.knownCommands = reflect.on(this.commandMap).get('knownCommands').get()
|
||||||
}
|
}
|
||||||
create(plugin: any, command: string) {
|
create(plugin: any, command: string) {
|
||||||
var cmd = this.commandMap.getCommand(command)
|
var cmd = this.commandMap.getCommand(command)
|
||||||
if (cmd && cmd instanceof PluginCommand) { return cmd };
|
if (cmd instanceof PluginCommand) { return cmd };
|
||||||
cmd = reflect.on(PluginCommand).create(command, this.pluginInstance).get()
|
cmd = reflect.on(PluginCommand).create(command, this.pluginInstance).get()
|
||||||
this.commandMap.register(plugin.description.name, cmd)
|
this.commandMap.register(plugin.description.name, cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
remove(plugin: any, command: string) {
|
remove(plugin: any, command: string) {
|
||||||
var cmd = this.commandMap.getCommand(command)
|
var cmd = this.commandMap.getCommand(command)
|
||||||
if (cmd && cmd instanceof PluginCommand) {
|
if (cmd instanceof PluginCommand) {
|
||||||
cmd.unregister(this.commandMap)
|
cmd.unregister(this.commandMap)
|
||||||
|
this.knownCommands.remove(command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tabComplete(sender: any, input: string, index?: number): string[] {
|
tabComplete(sender: any, input: string, index?: number): string[] {
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { MiaoScriptConsole } from '@ccms/api'
|
import { MiaoScriptConsole } from '@ccms/api'
|
||||||
|
|
||||||
let Bukkit = org.bukkit.Bukkit;
|
const Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
|
|
||||||
export class BukkitConsole extends MiaoScriptConsole {
|
export class BukkitConsole extends MiaoScriptConsole {
|
||||||
sender(sender, ...args) {
|
sender(sender, ...args) {
|
||||||
if (!(sender instanceof Java.type('org.bukkit.command.CommandSender'))) {
|
if (!(sender instanceof Java.type('org.bukkit.command.CommandSender'))) {
|
||||||
this.error(`First parameter ${sender} not instanceof org.bukkit.command.CommandSender can't send message!`)
|
this.error(`First parameter ${sender} not instanceof org.bukkit.command.CommandSender can't send message!`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (Object.prototype.toString.call(args[0]) === "[object Array]") {
|
if (Object.prototype.toString.call(args[0]) === "[object Array]") {
|
||||||
args[0].forEach(line => sender.sendMessage(this.prefix + line))
|
args[0].forEach(line => sender.sendMessage(this.prefix + line))
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(this.prefix + args.join(' '));
|
sender.sendMessage(this.prefix + args.join(' '))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console(...args: string[]): void {
|
console(...args: string[]): void {
|
||||||
this.sender(Bukkit.getConsoleSender(), args.join(' '));
|
this.sender(Bukkit.getConsoleSender(), args.join(' '))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { event, plugin } from '@ccms/api'
|
import { event, plugin } from '@ccms/api'
|
||||||
import { inject, provideSingleton } from '@ccms/container';
|
import { inject, provideSingleton } from '@ccms/container'
|
||||||
import * as reflect from '@ccms/common/dist/reflect'
|
import * as reflect from '@ccms/common/dist/reflect'
|
||||||
|
|
||||||
const Bukkit = Java.type("org.bukkit.Bukkit");
|
const URL = Java.type('java.net.URL')
|
||||||
const Event = Java.type("org.bukkit.event.Event");
|
const Bukkit = Java.type("org.bukkit.Bukkit")
|
||||||
const Modifier = Java.type("java.lang.reflect.Modifier");
|
const Event = Java.type("org.bukkit.event.Event")
|
||||||
const Listener = Java.type("org.bukkit.event.Listener");
|
const Modifier = Java.type("java.lang.reflect.Modifier")
|
||||||
const EventPriority = Java.type("org.bukkit.event.EventPriority");
|
const Listener = Java.type("org.bukkit.event.Listener")
|
||||||
const EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
|
const EventPriority = Java.type("org.bukkit.event.EventPriority")
|
||||||
|
const EventExecutor = Java.type("org.bukkit.plugin.EventExecutor")
|
||||||
|
|
||||||
@provideSingleton(event.Event)
|
@provideSingleton(event.Event)
|
||||||
export class BukkitEvent extends event.Event {
|
export class BukkitEvent extends event.Event {
|
||||||
@@ -15,11 +16,19 @@ export class BukkitEvent extends event.Event {
|
|||||||
private pluginInstance: any
|
private pluginInstance: any
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('org/bukkit/event');
|
super('org/bukkit/event')
|
||||||
}
|
}
|
||||||
|
|
||||||
getJarFile(resource: string) {
|
getJarFile(resource: string) {
|
||||||
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
try {
|
||||||
|
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
||||||
|
} catch (error) {
|
||||||
|
// 兼容 LoliServer 的 Bukkit 包无法获取的问题
|
||||||
|
let ModList = Java.type('net.minecraftforge.fml.ModList').get()
|
||||||
|
let forgeFile = ModList.getModFileById("forge").getFile().getFilePath()
|
||||||
|
let jarPath = `jar:file:${forgeFile}!/org/bukkit/Bukkit.class`
|
||||||
|
return new URL(jarPath).openConnection().jarFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isValidEvent(clazz: any): boolean {
|
isValidEvent(clazz: any): boolean {
|
||||||
// 继承于 org.bukkit.event.Event
|
// 继承于 org.bukkit.event.Event
|
||||||
@@ -27,10 +36,10 @@ export class BukkitEvent extends event.Event {
|
|||||||
// 访问符为Public
|
// 访问符为Public
|
||||||
Modifier.isPublic(clazz.getModifiers()) &&
|
Modifier.isPublic(clazz.getModifiers()) &&
|
||||||
// 不是抽象类
|
// 不是抽象类
|
||||||
!Modifier.isAbstract(clazz.getModifiers());
|
!Modifier.isAbstract(clazz.getModifiers())
|
||||||
}
|
}
|
||||||
register(eventCls: any, exec: Function, priority: event.EventPriority, ignoreCancel: boolean) {
|
register(eventCls: any, exec: Function, priority: event.EventPriority, ignoreCancel: boolean) {
|
||||||
let listener = new Listener({});
|
let listener = new Listener({})
|
||||||
Bukkit.pluginManager.registerEvent(
|
Bukkit.pluginManager.registerEvent(
|
||||||
eventCls,
|
eventCls,
|
||||||
listener,
|
listener,
|
||||||
@@ -39,10 +48,10 @@ export class BukkitEvent extends event.Event {
|
|||||||
execute: exec
|
execute: exec
|
||||||
}),
|
}),
|
||||||
this.pluginInstance,
|
this.pluginInstance,
|
||||||
ignoreCancel);
|
ignoreCancel)
|
||||||
return listener;
|
return listener
|
||||||
}
|
}
|
||||||
unregister(event: any, listener: any): void {
|
unregister(event: any, listener: any): void {
|
||||||
reflect.on(event).call('getHandlerList').get().unregister(listener);
|
reflect.on(event).call('getHandlerList').get().unregister(listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { server } from '@ccms/api'
|
|||||||
import { Container } from '@ccms/container'
|
import { Container } from '@ccms/container'
|
||||||
|
|
||||||
import { BukkitConsole } from './console'
|
import { BukkitConsole } from './console'
|
||||||
|
import './item'
|
||||||
import './chat'
|
import './chat'
|
||||||
import './task'
|
import './task'
|
||||||
import './event'
|
import './event'
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ let bukkitChatInvoke: BukkitChatInvoke
|
|||||||
abstract class BukkitChatInvoke {
|
abstract class BukkitChatInvoke {
|
||||||
private downgrade: boolean = false
|
private downgrade: boolean = false
|
||||||
protected RemapUtils: any
|
protected RemapUtils: any
|
||||||
|
protected ComponentSerializer: any
|
||||||
|
|
||||||
protected ChatSerializer: any
|
protected ChatSerializer: any
|
||||||
protected nmsChatSerializerMethodName: string
|
protected nmsChatSerializerMethodName: string
|
||||||
protected PacketPlayOutChat: any
|
protected PacketPlayOutChat: any
|
||||||
protected chatMessageTypes: any
|
protected chatMessageTypes: any
|
||||||
protected playerConnectionFieldName: string
|
protected playerConnectionFieldName: string
|
||||||
|
protected playerFieldName: string
|
||||||
protected sendPacketMethodName: string
|
protected sendPacketMethodName: string
|
||||||
|
|
||||||
constructor(private nmsVersion) {
|
constructor(private nmsVersion) {
|
||||||
@@ -20,30 +22,31 @@ abstract class BukkitChatInvoke {
|
|||||||
init() {
|
init() {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
|
this.ComponentSerializer = Java.type('net.md_5.bungee.chat.ComponentSerializer')
|
||||||
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
}
|
}
|
||||||
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
||||||
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
this.nmsChatSerializerMethodName = this.getNmsChatSerializerMethodName(nmsChatSerializerClass)
|
||||||
this.nmsChatSerializerMethodName = nmsChatSerializerMethod.getName()
|
|
||||||
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
||||||
let packetTypeClass = this.getPacketPlayOutChatClass()
|
let packetTypeClass = this.getPacketPlayOutChatClass()
|
||||||
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
||||||
let packetTypeConstructor: { parameterTypes: any[] }
|
|
||||||
let constructors = packetTypeClass.constructors
|
let constructors = packetTypeClass.constructors
|
||||||
Java.from(constructors).forEach(function (c) {
|
for (const constructor of Java.from(constructors)) {
|
||||||
if (c.parameterTypes.length === 2 || c.parameterTypes.length === 3) {
|
let parameterTypes = constructor.parameterTypes
|
||||||
packetTypeConstructor = c
|
if (parameterTypes.length === 2 || parameterTypes.length === 3) {
|
||||||
|
let nmsChatMessageTypeClass = parameterTypes[1]
|
||||||
|
if (nmsChatMessageTypeClass.isEnum()) {
|
||||||
|
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
||||||
|
break
|
||||||
|
} else if (nmsChatMessageTypeClass.getName() == 'int') {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
let parameterTypes = packetTypeConstructor.parameterTypes
|
|
||||||
let nmsChatMessageTypeClass = parameterTypes[1]
|
|
||||||
if (nmsChatMessageTypeClass.isEnum()) {
|
|
||||||
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
|
||||||
}
|
}
|
||||||
let playerConnectionField = this.getPlayerConnectionField()
|
let playerConnectionField = this.getPlayerConnectionField()
|
||||||
this.playerConnectionFieldName = playerConnectionField.getName()
|
this.playerConnectionFieldName = playerConnectionField.getName()
|
||||||
this.sendPacketMethodName = this.remapMethod(playerConnectionField.getType(), 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
this.sendPacketMethodName = this.getSendPacketMethodName(playerConnectionField.getType())
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
||||||
this.downgrade = true
|
this.downgrade = true
|
||||||
@@ -51,10 +54,12 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract getNmsChatSerializerClass()
|
abstract getNmsChatSerializerClass()
|
||||||
|
abstract getNmsChatSerializerMethodName(nmsChatSerializerClass: any)
|
||||||
abstract getPacketPlayOutChatClass()
|
abstract getPacketPlayOutChatClass()
|
||||||
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
||||||
abstract getPlayerConnectionField()
|
abstract getPlayerConnectionField()
|
||||||
abstract getPacketClass()
|
abstract getPacketClass()
|
||||||
|
abstract getSendPacketMethodName(playerConnectionClass: any)
|
||||||
|
|
||||||
nmsCls(name: string) {
|
nmsCls(name: string) {
|
||||||
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
||||||
@@ -84,9 +89,9 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json(sender: { name: string }, json: string) {
|
json(sender: any, json: string) {
|
||||||
if (this.downgrade) {
|
if (this.downgrade) {
|
||||||
return '/tellraw ' + sender.name + ' ' + json
|
return sender.spigot().sendMessage(this.ComponentSerializer.parse(json))
|
||||||
} else {
|
} else {
|
||||||
this.send(sender, json, 0)
|
this.send(sender, json, 0)
|
||||||
return false
|
return false
|
||||||
@@ -101,6 +106,13 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
||||||
|
getSendPacketMethodName(playerConnectionClass: any) {
|
||||||
|
return this.remapMethod(playerConnectionClass, 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
||||||
|
}
|
||||||
|
getNmsChatSerializerMethodName(nmsChatSerializerClass: any) {
|
||||||
|
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
||||||
|
return nmsChatSerializerMethod.getName()
|
||||||
|
}
|
||||||
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
||||||
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
||||||
}
|
}
|
||||||
@@ -149,17 +161,35 @@ class BukkitChatInvoke_1_17_1 extends BukkitChatInvoke_1_16_5 {
|
|||||||
return base.getClass('net.minecraft.network.protocol.Packet')
|
return base.getClass('net.minecraft.network.protocol.Packet')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class BukkitChatInvoke_1_18_2 extends BukkitChatInvoke_1_17_1 {
|
||||||
|
getSendPacketMethodName(playerConnectionClass: any) {
|
||||||
|
return playerConnectionClass.getMethod('a', this.getPacketClass()).getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class BukkitChatInvoke_1_19 extends BukkitChatInvoke_1_18_2 {
|
||||||
|
getPacketPlayOutChatClass() {
|
||||||
|
return base.getClass('net.minecraft.network.protocol.game.ClientboundSystemChatPacket')
|
||||||
|
}
|
||||||
|
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
||||||
|
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//@ts-ignore
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
let nmsVersion = org.bukkit.Bukkit.server.class.name.split('.')[3]
|
// @ts-ignore
|
||||||
|
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
||||||
let nmsSubVersion = nmsVersion.split("_")[1]
|
let nmsSubVersion = nmsVersion.split("_")[1]
|
||||||
if (nmsSubVersion >= 8) {
|
if (nmsSubVersion >= 19) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_19(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 16) {
|
} else if (nmsSubVersion >= 18) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_18_2(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 17) {
|
} else if (nmsSubVersion >= 17) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
||||||
|
} else if (nmsSubVersion >= 16) {
|
||||||
|
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
||||||
|
} else if (nmsSubVersion >= 8) {
|
||||||
|
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
||||||
} else {
|
} else {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
||||||
}
|
}
|
||||||
@@ -168,6 +198,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chat = {
|
let chat = {
|
||||||
|
invoke: bukkitChatInvoke,
|
||||||
json: bukkitChatInvoke.json.bind(bukkitChatInvoke),
|
json: bukkitChatInvoke.json.bind(bukkitChatInvoke),
|
||||||
send: bukkitChatInvoke.send.bind(bukkitChatInvoke)
|
send: bukkitChatInvoke.send.bind(bukkitChatInvoke)
|
||||||
}
|
}
|
||||||
2270
packages/bukkit/src/internal/item.ts
Normal file
2270
packages/bukkit/src/internal/item.ts
Normal file
File diff suppressed because it is too large
Load Diff
128
packages/bukkit/src/item.ts
Normal file
128
packages/bukkit/src/item.ts
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import { item } from "@ccms/api"
|
||||||
|
import { provideSingleton } from "@ccms/container"
|
||||||
|
|
||||||
|
import { itemIds } from './internal/item'
|
||||||
|
|
||||||
|
const Material: typeof org.bukkit.Material = Java.type('org.bukkit.Material')
|
||||||
|
const ItemStack: typeof org.bukkit.inventory.ItemStack = Java.type('org.bukkit.inventory.ItemStack')
|
||||||
|
|
||||||
|
@provideSingleton(item.Item)
|
||||||
|
export class BukkitItem extends item.Item {
|
||||||
|
private CraftItemStack: any
|
||||||
|
private NBTTagCompound: any
|
||||||
|
private nmsSaveNBTMethodName: any
|
||||||
|
private MojangsonParser: any
|
||||||
|
private nmsItemStack: any
|
||||||
|
private mpParseMethodName: any
|
||||||
|
private nmsVersion: any
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.reflect()
|
||||||
|
}
|
||||||
|
builder(): item.ItemBuilder {
|
||||||
|
return new BukkitItemBuilder()
|
||||||
|
}
|
||||||
|
toJson(item: any): string {
|
||||||
|
let nbt = new this.NBTTagCompound()
|
||||||
|
return this.CraftItemStack.asNMSCopy(item)[this.nmsSaveNBTMethodName](nbt).toString()
|
||||||
|
}
|
||||||
|
fromJson(json: string) {
|
||||||
|
return this.CraftItemStack.asBukkitCopy(new this.nmsItemStack(this.MojangsonParser[this.mpParseMethodName](json)))
|
||||||
|
}
|
||||||
|
private obcCls(name: string) {
|
||||||
|
return base.getClass(['org.bukkit.craftbukkit', this.nmsVersion, name].join('.'))
|
||||||
|
}
|
||||||
|
private nmsCls(name: string) {
|
||||||
|
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
||||||
|
}
|
||||||
|
private reflect() {
|
||||||
|
try {
|
||||||
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
|
// @ts-ignore
|
||||||
|
this.nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
||||||
|
let CraftItemStackClass = this.obcCls('inventory.CraftItemStack')
|
||||||
|
this.CraftItemStack = Java.type(CraftItemStackClass.getName())
|
||||||
|
// @ts-ignore
|
||||||
|
let asNMSCopyMethod = CraftItemStackClass.getMethod('asNMSCopy', ItemStack.class)
|
||||||
|
let nmsItemStackClass = asNMSCopyMethod.getReturnType()
|
||||||
|
this.nmsItemStack = Java.type(nmsItemStackClass.getName())
|
||||||
|
let nmsNBTTagCompoundClass = undefined
|
||||||
|
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (method.getParameterTypes().length == 0 && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
nmsNBTTagCompoundClass = rt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.NBTTagCompound = Java.type(nmsNBTTagCompoundClass.getName())
|
||||||
|
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
||||||
|
let params = method.getParameterTypes()
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (params.length == 1 && "NBTTagCompound" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
this.nmsSaveNBTMethodName = method.getName()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.MojangsonParser = this.nmsCls('MojangsonParser').static
|
||||||
|
} catch (error) {
|
||||||
|
this.MojangsonParser = Java.type('net.minecraft.nbt.MojangsonParser')
|
||||||
|
}
|
||||||
|
for (let method of Java.from(this.MojangsonParser.class.getMethods())) {
|
||||||
|
let params = method.getParameterTypes()
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (params.length == 1 && "String" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
this.mpParseMethodName = method.getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('Bukkit 物品管理器初始化失败:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BukkitItemBuilder implements item.ItemBuilder {
|
||||||
|
private itemStack: org.bukkit.inventory.ItemStack
|
||||||
|
private itemMeta: org.bukkit.inventory.meta.ItemMeta
|
||||||
|
|
||||||
|
from(itemStack: any): item.ItemBuilder {
|
||||||
|
this.itemStack = itemStack
|
||||||
|
this.itemMeta = this.itemStack.getItemMeta()
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
create(type: string | number): item.ItemBuilder {
|
||||||
|
let material = undefined
|
||||||
|
if (typeof type == 'number') {
|
||||||
|
type = itemIds[type]
|
||||||
|
}
|
||||||
|
material = Material[type] || Material[Material['LEGACY_PREFIX'] + type]
|
||||||
|
this.itemStack = new ItemStack(material)
|
||||||
|
this.itemMeta = this.itemStack.getItemMeta()
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
name(name: string): item.ItemBuilder {
|
||||||
|
this.itemMeta.setDisplayName(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
lore(...lores: string[]): item.ItemBuilder {
|
||||||
|
this.itemMeta.setLore(lores)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
amount(amount: number): item.ItemBuilder {
|
||||||
|
this.itemStack.setAmount(amount)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
durability(durability: number): item.ItemBuilder {
|
||||||
|
this.itemStack.setDurability(durability)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
clone() {
|
||||||
|
return this.build().clone()
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
this.itemStack.setItemMeta(this.itemMeta)
|
||||||
|
return this.itemStack
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,13 @@
|
|||||||
import { provideSingleton } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
import { particle, plugin } from '@ccms/api'
|
import { particle } from '@ccms/api'
|
||||||
|
|
||||||
@provideSingleton(particle.ParticleManager)
|
@provideSingleton(particle.ParticleManager)
|
||||||
export class BukkitParticleManager extends particle.ParticleManager {
|
export class BukkitParticleManager extends particle.ParticleManager {
|
||||||
private globalSpawner = new BukkitParticleSpawner()
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
particle.ParticleManager.globalSpawner = this.globalSpawner
|
|
||||||
}
|
|
||||||
protected getGlobalSpawner() {
|
|
||||||
return this.globalSpawner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@provideSingleton(particle.ParticleSpawner)
|
||||||
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
||||||
spawnParticle(location: any, particle: any, count: number = 1) {
|
spawn(location: org.bukkit.Location, particle: particle.Particle) {
|
||||||
location.getWorld().spawnParticle(particle, location, count)
|
|
||||||
}
|
|
||||||
spawn(location: any, particle: particle.Particle) {
|
|
||||||
location.getWorld().spawnParticle(
|
location.getWorld().spawnParticle(
|
||||||
particle.getParticle(),
|
particle.getParticle(),
|
||||||
location,
|
location,
|
||||||
@@ -28,4 +19,15 @@ export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
|||||||
particle.getData()
|
particle.getData()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
spawnToPlayer(player: org.bukkit.entity.Player, location: org.bukkit.Location, particle: particle.Particle) {
|
||||||
|
player.spawnParticle(
|
||||||
|
particle.getParticle(),
|
||||||
|
location,
|
||||||
|
particle.getCount(),
|
||||||
|
particle.getOffsetX(),
|
||||||
|
particle.getOffsetY(),
|
||||||
|
particle.getOffsetZ(),
|
||||||
|
particle.getExtra(),
|
||||||
|
particle.getData())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,22 @@ export class BukkitNativePluginManager extends server.NativePluginManager {
|
|||||||
get(name: string): server.NativePlugin {
|
get(name: string): server.NativePlugin {
|
||||||
return this.convert(this.bukkitPluginManager.getPlugin(name))
|
return this.convert(this.bukkitPluginManager.getPlugin(name))
|
||||||
}
|
}
|
||||||
|
enable(name: string): server.NativePlugin {
|
||||||
|
let origin = this.bukkitPluginManager.getPlugin(name)
|
||||||
|
if (!origin) { throw new Error(`Native Plugin ${name} not found.`) }
|
||||||
|
if (!origin.isEnabled()) {
|
||||||
|
this.bukkitPluginManager.enablePlugin(origin)
|
||||||
|
}
|
||||||
|
return this.convert(origin)
|
||||||
|
}
|
||||||
|
disable(name: string): server.NativePlugin {
|
||||||
|
let origin = this.bukkitPluginManager.getPlugin(name)
|
||||||
|
if (!origin) { throw new Error(`Native Plugin ${name} not found.`) }
|
||||||
|
if (origin.isEnabled()) {
|
||||||
|
this.bukkitPluginManager.disablePlugin(origin)
|
||||||
|
}
|
||||||
|
return this.convert(origin)
|
||||||
|
}
|
||||||
|
|
||||||
private convert(plugin: org.bukkit.plugin.Plugin): server.NativePlugin {
|
private convert(plugin: org.bukkit.plugin.Plugin): server.NativePlugin {
|
||||||
if (!plugin) return plugin as any
|
if (!plugin) return plugin as any
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { server, constants } from '@ccms/api'
|
import { server } from '@ccms/api'
|
||||||
import { provideSingleton } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
|
|
||||||
import * as reflect from '@ccms/common/dist/reflect'
|
import * as reflect from '@ccms/common/dist/reflect'
|
||||||
import chat from './enhance/chat'
|
|
||||||
|
|
||||||
let Bukkit: typeof org.bukkit.Bukkit = org.bukkit.Bukkit
|
const Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
|
|
||||||
@provideSingleton(server.Server)
|
@provideSingleton(server.Server)
|
||||||
export class BukkitServer extends server.ReflectServer {
|
export class BukkitServer extends server.ReflectServer {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { task, plugin } from '@ccms/api'
|
import { task, plugin } from '@ccms/api'
|
||||||
import { inject, provideSingleton } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
|
|
||||||
const Bukkit = Java.type('org.bukkit.Bukkit')
|
const Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
const BukkitRunnable = Java.type('org.bukkit.scheduler.BukkitRunnable')
|
const BukkitRunnable = Java.type('org.bukkit.scheduler.BukkitRunnable')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"outDir": "dist"
|
"outDir": "dist",
|
||||||
|
"resolveJsonModule": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bungee",
|
"name": "@ccms/bungee",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript bungee package",
|
"description": "MiaoScript bungee package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/bungee-api": "^0.0.3",
|
"@javatypes/bungee-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/client/.gitignore
vendored
1
packages/client/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
src/emp.ts
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"name": "@ccms/client",
|
|
||||||
"version": "0.18.0",
|
|
||||||
"description": "MiaoScript client 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": {
|
|
||||||
"dev": "ts-node-dev --respawn --debounce=1500 src/index.ts",
|
|
||||||
"clean": "rimraf dist",
|
|
||||||
"watch": "tsc --watch",
|
|
||||||
"build": "yarn clean && tsc",
|
|
||||||
"start": "node dist/index.js",
|
|
||||||
"debug": "DEBUG=minecraft-protocol node dist/index.js",
|
|
||||||
"emp": "node dist/emp.js",
|
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^0.25.0",
|
|
||||||
"minecraft-protocol": "^1.30.0",
|
|
||||||
"minecraft-protocol-forge": "^1.0.0",
|
|
||||||
"proxy-agent": "^5.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^17.0.17",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"typescript": "^4.5.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
class MessagePart {
|
|
||||||
text: string
|
|
||||||
color: string
|
|
||||||
clickEvent: MessagePartEvent
|
|
||||||
hoverEvent: MessagePartEvent
|
|
||||||
translate: string
|
|
||||||
with: MessagePart[]
|
|
||||||
extra: MessagePart[]
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagePartEvent {
|
|
||||||
action: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
for (const regex in regexMap) {
|
|
||||||
str = str.replace(regexMap[regex], `\u001b[${regex}m`)
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
let jsonColorMap = {
|
|
||||||
"black": '0',
|
|
||||||
"dark_blue": '1',
|
|
||||||
"dark_green": '2',
|
|
||||||
"dark_aqua": '3',
|
|
||||||
"dark_red": '4',
|
|
||||||
"dark_purple": '5',
|
|
||||||
"gold": '6',
|
|
||||||
"gray": '7',
|
|
||||||
"dark_gray": '8',
|
|
||||||
"blue": '9',
|
|
||||||
"green": 'a',
|
|
||||||
"aqua": 'b',
|
|
||||||
"red": 'c',
|
|
||||||
"light_purple": 'd',
|
|
||||||
"yellow": 'e',
|
|
||||||
"white": 'f',
|
|
||||||
"obfuscated": 'k',
|
|
||||||
"bold": 'l',
|
|
||||||
"strikethrough": 'm',
|
|
||||||
"underline": 'n',
|
|
||||||
"italic": 'o',
|
|
||||||
"reset": 'r',
|
|
||||||
};
|
|
||||||
|
|
||||||
function json2text(json: MessagePart): string {
|
|
||||||
let temp = "";
|
|
||||||
if (json.color) {
|
|
||||||
temp += `§${jsonColorMap[json.color]}`
|
|
||||||
}
|
|
||||||
temp += json.text || json.translate || ''
|
|
||||||
if (json.extra) {
|
|
||||||
json.extra.forEach((ext) => {
|
|
||||||
temp += json2text(ext)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return temp += '§r'
|
|
||||||
}
|
|
||||||
|
|
||||||
function $(input: any) {
|
|
||||||
if (typeof input === "string") {
|
|
||||||
input = JSON.parse(input)
|
|
||||||
}
|
|
||||||
input = json2text(input) + '§r'
|
|
||||||
if (input.startsWith('§卐')) {
|
|
||||||
input = input.substring(2)
|
|
||||||
}
|
|
||||||
return mcColor2ANSI(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
json2text,
|
|
||||||
mcColor2ANSI,
|
|
||||||
$
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { $ } from './color'
|
|
||||||
|
|
||||||
export function attachEvents(client) {
|
|
||||||
client.on('chat', (packet) => {
|
|
||||||
// Listen for chat messages and echo them back.
|
|
||||||
var jsonMsg = JSON.parse(packet.message)
|
|
||||||
console.log($(jsonMsg))
|
|
||||||
})
|
|
||||||
client.on('state', (newState, oldState) => {
|
|
||||||
console.log('Client Change State', oldState, 'to', newState)
|
|
||||||
let targetServer = process.argv[6]
|
|
||||||
if (newState == "play" && targetServer) {
|
|
||||||
setTimeout(() => {
|
|
||||||
client.write('chat', {
|
|
||||||
message: '/server ' + targetServer
|
|
||||||
})
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
client.on('update_health', (packet) => {
|
|
||||||
if (packet.health <= 0) {
|
|
||||||
console.log("Player Dead Auto Respawn...")
|
|
||||||
client.write('client_command', { payload: 0 })
|
|
||||||
} else if (packet.health > 0) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
client.on('kick_disconnect', (packet) => {
|
|
||||||
console.log($(packet.reason))
|
|
||||||
})
|
|
||||||
client.on('disconnect', (packet) => {
|
|
||||||
console.log($(packet.reason))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export function attachForge(client) {
|
|
||||||
client.on('custom_payload', function(packet) {
|
|
||||||
if (packet.channel === 'FML|HS') {
|
|
||||||
client.write('custom_payload', {
|
|
||||||
channel: 'FML|HS',
|
|
||||||
data: Buffer.of(0x01, 0x02)
|
|
||||||
});
|
|
||||||
client.write('custom_payload', {
|
|
||||||
channel: 'FML|HS',
|
|
||||||
data: Buffer.of(0x02, 0x00)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
import { createInterface } from 'readline'
|
|
||||||
import { Client, createClient } from 'minecraft-protocol'
|
|
||||||
|
|
||||||
import { attachForge } from './forge'
|
|
||||||
import { attachEvents } from './event'
|
|
||||||
|
|
||||||
let readUserInfo = process.argv[2] || 'Mr_jtb'
|
|
||||||
let realUserInfo = readUserInfo.split(":")
|
|
||||||
let username = realUserInfo[0]
|
|
||||||
let password = realUserInfo[1] || ''
|
|
||||||
let version = process.argv[3] || '1.12.2'
|
|
||||||
let readAddress = process.argv[4] || '192.168.2.25:25565'
|
|
||||||
let realAddress = readAddress.split(":")
|
|
||||||
let address = realAddress[0]
|
|
||||||
let port = parseInt(realAddress[1] || "25565")
|
|
||||||
let client = commandLineCreateClient()
|
|
||||||
|
|
||||||
function commandLineCreateClient() {
|
|
||||||
return createConnection(address, port, username, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createConnection(host: string, port: number, username: string, password: string) {
|
|
||||||
let clientOptions: any = {
|
|
||||||
version,
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
// clientToken: 'd02c7f39-2376-45da-a5a5-50e24fa8b185',
|
|
||||||
//@ts-ignore
|
|
||||||
// authServer: 'https://skin.yumc.pw/api/yggdrasil/authserver',
|
|
||||||
// sessionServer: 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
|
||||||
}
|
|
||||||
if (clientOptions.password) {
|
|
||||||
clientOptions.clientToken = 'd02c7f39-2376-45da-a5a5-50e24fa8b185'
|
|
||||||
clientOptions.authServer = 'https://skin.yumc.pw/api/yggdrasil/authserver'
|
|
||||||
clientOptions.sessionServer = 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
|
||||||
}
|
|
||||||
let client = createClient(clientOptions)
|
|
||||||
|
|
||||||
attachCommon(client)
|
|
||||||
attachForge(client)
|
|
||||||
attachEvents(client)
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachCommon(client: Client) {
|
|
||||||
client.on('login', () => {
|
|
||||||
// client.registerChannel('updater', ['string', []])
|
|
||||||
// client.registerChannel('updater-enabled', ['string', []])
|
|
||||||
// client.registerChannel('dragoncore', ['string', []])
|
|
||||||
// client.registerChannel('dragoncore:main', ['string', []])
|
|
||||||
client.on('REGISTER', (array) => {
|
|
||||||
for (const channel of array) {
|
|
||||||
client.on('channel', console.log)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// client.on('dragoncore:main', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
client.on('custom_payload', (data) => {
|
|
||||||
console.log('custom_payload' + JSON.stringify(data))
|
|
||||||
})
|
|
||||||
client.on('error', (error) => {
|
|
||||||
console.log("Client Error", error)
|
|
||||||
})
|
|
||||||
client.on('end', (resone) => {
|
|
||||||
console.log("Client End Resone:", resone)
|
|
||||||
if (`${resone}` != "SocketClosed") {
|
|
||||||
setTimeout(() => {
|
|
||||||
client = commandLineCreateClient()
|
|
||||||
}, 500)
|
|
||||||
} else {
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const rl = createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout,
|
|
||||||
completer: (line, func) => {
|
|
||||||
let args = line.split(' ')
|
|
||||||
let comp = args[args.length - 1]
|
|
||||||
client.once('tab_complete', (msg) => {
|
|
||||||
let mcts = msg.matches.filter(s => s)
|
|
||||||
func(null, [mcts, comp])
|
|
||||||
})
|
|
||||||
client.write('tab_complete', {
|
|
||||||
text: line
|
|
||||||
})
|
|
||||||
},
|
|
||||||
terminal: true,
|
|
||||||
prompt: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
rl.on('line', function (line) {
|
|
||||||
switch (line) {
|
|
||||||
case "":
|
|
||||||
break
|
|
||||||
case "eval":
|
|
||||||
break
|
|
||||||
case "write":
|
|
||||||
break
|
|
||||||
case "/respawn":
|
|
||||||
client.write('client_command', { payload: 0 })
|
|
||||||
break
|
|
||||||
case "//reco":
|
|
||||||
client.end("")
|
|
||||||
client = commandLineCreateClient()
|
|
||||||
break
|
|
||||||
case "//quit":
|
|
||||||
console.info('Disconnected')
|
|
||||||
client.end("")
|
|
||||||
break
|
|
||||||
case "//end":
|
|
||||||
console.info('Forcibly ended client')
|
|
||||||
process.exit(0)
|
|
||||||
default:
|
|
||||||
client.write('chat', { message: line })
|
|
||||||
}
|
|
||||||
rl.prompt()
|
|
||||||
})
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
while :; do
|
|
||||||
yarn emp
|
|
||||||
echo 进程退出 休眠120秒!
|
|
||||||
sleep 120
|
|
||||||
done
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/common",
|
"name": "@ccms/common",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript common package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"@javatypes/jdk": "^0.0.3",
|
"@javatypes/jdk": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,20 @@ interface RequestConfig {
|
|||||||
method?: Method
|
method?: Method
|
||||||
headers?: { [key: string]: string }
|
headers?: { [key: string]: string }
|
||||||
params?: { [key: string]: string }
|
params?: { [key: string]: string }
|
||||||
data?: any
|
data?: any,
|
||||||
|
connectTimeout?: number,
|
||||||
|
readTimeout?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
function request(config: RequestConfig) {
|
function request(config: RequestConfig) {
|
||||||
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
||||||
let xhr = new XMLHttpRequest()
|
let xhr = new XMLHttpRequest()
|
||||||
|
if (config.connectTimeout) {
|
||||||
|
xhr.connectTimeout = config.connectTimeout
|
||||||
|
}
|
||||||
|
if (config.readTimeout) {
|
||||||
|
xhr.readTimeout = config.readTimeout
|
||||||
|
}
|
||||||
xhr.open(config.method, config.url, false)
|
xhr.open(config.method, config.url, false)
|
||||||
for (const header in config.headers) {
|
for (const header in config.headers) {
|
||||||
xhr.setRequestHeader(header, config.headers[header])
|
xhr.setRequestHeader(header, config.headers[header])
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Reflect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
||||||
|
fieldCache.set(key, field)
|
||||||
return accessible(field)
|
return accessible(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,12 +130,14 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
let field = null
|
let field = null
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
while (target !== JavaObject.class) {
|
while (target !== JavaObject.class) {
|
||||||
|
console.debug(`reflect field ${name} from ${target.getName()}`)
|
||||||
try {
|
try {
|
||||||
field = target.getDeclaredField(name)
|
field = target.getDeclaredField(name)
|
||||||
if (field !== null) { break }
|
if (field !== null) { break }
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (target === undefined) { break }
|
if (target === undefined) { break }
|
||||||
target = target.getSuperclass()
|
target = target.getSuperclass()
|
||||||
|
console.debug(`switch to super class: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field === null) {
|
if (field === null) {
|
||||||
@@ -146,21 +149,32 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
||||||
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
||||||
if (methodCache.has(key)) { return methodCache.get(key) }
|
if (methodCache.has(key)) { return methodCache.get(key) }
|
||||||
|
let target = clazz
|
||||||
if (typeof nameOrIndex === "number") {
|
if (typeof nameOrIndex === "number") {
|
||||||
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
||||||
} else {
|
} else {
|
||||||
try {
|
while (target !== JavaObject.class && !methodCache.has(key)) {
|
||||||
methodCache.set(key, clazz.getMethod(nameOrIndex, clazzs as any))
|
|
||||||
} catch (ex: any) {
|
|
||||||
try {
|
try {
|
||||||
methodCache.set(key, clazz.getDeclaredMethod(nameOrIndex, clazzs as any))
|
console.debug(`reflect method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${target.getName()}`)
|
||||||
} catch (ex: any) {
|
try {
|
||||||
for (const m of Java.from(declaredMethods(clazz))) {
|
methodCache.set(key, target.getMethod(nameOrIndex, clazzs as any))
|
||||||
if (m.getName() == nameOrIndex) {
|
} catch (ex: any) {
|
||||||
methodCache.set(key, m)
|
try {
|
||||||
break
|
methodCache.set(key, target.getDeclaredMethod(nameOrIndex, clazzs as any))
|
||||||
|
} catch (ex: any) {
|
||||||
|
for (const m of Java.from(declaredMethods(target))) {
|
||||||
|
if (m.getName() == nameOrIndex) {
|
||||||
|
methodCache.set(key, m)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} not found.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (target === undefined) { break }
|
||||||
|
target = target.getSuperclass()
|
||||||
|
console.debug(`switch to super class: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +187,7 @@ function declaredMethods(clazz: java.lang.Class<any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapToObject(javaObj) {
|
function mapToObject(javaObj) {
|
||||||
if (!Java.isJavaObject(javaObj)) { throw new TypeError(`参数 ${javaObj} 不是一个Java对象!`) }
|
if (!Java.isJavaObject(javaObj)) { throw new TypeError(`argument ${javaObj} is not a java object.`) }
|
||||||
let target = Proxy.newProxy(javaObj, {
|
let target = Proxy.newProxy(javaObj, {
|
||||||
apply: (target, name, args) => { return args ? javaObj[name](args) : javaObj[name]() }
|
apply: (target, name, args) => { return args ? javaObj[name](args) : javaObj[name]() }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ class ChatMessagePart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
convert() {
|
convert() {
|
||||||
return this.internal;
|
return this.internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tellraw {
|
class Tellraw {
|
||||||
static duplicateChar = '§卐'
|
static duplicateChar = '§卐'
|
||||||
static create() {
|
static create() {
|
||||||
return new Tellraw().then(Tellraw.duplicateChar);
|
return new Tellraw().then(Tellraw.duplicateChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
private cache: string = '';
|
private cache: string = '';
|
||||||
@@ -32,77 +32,81 @@ class Tellraw {
|
|||||||
|
|
||||||
then(part: ChatMessagePart | string) {
|
then(part: ChatMessagePart | string) {
|
||||||
if (typeof part === "string") {
|
if (typeof part === "string") {
|
||||||
var newPart = new ChatMessagePart();
|
var newPart = new ChatMessagePart()
|
||||||
newPart.text = part
|
newPart.text = part
|
||||||
this.then(newPart);
|
this.then(newPart)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
var last = this.latest();
|
var last = this.latest()
|
||||||
if (!last.text) {
|
if (!last.text) {
|
||||||
last.text = part.text;
|
last.text = part.text
|
||||||
} else {
|
} else {
|
||||||
this.parts.push(part);
|
this.parts.push(part)
|
||||||
}
|
}
|
||||||
this.cache = null;
|
this.cache = null
|
||||||
}
|
}
|
||||||
|
|
||||||
text(text: string) {
|
text(text: string) {
|
||||||
this.latest().text = text;
|
this.latest().text = text
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
tip(text: string) {
|
tip(texts: string) {
|
||||||
this.latest().hover("show_text", text);
|
return this.hover(texts)
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item(text: string) {
|
hover(texts: string) {
|
||||||
this.latest().hover("show_item", text);
|
this.latest().hover("show_text", texts)
|
||||||
return this;
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
item(item: string) {
|
||||||
|
this.latest().hover("show_item", item)
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
command(command: string) {
|
command(command: string) {
|
||||||
this.latest().click("run_command", command);
|
this.latest().click("run_command", command)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
suggest(url: string) {
|
suggest(url: string) {
|
||||||
this.latest().click("suggest_command", url);
|
this.latest().click("suggest_command", url)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
file(path: string) {
|
file(path: string) {
|
||||||
this.latest().click("open_file", path);
|
this.latest().click("open_file", path)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
link(url: string) {
|
link(url: string) {
|
||||||
this.latest().click("open_url", url);
|
this.latest().click("open_url", url)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
latest() {
|
latest() {
|
||||||
return this.parts[this.parts.length - 1];
|
return this.parts[this.parts.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
json() {
|
json() {
|
||||||
if (!this.cache) {
|
if (!this.cache) {
|
||||||
var temp = [];
|
var temp = []
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp.push(t.convert());
|
temp.push(t.convert())
|
||||||
});
|
})
|
||||||
this.cache = JSON.stringify(temp);
|
this.cache = JSON.stringify(temp)
|
||||||
console.trace(this.cache);
|
console.trace(this.cache)
|
||||||
}
|
}
|
||||||
return this.cache;
|
return this.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
string() {
|
string() {
|
||||||
var temp = '';
|
var temp = ''
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp += t.text
|
temp += t.text
|
||||||
});
|
})
|
||||||
return temp;
|
return temp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
packages/common/src/version.ts
Normal file
35
packages/common/src/version.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
export type Version = [string, string, string]
|
||||||
|
|
||||||
|
export class VersionUtils {
|
||||||
|
static isEqual(version: string, targetVersion: string): boolean {
|
||||||
|
return version == targetVersion
|
||||||
|
}
|
||||||
|
static isGreaterOrEqual(version: string, targetVersion: string): boolean {
|
||||||
|
const v1 = parseVersion(version)
|
||||||
|
const v2 = parseVersion(targetVersion)
|
||||||
|
|
||||||
|
return (
|
||||||
|
v1[0] > v2[0] ||
|
||||||
|
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
||||||
|
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] >= v2[2])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
static isGreater(version: string, targetVersion: string): boolean {
|
||||||
|
const v1 = parseVersion(version)
|
||||||
|
const v2 = parseVersion(targetVersion)
|
||||||
|
|
||||||
|
return (
|
||||||
|
v1[0] > v2[0] ||
|
||||||
|
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
||||||
|
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] > v2[2])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVersion(version: string = ""): Version {
|
||||||
|
const v: Version = ['0', '0', '0']
|
||||||
|
|
||||||
|
version.split(".").forEach((value, i) => (v[i] = value))
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/compile",
|
"name": "@ccms/compile",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript compile package",
|
"description": "MiaoScript compile package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/container",
|
"name": "@ccms/container",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript container package",
|
"description": "MiaoScript container package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
|
|||||||
@@ -1,38 +1,9 @@
|
|||||||
import { interfaces, Container } from "inversify"
|
import { interfaces, Container } from "inversify"
|
||||||
|
import { _proxyGetter } from "./utils"
|
||||||
|
|
||||||
let _container: Container
|
let _container: Container
|
||||||
|
|
||||||
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
||||||
const INJECTION = Symbol.for("INJECTION")
|
|
||||||
|
|
||||||
function _proxyGetter(
|
|
||||||
proto: any,
|
|
||||||
key: string,
|
|
||||||
resolve: () => any,
|
|
||||||
doCache: boolean
|
|
||||||
) {
|
|
||||||
function getter(this: object) {
|
|
||||||
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
|
||||||
}
|
|
||||||
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
return Reflect.getMetadata(INJECTION, this, key)
|
|
||||||
} else {
|
|
||||||
return resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setter(this: object, newVal: any) {
|
|
||||||
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(proto, key, {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
get: getter,
|
|
||||||
set: setter
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function initContainer(container: Container) {
|
function initContainer(container: Container) {
|
||||||
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { initContainer, getContainer } from './decorators'
|
|||||||
import { interfaces, Container, inject, named } from 'inversify'
|
import { interfaces, Container, inject, named } from 'inversify'
|
||||||
import { fluentProvide } from 'inversify-binding-decorators'
|
import { fluentProvide } from 'inversify-binding-decorators'
|
||||||
import { ioc } from "./constants"
|
import { ioc } from "./constants"
|
||||||
|
import { _proxyGetter } from "./utils"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个命名对象
|
* 注册一个命名对象
|
||||||
@@ -49,9 +50,11 @@ export const JavaClass = (className: string) => {
|
|||||||
*/
|
*/
|
||||||
export const JSClass = (className: string) => {
|
export const JSClass = (className: string) => {
|
||||||
return function (target: object, propertyKey: string, index?: number) {
|
return function (target: object, propertyKey: string, index?: number) {
|
||||||
try { target[propertyKey] = Java.type(className); return } catch (error: any) { }
|
_proxyGetter(target, propertyKey, () => {
|
||||||
try { target[propertyKey] = base.getClass(className).static; return } catch (error: any) { }
|
try { return Java.type(className) } catch (error: any) { }
|
||||||
console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
try { return base.getClass(className).static } catch (error: any) { }
|
||||||
|
console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
||||||
|
}, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +91,59 @@ export const Resource = (resourceName?: string | any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DocumentBuilderFactory = Java.type('javax.xml.parsers.DocumentBuilderFactory')
|
||||||
|
|
||||||
|
export const MavenDepend = (groupId: string, artifactId: string, version: string, recursion = false) => {
|
||||||
|
return function (target: any) {
|
||||||
|
loadMavenDepend(groupId, artifactId, version, recursion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadedMavenDepend = new Set<string>()
|
||||||
|
|
||||||
|
export function loadMavenDepend(groupId: string, artifactId: string, version: string, recursion = false) {
|
||||||
|
const key = `${groupId}:${artifactId}:${version}`
|
||||||
|
try {
|
||||||
|
if (loadedMavenDepend.has(key)) { return }
|
||||||
|
console.info('loading maven dependency', key)
|
||||||
|
let [pom, _] = base.loadMavenDepend(groupId, artifactId, version)
|
||||||
|
loadedMavenDepend.add(key)
|
||||||
|
if (recursion) {
|
||||||
|
let doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(pom)
|
||||||
|
let dependencies = doc.getElementsByTagName("dependency")
|
||||||
|
let size = dependencies.length
|
||||||
|
if (!size) { return }
|
||||||
|
console.debug(key, 'found', size, 'dependencies loading...')
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
const dependency = dependencies.item(i)
|
||||||
|
const gav = dependency.getChildNodes()
|
||||||
|
const length = gav.length
|
||||||
|
const dependencyVersion = { groupId: '', artifactId: '', version: '' }
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
const prop = gav.item(j)
|
||||||
|
switch (prop.getNodeName()) {
|
||||||
|
case "groupId":
|
||||||
|
dependencyVersion.groupId = prop.getTextContent()
|
||||||
|
break
|
||||||
|
case "artifactId":
|
||||||
|
dependencyVersion.artifactId = prop.getTextContent()
|
||||||
|
break
|
||||||
|
case "version":
|
||||||
|
dependencyVersion.version = prop.getTextContent()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadMavenDepend(dependencyVersion.groupId, dependencyVersion.artifactId, dependencyVersion.version, recursion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.warn('load maven dependency', key, 'failed. Error:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
||||||
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
||||||
result[entry.key] = entry.value
|
result[entry.key] = entry.value
|
||||||
@@ -98,8 +154,10 @@ export const reduceMetadata = (ctx: interfaces.Context): any => {
|
|||||||
function initAutowired(container: Container) {
|
function initAutowired(container: Container) {
|
||||||
container.bind(ioc.Autowired).toDynamicValue((ctx) => {
|
container.bind(ioc.Autowired).toDynamicValue((ctx) => {
|
||||||
var metadata: any = reduceMetadata(ctx)
|
var metadata: any = reduceMetadata(ctx)
|
||||||
let key = Object.toString.call(metadata.named)
|
let key = Object.prototype.toString.call(metadata.named)
|
||||||
if (key === "[object Function]" || key === "[object Symbol]") { return container.get(metadata.named) }
|
if (key === "[object Function]" || key === "[object Symbol]") { return container.get(metadata.named) }
|
||||||
|
console.warn('container Autowired', metadata.named, 'failed. Error: illegal serviceIdentifier type', key)
|
||||||
|
console.debug(metadata.named, 'metadata', JSON.stringify(metadata))
|
||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
30
packages/container/src/utils.ts
Normal file
30
packages/container/src/utils.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const INJECTION = Symbol.for("INJECTION")
|
||||||
|
|
||||||
|
export function _proxyGetter(
|
||||||
|
proto: any,
|
||||||
|
key: string,
|
||||||
|
resolve: () => any,
|
||||||
|
doCache: boolean
|
||||||
|
) {
|
||||||
|
function getter(this: object) {
|
||||||
|
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
||||||
|
}
|
||||||
|
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
return Reflect.getMetadata(INJECTION, this, key)
|
||||||
|
} else {
|
||||||
|
return resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setter(this: object, newVal: any) {
|
||||||
|
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(proto, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: getter,
|
||||||
|
set: setter
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/core",
|
"name": "@ccms/core",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript core package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -20,12 +20,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/core/src/.gitignore
vendored
Normal file
1
packages/core/src/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
script
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
let containerStartTime = Date.now()
|
let containerStartTime = Date.now()
|
||||||
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
||||||
import { plugin, server, task, constants } from '@ccms/api'
|
import { plugin, server, task, constants, console as jsconsole } from '@ccms/api'
|
||||||
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
||||||
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
||||||
|
import * as yaml from 'js-yaml'
|
||||||
import http from '@ccms/common/dist/http'
|
import http from '@ccms/common/dist/http'
|
||||||
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
import { VersionUtils } from '@ccms/common/dist/version'
|
||||||
|
|
||||||
|
const UUID = Java.type('java.util.UUID')
|
||||||
|
const MiaoScriptAPI = Java.type('pw.yumc.MiaoScript.api.MiaoScriptAPI')
|
||||||
|
|
||||||
@provideSingleton(MiaoScriptCore)
|
@provideSingleton(MiaoScriptCore)
|
||||||
class MiaoScriptCore {
|
class MiaoScriptCore {
|
||||||
@@ -17,17 +23,31 @@ class MiaoScriptCore {
|
|||||||
private pluginManager: plugin.PluginManager
|
private pluginManager: plugin.PluginManager
|
||||||
|
|
||||||
enable() {
|
enable() {
|
||||||
|
process.emit('core.before.enable')
|
||||||
this.loadServerConsole()
|
this.loadServerConsole()
|
||||||
|
try {
|
||||||
|
MiaoScriptAPI.setPluginManager(this.pluginManager)
|
||||||
|
} catch (error) {
|
||||||
|
}
|
||||||
this.loadPlugins()
|
this.loadPlugins()
|
||||||
|
process.emit('core.after.enable')
|
||||||
|
console.i18n("ms.core.engine.completed", {
|
||||||
|
loader: base.version,
|
||||||
|
version: 'v' + global.ScriptEngineVersion,
|
||||||
|
time: (Date.now() - global.ScriptEngineStartTime) / 1000
|
||||||
|
})
|
||||||
return () => this.disable()
|
return () => this.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadServerConsole() {
|
loadServerConsole() {
|
||||||
|
process.emit('core.before.load.console')
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
global.setGlobal('console', new this.Console(), { writable: false, configurable: false })
|
global.setGlobal('console', new this.Console(), { writable: false, configurable: false })
|
||||||
|
process.emit('core.after.load.console')
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPlugins() {
|
loadPlugins() {
|
||||||
|
process.emit('core.before.load.plugins')
|
||||||
let loadPluginStartTime = new Date().getTime()
|
let loadPluginStartTime = new Date().getTime()
|
||||||
console.i18n("ms.core.plugin.initialize")
|
console.i18n("ms.core.plugin.initialize")
|
||||||
this.pluginManager.scan(this.pluginFolder)
|
this.pluginManager.scan(this.pluginFolder)
|
||||||
@@ -35,15 +55,25 @@ class MiaoScriptCore {
|
|||||||
this.pluginManager.load(this.pluginManager.getPlugins())
|
this.pluginManager.load(this.pluginManager.getPlugins())
|
||||||
this.pluginManager.enable(this.pluginManager.getPlugins())
|
this.pluginManager.enable(this.pluginManager.getPlugins())
|
||||||
console.i18n("ms.core.plugin.completed", { time: (new Date().getTime() - loadPluginStartTime) / 1000 })
|
console.i18n("ms.core.plugin.completed", { time: (new Date().getTime() - loadPluginStartTime) / 1000 })
|
||||||
|
process.emit('core.after.load.plugins')
|
||||||
}
|
}
|
||||||
|
|
||||||
disable() {
|
disable() {
|
||||||
|
process.emit('core.before.disable')
|
||||||
let disableStartTime = Date.now()
|
let disableStartTime = Date.now()
|
||||||
console.i18n("ms.core.engine.disable")
|
console.i18n("ms.core.engine.disable")
|
||||||
this.pluginManager.disable(this.pluginManager.getPlugins())
|
this.pluginManager.disable(this.pluginManager.getPlugins())
|
||||||
this.taskManager.disable()
|
this.taskManager.disable()
|
||||||
|
process.emit('core.after.disable')
|
||||||
|
loadCoreScript('exit')
|
||||||
|
process.emit('core.before.exit')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
console.i18n("ms.core.engine.disable.finish", { version: 'v' + global.ScriptEngineVersion, time: (new Date().getTime() - disableStartTime) / 1000 })
|
console.i18n("ms.core.engine.disable.finish", {
|
||||||
|
loader: base.version,
|
||||||
|
version: 'v' + global.ScriptEngineVersion,
|
||||||
|
time: (new Date().getTime() - disableStartTime) / 1000
|
||||||
|
})
|
||||||
|
process.emit('core.after.exit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,31 +106,76 @@ function detectServer(): constants.ServerType {
|
|||||||
throw Error('Unknow Server Type...')
|
throw Error('Unknow Server Type...')
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialize() {
|
function loadCoreScript(name) {
|
||||||
global.ScriptEngineVersion = require('../package.json').version
|
|
||||||
try { engineLoad({ script: http.get("http://ms.yumc.pw/api/plugin/download/name/initialize"), name: 'core/initialize.js' }) } catch (error: any) { console.debug(error) }
|
|
||||||
try {
|
try {
|
||||||
let corePackageStartTime = new Date().getTime()
|
let scriptname = name + (global.debug ? '-debug' : '')
|
||||||
container.bind(ContainerInstance).toConstantValue(container)
|
engineLoad({
|
||||||
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
|
script: http.get(`https://mscript.yumc.pw/api/plugin/download/name/${scriptname}`),
|
||||||
container.bind(plugin.PluginFolder).toConstantValue('plugins')
|
name: `core/${scriptname}.js`
|
||||||
let type = detectServer()
|
})
|
||||||
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
|
||||||
container.bind(server.ServerType).toConstantValue(type)
|
|
||||||
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
|
||||||
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
|
||||||
console.i18n("ms.core.package.initialize", { scope: global.scope, type })
|
|
||||||
require(`${global.scope}/${type}`).default(container)
|
|
||||||
require(`${global.scope}/plugin`)
|
|
||||||
container.load(buildProviderModule())
|
|
||||||
console.i18n("ms.core.package.completed", { scope: global.scope, type, time: (Date.now() - corePackageStartTime) / 1000 })
|
|
||||||
let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable()
|
|
||||||
console.i18n("ms.core.engine.completed", { version: 'v' + global.ScriptEngineVersion, time: (Date.now() - global.ScriptEngineStartTime) / 1000 })
|
|
||||||
return disable
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.i18n("ms.core.initialize.error", { error })
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.debug(error)
|
||||||
return () => console.i18n('ms.core.engine.disable.abnormal')
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMiaoScriptConfig() {
|
||||||
|
let configFile = fs.concat(root, 'config.yml')
|
||||||
|
if (!fs.exists(configFile)) {
|
||||||
|
global.ScriptEngineConfig = base.save(configFile, yaml.dump({
|
||||||
|
uuid: UUID.randomUUID().toString(),
|
||||||
|
slow_execute: 50
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
global.ScriptEngineConfig = yaml.load(base.read(configFile))
|
||||||
|
}
|
||||||
|
global.ScriptSlowExecuteTime = global.ScriptEngineConfig.slow_execute || 50
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCore() {
|
||||||
|
let corePackageStartTime = new Date().getTime()
|
||||||
|
container.bind(ContainerInstance).toConstantValue(container)
|
||||||
|
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
|
||||||
|
container.bind(plugin.PluginFolder).toConstantValue('plugins')
|
||||||
|
let type = detectServer()
|
||||||
|
|
||||||
|
process.emit('core.before.initialize.detect')
|
||||||
|
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
||||||
|
container.bind(server.ServerType).toConstantValue(type)
|
||||||
|
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
||||||
|
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
||||||
|
container.bind(server.NativePluginChecker).toSelf().inSingletonScope()
|
||||||
|
process.emit('core.after.initialize.detect')
|
||||||
|
|
||||||
|
process.emit('core.before.package.initialize')
|
||||||
|
console.i18n("ms.core.package.initialize", { scope: global.scope, type })
|
||||||
|
require(`${global.scope}/${type}`).default(container)
|
||||||
|
require(`${global.scope}/plugin`)
|
||||||
|
container.load(buildProviderModule())
|
||||||
|
console.i18n("ms.core.package.completed", { scope: global.scope, type, time: (Date.now() - corePackageStartTime) / 1000 })
|
||||||
|
process.emit('core.after.package.initialize')
|
||||||
|
return container.get<MiaoScriptCore>(MiaoScriptCore)
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
process.emit('core.before.initialize')
|
||||||
|
loadMiaoScriptConfig()
|
||||||
|
global.ScriptEngineVersion = require('../package.json').version
|
||||||
|
global.setGlobal('loadCoreScript', loadCoreScript)
|
||||||
|
loadCoreScript('initialize')
|
||||||
|
try {
|
||||||
|
let core = createCore()
|
||||||
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
|
} catch (error: any) {
|
||||||
|
let core = { enable: () => () => console.i18n('ms.core.engine.disable.abnormal') }
|
||||||
|
console.i18n("core.initialize.error", { error })
|
||||||
|
jsconsole.getStackTrace(error, false).forEach(line => console.log(line))
|
||||||
|
process.emit('core.initialize.error')
|
||||||
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
|
} finally {
|
||||||
|
process.emit('core.after.initialize')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
function initialize() {
|
|
||||||
var mspmc = 'http://ms.yumc.pw/api/plugin/download/name/'
|
|
||||||
|
|
||||||
var http = require('@ccms/common/dist/http').default
|
|
||||||
var fs = require('@ccms/common/dist/fs')
|
|
||||||
|
|
||||||
var pluginFolder = fs.concat(root, 'plugins')
|
|
||||||
var updateFolder = fs.concat(pluginFolder, 'update')
|
|
||||||
var pluginFile = fs.concat(pluginFolder, 'MiaoScriptPackageManager.js')
|
|
||||||
if (!fs.exists(pluginFile)) {
|
|
||||||
fs.mkdirs(pluginFile)
|
|
||||||
base.save(fs.concat(updateFolder, 'MiaoScriptPackageManager.auto.install'), '.')
|
|
||||||
}
|
|
||||||
fs.list(updateFolder).forEach(function (path) {
|
|
||||||
var file = path.toFile()
|
|
||||||
if (file.exists()) {
|
|
||||||
var filename = file.getName()
|
|
||||||
if (filename.endsWith(".auto.install")) {
|
|
||||||
var pluginName = filename.replace('.auto.install', '')
|
|
||||||
var pluginFile = fs.concat(pluginFolder, pluginName + '.js')
|
|
||||||
if (!fs.exists(pluginFile)) {
|
|
||||||
var pluginTemp = pluginFile + '.tmp'
|
|
||||||
http.download(mspmc + pluginName, pluginTemp)
|
|
||||||
fs.move(pluginTemp, pluginFile, true)
|
|
||||||
}
|
|
||||||
base.delete(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
var core = http.get('https://registry.npmmirror.com/@ccms/core')
|
|
||||||
if (base.VERSION && global.ScriptEngineVersion != core['dist-tags']['latest']) {
|
|
||||||
var Paths = Java.type('java.nio.file.Paths')
|
|
||||||
base.save(Paths.get(root, "upgrade"), core['dist-tags']['latest'])
|
|
||||||
console.info('@ccms/core found new version ' + core['dist-tags']['latest'] + ' will upgrade after reboot!')
|
|
||||||
}
|
|
||||||
console.debug('initialize finish!')
|
|
||||||
}
|
|
||||||
initialize()
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/database",
|
"name": "@ccms/database",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript database package",
|
"description": "MiaoScript database package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spring-jdbc": "^0.0.3",
|
"@javatypes/spring-jdbc": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,88 +1,109 @@
|
|||||||
import { Model } from './model'
|
import { database } from '@ccms/api'
|
||||||
|
import { JSClass } from '@ccms/container'
|
||||||
|
|
||||||
const HikariDataSource = Java.type('com.zaxxer.hikari.HikariDataSource')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
const HikariConfig = Java.type('com.zaxxer.hikari.HikariConfig')
|
const JavaString = Java.type('java.lang.String')
|
||||||
const JdbcTemplate = Java.type('org.springframework.jdbc.core.JdbcTemplate')
|
const Properties = Java.type('java.util.Properties')
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据库配置
|
|
||||||
*/
|
|
||||||
export interface DataBaseConfig {
|
|
||||||
/**
|
|
||||||
* 数据库连接串
|
|
||||||
*/
|
|
||||||
url: string | javax.sql.DataSource
|
|
||||||
/**
|
|
||||||
* 数据库驱动
|
|
||||||
*/
|
|
||||||
driverClassName?: string
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
password?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库封装类
|
* 数据库封装类
|
||||||
*/
|
*/
|
||||||
export class DataBase {
|
export class DataBase extends database.DataBase {
|
||||||
private dataSource: javax.sql.DataSource
|
private dataSource: javax.sql.DataSource
|
||||||
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
||||||
|
|
||||||
constructor(dbConfig: DataBaseConfig) {
|
@JSClass('com.zaxxer.hikari.HikariDataSource')
|
||||||
|
private HikariDataSource: any
|
||||||
|
@JSClass('com.zaxxer.hikari.HikariConfig')
|
||||||
|
private HikariConfig: any
|
||||||
|
@JSClass('org.springframework.jdbc.core.JdbcTemplate')
|
||||||
|
private JdbcTemplate: typeof org.springframework.jdbc.core.JdbcTemplate
|
||||||
|
|
||||||
|
constructor(dbConfig: database.DataBaseConfig) {
|
||||||
|
super()
|
||||||
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
||||||
this.createDataSource(dbConfig)
|
this.createDataSource(dbConfig)
|
||||||
this.initialize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private createDataSource(dbConfig: DataBaseConfig) {
|
private createDataSource(dbConfig: database.DataBaseConfig) {
|
||||||
if (typeof dbConfig.url === "string") {
|
if (typeof dbConfig.url === "string") {
|
||||||
if (!dbConfig.username || !dbConfig.password) {
|
let originClassLoader = Thread.currentThread().getContextClassLoader()
|
||||||
throw new Error('DataBase username or password can\'t be null!')
|
Thread.currentThread().setContextClassLoader(base.getInstance().class.classLoader)
|
||||||
}
|
let config = new this.HikariConfig()
|
||||||
let config = new HikariConfig()
|
|
||||||
if (dbConfig.driverClassName) {
|
if (dbConfig.driverClassName) {
|
||||||
config.setDriverClassName(dbConfig.driverClassName)
|
config.setDriverClassName(dbConfig.driverClassName)
|
||||||
|
} else {
|
||||||
|
switch (dbConfig.type) {
|
||||||
|
case "h2":
|
||||||
|
config.setDriverClassName("org.h2.Driver")
|
||||||
|
break
|
||||||
|
case "sqlite":
|
||||||
|
config.setDriverClassName("org.sqlite.JDBC")
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dbConfig.username) {
|
||||||
|
config.setUsername(dbConfig.username)
|
||||||
|
}
|
||||||
|
if (dbConfig.password) {
|
||||||
|
config.setPassword(dbConfig.password)
|
||||||
}
|
}
|
||||||
config.setUsername(dbConfig.username)
|
|
||||||
config.setPassword(dbConfig.password)
|
|
||||||
config.setJdbcUrl(dbConfig.url)
|
config.setJdbcUrl(dbConfig.url)
|
||||||
this.dataSource = new HikariDataSource(config)
|
if (dbConfig.properties) {
|
||||||
|
let properties = new Properties()
|
||||||
|
for (const key in dbConfig.properties) {
|
||||||
|
properties.setProperty(key, dbConfig.properties[key])
|
||||||
|
}
|
||||||
|
config.setDataSourceProperties(properties)
|
||||||
|
}
|
||||||
|
console.debug('createDataSource from config ' + JSON.stringify(dbConfig))
|
||||||
|
this.dataSource = new this.HikariDataSource(config)
|
||||||
|
Thread.currentThread().setContextClassLoader(originClassLoader)
|
||||||
} else {
|
} else {
|
||||||
this.dataSource = dbConfig.url
|
this.dataSource = dbConfig.url
|
||||||
}
|
}
|
||||||
|
this.jdbcTemplate = new this.JdbcTemplate(this.dataSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
private initialize() {
|
getDataSource() {
|
||||||
this.jdbcTemplate = new JdbcTemplate(this.dataSource)
|
return this.dataSource
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行SQL查询
|
* 执行SQL查询
|
||||||
* @param sql SQL语句
|
* @param sql SQL语句
|
||||||
|
* @param args 参数
|
||||||
*/
|
*/
|
||||||
query<T>(sql: string, ...args: any[]): Array<T> {
|
query<T>(sql: string, ...args: any[]): Array<T> {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
||||||
console.debug(java.lang.String.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(JavaString.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行SQL更新
|
* 执行SQL更新
|
||||||
* @param sql SQL语句
|
* @param sql SQL语句
|
||||||
|
* @param args 参数
|
||||||
*/
|
*/
|
||||||
update(sql: string, ...args: any[]): number {
|
update(sql: string, ...args: any[]): number {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = this.jdbcTemplate.update(sql, args)
|
let result = this.jdbcTemplate.update(sql, args)
|
||||||
console.debug(java.lang.String.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(JavaString.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行SQL语句
|
||||||
|
* @param sql SQL语句
|
||||||
|
*/
|
||||||
|
execute(sql: string): void {
|
||||||
|
let startTime = Date.now()
|
||||||
|
this.jdbcTemplate.execute(sql)
|
||||||
|
console.debug(`\n[DB] execute \nSQL : ${sql} \nCOST : ${Date.now() - startTime}ms`)
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this.dataSource.close()
|
this.dataSource.close()
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
export function id() {
|
|
||||||
return (target: Object, propertyKey: string | symbol) => void {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,5 +2,11 @@
|
|||||||
/// <reference types="@javatypes/jdk" />
|
/// <reference types="@javatypes/jdk" />
|
||||||
/// <reference types="@javatypes/spring-jdbc" />
|
/// <reference types="@javatypes/spring-jdbc" />
|
||||||
|
|
||||||
|
import { loadMavenDepend } from '@ccms/container'
|
||||||
|
|
||||||
|
loadMavenDepend('com.h2database', 'h2', '2.1.212')
|
||||||
|
loadMavenDepend("com.zaxxer", "HikariCP", "4.0.3")
|
||||||
|
loadMavenDepend("org.springframework", "spring-jdbc", "5.3.19", true)
|
||||||
|
|
||||||
export * from './database'
|
export * from './database'
|
||||||
export * from './manager'
|
export * from './manager'
|
||||||
|
|||||||
@@ -1,27 +1,46 @@
|
|||||||
import { plugin, database } from '@ccms/api'
|
import { database } from '@ccms/api'
|
||||||
import { provideSingleton, inject, postConstruct } from '@ccms/container'
|
import { JSClass, provideSingleton } from '@ccms/container'
|
||||||
import { DataBase, DataBaseConfig } from './database'
|
import { DataBase } from './database'
|
||||||
|
|
||||||
@provideSingleton(database.DataBaseManager)
|
@provideSingleton(database.DataBaseManager)
|
||||||
export class DataBaseManager {
|
export class DataBaseManager extends database.DataBaseManager {
|
||||||
@inject(plugin.PluginInstance)
|
|
||||||
private instance: any
|
|
||||||
|
|
||||||
private beanFactory: any
|
|
||||||
private mainDatabase: DataBase
|
private mainDatabase: DataBase
|
||||||
private databases: { [key: string]: DataBase } = {}
|
private databases = new Map<string, DataBase>()
|
||||||
|
|
||||||
@postConstruct()
|
@JSClass('org.h2.tools.Server')
|
||||||
initialize() {
|
private Server: any
|
||||||
try {
|
|
||||||
this.beanFactory = this.instance.getAutowireCapableBeanFactory()
|
private webManager: any
|
||||||
let mainDatasource = this.beanFactory.getBean(Packages.javax.sql.DataSource.class)
|
|
||||||
this.mainDatabase = new DataBase({ url: mainDatasource })
|
constructor() {
|
||||||
} catch (error: any) {
|
super()
|
||||||
console.ex(error)
|
process.on('exit', () => this.shutdown())
|
||||||
|
}
|
||||||
|
|
||||||
|
startWebManager(...args: string[]) {
|
||||||
|
this.webManager = this.Server.createWebServer(args)
|
||||||
|
this.webManager.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
stopWebManager() {
|
||||||
|
if (this.webManager) {
|
||||||
|
this.webManager.stop()
|
||||||
|
this.webManager.shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shutdown() {
|
||||||
|
this.stopWebManager()
|
||||||
|
this.disable()
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置主数据库
|
||||||
|
* @param mainDatabase 主数据库
|
||||||
|
*/
|
||||||
|
setMainDatabase(mainDatabase: DataBase) {
|
||||||
|
this.mainDatabase = mainDatabase
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得主数据库
|
* 获得主数据库
|
||||||
* Get MainDatabase
|
* Get MainDatabase
|
||||||
@@ -36,18 +55,28 @@ export class DataBaseManager {
|
|||||||
* @param name 数据库名称 用于代码 database Name use at code
|
* @param name 数据库名称 用于代码 database Name use at code
|
||||||
* @param config 数据库配置
|
* @param config 数据库配置
|
||||||
*/
|
*/
|
||||||
createDatabase(name: string, config: DataBaseConfig) {
|
createDatabase(name: string, config: database.DataBaseConfig) {
|
||||||
Java.synchronized(() => {
|
return Java.synchronized(() => {
|
||||||
if (this.databases[name]) return this.databases[name]
|
if (!this.databases.has(name)) {
|
||||||
return this.databases[name] = new DataBase(config)
|
this.databases.set(name, new DataBase(config))
|
||||||
|
}
|
||||||
|
return this.databases.get(name)
|
||||||
}, this.databases)()
|
}, this.databases)()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeDatabase(name: string) {
|
||||||
|
if (this.databases.has(name)) {
|
||||||
|
this.databases.get(name).close()
|
||||||
|
}
|
||||||
|
return this.databases.delete(name)
|
||||||
|
}
|
||||||
|
|
||||||
getDatabase(name: string) {
|
getDatabase(name: string) {
|
||||||
return this.databases[name]
|
return this.databases.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
disable() {
|
disable() {
|
||||||
Object.values(this.databases).forEach((ds) => ds?.close())
|
this.databases.forEach((db) => db.close())
|
||||||
|
this.databases.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { DataBase } from "./database"
|
|
||||||
|
|
||||||
export class Model<T> {
|
|
||||||
constructor(private database: DataBase) {
|
|
||||||
|
|
||||||
}
|
|
||||||
queryForList(): Array<T> {
|
|
||||||
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,7 @@ ms.core.plugin.initialize: "Initialization MiaoScript Plugin System. Please wait
|
|||||||
ms.core.plugin.completed: "MiaoScript Plugin System loading completed({time}s)!"
|
ms.core.plugin.completed: "MiaoScript Plugin System loading completed({time}s)!"
|
||||||
ms.core.engine.completed: "MiaoScript ScriptEngine loading completed... Done({time}s)!"
|
ms.core.engine.completed: "MiaoScript ScriptEngine loading completed... Done({time}s)!"
|
||||||
ms.core.engine.disable: "Disable MiaoScript Engine..."
|
ms.core.engine.disable: "Disable MiaoScript Engine..."
|
||||||
|
ms.core.engine.disable.finish: "MiaoScript framework {loader} engine {version} 关闭完成... 耗时({time}s)!"
|
||||||
ms.core.engine.disable.abnormal: "abnormal Initialization MiaoScript Engine. Skip disable step..."
|
ms.core.engine.disable.abnormal: "abnormal Initialization MiaoScript Engine. Skip disable step..."
|
||||||
|
|
||||||
ms.api.event.resource.not.found: "Can't Mapping Event Because not found Resources {resource}!"
|
ms.api.event.resource.not.found: "Can't Mapping Event Because not found Resources {resource}!"
|
||||||
@@ -21,16 +22,20 @@ ms.api.event.not.found: "§6Plugin §b{name} §6register {event} error. event no
|
|||||||
ms.api.event.execute.slow: "§cWARN! §6Plugin §b{name} §6execute §d{event} §6evnet §ccost §4{cost}ms !"
|
ms.api.event.execute.slow: "§cWARN! §6Plugin §b{name} §6execute §d{event} §6evnet §ccost §4{cost}ms !"
|
||||||
ms.api.event.execute.error: "§6Plugin §b{name} §6execute §d{event} §6event error §4{ex}"
|
ms.api.event.execute.error: "§6Plugin §b{name} §6execute §d{event} §6event error §4{ex}"
|
||||||
ms.api.event.listen.plugin.name.empty: "Plugin name can't be empty!"
|
ms.api.event.listen.plugin.name.empty: "Plugin name can't be empty!"
|
||||||
ms.api.event.register: "[{name}] register event {event}"
|
ms.api.event.register: "[{name}] register event {event} priority {priority} ignoreCancelled {ignore}"
|
||||||
ms.api.event.unregister: "[{name}] unregister event {event}"
|
ms.api.event.unregister: "[{name}] unregister event {event}"
|
||||||
|
|
||||||
ms.api.command.register.input.error: "CommandExec Must be a function... Input: {exec}"
|
ms.api.command.register.input.error: "CommandExec Must be a function... Input: {exec}"
|
||||||
ms.api.command.register: "[{plugin}] register command {name}({cmd})..."
|
ms.api.command.register: "[{plugin}] register command {name}({cmd})..."
|
||||||
ms.api.command.unregister: "[{plugin}] unregister command {name}..."
|
ms.api.command.unregister: "[{plugin}] unregister command {name}..."
|
||||||
|
ms.api.command.execute.slow: "§cWarn. §6Player §a{player} §6exec §b{plugin} §6Plugin §d{command} {args} §6Command §cCost §4{cost}ms !"
|
||||||
ms.api.command.execute.error: "§6Player {player} §6exec §b{plugin} §6Plugin Command §d{command} {args} §6error §4{ex}"
|
ms.api.command.execute.error: "§6Player {player} §6exec §b{plugin} §6Plugin Command §d{command} {args} §6error §4{ex}"
|
||||||
|
ms.api.command.tab.completer.slow: "§cWarn. §6Player §a{player} §6exec §b{plugin} §6Plugin §d{command} {args} §6TabComplete §cCost §4{cost}ms !"
|
||||||
ms.api.command.tab.completer.error: "§6Player {player} §6exec §b{plugin} §6Plugin TabComplete §d{command} {args} §6error §4{ex}"
|
ms.api.command.tab.completer.error: "§6Player {player} §6exec §b{plugin} §6Plugin TabComplete §d{command} {args} §6error §4{ex}"
|
||||||
|
|
||||||
ms.plugin.initialize: "Initialization MiaoScript Plugin System: Plugin: {plugin} Loader: {loader}..."
|
ms.plugin.initialize: "Initialization MiaoScript Plugin System: Plugin: {plugin} Loader: {loader}..."
|
||||||
ms.plugin.event.map: "Total {count} {type} Event Mapping Complate..."
|
ms.plugin.event.map: "Total {count} {type} Event Mapping Complate..."
|
||||||
|
ms.plugin.event.map.error: "Mapping {type} Event Failed. Error: {error}"
|
||||||
ms.plugin.manager.scan: "Scanner {scanner} Scanning Plugins in {folder} ..."
|
ms.plugin.manager.scan: "Scanner {scanner} Scanning Plugins in {folder} ..."
|
||||||
ms.plugin.manager.scan.finish: "Scanner {scanner} Found {size} Plugins in {folder} Start Build..."
|
ms.plugin.manager.scan.finish: "Scanner {scanner} Found {size} Plugins in {folder} Start Build..."
|
||||||
ms.plugin.manager.initialize.error: "§6Plugin §b{name} §6initialize error §4{ex}"
|
ms.plugin.manager.initialize.error: "§6Plugin §b{name} §6initialize error §4{ex}"
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ ms.core.package.initialize: "初始化 MiaoScript 扩展 {scope}/core {scope}/{t
|
|||||||
ms.core.package.completed: "MiaoScript 扩展 {scope}/core {scope}/{type} {scope}/plugin 加载完成 耗时({time}s)"
|
ms.core.package.completed: "MiaoScript 扩展 {scope}/core {scope}/{type} {scope}/plugin 加载完成 耗时({time}s)"
|
||||||
ms.core.plugin.initialize: "MiaoScript 开始引导插件系统. 请稍候..."
|
ms.core.plugin.initialize: "MiaoScript 开始引导插件系统. 请稍候..."
|
||||||
ms.core.plugin.completed: "MiaoScript 插件加载完毕 耗时({time}s)!"
|
ms.core.plugin.completed: "MiaoScript 插件加载完毕 耗时({time}s)!"
|
||||||
ms.core.engine.completed: "MiaoScript 脚本引擎 {version} 加载完毕... 耗时({time}s)!"
|
ms.core.engine.completed: "MiaoScript 框架 {loader} 引擎 {version} 加载完毕... 耗时({time}s)!"
|
||||||
ms.core.engine.disable: "MiaoScript 关闭脚本引擎 请稍候..."
|
ms.core.engine.disable: "MiaoScript 关闭脚本引擎 请稍候..."
|
||||||
ms.core.engine.disable.finish: "MiaoScript 脚本引擎 {version} 关闭完成... 耗时({time}s)!"
|
ms.core.engine.disable.finish: "MiaoScript 框架 {loader} 引擎 {version} 关闭完成... 耗时({time}s)!"
|
||||||
ms.core.engine.disable.abnormal: "引擎异常启动或初始化未完成 跳过关闭流程..."
|
ms.core.engine.disable.abnormal: "引擎异常启动或初始化未完成 跳过关闭流程..."
|
||||||
|
|
||||||
ms.api.event.resource.not.found: "无法映射事件 未找到资源文件 {resource}!"
|
ms.api.event.resource.not.found: "无法映射事件 未找到资源文件 {resource}!"
|
||||||
@@ -22,18 +22,22 @@ ms.api.event.not.found: "§6插件 §b{name} §6注册事件 §c{event} §6失
|
|||||||
ms.api.event.execute.slow: "§c注意! §6插件 §b{name} §6处理 §d{event} §6事件 §c耗时 §4{cost}ms !"
|
ms.api.event.execute.slow: "§c注意! §6插件 §b{name} §6处理 §d{event} §6事件 §c耗时 §4{cost}ms !"
|
||||||
ms.api.event.execute.error: "§6插件 §b{name} §6处理 §d{event} §6事件时发生异常 §4{ex}"
|
ms.api.event.execute.error: "§6插件 §b{name} §6处理 §d{event} §6事件时发生异常 §4{ex}"
|
||||||
ms.api.event.listen.plugin.name.empty: "插件名称为空 请检查传入参数!"
|
ms.api.event.listen.plugin.name.empty: "插件名称为空 请检查传入参数!"
|
||||||
ms.api.event.register: "[{name}] 注册事件 {event} => 执行器 {exec}"
|
ms.api.event.register: "[{name}] 注册事件 {event} => 执行器 {exec} 优先级 {priority} 忽略取消 {ignore}"
|
||||||
ms.api.event.unregister: "[{name}] 注销事件 {event} => 执行器 {exec}"
|
ms.api.event.unregister: "[{name}] 注销事件 {event} => 执行器 {exec}"
|
||||||
|
|
||||||
ms.api.command.register.input.error: "CommandExec 必须为一个函数... 输入: {exec}"
|
ms.api.command.register.input.error: "CommandExec 必须为一个函数... 输入: {exec}"
|
||||||
ms.api.command.register: "[{plugin}] 注册命令 {name}({cmd})..."
|
ms.api.command.register: "[{plugin}] 注册命令 {name}({cmd})..."
|
||||||
ms.api.command.unregister: "[{plugin}] 注销命令 {name}..."
|
ms.api.command.unregister: "[{plugin}] 注销命令 {name}..."
|
||||||
|
ms.api.command.execute.slow: "§c注意! §6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6命令 §c耗时 §4{cost}ms !"
|
||||||
ms.api.command.execute.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6命令时发生异常 §4{ex}"
|
ms.api.command.execute.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6命令时发生异常 §4{ex}"
|
||||||
|
ms.api.command.tab.completer.slow: "§c注意! §6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全 §c耗时 §4{cost}ms !"
|
||||||
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
||||||
|
|
||||||
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
||||||
ms.plugin.event.map: "总计 {count} 个 {type} 事件 映射完成..."
|
ms.plugin.event.map: "映射 {type} 事件 成功 总计 {count} 个 {type} 事件..."
|
||||||
|
ms.plugin.event.map.error: "映射 {type} 事件 异常 将无法使用事件简称. Error: {error}"
|
||||||
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
||||||
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始构建..."
|
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始编译..."
|
||||||
ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}"
|
ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}"
|
||||||
ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}"
|
ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}"
|
||||||
ms.plugin.manager.stage.exec: "[{plugin}] 执行 {stage} 阶段函数 {name} 匹配类型 {servers}..."
|
ms.plugin.manager.stage.exec: "[{plugin}] 执行 {stage} 阶段函数 {name} 匹配类型 {servers}..."
|
||||||
@@ -41,7 +45,7 @@ ms.plugin.manager.stage.exec.error: "§6插件 §b{plugin} §6执行 §d{executo
|
|||||||
ms.plugin.manager.stage.load: "加载"
|
ms.plugin.manager.stage.load: "加载"
|
||||||
ms.plugin.manager.stage.enable: "启用"
|
ms.plugin.manager.stage.enable: "启用"
|
||||||
ms.plugin.manager.stage.disable: "关闭"
|
ms.plugin.manager.stage.disable: "关闭"
|
||||||
ms.plugin.manager.build: "插件 {name}({version}) 构建完成 来源: {file}({scanner}) 引导: {loader} 构建耗时: {cost}s."
|
ms.plugin.manager.build: "插件 {name}({version}) 编译完成 来源: {file}({scanner}) 引导: {loader} 编译耗时: {cost}s."
|
||||||
ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4错误: §c{error}"
|
ms.plugin.manager.build.error: "§6从文件 §b{file} §6加载插件失败 §4错误: §c{error}"
|
||||||
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
|
ms.plugin.manager.build.update: "自动更新插件 {name} ..."
|
||||||
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
|
ms.plugin.manager.build.not.extends: "§4发现错误的插件 §b{source} §4未继承接口 interfaces.Plugin, 将不会被载入到服务器!"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/i18n",
|
"name": "@ccms/i18n",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript i18n package",
|
"description": "MiaoScript i18n package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/keyvalue",
|
"name": "@ccms/keyvalue",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript keyvalue package",
|
"description": "MiaoScript keyvalue package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,18 +19,18 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"@javatypes/amqp-client": "^0.0.3",
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
"@javatypes/spring-amqp": "^0.0.3",
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
"@javatypes/spring-rabbit": "^0.0.3",
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75"
|
"gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/molang",
|
"name": "@ccms/molang",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "A fast parser for Minecraft's MoLang",
|
"description": "A fast parser for Minecraft's MoLang",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@@ -21,9 +21,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.17",
|
"@types/node": "^18.13.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nashorn",
|
"name": "@ccms/nashorn",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript nashorn package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,34 @@ declare global {
|
|||||||
scope: string
|
scope: string
|
||||||
logger: any
|
logger: any
|
||||||
debug: boolean
|
debug: boolean
|
||||||
level: string
|
/**
|
||||||
|
* 引擎日志等级
|
||||||
|
*/
|
||||||
|
ScriptEngineLoggerLevel: string
|
||||||
|
/**
|
||||||
|
* 引擎配置
|
||||||
|
*/
|
||||||
|
ScriptEngineConfig: any
|
||||||
|
/**
|
||||||
|
* 引擎版本
|
||||||
|
*/
|
||||||
ScriptEngineVersion: string
|
ScriptEngineVersion: string
|
||||||
|
/**
|
||||||
|
* 引擎渠道
|
||||||
|
*/
|
||||||
|
ScriptEngineChannel: string
|
||||||
|
/**
|
||||||
|
* 慢执行检测时间
|
||||||
|
*/
|
||||||
|
ScriptSlowExecuteTime: number
|
||||||
ScriptEngineStartTime: number
|
ScriptEngineStartTime: number
|
||||||
|
/**
|
||||||
|
* 设置全局对象
|
||||||
|
* @param key 对象名称
|
||||||
|
* @param value 对象值
|
||||||
|
* @param config 对象属性
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
||||||
noop: () => void
|
noop: () => void
|
||||||
console: Console
|
console: Console
|
||||||
@@ -65,10 +90,12 @@ declare global {
|
|||||||
const ScriptEngineContextHolder: any
|
const ScriptEngineContextHolder: any
|
||||||
function engineLoad(str: string | { script: string, name: string }): any
|
function engineLoad(str: string | { script: string, name: string }): any
|
||||||
interface Core {
|
interface Core {
|
||||||
|
version: string
|
||||||
getClass(name: String): any
|
getClass(name: String): any
|
||||||
getProxyClass(): any
|
getProxyClass(): any
|
||||||
getJavaScriptTaskClass(): any
|
getJavaScriptTaskClass(): any
|
||||||
getInstance(): any
|
getInstance(): any
|
||||||
|
loadMavenDepend(groupId: string, artifactId: string, version: string): [any, any]
|
||||||
read(path: string): string
|
read(path: string): string
|
||||||
save(path: string, content: string): void
|
save(path: string, content: string): void
|
||||||
delete(path: string): void
|
delete(path: string): void
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nodejs",
|
"name": "@ccms/nodejs",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript nodejs package",
|
"description": "MiaoScript nodejs package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var Throwable = Java.type('java.lang.Throwable')
|
||||||
var R = typeof Reflect === 'object' ? Reflect : null
|
var R = typeof Reflect === 'object' ? Reflect : null
|
||||||
var ReflectApply = R && typeof R.apply === 'function'
|
var ReflectApply = R && typeof R.apply === 'function'
|
||||||
? R.apply
|
? R.apply
|
||||||
@@ -136,13 +137,19 @@ EventEmitter.prototype.emit = function emit(type) {
|
|||||||
var er;
|
var er;
|
||||||
if (args.length > 0)
|
if (args.length > 0)
|
||||||
er = args[0];
|
er = args[0];
|
||||||
if (er instanceof Error) {
|
if (er instanceof Error || er instanceof Throwable) {
|
||||||
// Note: The comments on the `throw` lines are intentional, they show
|
// Note: The comments on the `throw` lines are intentional, they show
|
||||||
// up in Node's output if this results in an unhandled exception.
|
// up in Node's output if this results in an unhandled exception.
|
||||||
throw er; // Unhandled 'error' event
|
throw er; // Unhandled 'error' event
|
||||||
}
|
}
|
||||||
|
if (er.error instanceof Error || er.error instanceof Throwable) {
|
||||||
|
throw er.error; // Unhandled 'error' event
|
||||||
|
}
|
||||||
|
if (er.cause instanceof Error || er.error instanceof Throwable) {
|
||||||
|
throw er.error; // Unhandled 'error' event
|
||||||
|
}
|
||||||
// At least give some kind of context to the user
|
// At least give some kind of context to the user
|
||||||
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
|
var err = new Error('Unhandled error.' + (er ? ' (' + (er.message || er.error || er.cause || er) + ')' : ''));
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
err.context = er;
|
err.context = er;
|
||||||
throw err; // Unhandled 'error' event
|
throw err; // Unhandled 'error' event
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const Path = Java.type("java.nio.file.Path");
|
|||||||
const JavaString = Java.type("java.lang.String");
|
const JavaString = Java.type("java.lang.String");
|
||||||
const File = Java.type("java.io.File");
|
const File = Java.type("java.io.File");
|
||||||
const Files = Java.type("java.nio.file.Files");
|
const Files = Java.type("java.nio.file.Files");
|
||||||
|
const Paths = Java.type("java.nio.file.Paths");
|
||||||
const Collector = Java.type("java.util.stream.Collector")
|
const Collector = Java.type("java.util.stream.Collector")
|
||||||
const separatorChar = File.separatorChar;
|
const separatorChar = File.separatorChar;
|
||||||
const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
|
const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
|
||||||
@@ -37,7 +38,7 @@ function javaFile(...opts: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renameSync(oldPath: PathLike, newPath: PathLike): void {
|
export function renameSync(oldPath: PathLike, newPath: PathLike): void {
|
||||||
|
Files.move(Paths.get(oldPath), Paths.get(oldPath), StandardCopyOption['ATOMIC_MOVE'])
|
||||||
}
|
}
|
||||||
export function truncateSync() {
|
export function truncateSync() {
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nukkit",
|
"name": "@ccms/nukkit",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript nukkit package",
|
"description": "MiaoScript nukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/nukkit-api": "^0.0.3",
|
"@javatypes/nukkit-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0"
|
"@ccms/container": "^0.28.0-beta.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/plugin",
|
"name": "@ccms/plugin",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript plugin package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -19,17 +19,19 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.18.0",
|
"@ccms/api": "^0.28.0-beta.2",
|
||||||
"@ccms/common": "^0.18.0",
|
"@ccms/common": "^0.28.0-beta.2",
|
||||||
"@ccms/container": "^0.18.0",
|
"@ccms/container": "^0.28.0-beta.2",
|
||||||
"@ccms/i18n": "^0.18.0",
|
"@ccms/i18n": "^0.28.0-beta.2",
|
||||||
"js-yaml": "^4.1.0",
|
"@ccms/verify": "^0.25.1",
|
||||||
"yaml": "^1.10.2"
|
"crypto-js": "^4.1.1",
|
||||||
|
"js-yaml": "^4.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,52 +15,90 @@ export class PluginCommandManager {
|
|||||||
process.on('plugin.after.disable', this.unregistryCommand.bind(this))
|
process.on('plugin.after.disable', this.unregistryCommand.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
private registryCommand(pluginInstance: plugin.Plugin) {
|
public registryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
|
||||||
let cmds = getPluginCommandMetadata(pluginInstance)
|
let cmds = getPluginCommandMetadata(executor)
|
||||||
let tabs = getPluginTabCompleterMetadata(pluginInstance)
|
let tabs = getPluginTabCompleterMetadata(executor)
|
||||||
for (const cmd of cmds) {
|
for (const cmd of cmds) {
|
||||||
if (!this.ServerChecker.check(cmd.servers)) {
|
if (!this.ServerChecker.check(cmd.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (let command of [cmd.name, ...cmd.alias]) {
|
for (let command of [cmd.name, ...cmd.alias]) {
|
||||||
let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, cmd, tabs.get(command))
|
let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, executor, cmd, tabs.get(command))
|
||||||
this.CommandManager.on(pluginInstance, command, {
|
this.CommandManager.on(pluginInstance, command, {
|
||||||
cmd: cmdExecutor.bind(pluginInstance),
|
cmd: cmdExecutor.bind(executor),
|
||||||
tab: cmdCompleter?.bind(pluginInstance)
|
tab: cmdCompleter?.bind(executor)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unregistryCommand(pluginInstance: plugin.Plugin) {
|
public unregistryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
|
||||||
let cmds = getPluginCommandMetadata(pluginInstance)
|
let cmds = getPluginCommandMetadata(executor)
|
||||||
cmds.forEach(cmd => this.CommandManager.off(pluginInstance, cmd.name))
|
for (const cmd of cmds) {
|
||||||
|
if (!this.ServerChecker.check(cmd.servers)) {
|
||||||
|
console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for (let command of [cmd.name, ...cmd.alias]) {
|
||||||
|
this.CommandManager.off(executor, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateAutoMainCommand(pluginInstance: plugin.Plugin, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
|
private generateAutoMainCommand(pluginInstance: plugin.Plugin, executor: any, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
|
||||||
let cmdExecutor = pluginInstance[cmd.executor]
|
let cmdExecutor = executor[cmd.executor]
|
||||||
let cmdCompleter = tab ? pluginInstance[tab.executor] : undefined
|
let cmdCompleter = tab ? executor[tab.executor] : undefined
|
||||||
let cmdSubCache = Object.keys(pluginInstance.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
|
let cmdSubCache = Object.keys(executor.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
|
||||||
if (cmd.autoMain) {
|
if (cmd.autoMain) {
|
||||||
cmdExecutor = (sender: any, command: string, args: string[]) => {
|
cmdExecutor = (sender: any, command: string, args: string[]) => {
|
||||||
let subcommand = args[0]
|
let subcommand = args[0]
|
||||||
let cmdKey = 'cmd' + subcommand
|
let cmdKey = 'cmd' + subcommand
|
||||||
if (pluginInstance[cmdKey]) {
|
if (!cmdSubCache.includes(subcommand)) {
|
||||||
args.shift()
|
if (!executor[cmd.executor].apply(executor, [sender, command, args])) {
|
||||||
return pluginInstance[cmdKey].apply(pluginInstance, [sender, ...args])
|
subcommand && pluginInstance.logger.sender(sender, `§4未知的命令: §b/${command} §c${subcommand}`)
|
||||||
} else if (pluginInstance['cmdmain']) {
|
pluginInstance.logger.sender(
|
||||||
return pluginInstance['cmdmain'].apply(pluginInstance, [sender, ...args])
|
sender,
|
||||||
|
executor['cmdhelp'] ?
|
||||||
|
`§6请执行 §b/${command} §ahelp §6查看帮助!` :
|
||||||
|
[
|
||||||
|
`§6插件: §b${pluginInstance.description.name}`,
|
||||||
|
`§6版本: §a${pluginInstance.description.version}`
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
pluginInstance.logger.sender(sender, '§4未知的子命令: §c' + subcommand)
|
let subcommandexec = executor[cmdKey]
|
||||||
pluginInstance['cmdhelp'] && pluginInstance.logger.sender(sender, `§6请执行 §b/${command} §ahelp §6查看帮助!`)
|
let permission: string
|
||||||
|
if (cmd.permission && sender.hasPermission) {
|
||||||
|
if (typeof cmd.permission == "string") {
|
||||||
|
permission = cmd.permission as string
|
||||||
|
} else {
|
||||||
|
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}.${subcommand || 'main'}`
|
||||||
|
}
|
||||||
|
if (!sender.hasPermission(permission)) {
|
||||||
|
return pluginInstance.logger.sender(sender, `§c你需要 §4${permission} §c权限 才可执行此命令.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args.shift()
|
||||||
|
return subcommandexec.apply(executor, [sender, ...args])
|
||||||
}
|
}
|
||||||
let originCompleter = cmdCompleter
|
let originCompleter = cmdCompleter
|
||||||
cmdCompleter = (sender: any, command: string, args: string[]) => {
|
cmdCompleter = (sender: any, command: string, args: string[]) => {
|
||||||
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(pluginInstance, [sender, command, args]) || [])
|
let permission: string
|
||||||
|
if (cmd.permission && sender.hasPermission) {
|
||||||
|
if (typeof cmd.permission == "string") {
|
||||||
|
permission = cmd.permission as string
|
||||||
|
} else {
|
||||||
|
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}`
|
||||||
|
}
|
||||||
|
if (!sender.hasPermission(permission)) { return [] }
|
||||||
|
}
|
||||||
|
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(executor, [sender, command, args]) || [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cmdCompleter) { console.warn(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
if (!cmdCompleter) { console.debug(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
||||||
return [cmdExecutor, cmdCompleter]
|
return [cmdExecutor, cmdCompleter]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,35 @@
|
|||||||
import * as yaml from 'js-yaml'
|
|
||||||
import * as fs from '@ccms/common/dist/fs'
|
|
||||||
import { plugin } from '@ccms/api'
|
import { plugin } from '@ccms/api'
|
||||||
import { provideSingleton } from '@ccms/container'
|
import { Autowired, Container, ContainerInstance, postConstruct, provideSingleton } from '@ccms/container'
|
||||||
|
|
||||||
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { getPluginConfigMetadata } from './utils'
|
import { getPluginConfigMetadata } from './utils'
|
||||||
|
|
||||||
export interface PluginConfigLoader {
|
import { PluginConfigLoader } from './config/interfaces'
|
||||||
load(content: string): any
|
import './config/loader'
|
||||||
dump(variable: any): string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class YamlPluginConfig implements PluginConfigLoader {
|
|
||||||
load(content: string) {
|
|
||||||
return yaml.load(content)
|
|
||||||
}
|
|
||||||
dump(variable: any): string {
|
|
||||||
return yaml.dump(variable, { skipInvalid: true, lineWidth: 120 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class JsonPluginConfig implements PluginConfigLoader {
|
|
||||||
load(content: string) {
|
|
||||||
return JSON.parse(content)
|
|
||||||
}
|
|
||||||
dump(variable: any): string {
|
|
||||||
return JSON.stringify(variable, undefined, 4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PluginConfig {
|
|
||||||
/**
|
|
||||||
* Save Config to File
|
|
||||||
*/
|
|
||||||
readonly save?: () => void
|
|
||||||
/**
|
|
||||||
* Reload Config from File
|
|
||||||
*/
|
|
||||||
readonly reload?: () => void
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
@provideSingleton(PluginConfigManager)
|
@provideSingleton(PluginConfigManager)
|
||||||
export class PluginConfigManager {
|
export class PluginConfigManager {
|
||||||
|
@Autowired(ContainerInstance)
|
||||||
|
private container: Container
|
||||||
|
|
||||||
private configLoaderMap = new Map<string, PluginConfigLoader>()
|
private configLoaderMap = new Map<string, PluginConfigLoader>()
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.configLoaderMap.set("json", new JsonPluginConfig())
|
|
||||||
let yaml = new YamlPluginConfig()
|
|
||||||
this.configLoaderMap.set("yml", yaml)
|
|
||||||
this.configLoaderMap.set("yaml", yaml)
|
|
||||||
process.on('plugin.before.load', this.loadConfig.bind(this))
|
process.on('plugin.before.load', this.loadConfig.bind(this))
|
||||||
process.on('plugin.after.disable', this.saveConfig.bind(this))
|
process.on('plugin.after.disable', this.saveConfig.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@postConstruct()
|
||||||
|
initialize() {
|
||||||
|
let configLoader = this.container.getAll<PluginConfigLoader>(PluginConfigLoader)
|
||||||
|
configLoader.forEach((scanner) => {
|
||||||
|
console.debug(`loading config loader ${scanner.type}...`)
|
||||||
|
this.configLoaderMap.set(scanner.type, scanner)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
getConfigLoader(format: string) {
|
getConfigLoader(format: string) {
|
||||||
if (!this.configLoaderMap.has(format)) { throw new Error(`Unsupport config format ${format} !`) }
|
if (!this.configLoaderMap.has(format)) { throw new Error(`Unsupport config format ${format} !`) }
|
||||||
return this.configLoaderMap.get(format)
|
return this.configLoaderMap.get(format)
|
||||||
@@ -73,50 +49,65 @@ export class PluginConfigManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private defienConfigProp(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata, value: any) {
|
createConfig(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata, value: any) {
|
||||||
Object.defineProperties(value, {
|
Object.defineProperties(value, {
|
||||||
'save': { value: () => this.saveConfig0(plugin, metadata) },
|
'save': { value: () => this.saveConfig0(plugin, metadata) },
|
||||||
'reload': { value: () => this.loadConfig0(plugin, metadata) }
|
'reload': { value: () => this.loadConfig0(plugin, metadata) }
|
||||||
})
|
})
|
||||||
Object.defineProperty(plugin, metadata.variable, { value })
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
private defienConfigProp(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata, value: any) {
|
||||||
|
Object.defineProperty(plugin, metadata.variable, {
|
||||||
|
value: this.createConfig(plugin, metadata, value),
|
||||||
|
configurable: true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
||||||
try {
|
try {
|
||||||
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
||||||
let configValue = defaultValue || {}
|
metadata.file = fs.concat(
|
||||||
if (defaultValue) {
|
fs.file(plugin.description.loadMetadata.file).parent,
|
||||||
metadata.file = fs.concat(fs.file(plugin.description.loadMetadata.file).parent, plugin.description.name, metadata.filename)
|
plugin.description.name,
|
||||||
let configLoader = this.getConfigLoader(metadata.format)
|
metadata.filename
|
||||||
if (!fs.exists(metadata.file)) {
|
)
|
||||||
base.save(metadata.file, configLoader.dump(defaultValue))
|
let configLoader = this.getConfigLoader(metadata.format)
|
||||||
console.i18n("ms.plugin.manager.config.save.default", { plugin: plugin.description.name, name: metadata.name, format: metadata.format })
|
if (!fs.exists(metadata.file) && defaultValue) {
|
||||||
} else {
|
base.save(metadata.file, configLoader.dump(defaultValue))
|
||||||
configValue = configLoader.load(base.read(metadata.file)) || {}
|
console.i18n("ms.plugin.manager.config.save.default", {
|
||||||
if (defaultValue && this.setDefaultValue(configValue, defaultValue)) {
|
plugin: plugin.description.name,
|
||||||
base.save(metadata.file, configLoader.dump(configValue))
|
name: metadata.name,
|
||||||
}
|
format: metadata.format
|
||||||
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file} =>\n${JSON.stringify(configValue, undefined, 4).substr(0, 500)}`)
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let configValue = configLoader.load(base.read(metadata.file)) || {}
|
||||||
|
if (metadata.migrate && defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
||||||
|
base.save(metadata.file, configLoader.dump(configValue))
|
||||||
|
}
|
||||||
|
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file}`)
|
||||||
this.defienConfigProp(plugin, metadata, configValue)
|
this.defienConfigProp(plugin, metadata, configValue)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.i18n("ms.plugin.manager.config.load.error", { plugin: plugin.description.name, name: metadata.name, format: metadata.format, error })
|
console.i18n("ms.plugin.manager.config.load.error", {
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
name: metadata.name,
|
||||||
|
format: metadata.format,
|
||||||
|
error
|
||||||
|
})
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setDefaultValue(configValue, defaultValue) {
|
private setDefaultValue(configValue, defaultValue, deepCopy) {
|
||||||
let needSave = false
|
let needSave = false
|
||||||
for (const key of Object.keys(defaultValue)) {
|
for (const key of Object.keys(defaultValue)) {
|
||||||
// 当配置文件不存在当前属性时才进行赋值
|
// 当配置文件不存在当前属性时才进行赋值
|
||||||
if (!Object.prototype.hasOwnProperty.call(configValue, key) && key != '____deep_copy____') {
|
if (!Object.prototype.hasOwnProperty.call(configValue, key)) {
|
||||||
configValue[key] = defaultValue[key]
|
configValue[key] = defaultValue[key]
|
||||||
needSave = true
|
needSave = true
|
||||||
} else if (Object.prototype.toString.call(configValue[key]) == "[object Object]"
|
} else if (Object.prototype.toString.call(configValue[key]) == "[object Object]" && deepCopy) {
|
||||||
&& Object.prototype.hasOwnProperty.call(defaultValue[key], '____deep_copy____')) {
|
// 对象需要递归检测
|
||||||
// 对象需要递归检测 如果对象内存在 ____deep_copy____ 那就忽略设置
|
needSave ||= this.setDefaultValue(configValue[key], defaultValue[key], deepCopy)
|
||||||
needSave ||= this.setDefaultValue(configValue[key], defaultValue[key])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return needSave
|
return needSave
|
||||||
@@ -127,10 +118,16 @@ export class PluginConfigManager {
|
|||||||
metadata.file = fs.concat(fs.file(plugin.description.loadMetadata.file).parent, plugin.description.name, metadata.filename)
|
metadata.file = fs.concat(fs.file(plugin.description.loadMetadata.file).parent, plugin.description.name, metadata.filename)
|
||||||
let result = this.getConfigLoader(metadata.format).dump(plugin[metadata.variable])
|
let result = this.getConfigLoader(metadata.format).dump(plugin[metadata.variable])
|
||||||
base.save(metadata.file, result)
|
base.save(metadata.file, result)
|
||||||
console.debug(`[${plugin.description.name}] Save Config ${metadata.variable} to file ${metadata.file} =>\n${result.substr(0, 500)}`)
|
console.debug(`[${plugin.description.name}] Save Config ${metadata.variable} to file ${metadata.file} =>
|
||||||
|
${result.substring(0, 500)}`)
|
||||||
return true
|
return true
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.i18n("ms.plugin.manager.config.save.error", { plugin: plugin.description.name, name: metadata.name, format: metadata.format, error })
|
console.i18n("ms.plugin.manager.config.save.error", {
|
||||||
|
plugin: plugin.description.name,
|
||||||
|
name: metadata.name,
|
||||||
|
format: metadata.format,
|
||||||
|
error
|
||||||
|
})
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/plugin/src/config/config.ts
Normal file
3
packages/plugin/src/config/config.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from "./loader"
|
||||||
|
export * from "./interfaces"
|
||||||
|
export * from "./file-config"
|
||||||
65
packages/plugin/src/config/file-config.ts
Normal file
65
packages/plugin/src/config/file-config.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
|
||||||
|
import { PluginConfig, PluginConfigLoader } from './interfaces'
|
||||||
|
|
||||||
|
export class PluginFileConfig implements PluginConfig {
|
||||||
|
private loader: PluginConfigLoader
|
||||||
|
private file: string
|
||||||
|
constructor(loader: PluginConfigLoader, file: string, def = {}) {
|
||||||
|
this.loader = loader
|
||||||
|
this.file = file
|
||||||
|
if (fs.exists(file)) {
|
||||||
|
this.reload()
|
||||||
|
} else {
|
||||||
|
Object.assign(this, def)
|
||||||
|
}
|
||||||
|
this.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
base.save(this.file, this.loader.dump(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
Object.assign(this, this.loader.load(base.read(this.file)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PluginConfigFolder {
|
||||||
|
private loader: PluginConfigLoader
|
||||||
|
private folder: string
|
||||||
|
|
||||||
|
private configCache = new Map<string, PluginFileConfig>()
|
||||||
|
|
||||||
|
constructor(loader: PluginConfigLoader, folder: string) {
|
||||||
|
this.loader = loader
|
||||||
|
this.folder = folder
|
||||||
|
}
|
||||||
|
|
||||||
|
createConfig(path: string, def = {}) {
|
||||||
|
return new PluginFileConfig(this.loader, path, def)
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfig(name: string, def = {}) {
|
||||||
|
let path = fs.concat(this.folder, name)
|
||||||
|
if (!this.configCache.has(path)) {
|
||||||
|
this.configCache.set(path, this.createConfig(path, def))
|
||||||
|
}
|
||||||
|
return this.configCache.get(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.configCache.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.configCache.forEach((config) => config.save())
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
this.configCache.forEach((config) => config.reload())
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/plugin/src/config/interfaces.ts
Normal file
18
packages/plugin/src/config/interfaces.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export const PluginConfigLoader = Symbol.for('PluginConfigLoader')
|
||||||
|
export interface PluginConfigLoader {
|
||||||
|
type: string
|
||||||
|
load(content: string): any
|
||||||
|
dump(variable: any): string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginConfig {
|
||||||
|
/**
|
||||||
|
* Save Config to File
|
||||||
|
*/
|
||||||
|
readonly save?: () => void
|
||||||
|
/**
|
||||||
|
* Reload Config from File
|
||||||
|
*/
|
||||||
|
readonly reload?: () => void
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
2
packages/plugin/src/config/loader/index.ts
Normal file
2
packages/plugin/src/config/loader/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './json-loader'
|
||||||
|
export * from './yaml-loader'
|
||||||
18
packages/plugin/src/config/loader/json-loader.ts
Normal file
18
packages/plugin/src/config/loader/json-loader.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { provideSingletonNamed } from '@ccms/container'
|
||||||
|
|
||||||
|
import { PluginConfigLoader } from '../interfaces'
|
||||||
|
|
||||||
|
const LOADER_TYPE_NAME = 'json'
|
||||||
|
|
||||||
|
@provideSingletonNamed(PluginConfigLoader, LOADER_TYPE_NAME)
|
||||||
|
export class JsonPluginConfig implements PluginConfigLoader {
|
||||||
|
type: string = LOADER_TYPE_NAME
|
||||||
|
|
||||||
|
load(content: string) {
|
||||||
|
return JSON.parse(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(variable: any): string {
|
||||||
|
return JSON.stringify(variable, undefined, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
19
packages/plugin/src/config/loader/yaml-loader.ts
Normal file
19
packages/plugin/src/config/loader/yaml-loader.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import * as yaml from 'js-yaml'
|
||||||
|
import { provideSingletonNamed } from '@ccms/container'
|
||||||
|
|
||||||
|
import { PluginConfigLoader } from '../interfaces'
|
||||||
|
|
||||||
|
const LOADER_TYPE_NAME = 'yml'
|
||||||
|
|
||||||
|
@provideSingletonNamed(PluginConfigLoader, LOADER_TYPE_NAME)
|
||||||
|
export class YamlPluginConfig implements PluginConfigLoader {
|
||||||
|
type: string = LOADER_TYPE_NAME
|
||||||
|
|
||||||
|
load(content: string) {
|
||||||
|
return yaml.load(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(variable: any): string {
|
||||||
|
return yaml.dump(variable, { skipInvalid: true, lineWidth: 120 })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ export const METADATA_KEY = {
|
|||||||
tab: Symbol.for("@ccms/plugin:tab"),
|
tab: Symbol.for("@ccms/plugin:tab"),
|
||||||
listener: Symbol.for("@ccms/plugin:listener"),
|
listener: Symbol.for("@ccms/plugin:listener"),
|
||||||
config: Symbol.for("@ccms/plugin:config"),
|
config: Symbol.for("@ccms/plugin:config"),
|
||||||
|
playerdata: Symbol.for("@ccms/plugin:playerdata"),
|
||||||
stage: {
|
stage: {
|
||||||
load: Symbol.for("@ccms/plugin:stage:load"),
|
load: Symbol.for("@ccms/plugin:stage:load"),
|
||||||
enable: Symbol.for("@ccms/plugin:stage:enable"),
|
enable: Symbol.for("@ccms/plugin:stage:enable"),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { plugin as pluginApi } from "@ccms/api"
|
|||||||
import { injectable, decorate } from "@ccms/container"
|
import { injectable, decorate } from "@ccms/container"
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { METADATA_KEY } from './constants'
|
import { METADATA_KEY } from './constants'
|
||||||
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources } from './utils'
|
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata, getPluginSources, getPluginPlayerDataMetadata } from './utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MiaoScript plugin
|
* MiaoScript plugin
|
||||||
@@ -76,6 +76,7 @@ export function config(metadata: interfaces.ConfigMetadata = {}) {
|
|||||||
metadata.variable = key
|
metadata.variable = key
|
||||||
metadata.version = metadata.version ?? 1
|
metadata.version = metadata.version ?? 1
|
||||||
metadata.format = metadata.format ?? 'yml'
|
metadata.format = metadata.format ?? 'yml'
|
||||||
|
metadata.migrate = metadata.migrate ?? true
|
||||||
metadata.autosave = metadata.autosave ?? false
|
metadata.autosave = metadata.autosave ?? false
|
||||||
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
||||||
let previousMetadata = getPluginConfigMetadata(target)
|
let previousMetadata = getPluginConfigMetadata(target)
|
||||||
@@ -84,6 +85,21 @@ export function config(metadata: interfaces.ConfigMetadata = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function playerdata(metadata: interfaces.PlayerDataMetadata = {}) {
|
||||||
|
return function (target: any, key: string) {
|
||||||
|
metadata.name = metadata.name || key
|
||||||
|
metadata.variable = key
|
||||||
|
metadata.version = metadata.version ?? 1
|
||||||
|
metadata.format = metadata.format ?? 'yml'
|
||||||
|
metadata.autosave = metadata.autosave ?? false
|
||||||
|
metadata.filename = metadata.filename ?? "username"
|
||||||
|
metadata.dir = metadata.dir ?? "playerdata"
|
||||||
|
let previousMetadata = getPluginPlayerDataMetadata(target)
|
||||||
|
previousMetadata.set(metadata.name, metadata)
|
||||||
|
Reflect.defineMetadata(METADATA_KEY.playerdata, previousMetadata, target.constructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function stage(stage: string) {
|
function stage(stage: string) {
|
||||||
return (metadata: interfaces.ExecMetadata = {}) => {
|
return (metadata: interfaces.ExecMetadata = {}) => {
|
||||||
return function (target: any, key: string, value: any) {
|
return function (target: any, key: string, value: any) {
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ import { getPluginListenerMetadata } from './utils'
|
|||||||
@provideSingleton(PluginEventManager)
|
@provideSingleton(PluginEventManager)
|
||||||
export class PluginEventManager {
|
export class PluginEventManager {
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private EventManager: event.Event
|
private eventManager: event.Event
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private ServerChecker: server.ServerChecker
|
private serverChecker: server.ServerChecker
|
||||||
|
@Autowired()
|
||||||
|
private nativePluginChecker: server.NativePluginChecker
|
||||||
|
|
||||||
|
private listenerMap = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
process.on('plugin.before.enable', this.registryListener.bind(this))
|
process.on('plugin.before.enable', this.registryListener.bind(this))
|
||||||
@@ -15,26 +19,44 @@ export class PluginEventManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapEventName() {
|
mapEventName() {
|
||||||
return this.EventManager.mapEventName().toFixed(0)
|
return this.eventManager.mapEventName().toFixed(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private registryListener(pluginInstance: plugin.Plugin) {
|
public registryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
|
||||||
let events = getPluginListenerMetadata(pluginInstance)
|
let events = getPluginListenerMetadata(listener)
|
||||||
|
let execes = []
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
// ignore space listener
|
// ignore space listener
|
||||||
if (!this.ServerChecker.check(event.servers)) {
|
if (!this.serverChecker.check(event.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible event ${event.name} server(${event.servers}) ignore.`)
|
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible server(${event.servers}) ignore event ${event.name}.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// ignore space listener
|
||||||
|
if (!this.nativePluginChecker.check(event.plugins)) {
|
||||||
|
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} require native plugins(${event.plugins}) ignore event ${event.name}.`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// here must bind this to pluginInstance
|
// here must bind this to pluginInstance
|
||||||
let exec = event.target[event.executor]
|
let exec = event.target[event.executor]
|
||||||
let execBinded = exec.bind(pluginInstance)
|
let execBinded = exec.bind(listener)
|
||||||
execBinded.executor = event.executor
|
execBinded.executor = event.executor
|
||||||
exec.off = this.EventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
exec.off = this.eventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
||||||
|
execes.push(exec)
|
||||||
}
|
}
|
||||||
|
let off = () => {
|
||||||
|
if (off['offed']) return
|
||||||
|
off['offed'] = true
|
||||||
|
execes.forEach((exec: { off: () => void }) => exec.off())
|
||||||
|
}
|
||||||
|
listener.off = off
|
||||||
}
|
}
|
||||||
|
|
||||||
private unregistryListener(pluginInstance: plugin.Plugin) {
|
private unregistryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
|
||||||
this.EventManager.disable(pluginInstance)
|
if (listener && listener.off) {
|
||||||
|
listener.off()
|
||||||
|
}
|
||||||
|
if (pluginInstance) {
|
||||||
|
this.eventManager.disable(pluginInstance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
import './scanner/file-scanner'
|
import '@ccms/verify'
|
||||||
|
import './scanner/js-scanner'
|
||||||
|
|
||||||
import './loader/ioc-loader'
|
import './loader/ioc-loader'
|
||||||
import './loader/basic-loader'
|
import './loader/basic-loader'
|
||||||
|
|
||||||
export * from './config'
|
export * from './config'
|
||||||
|
export * from './config/config'
|
||||||
export * from './manager'
|
export * from './manager'
|
||||||
export * from './decorators'
|
export * from './decorators'
|
||||||
export * from './interfaces'
|
export * from './interfaces'
|
||||||
|
|
||||||
|
export * from './event'
|
||||||
|
export * from './command'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
plugin as JSPlugin,
|
plugin as JSPlugin,
|
||||||
cmd as Cmd,
|
cmd as Cmd,
|
||||||
tab as Tab,
|
tab as Tab,
|
||||||
listener as Listener,
|
listener as Listener,
|
||||||
config as Config
|
config as Config,
|
||||||
|
playerdata as PlayerData
|
||||||
} from './decorators'
|
} from './decorators'
|
||||||
|
|
||||||
|
import '@ccms/database'
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export namespace interfaces {
|
|||||||
@injectable()
|
@injectable()
|
||||||
export abstract class Plugin implements plugin.Plugin {
|
export abstract class Plugin implements plugin.Plugin {
|
||||||
public description: plugin.PluginMetadata
|
public description: plugin.PluginMetadata
|
||||||
public logger: Console
|
public logger: MiaoScriptConsole
|
||||||
@inject(server.Console)
|
@inject(server.Console)
|
||||||
private Console: MiaoScriptConsole
|
private Console: MiaoScriptConsole
|
||||||
|
|
||||||
@@ -28,6 +28,11 @@ export namespace interfaces {
|
|||||||
return dataFolder.getAbsolutePath()
|
return dataFolder.getAbsolutePath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public registryCommand(executor: any) { }
|
||||||
|
public unregistryCommand(executor: any) { }
|
||||||
|
public registryListener(listener: any) { }
|
||||||
|
public unregistryListener(listener: any) { }
|
||||||
|
|
||||||
public load() { }
|
public load() { }
|
||||||
public enable() { }
|
public enable() { }
|
||||||
public disable() { }
|
public disable() { }
|
||||||
@@ -59,6 +64,10 @@ export namespace interfaces {
|
|||||||
* 自动化主命令
|
* 自动化主命令
|
||||||
*/
|
*/
|
||||||
autoMain?: boolean
|
autoMain?: boolean
|
||||||
|
/**
|
||||||
|
* 子命令权限效验
|
||||||
|
*/
|
||||||
|
permission?: boolean | string
|
||||||
}
|
}
|
||||||
export interface ListenerMetadata extends ExecMetadata {
|
export interface ListenerMetadata extends ExecMetadata {
|
||||||
/**
|
/**
|
||||||
@@ -69,8 +78,46 @@ export namespace interfaces {
|
|||||||
* 是否忽略已取消的事件
|
* 是否忽略已取消的事件
|
||||||
*/
|
*/
|
||||||
ignoreCancel?: boolean
|
ignoreCancel?: boolean
|
||||||
|
/**
|
||||||
|
* 依赖插件 没有就不加载
|
||||||
|
*/
|
||||||
|
plugins?: string[]
|
||||||
}
|
}
|
||||||
export interface ConfigMetadata extends plugin.BaseMetadata {
|
export interface ConfigMetadata extends plugin.BaseMetadata {
|
||||||
|
/**
|
||||||
|
* 配置文件版本号
|
||||||
|
*/
|
||||||
|
version?: number
|
||||||
|
/**
|
||||||
|
* 默认配置
|
||||||
|
*/
|
||||||
|
default?: any
|
||||||
|
/**
|
||||||
|
* 实体变量名称
|
||||||
|
*/
|
||||||
|
variable?: string
|
||||||
|
/**
|
||||||
|
* 配置文件格式 默认 yml
|
||||||
|
*/
|
||||||
|
format?: string
|
||||||
|
/**
|
||||||
|
* 是否合并默认配置
|
||||||
|
*/
|
||||||
|
migrate?: boolean
|
||||||
|
/**
|
||||||
|
* 自动保存 默认为 false
|
||||||
|
*/
|
||||||
|
autosave?: boolean
|
||||||
|
/**
|
||||||
|
* 配置文件名称
|
||||||
|
*/
|
||||||
|
filename?: string
|
||||||
|
/**
|
||||||
|
* 配置文件全路径
|
||||||
|
*/
|
||||||
|
file?: any
|
||||||
|
}
|
||||||
|
export interface PlayerDataMetadata extends plugin.BaseMetadata {
|
||||||
/**
|
/**
|
||||||
* 配置文件版本号
|
* 配置文件版本号
|
||||||
*/
|
*/
|
||||||
@@ -92,12 +139,16 @@ export namespace interfaces {
|
|||||||
*/
|
*/
|
||||||
autosave?: boolean
|
autosave?: boolean
|
||||||
/**
|
/**
|
||||||
* 配置文件名称
|
* 配置文件名称 默认玩家名称
|
||||||
*/
|
*/
|
||||||
filename?: string
|
filename?: "username" | "uuid"
|
||||||
/**
|
/**
|
||||||
* 配置文件全路径
|
* 配置文件目录 默认 playerdata
|
||||||
*/
|
*/
|
||||||
file?: any
|
dir?: string
|
||||||
|
/**
|
||||||
|
* 配置文件子目录 默认为空
|
||||||
|
*/
|
||||||
|
subdir?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ export class IocLoader implements plugin.PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bindPlugin(metadata: plugin.PluginMetadata) {
|
private bindPlugin(metadata: plugin.PluginMetadata) {
|
||||||
try {
|
if (this.container.isBoundNamed(plugin.Plugin, metadata.name)) {
|
||||||
let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
|
let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
|
||||||
if (pluginInstance.description.source + '' !== metadata.source + '') {
|
if (pluginInstance.description.source + '' !== metadata.source + '') {
|
||||||
console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
|
console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
|
||||||
}
|
}
|
||||||
this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
this.container.rebind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
||||||
} catch {
|
} else {
|
||||||
this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
this.container.bind(plugin.Plugin).to(metadata.target).inSingletonScope().whenTargetNamed(metadata.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ import i18n from '@ccms/i18n'
|
|||||||
import { plugin, server } from '@ccms/api'
|
import { plugin, server } from '@ccms/api'
|
||||||
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
||||||
|
|
||||||
import './config'
|
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { PluginTaskManager } from './task'
|
import { PluginTaskManager } from './task'
|
||||||
import { PluginEventManager } from './event'
|
import { PluginEventManager } from './event'
|
||||||
import { PluginCommandManager } from './command'
|
|
||||||
import { PluginConfigManager } from './config'
|
import { PluginConfigManager } from './config'
|
||||||
|
import { PluginCommandManager } from './command'
|
||||||
|
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
|
||||||
@@ -64,8 +63,13 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
initialize() {
|
initialize() {
|
||||||
if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
|
if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
|
||||||
if (this.initialized !== true) {
|
if (this.initialized !== true) {
|
||||||
|
process.emit('plugin.manager.before.initialize', this)
|
||||||
console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
|
console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
|
||||||
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
try {
|
||||||
|
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
||||||
|
} catch (error) {
|
||||||
|
console.i18n('ms.plugin.event.map.error', { type: this.serverType, error })
|
||||||
|
}
|
||||||
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
||||||
pluginScanner.forEach((scanner) => {
|
pluginScanner.forEach((scanner) => {
|
||||||
console.debug(`loading plugin sacnner ${scanner.type}...`)
|
console.debug(`loading plugin sacnner ${scanner.type}...`)
|
||||||
@@ -77,37 +81,38 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
this.loaderMap.set(loader.type, loader)
|
this.loaderMap.set(loader.type, loader)
|
||||||
})
|
})
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
process.emit('plugin.initialize')
|
process.emit('plugin.manager.after.initialize', this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scan(folder: string): void {
|
scan(folder: string): void {
|
||||||
if (!folder) { throw new Error('plugin scan folder can\'t be empty!') }
|
if (!folder) { throw new Error('plugin scan folder can\'t be empty!') }
|
||||||
this.initialize()
|
this.initialize()
|
||||||
|
process.emit('plugin.manager.before.scan', folder, this)
|
||||||
for (const [, scanner] of this.sacnnerMap) {
|
for (const [, scanner] of this.sacnnerMap) {
|
||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
||||||
let plugins = scanner.scan(folder)
|
let loadMetadatas = scanner.scan(folder)
|
||||||
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: plugins.length })
|
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: loadMetadatas.length })
|
||||||
plugins.forEach(loadMetadata => {
|
for (const loadMetadata of loadMetadatas) {
|
||||||
try {
|
try {
|
||||||
this.loadAndRequirePlugin(loadMetadata)
|
this.loadAndRequirePlugin(loadMetadata)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(`plugin scanner ${scanner.type} load ${loadMetadata.file} occurred error ${error}`)
|
console.console(`§c扫描器 §4${scanner.type} §c文件 §4${loadMetadata.file.toString().replace(root, '')} §c编译失败 请提供下列错误给开发者`)
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(`plugin scanner ${scanner.type} occurred error ${error}`)
|
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.emit('plugin.scan', folder)
|
process.emit('plugin.manager.after.scan', folder, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
build(): void {
|
build(): void {
|
||||||
|
process.emit('plugin.manager.before.build', this)
|
||||||
this.buildPlugins()
|
this.buildPlugins()
|
||||||
process.emit('plugin.build')
|
process.emit('plugin.manager.after.build', this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private logStage(plugin: plugin.Plugin, stage: string) {
|
private logStage(plugin: plugin.Plugin, stage: string) {
|
||||||
@@ -132,6 +137,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
private loadPlugin(loadMetadata: plugin.PluginLoadMetadata) {
|
private loadPlugin(loadMetadata: plugin.PluginLoadMetadata) {
|
||||||
if (!loadMetadata) { throw new Error('loadMetadata can\'t be undefiend when loadPlugin!') }
|
if (!loadMetadata) { throw new Error('loadMetadata can\'t be undefiend when loadPlugin!') }
|
||||||
if (loadMetadata.loaded) { throw new Error(`Plugin file ${loadMetadata.file} is already loaded by ${loadMetadata.loader?.type}!`) }
|
if (loadMetadata.loaded) { throw new Error(`Plugin file ${loadMetadata.file} is already loaded by ${loadMetadata.loader?.type}!`) }
|
||||||
|
process.emit(`plugin.before.require`, loadMetadata)
|
||||||
try {
|
try {
|
||||||
for (const [, loader] of this.loaderMap) {
|
for (const [, loader] of this.loaderMap) {
|
||||||
if (this.loaderRequirePlugin(loadMetadata, loader)?.loaded) return loadMetadata.metadata
|
if (this.loaderRequirePlugin(loadMetadata, loader)?.loaded) return loadMetadata.metadata
|
||||||
@@ -140,7 +146,6 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
console.i18n("ms.plugin.manager.initialize.error", { name: loadMetadata.file, ex: error })
|
console.i18n("ms.plugin.manager.initialize.error", { name: loadMetadata.file, ex: error })
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
console.console(`§6scanner: §b${loadMetadata.scanner.type} §ccan\'t load §6file §b${loadMetadata.file}. §eskip!`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private loaderRequirePlugin(loadMetadata: plugin.PluginLoadMetadata, loader: plugin.PluginLoader) {
|
private loaderRequirePlugin(loadMetadata: plugin.PluginLoadMetadata, loader: plugin.PluginLoader) {
|
||||||
@@ -154,6 +159,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
}
|
}
|
||||||
this.metadataMap.set(metadata.name, metadata)
|
this.metadataMap.set(metadata.name, metadata)
|
||||||
metadata.loadMetadata = loadMetadata
|
metadata.loadMetadata = loadMetadata
|
||||||
|
process.emit(`plugin.after.require`, loadMetadata)
|
||||||
}
|
}
|
||||||
return loadMetadata
|
return loadMetadata
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -169,6 +175,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
private loadAndRequirePlugin(loadMetadata: plugin.PluginLoadMetadata) {
|
private loadAndRequirePlugin(loadMetadata: plugin.PluginLoadMetadata) {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let metadata = this.loadPlugin(loadMetadata.scanner.load(loadMetadata))
|
let metadata = this.loadPlugin(loadMetadata.scanner.load(loadMetadata))
|
||||||
|
if (!metadata) { throw new Error('load plugin metadata failed.') }
|
||||||
console.i18n('ms.plugin.manager.build', {
|
console.i18n('ms.plugin.manager.build', {
|
||||||
name: loadMetadata.metadata.name,
|
name: loadMetadata.metadata.name,
|
||||||
version: loadMetadata.metadata.version,
|
version: loadMetadata.metadata.version,
|
||||||
@@ -184,11 +191,14 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
* 从文件加载插件
|
* 从文件加载插件
|
||||||
* @param file java.io.File
|
* @param file java.io.File
|
||||||
*/
|
*/
|
||||||
loadFromFile(file: string, scanner = this.sacnnerMap.get('file')): plugin.Plugin {
|
loadFromFile(file: string, ext: any = 'js'): plugin.Plugin {
|
||||||
if (!file) { throw new Error('plugin file can\'t be undefiend!') }
|
if (!file) { throw new Error('plugin file can\'t be undefiend.') }
|
||||||
if (!scanner) { throw new Error('plugin scanner can\'t be undefiend!') }
|
let scanner = this.sacnnerMap.get(ext)
|
||||||
|
if (!scanner) { throw new Error(`plugin scanner ${ext} can't found in sacnnerMap.`) }
|
||||||
let metadata = this.loadAndRequirePlugin(scanner.read(file))
|
let metadata = this.loadAndRequirePlugin(scanner.read(file))
|
||||||
let plugin = this.buildPlugin(metadata)
|
this.buildPlugin(metadata)
|
||||||
|
let plugin = metadata.target
|
||||||
|
if (!plugin) { throw new Error(`plugin scanner ${ext} can't found in sacnnerMap.`) }
|
||||||
this.load(plugin)
|
this.load(plugin)
|
||||||
this.enable(plugin)
|
this.enable(plugin)
|
||||||
return plugin
|
return plugin
|
||||||
@@ -213,12 +223,20 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
reload(...args: any[]): void {
|
reload(...args: any[]): void {
|
||||||
this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
|
this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
|
||||||
this.disable(pl)
|
this.disable(pl)
|
||||||
this.loadFromFile(pl.description.loadMetadata.file, pl.description.loadMetadata.scanner)
|
this.loadFromFile(pl.description.loadMetadata.file, pl.description.loadMetadata.scanner.type)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has(name: string) {
|
||||||
|
return this.instanceMap.has(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(name: string) {
|
||||||
|
return this.instanceMap.get(name) || null
|
||||||
|
}
|
||||||
|
|
||||||
getPlugin(name: string) {
|
getPlugin(name: string) {
|
||||||
return this.instanceMap.get(name)
|
return this.instanceMap.get(name) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlugins() {
|
getPlugins() {
|
||||||
@@ -235,12 +253,12 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private checkAndGet(name: string | plugin.Plugin | undefined | any): Map<string, plugin.Plugin> | plugin.Plugin[] {
|
private checkAndGet(name: string | plugin.Plugin | undefined | any): Map<string, plugin.Plugin> | plugin.Plugin[] {
|
||||||
if (name === undefined) throw new Error(`checkAndGet Plugin can't be undefiend!`)
|
if (name === undefined) throw new Error(`checkAndGet Plugin can't be undefiend.`)
|
||||||
if (name == this.instanceMap) { return this.instanceMap }
|
if (name == this.instanceMap) { return this.instanceMap }
|
||||||
if (typeof name == 'string' && this.instanceMap.has(name)) { return [this.instanceMap.get(name)] }
|
if (typeof name == 'string' && this.instanceMap.has(name)) { return [this.instanceMap.get(name)] }
|
||||||
if (name instanceof interfaces.Plugin) { return [name as plugin.Plugin] }
|
if (name instanceof interfaces.Plugin) { return [name as plugin.Plugin] }
|
||||||
if (name.description?.name) { return [name as plugin.Plugin] }
|
if (name.description?.name) { return [name as plugin.Plugin] }
|
||||||
throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
|
throw new Error(`Plugin ${JSON.stringify(name)} not exist.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildPlugins() {
|
private buildPlugins() {
|
||||||
@@ -248,10 +266,10 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
if (metadata?.depends?.length) {
|
if (metadata?.depends?.length) {
|
||||||
this.lazyMetadataMap.set(key, metadata)
|
this.lazyMetadataMap.set(key, metadata)
|
||||||
} else {
|
} else {
|
||||||
this.buildPlugin(metadata)
|
this.tryBuildPlugin(metadata)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.lazyMetadataMap.forEach((metadata, key) => this.buildPlugin(metadata))
|
this.lazyMetadataMap.forEach((metadata, key) => this.tryBuildPlugin(metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkDepends(depends: string | string[]) {
|
private checkDepends(depends: string | string[]) {
|
||||||
@@ -266,22 +284,29 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
for (const depend of depends) { if (!this.nativePluginManager.has(depend)) loseDepends.push(depend) }
|
for (const depend of depends) { if (!this.nativePluginManager.has(depend)) loseDepends.push(depend) }
|
||||||
return loseDepends
|
return loseDepends
|
||||||
}
|
}
|
||||||
private buildPlugin(metadata: plugin.PluginMetadata) {
|
|
||||||
|
private tryBuildPlugin(metadata: plugin.PluginMetadata) {
|
||||||
try {
|
try {
|
||||||
if (this.instanceMap.has(metadata.name)) { throw new Error(`Plugin ${metadata.name} is already load from ${metadata.source}...`) }
|
return this.buildPlugin(metadata)
|
||||||
if (!this.loaderMap.has(metadata.type)) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查 §c${metadata.type} §4加载器是否正常启用!`) }
|
|
||||||
if (!this.serverChecker.check(metadata.servers)) { throw new Error(`§6插件 §b${metadata.name} §c服务器类型不兼容(${metadata.servers.join(',')}) §6忽略加载...`) }
|
|
||||||
let loseDepends = this.checkDepends(metadata.depends) || []
|
|
||||||
if (loseDepends.length) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查脚本依赖 §3[${loseDepends.join(',')}] §4是否安装完整!`) }
|
|
||||||
let loseNativeDepends = this.checkNativeDepends(metadata.nativeDepends) || []
|
|
||||||
if (loseNativeDepends.length) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查插件依赖 §3[${loseNativeDepends.join(',')}] §4是否安装完整!`) }
|
|
||||||
let pluginInstance = this.loaderMap.get(metadata.type).build(metadata)
|
|
||||||
if (!pluginInstance) { throw new Error(`§4加载器 §c${metadata.type} §4加载插件 §c${metadata.name} §4失败!`) }
|
|
||||||
this.instanceMap.set(metadata.name, pluginInstance)
|
|
||||||
return pluginInstance
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.console(`§4无法加载插件 §b${metadata.name} §4构建插件失败!`)
|
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildPlugin(metadata: plugin.PluginMetadata) {
|
||||||
|
process.emit(`plugin.before.build`, metadata)
|
||||||
|
if (this.instanceMap.has(metadata.name)) { throw new Error(`Plugin ${metadata.name} is already load from ${metadata.source}...`) }
|
||||||
|
if (!this.loaderMap.has(metadata.type)) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查 §c${metadata.type} §4加载器是否正常启用!`) }
|
||||||
|
if (!this.serverChecker.check(metadata.servers)) { throw new Error(`§6插件 §b${metadata.name} §c服务器类型不兼容(${metadata.servers.join(',')}) §6忽略加载...`) }
|
||||||
|
let loseDepends = this.checkDepends(metadata.depends) || []
|
||||||
|
if (loseDepends.length) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查脚本依赖 §3[${loseDepends.join(',')}] §4是否安装完整!`) }
|
||||||
|
let loseNativeDepends = this.checkNativeDepends(metadata.nativeDepends) || []
|
||||||
|
if (loseNativeDepends.length) { throw new Error(`§4无法加载插件 §b${metadata.name} §4请检查插件依赖 §3[${loseNativeDepends.join(',')}] §4是否安装完整!`) }
|
||||||
|
let pluginInstance = this.loaderMap.get(metadata.type).build(metadata)
|
||||||
|
if (!pluginInstance) { throw new Error(`§4加载器 §c${metadata.type} §4加载插件 §c${metadata.name} §4失败!`) }
|
||||||
|
metadata.target = pluginInstance
|
||||||
|
this.instanceMap.set(metadata.name, pluginInstance)
|
||||||
|
process.emit(`plugin.after.build`, metadata, pluginInstance)
|
||||||
|
return pluginInstance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { plugin } from "@ccms/api"
|
|||||||
import * as fs from '@ccms/common/dist/fs'
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
import { provideSingletonNamed } from "@ccms/container"
|
import { provideSingletonNamed } from "@ccms/container"
|
||||||
|
|
||||||
const SCANNER_TYPE_NAME = 'file'
|
const SCANNER_TYPE_NAME = 'js'
|
||||||
|
|
||||||
@provideSingletonNamed(plugin.PluginScanner, SCANNER_TYPE_NAME)
|
@provideSingletonNamed(plugin.PluginScanner, SCANNER_TYPE_NAME)
|
||||||
export class JSFileScanner implements plugin.PluginScanner {
|
export class JSFileScanner implements plugin.PluginScanner {
|
||||||
@@ -67,7 +67,13 @@ function getPluginConfigMetadata(target: any) {
|
|||||||
) || new Map<string, interfaces.ConfigMetadata>()
|
) || new Map<string, interfaces.ConfigMetadata>()
|
||||||
return configMetadata
|
return configMetadata
|
||||||
}
|
}
|
||||||
|
function getPluginPlayerDataMetadata(target: any) {
|
||||||
|
let playerdataMetadata: Map<string, interfaces.ConfigMetadata> = Reflect.getMetadata(
|
||||||
|
METADATA_KEY.playerdata,
|
||||||
|
target.constructor
|
||||||
|
) || new Map<string, interfaces.ConfigMetadata>()
|
||||||
|
return playerdataMetadata
|
||||||
|
}
|
||||||
function getPluginStageMetadata(target: any, stage: string) {
|
function getPluginStageMetadata(target: any, stage: string) {
|
||||||
let stageMetadata: interfaces.ExecMetadata[] = Reflect.getMetadata(
|
let stageMetadata: interfaces.ExecMetadata[] = Reflect.getMetadata(
|
||||||
METADATA_KEY.stage[stage],
|
METADATA_KEY.stage[stage],
|
||||||
@@ -86,5 +92,6 @@ export {
|
|||||||
getPluginTabCompleterMetadata,
|
getPluginTabCompleterMetadata,
|
||||||
getPluginListenerMetadata,
|
getPluginListenerMetadata,
|
||||||
getPluginConfigMetadata,
|
getPluginConfigMetadata,
|
||||||
|
getPluginPlayerDataMetadata,
|
||||||
getPluginStageMetadata
|
getPluginStageMetadata
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/polyfill",
|
"name": "@ccms/polyfill",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript polyfill package",
|
"description": "MiaoScript polyfill package",
|
||||||
"author": "MiaoWoo <admin@yumc.pw>",
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
@@ -14,14 +14,14 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/i18n": "^0.18.0",
|
"@ccms/i18n": "^0.28.0-beta.2",
|
||||||
"@ccms/nodejs": "^0.18.0",
|
"@ccms/nodejs": "^0.28.0-beta.2",
|
||||||
"core-js": "^3.21.0"
|
"core-js": "^3.27.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.18.0",
|
"@ccms/nashorn": "^0.28.0-beta.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2134
packages/polyfill/src/buffer.ts
Normal file
2134
packages/polyfill/src/buffer.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,5 +12,7 @@ import 'core-js'
|
|||||||
process.on('exit', () => require.disable())
|
process.on('exit', () => require.disable())
|
||||||
global.setGlobal('Proxy', require('./proxy').Proxy)
|
global.setGlobal('Proxy', require('./proxy').Proxy)
|
||||||
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
|
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
|
||||||
|
global.setGlobal('Buffer', require('./buffer').Buffer)
|
||||||
global.setGlobal('Blob', require('blob-polyfill').Blob)
|
global.setGlobal('Blob', require('blob-polyfill').Blob)
|
||||||
console.i18n("ms.polyfill.completed", { time: (new Date().getTime() - polyfillStartTime) / 1000 })
|
console.i18n("ms.polyfill.completed", { time: (new Date().getTime() - polyfillStartTime) / 1000 })
|
||||||
|
export default true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { EventEmitter } from 'events'
|
|||||||
|
|
||||||
const System = Java.type('java.lang.System')
|
const System = Java.type('java.lang.System')
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
const ManagementFactory = Java.type('java.lang.management.ManagementFactory')
|
||||||
const InterruptedException = Java.type('java.lang.InterruptedException')
|
const InterruptedException = Java.type('java.lang.InterruptedException')
|
||||||
const ThreadGroup = Java.type("java.lang.ThreadGroup")
|
const ThreadGroup = Java.type("java.lang.ThreadGroup")
|
||||||
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
||||||
@@ -15,19 +16,35 @@ const DelayQueue = Java.type('java.util.concurrent.DelayQueue')
|
|||||||
const JavaScriptTask = Java.type(base.getJavaScriptTaskClass().name)
|
const JavaScriptTask = Java.type(base.getJavaScriptTaskClass().name)
|
||||||
|
|
||||||
const threadCount = new AtomicInteger(0)
|
const threadCount = new AtomicInteger(0)
|
||||||
const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task")
|
const threadGroup = new ThreadGroup("@ccms/micro-task")
|
||||||
const microTaskPool = new ThreadPoolExecutor(
|
const microTaskPool = new ThreadPoolExecutor(
|
||||||
100, 200, 60, TimeUnit.SECONDS,
|
100, 200, 60, TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(300),
|
new LinkedBlockingQueue(1024),
|
||||||
new ThreadFactory((run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()))
|
new ThreadFactory((run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()))
|
||||||
)
|
)
|
||||||
class Process extends EventEmitter {
|
class Process extends EventEmitter {
|
||||||
|
readonly version = base.version
|
||||||
|
readonly versions = []
|
||||||
|
readonly config = {}
|
||||||
|
readonly pid: number = parseInt(ManagementFactory.getRuntimeMXBean().getName().split('@')[0])
|
||||||
|
readonly ppid: number
|
||||||
|
title: string
|
||||||
|
readonly arch: string = System.getProperty("os.arch")
|
||||||
|
readonly platform = System.getProperty("os.name")
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
__noSuchProperty__: (prop) => {
|
__noSuchProperty__: (prop) => {
|
||||||
return System.getenv(prop)
|
return System.getenv(prop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
platform = System.getProperty("os.name")
|
|
||||||
|
stdout = System.out
|
||||||
|
stderr = System.err
|
||||||
|
stdin = System.in
|
||||||
|
|
||||||
|
execArgv = ''
|
||||||
|
execPath = ''
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.on('exit', () => {
|
this.on('exit', () => {
|
||||||
@@ -49,10 +66,10 @@ class Process extends EventEmitter {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
nextTick(func: Function, ...args: any[]) {
|
nextTick(callback: Function, ...args: any[]): void {
|
||||||
microTaskPool.execute(() => {
|
microTaskPool.execute(() => {
|
||||||
try {
|
try {
|
||||||
func(args)
|
callback(args)
|
||||||
} catch (origin: any) {
|
} catch (origin: any) {
|
||||||
try {
|
try {
|
||||||
super.emit('error', origin)
|
super.emit('error', origin)
|
||||||
@@ -65,27 +82,63 @@ class Process extends EventEmitter {
|
|||||||
}
|
}
|
||||||
exit(code: number) {
|
exit(code: number) {
|
||||||
console.log(`process exit by code ${code}!`)
|
console.log(`process exit by code ${code}!`)
|
||||||
this.emit('exit', code)
|
this.emit('exit', this.exitCode = code)
|
||||||
|
}
|
||||||
|
exitCode = 0
|
||||||
|
openStdin() {
|
||||||
|
throw new Error('MiaoScript unsupport openStdin.')
|
||||||
|
}
|
||||||
|
chdir(directory: string): void {
|
||||||
|
console.error('MiaoScript unsupport chdir. lock at ' + root)
|
||||||
|
}
|
||||||
|
cwd() {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
getgid(): number {
|
||||||
|
throw new Error('MiaoScript unsupport getgid.')
|
||||||
|
}
|
||||||
|
setgid(id: number | string) {
|
||||||
|
throw new Error('MiaoScript unsupport setgid.')
|
||||||
|
}
|
||||||
|
getuid(): number {
|
||||||
|
throw new Error('MiaoScript unsupport getuid.')
|
||||||
|
}
|
||||||
|
setuid(id: number | string) {
|
||||||
|
throw new Error('MiaoScript unsupport setuid.')
|
||||||
|
}
|
||||||
|
setUncaughtExceptionCaptureCallback(cb: ((err: Error) => void) | null) {
|
||||||
|
if (cb == null) {
|
||||||
|
this.removeAllListeners('error')
|
||||||
|
} else {
|
||||||
|
this.on('error', cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasUncaughtExceptionCaptureCallback() {
|
||||||
|
return this.listenerCount('error') > 0
|
||||||
|
}
|
||||||
|
kill(pid: number, signal?: string | number): true {
|
||||||
|
throw new Error('MiaoScript unsupport kill.')
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return "[object process]"
|
return "[object process]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventLoop {
|
class EventLoop {
|
||||||
|
private threadCount = new AtomicInteger(0)
|
||||||
private eventLoopMainThread = undefined
|
private eventLoopMainThread = undefined
|
||||||
private eventLoopTaskQueue = new DelayQueue()
|
private eventLoopTaskQueue = new DelayQueue()
|
||||||
private taskExecTimeout = 3
|
private taskExecuteTimeout = 3000
|
||||||
private fixedThreadPool = undefined
|
private fixedThreadPool = undefined
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.taskExecTimeout = parseInt(process.env.MS_NODE_EVENT_LOOP_TIMEOUT) || 3
|
this.taskExecuteTimeout = parseInt(process.env.MS_TASK_EXECUTE_TIMEOUT) || 3000
|
||||||
this.fixedThreadPool = new ThreadPoolExecutor(
|
this.fixedThreadPool = new ThreadPoolExecutor(
|
||||||
1, 1, 0, TimeUnit.SECONDS,
|
8, 16, 0, TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(300),
|
new LinkedBlockingQueue(1024),
|
||||||
new ThreadFactory((run: any) => {
|
new ThreadFactory((run: any) => {
|
||||||
let thread = new Thread(run, "@ccms/node-shim/event-loop-exec")
|
let thread = new Thread(run, "@ccms/event-loop-" + this.threadCount.incrementAndGet())
|
||||||
thread.setDaemon(true)
|
thread.setDaemon(true)
|
||||||
return thread
|
return thread
|
||||||
}))
|
}))
|
||||||
@@ -115,7 +168,7 @@ class EventLoop {
|
|||||||
this.intervalTasks = undefined
|
this.intervalTasks = undefined
|
||||||
this.eventLoopMainThread = undefined
|
this.eventLoopMainThread = undefined
|
||||||
}
|
}
|
||||||
}, "@ccms/node-shim/event-loop")
|
}, "@ccms/event-loop")
|
||||||
this.eventLoopMainThread.setDaemon(true)
|
this.eventLoopMainThread.setDaemon(true)
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
this.eventLoopMainThread.interrupt()
|
this.eventLoopMainThread.interrupt()
|
||||||
@@ -137,14 +190,16 @@ class EventLoop {
|
|||||||
if (!callback) {
|
if (!callback) {
|
||||||
throw new Error(`task ${name} callback function can't be null!`)
|
throw new Error(`task ${name} callback function can't be null!`)
|
||||||
}
|
}
|
||||||
if (this.fixedThreadPool.isShutdown()) { return console.warn(`FixedThreadPool isTerminated! ignore Task ${name}!`) }
|
if (this.fixedThreadPool.isShutdown()) {
|
||||||
|
return console.warn(`FixedThreadPool isTerminated! ignore Task ${name}!`)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
this.fixedThreadPool.submit(new Callable({
|
this.fixedThreadPool.submit(new Callable({
|
||||||
call: () => {
|
call: () => {
|
||||||
try {
|
try {
|
||||||
callback.apply(undefined, args)
|
callback.apply(undefined, args)
|
||||||
} catch (cause: any) {
|
} catch (cause: any) {
|
||||||
cause = cause.getCause && cause.getCause() || cause
|
cause = cause.getCause ? cause.getCause() : cause
|
||||||
try {
|
try {
|
||||||
process.emit('error', cause)
|
process.emit('error', cause)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -153,13 +208,13 @@ class EventLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})).get(this.taskExecTimeout, TimeUnit.SECONDS)
|
})).get(this.taskExecuteTimeout, TimeUnit.MILLISECONDS)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error instanceof InterruptedException) {
|
if (error instanceof InterruptedException) {
|
||||||
return console.warn(`FixedThreadPool isInterrupted exit! Task ${name} exec exit!`)
|
return console.warn(`FixedThreadPool isInterrupted exit! Task ${name} exec exit!`)
|
||||||
}
|
}
|
||||||
if (error instanceof TimeoutException) {
|
if (error instanceof TimeoutException) {
|
||||||
return console.warn(`Task ${name} => ${callback} exec time greater than ${this.taskExecTimeout}s!`)
|
return console.warn(`Task ${name} => ${callback} exec time greater than ${this.taskExecuteTimeout}ms!`)
|
||||||
}
|
}
|
||||||
throw error.getCause && error.getCause() || error
|
throw error.getCause && error.getCause() || error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,14 @@ type EventType =
|
|||||||
| 'timeout'
|
| 'timeout'
|
||||||
| 'loadend'
|
| 'loadend'
|
||||||
| 'loadstart'
|
| 'loadstart'
|
||||||
type HttpHeader = { [key: string]: string }
|
type RequestHttpHeader = { [key: string]: string }
|
||||||
|
type HttpHeader = { [key: string]: string[] }
|
||||||
|
|
||||||
const executor = Executors.newCachedThreadPool()
|
const executor = Executors.newCachedThreadPool()
|
||||||
|
|
||||||
export class XMLHttpRequest {
|
export class XMLHttpRequest {
|
||||||
private _timeout: number = 120000;
|
private _connectTimeout: number = 5000;
|
||||||
|
private _readTimeout: number = 120000;
|
||||||
private _responseType: ResponseType = 'text';
|
private _responseType: ResponseType = 'text';
|
||||||
private _withCredentials: boolean
|
private _withCredentials: boolean
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ export class XMLHttpRequest {
|
|||||||
private _url: string
|
private _url: string
|
||||||
private _async: boolean
|
private _async: boolean
|
||||||
private _mimeType: string
|
private _mimeType: string
|
||||||
private _requestHeaders: HttpHeader = {};
|
private _requestHeaders: RequestHttpHeader = {};
|
||||||
|
|
||||||
private _status: number = 0;
|
private _status: number = 0;
|
||||||
private _statusText: string = null;
|
private _statusText: string = null;
|
||||||
@@ -96,10 +97,22 @@ export class XMLHttpRequest {
|
|||||||
private _connection = null;
|
private _connection = null;
|
||||||
|
|
||||||
get timeout() {
|
get timeout() {
|
||||||
return this._timeout
|
return this._readTimeout
|
||||||
}
|
}
|
||||||
set timeout(timeout: number) {
|
set timeout(timeout: number) {
|
||||||
this._timeout = timeout
|
this._readTimeout = timeout
|
||||||
|
}
|
||||||
|
get connectTimeout() {
|
||||||
|
return this._connectTimeout
|
||||||
|
}
|
||||||
|
set connectTimeout(timeout: number) {
|
||||||
|
this._connectTimeout = timeout
|
||||||
|
}
|
||||||
|
get readTimeout() {
|
||||||
|
return this._readTimeout
|
||||||
|
}
|
||||||
|
set readTimeout(timeout: number) {
|
||||||
|
this._readTimeout = timeout
|
||||||
}
|
}
|
||||||
get readyState() {
|
get readyState() {
|
||||||
return this._readyState
|
return this._readyState
|
||||||
@@ -143,7 +156,7 @@ export class XMLHttpRequest {
|
|||||||
this._requestHeaders[key] = val
|
this._requestHeaders[key] = val
|
||||||
}
|
}
|
||||||
getResponseHeader(key: string): string {
|
getResponseHeader(key: string): string {
|
||||||
return this._responseHeaders[key]
|
return this._responseHeaders[key]?.[0]
|
||||||
}
|
}
|
||||||
getAllResponseHeaders(): any {
|
getAllResponseHeaders(): any {
|
||||||
return this._responseHeaders
|
return this._responseHeaders
|
||||||
@@ -169,8 +182,8 @@ export class XMLHttpRequest {
|
|||||||
this._connection.setRequestMethod(this._method)
|
this._connection.setRequestMethod(this._method)
|
||||||
this._connection.setDoOutput(true)
|
this._connection.setDoOutput(true)
|
||||||
this._connection.setDoInput(true)
|
this._connection.setDoInput(true)
|
||||||
this._connection.setConnectTimeout(this._timeout)
|
this._connection.setConnectTimeout(this._connectTimeout)
|
||||||
this._connection.setReadTimeout(this._timeout)
|
this._connection.setReadTimeout(this._readTimeout)
|
||||||
|
|
||||||
this.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
this.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
||||||
this.setReadyState(ReadyState.OPENED)
|
this.setReadyState(ReadyState.OPENED)
|
||||||
@@ -181,7 +194,7 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
|
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
|
||||||
let future = executor.submit(new Callable({ call: () => this._send(body) }))
|
let future = executor.submit(new Callable({ call: () => this._send(body) }))
|
||||||
if (!this._async) { future.get(this._timeout, TimeUnit.MILLISECONDS) }
|
if (!this._async) { future.get(this._connectTimeout + this._readTimeout + 100, TimeUnit.MILLISECONDS) }
|
||||||
return future
|
return future
|
||||||
}
|
}
|
||||||
get() {
|
get() {
|
||||||
@@ -199,22 +212,23 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
abort() {
|
abort() {
|
||||||
this._connection.disconnect()
|
this._connection.disconnect()
|
||||||
this.onabort && this.onabort()
|
this.onabort?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _send(body?: string | object) {
|
private _send(body?: string | object) {
|
||||||
try {
|
try {
|
||||||
this._connection.connect()
|
this._connection.connect()
|
||||||
this.onloadstart && this.onloadstart()
|
this.onloadstart?.()
|
||||||
if (body) {
|
if (body) {
|
||||||
let bodyType = Object.prototype.toString.call(body)
|
let bodyType = Object.prototype.toString.call(body)
|
||||||
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string!`) }
|
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string.`) }
|
||||||
var out = this._connection.getOutputStream()
|
var out = this._connection.getOutputStream()
|
||||||
out.write(new JavaString(body).getBytes(UTF_8))
|
out.write(new JavaString(body).getBytes(UTF_8))
|
||||||
out.flush()
|
out.flush()
|
||||||
out.close()
|
out.close()
|
||||||
}
|
}
|
||||||
this.setReadyState(ReadyState.LOADING)
|
this.setReadyState(ReadyState.LOADING)
|
||||||
|
this.onload?.()
|
||||||
this._status = this._connection.getResponseCode()
|
this._status = this._connection.getResponseCode()
|
||||||
this._statusText = this._connection.getResponseMessage()
|
this._statusText = this._connection.getResponseMessage()
|
||||||
if (this._status >= 0 && this._status < 300) {
|
if (this._status >= 0 && this._status < 300) {
|
||||||
@@ -224,8 +238,8 @@ export class XMLHttpRequest {
|
|||||||
} else {
|
} else {
|
||||||
this._responseText = this.readOutput(this._connection.getErrorStream())
|
this._responseText = this.readOutput(this._connection.getErrorStream())
|
||||||
}
|
}
|
||||||
this.setResponseHeaders(this._connection.getHeaderFields())
|
this.setResponseHeaders()
|
||||||
this.onloadend && this.onloadend()
|
this.onloadend?.()
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
if (ex instanceof SocketTimeoutException && this.ontimeout) {
|
if (ex instanceof SocketTimeoutException && this.ontimeout) {
|
||||||
return this.ontimeout(ex)
|
return this.ontimeout(ex)
|
||||||
@@ -239,15 +253,15 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setResponseHeaders(header: any) {
|
private setResponseHeaders() {
|
||||||
header.forEach((key: string | number, value: string | any[]) => {
|
this._connection.getHeaderFields().forEach((key: string | number, value: any[]) => {
|
||||||
this._responseHeaders[key + ''] = value[value.length - 1] + ''
|
this._responseHeaders[key + ''] = Java.from(value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private setReadyState(state: ReadyState) {
|
private setReadyState(state: ReadyState) {
|
||||||
this._readyState = state
|
this._readyState = state
|
||||||
this.onreadystatechange && this.onreadystatechange()
|
this.onreadystatechange?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
private readOutput(input: any) {
|
private readOutput(input: any) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/protocol",
|
"name": "@ccms/protocol",
|
||||||
"version": "0.18.0",
|
"version": "0.28.0-beta.2",
|
||||||
"description": "MiaoScript protocol package",
|
"description": "MiaoScript protocol package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
packages/qrcode/package.json
Normal file
26
packages/qrcode/package.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "@ccms/qrcode",
|
||||||
|
"version": "0.28.0-beta.2",
|
||||||
|
"description": "MiaoScript qrcode 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": "^4.1.2",
|
||||||
|
"typescript": "^4.9.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
1243
packages/qrcode/src/index.ts
Normal file
1243
packages/qrcode/src/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user