132 lines
3.9 KiB
JavaScript
132 lines
3.9 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()
|
|
|
|
const patchedExecuteSource = CommandDispatcher.prototype.execute
|
|
.toString()
|
|
.replace('context.command(', 'await context.command(')
|
|
const patchedExecute = eval(`const { ParseResults, StringReader } = require('brigadier-commands'); ({ async ${patchedExecuteSource} })`).execute
|
|
|
|
function inject (bot, options) {
|
|
bot.commands = {
|
|
dispatcher: null,
|
|
execute,
|
|
reload,
|
|
prefixes: options.prefixes ?? ['default.']
|
|
}
|
|
|
|
let cleanups = []
|
|
|
|
bot.on('message', ({ sender, plain }) => {
|
|
const prefix = bot.commands.prefixes.find(prefix => plain.startsWith(prefix))
|
|
if (!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(prefix.length), new CommandSource({ bot, player: sender, sendFeedback, displayName }))
|
|
})
|
|
|
|
async function execute (command, source) {
|
|
try {
|
|
return await patchedExecute.call(bot.commands.dispatcher, 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 1
|
|
}
|
|
|
|
source.sendError({ translate: 'command.failed', hoverEvent: { action: 'show_text', contents: error.stack } })
|
|
return 1
|
|
}
|
|
}
|
|
|
|
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) {
|
|
for (const cleanup of cleanups) cleanup()
|
|
if (loadFiles) loadCommands()
|
|
|
|
bot.commands.dispatcher = new CommandDispatcher()
|
|
cleanups = []
|
|
|
|
for (let command of commands) {
|
|
try {
|
|
if (command.create) command = command.create()
|
|
if (command.cleanup) cleanups.push(() => command.cleanup())
|
|
|
|
command.register(bot.commands.dispatcher, { bot })
|
|
} catch (error) {
|
|
console.error('Unable to register command:', error)
|
|
}
|
|
}
|
|
|
|
bot.emit('commands_loaded')
|
|
}
|
|
reload(false)
|
|
}
|
|
|
|
module.exports = inject
|