new save format

This commit is contained in:
Holly Stubbs 2023-11-07 20:46:17 +00:00
parent 79f3ae1d4f
commit de4203d9f0
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E

View file

@ -10,7 +10,7 @@ import { Console } from "hsconsole";
export class WorldSaveManager { export class WorldSaveManager {
private readonly worldFolderPath; private readonly worldFolderPath;
private readonly oldWorldChunksFolderPath; private readonly globalDataPath;
private readonly worldPlayerDataFolderPath; private readonly worldPlayerDataFolderPath;
private readonly infoFilePath; private readonly infoFilePath;
@ -26,8 +26,8 @@ export class WorldSaveManager {
this.chunksOnDisk = new FunkyArray<number, Array<number>>(); this.chunksOnDisk = new FunkyArray<number, Array<number>>();
this.worldFolderPath = `./${config.worldName}`; this.worldFolderPath = `./${config.worldName}`;
this.oldWorldChunksFolderPath = `${this.worldFolderPath}/chunks`;
this.worldPlayerDataFolderPath = `${this.worldFolderPath}/playerdata`; this.worldPlayerDataFolderPath = `${this.worldFolderPath}/playerdata`;
this.globalDataPath = `${this.worldFolderPath}/data`;
this.infoFilePath = `${this.worldFolderPath}/info.hwd`; this.infoFilePath = `${this.worldFolderPath}/info.hwd`;
this.config = config; this.config = config;
@ -35,6 +35,7 @@ export class WorldSaveManager {
// Create world folder if it doesn't exist // Create world folder if it doesn't exist
if (!existsSync(this.worldFolderPath)) { if (!existsSync(this.worldFolderPath)) {
mkdirSync(this.worldFolderPath); mkdirSync(this.worldFolderPath);
mkdirSync(this.globalDataPath);
} }
if (existsSync(this.infoFilePath)) { if (existsSync(this.infoFilePath)) {
@ -49,11 +50,13 @@ export class WorldSaveManager {
const chunksArray = new Array<number>(); const chunksArray = new Array<number>();
this.chunksOnDisk.set(dimension, chunksArray); this.chunksOnDisk.set(dimension, chunksArray);
const chunkFolderPath = `${this.worldFolderPath}/DIM${dimension}`; const dimensionFolderPath = `${this.worldFolderPath}/DIM${dimension}`
if (!existsSync(chunkFolderPath)) { if (!existsSync(dimensionFolderPath)) {
mkdirSync(chunkFolderPath); mkdirSync(dimensionFolderPath);
mkdirSync(`${dimensionFolderPath}/chunks`);
mkdirSync(`${dimensionFolderPath}/data`);
} else { } else {
const chunkFiles = readdirSync(chunkFolderPath); const chunkFiles = readdirSync(`${dimensionFolderPath}/chunks`);
for (const file of chunkFiles) { for (const file of chunkFiles) {
if (file.endsWith(".hwc")) { if (file.endsWith(".hwc")) {
const name = file.split(".")[0]; const name = file.split(".")[0];
@ -71,7 +74,7 @@ export class WorldSaveManager {
private createInfoFile(numericalSeed:number) { private createInfoFile(numericalSeed:number) {
const infoFileWriter = createWriter(Endian.BE, 26); const infoFileWriter = createWriter(Endian.BE, 26);
infoFileWriter.writeUByte(0xFD); // Info File Magic infoFileWriter.writeUByte(0xFD); // Info File Magic
infoFileWriter.writeUByte(1); // File Version infoFileWriter.writeUByte(2); // File Version
infoFileWriter.writeLong(this.worldCreationDate.getTime()); // World creation date infoFileWriter.writeLong(this.worldCreationDate.getTime()); // World creation date
infoFileWriter.writeLong(this.worldLastLoadDate.getTime()); // Last load date infoFileWriter.writeLong(this.worldLastLoadDate.getTime()); // Last load date
infoFileWriter.writeLong(numericalSeed); infoFileWriter.writeLong(numericalSeed);
@ -86,7 +89,9 @@ export class WorldSaveManager {
} }
const fileVersion = infoFileReader.readByte(); const fileVersion = infoFileReader.readByte();
if (fileVersion === 0 || fileVersion === 1) { // v0, v1 and v2 all contain the same data apart from version numbers
// All that changed between them was the folder format.
if (fileVersion === 0 || fileVersion === 1 || fileVersion === 2) {
this.worldCreationDate = new Date(Number(infoFileReader.readLong())); this.worldCreationDate = new Date(Number(infoFileReader.readLong()));
infoFileReader.readLong(); // Last load time is currently ignored infoFileReader.readLong(); // Last load time is currently ignored
this.worldSeed = Number(infoFileReader.readLong()); this.worldSeed = Number(infoFileReader.readLong());
@ -97,6 +102,20 @@ export class WorldSaveManager {
renameSync(`${this.worldFolderPath}/chunks`, `${this.worldFolderPath}/DIM0`); renameSync(`${this.worldFolderPath}/chunks`, `${this.worldFolderPath}/DIM0`);
this.createInfoFile(this.worldSeed); this.createInfoFile(this.worldSeed);
} }
// Upgrade v1 to v2
if (fileVersion === 1) {
Console.printInfo("Upgrading world to format v2 from v1");
const files = readdirSync(`${this.worldFolderPath}/`);
for (const file of files) {
if (file.startsWith("DIM")) {
renameSync(`${this.worldFolderPath}/${file}`, `${this.worldFolderPath}/OLD${file}`);
mkdirSync(`${this.worldFolderPath}/${file}`);
mkdirSync(`${this.worldFolderPath}/${file}/data`);
renameSync(`${this.worldFolderPath}/OLD${file}`, `${this.worldFolderPath}/${file}/chunks`);
}
}
this.createInfoFile(this.worldSeed);
}
} }
} }
@ -123,7 +142,7 @@ export class WorldSaveManager {
chunkFileWriter.writeInt(chunkData.length); // Data length chunkFileWriter.writeInt(chunkData.length); // Data length
chunkFileWriter.writeBuffer(chunkData); // Chunk data chunkFileWriter.writeBuffer(chunkData); // Chunk data
writeFile(`${this.worldFolderPath}/DIM${chunk.world.dimension}/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => { writeFile(`${this.worldFolderPath}/DIM${chunk.world.dimension}/chunks/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => {
const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z); const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z);
if (!codArr?.includes(cPair)) { if (!codArr?.includes(cPair)) {
@ -141,7 +160,7 @@ export class WorldSaveManager {
chunkFileWriter.writeInt(data.length); chunkFileWriter.writeInt(data.length);
chunkFileWriter.writeBuffer(data); chunkFileWriter.writeBuffer(data);
writeFile(`${this.worldFolderPath}/DIM${chunk.world.dimension}/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => { writeFile(`${this.worldFolderPath}/DIM${chunk.world.dimension}/chunks/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => {
const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z); const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z);
if (!codArr?.includes(cPair)) { if (!codArr?.includes(cPair)) {
codArr?.push(cPair); codArr?.push(cPair);
@ -158,7 +177,7 @@ export class WorldSaveManager {
readChunkFromDisk(world:World, x:number, z:number) { readChunkFromDisk(world:World, x:number, z:number) {
return new Promise<Chunk>((resolve, reject) => { return new Promise<Chunk>((resolve, reject) => {
readFile(`${this.worldFolderPath}/DIM${world.dimension}/${Chunk.CreateCoordPair(x, z).toString(16)}.hwc`, (err, data) => { readFile(`${this.worldFolderPath}/DIM${world.dimension}/chunks/${Chunk.CreateCoordPair(x, z).toString(16)}.hwc`, (err, data) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }