import { decode, encode } from "cbor-x"; import { Position } from "./classes.ts"; import { unlink, readFile, writeFile} from "node:fs/promises"; export class World { size: Position; data: Uint8Array; private dataView: DataView; name: string; // deno-lint-ignore no-explicit-any metadata: any = {}; constructor(size: Position, name: string) { this.size = size; this.name = name; this.data = new Uint8Array(4 + size.x * size.y * size.z); this.dataView = new DataView(this.data.buffer); this.dataView.setInt32(0, this.size.x * this.size.y * this.size.z, false); this.load(); } setBlock(pos: Position, block: number) { const szz = this.sizeToWorldSize(pos); this.dataView.setUint8(szz, block); } getBlock(pos: Position) { return this.dataView.getUint8(this.sizeToWorldSize(pos)); } findID(block: number): Position[] { const position: Position[] = []; for (let z = 0; z < this.size.z; z++) { for (let y = 0; y < this.size.y; y++) { for (let x = 0; x < this.size.x; x++) { if (this.getBlock({ z, y, x }) == block) { position.push({ z, y, x }); } } } } return position; } private sizeToWorldSize(pos: Position): number { return 4 + pos.x + this.size.z * (pos.z + this.size.x * pos.y); } getSpawn(): Position { return { x: Math.floor(this.size.x / 2) * 32, y: (Math.floor(this.size.y / 2) * 32) + 32, z: Math.floor(this.size.z / 2) * 32, }; } setLayer(y: number, type: number) { for (let i = 0; i < this.size.z; i += 1) { for (let b = 0; b < this.size.x; b += 1) { this.setBlock({ x: b, y, z: i, }, type); } } } async delete() { try { await unlink(`worlds/${this.name}.buf`) } catch { // gang } } private async load() { try { const ungziped = Bun.gunzipSync( await readFile(`worlds/${this.name}.buf`) ); if (!(ungziped instanceof Uint8Array)) return; const dv = new DataView(ungziped.buffer); const cborSize = dv.getUint32(0); this.metadata = decode(new Uint8Array(ungziped.buffer.slice(4, cborSize+4))); this.size = { x: this.metadata.x!, y: this.metadata.y!, z: this.metadata.z!, }; this.data = ungziped.slice(cborSize+4); this.dataView = new DataView(this.data.buffer); if(4 + this.size.x * this.size.y * this.size.z == this.data.length) { console.log('[WARNING] Encoding was wrong somewhere!') } } catch(e) { const layers = Math.floor(this.size.y / 2); for (let i = 0; i < layers; i += 1) { if (i === layers - 1) { this.setLayer(layers - 1, 2); } else { this.setLayer(i, 1); } } } } async save() { const metadata = { x: this.size.x!, y: this.size.y!, z: this.size.z!, ...this.metadata } const cborData = encode(metadata); const buffer = new Uint8Array(4 + cborData.byteLength + this.data.byteLength); const dv = new DataView(buffer.buffer); dv.setUint32(0, cborData.byteLength); buffer.set(cborData, 4); buffer.set(this.data, 4 + cborData.byteLength); await writeFile(`worlds/${this.name}.buf`, Bun.gzipSync(buffer)!); } }