Server
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Component } from "$/common/ecs/mod.ts";
|
||||
import { AIR_ID, BlockChange } from "$/common/protocol.ts";
|
||||
import { BlockRegistry, EverythingRegistry } from "$/common/everything_registry.ts";
|
||||
import { AIR, Faces, ID_MASK, VOID } from "../../common/constants.ts";
|
||||
import { AIR, CHUNK_AREA, CHUNK_HEIGHT, CHUNK_SIZE, Faces, ID_MASK, VOID } from "../../common/constants.ts";
|
||||
import { AssetManager } from "../assets.ts";
|
||||
import { ClientWorld } from "../client_world.ts";
|
||||
import { generate_chunk } from "../generation.ts";
|
||||
@@ -24,9 +25,7 @@ export interface Block {
|
||||
z: number;
|
||||
}
|
||||
|
||||
export const CHUNK_SIZE = 16;
|
||||
export const CHUNK_HEIGHT = 128;
|
||||
export const CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
||||
export { CHUNK_AREA, CHUNK_HEIGHT, CHUNK_SIZE };
|
||||
|
||||
export interface Chunk {
|
||||
x: number;
|
||||
@@ -47,10 +46,15 @@ export class Dimension extends Component {
|
||||
chunks: Chunk[] = [];
|
||||
second_timer = 0;
|
||||
tick_timer = 0;
|
||||
seed: string;
|
||||
|
||||
constructor(world: ClientWorld) {
|
||||
// blocks players changed from the generated terrain, per chunk, so they survive reloading chunks
|
||||
changes = new Map<string, Map<string, BlockChange>>();
|
||||
|
||||
constructor(world: ClientWorld, seed = "seed") {
|
||||
super();
|
||||
this.world = world;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
add_chunk(x: number, z: number) {
|
||||
@@ -200,8 +204,57 @@ export class Dimension extends Component {
|
||||
return [x, y, z];
|
||||
}
|
||||
|
||||
record_change(x: number, y: number, z: number, id: string) {
|
||||
const chunk_key = `${Math.floor(x / CHUNK_SIZE)},${Math.floor(z / CHUNK_SIZE)}`;
|
||||
let chunk_changes = this.changes.get(chunk_key);
|
||||
if (!chunk_changes) {
|
||||
chunk_changes = new Map();
|
||||
this.changes.set(chunk_key, chunk_changes);
|
||||
}
|
||||
chunk_changes.set(`${x},${y},${z}`, [x, y, z, id]);
|
||||
}
|
||||
|
||||
// call after the player changes a block so it gets saved and sent to the server
|
||||
sync_block(x: number, y: number, z: number) {
|
||||
const numeric_id = this.get_block(x, y, z);
|
||||
const id = numeric_id === AIR ? AIR_ID : EverythingRegistry.get_by_id<BlockRegistry>("blocks", numeric_id)?.id;
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
this.record_change(x, y, z, id);
|
||||
this.world.connection?.send({ type: "set_block", x, y, z, id });
|
||||
}
|
||||
|
||||
// set a block without drops or syncing, for changes that came from somewhere else
|
||||
apply_change(x: number, y: number, z: number, id: string) {
|
||||
const chunk = this.get_chunk(Math.floor(x / CHUNK_SIZE), Math.floor(z / CHUNK_SIZE));
|
||||
if (!chunk || !chunk.generated) {
|
||||
return;
|
||||
}
|
||||
|
||||
const current = this.get_block(x, y, z);
|
||||
if (id === AIR_ID) {
|
||||
if (current !== AIR) {
|
||||
this.break_block(x, y, z, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const nid = EverythingRegistry.get_id("blocks", id);
|
||||
if (nid === undefined || nid === current) {
|
||||
return;
|
||||
}
|
||||
this.add_block({ x, y, z, id });
|
||||
}
|
||||
|
||||
apply_chunk_changes(cx: number, cz: number) {
|
||||
for (const [x, y, z, id] of this.changes.get(`${cx},${cz}`)?.values() ?? []) {
|
||||
this.apply_change(x, y, z, id);
|
||||
}
|
||||
}
|
||||
|
||||
load_chunk(cx: number, cz: number) {
|
||||
generate_chunk(this, cx, cz);
|
||||
generate_chunk(this, cx, cz, this.seed);
|
||||
const chunk = this.get_chunk(cx, cz);
|
||||
if (chunk) {
|
||||
chunk.generated = true;
|
||||
@@ -221,6 +274,13 @@ export class Dimension extends Component {
|
||||
neighbor.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
// trees spill into neighboring chunks, so their changes need reapplying too
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
for (let dz = -1; dz <= 1; dz++) {
|
||||
this.apply_chunk_changes(cx + dx, cz + dz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unload_chunk(cx: number, cz: number) {
|
||||
|
||||
Reference in New Issue
Block a user