Chipmunk
5f3560910b
not sure if it's better or worse now. also, i have tried to optimize color codes, but this optimization seems unreliable (i might fix or remove it in the future)
151 lines
4.6 KiB
JavaScript
151 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')
|
|
const colorCodeStringify = require('../util/chat/stringify/color_code')
|
|
|
|
function inject (bot) {
|
|
bot.commands = {
|
|
dispatcher: new CommandDispatcher(),
|
|
add,
|
|
execute,
|
|
info,
|
|
isCommand,
|
|
loadFromDir,
|
|
isValid
|
|
}
|
|
|
|
bot.on('message', ({ sender, plain }) => {
|
|
if (!plain.startsWith(bot.prefix)) return
|
|
|
|
function sendFeedback (message) {
|
|
bot.tellraw(message, '@a')
|
|
}
|
|
bot.commands.execute(plain.substring(bot.prefix.length), new CommandSource({ bot, player: sender, 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
|