feat: impl bukkit chat api

Signed-off-by: MiaoWoo <admin@yumc.pw>
MiaoWoo 2020-07-28 09:39:52 +08:00
parent 91d2d836fc
commit 7dcc5ed45a
3 changed files with 62 additions and 56 deletions

View File

@ -0,0 +1,16 @@
import { chat } from '@ccms/api'
import { provideSingleton } from '@ccms/container'
import bukkitChat from './enhance/chat'
@provideSingleton(chat.Chat)
export class BukkitChat extends chat.Chat {
sendMessage(sender: any, message: string) {
bukkitChat.send(sender, { text: message }, 0)
}
sendActionBar(sender: any, message: string) {
bukkitChat.send(sender, { text: message }, 2)
}
sendTitle(sender: any, title: string, subtitle: string = '', fadeIn: number = 1, time: number = 5, fadeOut: number = 1) {
sender.sendTitle(title, subtitle, fadeIn, time, fadeOut)
}
}

View File

@ -1,29 +1,28 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
var nmsChatSerializerClass; let ChatSerializer: any
var nmsChatSerializerMethod; let nmsChatSerializerMethodName: string
var packetTypeConstructor; let PacketPlayOutChat: any
var nmsChatMessageTypeClass; let chatMessageTypes: any
var chatMessageTypes;
var RemapUtils; let RemapUtils: any
var playerConnectionFieldName; let playerConnectionFieldName: string
var sendPacketMethod; let sendPacketMethodName: string
var downgrade = false; let downgrade = false
/** /**
* NMS * NMS
*/ */
//@ts-ignore //@ts-ignore
var nmsVersion = org.bukkit.Bukkit.server.class.name.split('.')[3]; let nmsVersion = org.bukkit.Bukkit.server.class.name.split('.')[3]
/** /**
* NMS * NMS
*/ */
function nmsCls(name) { function nmsCls(name: string) {
return base.getClass(['net.minecraft.server', nmsVersion, name].join('.')) return base.getClass(['net.minecraft.server', nmsVersion, name].join('.'))
} }
function remapMethod(clazz: any, origin: string, test: string, params) { function remapMethod(clazz: any, origin: string, test: string, params: any) {
try { try {
return clazz.getMethod(origin, params) return clazz.getMethod(origin, params)
} catch (ex) { } catch (ex) {
@ -49,66 +48,57 @@ function remapFieldName(clazz: any, origin: string, test: string) {
function init() { function init() {
try { try {
RemapUtils = Java.type('catserver.server.remapper.RemapUtils'); RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
} catch (ex) { } catch (ex) {
} }
nmsChatSerializerClass = nmsCls(nmsVersion.split("_")[1] > 7 ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer"); let nmsChatSerializerClass = nmsCls(nmsVersion.split("_")[1] > 7 ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer")
nmsChatSerializerMethod = remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String')) let nmsChatSerializerMethod = remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
var packetTypeClass = nmsCls("PacketPlayOutChat"); nmsChatSerializerMethodName = nmsChatSerializerMethod.getName()
ChatSerializer = Java.type(nmsChatSerializerClass.getName())
let packetTypeClass = nmsCls("PacketPlayOutChat")
PacketPlayOutChat = Java.type(packetTypeClass.getName())
let packetTypeConstructor: { parameterTypes: any[] }
Java.from(packetTypeClass.constructors).forEach(function (c) { Java.from(packetTypeClass.constructors).forEach(function (c) {
if (c.parameterTypes.length === 2) { if (c.parameterTypes.length === 2) {
packetTypeConstructor = c packetTypeConstructor = c
} }
}); })
nmsChatMessageTypeClass = packetTypeConstructor.parameterTypes[1]; let nmsChatMessageTypeClass = packetTypeConstructor.parameterTypes[1]
if (nmsChatMessageTypeClass.isEnum()) { if (nmsChatMessageTypeClass.isEnum()) {
chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants(); 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;
} }
} let playerConnectionField = remapFieldName(nmsCls('EntityPlayer'), 'playerConnection', 'field_71135_a')
var entityPlayerClass = nmsCls('EntityPlayer');
var packetClass = nmsCls('Packet');
var playerConnectionField = remapFieldName(entityPlayerClass, 'playerConnection', 'field_71135_a')
playerConnectionFieldName = playerConnectionField.getName() playerConnectionFieldName = playerConnectionField.getName()
sendPacketMethod = remapMethod(playerConnectionField.getType(), 'sendPacket', 'func_179290_a', packetClass) sendPacketMethodName = remapMethod(playerConnectionField.getType(), 'sendPacket', 'func_179290_a', nmsCls('Packet')).getName()
} }
function json(sender, json) { function json(sender: { name: string }, json: string) {
if (downgrade) { if (downgrade) {
return '/tellraw ' + sender.name + ' ' + json return '/tellraw ' + sender.name + ' ' + json
} else { } else {
send(sender, json, 0); send(sender, json, 0)
return false; return false
} }
} }
function send(sender, json, type) { function send(sender: any, json: any, type: number) {
//@ts-ignore sendPacket(sender, new PacketPlayOutChat(ChatSerializer[nmsChatSerializerMethodName](json), chatMessageTypes == null ? type : chatMessageTypes[type]))
sendPacket(sender, packetTypeConstructor.newInstance(nmsChatSerializerMethod.invoke(null, json), chatMessageTypes == null ? nmsChatMessageTypeClass.valueOf(java.lang.String.valueOf(type)) : chatMessageTypes[type]))
} }
function sendPacket(player, p) { function sendPacket(player: { handle: { [x: string]: { [x: string]: (arg0: any) => void } } }, p: any) {
sendPacketMethod.invoke(player.handle[playerConnectionFieldName], p) player.handle[playerConnectionFieldName][sendPacketMethodName](p)
} }
try { try {
init(); init()
} catch (ex) { } catch (ex) {
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...`)
downgrade = true; downgrade = true
} }
let chat = { let chat = {
json json,
send
} }
export default chat export default chat

View File

@ -1,18 +1,18 @@
import { server, constants } from '@ccms/api' import { server, constants } 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' import chat from './enhance/chat'
let Bukkit = org.bukkit.Bukkit; let Bukkit = org.bukkit.Bukkit
@provideSingleton(server.Server) @provideSingleton(server.Server)
export class BukkitServer extends server.ReflectServer { export class BukkitServer extends server.ReflectServer {
private pluginsFolder: string; private pluginsFolder: string
constructor() { constructor() {
super(); super()
this.pluginsFolder = Bukkit.getUpdateFolderFile().getParentFile().getCanonicalPath(); this.pluginsFolder = Bukkit.getUpdateFolderFile().getParentFile().getCanonicalPath()
} }
getPlayer(name: string) { getPlayer(name: string) {
@ -40,25 +40,25 @@ export class BukkitServer extends server.ReflectServer {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command) return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command)
} }
getPluginsFolder(): string { getPluginsFolder(): string {
return this.pluginsFolder; return this.pluginsFolder
} }
getNativePluginManager() { getNativePluginManager() {
return Bukkit.getPluginManager() as any; return Bukkit.getPluginManager() as any
} }
getDedicatedServer() { getDedicatedServer() {
return reflect.on(Bukkit.getServer()).get('console').get() return reflect.on(Bukkit.getServer()).get('console').get()
} }
getNettyPipeline() { getNettyPipeline() {
return this.pipeline; return this.pipeline
} }
getRootLogger() { getRootLogger() {
return this.rootLogger; return this.rootLogger
} }
sendJson(sender: string | any, json: object | string): void { sendJson(sender: string | any, json: object | string): void {
if (typeof sender === "string") { if (typeof sender === "string") {
sender = this.getPlayer(sender) sender = this.getPlayer(sender)
} }
let result = chat.json(sender, json) let result = chat.json(sender, typeof json == "string" ? json : JSON.stringify(json))
if (result !== false) { if (result !== false) {
this.dispatchConsoleCommand(result) this.dispatchConsoleCommand(result)
} }