From a0886f8f2445950d27497eb17f31017d01bbdeed Mon Sep 17 00:00:00 2001 From: Paula Date: Sat, 7 Mar 2026 22:01:11 -0300 Subject: [PATCH] Watering can lore --- client/components/inventory.ts | 9 +- client/items/mod.ts | 1 + client/items/watering_can.ts | 16 ++++ client/main.ts | 2 + client/renderer.ts | 7 +- client/systems/rendering/player.ts | 36 +++++++- client/systems/rendering/render_utils.ts | 103 ++++++++++++++++++++++- client/tiles/dirt.ts | 7 +- client/tiles/mod.ts | 1 + client/tiles/water.ts | 18 ++++ common/everything_registry.ts | 7 ++ 11 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 client/items/mod.ts create mode 100644 client/items/watering_can.ts create mode 100644 client/tiles/water.ts diff --git a/client/components/inventory.ts b/client/components/inventory.ts index 887ded5..060bfb9 100644 --- a/client/components/inventory.ts +++ b/client/components/inventory.ts @@ -1,15 +1,22 @@ 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 { +export class ItemStack { type_id: string; amount: number; max_amount: number; + data?: T; constructor(type_id: string | string, amount: number = 1, max_amount: number = 64) { this.type_id = type_id; this.amount = amount; this.max_amount = max_amount; + this.data = undefined; + const item_info = EverythingRegistry.get("items", type_id); + if (item_info?.on_create) { + item_info.on_create(this); + } } clone(): ItemStack { diff --git a/client/items/mod.ts b/client/items/mod.ts new file mode 100644 index 0000000..3436f6a --- /dev/null +++ b/client/items/mod.ts @@ -0,0 +1 @@ +import "./watering_can.ts"; diff --git a/client/items/watering_can.ts b/client/items/watering_can.ts new file mode 100644 index 0000000..ba3d59c --- /dev/null +++ b/client/items/watering_can.ts @@ -0,0 +1,16 @@ +import { EverythingRegistry, ItemRegistry } from "$/common/everything_registry.ts"; + +export interface WateringCanData { + water: number; + max_water: number; +} + +EverythingRegistry.register>("items", "bworld:watering_can", { + texture_id: "bworld:watering_can", + on_create(item) { + item.data = { water: 0, max_water: 32 }; + }, + get_lore(item) { + return `Water: ${item.data?.water}/${item.data?.max_water}`; + }, +}); diff --git a/client/main.ts b/client/main.ts index 4eefda2..c5e8099 100644 --- a/client/main.ts +++ b/client/main.ts @@ -6,6 +6,8 @@ import { begin_drawing, end_drawing, init_font, init_window } from "./renderer.t EverythingRegistry.add_registry("tiles"); await import("./tiles/mod.ts"); +EverythingRegistry.add_registry("items"); +await import("./items/mod.ts"); export class ClientLoop { running = false; diff --git a/client/renderer.ts b/client/renderer.ts index b4d1ed6..fe4ba39 100644 --- a/client/renderer.ts +++ b/client/renderer.ts @@ -238,6 +238,10 @@ export function draw_texture_region( dh: number, flip_x = false, flip_y = false, + r = 1, + g = 1, + b = 1, + a = 1, ) { if (current_texture !== texture.tex) { flush_batch(); @@ -256,7 +260,7 @@ export function draw_texture_region( [v0, v1] = [v1, v0]; } - push_quad(dx, dy, dw, dh, u0, v0, u1, v1); + push_quad(dx, dy, dw, dh, u0, v0, u1, v1, r, g, b, a); } function flush_batch() { @@ -522,7 +526,6 @@ export function measure_text(str: string, scale: number = 1) { if (!glyph) { continue; } - x += glyph.xadvance * scale; } return x; diff --git a/client/systems/rendering/player.ts b/client/systems/rendering/player.ts index c319905..9b33625 100644 --- a/client/systems/rendering/player.ts +++ b/client/systems/rendering/player.ts @@ -3,7 +3,8 @@ import { AssetManager } from "$/client/assets.ts"; import { PlayerInventory } from "$/client/components/inventory.ts"; import { InputManager } from "$/client/input_manager.ts"; import { draw_item, draw_nine_slice } from "./render_utils.ts"; -import { canvas, Texture } from "$/client/renderer.ts"; +import { canvas, draw_text, measure_text, Texture } from "$/client/renderer.ts"; +import { EverythingRegistry, ItemRegistry } from "$/common/everything_registry.ts"; const PADDING = 10; @@ -55,10 +56,41 @@ export function render_player_inventory(player_inventory: PlayerInventory) { } } + const mouse = InputManager.get_mouse_position(); + if (player_inventory.holding_item) { - const mouse = InputManager.get_mouse_position(); 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) { diff --git a/client/systems/rendering/render_utils.ts b/client/systems/rendering/render_utils.ts index 6eb94fa..a73b39e 100644 --- a/client/systems/rendering/render_utils.ts +++ b/client/systems/rendering/render_utils.ts @@ -18,6 +18,7 @@ export function draw_nine_slice( y: number, width: number, height: number, + color = [1, 1, 1, 1], ) { const center_width = source_width - left - right; const center_height = source_height - top - bottom; @@ -26,10 +27,42 @@ export function draw_nine_slice( const dest_center_height = height - top - bottom; // top left - draw_texture_region(image, source_x, source_y, left, top, x, y, left, top); + draw_texture_region( + image, + source_x, + source_y, + left, + top, + x, + y, + left, + top, + false, + false, + color[0], + color[1], + color[2], + color[3], + ); // top right - draw_texture_region(image, source_x + source_width - right, source_y, right, top, x + width - right, y, right, top); + draw_texture_region( + image, + source_x + source_width - right, + source_y, + right, + top, + x + width - right, + y, + right, + top, + false, + false, + color[0], + color[1], + color[2], + color[3], + ); // bottom left draw_texture_region( @@ -42,6 +75,12 @@ export function draw_nine_slice( y + height - bottom, left, bottom, + false, + false, + color[0], + color[1], + color[2], + color[3], ); // bottom right @@ -55,10 +94,32 @@ export function draw_nine_slice( y + height - bottom, right, bottom, + false, + false, + color[0], + color[1], + color[2], + color[3], ); // top - draw_texture_region(image, source_x + left, source_y, center_width, top, x + left, y, dest_center_width, top); + draw_texture_region( + image, + source_x + left, + source_y, + center_width, + top, + x + left, + y, + dest_center_width, + top, + false, + false, + color[0], + color[1], + color[2], + color[3], + ); // bottom draw_texture_region( @@ -71,10 +132,32 @@ export function draw_nine_slice( y + height - bottom, dest_center_width, bottom, + false, + false, + color[0], + color[1], + color[2], + color[3], ); // left - draw_texture_region(image, source_x, source_y + top, left, center_height, x, y + top, left, dest_center_height); + draw_texture_region( + image, + source_x, + source_y + top, + left, + center_height, + x, + y + top, + left, + dest_center_height, + false, + false, + color[0], + color[1], + color[2], + color[3], + ); // right draw_texture_region( @@ -87,6 +170,12 @@ export function draw_nine_slice( y + top, right, dest_center_height, + false, + false, + color[0], + color[1], + color[2], + color[3], ); // center ! @@ -100,6 +189,12 @@ export function draw_nine_slice( y + top, dest_center_width, dest_center_height, + false, + false, + color[0], + color[1], + color[2], + color[3], ); } diff --git a/client/tiles/dirt.ts b/client/tiles/dirt.ts index 829683f..645f1e1 100644 --- a/client/tiles/dirt.ts +++ b/client/tiles/dirt.ts @@ -1,5 +1,6 @@ import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; import { PlayerInventory } from "../components/inventory.ts"; +import { WateringCanData } from "../items/watering_can.ts"; EverythingRegistry.register("tiles", "bworld:dirt", { texture_id: "bworld:dirt", @@ -40,7 +41,11 @@ EverythingRegistry.register("tiles", "bworld:hoed_dirt", { } if (item.type_id === "bworld:watering_can") { - tile.id = "bworld:hoed_watered_dirt"; + const data = item.data as WateringCanData; + if (data.water > 0) { + tile.id = "bworld:hoed_watered_dirt"; + data.water -= 1; + } } }, }); diff --git a/client/tiles/mod.ts b/client/tiles/mod.ts index 735fdfe..ea2e9e9 100644 --- a/client/tiles/mod.ts +++ b/client/tiles/mod.ts @@ -2,3 +2,4 @@ import "./grass.ts"; import "./dirt.ts"; import "./tree.ts"; import "./crops.ts"; +import "./water.ts"; diff --git a/client/tiles/water.ts b/client/tiles/water.ts new file mode 100644 index 0000000..5c6df54 --- /dev/null +++ b/client/tiles/water.ts @@ -0,0 +1,18 @@ +import { EverythingRegistry, TileRegistry } from "$/common/everything_registry.ts"; +import { PlayerInventory } from "../components/inventory.ts"; +import { WateringCanData } from "../items/watering_can.ts"; + +EverythingRegistry.register("tiles", "bworld:water", { + texture_id: "bworld:water", + has_collision: true, + + on_interact(world, _tile) { + const [player] = world.get_tag("player")!; + const player_inventory = player.get(PlayerInventory)!; + 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; + } + }, +}); diff --git a/common/everything_registry.ts b/common/everything_registry.ts index b823d7e..9566f53 100644 --- a/common/everything_registry.ts +++ b/common/everything_registry.ts @@ -1,5 +1,6 @@ import { ClientWorld } from "../client/client_world.ts"; import { Tile } from "../client/components/dimension.ts"; +import { ItemStack } from "../client/components/inventory.ts"; export class EverythingRegistry { static #registries = new Map>(); @@ -27,3 +28,9 @@ export interface TileRegistry { on_tick?(world: ClientWorld, tile: Tile, tick_delta: number): void; on_second?(world: ClientWorld, tile: Tile, second_delta: number): void; } + +export interface ItemRegistry { + texture_id: string | ((item: ItemStack) => string); + on_create?(item: ItemStack): void; + get_lore?(item: ItemStack): string; +}