From 8d81d6938e6ef4abc99a7653a586ff3fb70019cf Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Wed, 19 Feb 2020 18:59:02 +0800 Subject: [PATCH] feat: add mc console client package Signed-off-by: MiaoWoo --- packages/client/package.json | 33 ++++++++++++ packages/client/src/color.ts | 97 +++++++++++++++++++++++++++++++++++ packages/client/src/forge.ts | 14 +++++ packages/client/src/index.ts | 53 +++++++++++++++++++ packages/client/tsconfig.json | 7 +++ 5 files changed, 204 insertions(+) create mode 100644 packages/client/package.json create mode 100644 packages/client/src/color.ts create mode 100644 packages/client/src/forge.ts create mode 100644 packages/client/src/index.ts create mode 100644 packages/client/tsconfig.json diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 00000000..e3317e8b --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,33 @@ +{ + "name": "@ms/client", + "version": "0.1.0", + "description": "MiaoScript client package", + "keywords": [ + "miaoscript", + "minecraft", + "bukkit", + "sponge" + ], + "author": "MiaoWoo ", + "homepage": "https://github.com/circlecloud/ms.git", + "license": "ISC", + "main": "dist/index.js", + "publishConfig": { + "registry": "https://repo.yumc.pw/repository/npm-hosted/" + }, + "scripts": { + "dev": "ts-node-dev --respawn --debounce=1500 src/index.ts", + "clean": "rimraf dist", + "watch": "tsc --watch", + "build": "yarn clean && tsc", + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "dependencies": { + "minecraft-protocol": "^1.11.0" + }, + "devDependencies": { + "@nestjs/cli": "^6.14.2", + "rimraf": "^3.0.2", + "typescript": "^3.7.5" + } +} \ No newline at end of file diff --git a/packages/client/src/color.ts b/packages/client/src/color.ts new file mode 100644 index 00000000..848d2ac2 --- /dev/null +++ b/packages/client/src/color.ts @@ -0,0 +1,97 @@ +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) + } + return mcColor2ANSI(json2text(input) + '§r') +} + +export { + json2text, + mcColor2ANSI, + $ +} \ No newline at end of file diff --git a/packages/client/src/forge.ts b/packages/client/src/forge.ts new file mode 100644 index 00000000..422ff261 --- /dev/null +++ b/packages/client/src/forge.ts @@ -0,0 +1,14 @@ +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) + }); + } + }); +} \ No newline at end of file diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts new file mode 100644 index 00000000..a02da0f2 --- /dev/null +++ b/packages/client/src/index.ts @@ -0,0 +1,53 @@ +import { createInterface } from 'readline' +import { createClient } from 'minecraft-protocol' + +import { $ } from './color' +import { attachForge } from './forge' + +let client = createClient({ + version: '1.12.2', + host: '192.168.2.5', + port: 25577, + username: process.argv[2] || 'Mr_jtb', + skipValidation: true +}) + +attachForge(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[3] + if (newState == "play" && targetServer) { + setTimeout(() => { + client.write('chat', { + message: '/server ' + targetServer + }) + }, 3000) + } +}) + +const rl = createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false +}) + +rl.on('line', function(line) { + if (line === '') { + return + } else if (line === '/quit') { + console.info('Disconnected') + client.end("") + return + } else if (line === '/end') { + console.info('Forcibly ended client') + process.exit(0) + } + client.write('chat', { message: line }) +}) diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 00000000..7aae5d2b --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "src", + "outDir": "dist" + } +} \ No newline at end of file