cla66ic/classes/World.ts

135 lines
3.3 KiB
TypeScript
Raw Permalink Normal View History

2024-04-28 15:33:00 +00:00
import { decode, encode } from "cbor-x";
2022-06-01 22:30:34 +00:00
import { Position } from "./classes.ts";
2024-04-28 15:33:00 +00:00
import { unlink, readFile, writeFile} from "node:fs/promises";
2022-06-01 22:30:34 +00:00
export class World {
size: Position;
data: Uint8Array;
private dataView: DataView;
name: string;
// deno-lint-ignore no-explicit-any
2024-04-28 12:32:04 +00:00
metadata: any = {};
2022-06-01 22:30:34 +00:00
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[] {
2024-04-28 15:33:00 +00:00
const position: Position[] = [];
2022-06-01 22:30:34 +00:00
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 {
2024-04-28 15:33:00 +00:00
await unlink(`worlds/${this.name}.buf`)
2022-06-01 22:30:34 +00:00
} catch {
2024-04-28 12:32:04 +00:00
// gang
2022-06-01 22:30:34 +00:00
}
}
2024-04-28 12:32:04 +00:00
2022-06-01 22:30:34 +00:00
private async load() {
try {
2024-04-28 15:33:00 +00:00
const ungziped = Bun.gunzipSync(
await readFile(`worlds/${this.name}.buf`)
2022-06-01 22:30:34 +00:00
);
2024-04-28 12:32:04 +00:00
2022-06-01 22:30:34 +00:00
if (!(ungziped instanceof Uint8Array)) return;
2024-04-28 12:32:04 +00:00
const dv = new DataView(ungziped.buffer);
2022-06-01 22:30:34 +00:00
2024-04-28 12:32:04 +00:00
const cborSize = dv.getUint32(0);
2024-04-28 15:33:00 +00:00
this.metadata = decode(new Uint8Array(ungziped.buffer.slice(4, cborSize+4)));
2024-04-28 12:32:04 +00:00
2022-06-01 22:30:34 +00:00
this.size = {
2024-04-28 12:32:04 +00:00
x: this.metadata.x!,
y: this.metadata.y!,
z: this.metadata.z!,
2022-06-01 22:30:34 +00:00
};
2024-04-28 12:32:04 +00:00
this.data = ungziped.slice(cborSize+4);
2022-06-01 22:30:34 +00:00
this.dataView = new DataView(this.data.buffer);
2024-05-02 21:52:41 +00:00
if(4 + this.size.x * this.size.y * this.size.z == this.data.length) {
console.log('[WARNING] Encoding was wrong somewhere!')
}
2024-04-28 12:32:04 +00:00
} catch(e) {
2022-06-01 22:30:34 +00:00
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() {
2024-04-28 12:32:04 +00:00
const metadata = {
x: this.size.x!,
y: this.size.y!,
z: this.size.z!,
...this.metadata
}
2024-04-28 15:33:00 +00:00
const cborData = encode(metadata);
2024-04-28 12:32:04 +00:00
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);
2024-04-28 15:33:00 +00:00
await writeFile(`worlds/${this.name}.buf`, Bun.gzipSync(buffer)!);
2022-06-01 22:30:34 +00:00
}
}