Cool 3d
This commit is contained in:
@@ -4,7 +4,7 @@ import { AssetManager } from "../assets.ts";
|
||||
import { ClientWorld } from "../client_world.ts";
|
||||
import { Texture } from "../renderer/mod.ts";
|
||||
|
||||
export interface Tile<T = unknown> {
|
||||
export interface Block<T = unknown> {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
@@ -13,35 +13,90 @@ export interface Tile<T = unknown> {
|
||||
tickable?: boolean;
|
||||
}
|
||||
|
||||
export const CHUNK_SIDE_SIZE = 16;
|
||||
export const CHUNK_HEIGHT = 128;
|
||||
export const CHUNK_AREA = CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE;
|
||||
|
||||
export interface Chunk {
|
||||
x: number;
|
||||
z: number;
|
||||
blocks: Int32Array;
|
||||
}
|
||||
|
||||
export class Dimension extends Component {
|
||||
image: Texture;
|
||||
tiles: Tile[];
|
||||
image: Texture = AssetManager.instance.get("bworld:textures");
|
||||
chunks: Chunk[] = [];
|
||||
second_timer = 0;
|
||||
tick_timer = 0;
|
||||
|
||||
constructor(tiles: Tile[]) {
|
||||
super();
|
||||
this.image = AssetManager.instance.get("bworld:textures");
|
||||
this.tiles = tiles;
|
||||
add_chunk(x: number, z: number) {
|
||||
const chunk = { x, z, blocks: new Int32Array(CHUNK_AREA * CHUNK_HEIGHT) };
|
||||
this.chunks.push(chunk);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
add_tile(world: ClientWorld, tile: Tile) {
|
||||
this.tiles.push(tile);
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||
if (tile_info?.on_create) {
|
||||
tile_info?.on_create(world, tile);
|
||||
add_block(world: ClientWorld, block: Block) {
|
||||
const block_chunk_x = Math.floor(block.x / CHUNK_SIDE_SIZE);
|
||||
const block_chunk_z = Math.floor(block.z / CHUNK_SIDE_SIZE);
|
||||
let chunk = this.chunks.find((chunk) => chunk.x === block_chunk_x && chunk.z === block_chunk_z);
|
||||
if (!chunk) {
|
||||
chunk = this.add_chunk(block_chunk_x, block_chunk_z);
|
||||
}
|
||||
|
||||
const [nid, block_info] = EverythingRegistry.get_full<TileRegistry>("blocks", block.id)!;
|
||||
|
||||
const lx = block.x - block_chunk_x * CHUNK_SIDE_SIZE;
|
||||
const lz = block.z - block_chunk_z * CHUNK_SIDE_SIZE;
|
||||
const ly = block.y;
|
||||
|
||||
const index = ly * CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE + lz * CHUNK_SIDE_SIZE + lx;
|
||||
|
||||
chunk.blocks[index] = nid;
|
||||
if (block_info?.on_create) {
|
||||
block_info?.on_create(world, block);
|
||||
}
|
||||
}
|
||||
|
||||
delete_tile(_world: ClientWorld, tile: Tile) {
|
||||
const index = this.tiles.indexOf(tile);
|
||||
if (index !== -1) {
|
||||
this.tiles.splice(index, 1);
|
||||
get_block(x: number, y: number, z: number) {
|
||||
const chunk_x = Math.floor(x / CHUNK_SIDE_SIZE);
|
||||
const chunk_z = Math.floor(z / CHUNK_SIDE_SIZE);
|
||||
|
||||
const chunk = this.chunks.find(
|
||||
(c) => c.x === chunk_x && c.z === chunk_z,
|
||||
);
|
||||
|
||||
if (!chunk) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||
const lx = x - chunk_x * CHUNK_SIDE_SIZE;
|
||||
const lz = z - chunk_z * CHUNK_SIDE_SIZE;
|
||||
const ly = y;
|
||||
|
||||
const index = ly * CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE + lz * CHUNK_SIDE_SIZE + lx;
|
||||
|
||||
return chunk.blocks[index];
|
||||
}
|
||||
|
||||
delete_tile(_world: ClientWorld, _block: Block) {
|
||||
// const index = this.blocks.indexOf(tile);
|
||||
// if (index !== -1) {
|
||||
// this.blocks.splice(index, 1);
|
||||
// }
|
||||
|
||||
// const tile_info = EverythingRegistry.get<TileRegistry>("blocks", tile.id);
|
||||
// if (tile_info?.on_delete) {
|
||||
// tile_info?.on_delete(world, tile);
|
||||
// }
|
||||
}
|
||||
|
||||
index_to_xyz(index: number) {
|
||||
const y = Math.floor(index / CHUNK_AREA);
|
||||
const rem = index % CHUNK_AREA;
|
||||
|
||||
const z = Math.floor(rem / CHUNK_SIDE_SIZE);
|
||||
const x = rem % CHUNK_SIDE_SIZE;
|
||||
|
||||
return [x, y, z];
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,10 +13,10 @@ export function start_game(world: ClientWorld) {
|
||||
world.clear_entities();
|
||||
|
||||
const dimension = new Entity("dimension");
|
||||
world.dimension = new Dimension([]);
|
||||
world.dimension = new Dimension();
|
||||
dimension.add(world.dimension);
|
||||
world.add_entity(dimension);
|
||||
generate(dimension.get(Dimension)!, 20, 20);
|
||||
generate(world, dimension.get(Dimension)!, 32, 32);
|
||||
|
||||
create_player(world);
|
||||
|
||||
|
||||
+26
-26
@@ -1,47 +1,47 @@
|
||||
import { Alea, create_noise_2d } from "@paulaboks/rng";
|
||||
|
||||
import { Dimension } from "./components/dimension.ts";
|
||||
import { ClientWorld } from "./client_world.ts";
|
||||
|
||||
export function generate(dimension: Dimension, width: number, height: number, seed = "seed") {
|
||||
export function generate(
|
||||
world: ClientWorld,
|
||||
dimension: Dimension,
|
||||
width: number,
|
||||
depth: number,
|
||||
max_height = 64,
|
||||
seed = "seed",
|
||||
) {
|
||||
const height_noise = create_noise_2d(new Alea(seed + "_height"));
|
||||
const tree_noise = create_noise_2d(new Alea(seed + "_trees"));
|
||||
|
||||
const scale = 0.05;
|
||||
|
||||
for (let z = 0; z < height; z++) {
|
||||
for (let z = 0; z < depth; z++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
// multi-octave terrain
|
||||
const nx = x * scale;
|
||||
const nz = z * scale;
|
||||
|
||||
let h = height_noise(nx, nz) * 1 + height_noise(nx * 2, nz * 2) * 0.5 + height_noise(nx * 4, nz * 4) * 0.25;
|
||||
// multi-octave terrain
|
||||
let h = height_noise(nx, nz) * 1 +
|
||||
height_noise(nx * 2, nz * 2) * 0.5 +
|
||||
height_noise(nx * 4, nz * 4) * 0.25;
|
||||
|
||||
h /= 1.75; // normalize
|
||||
h /= 1.75;
|
||||
|
||||
let id = "bworld:grass";
|
||||
// convert noise to terrain height
|
||||
const terrain_height = Math.floor((h * 0.5 + 0.5) * max_height);
|
||||
|
||||
if (h < -0.25) {
|
||||
id = "bworld:water";
|
||||
} else if (h < -0.15) {
|
||||
id = "bworld:sand";
|
||||
} else {
|
||||
for (let y = 0; y <= terrain_height; y++) {
|
||||
let id = "bworld:stone";
|
||||
|
||||
// simple terrain layers
|
||||
if (y === terrain_height) {
|
||||
id = "bworld:grass";
|
||||
} else if (y > terrain_height - 4) {
|
||||
id = "bworld:dirt";
|
||||
}
|
||||
|
||||
dimension.tiles.push({ x, z, id, y: 0 });
|
||||
|
||||
// tree placement
|
||||
/*if (id === "bworld:grass") {
|
||||
const t = tree_noise(x * 0.12, y * 0.12);
|
||||
|
||||
if (t > 0.65) {
|
||||
dimension.tiles.push({
|
||||
x,
|
||||
y,
|
||||
id: "bworld:tree",
|
||||
});
|
||||
}
|
||||
}*/
|
||||
dimension.add_block(world, { x, y, z, id });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { mat4 } from "gl-matrix";
|
||||
export let gl: WebGLRenderingContext;
|
||||
export let canvas: HTMLCanvasElement;
|
||||
|
||||
const MAX_SPRITES = 10000;
|
||||
const MAX_SPRITES = 100000;
|
||||
const VERTS_PER_SPRITE = 6;
|
||||
const FLOATS_PER_VERT = 9;
|
||||
|
||||
@@ -101,6 +101,9 @@ export function init_window(canvas_element: HTMLCanvasElement) {
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gl.cullFace(gl.BACK);
|
||||
gl.frontFace(gl.CCW);
|
||||
|
||||
create_white_texture();
|
||||
}
|
||||
|
||||
@@ -165,6 +168,7 @@ export function begin_mode_3d(new_camera: Camera) {
|
||||
camera = new_camera;
|
||||
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
|
||||
update_camera();
|
||||
}
|
||||
@@ -178,6 +182,7 @@ export function end_mode_3d() {
|
||||
|
||||
mode3d = false;
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.disable(gl.CULL_FACE);
|
||||
}
|
||||
|
||||
export function clear_background(r: number, g: number, b: number, a = 1) {
|
||||
|
||||
@@ -17,6 +17,12 @@ export function push_cube(
|
||||
g = 1,
|
||||
b = 1,
|
||||
a = 1,
|
||||
front = true,
|
||||
back = true,
|
||||
left = true,
|
||||
right = true,
|
||||
top = true,
|
||||
bottom = true,
|
||||
) {
|
||||
if (get_current_texture() !== texture.tex) {
|
||||
flush_batch();
|
||||
@@ -32,41 +38,58 @@ export function push_cube(
|
||||
const u1 = (sx + sw) / texture.width;
|
||||
const v1 = (sy + sh) / texture.height;
|
||||
|
||||
// front (+z)
|
||||
if (front) {
|
||||
push_vertex(x, y, z2, u0, v0, r, g, b, a);
|
||||
push_vertex(x2, y, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y2, z2, u0, v1, r, g, b, a);
|
||||
push_vertex(x2, y, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z2, u1, v1, r, g, b, a);
|
||||
push_vertex(x, y2, z2, u0, v1, r, g, b, a);
|
||||
}
|
||||
|
||||
// back (-z)
|
||||
if (back) {
|
||||
push_vertex(x2, y, z, u0, v0, r, g, b, a);
|
||||
push_vertex(x, y, z, u1, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z, u0, v1, r, g, b, a);
|
||||
push_vertex(x, y, z, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y2, z, u1, v1, r, g, b, a);
|
||||
push_vertex(x2, y2, z, u0, v1, r, g, b, a);
|
||||
}
|
||||
|
||||
// left (-x)
|
||||
if (left) {
|
||||
push_vertex(x, y, z, u0, v0, r, g, b, a);
|
||||
push_vertex(x, y, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y2, z, u0, v1, r, g, b, a);
|
||||
push_vertex(x, y, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y2, z2, u1, v1, r, g, b, a);
|
||||
push_vertex(x, y2, z, u0, v1, r, g, b, a);
|
||||
}
|
||||
|
||||
// right (+x)
|
||||
if (right) {
|
||||
push_vertex(x2, y, z2, u0, v0, r, g, b, a);
|
||||
push_vertex(x2, y, z, u1, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z2, u0, v1, r, g, b, a);
|
||||
push_vertex(x2, y, z, u1, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z, u1, v1, r, g, b, a);
|
||||
push_vertex(x2, y2, z2, u0, v1, r, g, b, a);
|
||||
}
|
||||
|
||||
// top (+y)
|
||||
if (top) {
|
||||
push_vertex(x, y2, z2, u0, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y2, z, u0, v1, r, g, b, a);
|
||||
push_vertex(x2, y2, z2, u1, v0, r, g, b, a);
|
||||
push_vertex(x2, y2, z, u1, v1, r, g, b, a);
|
||||
push_vertex(x, y2, z, u0, v1, r, g, b, a);
|
||||
}
|
||||
|
||||
// bottom (-y)
|
||||
if (bottom) {
|
||||
push_vertex(x, y, z, u0, v0, r, g, b, a);
|
||||
push_vertex(x2, y, z, u1, v0, r, g, b, a);
|
||||
push_vertex(x, y, z2, u0, v1, r, g, b, a);
|
||||
@@ -74,3 +97,4 @@ export function push_cube(
|
||||
push_vertex(x2, y, z2, u1, v1, r, g, b, a);
|
||||
push_vertex(x, y, z2, u0, v1, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export class DimensionLogicSystem extends System {
|
||||
const tile = dimension.tiles.findLast((tile) => tile.x === tile_x && tile.y === tile_y);
|
||||
|
||||
if (tile) {
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("blocks", tile.id);
|
||||
|
||||
if (!tile_info) {
|
||||
return;
|
||||
@@ -75,9 +75,9 @@ export class DimensionLogicSystem extends System {
|
||||
}*/
|
||||
}
|
||||
handle_second(world: ClientWorld, dimension: Dimension) {
|
||||
const tickables = dimension.tiles.filter((t) => t.tickable);
|
||||
const tickables = dimension.blocks.filter((t) => t.tickable);
|
||||
for (const tickable of tickables) {
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tickable.id);
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("blocks", tickable.id);
|
||||
if (tile_info && tile_info.on_second) {
|
||||
tile_info.on_second(world, tickable, dimension.second_timer);
|
||||
}
|
||||
@@ -86,9 +86,9 @@ export class DimensionLogicSystem extends System {
|
||||
}
|
||||
|
||||
handle_tick(world: ClientWorld, dimension: Dimension) {
|
||||
const tickables = dimension.tiles.filter((t) => t.tickable);
|
||||
const tickables = dimension.blocks.filter((t) => t.tickable);
|
||||
for (const tickable of tickables) {
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tickable.id);
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("blocks", tickable.id);
|
||||
if (tile_info && tile_info.on_tick) {
|
||||
tile_info.on_tick(world, tickable, dimension.tick_timer);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,40 @@
|
||||
import { get_sprite_region } from "$/common/utils.ts";
|
||||
import { Dimension } from "$/client/components/dimension.ts";
|
||||
import { Chunk, CHUNK_SIDE_SIZE, Dimension } from "$/client/components/dimension.ts";
|
||||
import { TEXTURE_SIZE } from "$/common/constants.ts";
|
||||
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||
import { push_cube } from "$/client/renderer/mod.ts";
|
||||
|
||||
export function render_dimension(dimension: Dimension /*, camera: Camera*/) {
|
||||
for (const tile of dimension.tiles) {
|
||||
let texture_id = tile.id;
|
||||
const tile_info = EverythingRegistry.get<TileRegistry>("tiles", tile.id);
|
||||
for (const chunk of dimension.chunks) {
|
||||
render_chunk(chunk, dimension);
|
||||
}
|
||||
}
|
||||
|
||||
function render_chunk(chunk: Chunk, dimension: Dimension) {
|
||||
const blocks_registry = EverythingRegistry.get_registry<TileRegistry>("blocks");
|
||||
for (let i = 0; i < chunk.blocks.length; i += 1) {
|
||||
const block_nid = chunk.blocks[i];
|
||||
if (block_nid === 0) {
|
||||
continue;
|
||||
}
|
||||
const [x, y, z] = dimension.index_to_xyz(i);
|
||||
|
||||
const wx = chunk.x * CHUNK_SIDE_SIZE + x;
|
||||
const wz = chunk.z * CHUNK_SIDE_SIZE + z;
|
||||
const front = dimension.get_block(wx, y, wz + 1) === 0;
|
||||
const back = dimension.get_block(wx, y, wz - 1) === 0;
|
||||
const left = dimension.get_block(wx - 1, y, wz) === 0;
|
||||
const right = dimension.get_block(wx + 1, y, wz) === 0;
|
||||
const top = dimension.get_block(wx, y + 1, wz) === 0;
|
||||
const bottom = dimension.get_block(wx, y - 1, wz) === 0;
|
||||
|
||||
const tile_info = blocks_registry[block_nid];
|
||||
let texture_id = "bworld:missing";
|
||||
if (tile_info?.texture_id) {
|
||||
if (typeof tile_info.texture_id === "string") {
|
||||
texture_id = tile_info.texture_id;
|
||||
} else {
|
||||
texture_id = tile_info.texture_id(tile);
|
||||
// texture_id = tile_info.texture_id(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +42,9 @@ export function render_dimension(dimension: Dimension /*, camera: Camera*/) {
|
||||
|
||||
push_cube(
|
||||
dimension.image,
|
||||
tile.x,
|
||||
tile.y,
|
||||
tile.z,
|
||||
wx,
|
||||
y,
|
||||
wz,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
@@ -30,6 +52,16 @@ export function render_dimension(dimension: Dimension /*, camera: Camera*/) {
|
||||
region.y * TEXTURE_SIZE,
|
||||
TEXTURE_SIZE,
|
||||
TEXTURE_SIZE,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
front,
|
||||
back,
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
bottom,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ interface TileChestData {
|
||||
inventory: Inventory;
|
||||
}
|
||||
|
||||
EverythingRegistry.register<TileRegistry<TileChestData>>("tiles", "bworld:chest", {
|
||||
EverythingRegistry.register<TileRegistry<TileChestData>>("blocks", "bworld:chest", {
|
||||
texture_id: "bworld:chest",
|
||||
has_collision: false,
|
||||
|
||||
|
||||
@@ -125,22 +125,22 @@ function create_crop_tile(crop_id: string) {
|
||||
}
|
||||
|
||||
EverythingRegistry.register<TileRegistry<TileCropData>>(
|
||||
"tiles",
|
||||
"blocks",
|
||||
"bworld:tomato_crop",
|
||||
create_crop_tile("bworld:tomato"),
|
||||
);
|
||||
EverythingRegistry.register<TileRegistry<TileCropData>>(
|
||||
"tiles",
|
||||
"blocks",
|
||||
"bworld:carrot_crop",
|
||||
create_crop_tile("bworld:carrot"),
|
||||
);
|
||||
EverythingRegistry.register<TileRegistry<TileCropData>>(
|
||||
"tiles",
|
||||
"blocks",
|
||||
"bworld:potato_crop",
|
||||
create_crop_tile("bworld:potato"),
|
||||
);
|
||||
EverythingRegistry.register<TileRegistry<TileCropData>>(
|
||||
"tiles",
|
||||
"blocks",
|
||||
"bworld:pumpkin_crop",
|
||||
create_crop_tile("bworld:pumpkin"),
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.t
|
||||
import { WateringCanData } from "../items/watering_can.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:dirt", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:dirt", {
|
||||
texture_id: "bworld:dirt",
|
||||
has_collision: false,
|
||||
|
||||
@@ -16,7 +16,7 @@ EverythingRegistry.register<TileRegistry>("tiles", "bworld:dirt", {
|
||||
},
|
||||
});
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_dirt", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:hoed_dirt", {
|
||||
texture_id: "bworld:hoed_dirt",
|
||||
has_collision: false,
|
||||
|
||||
@@ -50,7 +50,7 @@ EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_dirt", {
|
||||
},
|
||||
});
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_watered_dirt", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:hoed_watered_dirt", {
|
||||
texture_id: "bworld:hoed_watered_dirt",
|
||||
has_collision: false,
|
||||
|
||||
@@ -75,19 +75,19 @@ EverythingRegistry.register<TileRegistry>("tiles", "bworld:hoed_watered_dirt", {
|
||||
}
|
||||
|
||||
if (item.type_id === "bworld:tomato_seeds") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:tomato_crop", tickable: true });
|
||||
world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:tomato_crop", tickable: true });
|
||||
item.amount -= 1;
|
||||
player_inventory.container.set_item(player_inventory.hotbar_selected, item);
|
||||
} else if (item.type_id === "bworld:potato_seeds") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:potato_crop", tickable: true });
|
||||
world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:potato_crop", tickable: true });
|
||||
item.amount -= 1;
|
||||
player_inventory.container.set_item(player_inventory.hotbar_selected, item);
|
||||
} else if (item.type_id === "bworld:pumpkin_seeds") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:pumpkin_crop", tickable: true });
|
||||
world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:pumpkin_crop", tickable: true });
|
||||
item.amount -= 1;
|
||||
player_inventory.container.set_item(player_inventory.hotbar_selected, item);
|
||||
} else if (item.type_id === "bworld:carrot_seeds") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:carrot_crop", tickable: true });
|
||||
world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:carrot_crop", tickable: true });
|
||||
item.amount -= 1;
|
||||
player_inventory.container.set_item(player_inventory.hotbar_selected, item);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ interface TileChestData {
|
||||
fuel: number;
|
||||
}
|
||||
|
||||
EverythingRegistry.register<TileRegistry<TileChestData>>("tiles", "bworld:furnace", {
|
||||
EverythingRegistry.register<TileRegistry<TileChestData>>("blocks", "bworld:furnace", {
|
||||
texture_id: "bworld:furnace",
|
||||
has_collision: false,
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:grass", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:grass", {
|
||||
texture_id: "bworld:grass",
|
||||
has_collision: false,
|
||||
|
||||
@@ -12,9 +12,9 @@ EverythingRegistry.register<TileRegistry>("tiles", "bworld:grass", {
|
||||
if (item?.type_id === "bworld:hoe") {
|
||||
tile.id = "bworld:hoed_dirt";
|
||||
} else if (item?.type_id === "bworld:chest") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:chest" });
|
||||
// world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:chest" });
|
||||
} else if (item?.type_id === "bworld:furnace") {
|
||||
world.dimension.add_tile(world, { x: tile.x, y: tile.y, id: "bworld:furnace", tickable: true });
|
||||
// world.dimension.add_block(world, { x: tile.x, y: tile.y, id: "bworld:furnace", tickable: true });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,3 +5,4 @@ import "./crops.ts";
|
||||
import "./water.ts";
|
||||
import "./chest.ts";
|
||||
import "./furnace.ts";
|
||||
import "./stone.ts";
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts";
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:stone", {
|
||||
texture_id: "bworld:stone",
|
||||
has_collision: true,
|
||||
});
|
||||
@@ -2,7 +2,7 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.t
|
||||
import { ItemStack } from "../inventory.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:tree", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:tree", {
|
||||
texture_id: "bworld:tree",
|
||||
has_collision: false,
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.t
|
||||
import { WateringCanData } from "../items/watering_can.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
|
||||
EverythingRegistry.register<TileRegistry>("tiles", "bworld:water", {
|
||||
EverythingRegistry.register<TileRegistry>("blocks", "bworld:water", {
|
||||
texture_id: "bworld:water",
|
||||
has_collision: true,
|
||||
|
||||
|
||||
@@ -1,28 +1,64 @@
|
||||
import { ClientWorld } from "../client/client_world.ts";
|
||||
import { Tile } from "../client/components/dimension.ts";
|
||||
import { ItemStack } from "../client/inventory.ts";
|
||||
import { ClientWorld } from "$/client/client_world.ts";
|
||||
import { Block } from "$/client/components/dimension.ts";
|
||||
import { ItemStack } from "$/client/inventory.ts";
|
||||
|
||||
export class EverythingRegistry {
|
||||
static #registries = new Map<string, unknown>();
|
||||
static #key_to_id = new Map<string, Map<string, number>>();
|
||||
static #id_to_value = new Map<string, unknown[]>();
|
||||
|
||||
static register<T>(registry_name: string, key: string, value: T) {
|
||||
this.#registries.set(`${registry_name}__${key}`, value);
|
||||
static register<T>(registry: string, key: string, value: T) {
|
||||
if (!this.#key_to_id.has(registry)) {
|
||||
this.#key_to_id.set(registry, new Map());
|
||||
this.#id_to_value.set(registry, []);
|
||||
}
|
||||
|
||||
static get<T>(registry_name: string, key: string): T {
|
||||
return this.#registries.get(`${registry_name}__${key}`) as T;
|
||||
const key_map = this.#key_to_id.get(registry)!;
|
||||
const values = this.#id_to_value.get(registry)!;
|
||||
|
||||
const id = values.length + 1;
|
||||
|
||||
key_map.set(key, id);
|
||||
values[id] = value;
|
||||
}
|
||||
|
||||
static get<T>(registry: string, key: string): T | undefined {
|
||||
const id = this.#key_to_id.get(registry)?.get(key);
|
||||
if (id === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return this.#id_to_value.get(registry)?.[id] as T;
|
||||
}
|
||||
|
||||
static get_id(registry: string, key: string): number | undefined {
|
||||
return this.#key_to_id.get(registry)?.get(key);
|
||||
}
|
||||
|
||||
static get_full<T>(registry: string, key: string): [number, T] | undefined {
|
||||
const id = this.#key_to_id.get(registry)?.get(key);
|
||||
if (id === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return [id, this.#id_to_value.get(registry)?.[id] as T];
|
||||
}
|
||||
|
||||
static get_by_id<T>(registry: string, id: number): T | undefined {
|
||||
return this.#id_to_value.get(registry)?.[id] as T;
|
||||
}
|
||||
|
||||
static get_registry<T>(registry: string): T[] {
|
||||
return this.#id_to_value.get(registry) as T[];
|
||||
}
|
||||
}
|
||||
|
||||
export interface TileRegistry<T = unknown | undefined> {
|
||||
texture_id: string | ((tile: Tile<T>) => string);
|
||||
texture_id: string | ((tile: Block<T>) => string);
|
||||
has_collision: boolean;
|
||||
|
||||
on_create?(world: ClientWorld, tile: Tile<T>): void;
|
||||
on_click?(world: ClientWorld, tile: Tile<T>): void;
|
||||
on_interact?(world: ClientWorld, tile: Tile<T>): void;
|
||||
on_tick?(world: ClientWorld, tile: Tile<T>, tick_delta: number): void;
|
||||
on_second?(world: ClientWorld, tile: Tile<T>, second_delta: number): void;
|
||||
on_create?(world: ClientWorld, tile: Block<T>): void;
|
||||
on_click?(world: ClientWorld, tile: Block<T>): void;
|
||||
on_interact?(world: ClientWorld, tile: Block<T>): void;
|
||||
on_tick?(world: ClientWorld, tile: Block<T>, tick_delta: number): void;
|
||||
on_second?(world: ClientWorld, tile: Block<T>, second_delta: number): void;
|
||||
}
|
||||
|
||||
export interface ItemRegistry<T = unknown | undefined> {
|
||||
|
||||
Reference in New Issue
Block a user