Compare commits

...

1 commit

Author SHA1 Message Date
4e1855ce1d Push older files 2023-06-26 23:26:15 -04:00
118 changed files with 634 additions and 12472 deletions

View file

@ -1,2 +0,0 @@
# chipmunkbot-archive
Archive of ChipmunkBot, a [kaboom](https://kaboom.pw) bot from 2022 (before the rewrite). The code should run with all modules installed, however, continue at your own risk, as the bot has a (sandboxed) public eval command, the security of which cannot be guaranteed. The bot's current chat parser is known to be broken on modern minecraft servers.

158
bot.js
View file

@ -1,139 +1,65 @@
const mc = require('minecraft-protocol')
const { states } = mc
const { EventEmitter } = require('events')
const parseText = require('./util/text_parser.js')
const fs = require('fs')
const path = require('path')
const randomUsername = require('./util/random-username.js')
function createBot (options = {}) {
// defaults
options.username ??= 'Bot'
options.username = options.username ?? 'Bot'
//options.password = options.password ?? null
options.prefix ??= '!'
options.isBukkit ??= false
options.isKaboom ??= false
options.isScissors ??= false
options.prefix = options.prefix ?? '!'
options.brand = options.brand ?? 'vanilla' //found that mineflayer has this so i added it here lol
options.colors = options.colors ?? { primary: 'white', secondary: 'gray', error: 'red' }
options.autoReconnect = options.autoReconnect ?? true
options.randomizeUsername = options.randomizeUsername ?? true;
if (options.randomizeUsername)
options.username += `§${String.fromCharCode(Math.floor(Math.random() * 65535))}`
options.plugins ??= {}
fs.readdirSync(
'plugins'
).forEach(filename => { // populate plugins array
if (typeof require.extensions[path.extname(filename)] && options.plugins[filename] == null) {
options.plugins[filename] = require(path.resolve('plugins', filename))
}
})
const plugins = []
Object.keys(options.plugins).forEach((key) => {
const plugin = options.plugins[key]
if (plugin) plugins.push(plugin)
})
let bot = new EventEmitter()
options.colors ??= {}
options.colors.primary ??= 'white'
options.colors.secondary ??= 'green'
options.autoReconnect ??= false
options.autoReconnectDelay ??= 1000
options.randomizeUsername ??= false
options['online-mode'] ??= {}
options['online-mode'].enabled ??= false
options['online-mode'].username ??= null
options['online-mode'].password ??= null
options['online-mode'].auth ??= 'mojang'
const clientOptions = { // TODO: More options
connect: options.connect,
host: options.server.host,
port: options.server.port,
version: options.version,
username: options['online-mode'].enabled ? options['online-mode'].username : options.username,
password: options['online-mode'].enabled ? options['online-mode'].username : null,
auth: options['online-mode'].enabled ? options['online-mode'].auth : null
}
if (options.randomizeUsername) {
clientOptions.username += randomUsername()
}
// actually create the bot
const bot = new EventEmitter()
bot.plugins = plugins
bot.loadPlugin = loadPlugin
// add some properties to the bot
bot.server = options.server
/* bot._client.on('set_protocol', (packet) => {
bot.host = packet.serverHost
bot.port = packet.serverPort
}) */
bot._client = options.client ?? mc.createClient(options)
//bot.host = function () { return bot._client.host }
//bot.username = function () { return bot._client.username }
//bot.uuid = function () { return bot._client.uuid }
bot.prefix = options.prefix
bot.colors = options.colors
bot.autoReconnect = options.autoReconnect
bot.randomizeUsername = options.randomizeUsername
bot['online-mode'] = options['online-mode']
// set the client and add listeners
bot.on('set_client', (client) => {
client.on('connect', () => bot.emit('connect'))
client.on('error', (err) => bot.emit('error', err))
bot.disconnect = reason => bot._client.end(reason)
bot.end = reason => {
bot.autoReconnect = false
bot.disconnect()
}
client.on('end', (reason) => {
bot.loggedIn = false
bot.emit('disconnect', reason)
// auto reconnect
if (bot.autoReconnect) {
setTimeout(() => {
if (bot.randomizeUsername && !bot['online-mode'].enabled) clientOptions.username = randomUsername()
bot._client.on('connect', () => bot.emit('connect'))
bot._client = mc.createClient(clientOptions)
bot.emit('set_client', bot._client)
}, options.autoReconnectDelay)
} else {
bot._client.on('error', (err) => bot.emit('error', err))
bot.on('error', () => {}) // idc about errors lol
bot.end = () => bot._client.end()
bot._client.on('end', (reason) => {
bot.emit('end', reason)
setTimeout(() => bot = createBot(options), 6400)
})
//amogus
bot._client.on('login', () => bot.emit('login'))
bot.position = { x: null, y: null, z: null } //to prevent errors i guess
bot._client.on('position', (position) => bot.position = position)
bot.sendChat = (message) => bot._client.write('chat', { message })
const plugins = []
fs.readdirSync(
path.join(__dirname, 'plugins')
).forEach((file) => { // populate plugins array
if (file.endsWith(".js")) {
plugins.push(path.join(__dirname, 'plugins', file));
}
})
// more event listeners
bot._client.on('state', state => {
bot.state = state
bot.emit('state', state)
})
bot._client.on('login', data => bot.emit('login', data))
// plugin injection
bot.plugins.forEach(plugin => {
if (typeof plugin.client === 'function') plugin.client(bot, options)
})
})
bot._client = options.client ?? mc.createClient(clientOptions)
bot.emit('set_client', bot._client)
bot.on('login', () => {
bot.username = bot._client.username
bot.uuid = bot._client.uuid
})
bot.plugins.forEach(plugin => {
if (typeof plugin.bot === 'function') plugin.bot(bot, options)
})
function loadPlugin (plugin) {
plugins.forEach((plugin) => {
try {
if (typeof plugin.bot === 'function') plugin.bot(bot, options)
if (typeof plugin.client === 'function') plugin.client(bot, options)
bot.plugins.push(plugin)
} catch (err) {
require(plugin)(bot)
} catch (e) {
console.log(`Error loading ${plugin}:`)
console.log(err)
console.log(require('util').inspect(e))
}
}
return bot
})
}
module.exports = createBot

View file

@ -1,17 +1,19 @@
const fs = require('fs')
const path = require('path')
const cperms = require('./cperms2.js')
const cperms = require('./cperms.js')
let commands = {}
commands = {}
function addCommand (command) {
if (!isValid(command)) throw new Error(`Command ${command} is invalid.`)
if (!isValid(command))
return//throw new Error(`Command ${command} is invalid.`)
if (commands[command] == null) { commands[command] = command }
if (commands[command] == null)
commands[command] = command
command.aliases.forEach((alias) => {
alias = alias.toLowerCase()
if (commands[alias] == null) commands[alias] = command
if (commands[alias] == null)
commands[alias] = command
})
}
@ -19,7 +21,7 @@ function load () {
fs.readdirSync(
path.join(__dirname, 'commands')
).forEach((file) => {
if (file.endsWith('.js')) {
if (file.endsWith(".js")) {
const command = path.join(__dirname, 'commands', file)
try {
const cmd = require(command)
@ -32,44 +34,29 @@ function load () {
})
}
function reload () {
try {
Object.keys(commands).forEach(key => {
const command = commands[key]
delete require.cache[command.path]
})
} catch (err) { }
commands = {}
load()
}
function execute (bot, command, player, args, ...custom) {
function execute (bot, command, entity, args, ...custom) {
const cmd = info(command)
if (!cmd.enabled) { return bot.core.run(`/bcraw &cThe command ${bot.prefix}${command} is disabled.`) }
if (!cmd.enabled)
return bot.core.run(`/bcraw &cThe command ${bot.prefix}${command} is disabled.`)
if (cmd.permLevel > 0) {
if (args.length < 1) {
bot.core.run('/bcraw &cYou must provide a code to run this command.')
return
}
if (args.length < 1)
return bot.core.run(`/bcraw &cYou must provide a code to run this command.`)
const code = args.splice(-1, 1)[0].replace(/\u00a7.?/g, '')
const code = parseFloat(args.splice(-1, 1)[0].replace(/§./g, ''))
if (!cperms.validate(cmd.permLevel, player.name, code)) {
bot.core.run(`/tellraw @a ${JSON.stringify([
if (!cperms.validate(cmd.permLevel, code))
return bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: `Invalid code: ${code}.`, color: bot.colors.error }
])}`)
return
}
}
try {
return cmd.execute(bot, command, player, args, module.exports, ...custom)
} catch (err) {
return cmd.execute(bot, command, entity, args, module.exports, ...custom)
} catch (e) {
console.log(`Error executing command ${command}:`)
console.log(err)
bot.core.run(`/tellraw @a ${JSON.stringify({ text: err.message, color: bot.colors.error })}`)
console.log(require('util').inspect(e))
}
}
@ -86,11 +73,11 @@ function isValid (command) {
typeof command.execute === 'function' &&
typeof command.name === 'string' &&
typeof command.description === 'string' &&
Array.isArray(command.usages) &&
Array.isArray(command.aliases) &&
typeof command.usage === 'string' &&
typeof command.enabled === 'boolean' &&
Array.isArray(command.aliases) &&
command.aliases.length > 0 &&
typeof command.permLevel === 'number'
}
module.exports = { addCommand, load, reload, execute, info, isCommand, isValid, commands }
module.exports = { addCommand, load, execute, info, isCommand, isValid, commands }

View file

@ -1,16 +0,0 @@
const name = '_eval'
const description = 'disabled command, ignore'
const usages = ['<code...>']
const aliases = ['_eval']
const enabled = false
const permLevel = 2
const { inspect } = require('util')
function execute (bot, cmd, player, args, handler) {
const result = eval(args.join(' ').replace(/\xa7.?/g, ''))
console.log(inspect(result)) // bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: inspect(result), color: bot.colors.primary }))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,13 +0,0 @@
const name = 'actionbar'
const description = 'exists for some reason'
const usages = ['<message...>']
const aliases = ['actionbar']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
const text = args.join(' ')
bot.core.run('minecraft:title @a actionbar ' + JSON.stringify({ text }))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,36 +0,0 @@
const name = 'antitnt'
const description = 'Prevents explosions'
const usages = [
'on',
'off'
]
const aliases = ['antitnt', 'antiexplosion']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
function sendState () {
bot.tellraw([{ text: 'antiTNT is now ', color: bot.colors.primary }, { text: bot.antiTNT.enabled ? 'on' : 'off', color: bot.colors.secondary }])
}
const subCommand = args.shift()
if (subCommand === undefined) {
throw new Error('ok')
return
}
switch (subCommand.toLowerCase()) {
case 'on':
bot.antiTNT.enabled = true
sendState()
break
case 'off':
bot.antiTNT.enabled = false
sendState()
break
default:
throw new Error('ok')
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,23 +0,0 @@
const name = 'bruhify'
const description = 'recyclebot'
const usages = ['<text>']
const aliases = ['bruhify']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
if (args[0] === 'format') {
args.shift()
const code = args.join(' ').replace(/\xa7.?/g, '')
const format = code ? bot.eval(code) : bot.bruhify._format
if (typeof format !== 'function') throw new TypeError('format must be a function')
bot.bruhify.format = format
return
}
bot.bruhify.text = args.join(' ').replace(/\xa7.?/g, '')
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,23 +0,0 @@
const name = 'bruhify'
const description = 'recyclebot'
const usages = ['<text>']
const aliases = ['bruhify']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
if (args[0] === 'format') {
args.shift()
const code = args.join(' ').replace(/\xa7.?/g, '')
const format = code ? bot.eval(code) : bot.bruhify._format
if (typeof format !== 'function') throw new TypeError('format must be a function')
bot.bruhify.format = format
return
}
bot.bruhify.text = args.join(' ').replace(/\xa7.?/g, '')
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,13 +1,13 @@
const name = 'cb'
const description = 'Runs a command in the command core'
const usages = ['<command...>']
const usage = '{prefix}cb <command...>'
const aliases = ['cb']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
function execute (bot, cmd, entity, args, handler) {
bot.core.run(args.join(' '))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,19 +0,0 @@
const name = 'clearchat'
const description = 'Clears the chat'
const usages = ['[selector]']
const aliases = ['clearchat', 'cc']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
const text = []
while (text.length < 100) {
text.push('\n')
}
text.push({ text: 'The chat has been cleared', color: 'dark_green' })
bot.core.run(`/minecraft:tellraw ${args.join(' ') || '@a'} ${JSON.stringify(text)}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,13 +0,0 @@
const name = 'clearchatqueue'
const description = 'Clears the chat queue of the bot'
const usages = []
const aliases = ['clearchatqueue', 'ccq']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
bot.chat.queue.splice(0, bot.chat.queue)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,53 +0,0 @@
const name = 'client'
const description = 'Creates and manages clients using minecraft-protocol.'
const usages = ['create <options (json)>', 'end <i>', 'write <i> <name> <data (json)>', 'list']
const aliases = ['client']
const enabled = true
const permLevel = 0
const mc = require('minecraft-protocol')
const clients = []
const sectionRegex = /\u00a7.?/g
const util = require('util')
function execute (bot, cmd, player, args, handler) {
const subCmd = args.shift()
let client, i, name, data
switch (subCmd) {
case 'create':
const options = JSON.parse(args.join(' ').replace(sectionRegex, ''))
options.host = bot.server.host
options.port = bot.server.port
client = mc.createClient(options)
i = clients.length
client.on('login', () => bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: client.username + '\u00a7r logged in.', color: bot.colors.primary })))
client.on('end', () => {
clients.splice(i, 1)
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: client.username + '\u00a7r ended.', color: bot.colors.primary }))
})
client.on('error', (err) => bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: util.inspect(err).replace(/\n.*/g, ''), color: bot.colors.error })))
clients.push(client)
break
case 'end':
i = parseInt(args.join(' '))
clients[i].end()
clients.splice(i, 1)
break
case 'write':
i = parseInt(args.shift())
name = args.shift()
data = JSON.parse(args.join(' ').replace(sectionRegex, ''))
clients[i].write(name, data)
break
case 'list':
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: 'Clients: ' + clients.map(client => client.username).join('\u00a7r, '), color: bot.colors.primary }))
break
default:
throw new Error('Invalid or missing argument')
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,54 +0,0 @@
const name = 'cloop'
const description = 'Loops commands'
const usages = [
'add <interval> <command...>',
'remove <index>',
'list'
]
const aliases = ['cloop']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args, handler) {
const subCommand = args.shift()
let interval, command, i, msg
switch (subCommand) {
case 'add':
interval = Number(args.shift())
if (Number.isNaN(interval)) throw new Error('Interval must be a number')
command = args.join(' ').replace(/xa7.?/g, '')
bot.cloops.push({ command, interval })
bot.tellraw([
{ text: 'Added command ', color: bot.colors.primary },
{ text: command, color: bot.colors.secondary },
' to cloops.'
])
break
case 'remove':
i = Number(args.shift())
if (Number.isNaN(i)) throw new Error('Index must be a number')
bot.cloops.splice(i, 1)
bot.tellraw([
{ text: 'Removed cloop ', color: bot.colors.primary },
{ text: i, color: bot.colors.secondary }
])
break
case 'list':
msg = [{ text: 'Cloops: \n', color: bot.colors.primary }]
for (const i in bot.cloops) {
msg.push({ text: `${i}: ` })
msg.push({ text: `${bot.cloops[i].command}\n`, color: bot.colors.secondary })
}
bot.tellraw(msg)
break
default:
throw new SyntaxError('Invalid or missing argument' + (subCommand ? ': ' + subCommand : ''))
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,42 +0,0 @@
const name = 'color'
const description = 'Changes your color (useless)'
const usages = ['<color>']
const aliases = ['color']
const enabled = true
const permLevel = 0
const colors = {
black: '§0',
dark_blue: '§1',
dark_green: '§2',
dark_aqua: '§3',
dark_red: '§4',
dark_purple: '§5',
gold: '§6',
gray: '§7',
dark_gray: '§8',
blue: '§9',
green: '§a',
aqua: '§b',
red: '§c',
light_purple: '§d',
yellow: '§e',
white: '§f',
reset: '§r'
}
function execute (bot, cmd, player, args) {
const { Team } = bot
const color = args.join(' ')
if (!(color in colors)) throw new Error('Invalid color: ' + color)
new Team(`chipmunk_${player.UUID}`)
.setColor(color)
.setSeeFriendlyInvisibles(false)
.add(player.UUID)
bot.core.run(`essentials:nick ${player.UUID} ${colors[color]}${player.name}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,13 +0,0 @@
const name = 'colortest'
const description = 'Sends the arguments with \\u00a7 escaped'
const usages = ['<message...>']
const aliases = ['colortest']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
bot.tellraw({ text: args.join(' ').replace(/\xa7/g, '\\u00a7') }, player.UUID)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,16 +0,0 @@
const name = 'consoleserver'
const description = 'sets the console server'
const usages = ['<host...>']
const aliases = ['consoleserver', 'consolesvr', 'csvr']
const enabled = false
const permLevel = 0
function execute (bot, cmd, player, args) {
const host = args.join(' ')
bot.getBots().forEach(bot => {
bot.console.host = host
})
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,39 +1,26 @@
const name = 'credits'
const description = 'Shows bot credits.'
const usages = []
const usage = '{prefix}credits'
const aliases = ['credits']
const enabled = true
const permLevel = 0
const { dependencies } = require('./../package.json')
function execute(bot, cmd, entity, args, handler) {
bot.tellraw([
{ text: '', color: 'gray' },
bot.core.run(`/tellraw @a ${JSON.stringify([
'',
{ text: 'Credits\n', color: bot.colors.primary, bold: true },
{ text: '_ChipMC_', color: 'blue' },
' - creating the bot\n',
'created the bot.\n',
{ text: 'hhhzzzsss', color: 'aqua', bold: true },
' - creating the original midi converter\n',
' and ',
{ text: 'eva', color: 'light_purple', italic: true },
' - creating the original midi converter\n',
' created the midi converter.\n'//,
{ text: 'ma', color: 'aqua' },
{ text: 'ni', color: 'light_purple' },
{ text: 'a', color: 'white' },
{ text: 'pl', color: 'light_purple' },
{ text: 'ay', color: 'aqua' },
' - creating the original image converter',
{ text: 'ayunami2000', color: 'red' },
' - creating the image converter\n',
`\nDependencies: ${Object.entries(dependencies).map([key, value] => key + ' ' + value).join(' ')}`
])
])}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,13 +0,0 @@
const name = 'disconnect'
const description = 'Ends the bot\'s client.'
const usages = []
const aliases = ['disconnect']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args, handler) {
bot.disconnect()
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,17 +0,0 @@
const name = 'discord'
const description = 'totally real discord command!11'
const usages = []
const aliases = ['discord']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
bot.tellraw([
{ text: 'Join the ', color: 'gray' },
{ text: 'totally real ChipmunkBot Discord', color: bot.colors.primary },
' at ',
{ text: 'https://discord.gg/asIwmNwC', color: bot.colors.primary, underlined: true, clickEvent: { action: 'open_url', value: 'https://sus.red' } }
])
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,16 +0,0 @@
const name = 'echo'
const description = 'Echoes text'
const usages = ['<message...>']
const aliases = ['echo']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
const raw = args
.join(' ')
.replace(/&([0-9a-fkl-or]|#[0-9a-f]{6})/gi, m => '\xa7' + m.substring(1))
bot.core.run(`essentials:sudo ${bot._client.uuid} ${raw.startsWith('/') ? raw.substring(1) : 'c:' + raw}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

13
commands/end.js Normal file
View file

@ -0,0 +1,13 @@
const name = 'end'
const description = `Ends the bot's client.`
const usage = '{prefix}end'
const aliases = ['end']
const enabled = true
const permLevel = 0
function execute (bot, cmd, entity, args, handler) {
bot.end()
}
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,40 +1,20 @@
const name = 'eval'
const description = 'secure!!1'
const usages = ['<code...>']
const aliases = ['eval']
const enabled = true
const permLevel = 0
var name = 'eval'
var aliases = ['eval']
var description = "Runs code using eval()."
var usage = "{prefix}eval <code...>"
var enabled = false
const { inspect } = require('util')
const dineval = require('../util/dineval.js')
const { stylizeWithColor } = require('../util/stylize_with_color.js')
const permLevel = 2
async function execute (bot, cmd, player, args) {
const getCode = () => args.join(' ').replace(/\xa7.?/g, '')
switch (args.shift()) {
case 'run': {
let result
try {
result = await bot.eval(getCode(), { inspect: true })
} catch (err) {
result = err
}
bot.tellraw(result)
} break
case 'reset': {
bot.eval._worker.terminate()
} break
case 'dineval': {
const result = await dineval(getCode(), { colors: 'minecraft' })
const resultStr = typeof result === 'string' ? result : inspect(result, { stylize: stylizeWithColor })
bot.tellraw(resultStr)
} break
default: {
throw new SyntaxError('Invalid or missing argument')
}
}
function execute(bot, cmd, username, args, handler) {
new Promise((resolve, reject) => {
resolve(eval(args.join(' ')))
}).then((output) => {
bot.core.run(`/tellraw @a ${JSON.stringify({ text: `>${output}`, color: 'green' })}`)
}).catch((err) => {
//console.log(err);
bot.core.run(`/tellraw @a ${JSON.stringify({ text: `>${err}`, color: 'red' })}`)
})
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel}

View file

@ -1,27 +0,0 @@
const name = 'execute'
const description = 'Very normal execute command :)'
const usages = [ // TODO: Improve
'align <axes> -> execute',
'anchored <anchor> -> execute',
'/execute as <targets> -> execute',
'at <targets> -> execute',
'facing (entity|<pos>)',
'if (block|blocks|data|entity|predicate|score)',
'in <dimension> -> execute',
'positioned (as|<pos>)',
'rotated (as|<rot>)',
'run ...',
'store (result|success)',
'unless (block|blocks|data|entity|predicate|score)'
]
const aliases = ['execute']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
if (!bot.execute) throw new Error('Execute is not supported by the bot')
bot.execute(`as ${player.UUID} at @s ${args.join(' ')}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,34 +0,0 @@
const name = 'grainbowify'
const description = 'Makes text green rainbow'
const usages = ['<message...>']
const aliases = ['grainbowify']
const enabled = true
const permLevel = 0
const colorsys = require('colorsys')
function execute (bot, cmd, player, args, handler) {
const message = args.join(' ')
const result = []
let val = 0
let backwards = false
message.split('').forEach((char) => {
result.push({ text: char, color: colorsys.hsv2Hex(100, 100, val) })
incr()
if (val <= 0 || val >= 100) {
backwards = !backwards
incr()
}
function incr () {
const incr = 100 / Math.max(message.length, 20)
if (!backwards) { val += incr } else { val -= incr }
}
})
bot.tellraw(result)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,81 +1,49 @@
const name = 'help'
const description = 'Lists commands or shows info about a command.'
const usages = ['[command]']
const usage = '{prefix}help <command>'
const aliases = ['help']
const enabled = true
const permLevel = 0
function execute (bot, cmd, entity, args) {
function execute (bot, cmd, entity, args, handler) {
if (args.length > 0) {
if (!bot.commands.isCommand(args[0])) { return bot.core.run(`/tellraw @a ${JSON.stringify({ text: `Unknown command: ${bot.prefix}${args[0]}`, color: bot.colors.error })}`) }
if (!handler.isCommand(args[0]))
return bot.core.run(`/tellraw @a ${JSON.stringify({ text: `Unknown command: ${bot.prefix}${args[0]}`, color: bot.colors.error })}`)
const command = bot.commands.info(args.shift())
const command = handler.info(args.shift())
let msg
if (command.usages.length !== 1) {
msg = [
{ text: bot.prefix + command.name, color: bot.colors.primary },
{ text: ' (' + command.aliases.join(', ') + ')', color: 'white' },
{ text: ` - ${command.description}\n`, color: 'gray' }
]
command.usages.forEach((usage, i) => {
msg.push(bot.prefix + command.name)
msg.push({
text: ` ${usage}\n`,
color: bot.colors.secondary,
clickEvent: { action: 'suggest_command', value: command.name + ' ' + usage }
// hoverEvent: { action: 'show_text', value: 'Click to teleport' }
})
})
msg[msg.length - 1].text = msg[msg.length - 1].text.slice(0, -1)
} else {
msg = [
{ text: bot.prefix + command.name, color: bot.colors.primary },
{ text: ' (' + command.aliases.join(', ') + ')', color: 'white' },
{
text: ` ${command.usages[0]}`,
color: bot.colors.secondary,
clickEvent: { action: 'suggest_command', value: command.name + ' ' + command.usages[0] }
},
{ text: ` - ${command.description}`, color: 'gray' }
]
}
return bot.core.run(`minecraft:tellraw @a ${JSON.stringify(msg)}`)
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: 'Name: ', color: bot.colors.primary }, { text: `${command.name}\n`, color: bot.colors.secondary },
{ text: 'Description: ' }, { text: `${command.description}\n`, color: bot.colors.secondary },
{ text: 'Usage: ' }, { text: `${command.usage.replace(/{prefix}/g, bot.prefix)}\n`, color: bot.colors.secondary },
{ text: 'Aliases: ' }, { text: `${command.name}\n`, color: bot.colors.secondary },
{ text: 'Enabled: ' }, { text: `${command.enabled}\n`, color: bot.colors.secondary },
{ text: 'Permission Level: ' }, { text: command.permLevel, color: bot.colors.secondary }
])}`)
return
}
let commands = []
Object.keys(bot.commands.commands).forEach((command) => {
if (bot.commands.isCommand(command) && !commands.includes(bot.commands.info(command))) { commands.push(bot.commands.info(command)) }
Object.keys(handler.commands).forEach((command) => {
if (handler.isCommand(command))
commands.push(handler.info(command))
})
commands = commands.filter((command) => command.enabled)
const publicList = []
const trustedList = []
const adminList = []
const unknownList = []
const commandNames = []
commands.forEach((command) => {
const msg = {
color: 'dark_aqua',
text: bot.prefix + command.name + ' ',
clickEvent: { action: 'run_command', value: bot.prefix + aliases[0] + ' ' + command.name },
hoverEvent: { action: 'show_text', value: 'Click to see info about the command' }
}
if (command.permLevel === 0) {
msg.color = 'green'
publicList.push(msg)
} else if (command.permLevel === 1) {
msg.color = 'red'
trustedList.push(msg)
} else if (command.permLevel === 2) {
msg.color = 'dark_red'
adminList.push(msg)
} else {
unknownList.push(msg)
}
if (!commandNames.includes(command.name))
commandNames.push(command.name)
})
const msg = [{ text: 'Commands - ', color: 'gray' }, ...publicList, ...trustedList, ...adminList, ...unknownList]
bot.core.run(`/tellraw @a ${JSON.stringify(msg)}`)
text = [{ text: 'Commands:\n', color: bot.colors.primary }]
commandNames.forEach((cmdName) => {
text.push(cmdName)
text.push({ text: ', ', color: bot.colors.secondary })
})
text.splice(-1, 1)
bot.core.run(`/tellraw @a ${JSON.stringify(text)}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,70 +0,0 @@
const name = 'image'
const description = 'Renders an image.'
const usages = [
'render <name/url>',
'list'
]
const aliases = ['image']
const enabled = false
const permLevel = 0
const fs = require('fs')
const { loadImage } = require('canvas')
async function execute (bot, cmd, player, args, handler) {
const subCmd = args.shift()
switch (subCmd) {
case 'render': {
let src = args.join(' ').replace(/§.?/g, '')
if (/^https?:\/\//.test(src)) {
bot.core.run(`/minecraft:tellraw @a ${JSON.stringify([
{ text: 'Attempting to convert image at ', color: bot.colors.primary },
{ text: src, color: bot.colors.secondary }
])}`)
} else {
src = `./images/${src}`
if (!src.endsWith('.jpg')) { src += '.jpg' }
if (src.match(/\//g).length > 2) { throw new Error('Invalid image name.') }
if (!fs.existsSync(src)) { throw new Error('Invalid image name.') }
bot.core.run(`/minecraft:tellraw @a ${JSON.stringify([
{ text: 'Attempting to convert image ', color: bot.colors.primary },
{ text: args.join(' ').replace(/§.?/g, ''), color: bot.colors.secondary },
'.'
])}`)
}
const canvas = new bot.ChatCanvas()
const ctx = canvas.getContext('2d')
const img = await loadImage(src)
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
canvas.render()
} break
case 'list': {
const files = fs.readdirSync('./images')
files.filter((file) => file.endsWith('.jpg'))
let primary = false
const msg = [{ text: 'Images - ', color: 'gray' }]
files.forEach((file) => {
msg.push({
text: `${file} `,
color: (((primary = !primary)) ? bot.colors.primary : bot.colors.secondary),
clickEvent: { action: 'run_command', value: `${bot.prefix}${name} render ${file}` },
hoverEvent: { action: 'show_text', value: 'Click to render the image' }
})
})
bot.tellraw(msg)
} break
default: {
throw new Error('Invalid or missing argument.')
}
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,25 +0,0 @@
const name = 'kahoot'
const description = 'kahoot client lol'
const usages = ['join <pin> <username>', 'leave', 'answer <answer>']
const aliases = ['kahoot']
const enabled = false
const permLevel = 0
function execute (bot, cmd, player, args) {
const subCmd = args.shift()
switch (subCmd) {
case 'join':
bot.kahoot.join(parseFloat(args.shift()), args.join(' '))
break
case 'leave':
bot.kahoot.leave()
break
case 'answer':
bot.kahoot.answer(parseFloat(args.join(' ')))
break
default:
throw new Error('Invalid or missing argument.')
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,40 +0,0 @@
const name = 'kbwl'
const description = 'kaboom whitelist real'
const usages = ['enable', 'disable', 'add <player>', 'remove <player>', 'list']
const aliases = ['kbwl']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
switch (args.shift()) {
case 'enable':
bot.kbwl.players.push(player.name)
bot.kbwl.enabled = true
bot.tellraw([{ text: 'Enabled KBWL Mode', color: bot.colors.primary }], player.UUID)
break
case 'disable':
bot.kbwl.enabled = false
bot.tellraw([{ text: 'Disabled KBWL Mode', color: bot.colors.primary }], player.UUID)
break
case 'add': {
const username = args.join(' ')
if (bot.kbwl.players.includes(username)) throw new Error(username + ' is already whitelisted')
bot.kbwl.players.push(username)
bot.tellraw([{ text: 'Added ', color: bot.colors.primary }, { text: username, color: bot.colors.secondary }, 'to the whitelist'], player.UUID)
} break
case 'remove': {
const username = args.join(' ')
const index = bot.kbwl.players.indexOf(username)
if (index === -1) throw new Error(username + ' is not whitelisted')
bot.kbwl.players.splice(index, 1)
bot.tellraw([{ text: 'Removed ', color: bot.colors.primary }, { text: username, color: bot.colors.secondary }, 'from the whitelist'], player.UUID)
} break
case 'list':
bot.tellraw([
{ text: 'Players - ', color: bot.colors.primary },
...bot.kbwl.players.map((username, i) => ({ text: username + ' ', color: i % 2 === 0 ? bot.colors.secondary : bot.colors.primary }))
], player.UUID)
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,16 +0,0 @@
const name = 'kick'
const description = 'Kicks a player'
const usages = [ // TODO: Improve
'<target>'
]
const aliases = ['kick']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
if (!bot.kick) throw new Error('Kicking is not supported by the bot')
bot.kick(args.join(' '))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,29 +0,0 @@
const name = 'lint'
const description = 'Lints code using standard'
const usages = ['<code...>']
const aliases = ['lint']
const enabled = true
const permLevel = 0
const standard = require('standard')
async function execute (bot, cmd, entity, args) {
let fix = false
if (args[0] === 'fix') {
fix = true
args.shift()
}
const result = standard.lintTextSync(
args.join(' ').replace(/\xa7.?/g, '') + '\n',
{ fix }
).results[0]
let resultText = ''
result.messages.forEach(message => {
resultText += message.line + ':' + message.column + ': ' + message.message + '\n'
})
if (result.output != null) resultText += 'Output: ' + result.output
bot.tellraw(resultText)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,29 +0,0 @@
const name = 'linteval'
const description = 'lints and evaluates javascript'
const usages = ['<code...>']
const aliases = ['linteval', 'leval']
const enabled = true
const permLevel = 0
const { inspect } = require('util')
const standard = require('standard')
const colormap = ['white', 'yellow', 'red']
const lintOpts = {
usePackageJson: false
}
async function execute (bot, cmd, player, args) {
const code = args.join(' ').replace(/\xa7.?/g, '')
const { results: [ lintResult ] } = standard.lintTextSync(code + '\n', lintOpts)
const resultMsg = lintResult.messages.map(
({ line, column, message, severity }) => ({ text: `${line}:${column}: ${message}`, color: colormap[severity] })
)
bot.tellraw(resultMsg)
const evalResult = await bot.eval(code)
bot.tellraw({ text: inspect(evalResult), color: bot.colors.primary })
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,20 +0,0 @@
const name = 'list'
const description = 'Lists Entities (test command)'
const usages = ['[target]']
const aliases = ['list']
const enabled = true
const permLevel = 0
const parseSelectorComponent = require('../util/parse-selector-component.js')
async function execute (bot, cmd, player, args, handler) {
const selector = args.join(' ').replace(/\xa7.?/g, '') || '@e'
const entities = parseSelectorComponent((await bot.resolveComponent({ selector }))[0])
bot.tellraw([
{ text: 'Entities - ', color: bot.colors.primary },
...entities.flatMap((e, i) => [{ ...e.name, color: (i % 2) ? bot.colors.primary : bot.colors.secondary }, ' '])
])
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,35 +0,0 @@
const name = 'lock'
const description = 'real'
const usages = ['add <username>', 'remove <username>']
const aliases = ['lock']
const enabled = false
const permLevel = 1
const nbt = require('prismarine-nbt')
function execute (bot, cmd, player, args, handler) {
const subCommand = args.shift()?.toLowerCase()
const username = args.join(' ').replace(/\xa7.?/g, '')
switch (subCommand) {
case 'add':
bot.locked.push(username)
bot.tellraw([{ text: 'Added ', color: bot.colors.primary }, { text: username, color: bot.colors.secondary }, ' to the lock list'])
break
case 'remove':
const index = bot.locked.indexOf(username)
if (index === -1) {
throw new ReferenceError(username + ' is not locked')
}
// TODO: Unlock them
bot.locked.splice(index, 1)
bot.tellraw([{ text: 'Removed ', color: bot.colors.primary }, { text: username, color: bot.colors.secondary }, ' from the lock list'])
break
default:
throw new SyntaxError('ok')
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,49 +0,0 @@
const name = 'mail'
const description = 'Shows mail'
const usages = ['send <username> <message>', 'list', 'clear']
const aliases = ['mail']
const enabled = false
const permLevel = 0
function execute (bot, cmd, player, args) {
const subCmd = args.shift()
switch (subCmd) {
case 'send': {
const u = args.shift()
const message = args.join(' ')
bot.sendMail(player.name, bot.players[u].name ?? u, message)
bot.tellraw([
{ text: 'Sent ', color: bot.colors.primary },
{ text: message, color: bot.colors.secondary },
' to ',
{ text: u, color: bot.colors.secondary },
'.'
], player.UUID)
} break
case 'list': {
const messages = bot.mail[player.name]
if (!messages || messages.length < 1) {
bot.tellraw({ text: 'You have no mail', color: bot.colors.primary }, player.UUID)
return
}
const msg = [{ text: 'Mail:', color: bot.colors.primary }]
messages.forEach(message => {
msg.push(`\n${message.sender} (from ${message.host}): `)
msg.push({ text: message.message, color: bot.colors.secondary })
})
bot.tellraw(msg, player.UUID)
} break
case 'clear': {
bot.mail[player.name].splice(0, bot.mail[player.name].length)
bot.tellraw({ text: 'Your mail has been cleared.', color: bot.colors.primary }, player.UUID)
} break
default: {
throw new SyntaxError('TODO: add correct error message')
}
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,94 +0,0 @@
const name = 'music'
const description = 'Plays music'
const usages = [
'play <song>',
'list',
'skip',
'stop'
// 'goto <m>:<ss>'
]
const aliases = ['music']
const enabled = true
const permLevel = 0
const fs = require('fs/promises')
const path = require('path')
async function execute (bot, cmd, player, args) {
const subCmd = args.shift()
switch (subCmd) {
case 'play': {
let filepath = args.join(' ').replace(/\xa7.?/g, '')
filepath = path.join('music', filepath)
// if (!filepath.endsWith('.mid')) { filepath += '.mid' }
if (!checkPath(filepath)) throw new Error('among us')
try {
const stats = await fs.lstat(filepath)
if (stats.isDirectory()) {
const files = await fs.readdir(filepath)
filepath = path.join(filepath, files[Math.floor(Math.random() * files.length)])
}
if (!bot.music.playing) {
bot.music.play(filepath)
} else {
bot.music.queue.push(filepath)
}
} catch (err) {
throw new Error('File does not exist')
}
} break
case 'list': {
const clean = args.join(' ').replace(/\xa7.?/g, '')
const filepath = path.join('music', clean)
if (!checkPath(filepath)) throw new Error('among us')
const files = await fs.readdir(filepath)
let primary = true
const msg = [{ text: 'Songs - ', color: bot.colors.secondary }]
for (const file of files) { // TODO: Make this code better
const isFile = (await fs.lstat(path.join(filepath, file))).isFile()
msg.push({
text: file + ' ',
color: (!((primary = !primary)) ? bot.colors.primary : bot.colors.secondary),
clickEvent: { action: 'run_command', value: `${bot.prefix}${cmd} ${isFile ? 'play' : 'list'} ${path.join(clean, file)}` }
// hoverEvent: { action: 'show_text', value: 'Click to play the song' }
})
}
bot.tellraw(msg)
} break
case 'skip':
bot.music.skip()
break
case 'stop':
throw new Error('trold')
// bot.music.stop()
break
case 'loop':
bot.music.looping = !bot.music.looping
break
// case 'goto': {
// const [minutes, seconds] = args.split(':').map(Number)
//
// } break
default:
throw new SyntaxError('Invalid or missing argument')
}
}
function checkPath (filepath) { // TODO: Make this code better
return filepath.startsWith('music')
}
/* function randomFile (dirpath) {
const paths = fs.readdirSync(dirpath)
.map(filename => path.join(dirpath, filename))
.filter(file)
} */
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,15 +0,0 @@
const name = 'myuser'
const description = 'Shows your username'
const usages = []
const aliases = ['myuser']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
bot.tellraw([
{ text: 'Your username is: ', color: bot.colors.primary },
{ text: player.name, color: bot.colors.secondary }
])
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,41 +0,0 @@
const name = 'netmsg'
const description = 'Sends a message as each bot'
const usages = ['<message...>']
const aliases = ['netmsg']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
const { host, port = 25565 } = bot.server
let displayNameArr = player.displayName
if (!Array.isArray(displayNameArr)) {
if (typeof displayNameArr === 'object') {
const arr = [displayNameArr, ...(Array.isArray(displayNameArr.extra) ? displayNameArr.extra : [])]
delete displayNameArr.extra
displayNameArr = arr
} else if (typeof displayNameArr === 'string') {
displayNameArr = [displayNameArr]
} else {
displayNameArr = [player.name]
}
}
displayNameArr[0].color ??= bot.colors.secondary
const msg = JSON.stringify([
{ text: '', color: 'gray' },
{ text: '[', color: 'dark_gray' },
{ text: host, clickEvent: { action: 'copy_to_clipboard', value: host + ':' + port }, hoverEvent: { action: 'show_text', value: { text: host + ':' + port + '\nClick to copy the ip to your clipboard', color: bot.colors.primary } } },
{ text: '] ', color: 'dark_gray' },
...displayNameArr,
{ text: ' ', color: 'dark_gray' },
args.join(' ')
])
bot.getBots().forEach((bot) => {
bot.core.run('minecraft:tellraw @a ' + msg)
})
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,15 +0,0 @@
const name = 'parsetest'
const description = 'Displays a chat message (can be colored with %)'
const usages = ['<message...>']
const aliases = ['parsetest']
const enabled = true
const permLevel = 0
const parseString = require('../util/bukkit_chat_parse.js')
function execute (bot, cmd, player, args, handler) {
const message = args.join(' ').replace(/%[0123456789a-fk-orx]/gi, m => '\xa7' + m[1])
parseString(message, false, false).forEach(m => bot.tellraw(m))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,25 +0,0 @@
const name = 'pos'
const description = 'Gets the position of a player'
const usages = ['<selector>']
const aliases = ['pos']
const enabled = false
const permLevel = 0
function execute (bot, cmd, player, args) {
bot.getEntityPos(args.join(' '), (position) => {
const { x, y, z } = position
bot.core.run(`minecraft:tellraw @a ${JSON.stringify([
{ text: 'Position: ', color: bot.colors.primary },
{
text: `[${x}, ${y}, ${z}]`,
color: bot.colors.secondary,
clickEvent: { action: 'run_command', value: `/essentials:tp ${x} ${y} ${z}` },
hoverEvent: { action: 'show_text', value: 'Click to teleport' }
}
])}`)
// bot.chatQueue.push(`&aPosition: &2${x} ${y} ${z}`)
})
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,6 +1,6 @@
const name = 'rainbowify'
const description = 'Makes text rainbow'
const usages = ['<message...>']
const description = 'Rainbowifys text'
const usage = '{prefix}rainbowify'
const aliases = ['rainbowify']
const enabled = true
@ -8,19 +8,17 @@ const permLevel = 0
const colorsys = require('colorsys')
function execute (bot, cmd, player, args, handler) {
function execute (bot, cmd, entity, args, handler) {
const message = args.join(' ')
let hue = 0
const rainbowified = message
.split('')
.map((char) => {
const component = { text: char, color: colorsys.hsv2Hex(hue, 100, 100) }
hue = (hue + (360 / Math.max(message.length, 20))) % 360
return component
const result = []
let hue = 0
message.split('').forEach((char) => {
result.push({ text: char, color: colorsys.hsv2Hex(hue, 100, 100) })
hue += 355 / Math.max(message.length, 20)//; console.log(hue)
})
bot.tellraw(rainbowified)
bot.core.run(`/tellraw @a ${JSON.stringify(result)}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,13 +0,0 @@
const name = 'rc'
const description = 'Resets the bot\'s command core'
const usages = []
const aliases = ['rc']
const enabled = true
const permLevel = 0
function execute (bot, cmd, entity, args) {
bot.core.reset()
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,16 +0,0 @@
const name = 'resolve'
const description = 'Resolves a text component' // '\xa7mUseless\xa7r backwards-compatible tellraw command'
const usages = ['<component (JSON)...>']
const aliases = ['resolve']
const enabled = true
const permLevel = 0
async function execute (bot, cmd, player, args, handler) {
const component = JSON.parse(args.join(' ').replace(/\xa7.?/g)
const resolved = await bot.resolveComponent(component)
bot.tellraw(JSON.stringify(resolved))
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,19 +0,0 @@
const name = 'runjson'
const description = 'Runs a command from a JSON string'
const usages = ['<command (JSON)...>']
const aliases = ['runjson']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args) {
const command = JSON.parse(args
.join(' ')
.replace(/\xa7.?/g, '')
)
if (typeof command !== 'string') throw new TypeError('command must be a string')
bot.core.run(command)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,25 +0,0 @@
const name = 'spawnmob'
const description = 'but better'
const usages = ['<entity> <amount> [nbt]']
const aliases = ['spawnmob']
const enabled = true
const permLevel = 0
const snbt = require('mojangson')
const nbt = require('prismarine-nbt')
function execute (bot, cmd, player, args) {
const entity = nbt.string(args.shift())
if (entity === undefined) throw new Error('Expected an entity')
const amount = parseInt(args.shift()) || 0
if (Number.isNaN(amount) || amount > 2000) throw new Error('Invalid amount')
const optionalNbt = args.length === 0 ? undefined : snbt.parse(args.join(' '))
if (optionalNbt !== undefined && optionalNbt.type !== 'compound') throw new Error('Invalid optional nbt')
const Passengers = nbt.list(nbt.comp(new Array(amount).fill(optionalNbt ? { id: entity, ...optionalNbt.value } : { id: entity })))
bot.execute(`at ${player.UUID} run summon area_effect_cloud ~ ~ ~ ${snbt.stringify(nbt.comp({ Passengers }))}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,24 +0,0 @@
const name = 'sudo'
const description = 'Forces a player to send a chat message'
const usages = ['<target> <command>', '<target> c:<message>']
const aliases = ['sudo']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
let target = args.shift()
if (!target) throw new Error('Expected a target')
let command = args.join(' ').replace(/\xa7.?/g, '')
if (!command) throw new Error('Expected a command to run')
if (command.startsWith('c:/')) command = command.substring(3)
if (bot.server.isAyunBoom && (target === '*' || target === '**')) {
// Object.values(bot.players).forEach(({ UUID }) => bot.core.run('essentials:sudo ' + UUID + ' ' + command))
// return
target = ' ' + target
}
bot.core.run('essentials:sudo ' + target + ' ' + command)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,14 +0,0 @@
const name = 'tellraw'
const description = 'Tellraw command' // '\xa7mUseless\xa7r backwards-compatible tellraw command'
const usages = ['<target> <component (JSON)...>']
const aliases = ['tellraw']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
const target = args.shift()
bot.tellraw(JSON.parse(args.join(' ').replace(/\xa7.?/g, '')), target)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,42 +0,0 @@
const name = 'urban'
const description = 'Shows word definitions from the Urban Dictionary'
const usages = ['<word...>']
const aliases = ['urban']
const enabled = true
const permLevel = 0
const ud = require('urban-dictionary')
function execute (bot, cmd, player, args, handler) {
// Callback
ud.define(args.join(' ').replace(/§./, ''), (error, results) => {
if (error) {
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: error.message, color: bot.colors.error }
])}`)
return
}
const msg = [{ text: '', color: 'gray' }]
results.forEach((result) => {
msg.push({ text: '[', color: 'dark_gray' })
msg.push({ text: 'Urban', color: 'red' })
msg.push({ text: '] ', color: 'dark_gray' })
msg.push({ text: `${result.word} `, bold: true })
const a = result.definition.replace(/\r\n?/g, '\n').split(/\[|\]/)
for (let i = 0; i < a.length; i += 2) {
msg.push({ text: a[i] })
if (a[i + 1] != null) {
msg.push(
{ text: a[i + 1], underlined: true, clickEvent: { action: 'run_command', value: `${bot.prefix}${name} ${a[i + 1]}` } }
)
}
}
msg[msg.length - 1].text += '\n'
})
bot.tellraw(msg)
})
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,13 +1,15 @@
const name = 'validate'
const description = 'Tests trusted hash validation.'
const usages = ['<hash>']
const description = 'Tests trusted code validation.'
const usage = '{prefix}validate'
const aliases = ['validate']
const enabled = true
const permLevel = 1
function execute (bot, cmd, player, args) {
bot.tellraw({ text: 'Valid hash', color: bot.colors.primary })
function execute (bot, cmd, entity, args, handler) {
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: 'Valid code.', color: bot.colors.primary }
])}`)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }
module.exports = { name, description, usage, aliases, enabled, execute, permLevel }

View file

@ -1,31 +0,0 @@
const name = 'vnc'
const description = 'fard'
const usages = [
'connect \xa7m<host> <port> [password]\xa7r',
'mouse <x> <y> [state]',
'update',
'end'
]
const aliases = ['vnc']
const enabled = true
const permLevel = 0
function execute (bot, cmd, player, args, handler) {
const subCmd = args.shift().toLowerCase()
if (subCmd === 'connect') {
bot.vnc.connect({ host: 'localhost', port: 5900 })
} else if (subCmd === 'clear') {
bot.vnc.display.clearEntities()
} else if (subCmd === 'mouse') {
const [x, y, state = 1] = args.map(Number)
bot.vnc._client?.pointerEvent(x, y, state)
} else if (subCmd === 'update') {
bot.vnc._client?.requestUpdate()
} else if (subCmd === 'end') {
bot.vnc._client.end()
}
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

View file

@ -1,17 +0,0 @@
const name = 'wikipedia'
const description = 'Shows summaries of wikipedia pages'
const usages = []
const aliases = ['wikipedia', 'wiki']
const enabled = true
const permLevel = 0
const wiki = require('wikipedia')
async function execute (bot, cmd, player, args) {
const page = await wiki.page(args.join(' ').replace(/\xa7.?/g, ''))
const summary = await page.summary()
bot.tellraw(summary.extract, player.UUID)
}
module.exports = { name, description, usages, aliases, enabled, execute, permLevel }

23
cperms.js Normal file
View file

@ -0,0 +1,23 @@
let codes = [null, Math.random(), Math.random()]
printCodes()
function validate(level, code) {
for (let i = level; i < codes.length; i++) {
if (codes[i] === code) {
codes[i] = Math.random()
console.log(`New code for level ${i}: ${codes[i]}`)
return true
}
}
return false
}
function printCodes() {
console.log('Codes: ')
for (const i in codes) {
console.log(`Permission level ${i}: ${codes[i]}`)
}
}
module.exports = { codes, validate, printCodes }

View file

@ -1,20 +0,0 @@
module.exports = [
{
username: 'ChipmunkBot',
prefix: "'",
colors: { primary: 'green', secondary: 'dark_green', error: 'red' },
version: '1.18.2',
randomizeUsername: true,
autoReconnect: true,
autoReconnectDelay: 6000,
server: {
host: 'localhost',
port: 25565,
isBukkit: true,
isKaboom: true,
isScissors: true,
isAyunBoom: false
},
trustedKey: 'among us'
}
]

View file

@ -1,62 +1,10 @@
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prefix: '> '
})
const createBot = require('./bot.js')
// const commandHandler = require('./commands.js')
const fs = require('fs/promises')
const path = require('path')
const moment = require('moment')
async function exists (filepath) {
try {
await fs.access(filepath)
return true
} catch {
return false
}
}
async function main () {
let logPath = path.join('logs', moment().format('YYYY-MM-DD'))
if (await exists(logPath)) {
const suffixed = logPath + '-'
let i = 0
while (await exists(logPath)) {
logPath = suffixed + (i++)
}
}
await fs.writeFile(logPath, '')
const absolutePath = path.resolve('config')
let optionsArray
try {
optionsArray = require(absolutePath)
} catch {
await fs.copyFile(path.join(__dirname, 'default.js'), 'config.js')
console.info('No config file was found, so a default one was created.')
optionsArray = require(absolutePath)
}
const bots = []
optionsArray.forEach((options, index) => {
const bot = createBot(options)
bot.getBots = () => bots
bot.on('error', console.error)
bot.console.filepath = logPath
bot.console.setRl(rl)
bot.commands.loadFromDir('commands')
bots.push(bot)
const bot = createBot({
host: process.argv[2] ?? 'kaboom.pw',
port: 25565,
username: 'fard',
prefix: `'`,
brand: 'kaboom',
colors: { primary: 'green', secondary: 'dark_green', error: 'red' }
})
}
main()

1
launcher_accounts.json Normal file
View file

@ -0,0 +1 @@
{}

8378
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,28 +1,12 @@
{
"dependencies": {
"@mozilla/readability": "^0.4.1",
"@skeldjs/client": "^2.15.17",
"@tonejs/midi": "^2.0.27",
"axios": "^0.27.2",
"badwords": "^1.0.0",
"canvas": "^2.9.1",
"canvas": "^2.8.0",
"colorsys": "^1.0.22",
"fluent-ffmpeg": "^2.1.2",
"fs": "^0.0.1-security",
"kahoot.js-api": "^2.4.0",
"minecraft-protocol": "^1.35.0",
"mojangson": "^2.0.2",
"moment": "^2.29.1",
"namemc": "^1.8.16",
"node-fetch": "^3.2.3",
"path": "^0.12.7",
"prismarine-nbt": "^2.2.0",
"rfb2": "^0.2.2",
"standard": "^16.0.4",
"tmp": "^0.2.1",
"translate": "^1.4.1",
"urban-dictionary": "^3.0.2",
"vm2": "^3.9.9",
"wikipedia": "^1.1.9"
"minecraft-protocol": "^1.30.0",
"path": "^0.12.7"
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,19 +0,0 @@
// I had to make this plugin because of skids (ab)using tnt
const { states } = require('minecraft-protocol')
function bot (bot) {
bot.antiTNT = {
enabled: false
}
setInterval(() => {
if (!bot.antiTNT.enabled || bot.state !== states.PLAY) return // do nothing if antiTNT is disabled or the bot is not logged in
bot.core.run('minecraft:gamerule mobGriefing false') // disable mobGriefing
bot.core.run('minecraft:kill @e[type=tnt]') // remove tnt entities
bot.core.run('minecraft:kill @e[type=tnt_minecart]') // remove tnt minecart entities
bot.core.run('minecraft:execute as @e[name=WeaponGrenade] run data merge entity @s {CustomName: ""}') // change grenades to normal eggs
}, 25)
}
module.exports = { bot }

View file

@ -1,37 +0,0 @@
function inject (bot) {
bot.antiCB ??= false
setInterval(() => {
if (!bot.antiCB) return
let offsets
offsets = { x: randomInt(-8, 8), /* y: 0, */ z: randomInt(-8, 8) }
bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${(-3) - offsets.x} 0 ~${(-3) - offsets.z} ~${(3) - offsets.x} 255 ${3 - offsets.z} chain_command_block replace command_block', auto: 1b} destroy`)
offsets = { x: randomInt(-8, 8), /* y: 0, */ z: randomInt(-8, 8) }
bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${(-3) - offsets.x} 0 ~${(-3) - offsets.z} ~${(3) - offsets.x} 255 ${3 - offsets.z} chain_command_block replace repeating_command_block', auto: 1b} destroy`)
}, 50)
// setInterval(() => {
// if (!bot.antiCB) return
// let offsets
//
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 0 ~${-8 - offsets.z} ~${8 - offsets.x} 112 ${8 - offsets.z} chain_command_block replace command_block', auto: 1b} destroy`)
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 113 ~${-8 - offsets.z} ~${8 - offsets.x} 225 ${8 - offsets.z} chain_command_block replace command_block', auto: 1b} destroy`)
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 226 ~${-8 - offsets.z} ~${8 - offsets.x} 255 ${8 - offsets.z} chain_command_block replace command_block', auto: 1b} destroy`)
//
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 0 ~${-8 - offsets.z} ~${8 - offsets.z} 112 ${8 - offsets.z} chain_command_block replace repeating_command_block', auto: 1b} destroy`)
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 113 ~${-8 - offsets.z} ~${8 - offsets.z} 225 ${8 - offsets.z} chain_command_block replace repeating_command_block', auto: 1b} destroy`)
// offsets = { x: randomInt(-8, 8), /*y: 0,*/ z: randomInt(-8, 8) }
// bot.core.run(`minecraft:execute at @a run setblock ~${offsets.x} 0 ~${offsets.z} command_block{Command: 'minecraft:fill ~${-8 - offsets.x} 226 ~${-8 - offsets.z} ~${8 - offsets.x} 255 ${8 - offsets.z} chain_command_block replace repeating_command_block', auto: 1b} destroy`)
// }, 50)
}
function randomInt (min, max) {
return Math.floor((Math.random() * (max - min) + min) + 1)
}
module.exports = inject

View file

@ -1,31 +0,0 @@
const { hsv2Hex } = require('colorsys')
function bot (bot) {
bot.bruhify = {
text: '',
_format: comp => 'minecraft:title @a actionbar ' + comp
}
bot.bruhify.format = bot.bruhify._format
let startHue = 0
setInterval(() => {
const { text, format } = bot.bruhify
if (!text) return
let hue = startHue
const increment = (360 / Math.max(text.length, 20)) % 360
const _component = text
.split('')
.map(char => {
const text = { text: char, color: hsv2Hex(hue, 100, 100) }
hue = (hue + increment) % 360
return text
})
bot.core.run(format(JSON.stringify([{ text: '▚ ', color: 'light_purple' }, ..._component, ' ▚'])))
startHue = (startHue + increment) % 360
}, 50)
}
module.exports = { bot }

View file

@ -1,16 +0,0 @@
function inject (bot) {
bot.on('cspy', (player, command) => {
if (command.startsWith('/')) { command = command.slice(1) }
const args = command.split(' ')
command = args.shift()
if (command === 'cc' || command === 'clearchat' || command === 'extras:cc' || command === 'extras:clearchat') {
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: '', color: 'dark_green' },
`${player.name} cleared the chat`
])}`)
}
})
}
module.exports.bot = inject

View file

@ -1,48 +1,44 @@
const { waterfowl } = require('../util/waterfowl.js')
const { normalize, parseText } = require('../util/text_parser.js')
const commandSet = 'advMode.setCommand.success'
const commandSetStr = 'Command set: '
const { states } = require('minecraft-protocol')
const parseText = require('./../util/text_parser.js')
function bot (bot) {
bot.chat = {
queue: []
}
function inject (bot) {
bot.chatQueue = []
setInterval(() => {
if (bot.state !== states.PLAY) return
const message = bot.chat.queue.shift()
if (message) bot._client.write('chat', { message: String(message) })
}, 100)
bot.on('chat', ({ message, sender, position }) => {
const waterfowlMessage = waterfowl(message, position, sender, { Extras: bot.server.isKaboom, CommandSpy: bot.server.isKaboom })
if (waterfowlMessage != null) {
bot.emit('waterfowl_message', waterfowlMessage, { message, sender, position })
bot.emit(waterfowlMessage.type, waterfowlMessage, { message, sender, position })
const message = bot.chatQueue.shift()
if (message != null && message.length < 256) {
bot._client.write('chat', { message })
}
}, 200)
bot.emit('chat_motd', parseText(message).raw, { message, sender, position })
bot._client.on('chat', (packet) => {
const message = parseText(packet.message)
bot.emit('chat', message, packet)
})
bot.on('chat_motd', (message, { sender }) => {
bot.console.log(`[${bot.server.host}] ${message.replace(/\n+/g, '\n')}`)
bot.on('chat', (message, data) => {
console.log(message.ansi)
let msg = message.raw;
if (msg.match(/<.*§r> .*/g)) {
if (data.sender === '00000000-0000-0000-0000-000000000000') return
let username = bot.uuidMap[data.sender]//msg.substr(3).split('§r>')[0]
let message = msg.split('§r> §r')[1]
bot.emit("message", { username: username, uuid: data.sender }, message)
} else if (msg.match(/<.*> .*/g)) {
if (data.sender === '00000000-0000-0000-0000-000000000000') return
let username = bot.uuidMap[data.sender]//msg.substr(3).split(">")[0]
let message = msg.split('> ')[1]
bot.emit("message", { username: username, uuid: data.sender }, message)
} else if (msg.match(/.* .*§r: §.*/g)) {
if(data.sender === '00000000-0000-0000-0000-000000000000') return;
let username = bot.uuidMap[data.sender]//msg.split(' ')[1].split("§r:")[0]
let message = msg.split('§r: ')[1].substr(2)
bot.emit("message", { username: username, uuid: data.sender }, message)
} else if (msg.match(/§.*§b: \/.*/g)) {
let username = msg.split('§b: ')[0]
let command = msg.split('§b: ')[1]
bot.emit("cspy", username, command)
}
})
}
function client (bot) {
bot._client.on('chat', ({ message, sender, position }) => {
message = JSON.parse(message)
if (isCommandSet(message)) return
bot.emit(position === 2 ? 'actionbar' : 'chat', { message, sender, position })
})
}
function isCommandSet (message) {
message = normalize(message)
let firstExtra = message?.extra?.length ? message?.extra[0] : {}
return (message?.translate === commandSet || firstExtra?.translate === commandSet || message?.text === commandSetStr || firstExtra?.text === commandSetStr)
}
module.exports = { bot, client }
module.exports = inject

View file

@ -1,27 +0,0 @@
const { Canvas } = require('canvas')
const convertImageData = require('../util/image_data_converter.js')
const { states } = require('minecraft-protocol')
function bot (bot) {
const canvas = new Canvas(320, 20)
bot.chatCanvas = canvas
const _renderCtx = canvas.getContext('2d')
canvas.render = function render (options = {}) {
const { data } = _renderCtx.getImageData(0, 0, canvas.width, canvas.height)
const components = convertImageData(data, canvas.width, options)
components.forEach(c => bot.tellrawJSON(c))
}
canvas.renderOnTick = false
setInterval(() => {
if (!canvas.renderOnTick || bot.state !== states.PLAY) return
canvas.render()
}, 50)
bot.on('chat_motd', (motd, { position }) => {
if (!canvas.renderOnTick || position !== 0) return
bot.core.run('minecraft:title @a actionbar ' + JSON.stringify(motd))
})
}
module.exports = { bot }

View file

@ -1,50 +0,0 @@
const nbt = require('prismarine-nbt')
const filter = require('badwords/regexp')
// filter the chat
function inject (bot) {
bot.chatFilter = {
enabled: false,
_lines: [],
_filter
}
bot.on('chat_motd', (motd) => {
const filtered = _filter(motd)
bot.chatFilter._lines = [...bot.chatFilter._lines, ...filtered.split('\n')]
while (bot.chatFilter._lines.length > 99) {
bot.chatFilter._lines.shift()
}
if (motd !== filtered) {
bot._client.write('set_creative_slot', {
slot: 36,
item: {
present: true,
itemId: 1,
itemCount: 1,
nbtData: nbt.comp({
'': nbt.string('\xa7r' + bot.chatFilter._lines.join('\xa7r\n'))
})
}
})
if (bot.server.isScissors) {
const storage = Math.random().toString()
bot.core.run('minecraft:data modify storage ' + storage + ' "" set from entity ' + bot._client.uuid + ' Inventory[0].tag.""')
bot.tellraw({ nbt: '""', storage }, '@a[tag=chatfilter]')
bot.core.run('minecraft:data remove storage ' + storage + ' i')
} else bot.tellraw({ nbt: 'Inventory[0].tag.""', entity: bot._client.uuid }, '@a[tag=chatfilter]')
}
})
}
function _filter (message) {
let filtered = message
filtered = filtered.replace(filter, mogus)
return filtered
}
function mogus (match) {
return new Array(match.length).fill('\u0d9e').join('')
}
module.exports.bot = inject

View file

@ -1,17 +0,0 @@
function inject (bot) {
bot.cloops = []
setInterval(() => {
bot.cloops.forEach((cloop, i) => {
if (!cloop._looping) loop(i)
})
}, 1)
function loop (i) {
if (bot.cloops[i] == null) { return }
bot.cloops[i]._looping = true
bot.core.run(bot.cloops[i].command)
setTimeout(() => loop(i), bot.cloops[i].interval)
}
}
module.exports.bot = inject

View file

@ -1,133 +1,19 @@
const fs = require('fs')
const path = require('path')
const { inspect } = require('util')
const { parseText } = require('../util/text_parser.js')
const { getHash } = require('../util/cval.js')
const handler = require('../commands.js')
const sectionRegex = /\xa7.?/g
function inject (bot) {
handler.load()
function inject (bot, options) {
bot.commands = {
commands: {},
add,
execute,
info,
isCommand,
loadFromDir,
isValid
}
const listener = ({ message }, { sender }) => {
message = parseText(message).raw // fard
const player = bot.players[sender]
if (!message.startsWith(bot.prefix)) return
const args = message.slice(bot.prefix.length).trim().split(' ')
const command = args.shift().toLowerCase()
if (!isCommand(command)) {
bot.tellraw({ text: `Unknown command: ${bot.prefix}${command}`, color: bot.colors.error })
return
}
if (args[args.length - 1]?.endsWith('\\')) {
bot.tellraw({ text: 'This will be added... idk when.' })
return
}
const { permLevel } = bot.commands.info(command)
if (permLevel) {
if (args.length === 0) {
bot.tellraw({ text: 'Expected a hash', color: bot.colors.error })
return
}
// TODO: Don't use a bad argument parser
const commandHashLength = message.charCodeAt(message.length - 2) * 2
if (commandHashLength >= message.length) {
bot.tellraw({ text: `Length of the hash (${commandHashLength}) is longer than the message's length (${message.length})`, color: bot.colors.error })
bot.on('message', (entity, message) => {
if (!message.startsWith(bot.prefix))
return
}
const originalCommand = message.substring(0, message.length - commandHashLength - 4)
let commandHash = ''
for (let i = message.length - commandHashLength - 2; i < message.length - 3; i += 2) {console.log(i, message[i])
if (message[i - 1] !== '\xa7') {
bot.tellraw(`Expected an escape character at ${i - 1}`)
return
}
commandHash += message[i]
}
const args = message.slice(bot.prefix.length).split(' ')
const command = args.shift()
if (!handler.isCommand(command))
return bot.core.run(`bcraw &cUnknown command: ${bot.prefix}${command}`)
const hash = getHash(originalCommand, player.UUID, options.trustedKey)
console.log({ message, commandHash, commandHashLength, hash, originalCommand })
if (commandHash !== hash) {
bot.tellraw({ text: 'Invalid hash', color: bot.colors.error })
return
}
args.splice(-1, hash.split(' ').length) // TODO: Make this less bad
}
bot.commands.execute(bot, command, player, args)
}
bot.on('emote', listener)
bot.on('whisper', listener)
bot.on('announcement', listener)
function add (command) {
if (!isValid(command)) throw new Error('Invalid command', 'invalid_command')
command.aliases.forEach(alias => (bot.commands.commands[alias.toLowerCase()] = command))
}
function loadFromDir (dirpath) {
fs.readdirSync(dirpath).forEach(filename => {
const filepath = path.resolve(dirpath, filename)
if (!filepath.endsWith('js') || !fs.statSync(filepath).isFile()) return // TODO: Use require.extensions
try {
bot.commands.add(require(filepath))
} catch (err) {
bot.console.error('Error loading command ' + filepath + ': ' + inspect(err))
}
handler.execute(bot, command, entity, args)
})
}
function info (command) {
const info = bot.commands.commands[command] ?? command
if (isValid(info)) return info
}
function isCommand (command) { return bot.commands.info(command) != null }
async function execute (bot, command, player, args, ...custom) {
const info = bot.commands.info(command)
if (info == null) {
bot.tellraw({ text: 'Unknown command: ' + bot.prefix + command, color: bot.colors.error })
return
}
if (!info.enabled) {
bot.tellraw({ text: bot.prefix + command + ' is disabled', color: bot.colors.error })
return
}
try {
return await info.execute(bot, command, player, args, ...custom)
} catch (err) {
bot.console.error('Error executing command ' + command + ': ' + inspect(err))
bot.tellraw({ text: err?.name + ': ' + err?.message, color: bot.colors.error })
}
}
}
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.bot = inject
module.exports = inject

View file

@ -1,35 +0,0 @@
const parseString = require('../util/bukkit_chat_parse.js')
function bot (bot) {
const players = []
bot.on('player_added', player => {
const existing = players.findIndex(e => e.player.UUID === player.UUID)
if (existing !== -1) players.splice(existing, 1)
players.push({
player,
components: [
...parseString(`\xa7b${player.name}\xa7b: /`, true, false),
...parseString(`\xa7e${player.name}\xa7e: /`, true, false)
]
})
})
bot.on('chat', ({ message, sender }) => {
if (sender !== '00000000-0000-0000-0000-000000000000' || typeof message !== 'object') return
for (const { player, components } of players) {
for (const component of components) {
/* const command = parseCommandSpy(message, component)
if (command != null) {
bot.emit('commandspy', player, command)
bot.core.run('minecraft:say ' + player.name + ' ran ' + command)
return
} */
}
}
})
}
module.exports = { bot }

View file

@ -1,96 +0,0 @@
const fs = require('fs')
const util = require('util')
const moment = require('moment')
const ansimap = {
0: '\x1b[0m\x1b[30m',
1: '\x1b[0m\x1b[34m',
2: '\x1b[0m\x1b[32m',
3: '\x1b[0m\x1b[36m',
4: '\x1b[0m\x1b[31m',
5: '\x1b[0m\x1b[35m',
6: '\x1b[0m\x1b[33m',
7: '\x1b[0m\x1b[37m',
8: '\x1b[0m\x1b[90m',
9: '\x1b[0m\x1b[94m',
a: '\x1b[0m\x1b[92m',
b: '\x1b[0m\x1b[96m',
c: '\x1b[0m\x1b[91m',
d: '\x1b[0m\x1b[95m',
e: '\x1b[0m\x1b[93m',
f: '\x1b[0m\x1b[97m',
r: '\x1b[0m',
l: '\x1b[1m',
o: '\x1b[3m',
n: '\x1b[4m',
m: '\x1b[9m',
k: '\x1b[6m'
}
function inject (bot) {
bot.console = {
filepath: null,
host: 'all',
log,
warn,
error,
_log,
setRl,
_rl: null
}
function log (data) {
_log('\u00a72INFO', process.stdout, data)
}
function warn (data) {
_log('\u00a7eWARN', process.stderr, data)
}
function error (data) {
_log('\u00a7cERROR', process.stderr, data)
}
function _log (prefix, stdout, data) {
// format it
data = `[${moment().format('HH:mm:ss')} ${prefix}\u00a7r] ${data}\n`
// log to file
const filepath = bot.console.filepath
if (filepath != null) {
fs.appendFile(filepath, data, err => {
if (err) console.error(err)
})
}
// log to stdout
data = data.replace(/\u00a7.?/g, m => ansimap[m.slice(1)] ?? '') + '\x1b[0m'
stdout.write(data)
}
function setRl (rl) {
rl?.prompt(true)
rl?.on('line', handleLine)
// bot.console._rl?.removeListener('line', handleLine)
bot.console._rl = rl
async function handleLine (line) {
if (bot.server.host !== bot.console.host && bot.console.host !== 'all') return
if (line.startsWith('.')) {
const args = line.slice(1).trim().split(' ')
const command = args.shift()
if (!bot.commands.isCommand(command)) {
bot.console.error('Unknown command: ' + command)
return
}
const info = bot.commands.info(command)
try {
await info.execute(bot, command, bot.players[bot.uuid], args)
} catch (err) {
bot.console.error(`Error executing ${command} in console: ${util.inspect(err)}`)
}
} else {
bot.fancyMsg(bot._client.username + ' Console', '_ChipMC_', line)
rl?.prompt(true)
}
}
}
}
module.exports.bot = inject

View file

@ -1,89 +1,41 @@
const { states } = require('minecraft-protocol')
const nbt = require('prismarine-nbt')
const mcNamespace = 'minecraft:'
function inject (bot) {
const core = {}
function bot (bot) {
let mcData = require('minecraft-data')('1.17.1')
bot.on('login', () => (mcData = require('minecraft-data')(bot._client.version)))
core.pos = { x: 0, y: null, z: null }
core.size = { fromX: -8, fromY: 0, fromZ: -8, toX: 8, toY: 0, toZ: 8 }
core.block = { x: core.size.fromX, y: core.size.fromY, z: core.size.fromZ }
core.refill = () => {
core.pos = { x: Math.round(bot.position.x), y: 0, z: Math.round(bot.position.z) }
core.block = { x: core.size.fromX, y: core.size.fromY, z: core.size.fromZ }
bot.chatQueue.push(`/fill ${core.pos.x + core.size.fromX} ${core.pos.y + core.size.fromY} ${core.pos.z + core.size.fromZ} ${core.pos.x + core.size.toX} ${core.pos.y + core.size.toY} ${core.size.toZ + core.pos.z} repeating_command_block replace`)
}
core.run = command => {
core.block.x++
if (core.block.x > core.size.toX) {
core.block.x = core.size.fromX;
core.block.z++
if (core.block.z > core.size.toZ) {
core.block.z = core.size.fromZ
core.block.y++
if (core.block.y > core.size.toY) {
core.block.x = core.size.fromX
core.block.y = core.size.fromY
core.block.z = core.size.fromZ
}
}
}
bot._client.write('update_command_block', {
location: {
x: core.pos.x + core.block.x,
y: core.pos.y + core.block.y,
z: core.pos.z + core.block.z
}, command: command, mode: 1, flags: 0b100 })
}
bot.core = {
size: { from: { x: -8, y: 0, z: -8 }, to: { x: 8, y: 0, z: 8 } },
from: { x: null, y: null, z: null },
to: { x: null, y: null, z: null },
block: { x: null, y: null, z: null },
refill () {
const refillCommand = `/fill ${this.from.x} ${this.from.y} ${this.from.z} ${this.to.x} ${this.to.y} ${this.to.z} repeating_command_block{CustomName:'""'}`
const location = { x: Math.floor(bot.position.x), y: Math.floor(bot.position.y) - 1, z: Math.floor(bot.position.z) }
const commandBlockId = mcData?.itemsByName.command_block.id
bot._client.write('set_creative_slot', {
slot: 36,
item: {
present: true,
itemId: commandBlockId,
itemCount: 1,
nbtData: nbt.comp({
BlockEntityTag: nbt.comp({
auto: nbt.byte(1),
Command: nbt.string(refillCommand)
})
bot.core = core
bot._client.once('position', () => {
bot.core.refill()
})
}
})
bot._client.write('block_dig', {
status: 0,
location,
face: 1
})
bot._client.write('block_place', {
location,
direction: 1,
hand: 0,
cursorX: 0.5,
cursorY: 0.5,
cursorZ: 0.5,
insideBlock: false
})
},
run (command) {
if (bot.state !== states.PLAY) return
if (!bot.server.isBukkit && command.startsWith(mcNamespace)) command = command.substring(mcNamespace.length)
if (!bot.isKaboom) bot._client.write('update_command_block', { location: this.block, command: '', mode: 0, flags: 0b000 })
bot._client.write('update_command_block', { location: this.block, command: String(command).substring(0, 32767), mode: bot.server.isKaboom ? 1 : 2, flags: 0b100 })
this.block.x++
if (this.block.x > this.to.x) {
this.block.x = this.from.x
this.block.z++
if (this.block.z > this.to.z) {
this.block.z = this.from.z
this.block.y++
if (this.block.y > this.to.y) {
this.block.x = this.from.x
this.block.y = this.from.y
this.block.z = this.from.z
}
}
}
},
reset () {
this.from = { x: Math.floor(this.size.from.x + bot.position.x), y: 0, z: Math.floor(this.size.from.z + bot.position.z) }
this.to = { x: Math.floor(this.size.to.x + bot.position.x), y: Math.floor(this.size.to.y), z: Math.floor(this.size.to.z + bot.position.z) }
this.block = { ...this.from }
this.refill()
}
}
bot.on('move', oldPos => {
bot.core.run(`minecraft:setblock ${Math.floor(oldPos.x)} ${Math.floor(oldPos.y - 1)} ${Math.floor(oldPos.z)} minecraft:air replace mincecraft:command:block`) // Clean up after refills
bot.core.reset()
})
setInterval(() => bot.core.refill(), 60 * 1000)
}
module.exports = { bot }
module.exports = inject

View file

@ -1 +0,0 @@
module.exports = require('./eval/plugin.js')

View file

@ -1,45 +0,0 @@
const {
Worker,
// isMainThread,
parentPort,
workerData
} = require('worker_threads')
function bot (bot) {
bot.eval = function (code, options = {}) {
return new Promise((resolve, reject) => {
const listener = ({ action, data }) => {
if (action === 'resolve') resolve(data)
else if (action === 'reject') reject(data)
else return
bot.eval._worker.removeListener('message', listener)
}
bot.eval._worker.on('message', listener)
bot.eval._worker.postMessage({ action: 'eval', data: { code, ...options } })
})
}
function stdoutListener (data) { bot.tellraw({ text: String(data) }) } // TODO: Make it less broken
function exitListener (exitCode) {
if (bot.loggedIn) bot.tellraw([{ text: 'Eval worker exited with code ', color: bot.colors.primary }, { text: exitCode, color: bot.colors.secondary }])
bot.eval._worker = new Worker(require.resolve('./worker.js'), {
env: { among: 'us' }
})
const worker = bot.eval._worker
worker.on('message', ({ action, data }) => {
if (action === 'run') bot.core.run(data)
})
worker.stdout.on('data', stdoutListener)
worker.stderr.on('data', stdoutListener)
worker.on('error', console.error)
worker.on('exit', exitListener)
}
exitListener(-69)
}
module.exports = { bot }

View file

@ -1,7 +0,0 @@
const { Module } = require('../util/module.js')
function inject () {
global.module = new Module('<eval>')
}
module.exports = inject

View file

@ -1,12 +0,0 @@
const _process = require('process')
const Process = _process.constructor
function inject () {
const process = new Process()
global.process = process
process.exit = _process.exit
process.nextTick = _process.nextTick
}
module.exports = inject

View file

@ -1,42 +0,0 @@
const path = require('path/posix')
const _fs = {}
class SymbolicLink {
constructor (filepath = '/') {
this.filepath = filepath
}
}
function _parse (filepath) {
const { root, dir, base, ext } = path.parse(filepath)
if (root === '') return _parse(path.join('/', filepath))
let _dir = _fs
for (const key of dir.split(path.sep)) {
if (_dir[key] == null) throw new Error('no such file or directory, open ' + filepath, 'ENOENT')
_dir = _dir[key]
}
return { dir: _dir, filename: base + ext }
}
function existsSync (filepath) {
const { dir, filename } = _parse(filepath)
return dir[filename] == null
}
function statSync (filepath) {
const stats = new fs.Stats()
}
function readFileSync (filepath, options) {
const { dir, filename } = _parse(filepath)
if (dir[filename] == null) throw new Error('ENOENT: no such file or directory, open ' + filepath, 'ENOENT')
return dir[filename]
}
functi

View file

@ -1,32 +0,0 @@
const _Module = require('module')
const _builtinModules = {
aasert: require('assert'),
buffer: require('buffer'),
console: require('console'),
crypto: require('crypto'),
events: require('events'),
vm: require('vm'),
'minecraft-protocol': require('minecraft-protocol')
}
class Module {
id = ''
path = '.'
exports = {}
filename = null
loaded = false
children = []
constructor (path) {
this.id = path
}
require (filepath) {
if (filepath in _builtinModules) return _builtinModules[filepath]
throw new Error('i will add that whenever i finish the fake fs')
}
}
module.exports = { Module, _builtinModules }

View file

@ -1,31 +0,0 @@
const { parentPort } = require('worker_threads')
const { runInThisContext, Module } = require('vm')
const { inspect } = require('util')
const path = require('path')
const { stylizeWithColor } = require('../../util/stylize_with_color.js')
const plugins = {
process: require('./plugins/process.js'),
cjs: require('./plugins/cjs.js')
}
process = null
parentPort.on('message', ({ action, data }) => {
if (action === 'eval') {
try {
let result = runInThisContext(data.code, { filename: 'this is totally a real file' })
result = data.inspect ? inspect(result, { stylize: stylizeWithColor }) : result
parentPort.postMessage({ action: 'resolve', data: result })
} catch (err) {
err = data.inspect ? inspect(err, { stylize: stylizeWithColor }) : err
parentPort.postMessage({ action: 'reject', data: err })
}
}
})
// plugin injection
Object.values(plugins).forEach(inject => inject())

View file

@ -1,23 +0,0 @@
const nbt = require('prismarine-nbt')
const snbt = require('mojangson')
const toNBTUUID = require('../util/uuid-to-nbt-uuid.js')
function bot (bot) {
function execute (command) {
bot.core.run(`minecraft:execute ${bot.server.isKaboom ? 'unless entity @s[name= run ] ' : ''}${command}`)
}
function kick (target) {
if (/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/.test(target)) {
target = `@p[nbt=${snbt.stringify(nbt.comp({ UUID: toNBTUUID(target) }))}]`
}
if (bot.server.isKaboom) bot.core.run(`minecraft:item replace entity ${target} container.9 with stone{i:"\xa74${'\u0d9e'.repeat(30000)}\xa7r"}`)
else bot.core.run('minecraft:kick ' + target)
}
bot.execute = execute
bot.kick = kick
}
module.exports = { bot }

View file

@ -1,18 +0,0 @@
/* function bot (bot) {
function fakeKaboomMessage (
prefix = []
) {
bot.tellraw({
extra: [
{ bold: true, color: 'dark_red', text: '['}, { bold: true, color: 'red', text: 'OP'}, {"bold":true,"color":"dark_red","text":"] "},
{"color":"red","text":"Enderman"},{"text":": "},
{"text":"why do u look like a headchog"}
],
text: ''
})
}
bot.fakeKaboomMessage = fakeKaboomMessage
}
module.exports = { bot } */

View file

@ -1,15 +0,0 @@
function inject (bot) {
bot.fancyMsg = function (rank, username, message) {
bot.tellraw([
{ text: '', color: 'gray' },
{ text: '[', color: 'dark_gray' },
rank,
{ text: '] ', color: 'dark_gray' },
{ text: username, color: bot.colors.secondary },
{ text: ' ', color: 'dark_gray' },
message
])
}
}
module.exports.bot = inject

View file

@ -1,14 +0,0 @@
const fs = require('fs')
function inject (bot) {
bot.runFunction = function (filepath) {
const commands = fs.readFileSync(filepath).toString().replace(/\r\n?/g, '\n').split('\n')
let i = 0
const interval = setInterval(() => {
if (!commands[i]?.startsWith('#')) { bot.exploits.execute('run ' + commands[i]) }
if (++i > commands.length) { clearInterval(interval) }
}, 50)
}
}
module.exports = inject

View file

@ -1,24 +0,0 @@
function bot (bot) {
function setInventorySlot (slot, item) {
bot._client.write('set_creative_slot', { slot, item })
}
bot.setInventorySlot = setInventorySlot
}
function client (bot) {
bot.inventory = new Array(46).fill({ present: false })
// TODO: Hotbar slots
bot._client.on('set_slot', ({ windowId, slot, item }) => {
if (windowId !== 0) return // Ignore non-inventory set_slot packets
bot.inventory[slot] = { ...defaultItem, ...clean(item) } // set the slot
})
bot._client.on('window_items', ({ windowId, items }) => {
if (windowId !== 0) return // Ignore non-inventory window_items packets
items.forEach((item, slot) => {
bot.inventory[slot] = { ...defaultItem, ...clean(item) } // set the slot
})
})
}

View file

@ -1,85 +0,0 @@
const Kahoot = require('kahoot.js-api')
const questionColors = ['red', 'aqua', 'yellow', 'green']
const questionSymbols = ['▲', '♦', '●', '■']
function inject (bot) {
const answerError = () => bot.core.run(`minecraft:tellraw @a ${kahootErrMsg('You cannot currently answer.')}`)
bot.kahoot ??= {}
bot.kahoot.playing ??= false
bot.kahoot.answer ??= answerError
bot.kahoot.client ??= new Kahoot()
bot.kahoot.leave = () => {
bot.core.run(`minecraft:tellraw @a ${kahootMsg('Leaving...')}`)
bot.kahoot.client?.leave()
bot.kahoot.playing = false
}
bot.kahoot.join = function (pin, username = 'Player') {
if (bot.kahoot.playing) {
bot.core.run(`minecraft:tellraw @a ${kahootErrMsg('The bot is already playing kahoot.')}`)
return
}
bot.kahoot.playing = true
bot.kahoot.client = new Kahoot()
bot.kahoot.client.join(pin, username).catch((err) => {
bot.kahoot.playing = false
bot.core.run(`minecraft:tellraw @a ${kahootErrMsg(err.description)}`)
})
bot.kahoot.client.on('Joined', () =>
bot.core.run(`minecraft:tellraw @a ${kahootMsg('Successfully joined the kahoot.')}`)
)
bot.kahoot.client.on('QuizStart', () =>
bot.core.run(`minecraft:tellraw @a ${kahootMsg('The quiz has started.')}`)
)
bot.kahoot.client.on('QuestionReady', (question) =>
bot.core.run(`minecraft:tellraw @a ${kahootMsg(`A ${question.type} question will start in ${question.timeLeft} seconds.`)}`)
)
bot.kahoot.client.on('QuestionStart', (question) => {
bot.kahoot.answer = (answer) => {
question.answer(answer)
bot.kahoot.answer = answerError
}
bot.core.run(`minecraft:tellraw @a ${kahootMsg(`A ${question.type} question has started (Time Left: ${question.timeLeft / 1000} seconds).`)}`)
const answersMsg = ['']
for (let i = 0; i < question.numberOfChoices; i++) {
answersMsg.push({ text: '[', color: questionColors[i], clickEvent: { action: 'run_command', value: `${bot.prefix}kahoot answer ${i}` }, hoverEvent: { action: 'show_text', value: 'Click to answer' } })
answersMsg.push({ text: questionSymbols[i], clickEvent: { action: 'run_command', value: `${bot.prefix}kahoot answer ${i}` }, hoverEvent: { action: 'show_text', value: 'Click to answer' } })
answersMsg.push({ text: '] ', color: questionColors[i], clickEvent: { action: 'run_command', value: `${bot.prefix}kahoot answer ${i}` }, hoverEvent: { action: 'show_text', value: 'Click to answer' } })
}
bot.core.run(`minecraft:tellraw @a ${JSON.stringify(answersMsg)}`)
})
bot.kahoot.client.on('QuestionEnd', (results) => {
bot.kahoot.answer = answerError
bot.core.run(`minecraft:tellraw @a ${kahootMsg(`You answered ${results.isCorrect ? '' : 'in'}correctly! You currently have ${results.points} points.`)}`)
})
bot.kahoot.client.on('QuizEnd', (results) =>
bot.core.run(`minecraft:tellraw @a ${kahootMsg(`The quiz has ended! Your rank is: ${results.rank}.`)}`)
)
bot.kahoot.client.on('Disconnect', (reason) => {
bot.core.run(`minecraft:tellraw @a ${kahootMsg(`Disconnected: ${reason}`)}`)
})
}
}
function kahootMsg (message) {
return JSON.stringify([
{ text: '', color: 'gray' },
{ text: '[', color: 'dark_gray' },
{ text: 'Kahoot', color: 'dark_purple' },
{ text: '] ', color: 'dark_gray' },
message
])
}
function kahootErrMsg (message) {
return JSON.stringify([
{ text: '', color: 'red' },
{ text: '[', color: 'dark_gray' },
{ text: 'Kahoot', color: 'dark_purple' },
{ text: '] ', color: 'dark_gray' },
message
])
}
module.exports.bot = inject

View file

@ -1,17 +0,0 @@
// const nbt = require('prismarine-nbt')
// const snbt = require('../util/snbt.js')
// const toNBTUUID = require('../util/uuid-to-nbt-uuid.js')
function bot (bot) {
bot.kbwl = {
enabled: false,
players: []
}
bot.on('player_added', ({ name, UUID }) => {
if (!bot.kbwl.enabled || UUID === bot.uuid || bot.kbwl.players.includes(name)) return
bot.kick(UUID)
})
}
module.exports = { bot }

View file

@ -1,15 +0,0 @@
/* const nbt = require('prismarine-nbt')
const dataPromise = require('../util/persistent-data.js')
async function inject (bot) {
const data = await dataPromise
bot.mail = mail
bot.sendMail = (sender, reciever, message) => {
if (!mail[reciever]) mail[reciever] = []
mail[reciever].push({ sender: sender, message, host: bot.server.host + ':' + (bot.server.port || 25565) })
}
}
module.exports.bot = inject
*/

View file

@ -1,214 +1,112 @@
const fs = require('fs')
const path = require('path')
const { Midi } = require('@tonejs/midi')
const { convertMidi } = require('../util/midi_converter')
const convertNBS = require('../util/nbs-converter.js')
const parseTXTSong = require('../util/txt-song-parser')
const { instruments } = require('minecraft-data')('1.15.2') // fard
const soundMap = {
harp: 'block.note_block.harp',
basedrum: 'block.note_block.basedrum',
snare: 'block.note_block.snare',
hat: 'block.note_block.hat',
bass: 'block.note_block.bass',
flute: 'block.note_block.flute',
bell: 'block.note_block.bell',
guiter: 'block.note_block.guiter',
chime: 'block.note_block.chime',
xylophone: 'block.note_block.xylophone',
iron_xylophone: 'block.note_block.iron_xylophone',
cow_bell: 'block.note_block.cow_bell',
didgeridoo: 'block.note_block.didgeridoo',
bit: 'block.note_block.bit',
banjo: 'block.note_block.banjo',
pling: 'block.note_block.pling'
}
const oldSoundMap = {
harp: 'block.note_block.harp',
basedrum: 'block.note_block.basedrum',
snare: 'block.note_block.snare',
hat: 'block.note_block.hat',
bass: 'block.note_block.bass',
flute: 'block.note_block.harp',
bell: 'block.note_block.harp', // 'entity.experience_orb.pickup'
guiter: 'block.note_block.bass',
chime: 'block.note_block.harp',
xylophone: 'block.note_block.harp',
iron_xylophone: 'block.note_block.harp',
cow_bell: 'block.note_block.cow_bell',
didgeridoo: 'block.note_block.bass',
bit: 'block.note_block.harp',
banjo: 'block.note_block.bass',
pling: 'block.note_block.pling'
}
const convertMidi = require('../util/midi_converter.js')
function inject(bot) {
bot.music = {
playing: false,
queue: [],
nowPlaying: undefined,
looping: false,
_interval: null,
_playNextSong,
nowPlaying,
skip,
stop,
play,
normalize
play
}
bot.music.nowPlaying = {
var nowPlaying = {
name: '',
tick: {
current: null,
total: null
// npt: null
note: {
current: null, total: null
}
}
setInterval(() => {
if (!bot.music.playing) return
const msg = [
if (bot.music.playing)
bot.core.run(`/title @a actionbar ${JSON.stringify([
{ text: 'Now Playing', color: bot.colors.primary },
{ text: ' | ', color: 'dark_gray' },
{ text: bot.music.nowPlaying.displayName, color: bot.colors.secondary, bold: true },
{ text: nowPlaying.name, color: bot.colors.secondary, bold: true },
{ text: ' | ', color: 'dark_gray' },
format(bot.music.nowPlaying.time),
nowPlaying.note.current,
{ text: ' / ', color: 'gray' },
format(bot.music.nowPlaying.length)
// { text: ' (', color: 'dark_gray' },
// bot.music.nowPlaying.note.npt + ' npt',
// { text: ')', color: 'dark_gray' }
]
if (bot.music.looping) {
msg.push({ text: ' | ', color: 'dark_gray' })
msg.push({ text: 'Looping', color: bot.colors.secondary })
}
bot.core.run('/title @a actionbar ' + JSON.stringify(msg))
}, 500)
nowPlaying.note.total
])}`)
}, 50)
function _playNextSong () {
const song = bot.music.queue.shift()
if (song != null) play(song)
setInterval(() => {
if (!bot.music.playing) {
const filepath = bot.music.queue.shift()
if (filepath != null)
play(filepath)
}
}, 1)
function skip() {
clearInterval(bot.music._interval)
bot.music.playing = false
if (bot.music.queue.length !== 0) _playNextSong()
cancel = true
}
function stop() {
bot.music.queue = []
clearInterval(bot.music._interval)
bot.music.playing = false
cancel = true
}
var cancel = false
function play(filepath) {
//set stuff up
filepath = path.resolve(filepath)
let song
try {
switch (path.extname(filepath)) {
case '.nbs':
song = convertNBS(fs.readFileSync(filepath))
break
case '.js':
case '.cjs':
case '.json':
const requirePath = require.resolve(filepath)
delete require.cache[requirePath]
song = normalize(require(requirePath))
break
case '.txt':
song = parseTXTSong(fs.readFileSync(filepath).toString())
break
default:
const midi = new Midi(fs.readFileSync(filepath))
song = normalize(convertMidi(midi))
}
song.displayName = song.name.length > 0 ? `${song.name} (${path.basename(filepath)})` : path.basename(filepath)
song.time = 0
bot.music.nowPlaying = song
} catch (err) {
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: err?.message, color: bot.colors.error }))
return
}
cancel = false
const noteList = convertMidi(filepath)
nowPlaying.name = filepath.replace(/.+\//g, '')
nowPlaying.note.current = 0
nowPlaying.note.total = noteList.length
//play the music lol
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: 'Now playing ', color: bot.colors.primary },
{ text: song.displayName, color: bot.colors.secondary },
{ text: nowPlaying.name, color: bot.colors.secondary },
'.'
])}`)
bot.music.playing = true
bot.music.looping = song.loop
let startTime = Date.now()
bot.music._interval = setInterval(() => {
const intervalTime = song.time + 1
song.time = Date.now() - startTime
song.notes.forEach((note, i) => {
const _time = note.time // Math.floor(note.time)
if (intervalTime <= _time && song.time >= _time) {
const sound = soundMap[note.instrument]
// const oldSound = oldSoundMap[note.instrument]
let tick = 0
const interval = setInterval(() => {
for (const i in noteList) {
const note = noteList[i]
if (tick >= note.tick) {
const floatingpitch = Math.pow(2, (note.pitch - 12) / 12.0)
bot.core.run(`minecraft:execute as @a[tag=!nomusic] at @s run playsound ${sound} record @s ^ ^ ^ ${note.volume} ${floatingpitch}`)
}
})
bot.core.run(`/execute at @a positioned ^-2.0 ^ ^ run playsound block.note_block.${note.instrument} record @p ~ ~ ~ 65535 ${floatingpitch}`)
if (song.time > song.length) {
if (bot.music.looping) {
startTime = Date.now() + song.loopPosition
return
nowPlaying.note.current++
noteList.splice(i, 1)
}
}
tick++//;bot.core.run(`/bcraw Tick: ${tick}`)
if (noteList.length == 0 || cancel) {
clearInterval(interval)
clearInterval(bot.music._interval)
bot.music.playing = false
bot.core.run('/tellraw @a ' + JSON.stringify([
bot.core.run(`/tellraw @a ${JSON.stringify([
{ text: 'Finished playing ', color: 'green' },
{ text: bot.music.nowPlaying.name, color: 'dark_green' }
]))
if (bot.music.queue.length !== 0) _playNextSong()
{ text: nowPlaying.name, color: 'dark_green' },
'.'
])}`)
}
}, 1)
}, 50)
}
}
function normalize (song) {
const normalizeNote = note => { // change notes with tick to notes with time
if (note.time == null && note.tick != null) {
note.time = note.tick * 50
delete note.tick
}
//module.exports.timeConverter = timeConverter
//module.exports.tuneNoteblocks = tuneNoteblocks
//module.exports.tuneNoteblock = tuneNoteblock
//module.exports.parse = parse
//module.exports.play = play
//module.exports.songInfo = songInfo
//module.exports.isValidFile = isValidFile
const num = Number(note.instrument)
if (!Number.isNaN(num)) note.instrument = instruments[num].name
}
if (Array.isArray(song)) { // if the song is actually an array, convert it to a song
let length = 0
for (const note of song) {
normalizeNote(note)
length = Math.max(note.time, length)
}
return { name: '', notes: song, loop: false, loopPosition: 0, length }
}
let length = 0
for (const note of song.notes ?? []) {
normalizeNote(note)
length = Math.max(note.time, length)
}
song.length = length
return { name: '', notes: [], loop: false, loopPosition: 0, length, ...song }
}
function format (ms) {
const s = ms / 1000
//module.exports.getNowPlaying = () => {return nowPlaying}
//module.exports.editNowPlaying = (song_name, current, full, url, addedBy) => {
// song_name != undefined ? nowPlaying.song_name = song_name : undefined
// current != undefined ? nowPlaying.time.current = current : undefined
// full != undefined ? nowPlaying.time.full = full : undefined
// url != undefined ? nowPlaying.url = url : undefined
// addedBy != undefined ? nowPlaying.addedBy = addedBy : undefined
//}
const seconds = Math.floor(s / 60).toString()
const minutes = Math.floor(s % 60).toString()
return seconds + ':' + (minutes.length <= 1 ? '0' : '') + minutes
}
module.exports.bot = inject
module.exports = inject

View file

@ -1,8 +0,0 @@
function bot (bot) {
bot.playerFilter = null
bot.on('player_added', ({ name, UUID }) => {
if (bot.playerFilter != null && bot.playerFilter.test(name)) bot.kick(UUID)
})
}
module.exports = { bot }

View file

@ -1,55 +0,0 @@
const actions = {
// doesnt include 0 and 4 because they are special
1: 'gamemode',
2: 'ping',
3: 'displayName'
}
function inject (bot) {
bot.players = {}
function removePlayer (uuid) {
const player = bot.players[uuid]
if (!player) return false
delete bot.players[player.name]
delete bot.players[uuid]
bot.emit('player_removed', player)
return true
}
bot._client.on('player_info', ({ action, data }) => {
if (actions[action] == null) { // Special cases
data.forEach(async player => {
if (action === 0) {
bot.players[player.name] = player
bot.players[player.UUID] = player
bot.emit('player_added', player)
} /* else if (action === 4) {
const { UUID } = player
try {
const [selectorComp] = await bot.resolveComponent({ selector: UUID })
if (selectorComp.text === '' && !selectorComp.extra) removePlayer(UUID)
} catch (err) {
removePlayer(UUID)
}
} */
})
return
}
data.forEach(player2 => {
const player = bot.players[player2.UUID]
if (!player) return
const info = actions[action]
if (player[info] == null || player2[info] == null) return
player[info] = player2[info]
bot.emit('player_updated', info, player)
})
})
}
module.exports.client = inject

View file

@ -1,18 +0,0 @@
function bot (bot) { bot.position = { x: null, y: null, z: null } }
function client (bot) {
bot._client.on('position', ({ x, y, z, flags, teleportId }) => {
// TODO: Don't ignore yaw, pitch
const oldPosition = { ...bot.position }
bot.position.x = flags & 1 ? (bot.position.x + x) : x
bot.position.y = flags & 2 ? (bot.position.y + y) : y
bot.position.z = flags & 4 ? (bot.position.z + z) : z
bot._client.write('teleport_confirm', { teleportId })
bot.emit('move', oldPosition, true)
})
}
module.exports = { bot, client }

View file

@ -1,34 +0,0 @@
function bot (bot) {
bot.on('login', () => {
bot.chat.queue.push('/commandspy:commandspy on')
// bot.chat.queue.push('/essentials:vanish enable')
bot.chat.queue.push('/essentials:god enable')
})
bot.on('cspy', (player, command, args) => {
switch (command) {
case 'icu':
case 'icontrolu:icu':
if (args[0] === 'control' && (bot._client.username.startsWith(args[1]) || args[1] === bot._client.uuid)) { bot.core.run(`essentials:sudo ${player.UUID} icontrolu:icu stop`) }
}
})
}
function client (bot, client) {
bot._client.on('game_state_change', (packet) => {
switch (packet.reason) {
case 3:
if (packet.gameMode !== 1) { bot.chat.queue.push('/minecraft:gamemode creative @s[type=player]') }
break
case 4:
bot._client.write('client_command', { payload: 0 })
}
})
bot._client.on('update_health', (packet) => {
if (packet.health <= 0) { bot._client.write('client_command', { payload: 0 }) }
})
bot._client.on('declare_commands', () => bot.chat.queue.push('/op @s[type=player]'))
}
module.exports = { bot, client }

View file

@ -1,19 +0,0 @@
function bot (bot) {
if (!bot.server.isKaboom) return
bot.skinQueue = []
setInterval(() => {
if (!bot.loggedIn) bot.skinQueue.splice(0, bot.skinQueue.length)
if (bot.skinQueue.length === 0) return
const { UUID, name } = bot.skinQueue.shift()
// bot.core.run('minecraft:tellraw @a ' + JSON.stringify([{ text: 'Setting the skin of ', color: bot.colors.primary }, { text: name, color: bot.colors.secondary }]))
bot.core.run('essentials:sudo ' + UUID + ' extras:skin ' + name)
}, 2250)
bot.on('player_added', ({ name, UUID, properties }) => {
if (UUID === bot._client.uuid || properties.some(({ name }) => name === 'textures')) return
bot.skinQueue.push({ name, UUID })
})
}
module.exports = { bot }

View file

@ -1,66 +0,0 @@
// Valid values
const visibilityValues = ['never', 'hideForOtherTeams', 'hideForOwnTeam', 'always']
const collisionRuleValues = ['always','never', 'pushOtherTeams', 'pushOwnTeam']
// TODO: Track players
function bot (bot) {
class Team {
destroyed = false
constructor (name, displayName, isExistingTeam = false) {
this.name = String(name)
if (!isExistingTeam) bot.core.run(`minecraft:team add ${this.name}`)
}
add (target) {
bot.core.run(`minecraft:execute at ${bot.uuid} as ${target} run team join ${this.name}`) // execute seems safer than team
return this
}
setDisplayName (displayName) {
bot.core.run(`minecraft:team modify ${this.name} displayName ${JSON.stringify(displayName)}`)
return this
}
setColor (color) {
// TODO: Check if the color is valid
bot.core.run(`minecraft:team modify ${this.name} color ${color}`)
return this
}
setFriendlyFire (boolean) {
bot.core.run(`minecraft:team modify ${this.name} friendlyFire ${Boolean(boolean)}`)
return this
}
setSeeFriendlyInvisibles (boolean) {
bot.core.run(`minecraft:team modify ${this.name} seeFriendlyInvisibles ${Boolean(boolean)}`)
return this
}
setNametagVisibility (visibility) {
if (!visibilityValues.includes(visibility)) throw new TypeError('Value must be ' + visibilityValues.join(', '))
bot.core.run(`minecraft:team modify ${this.name} nametagVisibility ${visibility}`)
return this
}
setDeathMessageVisibility (visibility) {
if (!visibilityValues.includes(visibility)) throw new TypeError('Value must be ' + visibilityValues.join(', '))
bot.core.run(`minecraft:team modify ${this.name} deathMessageVisibility ${visibility}`)
return this
}
setCollisionRule (collisionRule) {
if (!collisionRuleValues.includes(collisionRule)) throw new TypeError('Value must be ' + collisionRuleValues.join(', '))
bot.core.run(`minecraft:team modify ${this.name} collisionRule ${collisionRule}`)
return this
}
setPrefix (prefix) {
bot.core.run(`minecraft:team modify ${this.name} prefix ${JSON.stringify(prefix)}`)
return this
}
setSuffix (suffix) {
bot.core.run(`minecraft:team modify ${this.name} suffix ${JSON.stringify(suffix)}`)
return this
}
destroy () {
bot.core.run(`minecraft:team remove ${this.name}`)
this.destroyed = true
}
}
bot.Team = Team
}
module.exports = { bot }

View file

@ -1,73 +0,0 @@
const nbt = require('prismarine-nbt')
const snbt = require('mojangson')
const toNBTUUID = require('../util/uuid-to-nbt-uuid.js')
function bot (bot) {
function _itemTellraw (json, target) {
bot._client.write('set_creative_slot', {
slot: 36,
item: {
present: true,
itemId: 1,
itemCount: 1,
nbtData: nbt.comp({
'': nbt.string(json)
})
}
})
if (bot.server.isScissors) {
const storage = Math.random().toString()
bot.core.run('minecraft:data modify storage ' + storage + ' "" set from entity ' + bot._client.uuid + ' Inventory[0].tag.""')
bot.core.run(`minecraft:tellraw ${target} ${JSON.stringify({ nbt: '""', storage, interpret: true })}`)
bot.core.run('minecraft:data remove storage ' + storage + ' i')
} else {
bot.core.run(`minecraft:tellraw ${target} ${JSON.stringify({ nbt: 'Inventory[0].tag.""', entity: bot._client.uuid, interpret: true })}`)
}
}
function tellrawJSON (json, target = '@a') {
if (/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/.test(target)) {
target = `@p[nbt=${snbt.stringify(nbt.comp({ UUID: toNBTUUID(target) }))}]`
}
const command = `minecraft:tellraw ${target} ${json}`
if (command.length > 32767 || command.includes('selector') || (bot.server.isAyunBoom && /@e|@r\[[^\]]*limit=\d+[^\]]*\]/.test(command))) {
_itemTellraw(json, target)
return
}
bot.core.run(command)
}
function tellraw (message, target) { tellrawJSON(JSON.stringify(message), target) }
function resolveComponent (message, timeout = 30000) {
return new Promise((resolve, reject) => {
if (typeof message === 'object' && !Array.isArray(message)) {
if (message.extra) message = [message, ...message.extra]
else message = [message]
} else if (typeof message !== 'object') {
message = [message].flat()
}
const char = String.fromCharCode(Math.floor(Math.random() * (0xFFF + 1)))
bot.tellraw({ text: char, extra: message }, bot.uuid)
const listener = ({ message, sender, position }) => {
if (message?.text !== char || sender !== '00000000-0000-0000-0000-000000000000' || position !== 1) return
resolve(message.extra)
bot.removeListener('chat', listener)
}
bot.on('chat', listener)
setInterval(() => {
reject(new Error(`Timed out after ${timeout}ms`))
bot.removeListener('chat', listener)
}, timeout)
})
}
bot.tellrawJSON = tellrawJSON
bot.tellraw = tellraw
bot.resolveComponent = resolveComponent
}
module.exports = { bot }

View file

@ -1,45 +0,0 @@
function longToBigInt (array) {
return BigInt.asIntN(64, (BigInt(array[0]) << 32n)) | BigInt(array[1])
}
function bot (bot) {
bot.time = {
doDaylightCycle: null,
bigTime: null,
time: null,
timeOfDay: null,
day: null,
isDay: null,
moonPhase: null,
bigAge: null,
age: null
}
}
function client (bot) {
bot._client.on('update_time', (packet) => {
const oldTime = { ...bot.time }
let time = longToBigInt(packet.time)
if (time < 0) {
bot.time.doDaylightCycle = false
time *= -1n
} else {
bot.time.doDaylightCycle = true
}
bot.time.bigTime = time
bot.time.time = Number(time)
bot.time.timeOfDay = bot.time.time % 24000
bot.time.day = Math.floor(bot.time.time / 24000)
bot.time.isDay = bot.time.timeOfDay < 13000 || bot.time.timeOfDay >= 23000
bot.time.moonPhase = bot.time.day % 8
bot.time.bigAge = longToBigInt(packet.age)
bot.time.age = Number(bot.time.bigAge)
bot.emit('update_time', oldTime)
})
}
module.exports = { bot, client }

12
plugins/uuid_map.js Normal file
View file

@ -0,0 +1,12 @@
function inject (bot) {
bot.uuidMap = {}
bot._client.on('player_info', (packet) => {
if (packet.action === 0)
packet.data.forEach((player) => {
bot.uuidMap[player.UUID] = player.name
})
})
}
module.exports = inject

View file

@ -1,59 +0,0 @@
const rfb = require('rfb2')
function inject (bot) {
const display = bot.chatCanvas
const displayCtx = display.getContext('2d')
const canvas = new display.constructor(640, 480)
const ctx = canvas.getContext('2d')
bot.vnc = {
connect,
connected: false,
display,
_client: null
}
function connect (options = {}) {
const r = rfb.createConnection(options)
bot.vnc.ended = false
r.on('connect', () => {
bot.vnc.connected = true
canvas.width = r.width
canvas.height = r.height
bot.core.run('minecraft:tellraw @a ' + JSON.stringify([
{ text: 'Connected to ', color: bot.colors.primary },
{ text: r.title, color: bot.colors.secondary }
]))
})
r.on('rect', rect => setImmediate(() => {
if (rect.encoding === rfb.encodings.raw) {
const id = ctx.createImageData(rect.width, rect.height)
for (let i = 0; i < id.data.length; i += 4) {
id.data[i] = rect.data[i + 2]
id.data[i + 1] = rect.data[i + 1]
id.data[i + 2] = rect.data[i]
id.data[i + 3] = 255
}
ctx.putImageData(id, rect.x, rect.y)
render()
} else if (rect.encoding === rfb.encodings.copyRect) {
ctx.drawImage(canvas, rect.src.x, rect.src.y, rect.width, rect.height, rect.x, rect.y)
// render()
}
}))
r.on('resize', ({ width, height }) => {
canvas.width = width
canvas.height = height
})
r.on('error', err => bot.tellraw({ text: 'VNC ' + err, color: bot.colors.error }))
r.on('end', () => (bot.vnc.ended = true))
bot.vnc._client = r
function render () {
displayCtx.drawImage(canvas, 0, 0, display.width, display.height) // draw image
display.render() // render it in mc
}
}
}
module.exports.bot = inject

View file

@ -1,7 +0,0 @@
while true
do
echo Starting Bot
node .
echo Restarting Bot in 6 Seconds...
sleep 6
done

View file

@ -1,101 +0,0 @@
// totallynotskidded™ from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
const incrementalPattern = /(?<colorCode>\xa7[0-9a-fk-orx])|(?<url>(?:(?:https?):\/\/)?(?:[-\w_\.]{2,}\.[a-z]{2,4}.*?(?=[\.\?!,;:]?(?:[\xa7 \n]|$))))|(?<newline>\n)/gi
const incrementalPatternKeepNewlines = /(?<colorCode>\xa7[0-9a-fk-orx])|(?<url>(?:(?:https?):\/\/)?(?:[-\w_\.]{2,}\.[a-z]{2,4}.*?(?=[\.\?!,;:]?(?:[\xa7 ]|$))))/gi
const colors = {
0: 'black',
1: 'dark_blue',
2: 'dark_green',
3: 'dark_aqua',
4: 'dark_red',
5: 'dark_purple',
6: 'gold',
7: 'gray',
8: 'dark_gray',
9: 'blue',
a: 'green',
b: 'aqua',
c: 'red',
d: 'light_purple',
e: 'yellow',
f: 'white',
r: 'reset'
}
const formatting = {
l: 'bold',
o: 'italic',
n: 'underline',
m: 'strikethrough',
k: 'obfuscated'
}
function parseString (message, keepNewlines, plain) {
const list = []
let currentChatComponent = { text: '' }
let modifier = {}
let currentIndex = 0
let hex = null
if (message == null) return currentChatComponent
list.push(currentChatComponent)
const pattern = keepNewlines ? incrementalPatternKeepNewlines : incrementalPattern
let needsAdd = false
for (const match of message.matchAll(pattern)) {
if (match.index > currentIndex) {
needsAdd = false
appendNewComponent(match.index)
}
const group = Object.keys(match.groups).find(key => match.groups[key] !== undefined)
switch (group) {
case 'colorCode': {
const c = match[0].toLowerCase().charAt(1)
if (c === 'x') hex = '#'
else if (hex != null) {
hex += c
if (hex.length === 7) {
modifier = { color: hex }
hex = null
}
}
else if (formatting[c] != null) modifier[formatting[c]] = true
else modifier = { color: colors[c] }
}
break
case 'url':
if (plain) appendNewComponent(match.index + match[0].length)
else {
let url = match[0]
if (!(url.startsWith("http://") || url.startsWith("https://"))) url = 'http://' + url
modifier.clickEvent = { action: 'open_url', value: url }
appendNewComponent(match.index + match[0].length)
}
break
case 'newline':
if (needsAdd) appendNewComponent(match.index)
currentChatComponent = null
}
currentIndex = match.index + match[0].length
}
if (currentIndex < message.length || needsAdd) appendNewComponent(message.length)
return list
function appendNewComponent (index) {
const addition = { text: message.substring(currentIndex, index), ...modifier }
currentIndex = index
if (currentChatComponent == null) {
currentChatComponent = { text: '' }
list.push(currentChatComponent)
}
currentChatComponent.extra ??= []
currentChatComponent.extra.push(addition)
}
}
module.exports = parseString

View file

@ -1,23 +0,0 @@
const { createHmac } = require('crypto')
function uuidToIntArray (uuid) {
return uuid.replace(/-/g, '').match(/.{8}/g).map(str => Number.parseInt(str, 16)).map(num => num & 0x80000000 ? num - 0xffffffff - 1 : num)
}
function getHash (message, uuid, key) {
const hmac = createHmac('sha256', uuid, key)
const time = Math.floor(new Date().getTime() / 6942)
const raw = message + '\\' + uuidToIntArray(uuid).join(';') + '\\' + time + '\\' + key
const hash = hmac.update(raw).digest()
const strHash = hash.toString('utf-8')
return strHash
}
function getCommand (message, uuid, key) {
const strHash = getHash(message.replace(/[\xa7&][0-9a-fkl-or]/g, ''), uuid, key)
return `${message} ${strHash.split('').map(c => '\xa7' + c).join('')}\xa7${String.fromCharCode(strHash.length)}\xa7`
}
module.exports = { getHash, getCommand }

View file

@ -1,16 +0,0 @@
const axios = require('axios')
async function dineval (code, options = {}) {
options.server ??= 'http://eval.dinhero21.repl.co'
options.colors ??= 'none'
const { data } = await axios.get(options.server, {
headers: {
data: code,
colors: options.colors
}
})
return data
}
module.exports = dineval

View file

@ -1,37 +0,0 @@
const { Buffer } = require('buffer')
function convertImageData (data, width, options = {}) {
// Default options
options.char ??= '⎮'
options.optimized ??= true
const components = ['[{"text":"']
const _jsonChar = options.char.replace(/[\\"]/g, m => '\\' + m)
let _lastColor = null
for (let i = 0; i < data.length; i += 4) {
const r = data[i]
const g = data[i + 1]
const b = data[i + 2]
let color = ''
if (r !== 0) color += r.toString(16)
if (g !== 0) color = color.padStart(2, '0') + g.toString(16).padStart(2, '0')
if (b !== 0) color = color.padStart(4, '0') + b.toString(16).padStart(2, '0')
color ||= '0'
if (_lastColor === color) components[components.length - 1] += _jsonChar
else components[components.length - 1] += `","color":"#${color}"},{"text":"${_jsonChar}`
_lastColor = color
if (((i / 4) % width) === 0) {
components[components.length - 1] += `","color":"#${color}"}]`
components.push('[{"text":"')
}
}
return components
}
module.exports = convertImageData

Some files were not shown because too many files have changed in this diff Show more