152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
const fs = require('fs')
|
|
const path = require('path')
|
|
const util = require('util')
|
|
const { CommandDispatcher, builder: { LiteralArgumentBuilder: { literal }, RequiredArgumentBuilder: { argument } }, arguments: { StringArgumentType: { greedyString } }, exceptions: { CommandSyntaxException } } = require('brigadier-commands')
|
|
const CommandSource = require('../util/command/command_source')
|
|
const TextMessage = require('../util/command/text_message')
|
|
|
|
function inject (bot) {
|
|
bot.commands = {
|
|
dispatcher: new CommandDispatcher(),
|
|
add,
|
|
execute,
|
|
info,
|
|
isCommand,
|
|
loadFromDir,
|
|
isValid
|
|
}
|
|
|
|
/*
|
|
bot.on('message', (player, message) => {
|
|
if (!message.startsWith(bot.prefix)) return
|
|
|
|
function sendFeedback (message) {
|
|
bot.core.run('minecraft:tellraw @a ' + JSON.stringify(message))
|
|
}
|
|
bot.commands.execute(message.substring(bot.prefix.length), new CommandSource({ bot, player, sendFeedback }))
|
|
})
|
|
*/
|
|
|
|
function add (command) {
|
|
if (command.register) {
|
|
command.register(bot.commands.dispatcher)
|
|
return
|
|
}
|
|
|
|
if (isValid(command)) {
|
|
bot.console.warn(`Command '${command.aliases[0]}' is using the legacy command system!`)
|
|
|
|
const _execute = (c, args) => {
|
|
try {
|
|
const player = c.source.player
|
|
command.execute(bot, command.aliases[0], { UUID: player?.uuid, name: player?.username }, args)
|
|
} catch (error) {
|
|
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: error.toString(), color: 'red' }))
|
|
}
|
|
}
|
|
|
|
const requirement = source => source.permissionLevel >= command.permLevel
|
|
|
|
const node = bot.commands.dispatcher.register(
|
|
literal(command.aliases[0])
|
|
.executes(c => { _execute(c, []); return 0 })
|
|
.requires(requirement)
|
|
.then(
|
|
argument('args', greedyString())
|
|
.executes(c => { _execute(c, c.getArgument('args').split(' ')); return 0 })
|
|
)
|
|
)
|
|
for (let i = 1; i < command.aliases.length; i++) {
|
|
bot.commands.dispatcher.register(
|
|
literal(command.aliases[i])
|
|
.executes(context => { _execute([]); return 0 })
|
|
.requires(requirement)
|
|
.redirect(node)
|
|
)
|
|
}
|
|
|
|
// add metadata for help command
|
|
node.description = command.description
|
|
node.permissionLevel = command.permLevel
|
|
|
|
return
|
|
}
|
|
|
|
throw new Error('Invalid command', 'invalid_command')
|
|
}
|
|
|
|
function loadFromDir (dirpath) {
|
|
fs.readdirSync(dirpath).forEach(filename => {
|
|
const filepath = path.resolve(dirpath, filename)
|
|
if (!filepath.endsWith('js') || !fs.statSync(filepath).isFile()) return
|
|
try {
|
|
bot.commands.add(require(filepath))
|
|
} catch (error) {
|
|
bot.console.error('Error loading command ' + filepath + ': ' + util.inspect(error))
|
|
}
|
|
})
|
|
}
|
|
|
|
function info (command) {
|
|
const info = bot.commands.commands[command] ?? command
|
|
if (isValid(info)) { return info }
|
|
}
|
|
|
|
function isCommand (command) { return true }
|
|
|
|
function execute (command, source) {
|
|
try {
|
|
bot.commands.dispatcher.execute(command, source)
|
|
} catch (error) {
|
|
if (error instanceof CommandSyntaxException) {
|
|
const text = (error._message instanceof TextMessage) ? error._message.text : error._message.getString()
|
|
source.sendError(text)
|
|
const context = getContext(error)
|
|
if (context) source.sendError(context)
|
|
|
|
return
|
|
}
|
|
|
|
source.sendError({ translate: 'command.failed', hoverEvent: { action: 'show_text', contents: error.stack } })
|
|
}
|
|
}
|
|
|
|
function getContext (error) {
|
|
const _cursor = error.cursor
|
|
const input = error.input
|
|
|
|
if (input == null || _cursor < 0) {
|
|
return null
|
|
}
|
|
|
|
const text = [{ text: '', color: 'gray', clickEvent: { action: 'suggest_command', value: bot.prefix + input } }]
|
|
|
|
const cursor = Math.min(input.length, _cursor)
|
|
|
|
if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) {
|
|
text.push('...')
|
|
}
|
|
|
|
text.push(
|
|
input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor),
|
|
{ text: input.substring(cursor), color: 'red', underline: true },
|
|
{ translate: 'command.context.here', color: 'red', italic: true }
|
|
)
|
|
|
|
return text
|
|
}
|
|
}
|
|
|
|
function isValid (command) {
|
|
return command != null &&
|
|
typeof command.execute === 'function' &&
|
|
typeof command.name === 'string' &&
|
|
typeof command.description === 'string' &&
|
|
Array.isArray(command.usages) &&
|
|
Array.isArray(command.aliases) &&
|
|
typeof command.enabled === 'boolean' &&
|
|
command.aliases.length > 0 &&
|
|
typeof command.permLevel === 'number'
|
|
}
|
|
|
|
module.exports = inject
|