No more ecs
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { canvas, draw_rect, draw_text } from "$/client/renderer/mod.ts";
|
||||
|
||||
const LINE_HEIGHT = 24;
|
||||
const VISIBLE_SECONDS = 10;
|
||||
const MAX_LINES = 10;
|
||||
const MAX_HISTORY = 100;
|
||||
|
||||
interface ChatLine {
|
||||
text: string;
|
||||
time: number;
|
||||
}
|
||||
|
||||
// the chat log, like minecraft's ChatComponent
|
||||
export class ChatComponent {
|
||||
lines: ChatLine[] = [];
|
||||
|
||||
add(text: string) {
|
||||
this.lines.push({ text, time: performance.now() });
|
||||
if (this.lines.length > MAX_HISTORY) {
|
||||
this.lines.shift();
|
||||
}
|
||||
}
|
||||
|
||||
// above the bottom left corner. `all` shows old messages too, for when the chat is open
|
||||
render(all: boolean, bottom = canvas.height - 100) {
|
||||
const now = performance.now();
|
||||
const lines = this.lines
|
||||
.filter((line) => all || now - line.time < VISIBLE_SECONDS * 1000)
|
||||
.slice(-MAX_LINES);
|
||||
|
||||
let y = bottom - lines.length * LINE_HEIGHT;
|
||||
for (const line of lines) {
|
||||
draw_rect(0, y, 600, LINE_HEIGHT, [0, 0, 0, 0.4]);
|
||||
draw_text(line.text, 4, y, 2, [1, 1, 1, 1]);
|
||||
y += LINE_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { Client } from "$/client/client.ts";
|
||||
import { DebugUI } from "$/client/debug_ui.ts";
|
||||
|
||||
// f3: every entity's fields, editable
|
||||
export class DebugOverlay {
|
||||
render(client: Client) {
|
||||
DebugUI.begin("Entities", 10, 10, 300);
|
||||
|
||||
for (const entity of client.level.entities.values()) {
|
||||
if (DebugUI.collapsing_header(`${entity.constructor.name} - ${entity.id}`)) {
|
||||
this.#render_fields(entity);
|
||||
}
|
||||
}
|
||||
if (DebugUI.collapsing_header("Camera")) {
|
||||
this.#render_fields(client.camera);
|
||||
}
|
||||
if (DebugUI.collapsing_header("Options")) {
|
||||
this.#render_fields(client.options);
|
||||
}
|
||||
|
||||
DebugUI.end();
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
#render_fields(object: any) {
|
||||
for (const key in object) {
|
||||
const value = object[key];
|
||||
if (typeof value === "number") {
|
||||
object[key] = DebugUI.float_input(key, value);
|
||||
} else if (typeof value === "string") {
|
||||
object[key] = DebugUI.text_input(key, value);
|
||||
} else if (typeof value === "boolean") {
|
||||
object[key] = DebugUI.checkbox(key, value);
|
||||
} else if (Array.isArray(value)) {
|
||||
DebugUI.text(`${key}: ${JSON.stringify(value.slice(0, 10))}`);
|
||||
} else if (value && typeof value === "object" && value.constructor !== Object) {
|
||||
// other objects like the level point back at this one, only name them
|
||||
DebugUI.text(`${key}: ${value.constructor.name}`);
|
||||
} else {
|
||||
DebugUI.text(`${key}: ${JSON.stringify(value)}`);
|
||||
}
|
||||
DebugUI.separator();
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-13
@@ -1,29 +1,27 @@
|
||||
import { GuiScreen } from "./gui_screen.ts";
|
||||
import { canvas, draw_rect, draw_text, measure_text } from "$/client/renderer/mod.ts";
|
||||
import { InputManager } from "../input_manager.ts";
|
||||
import { ClientWorld } from "../client_world.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
import type { Client } from "../client.ts";
|
||||
import { MAX_CHAT_LENGTH } from "$/common/protocol.ts";
|
||||
import { render_chat_log } from "../systems/rendering/network.ts";
|
||||
|
||||
export class GuiChat extends GuiScreen {
|
||||
world: ClientWorld;
|
||||
client: Client;
|
||||
|
||||
text_typed = "";
|
||||
caret = 0;
|
||||
key_repeat_timer = 0;
|
||||
show_caret = true;
|
||||
|
||||
constructor(world: ClientWorld) {
|
||||
constructor(client: Client) {
|
||||
super();
|
||||
this.world = world;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
override on_render(): void {
|
||||
draw_rect(0, 0, canvas.width, canvas.height, [0, 0, 0, 0.8]);
|
||||
|
||||
const y = canvas.height - 32;
|
||||
render_chat_log(this.world, true, y - 8);
|
||||
this.client.chat.render(true, y - 8);
|
||||
draw_rect(0, y, canvas.width, canvas.height, [0, 0, 0, 0.4]);
|
||||
|
||||
draw_text(this.text_typed, 0, y, 2, [1, 1, 1]);
|
||||
@@ -103,14 +101,10 @@ export class GuiChat extends GuiScreen {
|
||||
submit() {
|
||||
// commands like /give run on the server too
|
||||
if (this.text_typed.trim().length > 0) {
|
||||
this.world.connection.send({ type: "chat", text: this.text_typed });
|
||||
this.client.connection.send({ type: "chat", text: this.text_typed });
|
||||
}
|
||||
this.text_typed = "";
|
||||
|
||||
const [player] = this.world.get_tag("player")!;
|
||||
const player_component = player.get(PlayerComponent);
|
||||
if (player_component) {
|
||||
player_component.pop_screen();
|
||||
}
|
||||
this.client.pop_screen();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { canvas, draw_rect, draw_texture_region, Texture } from "$/client/render
|
||||
import { AssetManager } from "../assets.ts";
|
||||
import { SLOT_SIZE, TEXTURE_SIZE } from "$/common/constants.ts";
|
||||
import { ClientMessage, ScreenLayout } from "$/common/protocol.ts";
|
||||
import { draw_nine_slice } from "../systems/rendering/render_utils.ts";
|
||||
import { draw_nine_slice } from "../rendering/render_utils.ts";
|
||||
import { get_sprite_region } from "$/client/sprites.ts";
|
||||
import { ClientInventories } from "../inventory.ts";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { add_player_hotbar, add_player_inventory, GuiInventoryScreen, Slot } fro
|
||||
import { canvas, draw_rect, Texture } from "$/client/renderer/mod.ts";
|
||||
import { AssetManager } from "../assets.ts";
|
||||
import { SLOT_SIZE } from "../../common/constants.ts";
|
||||
import { draw_nine_slice } from "../systems/rendering/render_utils.ts";
|
||||
import { draw_nine_slice } from "../rendering/render_utils.ts";
|
||||
import { ClientInventories } from "../inventory.ts";
|
||||
import { ClientMessage, CRAFTING_RESULT_SLOT } from "$/common/protocol.ts";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { AssetManager } from "../assets.ts";
|
||||
import { InputManager } from "../input_manager.ts";
|
||||
import { ClientInventories } from "../inventory.ts";
|
||||
import { canvas, Texture } from "../renderer/mod.ts";
|
||||
import { draw_item, draw_nine_slice } from "../systems/rendering/render_utils.ts";
|
||||
import { draw_item, draw_nine_slice } from "../rendering/render_utils.ts";
|
||||
|
||||
export class Slot {
|
||||
container: ContainerKey;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { System } from "$/common/ecs/mod.ts";
|
||||
import { ClientWorld } from "../client_world.ts";
|
||||
import { PlayerComponent } from "../player.ts";
|
||||
|
||||
export class GuiRenderSystem extends System {
|
||||
update(world: ClientWorld, _delta: number): void {
|
||||
const [player] = world.get_tag("player")!;
|
||||
const player_component = player.get(PlayerComponent)!;
|
||||
|
||||
player_component.screens.at(-1)?.on_render();
|
||||
}
|
||||
}
|
||||
|
||||
export class GuiTickSystem extends System {
|
||||
update(world: ClientWorld, delta: number): void {
|
||||
const [player] = world.get_tag("player")!;
|
||||
const player_component = player.get(PlayerComponent)!;
|
||||
|
||||
player_component.screens.at(-1)?.on_tick(delta);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { SLOT_SIZE } from "$/common/constants.ts";
|
||||
import { AssetManager } from "$/client/assets.ts";
|
||||
import type { Client } from "$/client/client.ts";
|
||||
import type { ClientInventories } from "$/client/inventory.ts";
|
||||
import { draw_item, draw_nine_slice } from "$/client/rendering/render_utils.ts";
|
||||
import { canvas, draw_rect_stroke, Texture } from "$/client/renderer/mod.ts";
|
||||
|
||||
const PADDING = 10;
|
||||
const CROSSHAIR_SIZE = 8;
|
||||
|
||||
// what's drawn over the world while playing, like minecraft's Gui: hotbar, crosshair and chat
|
||||
export class Hud {
|
||||
render(client: Client) {
|
||||
this.#render_hotbar(client.player.inventories);
|
||||
this.#render_crosshair();
|
||||
client.chat.render(false);
|
||||
}
|
||||
|
||||
#render_hotbar(inventories: ClientInventories) {
|
||||
const ui = AssetManager.instance.get<Texture>("bworld:ui");
|
||||
|
||||
const hotbar_width = PADDING * 2 + SLOT_SIZE * 9;
|
||||
const hotbar_height = PADDING * 2 + SLOT_SIZE;
|
||||
|
||||
const x = canvas.width / 2 - hotbar_width / 2;
|
||||
const y = canvas.height - hotbar_height;
|
||||
|
||||
draw_nine_slice(ui, 160, 0, 16, 16, 4, 4, 4, 4, x, y, hotbar_width, hotbar_height);
|
||||
|
||||
for (let index = 0; index < 9; index += 1) {
|
||||
const selected = inventories.hotbar_selected === index;
|
||||
draw_nine_slice(
|
||||
ui,
|
||||
selected ? 19 * 16 : 160 + 32,
|
||||
selected ? 16 : 0,
|
||||
16,
|
||||
16,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
x + PADDING + index * SLOT_SIZE,
|
||||
y + PADDING,
|
||||
SLOT_SIZE,
|
||||
SLOT_SIZE,
|
||||
);
|
||||
}
|
||||
|
||||
for (let index = 0; index < 9; index += 1) {
|
||||
const item = inventories.inventory.get_item(index);
|
||||
if (item) {
|
||||
draw_item(item, x + PADDING + index * SLOT_SIZE, y + PADDING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#render_crosshair() {
|
||||
draw_rect_stroke(
|
||||
(canvas.width - CROSSHAIR_SIZE) / 2,
|
||||
(canvas.height - CROSSHAIR_SIZE) / 2,
|
||||
CROSSHAIR_SIZE,
|
||||
CROSSHAIR_SIZE,
|
||||
[0, 0, 0, 0.6],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user