release: v0.23.0
1. add item api 2. support rollup source map 3. fix database drvice error 4. support loliserver 5. support 1.19 bukkit chat 6. config add migrate options 7. Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
b5fac23c5c
commit
15d1f8392b
@ -9,5 +9,8 @@
|
|||||||
"run": {
|
"run": {
|
||||||
"stream": true
|
"stream": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"np": "./script/push.sh",
|
"np": "./script/push.sh",
|
||||||
"lsp": "npm login --registry=https://registry.npmjs.org --scope=@ccms",
|
"lsp": "npm login --registry=https://registry.npmjs.org --scope=@ccms",
|
||||||
"lp": "lerna publish --registry https://registry.npmjs.org",
|
"lp": "lerna publish --registry https://registry.npmjs.org",
|
||||||
"lpb": "lerna publish --registry https://registry.npmjs.org --canary --pre-dist-tag beta"
|
"lpb": "lerna publish --registry https://registry.npmjs.org --canary --preid beta --pre-dist-tag beta"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
@ -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)
|
||||||
|
} else if (global.debug) {
|
||||||
|
console.debug('readSourceMap can\'t found', fileName, 'source map file', sourceMappingURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceContent) {
|
||||||
|
sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||||
|
sourceFileMaps[fileName] = Paths.get(fileName, '..', sourceMaps[fileName].sources[0]).toFile().getCanonicalPath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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} => §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 } = 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 {
|
||||||
|
@ -6,6 +6,10 @@ export namespace database {
|
|||||||
* 数据库配置
|
* 数据库配置
|
||||||
*/
|
*/
|
||||||
export interface DataBaseConfig {
|
export interface DataBaseConfig {
|
||||||
|
/**
|
||||||
|
* 数据库类型
|
||||||
|
*/
|
||||||
|
type: 'h2' | 'mysql' | 'mongodb' | 'sqlite' | 'postgres' | 'redis'
|
||||||
/**
|
/**
|
||||||
* 数据库连接串
|
* 数据库连接串
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -149,7 +149,15 @@ export namespace plugin {
|
|||||||
/**
|
/**
|
||||||
* 插件名称 不填默认为类名
|
* 插件名称 不填默认为类名
|
||||||
*/
|
*/
|
||||||
name?: string
|
name: string
|
||||||
|
/**
|
||||||
|
* 插件中文名称
|
||||||
|
*/
|
||||||
|
cname?: string
|
||||||
|
/**
|
||||||
|
* 插件等级 付费插件自动注入
|
||||||
|
*/
|
||||||
|
level?: number
|
||||||
/**
|
/**
|
||||||
* 前缀
|
* 前缀
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,7 @@ 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 URL = Java.type('java.net.URL')
|
||||||
const Bukkit = Java.type("org.bukkit.Bukkit")
|
const Bukkit = Java.type("org.bukkit.Bukkit")
|
||||||
const Event = Java.type("org.bukkit.event.Event")
|
const Event = Java.type("org.bukkit.event.Event")
|
||||||
const Modifier = Java.type("java.lang.reflect.Modifier")
|
const Modifier = Java.type("java.lang.reflect.Modifier")
|
||||||
@ -19,7 +20,15 @@ export class BukkitEvent extends event.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
|
||||||
|
@ -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,12 +22,12 @@ 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())
|
||||||
@ -42,7 +44,7 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
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
|
||||||
@ -50,10 +52,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('.'))
|
||||||
@ -83,9 +87,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
|
||||||
@ -100,6 +104,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 +160,31 @@ class BukkitChatInvoke_1_17_1 extends BukkitChatInvoke_1_16_5 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BukkitChatInvoke_1_19 extends BukkitChatInvoke_1_17_1 {
|
||||||
|
getSendPacketMethodName(playerConnectionClass: any) {
|
||||||
|
return playerConnectionClass.getMethod('a', this.getPacketClass()).getName()
|
||||||
|
}
|
||||||
|
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 == 0 ? 1 : type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
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) {
|
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(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)
|
||||||
}
|
}
|
||||||
|
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
126
packages/bukkit/src/item.ts
Normal file
126
packages/bukkit/src/item.ts
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
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 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(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()
|
||||||
|
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')
|
||||||
|
} 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
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"outDir": "dist"
|
"outDir": "dist",
|
||||||
|
"resolveJsonModule": true
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -129,12 +129,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(`切换到超类: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field === null) {
|
if (field === null) {
|
||||||
@ -146,21 +148,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(`切换到超类: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
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 * as yaml from 'js-yaml'
|
||||||
@ -161,19 +161,13 @@ function initialize() {
|
|||||||
loadCoreScript('initialize')
|
loadCoreScript('initialize')
|
||||||
try {
|
try {
|
||||||
let core = createCore()
|
let core = createCore()
|
||||||
if (VersionUtils.isGreaterOrEqual(base.version, '0.22.0')) { return core }
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
return core.enable()
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (console.console) {
|
let core = { enable: () => () => console.i18n('ms.core.engine.disable.abnormal') }
|
||||||
console.i18n("core.initialize.error", { error })
|
console.i18n("core.initialize.error", { error })
|
||||||
console.ex(error)
|
jsconsole.getStackTrace(error, false).forEach(line => console.log(line))
|
||||||
} else {
|
|
||||||
error.printStackTrace()
|
|
||||||
}
|
|
||||||
process.emit('core.initialize.error')
|
process.emit('core.initialize.error')
|
||||||
return {
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
enable: () => console.i18n('ms.core.engine.disable.abnormal')
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
process.emit('core.after.initialize')
|
process.emit('core.after.initialize')
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { database } from '@ccms/api'
|
import { database } from '@ccms/api'
|
||||||
import { JSClass, postConstruct } from '@ccms/container'
|
import { JSClass } from '@ccms/container'
|
||||||
|
|
||||||
|
const Thread = Java.type('java.lang.Thread')
|
||||||
const JavaString = Java.type('java.lang.String')
|
const JavaString = Java.type('java.lang.String')
|
||||||
const Properties = Java.type('java.util.Properties')
|
const Properties = Java.type('java.util.Properties')
|
||||||
|
|
||||||
@ -26,9 +27,21 @@ export class DataBase extends database.DataBase {
|
|||||||
|
|
||||||
private createDataSource(dbConfig: database.DataBaseConfig) {
|
private createDataSource(dbConfig: database.DataBaseConfig) {
|
||||||
if (typeof dbConfig.url === "string") {
|
if (typeof dbConfig.url === "string") {
|
||||||
|
let originClassLoader = Thread.currentThread().getContextClassLoader()
|
||||||
|
Thread.currentThread().setContextClassLoader(base.getInstance().class.classLoader)
|
||||||
let config = new this.HikariConfig()
|
let config = new this.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) {
|
if (dbConfig.username) {
|
||||||
config.setUsername(dbConfig.username)
|
config.setUsername(dbConfig.username)
|
||||||
@ -44,7 +57,9 @@ export class DataBase extends database.DataBase {
|
|||||||
}
|
}
|
||||||
config.setDataSourceProperties(properties)
|
config.setDataSourceProperties(properties)
|
||||||
}
|
}
|
||||||
|
console.debug('createDataSource from config ' + JSON.stringify(dbConfig))
|
||||||
this.dataSource = new this.HikariDataSource(config)
|
this.dataSource = new this.HikariDataSource(config)
|
||||||
|
Thread.currentThread().setContextClassLoader(originClassLoader)
|
||||||
} else {
|
} else {
|
||||||
this.dataSource = dbConfig.url
|
this.dataSource = dbConfig.url
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
export function id() {
|
|
||||||
return (target: Object, propertyKey: string | symbol) => void {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import { DataBase } from "./database"
|
|
||||||
|
|
||||||
export class Model<T> {
|
|
||||||
constructor(private database: DataBase) {
|
|
||||||
|
|
||||||
}
|
|
||||||
queryForList(): Array<T> {
|
|
||||||
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,7 +34,7 @@ ms.api.command.tab.completer.slow: "§c注意! §6玩家 §a{player} §6执行
|
|||||||
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.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} 个插件 开始编译..."
|
||||||
|
@ -83,7 +83,7 @@ export class PluginConfigManager {
|
|||||||
name: metadata.name,
|
name: metadata.name,
|
||||||
format: metadata.format
|
format: metadata.format
|
||||||
})
|
})
|
||||||
} else {
|
} else if (metadata.migrate) {
|
||||||
configValue = configLoader.load(base.read(metadata.file)) || {}
|
configValue = configLoader.load(base.read(metadata.file)) || {}
|
||||||
if (defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
if (defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
||||||
base.save(metadata.file, configLoader.dump(configValue))
|
base.save(metadata.file, configLoader.dump(configValue))
|
||||||
|
@ -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)
|
||||||
|
@ -91,6 +91,10 @@ export namespace interfaces {
|
|||||||
* 配置文件格式 默认 yml
|
* 配置文件格式 默认 yml
|
||||||
*/
|
*/
|
||||||
format?: string
|
format?: string
|
||||||
|
/**
|
||||||
|
* 是否合并默认配置
|
||||||
|
*/
|
||||||
|
migrate?: boolean
|
||||||
/**
|
/**
|
||||||
* 自动保存 默认为 false
|
* 自动保存 默认为 false
|
||||||
*/
|
*/
|
||||||
|
@ -69,7 +69,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.i18n('ms.plugin.event.map.error', { 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) => {
|
||||||
|
@ -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")
|
||||||
@ -18,16 +19,32 @@ const threadCount = new AtomicInteger(0)
|
|||||||
const threadGroup = new ThreadGroup("@ccms/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,9 +82,44 @@ 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]"
|
||||||
}
|
}
|
||||||
@ -83,7 +135,7 @@ class EventLoop {
|
|||||||
this.taskExecuteTimeout = parseInt(process.env.MS_TASK_EXECUTE_TIMEOUT) || 3000
|
this.taskExecuteTimeout = parseInt(process.env.MS_TASK_EXECUTE_TIMEOUT) || 3000
|
||||||
this.fixedThreadPool = new ThreadPoolExecutor(
|
this.fixedThreadPool = new ThreadPoolExecutor(
|
||||||
1, 1, 0, TimeUnit.SECONDS,
|
1, 1, 0, TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(500),
|
new LinkedBlockingQueue(1024),
|
||||||
new ThreadFactory((run: any) => {
|
new ThreadFactory((run: any) => {
|
||||||
let thread = new Thread(run, "@ccms/event-loop")
|
let thread = new Thread(run, "@ccms/event-loop")
|
||||||
thread.setDaemon(true)
|
thread.setDaemon(true)
|
||||||
|
Loading…
Reference in New Issue
Block a user