feat: complate server & update spring

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2020-06-02 17:50:47 +08:00
parent 7e1111470c
commit 16fcbfa69c
9 changed files with 230 additions and 126 deletions

View File

@ -1,38 +1,143 @@
import * as reflect from '@ccms/common/dist/reflect'
import { injectable } from '@ccms/container'
import { NativePluginManager } from './native_plugin' import { NativePluginManager } from './native_plugin'
import { constants } from '../../constants'
export namespace server { export namespace server {
/** /**
* Runtime ServerType * Runtime ServerType
*/ */
export const ServerType = Symbol("ServerType"); export const ServerType = Symbol("ServerType")
/** /**
* Runtime Console * Runtime Console
*/ */
export const Console = Symbol("Console"); export const Console = Symbol("Console")
/** /**
* MiaoScript Server * MiaoScript Server
*/ */
export const Server = Symbol("Server"); export const Server = Symbol("Server")
/** /**
* Runtime Server Instance * Runtime Server Instance
*/ */
export const ServerInstance = Symbol("ServerInstance"); export const ServerInstance = Symbol("ServerInstance")
/** /**
* MiaoScript Server * MiaoScript Server
*/ */
export interface Server { export interface Server {
getVersion(): string; getVersion(): string
getPlayer(name: string): any; getPlayer(name: string): any
getOnlinePlayers(): any[]; getOnlinePlayers(): any[]
getConsoleSender(): any; getConsoleSender(): any
getService(service: string): any; getService(service: string): any
dispatchCommand(sender: string | any, command: string): boolean; dispatchCommand(sender: string | any, command: string): boolean
dispatchConsoleCommand(command: string): boolean; dispatchConsoleCommand(command: string): boolean
getPluginsFolder(): string; getPluginsFolder(): string
getNativePluginManager(): NativePluginManager; getNativePluginManager(): NativePluginManager
getNettyPipeline(): any; getDedicatedServer?(): any
getRootLogger(): any; getNettyPipeline(): any
sendJson(sender: string | any, json: object | string): void; getRootLogger(): any
tabComplete?(sender: string | any, input: string, index?: number); sendJson(sender: string | any, json: object | string): void
tabComplete?(sender: string | any, input: string, index?: number)
}
@injectable()
export abstract class ReflectServer implements server.Server {
protected pipeline: any
protected rootLogger: any
constructor() {
this.reflect()
}
getVersion(): string {
throw new Error("Method not implemented.")
}
getPlayer(name: string) {
throw new Error("Method not implemented.")
}
getOnlinePlayers(): any[] {
throw new Error("Method not implemented.")
}
getConsoleSender() {
throw new Error("Method not implemented.")
}
getService(service: string) {
throw new Error("Method not implemented.")
}
dispatchCommand(sender: any, command: string): boolean {
throw new Error("Method not implemented.")
}
dispatchConsoleCommand(command: string): boolean {
throw new Error("Method not implemented.")
}
getPluginsFolder(): string {
throw new Error("Method not implemented.")
}
getNativePluginManager(): NativePluginManager {
throw new Error("Method not implemented.")
}
getDedicatedServer() {
throw new Error("Method not implemented.")
}
getNettyPipeline() {
throw new Error("Method not implemented.")
}
getRootLogger() {
throw new Error("Method not implemented.")
}
sendJson(sender: any, json: string | object): void {
throw new Error("Method not implemented.")
}
tabComplete?(sender: any, input: string, index?: number) {
throw new Error("Method not implemented.")
}
protected reflect() {
try {
let consoleServer = this.getDedicatedServer()
this.reflectPipeline(consoleServer)
this.reflectRootLogger(consoleServer)
} catch (error) {
console.error('Error When Reflect MinecraftServer!', error)
console.ex(error)
}
}
protected reflectPipeline(consoleServer: any) {
let connection: any
let promise: any
for (const method of constants.Reflect.Method.getServerConnection) {
try {
connection = reflect.on(consoleServer).call(method).get()
if (connection.class.name.indexOf('ServerConnection') !== -1
|| connection.class.name.indexOf('NetworkSystem') !== -1) { break }
connection = undefined
} catch (error) { }
}
if (!connection) { console.error("Can't found ServerConnection!"); return }
for (const field of constants.Reflect.Field.listeningChannels) {
try {
promise = reflect.on(connection).get(field).get().get(0)
if (promise.class.name.indexOf('Promise') !== -1) { break }
promise = undefined
} catch (error) { }
}
if (!promise) { console.error("Can't found listeningChannels!"); return }
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
}
protected reflectRootLogger(consoleServer: any) {
try {
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
} catch (error) {
try { this.rootLogger = reflect.on(consoleServer).get(0).get().parent } catch (error) { }
}
if (this.rootLogger && this.rootLogger.class.name.indexOf('Logger') === -1) {
console.error('Error Logger Class: ' + this.rootLogger.class.name)
this.rootLogger = undefined
}
// get root logger
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
this.rootLogger = this.rootLogger.parent
}
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
}
} }
} }

View File

@ -7,14 +7,12 @@ import chat from './enhance/chat'
let Bukkit = org.bukkit.Bukkit; let Bukkit = org.bukkit.Bukkit;
@provideSingleton(server.Server) @provideSingleton(server.Server)
export class BukkitServer implements server.Server { export class BukkitServer extends server.ReflectServer {
private pluginsFolder: string; private pluginsFolder: string;
private pipeline: any;
private rootLogger: any;
constructor() { constructor() {
super();
this.pluginsFolder = Bukkit.getUpdateFolderFile().getParentFile().getCanonicalPath(); this.pluginsFolder = Bukkit.getUpdateFolderFile().getParentFile().getCanonicalPath();
this.reflect()
} }
getPlayer(name: string) { getPlayer(name: string) {
@ -47,6 +45,9 @@ export class BukkitServer implements server.Server {
getNativePluginManager() { getNativePluginManager() {
return Bukkit.getPluginManager() as any; return Bukkit.getPluginManager() as any;
} }
getDedicatedServer() {
return reflect.on(Bukkit.getServer()).get('console').get()
}
getNettyPipeline() { getNettyPipeline() {
return this.pipeline; return this.pipeline;
} }
@ -62,41 +63,4 @@ export class BukkitServer implements server.Server {
this.dispatchConsoleCommand(result) this.dispatchConsoleCommand(result)
} }
} }
private reflect() {
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
this.reflectPipeline(consoleServer)
this.reflectRootLogger(consoleServer)
}
private reflectPipeline(consoleServer: any) {
let connection: any;
let promise: any;
for (const method of constants.Reflect.Method.getServerConnection) {
try {
connection = reflect.on(consoleServer).call(method).get()
if (connection.class.name.indexOf('ServerConnection') !== -1
|| connection.class.name.indexOf('NetworkSystem') !== -1) { break; }
connection = undefined;
} catch (error) { }
}
if (!connection) { console.error("Can't found ServerConnection!"); return }
for (const field of constants.Reflect.Field.listeningChannels) {
try {
promise = reflect.on(connection).get(field).get().get(0);
if (promise.class.name.indexOf('Promise') !== -1) { break; }
promise = undefined;
} catch (error) { }
}
if (!promise) { console.error("Can't found listeningChannels!"); return }
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
}
private reflectRootLogger(consoleServer: any) {
try {
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
} catch (error) {
console.error("Can't found rootLogger!")
}
}
} }

View File

@ -8,14 +8,12 @@ const TextSerializers = org.spongepowered.api.text.serializer.TextSerializers;
const File = Java.type("java.io.File"); const File = Java.type("java.io.File");
@provideSingleton(server.Server) @provideSingleton(server.Server)
export class SpongeServer implements server.Server { export class SpongeServer extends server.ReflectServer {
private pluginsFolder: string; private pluginsFolder: string;
private pipeline: any;
private rootLogger: any;
constructor() { constructor() {
super();
this.pluginsFolder = new File(base.getInstance().getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile().getCanonicalPath() this.pluginsFolder = new File(base.getInstance().getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile().getCanonicalPath()
this.reflect()
} }
getPlayer(name: string) { getPlayer(name: string) {
@ -37,10 +35,10 @@ export class SpongeServer implements server.Server {
if (typeof sender === 'string') { if (typeof sender === 'string') {
sender = this.getPlayer(sender) sender = this.getPlayer(sender)
} }
return Sponge.getCommandManager().process(sender, command).getQueryResult() return Sponge.getCommandManager().process(sender, command).getQueryResult().get()
} }
dispatchConsoleCommand(command: string): boolean { dispatchConsoleCommand(command: string): boolean {
return Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command).getQueryResult() return Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command).getQueryResult().get()
} }
getPluginsFolder(): string { getPluginsFolder(): string {
return this.pluginsFolder; return this.pluginsFolder;
@ -48,6 +46,9 @@ export class SpongeServer implements server.Server {
getNativePluginManager() { getNativePluginManager() {
return Sponge.getPluginManager() as any; return Sponge.getPluginManager() as any;
} }
getDedicatedServer() {
return reflect.on(Sponge.getServer()).get()
}
getNettyPipeline() { getNettyPipeline() {
return this.pipeline; return this.pipeline;
} }
@ -60,37 +61,4 @@ export class SpongeServer implements server.Server {
} }
sender.sendMessage(TextSerializers.JSON.deserialize(json)) sender.sendMessage(TextSerializers.JSON.deserialize(json))
} }
private reflect() {
let consoleServer = reflect.on(Sponge.getServer()).get()
this.reflectPipeline(consoleServer)
this.reflectRootLogger(consoleServer)
}
private reflectPipeline(consoleServer: any) {
let connection: any;
let promise: any;
for (const method of constants.Reflect.Method.getServerConnection) {
try {
connection = reflect.on(consoleServer).call(method).get()
if (connection.class.name.indexOf('NetworkSystem') !== -1) { break; }
connection = undefined;
} catch (error) { }
}
if (!connection) { console.error("Can't found ServerConnection!"); return }
for (const field of constants.Reflect.Field.listeningChannels) {
try {
promise = reflect.on(connection).get(field).get().get(0);
if (promise.class.name.indexOf('Promise') !== -1) { break; }
promise = undefined;
} catch (error) { }
}
if (!promise) { console.error("Can't found listeningChannels!"); return }
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
}
private reflectRootLogger(consoleServer: any) {
try {
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
} catch (error) {
console.error("Can't found rootLogger!")
}
}
} }

View File

@ -3,21 +3,25 @@ import '@ccms/nashorn'
import { command, plugin } from '@ccms/api' import { command, plugin } from '@ccms/api'
import { inject, provideSingleton, postConstruct } from '@ccms/container' import { inject, provideSingleton, postConstruct } from '@ccms/container'
import { CommandMap } from './internal/command'
@provideSingleton(command.Command) @provideSingleton(command.Command)
export class SpringCommand extends command.Command { export class SpringCommand extends command.Command {
@inject(plugin.PluginInstance) @inject(plugin.PluginInstance)
private pluginInstance: any private pluginInstance: any
@inject(CommandMap)
private commandMap: CommandMap = new CommandMap()
protected create(plugin: any, command: string) { protected create(plugin: any, command: string) {
console.console('§4Spring暂不支持create命令!') return this.commandMap.register(plugin, command)
} }
protected remove(plugin: any, command: string) { protected remove(plugin: any, command: string) {
console.console('§4Spring暂不支持remove命令!') this.commandMap.unregister(plugin, command)
} }
protected onCommand(plugin: any, command: any, executor: Function) { protected onCommand(plugin: any, command: any, executor: Function) {
console.console('§4Spring暂不支持onCommand!') command.setExecutor(super.setExecutor(plugin, command, executor))
} }
protected onTabComplete(plugin: any, command: any, tabCompleter: Function) { protected onTabComplete(plugin: any, command: any, tabCompleter: Function) {
console.console('§4Spring暂不支持onTabComplete!') command.setTabCompleter(super.setExecutor(plugin, command, tabCompleter))
} }
} }

View File

@ -1,5 +1,6 @@
import { server, plugin } from '@ccms/api' import { server } from '@ccms/api'
import { Container } from '@ccms/container' import { Container } from '@ccms/container'
import '@ccms/database'
import { SpringConsole } from './console'; import { SpringConsole } from './console';
import './event'; import './event';
@ -7,8 +8,6 @@ import './server';
import './command'; import './command';
import './task'; import './task';
const BeanKit = Java.type('com.sixi.micro.common.kits.BeanKit')
export default function SpringImpl(container: Container) { export default function SpringImpl(container: Container) {
container.bind(server.Console).toConstantValue(SpringConsole) container.bind(server.Console).toConstantValue(SpringConsole)
} }

View File

@ -0,0 +1,59 @@
import { provideSingleton } from "@ccms/container"
import { plugin } from "@ccms/api"
type CommandExec = (sender: any, _: any, command: string, args: string[]) => boolean
type TabCompleter = (sender: any, _: any, command: string, args: string[]) => string[]
type CommandStore = { [key: string]: SpringCommand }
@provideSingleton(CommandMap)
export class CommandMap {
private commands: CommandStore = {}
private pluginCommands: { [key: string]: CommandStore } = {}
register(plugin: plugin.Plugin, command: string) {
let springCommand = new SpringCommand(plugin, command)
this.commands[command] = springCommand
if (!this.pluginCommands[plugin.description.name]) { this.pluginCommands[plugin.description.name] = {} }
this.pluginCommands[plugin.description.name][command] = springCommand
return springCommand
}
unregister(plugin: plugin.Plugin, command: string) {
delete this.commands[command]
delete this.pluginCommands[plugin.description.name][command]
}
dispatch(sender: any, command: string, args: string[]): boolean {
if (command === "help") {
sender.sendMessage('§e--------- §rHelp: Index §e---------------------------')
sender.sendMessage('Use /help [n] to get page n of help.')
for (const cmdName of Object.getOwnPropertyNames(this.commands)) {
sender.sendMessage(`§6/${cmdName}: §rA command provided by plugin §b${this.commands[cmdName].plugin.description.name}§r.`)
}
return
}
let exists = this.commands[command]
if (exists) {
return exists.executor(sender, '', command, Java.to(args))
} else {
sender.sendMessage && sender.sendMessage(`Unknown command. Type "/help" for help.`)
return false
}
}
}
export class SpringCommand {
public plugin: plugin.Plugin
public name: string
public executor: CommandExec
public tabCompleter: TabCompleter
constructor(plugin: plugin.Plugin, command: string, description: string = '暂无描述!') {
this.plugin = plugin
this.name = command
}
setExecutor = (executor: CommandExec) => this.executor = executor
setTabCompleter = (tabCompleter: TabCompleter) => this.tabCompleter = tabCompleter
toString = () => `SpringCommand(${this.name})`
}

View File

@ -1,50 +1,55 @@
import { server } from '@ccms/api' import { server } from '@ccms/api'
import { provideSingleton } from '@ccms/container'; import { provideSingleton, inject } from '@ccms/container'
import { NativePluginManager } from '@ccms/api/dist/interfaces/server/native_plugin'; import { NativePluginManager } from '@ccms/api/dist/interfaces/server/native_plugin'
import { CommandMap } from './internal/command'
@provideSingleton(server.Server) @provideSingleton(server.Server)
export class SpringServer implements server.Server { export class SpringServer implements server.Server {
@inject(CommandMap)
private commandMap: CommandMap
constructor() { constructor() {
} }
getVersion(): string { getVersion(): string {
return "SpringFramework" return "SpringFramework"
} }
getPlayer(name: string) { getPlayer(name: string) {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
getOnlinePlayers(): any[] { getOnlinePlayers(): any[] {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
getConsoleSender() { getConsoleSender() {
return undefined; return {
sendMessage: (message: string) => console.console(message)
}
} }
getService(service: string) { getService(service: string) {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
dispatchCommand(sender: any, command: string): boolean { dispatchCommand(sender: any, command: string): boolean {
console.console('§4Spring暂不支持dispatchCommand!') let cmd_args = command.split(" ")
return false; return this.commandMap.dispatch(sender, cmd_args.shift(), cmd_args || [])
} }
dispatchConsoleCommand(command: string): boolean { dispatchConsoleCommand(command: string): boolean {
console.console('§4Spring暂不支持dispatchConsoleCommand!') return this.dispatchCommand(this.getConsoleSender(), command)
return false;
} }
getPluginsFolder(): string { getPluginsFolder(): string {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
getNativePluginManager(): NativePluginManager { getNativePluginManager(): NativePluginManager {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
getNettyPipeline() { getNettyPipeline() {
return base.getInstance().getAutowireCapableBeanFactory() return base.getInstance().getAutowireCapableBeanFactory()
} }
getRootLogger() { getRootLogger() {
return global.logger return Packages.org.slf4j.LoggerFactory.getLogger("root") || global.logger
} }
sendJson(sender: any, json: string | object): void { sendJson(sender: any, json: string | object): void {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
tabComplete(sender: any, input: string, index?: number) { tabComplete(sender: any, input: string, index?: number) {
throw new Error("Method not implemented."); throw new Error("Method not implemented.")
} }
} }

View File

@ -34,7 +34,7 @@ export class SpringTaskManager implements task.TaskManager {
return func() return func()
} }
disable() { disable() {
Object.values(tasks).forEach((task) => task.cancel()) Object.values(tasks).forEach((task) => task?.cancel())
executor.shutdown(); executor.shutdown();
} }
} }
@ -43,7 +43,7 @@ export class SpringTask extends task.Task {
public id = taskId++ public id = taskId++
private running = new AtomicBoolean(true) private running = new AtomicBoolean(true)
run() { run(...args: any[]) {
if (this.laterTime > 0) { if (this.laterTime > 0) {
try { try {
Thread.sleep(this.laterTime) Thread.sleep(this.laterTime)
@ -53,7 +53,7 @@ export class SpringTask extends task.Task {
} }
while (this.running.get()) { while (this.running.get()) {
try { try {
this.func() this.func(...args)
} catch (t) { } catch (t) {
console.error("Task exec error:", t) console.error("Task exec error:", t)
console.ex(t) console.ex(t)
@ -72,13 +72,13 @@ export class SpringTask extends task.Task {
cancel(): any { cancel(): any {
var wasRunning = this.running.getAndSet(false) var wasRunning = this.running.getAndSet(false)
if (wasRunning) { if (wasRunning) {
tasks[this.id] = undefined delete tasks[this.id]
} }
} }
submit(): task.Cancelable { submit(...args: any[]): task.Cancelable {
tasks[this.id] = this tasks[this.id] = this
executor.execute(this.run.bind(this)) executor.execute(() => this.run(...args))
return { return {
cancel: () => { cancel: () => {
return this.cancel() return this.cancel()

View File

@ -28,7 +28,7 @@ class TomcatWebSocketServer extends EventEmitter {
let NashornWebSocketServerProxy = Java.extend(WebSocketServerProxy, { let NashornWebSocketServerProxy = Java.extend(WebSocketServerProxy, {
onOpen: (session: TomcatWebSocketSession) => { onOpen: (session: TomcatWebSocketSession) => {
let tomcatClient = new TomcatClient(this, session) let tomcatClient = new TomcatClient(this, session)
this.allClients[tomcatClient.id] = tomcatClient this.allClients[session.getId()] = tomcatClient
this.emit(ServerEvent.connect, tomcatClient) this.emit(ServerEvent.connect, tomcatClient)
}, },
onMessage: (session: TomcatWebSocketSession, message: string) => { onMessage: (session: TomcatWebSocketSession, message: string) => {