Terrain generation

This commit is contained in:
2026-03-13 16:34:09 -03:00
parent 96a485743f
commit 5348cd3d06
15 changed files with 320 additions and 98 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

+2 -2
View File
@@ -6,12 +6,12 @@ import { DebugSystem } from "$/client/systems/debug_system.ts";
import { UIInteractionSystem } from "$/client/systems/ui_interaction_system.ts"; import { UIInteractionSystem } from "$/client/systems/ui_interaction_system.ts";
import { UIRenderSystem } from "$/client/systems/ui_render_system.ts"; import { UIRenderSystem } from "$/client/systems/ui_render_system.ts";
import { create_main_menu } from "./main_menu.ts"; import { create_main_menu } from "./main_menu.ts";
import { ClickableSystem } from "./systems/clickable_system.ts";
import { start_game } from "./game.ts"; import { start_game } from "./game.ts";
import { canvas, resize_canvas } from "./renderer/mod.ts"; import { canvas, resize_canvas } from "./renderer/mod.ts";
import { DimensionLogicSystem } from "./systems/dimension_logic.ts"; import { DimensionLogicSystem } from "./systems/dimension_logic.ts";
import { Dimension } from "./components/dimension.ts"; import { Dimension } from "./components/dimension.ts";
import { GuiRenderSystem, GuiTickSystem } from "./gui/gui_systems.ts"; import { GuiRenderSystem, GuiTickSystem } from "./gui/gui_systems.ts";
import { WorldGenerationSystem } from "./systems/world_generation_system.ts";
export class ClientWorld extends World { export class ClientWorld extends World {
paused = false; paused = false;
@@ -39,9 +39,9 @@ export class ClientWorld extends World {
this.add_system(new UIInteractionSystem(), "main_menu"); this.add_system(new UIInteractionSystem(), "main_menu");
this.add_system(new UIInteractionSystem(), "paused"); this.add_system(new UIInteractionSystem(), "paused");
this.add_system(new GuiTickSystem(), "game"); this.add_system(new GuiTickSystem(), "game");
this.add_system(new ClickableSystem(), "game");
this.add_system(new PlayerControlsSystem(), "game"); this.add_system(new PlayerControlsSystem(), "game");
this.add_system(new MovementSystem(), "game"); this.add_system(new MovementSystem(), "game");
this.add_system(new WorldGenerationSystem(), "game");
this.add_system(new DimensionLogicSystem(), "game"); this.add_system(new DimensionLogicSystem(), "game");
// render systems // render systems
+50 -19
View File
@@ -2,7 +2,8 @@ import { Component } from "$/common/ecs/mod.ts";
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
import { AssetManager } from "../assets.ts"; import { AssetManager } from "../assets.ts";
import { ClientWorld } from "../client_world.ts"; import { ClientWorld } from "../client_world.ts";
import { Texture } from "../renderer/mod.ts"; import { generate_chunk } from "../generation.ts";
import { gl, Texture } from "../renderer/mod.ts";
export interface Block<T = unknown> { export interface Block<T = unknown> {
x: number; x: number;
@@ -13,17 +14,18 @@ export interface Block<T = unknown> {
tickable?: boolean; tickable?: boolean;
} }
export const CHUNK_SIDE_SIZE = 16; export const CHUNK_SIZE = 16;
export const CHUNK_HEIGHT = 128; export const CHUNK_HEIGHT = 128;
export const CHUNK_AREA = CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE; export const CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
export interface Chunk { export interface Chunk {
x: number; x: number;
z: number; z: number;
blocks: Int32Array; blocks: Int32Array;
generated: boolean;
dirty: boolean;
vertexBuffer?: WebGLBuffer; vertexBuffer?: WebGLBuffer;
vertexCount?: number; vertexCount?: number;
dirty: boolean;
vertexTransparentBuffer?: WebGLBuffer; vertexTransparentBuffer?: WebGLBuffer;
vertexTransparentCount?: number; vertexTransparentCount?: number;
} }
@@ -35,14 +37,14 @@ export class Dimension extends Component {
tick_timer = 0; tick_timer = 0;
add_chunk(x: number, z: number) { add_chunk(x: number, z: number) {
const chunk = { x, z, blocks: new Int32Array(CHUNK_AREA * CHUNK_HEIGHT), dirty: true }; const chunk = { x, z, blocks: new Int32Array(CHUNK_AREA * CHUNK_HEIGHT), dirty: true, generated: false };
this.chunks.push(chunk); this.chunks.push(chunk);
return chunk; return chunk;
} }
add_block(world: ClientWorld, block: Block) { add_block(block: Block) {
const block_chunk_x = Math.floor(block.x / CHUNK_SIDE_SIZE); const block_chunk_x = Math.floor(block.x / CHUNK_SIZE);
const block_chunk_z = Math.floor(block.z / CHUNK_SIDE_SIZE); const block_chunk_z = Math.floor(block.z / CHUNK_SIZE);
let chunk = this.chunks.find((chunk) => chunk.x === block_chunk_x && chunk.z === block_chunk_z); let chunk = this.chunks.find((chunk) => chunk.x === block_chunk_x && chunk.z === block_chunk_z);
if (!chunk) { if (!chunk) {
chunk = this.add_chunk(block_chunk_x, block_chunk_z); chunk = this.add_chunk(block_chunk_x, block_chunk_z);
@@ -50,21 +52,21 @@ export class Dimension extends Component {
const [nid, block_info] = EverythingRegistry.get_full<TileRegistry>("blocks", block.id)!; const [nid, block_info] = EverythingRegistry.get_full<TileRegistry>("blocks", block.id)!;
const lx = block.x - block_chunk_x * CHUNK_SIDE_SIZE; const lx = block.x - block_chunk_x * CHUNK_SIZE;
const lz = block.z - block_chunk_z * CHUNK_SIDE_SIZE; const lz = block.z - block_chunk_z * CHUNK_SIZE;
const ly = block.y; const ly = block.y;
const index = ly * CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE + lz * CHUNK_SIDE_SIZE + lx; const index = ly * CHUNK_SIZE * CHUNK_SIZE + lz * CHUNK_SIZE + lx;
chunk.blocks[index] = nid; chunk.blocks[index] = nid;
if (block_info?.on_create) { if (block_info?.on_create) {
block_info?.on_create(world, block); block_info?.on_create(this, block);
} }
} }
get_block(x: number, y: number, z: number) { get_block(x: number, y: number, z: number) {
const chunk_x = Math.floor(x / CHUNK_SIDE_SIZE); const chunk_x = Math.floor(x / CHUNK_SIZE);
const chunk_z = Math.floor(z / CHUNK_SIDE_SIZE); const chunk_z = Math.floor(z / CHUNK_SIZE);
const chunk = this.chunks.find( const chunk = this.chunks.find(
(c) => c.x === chunk_x && c.z === chunk_z, (c) => c.x === chunk_x && c.z === chunk_z,
@@ -74,11 +76,11 @@ export class Dimension extends Component {
return 0; return 0;
} }
const lx = x - chunk_x * CHUNK_SIDE_SIZE; const lx = x - chunk_x * CHUNK_SIZE;
const lz = z - chunk_z * CHUNK_SIDE_SIZE; const lz = z - chunk_z * CHUNK_SIZE;
const ly = y; const ly = y;
const index = ly * CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE + lz * CHUNK_SIDE_SIZE + lx; const index = ly * CHUNK_SIZE * CHUNK_SIZE + lz * CHUNK_SIZE + lx;
return chunk.blocks[index]; return chunk.blocks[index];
} }
@@ -99,9 +101,38 @@ export class Dimension extends Component {
const y = Math.floor(index / CHUNK_AREA); const y = Math.floor(index / CHUNK_AREA);
const rem = index % CHUNK_AREA; const rem = index % CHUNK_AREA;
const z = Math.floor(rem / CHUNK_SIDE_SIZE); const z = Math.floor(rem / CHUNK_SIZE);
const x = rem % CHUNK_SIDE_SIZE; const x = rem % CHUNK_SIZE;
return [x, y, z]; return [x, y, z];
} }
load_chunk(cx: number, cz: number) {
generate_chunk(this, cx, cz);
const chunk = this.chunks.find((c) => c.x === cx && c.z === cz);
if (chunk) {
chunk.generated = true;
chunk.dirty = true;
}
}
unload_chunk(cx: number, cz: number) {
const chunk_i = this.chunks.findIndex((c) => c.x === cx && c.z === cz);
if (chunk_i === -1) {
console.warn("Tried unloading a chunk that doesn't exist dumbass");
return;
}
this.delete_chunk_mesh(this.chunks[chunk_i]);
this.chunks.splice(chunk_i, 1);
}
delete_chunk_mesh(chunk: Chunk) {
if (chunk.vertexBuffer) {
gl.deleteBuffer(chunk.vertexBuffer);
}
if (chunk.vertexTransparentBuffer) {
gl.deleteBuffer(chunk.vertexTransparentBuffer);
}
}
} }
+1 -1
View File
@@ -2,7 +2,7 @@ import { Component } from "$/common/ecs/mod.ts";
import { KeyCode } from "$/client/input_manager.ts"; import { KeyCode } from "$/client/input_manager.ts";
export class PlayerControls extends Component { export class PlayerControls extends Component {
move_speed: number = 5; move_speed: number = 50;
// Keys // Keys
move_forward: KeyCode = "KeyW"; move_forward: KeyCode = "KeyW";
-2
View File
@@ -5,7 +5,6 @@ import { Dimension } from "./components/dimension.ts";
import { create_player } from "./player.ts"; import { create_player } from "./player.ts";
import { UIButton } from "./components/ui_components.ts"; import { UIButton } from "./components/ui_components.ts";
import { open_about } from "./about.ts"; import { open_about } from "./about.ts";
import { generate } from "./generation.ts";
import { canvas } from "./renderer/mod.ts"; import { canvas } from "./renderer/mod.ts";
export function start_game(world: ClientWorld) { export function start_game(world: ClientWorld) {
@@ -16,7 +15,6 @@ export function start_game(world: ClientWorld) {
world.dimension = new Dimension(); world.dimension = new Dimension();
dimension.add(world.dimension); dimension.add(world.dimension);
world.add_entity(dimension); world.add_entity(dimension);
generate(world, dimension.get(Dimension)!, 16 * 8, 16 * 8);
create_player(world); create_player(world);
+196 -31
View File
@@ -1,46 +1,211 @@
import { Alea, create_noise_2d } from "@paulaboks/rng"; import { Alea, create_noise_2d, NoiseFunction2D } from "@paulaboks/rng";
import { CHUNK_SIZE, Dimension } from "./components/dimension.ts";
import { Dimension } from "./components/dimension.ts"; type Biome =
import { ClientWorld } from "./client_world.ts"; | "desert"
| "plains"
| "forest"
| "jungle"
| "tundra"
| "taiga"
| "snow"
| "savanna"
| "swamp";
export function generate( function get_biome(temp: number, moisture: number): Biome {
world: ClientWorld, if (temp > 0.6) {
dimension: Dimension, if (moisture < -0.2) {
width: number, return "desert";
depth: number, }
max_height = 64, if (moisture > 0.4) {
seed = "seed", return "jungle";
) { }
return "savanna";
}
if (temp > 0) {
if (moisture > 0.5) {
return "swamp";
}
if (moisture > 0) {
return "forest";
}
return "plains";
}
if (temp > -0.5) {
return "taiga";
}
return "tundra";
}
function get_surface_block(biome: Biome) {
if (biome === "desert") {
return "bworld:sand";
} else if (biome === "tundra") {
return "bworld:snow";
}
return "bworld:grass";
}
function biome_height_modifier(biome: Biome) {
if (biome === "desert") {
return 0.2;
}
if (biome === "plains") {
return 0.4;
}
if (biome === "forest") {
return 0.5;
}
if (biome === "jungle") {
return 0.45;
}
if (biome === "taiga") {
return 0.55;
}
if (biome === "tundra") {
return 0.35;
}
if (biome === "savanna") {
return 0.4;
}
if (biome === "swamp") {
return 0.35;
}
return 0.4;
}
function fractal_noise(noise: NoiseFunction2D, x: number, y: number, octaves = 2) {
let value = 0;
let amp = 1;
let freq = 1;
let max = 0;
for (let i = 0; i < octaves; i++) {
value += noise(x * freq, y * freq) * amp;
max += amp;
amp *= 0.5;
freq *= 2;
}
return value / max;
}
function get_terrain_height(base: number, biome: Biome, x: number, z: number, noise: NoiseFunction2D) {
const biomeMod = biome_height_modifier(biome);
const main = fractal_noise(noise, x * 0.003, z * 0.003) * 15;
const detail = fractal_noise(noise, x * 0.01, z * 0.01) * 3;
return Math.floor(base + biomeMod * 20 + main + detail);
}
function can_place_tree(tree_map: boolean[][], local_x: number, local_z: number) {
const TREE_SPACING = 4;
for (let dx = -TREE_SPACING; dx <= TREE_SPACING; dx++) {
for (let dz = -TREE_SPACING; dz <= TREE_SPACING; dz++) {
const nx = local_x + dx;
const nz = local_z + dz;
if (nx >= 0 && nx < CHUNK_SIZE && nz >= 0 && nz < CHUNK_SIZE && tree_map[nx][nz]) {
return false;
}
}
}
return true;
}
function place_tree(dimension: Dimension, x: number, y: number, z: number, biome: Biome) {
const height = Math.floor(Math.random() * 3) + (biome === "jungle" ? 8 : 4);
const trunk_block = "bworld:log";
const leaves_block = "bworld:leaves";
// if (biome === "jungle") {
// trunkBlock = "bworld:jungle_log";
// leavesBlock = "bworld:jungle_leaves";
// } else if (biome === "taiga") {
// leavesBlock = "bworld:spruce_leaves";
// }
for (let i = 0; i < height; i++) {
dimension.add_block({ x, y: y + i, z, id: trunk_block });
}
for (let dx = -2; dx <= 2; dx++) {
for (let dz = -2; dz <= 2; dz++) {
for (let dy = -1; dy <= 1; dy++) {
if (Math.abs(dx) + Math.abs(dz) + Math.abs(dy) <= 3) {
dimension.add_block({
x: x + dx,
y: y + height + dy,
z: z + dz,
id: leaves_block,
});
}
}
}
}
}
const TREE_THRESHOLD: Record<Biome, number> = {
forest: 0.5,
jungle: 0.3,
taiga: 0.6,
plains: 0.95,
desert: 1,
tundra: 1,
savanna: 0.65,
swamp: 0.5,
snow: 0.8,
};
function should_place_tree(feature_noise: NoiseFunction2D, biome: Biome, x: number, z: number) {
const n = feature_noise(x * 0.1, z * 0.1);
return n > (TREE_THRESHOLD[biome] ?? 0.8);
}
export function generate_chunk(dimension: Dimension, cx: number, cz: number, seed = "seed") {
const height_noise = create_noise_2d(new Alea(seed + "_height")); const height_noise = create_noise_2d(new Alea(seed + "_height"));
const temp_noise = create_noise_2d(new Alea(seed + "_temp"));
const moisture_noise = create_noise_2d(new Alea(seed + "_moisture"));
const feature_noise = create_noise_2d(new Alea(seed + "_feature"));
const scale = 0.05; const biome_scale = 0.003;
const terrain_scale = 0.01;
for (let z = 0; z < depth; z++) { const tree_map: boolean[][] = Array.from({ length: CHUNK_SIZE }, () => Array(CHUNK_SIZE).fill(false));
for (let x = 0; x < width; x++) {
const nx = x * scale;
const nz = z * scale;
// multi-octave terrain for (let x = 0; x < CHUNK_SIZE; x++) {
let h = height_noise(nx, nz) * 1 + for (let z = 0; z < CHUNK_SIZE; z++) {
height_noise(nx * 2, nz * 2) * 0.5 + const wx = cx * CHUNK_SIZE + x;
height_noise(nx * 4, nz * 4) * 0.25; const wz = cz * CHUNK_SIZE + z;
h /= 1.75; const temp = temp_noise(wx * biome_scale, wz * biome_scale);
const moisture = moisture_noise(wx * biome_scale, wz * biome_scale);
const biome = get_biome(temp, moisture);
// convert noise to terrain height const height_noise_value = fractal_noise(height_noise, wx * terrain_scale, wz * terrain_scale);
const terrain_height = Math.floor((h * 0.5 + 0.5) * max_height); const base_height = (height_noise_value + 1) * 15 + 50;
const height = get_terrain_height(base_height, biome, wx, wz, height_noise);
for (let y = 0; y <= terrain_height; y++) { const surface_block = get_surface_block(biome);
let id = "bworld:stone";
// simple terrain layers for (let y = 0; y <= height; y++) {
if (y === terrain_height) { let block = "bworld:stone";
id = "bworld:leaves"; if (y === height) {
} else if (y > terrain_height - 4) { block = surface_block;
id = "bworld:dirt"; } else if (y > height - 4) {
block = "bworld:dirt";
} }
dimension.add_block(world, { x, y, z, id }); if (biome === "swamp" && y === height && Math.random() < 0.2) {
block = "bworld:water";
}
dimension.add_block({ x: wx, y, z: wz, id: block });
}
if (should_place_tree(feature_noise, biome, wx, wz) && can_place_tree(tree_map, x, z)) {
place_tree(dimension, wx, height + 1, wz, biome);
tree_map[x][z] = true;
} }
} }
} }
+1
View File
@@ -10,6 +10,7 @@ import { GuiScreen } from "./gui/gui_screen.ts";
export class PlayerComponent extends Component { export class PlayerComponent extends Component {
player_inventory = new PlayerInventory(""); player_inventory = new PlayerInventory("");
screens: GuiScreen[] = []; screens: GuiScreen[] = [];
render_distance = 6;
pop_screen() { pop_screen() {
const screen = this.screens.pop(); const screen = this.screens.pop();
-14
View File
@@ -1,14 +0,0 @@
import { System } from "$/common/ecs/mod.ts";
import { Position } from "$/common/components/position.ts";
import { Sprite } from "../components/sprite.ts";
import { ClientWorld } from "../client_world.ts";
import { ClickableSprite } from "../components/clickable.ts";
import { point_inside_rec } from "$/common/utils.ts";
import { InputManager } from "../input_manager.ts";
import { Camera } from "../components/camera.ts";
import { canvas } from "../renderer/mod.ts";
export class ClickableSystem extends System {
update(world: ClientWorld, _delta: number): void {
}
}
+4 -7
View File
@@ -1,5 +1,5 @@
import { distance_point_point, get_sprite_region } from "$/common/utils.ts"; import { distance_point_point, get_sprite_region } from "$/common/utils.ts";
import { Chunk, CHUNK_SIDE_SIZE, Dimension } from "$/client/components/dimension.ts"; import { Chunk, CHUNK_SIZE, Dimension } from "$/client/components/dimension.ts";
import { TEXTURE_SIZE } from "$/common/constants.ts"; import { TEXTURE_SIZE } from "$/common/constants.ts";
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
import { flush_buffer, gl, push_cube_to_mesh, set_current_texture } from "$/client/renderer/mod.ts"; import { flush_buffer, gl, push_cube_to_mesh, set_current_texture } from "$/client/renderer/mod.ts";
@@ -9,10 +9,7 @@ export function render_dimension(dimension: Dimension, camera: Camera) {
set_current_texture(dimension.image.tex); set_current_texture(dimension.image.tex);
for (const chunk of dimension.chunks) { for (const chunk of dimension.chunks) {
if (chunk.dirty) { if (chunk.dirty) {
if (chunk.vertexBuffer && chunk.vertexTransparentBuffer) { dimension.delete_chunk_mesh(chunk);
gl.deleteBuffer(chunk.vertexBuffer);
gl.deleteBuffer(chunk.vertexTransparentBuffer);
}
chunk.dirty = false; chunk.dirty = false;
make_chunk_mesh(chunk, dimension, camera); make_chunk_mesh(chunk, dimension, camera);
} }
@@ -80,8 +77,8 @@ function make_chunk_mesh(chunk: Chunk, dimension: Dimension, camera: Camera) {
const [x, y, z] = dimension.index_to_xyz(i); const [x, y, z] = dimension.index_to_xyz(i);
const wx = chunk.x * CHUNK_SIDE_SIZE + x; const wx = chunk.x * CHUNK_SIZE + x;
const wz = chunk.z * CHUNK_SIDE_SIZE + z; const wz = chunk.z * CHUNK_SIZE + z;
const show_face = (x: number, y: number, z: number) => { const show_face = (x: number, y: number, z: number) => {
const block = dimension.get_block(x, y, z); const block = dimension.get_block(x, y, z);
+43
View File
@@ -0,0 +1,43 @@
import { System } from "$/common/ecs/mod.ts";
import { ClientWorld } from "../client_world.ts";
import { Position } from "../../common/components/position.ts";
import { CHUNK_SIZE } from "../components/dimension.ts";
import { PlayerComponent } from "$/client/player.ts";
export class WorldGenerationSystem extends System {
constructor() {
super();
}
update(world: ClientWorld, _delta: number): void {
const [player] = world.get_tag("player")!;
const position = player.get(Position)!;
const player_component = player.get(PlayerComponent)!;
const dimension = world.dimension;
const player_chunk_x = Math.floor(position.x / CHUNK_SIZE);
const player_chunk_z = Math.floor(position.z / CHUNK_SIZE);
const render_distance = player_component.render_distance;
for (const chunk of dimension.chunks) {
if (Math.abs(chunk.x - player_chunk_x) > render_distance) {
dimension.unload_chunk(chunk.x, chunk.z);
}
if (Math.abs(chunk.z - player_chunk_z) > render_distance) {
dimension.unload_chunk(chunk.x, chunk.z);
}
}
for (let i = player_chunk_x - render_distance; i <= player_chunk_x + render_distance; i += 1) {
for (let j = player_chunk_z - render_distance; j <= player_chunk_z + render_distance; j += 1) {
const maybe_chunk = dimension.chunks.find((chunk) => chunk.x === i && chunk.z === j);
if (!maybe_chunk || !maybe_chunk.generated) {
console.log("loading chunk", i, j);
dimension.load_chunk(i, j);
return;
}
}
}
}
}
+2
View File
@@ -7,3 +7,5 @@ import "./chest.ts";
import "./furnace.ts"; import "./furnace.ts";
import "./stone.ts"; import "./stone.ts";
import "./log.ts"; import "./log.ts";
import "./sand.ts";
import "./snow.ts";
+6
View File
@@ -0,0 +1,6 @@
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
EverythingRegistry.register<TileRegistry>("blocks", "bworld:sand", {
texture_id: "bworld:sand",
has_collision: true,
});
+6
View File
@@ -0,0 +1,6 @@
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
EverythingRegistry.register<TileRegistry>("blocks", "bworld:snow", {
texture_id: "bworld:snow",
has_collision: true,
});
+1 -13
View File
@@ -1,18 +1,6 @@
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
import { WateringCanData } from "../items/watering_can.ts";
import { PlayerComponent } from "../player.ts";
EverythingRegistry.register<TileRegistry>("blocks", "bworld:water", { EverythingRegistry.register<TileRegistry>("blocks", "bworld:water", {
texture_id: "bworld:water", texture_id: "bworld:water",
has_collision: true, has_collision: false,
on_interact(world, _tile) {
const [player] = world.get_tag("player")!;
const player_inventory = player.get(PlayerComponent)!.player_inventory;
const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected);
if (maybe_item && maybe_item.type_id === "bworld:watering_can") {
const data = maybe_item.data as WateringCanData;
data.water = data.max_water;
}
},
}); });
+6 -7
View File
@@ -1,5 +1,4 @@
import { ClientWorld } from "$/client/client_world.ts"; import { Block, Dimension } from "$/client/components/dimension.ts";
import { Block } from "$/client/components/dimension.ts";
import { ItemStack } from "$/client/inventory.ts"; import { ItemStack } from "$/client/inventory.ts";
export class EverythingRegistry { export class EverythingRegistry {
@@ -55,11 +54,11 @@ export interface TileRegistry<T = unknown | undefined> {
has_collision: boolean; has_collision: boolean;
transparent?: boolean; transparent?: boolean;
on_create?(world: ClientWorld, tile: Block<T>): void; on_create?(dimension: Dimension, tile: Block<T>): void;
on_click?(world: ClientWorld, tile: Block<T>): void; on_click?(dimension: Dimension, tile: Block<T>): void;
on_interact?(world: ClientWorld, tile: Block<T>): void; on_interact?(dimension: Dimension, tile: Block<T>): void;
on_tick?(world: ClientWorld, tile: Block<T>, tick_delta: number): void; on_tick?(dimension: Dimension, tile: Block<T>, tick_delta: number): void;
on_second?(world: ClientWorld, tile: Block<T>, second_delta: number): void; on_second?(dimension: Dimension, tile: Block<T>, second_delta: number): void;
} }
export interface ItemRegistry<T = unknown | undefined> { export interface ItemRegistry<T = unknown | undefined> {