Better world generation

This commit is contained in:
2026-09-25 17:14:26 -03:00
parent c750321ced
commit d07528bd0e
14 changed files with 1315 additions and 334 deletions
+2
View File
@@ -466,6 +466,8 @@ export class GameServer {
const saved = this.#saved_players[player.name];
if (saved) {
player.load(saved);
} else {
Object.assign(player, this.world.spawn_point());
}
this.#send(player, {
+35 -3
View File
@@ -6,9 +6,11 @@ import { AIR_ID, BlockChange } from "$/common/protocol.ts";
import { block_value, chunk_key, default_block_value } from "$/common/utils.ts";
import { LruMap } from "./lru.ts";
// generation only, rebuilt when needed. 128 KB each
const RAW_CACHE_SIZE = 256;
const CHUNK_CACHE_SIZE = 512;
// generation only, rebuilt when needed. 256 KB each
const RAW_CACHE_SIZE = 128;
const CHUNK_CACHE_SIZE = 256;
// how far from the middle of the world to look for dry land to spawn on, in chunks
const SPAWN_SEARCH_CHUNKS = 32;
// a block with state the server keeps, like a chest's items. never sent to clients as is
export interface Tile {
@@ -56,6 +58,36 @@ export class ServerWorld {
});
}
#spawn: { x: number; y: number; z: number } | undefined;
// where new players start: the dry land closest to the middle of the world, like minecraft's world spawn
spawn_point() {
if (!this.#spawn) {
this.#spawn = this.#find_spawn();
}
return this.#spawn;
}
#find_spawn() {
const water = this.block_ids["bworld:water"];
// chunks in rings around the middle, one column each
for (let radius = 0; radius <= SPAWN_SEARCH_CHUNKS; radius++) {
for (let cz = -radius; cz <= radius; cz++) {
for (let cx = -radius; cx <= radius; cx++) {
if (Math.max(Math.abs(cx), Math.abs(cz)) !== radius) continue;
const x = cx * CHUNK_SIZE + CHUNK_SIZE / 2;
const z = cz * CHUNK_SIZE + CHUNK_SIZE / 2;
let y = CHUNK_HEIGHT - 1;
while (y > 0 && this.get_block_nid(x, y, z) === AIR) y--;
if (y > 0 && this.get_block_nid(x, y, z) !== water) {
return { x: x + 0.5, y: y + 1, z: z + 0.5 };
}
}
}
}
return { x: 0.5, y: CHUNK_HEIGHT - 1, z: 0.5 };
}
get_block_id(x: number, y: number, z: number): string {
const nid = this.get_block_nid(x, y, z);
return nid === AIR ? AIR_ID : EverythingRegistry.get_by_id<BlockRegistry>("blocks", nid)?.id ?? AIR_ID;