chipmunkbot3/plugins/player_data.js
2024-05-26 22:21:16 -04:00

91 lines
2.3 KiB
JavaScript

const fs = require('fs/promises')
const path = require('path')
const nbt = require('prismarine-nbt')
const PlayerData = require('../util/player_data')
const fileExists = require('../util/file_exists')
const getOfflineUUID = require('../util/offline_player_uuid')
const playerData = {}
async function inject (bot) {
const persistentDir = bot.paths.persistent
const playerDataDir = path.join(persistentDir, 'playerdata')
if (!await fileExists(playerDataDir)) await fs.mkdir(playerDataDir)
bot.playerData = playerData
bot.loadPlayerData = loadPlayerData
if (bot.loggedIn && bot.players) {
for (const player of bot.players) {
// If we logged in while the async file operations were happening (highly unlikely but possible), load the player data for the players on the server
handlePlayerAdded(player)
}
}
bot.on('player_added', handlePlayerAdded)
async function handlePlayerAdded (player) {
if (player.uuid === bot.uuid) return
let data = playerData[player.uuid]
if (data) {
data._bots.add(bot)
return
}
data = await loadPlayerData(player.username)
data._bots.add(bot)
playerData[player.uuid] = data
data.data.username = player.username
bot.emit('player_data_loaded', player, data)
}
async function loadPlayerData (uuid) {
if (uuid.length <= 16) {
// Usernames
uuid = getOfflineUUID(uuid)
}
const data = new PlayerData(path.join(playerDataDir, uuid + '.dat'))
await data.load()
return data
}
bot.on('player_removed', async player => {
const data = playerData[player.uuid]
if (!data) return
data._bots.delete(bot)
if (data._bots.size) return
bot.emit('player_data_unloading', player, data)
await data.unload(true)
delete bot.playerData[player.uuid]
})
}
async function saveAll () {
console.log('Saving player data...')
for (const uuid in playerData) {
const data = playerData[uuid]
if (!data?.data) {
// We _somehow_ found some unloaded data
delete playerData[uuid]
continue
}
try {
await data.save()
} catch (error) {
console.error('Unable to write data for player %s:', data?.data?.username, error)
}
}
console.log('Saved!')
}
setInterval(saveAll, 60 * 3 * 1000)
module.exports = inject