92 lines
2.3 KiB
JavaScript
92 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
|