player refactor & stuff
This commit is contained in:
parent
9c23572db3
commit
9de7b08cee
13 changed files with 179 additions and 59767 deletions
18
bot.js
18
bot.js
|
@ -3,22 +3,6 @@ const { EventEmitter } = require('events')
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function createBots (servers = ['localhost'], options = {}) {
|
||||
const bots = []
|
||||
servers.forEach((server) => {
|
||||
const a = server.split(':')
|
||||
options.host = a[0]
|
||||
options.port = parseInt(a[1])
|
||||
options.brand = a[2]
|
||||
|
||||
const bot = createBot({ ...options })
|
||||
bot.getBots = () => bots
|
||||
bot.on('error', console.error) // "fix"
|
||||
bots.push(bot)
|
||||
})
|
||||
return bots
|
||||
}
|
||||
|
||||
function createBot (options = {}) {
|
||||
// defaults
|
||||
options.username ??= 'Bot'
|
||||
|
@ -138,4 +122,4 @@ function createBot (options = {}) {
|
|||
return bot
|
||||
}
|
||||
|
||||
module.exports = { createBot, createBots }
|
||||
module.exports = createBot
|
||||
|
|
|
@ -18,7 +18,7 @@ function execute (bot, cmd, player, args, handler) {
|
|||
case 'send':
|
||||
u = args.shift()
|
||||
message = args.join(' ')
|
||||
bot.sendMail(player.name, bot.players[u].name ?? u, message)
|
||||
bot.sendMail(player.name, u, message)
|
||||
bot.core.run(`minecraft:tellraw @a[nbt=${SNBT.stringify(nbt.comp({ UUID: toNBTUUID(player.UUID) }))}] ${JSON.stringify([
|
||||
{ text: 'Sent ', color: bot.colors.primary },
|
||||
{ text: message, color: bot.colors.secondary },
|
||||
|
|
16
default.json5
Normal file
16
default.json5
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
bots: [
|
||||
{
|
||||
host: 'localhost',
|
||||
port: 25565,
|
||||
brand: 'kaboom', // TODO: Rename this
|
||||
|
||||
username: ' ',
|
||||
prefix: "'",
|
||||
colors: { primary: 'green', secondary: 'dark_green', error: 'red' },
|
||||
version: '1.20.4',
|
||||
randomizeUsername: true,
|
||||
autoReconnect: true
|
||||
}
|
||||
]
|
||||
}
|
26
index.js
26
index.js
|
@ -1,12 +1,12 @@
|
|||
const readline = require('readline')
|
||||
const { createBots } = require('./bot.js')
|
||||
const createBot = require('./bot.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const moment = require('moment')
|
||||
const json5 = require('json5')
|
||||
|
||||
if (!fs.existsSync('config.json5')) {
|
||||
fs.copyFileSync(path.join(__dirname, 'default.json5'), 'config.json')
|
||||
fs.copyFileSync(path.join(__dirname, 'default.json5'), 'config.json5')
|
||||
console.info('No config file was found, so a default one was created.')
|
||||
}
|
||||
const config = json5.parse(fs.readFileSync('config.json5', 'utf-8'))
|
||||
|
@ -14,7 +14,7 @@ const config = json5.parse(fs.readFileSync('config.json5', 'utf-8'))
|
|||
const logdir = 'logs'
|
||||
if (!fs.existsSync(logdir)) fs.mkdirSync(logdir)
|
||||
|
||||
let logfile = path.join(logDir, moment().format('YYYY-MM-DD'))
|
||||
let logfile = path.join(logdir, moment().format('YYYY-MM-DD'))
|
||||
if (fs.existsSync(logfile)) {
|
||||
const pathWithSeparator = logfile + '-'
|
||||
let i = 0
|
||||
|
@ -22,7 +22,7 @@ if (fs.existsSync(logfile)) {
|
|||
logfile = pathWithSeparator + (i++)
|
||||
}
|
||||
}
|
||||
filepath += '.log'
|
||||
logfile += '.log'
|
||||
fs.writeFileSync(logfile, '')
|
||||
|
||||
const rl = readline.createInterface({
|
||||
|
@ -31,18 +31,12 @@ const rl = readline.createInterface({
|
|||
prefix: '> '
|
||||
})
|
||||
|
||||
const bots = createBots(servers, {
|
||||
username: ' ',
|
||||
prefix: "'",
|
||||
colors: { primary: 'green', secondary: 'dark_green', error: 'red' },
|
||||
version: '1.20.4',
|
||||
randomizeUsername: true,
|
||||
autoReconnect: true
|
||||
// 'online-mode': { enabled: false, username: 'removed lol', password: null }
|
||||
})
|
||||
for (const options of config.bots) {
|
||||
const bot = createBot(options)
|
||||
|
||||
bots.forEach((bot) => {
|
||||
bot.console.filepath = filepath
|
||||
bot.on('error', console.error)
|
||||
|
||||
bot.console.filepath = logfile
|
||||
bot.console.setRl(rl)
|
||||
bot.commands.loadFromDir('commands')
|
||||
})
|
||||
}
|
||||
|
|
9772
persistent/mail.json
9772
persistent/mail.json
File diff suppressed because one or more lines are too long
49927
persistent/seen.json
49927
persistent/seen.json
File diff suppressed because one or more lines are too long
|
@ -53,23 +53,23 @@ function bot (bot) {
|
|||
const msg = message.raw
|
||||
if (msg.match(/<.*§r> §r.*/g)) {
|
||||
if (packet.sender === '00000000-0000-0000-0000-000000000000') return
|
||||
const player = bot.players[packet.sender]
|
||||
const player = bot.players.find(player => player.uuid === packet.sender)
|
||||
const message = msg.split('§r> §r')[1]
|
||||
bot.emit('message', player, message)
|
||||
} else if (msg.match(/<.*> .*/g)) {
|
||||
if (packet.sender === '00000000-0000-0000-0000-000000000000') return
|
||||
const player = bot.players[packet.sender]
|
||||
const player = bot.players.find(player => player.uuid === packet.sender)
|
||||
const message = msg.split('> ')[1]
|
||||
bot.emit('message', player, message)
|
||||
} else if (msg.match(/.* .*§r:§r §.*/g)) {
|
||||
if (packet.sender === '00000000-0000-0000-0000-000000000000') return
|
||||
const player = bot.players[packet.sender]
|
||||
const player = bot.players.find(player => player.uuid === packet.sender)
|
||||
const message = msg.split('§r:§r ')[1].substring(2)
|
||||
bot.emit('message', player, message)
|
||||
} else if (msg.match(/§.*§b: \/.*/g)) {
|
||||
let username = msg.split('§b: ')[0]
|
||||
if (username.startsWith('§b')) { username = username.slice(2) }
|
||||
const player = bot.players[username]
|
||||
const player = bot.players.find(player => player.username === username)
|
||||
if (player == null) return
|
||||
const command = msg.split('§b: ')[1]
|
||||
bot.emit('cspy', player, command)
|
||||
|
|
|
@ -22,7 +22,7 @@ function inject (bot) {
|
|||
function sendFeedback (message) {
|
||||
bot.core.run('minecraft:tellraw @a ' + JSON.stringify(message))
|
||||
}
|
||||
bot.commands.execute(message.substring(bot.prefix.length), new CommandSource({ bot, sendFeedback }))
|
||||
bot.commands.execute(message.substring(bot.prefix.length), new CommandSource({ bot, player, sendFeedback }))
|
||||
})
|
||||
|
||||
function add (command) {
|
||||
|
@ -34,9 +34,10 @@ function inject (bot) {
|
|||
if (isValid(command)) {
|
||||
bot.console.warn(`Command '${command.aliases[0]}' is using the legacy command system!`)
|
||||
|
||||
const _execute = args => {
|
||||
const _execute = (c, args) => {
|
||||
try {
|
||||
command.execute(bot, command.aliases[0], {}, args)
|
||||
const player = c.source.player
|
||||
command.execute(bot, command.aliases[0], { UUID: player?.uuid, name: player?.username }, args)
|
||||
} catch (error) {
|
||||
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: error.toString(), color: 'red' }))
|
||||
}
|
||||
|
@ -44,10 +45,10 @@ function inject (bot) {
|
|||
|
||||
const node = bot.commands.dispatcher.register(
|
||||
literal(command.aliases[0])
|
||||
.executes(context => { _execute([]); return 0 })
|
||||
.executes(c => { _execute(c, []); return 0 })
|
||||
.then(
|
||||
argument('args', greedyString())
|
||||
.executes(context => { _execute(context.getArgument('args').split(' ')); return 0 })
|
||||
.executes(c => { _execute(c, c.getArgument('args').split(' ')); return 0 })
|
||||
)
|
||||
)
|
||||
for (let i = 1; i < command.aliases.length; i++) {
|
||||
|
|
|
@ -13,7 +13,7 @@ try {
|
|||
|
||||
// save it every 5 minutes
|
||||
setInterval(() => {
|
||||
fs.writeFileSync(filepath, JSON.stringify(mail, null, 2))
|
||||
fs.writeFileSync(filepath, JSON.stringify(mail))
|
||||
}, 5 * 6000)
|
||||
|
||||
// make the bot uuid ban blacklisted players
|
||||
|
|
|
@ -1,5 +1,89 @@
|
|||
const nbt = require('prismarine-nbt')
|
||||
|
||||
const gamemodes = ['survival', 'creative', 'adventure', 'spectator']
|
||||
|
||||
function inject (bot, client) {
|
||||
bot
|
||||
bot.players = []
|
||||
|
||||
client.on('player_info', packet => {
|
||||
for (const player of packet.data) {
|
||||
if (packet.action & 1) addPlayer(player)
|
||||
if (packet.action & 2) initializeChat(player)
|
||||
if (packet.action & 4) updateGamemode(player)
|
||||
if (packet.action & 8) updateListed(player)
|
||||
if (packet.action & 16) updateLatency(player)
|
||||
if (packet.action & 32) updateDisplayName(player)
|
||||
}
|
||||
})
|
||||
|
||||
function addPlayer (player) {
|
||||
bot.players.filter(_player => _player.uuid !== player.uuid) // Remove duplicates
|
||||
|
||||
const target = {
|
||||
uuid: player.uuid,
|
||||
username: player.player.name,
|
||||
properties: player.player.properties
|
||||
}
|
||||
bot.players.push(target)
|
||||
|
||||
bot.emit('player_added', target)
|
||||
}
|
||||
|
||||
function initializeChat (player) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
target.chatSession = player.chatSession
|
||||
}
|
||||
|
||||
function updateGamemode (player) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
target.gamemode = gamemodes[player.gamemode]
|
||||
}
|
||||
|
||||
function updateListed (player) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
target.listed = player.listed
|
||||
}
|
||||
|
||||
function updateLatency (player) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
target.latency = player.latency
|
||||
}
|
||||
|
||||
function updateDisplayName (player) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
target.displayName = nbt.simplify(player.displayName)
|
||||
}
|
||||
|
||||
async function removePlayer (uuid) {
|
||||
const target = bot.players.find(_player => _player.uuid === player.uuid)
|
||||
if (target == null) return
|
||||
|
||||
// Check that the player actually left
|
||||
const completions = await bot.tabComplete('scoreboard players add ')
|
||||
for (const match of completions.matches) {
|
||||
if (match.tooltip) return
|
||||
|
||||
if (match.match === target.username) {
|
||||
target.listed = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
bot.players = bot.players.filter(player => player.uuid !== uuid)
|
||||
bot.emit('player_removed', target)
|
||||
}
|
||||
|
||||
client.on('end', () => (bot.players = []))
|
||||
}
|
||||
|
||||
module.exports.client = inject
|
||||
|
|
|
@ -13,37 +13,31 @@ try {
|
|||
|
||||
// save it every 5 minutes
|
||||
setInterval(() => {
|
||||
fs.writeFileSync(filepath, JSON.stringify(seen, null, 2))
|
||||
fs.writeFileSync(filepath, JSON.stringify(seen))
|
||||
}, 5 * 6000)
|
||||
|
||||
// expose the data to the bot
|
||||
function bot (bot) {
|
||||
bot.seen = seen
|
||||
}
|
||||
|
||||
// add players to it
|
||||
function client (bot, client) {
|
||||
client.on('player_info', (packet) => {
|
||||
packet.data.forEach((player) => {
|
||||
if (player.UUID === client.uuid) return
|
||||
if (packet.action !== 0) {
|
||||
const name = bot.players[player.UUID]?.name
|
||||
if (seen[name] != null) seen[name].last = new Date()
|
||||
return
|
||||
}
|
||||
bot.on('player_added', player => {
|
||||
if (player.uuid === bot._client.uuid) return
|
||||
|
||||
seen[player.name] ??= {}
|
||||
if (seen[player.name].first == null) {
|
||||
seen[player.name].first = new Date()
|
||||
bot.core.run('minecraft:tellraw @a ' + JSON.stringify([
|
||||
{ text: 'Welcome ', color: bot.colors.primary },
|
||||
{ text: player.name, color: bot.colors.secondary },
|
||||
' to the server!'
|
||||
]))
|
||||
}
|
||||
seen[player.name].last = new Date()
|
||||
})
|
||||
seen[player.username] ??= {}
|
||||
if (seen[player.username].first == null) {
|
||||
seen[player.username].first = new Date()
|
||||
bot.core.run('minecraft:tellraw @a ' + JSON.stringify([
|
||||
{ text: 'Welcome ', color: bot.colors.primary },
|
||||
{ text: player.username, color: bot.colors.secondary },
|
||||
' to the server!'
|
||||
]))
|
||||
}
|
||||
seen[player.username].last = new Date()
|
||||
})
|
||||
|
||||
bot.on('player_removed', player => {
|
||||
if (seen[player.username] != null) seen[player.username].last = new Date()
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { bot, client }
|
||||
module.exports = { bot }
|
||||
|
|
24
plugins/tab_complete.js
Normal file
24
plugins/tab_complete.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
function inject (bot, client) {
|
||||
const transactions = {}
|
||||
let transactionId = 0
|
||||
|
||||
function tabComplete (text) {
|
||||
return new Promise(resolve => {
|
||||
transactions[transactionId] = resolve
|
||||
client.write('tab_complete', { transactionId, text })
|
||||
|
||||
transactionId = (transactionId + 1) % 256
|
||||
})
|
||||
}
|
||||
|
||||
client.on('tab_complete', packet => {
|
||||
if (!transactions[packet.transactionId]) return
|
||||
|
||||
transactions[packet.transactionId](packet)
|
||||
delete transactions[packet.transactionId]
|
||||
})
|
||||
|
||||
bot.tabComplete = tabComplete
|
||||
}
|
||||
|
||||
module.exports.client = inject
|
|
@ -1,6 +1,11 @@
|
|||
const { exceptions: { SimpleCommandExceptionType }, LiteralMessage } = require('brigadier-commands')
|
||||
|
||||
const COMMAND_MUST_BE_EXECUTED_BY_A_PLAYER_EXCEPTION = new SimpleCommandExceptionType(new LiteralMessage('Command must be executed by a player')) // TODO: Translations
|
||||
|
||||
class CommandSource {
|
||||
constructor ({ bot, permissionLevel = 0, sendFeedback = () => {} } = {}) {
|
||||
constructor ({ bot, player = null, permissionLevel = 0, sendFeedback = () => {} } = {}) {
|
||||
this.bot = bot
|
||||
this.player = player
|
||||
this.permissionLevel = permissionLevel
|
||||
this.sendFeedback = sendFeedback
|
||||
}
|
||||
|
@ -8,6 +13,11 @@ class CommandSource {
|
|||
sendError (error) {
|
||||
this.sendFeedback([{ text: '', color: 'red' }, error], false)
|
||||
}
|
||||
|
||||
getPlayerOrThrow () {
|
||||
if (this.player == null) throw COMMAND_MUST_BE_EXECUTED_BY_A_PLAYER_EXCEPTION.create()
|
||||
return this.player
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommandSource
|
||||
|
|
Loading…
Reference in a new issue