const { literal, argument, string, DynamicCommandExceptionType } = require('brigadier-commands') const { json } = require('../util/command/argument/json') const TextMessage = require('../util/command/text_message') const mc = require('minecraft-protocol') const UNKNOWN_CLIENT_ERROR = new DynamicCommandExceptionType(string => new TextMessage(['Unknown client: ', string])) module.exports = { clients: [], create () { return Object.create(this) }, register (dispatcher) { const node = dispatcher.register( literal('client') .then( literal('create') .then( argument('options', json()) .executes(this.createCommand.bind(this)) ) ) .then( literal('write') .then( argument('client', string()) .then( argument('name', string()) .then( argument('data', json()) .executes(this.writeCommand.bind(this)) ) ) ) ) .then( literal('end') .then( argument('client', string()) .executes(this.endCommand.bind(this)) ) ) .then( literal('list') .executes(this.listCommand.bind(this)) ) ) node.description = 'Creates and manages this.clients using minecraft-protocol' node.permissionLevel = 0 }, cleanup () { this.clients.forEach(client => client.end()) }, createCommand (context) { const source = context.source const bot = source.bot const options = { host: bot.host, port: bot.port, ...context.getArgument('options') } const client = mc.createClient(options) const idx = this.clients.length client.once('login', () => source.sendFeedback([{ text: client.username, ...bot.styles.primary }, ' logged in']), false) client.on('end', () => { this.clients.splice(idx, 1) source.sendFeedback([{ text: client.username, ...bot.styles.primary }, ' ended'], false) }) client.on('error', (err) => bot.tellraw({ text: err.toString(), ...bot.styles.error }, '@a')) this.clients.push(client) }, writeCommand (context) { const idx = this.findClientIdxByString(context.getArgument('client')) const name = context.getArgument('name') const data = context.getArgument('data') this.clients[idx].write(name, data) }, endCommand (context) { const source = context.source const idx = this.findClientIdxByString(context.getArgument('client')) this.clients[idx].end() this.clients.splice(idx, 1) }, listCommand (context) { const source = context.source const bot = source.bot const list = [] for (let i = 0; i < this.clients.length; i++) { const client = this.clients[i] if (i !== 0) list.push(', ') list.push(client.username) } source.sendFeedback([{ text: 'Clients: ', ...bot.styles.primary }, list], false) }, findClientIdxByString (string) { let idx = Number(string) if (!this.clients[idx]) this.clients.forEach((client, cidx) => { if (client.username === string) idx = cidx }) if (!this.clients[idx]) throw UNKNOWN_CLIENT_ERROR.create(string) return idx } }