91 lines
2.3 KiB
JavaScript
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')
|
|
|
|
bot.playerData = playerData
|
|
bot.loadPlayerData = loadPlayerData
|
|
|
|
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.substring(0, 2) + '/' + uuid.substring(2) + '.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)
|
|
|
|
try {
|
|
await data.unload(true)
|
|
} catch (error) {
|
|
console.error('Failed to unload data for player %s (%s):', data?.data?.username, data?.filename, error)
|
|
try {
|
|
console.error('Contents:', JSON.stringify(data))
|
|
} catch {
|
|
console.log('Unable to print contents')
|
|
}
|
|
}
|
|
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 (%s):', data?.data?.username, data?.filepath, error)
|
|
}
|
|
}
|
|
console.log('Saved!')
|
|
}
|
|
setInterval(saveAll, 60 * 3 * 1000)
|
|
|
|
module.exports = inject
|