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