95 lines
2.6 KiB
JavaScript
95 lines
2.6 KiB
JavaScript
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
|