120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
import { add_player_hotbar, add_player_inventory, GuiInventoryScreen, Slot } from "./gui_screen.ts";
|
|
import { canvas, draw_rect, draw_texture_region, Texture } from "$/client/renderer/mod.ts";
|
|
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 "../rendering/render_utils.ts";
|
|
import { get_sprite_region } from "$/client/sprites.ts";
|
|
import { ClientInventories } from "../inventory.ts";
|
|
|
|
const PADDING = 10;
|
|
|
|
// a screen opened by the server (chest, furnace, ...), drawn from the layout it sent
|
|
export class GuiContainer extends GuiInventoryScreen {
|
|
layout: ScreenLayout;
|
|
properties: Record<string, number>;
|
|
|
|
constructor(
|
|
inventories: ClientInventories,
|
|
send: (message: ClientMessage) => void,
|
|
layout: ScreenLayout,
|
|
properties: Record<string, number>,
|
|
) {
|
|
super(inventories, send);
|
|
this.layout = layout;
|
|
this.properties = properties;
|
|
|
|
this.inventory_width = PADDING * 2 + SLOT_SIZE * 9;
|
|
this.inventory_height = PADDING * 4 + SLOT_SIZE * (4 + layout.rows);
|
|
|
|
add_player_hotbar(this, PADDING, PADDING);
|
|
add_player_inventory(this, PADDING, PADDING * 2 + SLOT_SIZE);
|
|
|
|
const area_y = PADDING * 3 + SLOT_SIZE * 4;
|
|
for (const slot of layout.slots) {
|
|
this.slots.push(
|
|
new Slot("screen", slot.index, PADDING + slot.x * SLOT_SIZE, area_y + slot.y * SLOT_SIZE, slot.output),
|
|
);
|
|
}
|
|
}
|
|
|
|
override on_render(): void {
|
|
draw_rect(0, 0, canvas.width, canvas.height, [0, 0, 0, 0.8]);
|
|
|
|
const ui = AssetManager.instance.get<Texture>("bworld:ui");
|
|
|
|
draw_nine_slice(
|
|
ui,
|
|
160,
|
|
0,
|
|
16,
|
|
16,
|
|
4,
|
|
4,
|
|
4,
|
|
4,
|
|
this.x,
|
|
this.y,
|
|
this.inventory_width,
|
|
this.inventory_height,
|
|
);
|
|
|
|
this.draw_bars();
|
|
|
|
super.on_render();
|
|
}
|
|
|
|
draw_bars() {
|
|
const atlas = AssetManager.instance.get<Texture>("bworld:textures");
|
|
const area_y = PADDING * 3 + SLOT_SIZE * 4;
|
|
|
|
for (const bar of this.layout.bars) {
|
|
const x = this.x + PADDING + bar.x * SLOT_SIZE;
|
|
const y = this.y + area_y + bar.y * SLOT_SIZE;
|
|
const max = this.properties[bar.max] ?? 0;
|
|
const pct = max > 0 ? Math.max(0, Math.min(1, (this.properties[bar.value] ?? 0) / max)) : 0;
|
|
|
|
const empty = get_sprite_region(bar.empty_texture);
|
|
draw_texture_region(
|
|
atlas,
|
|
empty.x * TEXTURE_SIZE,
|
|
empty.y * TEXTURE_SIZE,
|
|
TEXTURE_SIZE,
|
|
TEXTURE_SIZE,
|
|
x,
|
|
y,
|
|
SLOT_SIZE,
|
|
SLOT_SIZE,
|
|
);
|
|
|
|
const full = get_sprite_region(bar.full_texture);
|
|
if (bar.direction === "right") {
|
|
draw_texture_region(
|
|
atlas,
|
|
full.x * TEXTURE_SIZE,
|
|
full.y * TEXTURE_SIZE,
|
|
TEXTURE_SIZE * pct,
|
|
TEXTURE_SIZE,
|
|
x,
|
|
y,
|
|
SLOT_SIZE * pct,
|
|
SLOT_SIZE,
|
|
);
|
|
} else {
|
|
// fills from the bottom up
|
|
draw_texture_region(
|
|
atlas,
|
|
full.x * TEXTURE_SIZE,
|
|
full.y * TEXTURE_SIZE + TEXTURE_SIZE * (1 - pct),
|
|
TEXTURE_SIZE,
|
|
TEXTURE_SIZE * pct,
|
|
x,
|
|
y + SLOT_SIZE * (1 - pct),
|
|
SLOT_SIZE,
|
|
SLOT_SIZE * pct,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|