From ada5d80023ae539ca925cc708ee595bc854274c9 Mon Sep 17 00:00:00 2001 From: paulaboks Date: Tue, 10 Mar 2026 17:43:58 -0300 Subject: [PATCH] Gui handler and basic inventory screen --- client/client_world.ts | 5 +- client/gui/gui_player_inventory.ts | 66 ++++++ client/gui/gui_screen.ts | 276 +++++++++++++++++++++++ client/gui/gui_systems.ts | 25 ++ client/{components => }/inventory.ts | 24 +- client/player.ts | 38 +++- client/systems/inventory_system.ts | 187 --------------- client/systems/player_controls.ts | 15 +- client/systems/render_system.ts | 13 +- client/systems/rendering/player.ts | 99 +------- client/systems/rendering/render_utils.ts | 2 +- client/tiles/crops.ts | 7 +- client/tiles/dirt.ts | 12 +- client/tiles/grass.ts | 4 +- client/tiles/tree.ts | 5 +- client/tiles/water.ts | 4 +- common/everything_registry.ts | 2 +- 17 files changed, 435 insertions(+), 349 deletions(-) create mode 100644 client/gui/gui_player_inventory.ts create mode 100644 client/gui/gui_screen.ts create mode 100644 client/gui/gui_systems.ts rename client/{components => }/inventory.ts (82%) delete mode 100644 client/systems/inventory_system.ts diff --git a/client/client_world.ts b/client/client_world.ts index ad769c9..978f914 100644 --- a/client/client_world.ts +++ b/client/client_world.ts @@ -3,7 +3,6 @@ import { MovementSystem } from "$/common/systems/movement_system.ts"; import { RenderSystem } from "$/client/systems/render_system.ts"; import { PlayerControlsSystem } from "$/client/systems/player_controls.ts"; import { DebugSystem } from "$/client/systems/debug_system.ts"; -import { InventorySystem } from "$/client/systems/inventory_system.ts"; import { UIInteractionSystem } from "$/client/systems/ui_interaction_system.ts"; import { UIRenderSystem } from "$/client/systems/ui_render_system.ts"; import { create_main_menu } from "./main_menu.ts"; @@ -12,6 +11,7 @@ import { start_game } from "./game.ts"; import { canvas, resize_canvas } from "./renderer.ts"; import { DimensionLogicSystem } from "./systems/dimension_logic.ts"; import { Dimension } from "./components/dimension.ts"; +import { GuiRenderSystem, GuiTickSystem } from "./gui/gui_systems.ts"; export class ClientWorld extends World { paused = false; @@ -39,13 +39,14 @@ export class ClientWorld extends World { this.add_system(new UIInteractionSystem(), "main_menu"); this.add_system(new UIInteractionSystem(), "paused"); this.add_system(new ClickableSystem(), "game"); - this.add_system(new InventorySystem(), "game"); this.add_system(new PlayerControlsSystem(), "game"); this.add_system(new MovementSystem(), "game"); this.add_system(new DimensionLogicSystem(), "game"); + this.add_system(new GuiTickSystem(), "game"); // render systems this.add_system(new RenderSystem(), "game"); + this.add_system(new GuiRenderSystem(), "game"); this.add_system(new DebugSystem(), "game"); this.add_system(new UIRenderSystem(), "main_menu"); this.add_system(new UIRenderSystem(), "paused"); diff --git a/client/gui/gui_player_inventory.ts b/client/gui/gui_player_inventory.ts new file mode 100644 index 0000000..b465e99 --- /dev/null +++ b/client/gui/gui_player_inventory.ts @@ -0,0 +1,66 @@ +import { Container, Inventory, PlayerInventory } from "../inventory.ts"; +import { add_player_hotbar, add_player_inventory, GuiScreen, Slot } from "./gui_screen.ts"; +import { canvas, draw_rect, Texture } from "$/client/renderer.ts"; +import { AssetManager } from "../assets.ts"; +import { SLOT_SIZE } from "../../common/constants.ts"; +import { draw_nine_slice } from "../systems/rendering/render_utils.ts"; + +const PADDING = 10; + +export class GuiPlayerInventory extends GuiScreen { + override inventory_width = PADDING * 2 + SLOT_SIZE * 9; + override inventory_height = PADDING * 2 + SLOT_SIZE * 4 + PADDING + SLOT_SIZE * 3 + PADDING; + + constructor(player_inventory: PlayerInventory) { + super(new Inventory(new Container(10)), player_inventory, undefined); + + add_player_hotbar(this, player_inventory, PADDING, PADDING); + add_player_inventory(this, player_inventory, PADDING, PADDING * 2 + SLOT_SIZE); + + const crafting_x = PADDING; + const crafting_y = PADDING * 3 + SLOT_SIZE * 4; + + for (let i = 0; i < 3; i += 1) { + for (let j = 0; j < 3; j += 1) { + this.slots.push( + new Slot(this.inventory, i * 3 + j, crafting_x + i * SLOT_SIZE, crafting_y + j * SLOT_SIZE), + ); + } + } + + this.slots.push(new Slot(this.inventory, 9, crafting_x + 5 * SLOT_SIZE, crafting_y + 1 * SLOT_SIZE)); + } + + override on_render(): void { + draw_rect(0, 0, canvas.width, canvas.height, [0, 0, 0, 0.8]); + + const ui = AssetManager.instance.get("bworld:ui"); + + draw_nine_slice( + ui, + 160, + 0, + 16, + 16, + 4, + 4, + 4, + 4, + this.x, + this.y, + this.inventory_width, + this.inventory_height, + ); + + super.on_render(); + } + + override on_close(): void { + for (let i = 0; i < this.inventory.container.size; i += 1) { + const item = this.inventory.container.get_item(i); + if (item) { + this.player_inventory.container.add_item(item); + } + } + } +} diff --git a/client/gui/gui_screen.ts b/client/gui/gui_screen.ts new file mode 100644 index 0000000..1760c9e --- /dev/null +++ b/client/gui/gui_screen.ts @@ -0,0 +1,276 @@ +import { SLOT_SIZE } from "$/common/constants.ts"; +import { point_inside_rec } from "../../common/utils.ts"; +import { AssetManager } from "../assets.ts"; +import { InputManager } from "../input_manager.ts"; +import { Inventory, ItemStack, PlayerInventory } from "../inventory.ts"; +import { canvas, Texture } from "../renderer.ts"; +import { draw_item, draw_nine_slice } from "../systems/rendering/render_utils.ts"; + +export class Slot { + inventory: Inventory; + index: number; + // relative to screen top left + x: number; + y: number; + + constructor(inventory: Inventory, index: number, x: number, y: number) { + this.inventory = inventory; + this.index = index; + this.x = x; + this.y = y; + } + + get item(): ItemStack | undefined { + return this.inventory.container.get_item(this.index); + } +} + +export class GuiScreen | undefined> { + inventory: Inv; + player_inventory: PlayerInventory; + properties: Properties; + + slots: Slot[] = []; + x: number = 0; + y: number = 0; + inventory_width: number = 500; + inventory_height: number = 500; + + constructor( + inventory: Inv, + player_inventory: PlayerInventory, + properties: Properties, + ) { + this.inventory = inventory; + this.player_inventory = player_inventory; + this.properties = properties; + } + + on_tick(_delta: number): void { + this.x = canvas.width / 2 - (this.inventory_width / 2); + this.y = canvas.height / 2 - (this.inventory_height / 2); + + this.handle_interaction(); + + if (this.player_inventory.holding_item?.amount === 0) { + this.player_inventory.holding_item = undefined; + } + } + + on_render(): void { + const ui = AssetManager.instance.get("bworld:ui"); + + for (const slot of this.slots) { + draw_nine_slice( + ui, + slot.inventory.hovering_slot === slot.index ? 19 * 16 : 160 + 32, + slot.inventory.hovering_slot === slot.index ? 16 : 0, + 16, + 16, + 4, + 4, + 4, + 4, + this.x + slot.x, + this.y + slot.y, + SLOT_SIZE, + SLOT_SIZE, + ); + } + + for (const slot of this.slots) { + const item = slot.item; + if (item) { + draw_item(item, this.x + slot.x, this.y + slot.y); + } + } + + if (this.player_inventory.holding_item) { + const mouse = InputManager.get_mouse_position(); + draw_item(this.player_inventory.holding_item, mouse.x, mouse.y); + } + } + + on_close(): void {} + + handle_interaction() { + this.player_inventory.hovering_slot = -1; + this.inventory.hovering_slot = -1; + for (const slot of this.slots) { + const mouse = InputManager.get_mouse_position(); + const slot_x = slot.x + this.x; + const slot_y = slot.y + this.y; + const hovering = point_inside_rec(mouse.x, mouse.y, slot_x, slot_y, SLOT_SIZE, SLOT_SIZE); + if (hovering) { + slot.inventory.hovering_slot = slot.index; + + if (InputManager.is_mouse_pressed(0)) { + InputManager.consume_mouse(0); + this.handle_left_click(slot); + return; + } + + if (InputManager.is_mouse_pressed(2)) { + InputManager.consume_mouse(2); + this.handle_right_click(slot); + return; + } + } + } + } + + switch_item_with_holding(inventory: Inventory, index: number) { + const container_slot = inventory.container.get_slot(index); + const original_holding_item = this.player_inventory.holding_item; + this.player_inventory.holding_item = container_slot.get_item(); + container_slot.set_item(original_holding_item); + } + + handle_left_click(slot: Slot) { + const holding = this.player_inventory.holding_item; + const inventory_slot = slot.inventory.container.get_slot(slot.index); + const slot_item = inventory_slot.get_item(); + + // if you aren't holding anything + // "swap" with nothing on your hand (pick it up) + if (!holding) { + this.switch_item_with_holding(slot.inventory, slot.index); + return; + } + + // if you are holding something and slot type equals holding type + // try to add to stack + if (slot_item && inventory_slot.type_id === holding.type_id) { + const space_left = inventory_slot.max_amount! - slot_item.amount!; + const amount_to_add = Math.min(space_left, holding.amount); + + slot_item.amount += amount_to_add; + holding.amount -= amount_to_add; + + return; + } + + // if something on hand but not the same + // swap + this.switch_item_with_holding(slot.inventory, slot.index); + } + + handle_right_click(slot: Slot) { + const holding = this.player_inventory.holding_item; + const inventory_slot = slot.inventory.container.get_slot(slot.index); + const slot_item = inventory_slot.get_item(); + + // if holding something + if (holding) { + // and slot type equals holding type + // add 1 to matching stack + if (slot_item && inventory_slot.type_id === holding.type_id) { + if (slot_item.amount < slot_item.max_amount!) { + slot_item.amount += 1; + holding.amount -= 1; + } + return; + } + + // (actually the same as the last one but creates a new one techinically) + // place 1 into empty slot + if (!slot_item) { + const new_item = holding.clone(); + new_item.amount = 1; + inventory_slot.set_item(new_item); + holding.amount -= 1; + return; + } + + // if something on hand but not the same + // swap + this.switch_item_with_holding(slot.inventory, slot.index); + return; + } + + // if player is holding nothing and clicks nothing, nothing happens + if (!slot_item) { + return; + } + + // pick up half of the stack + const original_amount = slot_item.amount; + const half = Math.floor(original_amount / 2); + + slot_item.amount = half; + + const picked_up = slot_item.clone(); + picked_up.amount = original_amount - half; + + this.player_inventory.holding_item = picked_up; + + if (slot_item.amount === 0) { + inventory_slot.set_item(undefined); + } + } + + /*handle_hotbar(world: ClientWorld, player_inventory: PlayerInventory) { + const [player, player_hand] = world.get_tag("player")!; + + const player_position = player.get(Position); + const player_sprite = player.get(AnimatedSprite); + const hand_position = player_hand.get(Position); + const hand_sprite = player_hand.get(Sprite); + + if (!player_position || !hand_position || !hand_sprite || !player_sprite) { + return; + } + + // sync position + hand_position.x = player_position.x + (player_sprite.flip_x ? 34 : 4); + hand_position.y = player_position.y + 34; + hand_sprite.flip_x = player_sprite.flip_x; + + const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected); + if (maybe_item) { + const region = get_sprite_region(maybe_item.type_id); + hand_sprite.source_x = region.x * 16; + hand_sprite.source_y = region.y * 16; + hand_sprite.source_width = 16; + hand_sprite.source_height = 16; + hand_sprite.width = 32; + hand_sprite.height = 32; + } else { + hand_sprite.width = 0; + hand_sprite.height = 0; + } + }*/ +} + +// generic methods that is often needed + +export function add_player_inventory( + handler: GuiScreen, + player_inventory: PlayerInventory, + offset_x: number, + offset_y: number, +) { + for (let i = 0; i < 3; ++i) { + for (let l = 0; l < 9; ++l) { + handler.slots.push( + new Slot( + player_inventory, + l + i * 9 + 9, + offset_x + l * SLOT_SIZE, + offset_y + i * SLOT_SIZE, + ), + ); + } + } +} + +export function add_player_hotbar( + handler: GuiScreen, + player_inventory: PlayerInventory, + offset_x: number, + offset_y: number, +) { + for (let i = 0; i < 9; ++i) { + handler.slots.push(new Slot(player_inventory, i, offset_x + i * SLOT_SIZE, offset_y)); + } +} diff --git a/client/gui/gui_systems.ts b/client/gui/gui_systems.ts new file mode 100644 index 0000000..b2d8076 --- /dev/null +++ b/client/gui/gui_systems.ts @@ -0,0 +1,25 @@ +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)!; + + for (const screen of player_component.screens) { + screen.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)!; + + for (const screen of player_component.screens) { + screen.on_tick(delta); + } + } +} diff --git a/client/components/inventory.ts b/client/inventory.ts similarity index 82% rename from client/components/inventory.ts rename to client/inventory.ts index 060bfb9..43c9f6a 100644 --- a/client/components/inventory.ts +++ b/client/inventory.ts @@ -1,5 +1,3 @@ -import { Component } from "$/common/ecs/mod.ts"; -import { SLOT_SIZE } from "$/common/constants.ts"; import { EverythingRegistry, ItemRegistry } from "$/common/everything_registry.ts"; export class ItemStack { @@ -108,18 +106,13 @@ export interface ContainerLayout { offset_y: number; } -export class Inventory extends Component { +export class Inventory { container: Container; - is_open: boolean = false; - layout: ContainerLayout; - hovering_slot: number = -1; - constructor(container: Container, layout: ContainerLayout) { - super(); + constructor(container: Container) { this.container = container; - this.layout = layout; } } @@ -130,18 +123,7 @@ export class PlayerInventory extends Inventory { constructor(owner_id: string) { const container = new Container(9 * 4); - const layout: ContainerLayout = { - slots: [], - offset_x: 10, - offset_y: 10, - }; - - for (let row = 0; row < 4; row += 1) { - for (let column = 0; column < 9; column += 1) { - layout.slots.push({ type: "*", x: column * SLOT_SIZE, y: row * SLOT_SIZE }); - } - } - super(container, layout); + super(container); this.owner_id = owner_id; } } diff --git a/client/player.ts b/client/player.ts index 9a6a0a3..08310b3 100644 --- a/client/player.ts +++ b/client/player.ts @@ -1,12 +1,25 @@ import { Position } from "$/common/components/position.ts"; import { Velocity } from "$/common/components/velocity.ts"; -import { Entity } from "$/common/ecs/mod.ts"; +import { Component, Entity } from "$/common/ecs/mod.ts"; import { Camera } from "$/client/components/camera.ts"; -import { ItemStack, PlayerInventory } from "$/client/components/inventory.ts"; +import { ItemStack, PlayerInventory } from "./inventory.ts"; import { PlayerControls } from "$/client/components/player_controls.ts"; import { AnimatedSprite, Sprite } from "$/client/components/sprite.ts"; import { ClientWorld } from "./client_world.ts"; import { AssetManager } from "./assets.ts"; +import { GuiScreen } from "./gui/gui_screen.ts"; + +export class PlayerComponent extends Component { + player_inventory = new PlayerInventory(""); + screens: GuiScreen[] = []; + + pop_screen() { + const screen = this.screens.pop(); + if (screen) { + screen.on_close(); + } + } +} export function create_player(world: ClientWorld) { const player = new Entity("player"); @@ -31,18 +44,19 @@ export function create_player(world: ClientWorld) { }, "idle"), ); player.add(new PlayerControls()); - // TODO: actual player ids - player.add(new PlayerInventory(player.id)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:pickaxe", 1, 1)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:hoe", 1, 1)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:watering_can", 1, 1)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:axe", 1, 1)); + + player.add(new PlayerComponent()); + const player_inventory = player.get(PlayerComponent)!.player_inventory; + player_inventory.container.add_item(new ItemStack("bworld:pickaxe", 1, 1)); + player_inventory.container.add_item(new ItemStack("bworld:hoe", 1, 1)); + player_inventory.container.add_item(new ItemStack("bworld:watering_can", 1, 1)); + player_inventory.container.add_item(new ItemStack("bworld:axe", 1, 1)); // player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:sword", 1, 1)); // player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:bomb", 64)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:tomato_seeds", 64)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:potato_seeds", 64)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:pumpkin_seeds", 64)); - player.get(PlayerInventory)!.container.add_item(new ItemStack("bworld:carrot_seeds", 64)); + player_inventory.container.add_item(new ItemStack("bworld:tomato_seeds", 64)); + player_inventory.container.add_item(new ItemStack("bworld:potato_seeds", 64)); + player_inventory.container.add_item(new ItemStack("bworld:pumpkin_seeds", 64)); + player_inventory.container.add_item(new ItemStack("bworld:carrot_seeds", 64)); player.add(new Camera(-100, -100)); world.add_entity(player); diff --git a/client/systems/inventory_system.ts b/client/systems/inventory_system.ts deleted file mode 100644 index 1660199..0000000 --- a/client/systems/inventory_system.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { System } from "$/common/ecs/mod.ts"; -import { get_sprite_region, point_inside_rec } from "$/common/utils.ts"; -import { SLOT_SIZE } from "$/common/constants.ts"; -import { Container, PlayerInventory } from "$/client/components/inventory.ts"; -import { InputManager } from "$/client/input_manager.ts"; -import { ClientWorld } from "$/client/client_world.ts"; -import { Position } from "../../common/components/position.ts"; -import { AnimatedSprite, Sprite } from "../components/sprite.ts"; -import { canvas } from "../renderer.ts"; - -export class InventorySystem extends System { - update(world: ClientWorld, _delta: number): void { - for (const entity of world.get_entities()) { - const player_inventory = entity.get(PlayerInventory); - - if (player_inventory) { - this.handle_interaction(player_inventory); - this.handle_hotbar(world, player_inventory); - } - } - } - - handle_interaction(player_inventory: PlayerInventory) { - const inventory_width = 10 * 2 + SLOT_SIZE * 9; - const inventory_height = 10 * 2 + SLOT_SIZE * 4; - - const offset_x = canvas.width / 2 - (inventory_width / 2); - const offset_y = canvas.height / 2 - (inventory_height / 2); - - player_inventory.hovering_slot = -1; - const container = player_inventory.container; - if (player_inventory.is_open) { - for (const [index, slot] of player_inventory.layout.slots.entries()) { - const mouse = InputManager.get_mouse_position(); - const slot_x = slot.x + player_inventory.layout.offset_x + offset_x; - const slot_y = slot.y + player_inventory.layout.offset_y + offset_y; - const hovering = point_inside_rec(mouse.x, mouse.y, slot_x, slot_y, SLOT_SIZE, SLOT_SIZE); - if (hovering) { - player_inventory.hovering_slot = index; - - if (InputManager.is_mouse_pressed(0)) { - InputManager.consume_mouse(0); - this.handle_left_click(player_inventory, container, index); - return; - } - - if (InputManager.is_mouse_pressed(2)) { - InputManager.consume_mouse(2); - this.handle_right_click(player_inventory, container, index); - return; - } - } - } - } else { - if (player_inventory.holding_item) { - container.add_item(player_inventory.holding_item); - player_inventory.holding_item = undefined; - } - } - - if (player_inventory.holding_item?.amount === 0) { - player_inventory.holding_item = undefined; - } - } - - switch_item_with_holding(player_inventory: PlayerInventory, index: number) { - const container_slot = player_inventory.container.get_slot(index); - const original_holding_item = player_inventory.holding_item; - player_inventory.holding_item = container_slot.get_item(); - container_slot.set_item(original_holding_item); - } - - handle_left_click(player_inventory: PlayerInventory, container: Container, index: number) { - const holding = player_inventory.holding_item; - const slot = container.get_slot(index); - const slot_item = slot.get_item(); - - // if you aren't holding anything - // "swap" with nothing on your hand (pick it up) - if (!holding) { - this.switch_item_with_holding(player_inventory, index); - return; - } - - // if you are holding something and slot type equals holding type - // try to add to stack - if (slot_item && slot.type_id === holding.type_id) { - const space_left = slot.max_amount! - slot_item.amount!; - const amount_to_add = Math.min(space_left, holding.amount); - - slot_item.amount += amount_to_add; - holding.amount -= amount_to_add; - - return; - } - - // if something on hand but not the same - // swap - this.switch_item_with_holding(player_inventory, index); - } - - handle_right_click(player_inventory: PlayerInventory, container: Container, index: number) { - const holding = player_inventory.holding_item; - const slot = container.get_slot(index); - const slot_item = slot.get_item(); - - // if holding something - if (holding) { - // and slot type equals holding type - // add 1 to matching stack - if (slot_item && slot.type_id === holding.type_id) { - if (slot_item.amount < slot_item.max_amount!) { - slot_item.amount += 1; - holding.amount -= 1; - } - return; - } - - // (actually the same as the last one but creates a new one techinically) - // place 1 into empty slot - if (!slot_item) { - const new_item = holding.clone(); - new_item.amount = 1; - slot.set_item(new_item); - holding.amount -= 1; - return; - } - - // if something on hand but not the same - // swap - this.switch_item_with_holding(player_inventory, index); - return; - } - - // if player is holding nothing and clicks nothing, nothing happens - if (!slot_item) { - return; - } - - // pick up half of the stack - const original_amount = slot_item.amount; - const half = Math.floor(original_amount / 2); - - slot_item.amount = half; - - const picked_up = slot_item.clone(); - picked_up.amount = original_amount - half; - - player_inventory.holding_item = picked_up; - - if (slot_item.amount === 0) { - slot.set_item(undefined); - } - } - - handle_hotbar(world: ClientWorld, player_inventory: PlayerInventory) { - const [player, player_hand] = world.get_tag("player")!; - - const player_position = player.get(Position); - const player_sprite = player.get(AnimatedSprite); - const hand_position = player_hand.get(Position); - const hand_sprite = player_hand.get(Sprite); - - if (!player_position || !hand_position || !hand_sprite || !player_sprite) { - return; - } - - // sync position - hand_position.x = player_position.x + (player_sprite.flip_x ? 34 : 4); - hand_position.y = player_position.y + 34; - hand_sprite.flip_x = player_sprite.flip_x; - - const maybe_item = player_inventory.container.get_item(player_inventory.hotbar_selected); - if (maybe_item) { - const region = get_sprite_region(maybe_item.type_id); - hand_sprite.source_x = region.x * 16; - hand_sprite.source_y = region.y * 16; - hand_sprite.source_width = 16; - hand_sprite.source_height = 16; - hand_sprite.width = 32; - hand_sprite.height = 32; - } else { - hand_sprite.width = 0; - hand_sprite.height = 0; - } - } -} diff --git a/client/systems/player_controls.ts b/client/systems/player_controls.ts index e83f0ca..88218c3 100644 --- a/client/systems/player_controls.ts +++ b/client/systems/player_controls.ts @@ -4,10 +4,11 @@ import { InputManager } from "../input_manager.ts"; import { AnimatedSprite } from "../components/sprite.ts"; import { ClientWorld } from "../client_world.ts"; import { PlayerControls } from "../components/player_controls.ts"; -import { PlayerInventory } from "../components/inventory.ts"; import { Camera } from "../components/camera.ts"; import { Position } from "../../common/components/position.ts"; import { canvas } from "../renderer.ts"; +import { PlayerComponent } from "../player.ts"; +import { GuiPlayerInventory } from "../gui/gui_player_inventory.ts"; export class PlayerControlsSystem extends System { constructor() { @@ -18,7 +19,7 @@ export class PlayerControlsSystem extends System { const [player] = world.get_tag("player")!; const velocity = player.get(Velocity)!; const controls = player.get(PlayerControls)!; - const player_inventory = player.get(PlayerInventory)!; + const player_component = player.get(PlayerComponent)!; if (InputManager.is_key_down(controls.move_left)) { velocity.vx = -controls.move_speed; @@ -54,8 +55,11 @@ export class PlayerControlsSystem extends System { } if (InputManager.is_key_pressed(controls.open_inventory)) { - const inventory = player.get(PlayerInventory)!; - inventory.is_open = !inventory.is_open; + if (player_component.screens.length === 0) { + player_component.screens.push(new GuiPlayerInventory(player_component.player_inventory)); + } else { + player_component.pop_screen(); + } } if (InputManager.is_key_pressed(controls.open_debug)) { @@ -70,7 +74,8 @@ export class PlayerControlsSystem extends System { camera.offset_x = Math.floor(canvas.width / 2); camera.offset_y = Math.floor(canvas.height / 2); - if (!player_inventory.is_open) { + if (player_component.screens.length === 0) { + const player_inventory = player_component.player_inventory; const scroll = InputManager.get_wheel_delta(); if (scroll > 0) { player_inventory.hotbar_selected = Math.min(8, player_inventory.hotbar_selected + 1); diff --git a/client/systems/render_system.ts b/client/systems/render_system.ts index a0884a8..3ffca2a 100644 --- a/client/systems/render_system.ts +++ b/client/systems/render_system.ts @@ -3,13 +3,13 @@ import { World } from "$/common/ecs/world.ts"; import { Position } from "$/common/components/position.ts"; import { AnimatedSprite, Sprite } from "$/client/components/sprite.ts"; import { Dimension } from "../components/dimension.ts"; -import { PlayerInventory } from "$/client/components/inventory.ts"; import { Camera } from "$/client/components/camera.ts"; import { render_animated_sprite, render_sprite } from "./rendering/sprites.ts"; import { render_dimension } from "./rendering/dimension.ts"; -import { render_player_hotbar, render_player_inventory } from "./rendering/player.ts"; +import { render_player_hotbar } from "./rendering/player.ts"; import { begin_mode_2d, end_mode_2d } from "../renderer.ts"; +import { PlayerComponent } from "../player.ts"; export class RenderSystem extends System { constructor() { @@ -50,13 +50,10 @@ export class RenderSystem extends System { end_mode_2d(); for (const entity of world.get_entities()) { - const player_inventory = entity.get(PlayerInventory); + const player_component = entity.get(PlayerComponent); - if (player_inventory) { - render_player_hotbar(player_inventory); - if (player_inventory.is_open) { - render_player_inventory(player_inventory); - } + if (player_component) { + render_player_hotbar(player_component.player_inventory); } } } diff --git a/client/systems/rendering/player.ts b/client/systems/rendering/player.ts index 8fee6ad..05e148b 100644 --- a/client/systems/rendering/player.ts +++ b/client/systems/rendering/player.ts @@ -1,106 +1,11 @@ import { SLOT_SIZE } from "$/common/constants.ts"; import { AssetManager } from "$/client/assets.ts"; -import { PlayerInventory } from "$/client/components/inventory.ts"; -import { InputManager } from "$/client/input_manager.ts"; +import { PlayerInventory } from "../../inventory.ts"; import { draw_item, draw_nine_slice } from "./render_utils.ts"; -import { canvas, draw_rect, draw_text, measure_text, Texture } from "$/client/renderer.ts"; -import { EverythingRegistry, ItemRegistry } from "$/common/everything_registry.ts"; +import { canvas, Texture } from "$/client/renderer.ts"; const PADDING = 10; -export function render_player_inventory(player_inventory: PlayerInventory) { - draw_rect(0, 0, canvas.width, canvas.height, [0, 0, 0, 0.8]); - - const ui = AssetManager.instance.get("bworld:ui"); - const layout = player_inventory.layout.slots; - - const inventory_width = PADDING * 2 + SLOT_SIZE * 9; - const inventory_height = PADDING * 2 + SLOT_SIZE * 4; - - const offset_x = canvas.width / 2 - (inventory_width / 2); - const offset_y = canvas.height / 2 - (inventory_height / 2); - - draw_nine_slice( - ui, - 160, - 0, - 16, - 16, - 4, - 4, - 4, - 4, - offset_x, - offset_y, - inventory_width, - inventory_height, - ); - - for (const [index, slot] of layout.entries()) { - const x = slot.x + PADDING; - const y = slot.y + PADDING; - draw_nine_slice( - ui, - player_inventory.hovering_slot === index ? 19 * 16 : 160 + 32, - player_inventory.hovering_slot === index ? 16 : 0, - 16, - 16, - 4, - 4, - 4, - 4, - offset_x + x, - offset_y + y, - SLOT_SIZE, - SLOT_SIZE, - ); - } - for (const [index, slot] of layout.entries()) { - const x = slot.x + PADDING; - const y = slot.y + PADDING; - const item = player_inventory.container.get_item(index); - if (item) { - draw_item(item, offset_x + x, offset_y + y); - } - } - - const mouse = InputManager.get_mouse_position(); - - if (player_inventory.holding_item) { - draw_item(player_inventory.holding_item, mouse.x, mouse.y); - } - - if (player_inventory.hovering_slot !== -1) { - const item = player_inventory.container.get_item(player_inventory.hovering_slot); - if (item) { - const item_info = EverythingRegistry.get("items", item.type_id); - const item_name = item.type_id; - const box_width = measure_text(item_name, 2) + 4 * 3; - const lines = item_info?.get_lore ? 2 : 1; - draw_nine_slice( - ui, - 16 * 11, - 0, - 16, - 16, - 4, - 4, - 4, - 4, - mouse.x + 4, - mouse.y, - box_width, - 32 * lines + 4 * (lines + 2), - [1, 1, 1, 0.8], - ); - draw_text(item_name, mouse.x + 4, mouse.y, 2); - if (item_info?.get_lore) { - draw_text(item_info.get_lore(item), mouse.x + 4, mouse.y + 32, 2); - } - } - } -} - export function render_player_hotbar(player_inventory: PlayerInventory) { const ui = AssetManager.instance.get("bworld:ui"); diff --git a/client/systems/rendering/render_utils.ts b/client/systems/rendering/render_utils.ts index a73b39e..d56253b 100644 --- a/client/systems/rendering/render_utils.ts +++ b/client/systems/rendering/render_utils.ts @@ -1,7 +1,7 @@ import { SLOT_SIZE } from "$/common/constants.ts"; import { get_sprite_region } from "$/common/utils.ts"; import { AssetManager } from "$/client/assets.ts"; -import { ItemStack } from "$/client/components/inventory.ts"; +import { ItemStack } from "../../inventory.ts"; import { draw_text, draw_texture_region, Texture } from "$/client/renderer.ts"; export function draw_nine_slice( diff --git a/client/tiles/crops.ts b/client/tiles/crops.ts index 2354c9f..82c2d0d 100644 --- a/client/tiles/crops.ts +++ b/client/tiles/crops.ts @@ -1,5 +1,6 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; -import { ItemStack, PlayerInventory } from "../components/inventory.ts"; +import { ItemStack } from "../inventory.ts"; +import { PlayerComponent } from "../player.ts"; interface CropsRegistry { total_stages: number; @@ -84,7 +85,7 @@ function create_crop_tile(crop_id: string) { }, on_click(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; const item = player_inventory.container.get_item(player_inventory.hotbar_selected); if (!item) { return; @@ -99,7 +100,7 @@ function create_crop_tile(crop_id: string) { return; } const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; player_inventory.container.add_item(new ItemStack(crop_info.item_drop)); if (crop_info.regrowable) { tile.data!.current_stage -= 1; diff --git a/client/tiles/dirt.ts b/client/tiles/dirt.ts index 645f1e1..5d86035 100644 --- a/client/tiles/dirt.ts +++ b/client/tiles/dirt.ts @@ -1,6 +1,6 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; -import { PlayerInventory } from "../components/inventory.ts"; import { WateringCanData } from "../items/watering_can.ts"; +import { PlayerComponent } from "../player.ts"; EverythingRegistry.register("tiles", "bworld:dirt", { texture_id: "bworld:dirt", @@ -8,7 +8,7 @@ EverythingRegistry.register("tiles", "bworld:dirt", { on_interact(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + 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:hoe") { tile.id = "bworld:hoed_dirt"; @@ -22,7 +22,7 @@ EverythingRegistry.register("tiles", "bworld:hoed_dirt", { on_click(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; const item = player_inventory.container.get_item(player_inventory.hotbar_selected); if (!item) { return; @@ -34,7 +34,7 @@ EverythingRegistry.register("tiles", "bworld:hoed_dirt", { }, on_interact(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; const item = player_inventory.container.get_item(player_inventory.hotbar_selected); if (!item) { return; @@ -56,7 +56,7 @@ EverythingRegistry.register("tiles", "bworld:hoed_watered_dirt", { on_click(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; const item = player_inventory.container.get_item(player_inventory.hotbar_selected); if (!item) { return; @@ -68,7 +68,7 @@ EverythingRegistry.register("tiles", "bworld:hoed_watered_dirt", { }, on_interact(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + const player_inventory = player.get(PlayerComponent)!.player_inventory; const item = player_inventory.container.get_item(player_inventory.hotbar_selected); if (!item) { return; diff --git a/client/tiles/grass.ts b/client/tiles/grass.ts index b23c876..09e973a 100644 --- a/client/tiles/grass.ts +++ b/client/tiles/grass.ts @@ -1,5 +1,5 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; -import { PlayerInventory } from "../components/inventory.ts"; +import { PlayerComponent } from "../player.ts"; EverythingRegistry.register("tiles", "bworld:grass", { texture_id: "bworld:grass", @@ -7,7 +7,7 @@ EverythingRegistry.register("tiles", "bworld:grass", { on_interact(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + 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:hoe") { tile.id = "bworld:hoed_dirt"; diff --git a/client/tiles/tree.ts b/client/tiles/tree.ts index 116ed8f..a5100dc 100644 --- a/client/tiles/tree.ts +++ b/client/tiles/tree.ts @@ -1,5 +1,6 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; -import { ItemStack, PlayerInventory } from "../components/inventory.ts"; +import { ItemStack } from "../inventory.ts"; +import { PlayerComponent } from "../player.ts"; EverythingRegistry.register("tiles", "bworld:tree", { texture_id: "bworld:tree", @@ -7,7 +8,7 @@ EverythingRegistry.register("tiles", "bworld:tree", { on_click(world, tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + 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:axe") { tile.id = "bworld:grass"; diff --git a/client/tiles/water.ts b/client/tiles/water.ts index 5c6df54..3f17971 100644 --- a/client/tiles/water.ts +++ b/client/tiles/water.ts @@ -1,6 +1,6 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; -import { PlayerInventory } from "../components/inventory.ts"; import { WateringCanData } from "../items/watering_can.ts"; +import { PlayerComponent } from "../player.ts"; EverythingRegistry.register("tiles", "bworld:water", { texture_id: "bworld:water", @@ -8,7 +8,7 @@ EverythingRegistry.register("tiles", "bworld:water", { on_interact(world, _tile) { const [player] = world.get_tag("player")!; - const player_inventory = player.get(PlayerInventory)!; + 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; diff --git a/common/everything_registry.ts b/common/everything_registry.ts index 9566f53..7769ed2 100644 --- a/common/everything_registry.ts +++ b/common/everything_registry.ts @@ -1,6 +1,6 @@ import { ClientWorld } from "../client/client_world.ts"; import { Tile } from "../client/components/dimension.ts"; -import { ItemStack } from "../client/components/inventory.ts"; +import { ItemStack } from "../client/inventory.ts"; export class EverythingRegistry { static #registries = new Map>();