From 73db4a9169cd8db2485dd7f84ab153da7afe3dce Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Tue, 14 Jan 2020 17:44:20 +0800 Subject: [PATCH] feat: add server module Signed-off-by: MiaoWoo --- packages/api/src/interfaces/server.ts | 6 ++ packages/bukkit/src/enhance/chat.ts | 80 +++++++++++++++++++++++++++ packages/bukkit/src/index.ts | 4 +- packages/bukkit/src/server.ts | 43 ++++++++++++++ packages/sponge/src/index.ts | 4 +- packages/sponge/src/server.ts | 39 +++++++++++++ 6 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 packages/bukkit/src/enhance/chat.ts create mode 100644 packages/bukkit/src/server.ts create mode 100644 packages/sponge/src/server.ts diff --git a/packages/api/src/interfaces/server.ts b/packages/api/src/interfaces/server.ts index e1d32e1a..ae6d29bf 100644 --- a/packages/api/src/interfaces/server.ts +++ b/packages/api/src/interfaces/server.ts @@ -5,5 +5,11 @@ export namespace server { export interface Server { getVersion(): string; getPlayer(name: string): any; + getOnlinePlayers(): any[]; + getConsoleSender(): any; + getService(service: string): any; + dispatchCommand(sender: string | any, command: string): boolean; + dispatchConsoleCommand(command: string): boolean; + sendJson(sender: string | any, json: object | string): void; } } diff --git a/packages/bukkit/src/enhance/chat.ts b/packages/bukkit/src/enhance/chat.ts new file mode 100644 index 00000000..0971af74 --- /dev/null +++ b/packages/bukkit/src/enhance/chat.ts @@ -0,0 +1,80 @@ +/*global Java, base, module, exports, require*/ +var nmsChatSerializerClass; +var nmsChatSerializerMethod; +var packetTypeConstructor; +var nmsChatMessageTypeClass; +var chatMessageTypes; + +var downgrade = false; +/** + * 获取NMS版本 + */ +//@ts-ignore +var nmsVersion = org.bukkit.Bukkit.server.class.name.split('.')[3]; +/** + * 获取NMS类 + */ +function nmsCls(name) { + return base.getClass(['net.minecraft.server', nmsVersion, name].join('.')) +} + +function init() { + nmsChatSerializerClass = nmsCls(nmsVersion.split("_")[1] > 7 ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer"); + try { + nmsChatSerializerMethod = nmsChatSerializerClass.getMethod('a', base.getClass('java.lang.String')) + } catch (ex) { + nmsChatSerializerMethod = nmsChatSerializerClass.getMethod('func_150699_a', base.getClass('java.lang.String')) + } + var packetTypeClass = nmsCls("PacketPlayOutChat"); + Java.from(packetTypeClass.constructors).forEach(function(c) { + if (c.parameterTypes.length === 2) { + packetTypeConstructor = c + } + }); + nmsChatMessageTypeClass = packetTypeConstructor.parameterTypes[1]; + if (nmsChatMessageTypeClass.isEnum()) { + chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants(); + } else { + switch (nmsChatMessageTypeClass.name) { + case "int": + //@ts-ignore + nmsChatMessageTypeClass = java.lang.Integer; + break; + case "byte": + //@ts-ignore + nmsChatMessageTypeClass = java.lang.Byte; + break; + } + } +} + +function json(sender, json) { + if (downgrade) { + return '/tellraw ' + sender.name + ' ' + json + } else { + send(sender, json, 0); + return false; + } +} + +function send(sender, json, type) { + //@ts-ignore + sendPacket(sender, packetTypeConstructor.newInstance(nmsChatSerializerMethod.invoke(null, json), chatMessageTypes == null ? nmsChatMessageTypeClass.valueOf(java.lang.String.valueOf(type)) : chatMessageTypes[type])) +} + +function sendPacket(player, p) { + player.handle.playerConnection.sendPacket(p); +} + +try { + init(); +} catch (ex) { + org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`) + downgrade = true; +} + +let chat = { + json +} + +export default chat diff --git a/packages/bukkit/src/index.ts b/packages/bukkit/src/index.ts index 75e0e8fe..8bc77c48 100644 --- a/packages/bukkit/src/index.ts +++ b/packages/bukkit/src/index.ts @@ -5,6 +5,7 @@ import { DefaultContainer as container } from '@ms/container' import { BukkitConsole } from './console'; import { BukkitEvent } from './event'; +import { BukkitServer } from './server'; import { BukkitCommand } from './command'; import { BukkitTaskManager } from './task'; @@ -16,7 +17,6 @@ container.bind(server.ServerType).toConstantValue(BukkitServerType); container.bind(plugin.PluginInstance).toConstantValue(Bukkit.pluginManager.getPlugin('MiaoScript')); container.bind(event.Event).to(BukkitEvent).inSingletonScope(); +container.bind(server.Server).to(BukkitServer).inSingletonScope(); container.bind(command.Command).to(BukkitCommand).inSingletonScope(); container.bind(task.TaskManager).to(BukkitTaskManager).inSingletonScope(); - -console.debug(`Detect Bukkit Compatible set ServerType to ${BukkitServerType} ...`) diff --git a/packages/bukkit/src/server.ts b/packages/bukkit/src/server.ts new file mode 100644 index 00000000..f63abea4 --- /dev/null +++ b/packages/bukkit/src/server.ts @@ -0,0 +1,43 @@ +import { server } from '@ms/api' +import { injectable } from '@ms/container'; + +import chat from './enhance/chat' + +let Bukkit = org.bukkit.Bukkit; + +@injectable() +export class BukkitServer implements server.Server { + getPlayer(name: string) { + return Bukkit.getPlayer(name) + } + getVersion(): string { + return Bukkit.getVersion() + } + getOnlinePlayers() { + return Bukkit.getOnlinePlayers() as unknown as any[] + } + getConsoleSender() { + return Bukkit.getConsoleSender() + } + getService(service: string) { + return Bukkit.getServicesManager().getRegistration(base.getClass(service))?.getProvider() + } + dispatchCommand(sender: string | any, command: string): boolean { + if (typeof sender === 'string') { + sender = this.getPlayer(sender) + } + return Bukkit.dispatchCommand(sender, command) + } + dispatchConsoleCommand(command: string): boolean { + return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command) + } + sendJson(sender: string | any, json: object | string): void { + if (typeof sender === "string") { + sender = this.getPlayer(sender) + } + let result = chat.json(sender, json) + if (result !== false) { + this.dispatchConsoleCommand(result) + } + } +} diff --git a/packages/sponge/src/index.ts b/packages/sponge/src/index.ts index 87303566..6c19b9c9 100644 --- a/packages/sponge/src/index.ts +++ b/packages/sponge/src/index.ts @@ -5,6 +5,7 @@ import { DefaultContainer as container } from '@ms/container' import { SpongeConsole } from './console'; import { SpongeEvent } from './event'; +import { SpongeServer } from './server'; import { SpongeCommand } from './command'; import { SpongeTaskManager } from './task'; @@ -16,7 +17,6 @@ container.bind(server.ServerType).toConstantValue(SpongeServerType); container.bind(plugin.PluginInstance).toConstantValue(Sponge.getPluginManager().getPlugin('MiaoScript').orElse(null)); container.bind(event.Event).to(SpongeEvent).inSingletonScope(); +container.bind(server.Server).to(SpongeServer).inSingletonScope(); container.bind(command.Command).to(SpongeCommand).inSingletonScope(); container.bind(task.TaskManager).to(SpongeTaskManager).inSingletonScope(); - -console.debug(`Detect Sponge Compatible set ServerType to ${SpongeServerType} ...`) diff --git a/packages/sponge/src/server.ts b/packages/sponge/src/server.ts new file mode 100644 index 00000000..b448bd61 --- /dev/null +++ b/packages/sponge/src/server.ts @@ -0,0 +1,39 @@ +import { server } from '@ms/api' +import { injectable } from '@ms/container'; + +let Sponge = org.spongepowered.api.Sponge; +let TextSerializers = org.spongepowered.api.text.serializer.TextSerializers; + +@injectable() +export class SpongeServer implements server.Server { + getPlayer(name: string) { + return Sponge.getServer().getPlayer(name).orElse(null) + } + getVersion(): string { + return `${Sponge.getPlatform().getImplementation().getName()} (${Sponge.getPlatform().getImplementation().getVersion()})` + } + getOnlinePlayers() { + return Sponge.getServer().getOnlinePlayers() + } + getConsoleSender() { + return Sponge.getServer().getConsole() + } + getService(service: string) { + return Sponge.getServiceManager().provide(base.getClass(service)).orElse(null) + } + dispatchCommand(sender: string | any, command: string): boolean { + if (typeof sender === 'string') { + sender = this.getPlayer(sender) + } + return Sponge.getCommandManager().process(sender, command).getQueryResult() + } + dispatchConsoleCommand(command: string): boolean { + return Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command).getQueryResult() + } + sendJson(sender: string | any, json: string): void { + if (typeof sender === "string") { + sender = this.getPlayer(sender) + } + sender.sendMessage(TextSerializers.JSON.deserialize(json)) + } +}