chipmunkbot3/plugins/commands.js

116 lines
3.2 KiB
JavaScript

const fs = require('fs')
const path = require('path')
const { CommandDispatcher, literal, argument, greedyString, 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')
let commands
function loadCommands () {
commands = []
for (const filename of fs.readdirSync(path.resolve(__dirname, '..', 'commands'))) {
const filepath = path.resolve(__dirname, '..', 'commands', filename)
if (!filepath.endsWith('.js') || !fs.statSync(filepath).isFile()) return
try {
delete require.cache[require.resolve(filepath)]
commands.push(require(filepath))
} catch (error) {
console.error('Error loading command', filepath, ':', error)
}
}
}
loadCommands()
function inject (bot) {
bot.commands = {
dispatcher: null,
execute,
reload,
}
bot.on('message', ({ sender, plain }) => {
if (!plain.startsWith(bot.prefix)) return
function sendFeedback (message) {
bot.tellraw(message, '@a')
}
const displayName = {
insertion: sender.username,
clickEvent: { action: 'suggest_command', value: `/tell ${sender.username} ` },
hoverEvent: {
action: 'show_entity',
contents: {
type: 'minecraft:player',
id: sender.uuid,
name: sender.username
}
},
text: sender.username
}
bot.commands.execute(plain.substring(bot.prefix.length), new CommandSource({ bot, player: sender, sendFeedback, displayName }))
})
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 reload (loadFiles = true) {
bot.commands.dispatcher = new CommandDispatcher()
if (loadFiles) loadCommands()
for (const command of commands) {
try {
command.register(bot.commands.dispatcher)
} catch (error) {
console.error('Unable to register command:', error)
}
}
bot.emit('commands_loaded')
}
reload(false)
}
module.exports = inject