chipmunkbot3/util/persistent_data.js

74 lines
1.6 KiB
JavaScript

const fs = require('fs/promises')
const path = require('path')
const { createWriteStream } = require('fs')
const zlib = require('zlib')
const stream = require('stream/promises')
const nbt = require('prismarine-nbt')
const fileExists = require('./file_exists')
class PersistentData {
#endianness
data = null
constructor (filepath) {
this.filepath = filepath
this.loaded = false
}
async load () {
const { parsed, type } = await this.#loadData(this.filepath, true)
this.data = this.parse(parsed)
this.#endianness = type
this.loaded = true
}
async #loadData (filepath, tryBackup) {
if (!await fileExists(filepath)) {
return { parsed: nbt.comp({}), type: 'big' }
}
const buffer = await fs.readFile(filepath)
try {
return nbt.parse(buffer)
} catch (error) {
if (tryBackup) return this.#loadData(filepath + '_old', false)
throw error
}
}
async save () {
await fs.mkdir(path.dirname(this.filepath), { recursive: true })
const data = this.unparse(this.data)
if (await fileExists(this.filepath)) await fs.copyFile(this.filepath, this.filepath + '_old') // Back up our data before a save
const gzip = zlib.createGzip()
const out = createWriteStream(this.filepath)
gzip.pipe(out)
gzip.write(nbt.writeUncompressed(data))
gzip.end()
await stream.finished(gzip)
}
async unload (save) {
if (save) await this.save()
this.data = null
this.#endianness = undefined
this.loaded = false
}
parse (data) {
return data
}
unparse (data) {
return data
}
}
module.exports = PersistentData