const { parseText } = require('../util/chat/utility') const gamemodes = ['survival', 'creative', 'adventure', 'spectator'] function inject (bot) { bot.players = [] bot.on('packet.player_info', packet => { const usesBitfield = bot.supportFeature('playerInfoActionIsBitfield') let f if (usesBitfield) { if (packet.action & 1) f = addPlayer else f = updatePlayer } else { if (packet.action === 0) f = addPlayer else if (packet.action === 4) f = p => removePlayer(p.uuid) else f = updatePlayer } for (const player of packet.data) { const parsed = parsePlayer(player) f(parsed) } }) bot.on('packet.player_remove', packet => { for (const uuid of packet.players) { removePlayer(uuid) } }) function handleLegacyPlayerInfo (packet) { for (const player of packet.data) { switch (packet.action) { case 0: addPlayer(player); break case 4: removePlayer(player); break default: updatePlayer(player) } } } function addPlayer (player) { bot.players.filter(_player => _player.uuid !== player.uuid) // Remove duplicates bot.players.push(player) bot.emit('player_added', player) } function updatePlayer (player) { const target = bot.players.find(_player => _player.uuid === player.uuid) if (target == null) return for (const key in player) { if (player[key] == null) continue target[key] = player[key] } } async function removePlayer (uuid) { const target = bot.players.find(_player => _player.uuid === 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) continue if (match.match === target.username) { target.listed = false return } } bot.players = bot.players.filter(player => player.uuid !== uuid) bot.emit('player_removed', target) } // * It's backwards-compatible! (notice the fallbacks) function parsePlayer (player) { return { uuid: player.uuid ?? player.UUID, username: player.player?.name ?? player.name, properties: player.player?.properties ?? player.properties, chatSession: player.chatSession, // https://encyclopediadramatica.win/Shit_nobody_cares_about gamemode: gamemodes[player.gamemode], latency: player.latency ?? player.ping, displayName: player.displayName ? parseText(player.displayName) : undefined } } bot.on('end', () => (bot.players = [])) } module.exports = inject