aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--data/maps/sushibar.yaml20
-rw-r--r--data/recipes/default.ts302
-rw-r--r--server/src/data/mod.rs17
-rw-r--r--server/src/entity/portal.rs17
-rw-r--r--server/src/state.rs3
-rw-r--r--test-client/tiles.ts44
-rw-r--r--test-client/visual.ts15
8 files changed, 252 insertions, 170 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4f768d48..80d683be 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -924,9 +924,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
"bitflags",
]
diff --git a/data/maps/sushibar.yaml b/data/maps/sushibar.yaml
index b96dcafb..3dee515a 100644
--- a/data/maps/sushibar.yaml
+++ b/data/maps/sushibar.yaml
@@ -17,16 +17,16 @@ map:
- "*''''*''''*''''''''*''"
- "'''*'''''''**''''''''*"
- "''█████████████'X'''*'"
- - "''█R.....#c...█'''''**"
- - "''█T.....#c...d____'''"
- - "'*█F..S..#c...d____'*'"
- - "*'█L..S..#c...█''__'''"
- - "''█f..⌷..#c...█''__''*"
- - "*'█f..⌷..#c.~.█''__'*'"
- - "'*█o..C..#c...█''__''*"
- - "''█o..C..███d██''__'''"
- - "*'█s..........█''__'*'"
- - "'*█⌷ZZ⌷⌷⌷ggg⌷⌷█''__''*"
+ - "''█f.....#c...█'''''**"
+ - "''█f..⌷⌷.#c...d____'''"
+ - "'*█o..S⌷.#c...d____'*'"
+ - "*'█o..S⌷.#c...█''__'''"
+ - "''█R.....#c...█''__''*"
+ - "*'█T..⌷⌷.#c.~.█''__'*'"
+ - "'*█F..C⌷.#c...█''__''*"
+ - "''█L..C⌷.███d██''__'''"
+ - "*'█Z..........█''__'*'"
+ - "'*█Z⌷s⌷ggggg⌷⌷█''__''*"
- "*'█████████████''__'''"
- "'''*'''''''''''''_!'''"
- "'*''''''''''''''''''''"
diff --git a/data/recipes/default.ts b/data/recipes/default.ts
index 33b433a6..662b6817 100644
--- a/data/recipes/default.ts
+++ b/data/recipes/default.ts
@@ -16,12 +16,12 @@
*/
-//? Is is a good idea? Probably not.
+//? Is this a good idea? Probably not.
export interface Recipe {
tile?: string,
- inputs: (string | null)[],
- outputs: (string | null)[],
+ inputs: (Item | null | undefined)[],
+ outputs: (Item | null | undefined)[],
action: "instant" | "passive" | "active" | "demand" | "demand"
duration?: number
revert_duration?: number,
@@ -29,184 +29,204 @@ export interface Recipe {
points?: number,
}
-function trash_output(ifull: string) {
- const [i, ic] = get_container(ifull)
- if (i == "plate") return ifull
- if (i == "glass") return ifull
- if (i == "pot") return ifull
- if (i == "foodprocessor") return ifull
- if (i == "dirty") return ifull
- if (ic == "glass") return "glass"
- if (ic == "plate") return "dirty-plate"
- return null
-}
-
-export const all_items = new Set<string>()
-export function auto_trash() {
- for (const ifull of all_items) {
- let [i, ic] = get_container(ifull)
- if (i == "plate") continue
- if (i == "glass") continue
- if (i == "pot") continue
- if (i == "foodprocessor") continue
- if (i == "dirty") continue
- if (ic == "glass") ic = "glass"
- if (ic == "plate") ic = "dirty-plate"
- out({
- action: "instant",
- tile: ic == "glass" ? "sink" : "trash",
- inputs: [ifull],
- outputs: [ic]
- })
- }
-}
-
+const all_items = new Set<Item>()
+const all_recipes = new Set<Recipe>()
export function out(r: Recipe) {
r.inputs.forEach(i => i ? all_items.add(i) : void 0)
r.outputs.forEach(i => i ? all_items.add(i) : void 0)
r.inputs = r.inputs.filter(e => e)
r.outputs = r.outputs.filter(e => e)
- console.log(`- ${JSON.stringify(r).replaceAll("\"active\"", "!active").replaceAll("\"passive\"", "!passive").replaceAll("\"instant\"", "!instant")}`);
+ all_recipes.add(r);
+}
+export function finish() {
+ const k = new Set<string>()
+ for (const r of all_recipes) {
+ let s = `- action: !${r.action}\n`
+ s += ` inputs: [${r.inputs.map(e => e!.toString()).join(",")}]\n`
+ s += ` outputs: [${r.outputs.map(e => e!.toString()).join(",")}]\n`
+ if (r.warn) s += ` warn: true\n`
+ if (r.duration) s += ` duration: ${r.duration}\n`
+ if (r.revert_duration) s += ` revert_duration: ${r.revert_duration}\n`
+ if (r.points) s += ` points: ${r.points}\n`
+ if (r.tile) s += ` tile: ${r.tile}\n`
+ k.add(s)
+ }
+ for (const r of k)
+ console.log(r);
+}
+function auto_trash() {
+ for (const i of all_items) {
+ if (i instanceof Container) continue
+ if (!i.container) out({ action: "instant", inputs: [i], outputs: [], tile: "trash" })
+ else {
+ out({ action: "instant", inputs: [i], outputs: [i.container.dispose ?? i.container], tile: "trash" })
+ }
+ }
}
-export function edible(item: string) {
- let i = item
- if (!item.endsWith("-plate") && !item.endsWith("-glass")) {
- i += "-plate"
- out({ action: "instant", inputs: [item], outputs: [i] })
+class Item {
+ constructor(
+ public name: string,
+ public container?: Container
+ ) { }
+ as(s: string) { this.name = s; return this }
+ tr(container?: Container) {
+ const o = new Item(this.name, container)
+ if (this.container) out({ action: "instant", inputs: [this, container], outputs: [this.container, o] })
+ else out({ action: "instant", inputs: [container, this], outputs: [o] })
+ return o
+ }
+ toString() {
+ return this.name + (this.container ? "-" + this.container : "")
}
- out({ action: "demand", inputs: [i], outputs: [trash_output(i)], duration: 10 })
}
-export function cut(from: string, to?: string, to2?: string) {
- out({ action: "active", duration: 2, tile: "cuttingboard", inputs: [from], outputs: [to ?? ("sliced-" + from), to2 ?? null] })
+class Container extends Item { constructor(name: string, public dispose?: Item) { super(name) } }
+const FP = new Container("foodprocessor")
+const POT = new Container("pot")
+const PL = new Container("plate", new Container("dirty-plate"))
+const GL = new Container("glass")
+
+function crate(s: string): Item {
+ const item = new Item(s);
+ out({ action: "instant", inputs: [], outputs: [item], tile: `${s}-crate`, points: -1 })
+ return item
}
-export function cook(from: string, to?: string) {
- const i = from.endsWith("-pot") ? from : from + "-pot"
- const o = (to ?? ("cooked-" + from)) + "-pot"
- if (!from.endsWith("-pot")) out({ action: "instant", inputs: ["pot", from], outputs: [i] })
- out({ action: "passive", duration: 20, revert_duration: 40, tile: "stove", inputs: [i], outputs: [o] })
- out({ action: "passive", duration: 5, revert_duration: 10, tile: "stove", inputs: [o], outputs: ["burned-pot"], warn: true })
+function cut(s: Item, two?: boolean): Item {
+ const o = new Item(`sliced-${s.name}`, s.container)
+ out({ action: "active", inputs: [s], outputs: [o, two ? o : null], tile: "cuttingboard", duration: 2 })
+ return o
}
-export function process(from: string, to?: string) {
- const i = from.endsWith("-foodprocessor") ? from : from + "-foodprocessor"
- const o = (to ?? (from + "-juice")) + "-foodprocessor"
- if (!from.endsWith("-foodprocessor")) out({ action: "instant", inputs: ["foodprocessor", from], outputs: [i] })
- out({ action: "passive", duration: 5, inputs: [i], outputs: [o] })
+function cook(s: Item, duration = 20): Item {
+ const o = new Item(`cooked-${s.name}`, s.container)
+ out({ action: "passive", duration, tile: "stove", inputs: [s], outputs: [o] })
+ out({ action: "passive", duration: duration / 3, revert_duration: 20, tile: "stove", inputs: [o], outputs: [new Item("burned", POT)], warn: true })
+ return o
}
-export function bake(from: string, to?: string) {
- const o = (to ?? ("baked-" + from))
- out({ action: "passive", duration: 25, tile: "oven", inputs: [from], outputs: [o] })
- out({ action: "passive", duration: 15, revert_duration: 20, tile: "oven", inputs: [o], outputs: ["burned"], warn: true })
+function bake(s: Item, duration = 25): Item {
+ const o = new Item(`sliced-${s.name}`, s.container)
+ out({ action: "passive", duration, tile: "oven", inputs: [s], outputs: [o] })
+ out({ action: "passive", duration: duration / 2, revert_duration: 20, tile: "oven", inputs: [o], outputs: [new Item("burned")], warn: true })
+ return o
}
-export function crate(item: string) {
- out({ action: "instant", tile: item + "-crate", inputs: [], outputs: [item], points: -1 })
+function freeze(s: Item): Item {
+ const o = new Item(`frozen-${s.name}`, s.container)
+ out({ action: "passive", duration: 25, tile: "freezer", inputs: [s], outputs: [o] })
+ return o
}
-
-export function get_container(ifull: string): [string, string | null] {
- const iparts = ifull.split("-")
- const ic = iparts.pop()
- if (ic && iparts.length && ["pot", "plate", "foodprocessor", "glass"].includes(ic)) return [iparts.join("-"), ic]
- return [ifull, null]
+function process(s: Item): Item {
+ const o = new Item(`processed-${s.name}`, s.container)
+ out({ action: "passive", duration: 5, inputs: [s], outputs: [o] })
+ return o
}
-
-export function combine(container: string, ...inputs: string[]) {
- const open = inputs.map(ifull => {
- const [i, ic] = get_container(ifull)
- out({ action: "instant", inputs: [container, ifull], outputs: [i + "-" + container, ic] })
- return [i]
- })
+function container_add(base: Item, add: Item): Item {
+ const o = new Item("!!!", base.container)
+ out({ action: "instant", inputs: [base, add], outputs: [o, add.container] })
+ return o
+}
+function combine(c: Container, ...items: Item[]): Item {
+ const open = items.map(i => (i.tr(c), [i.name]))
const seen = new Set<string>()
+ let result
while (1) {
const cur = open.pop()
if (!cur) break;
- const c = cur.join("-") + "-" + container
- for (const ifull of inputs) {
- const [i, ic] = get_container(ifull)
- if (cur.includes(i)) continue
- const rkey = cur.join("-") + "#" + i
+ for (const new_item of items) {
+ if (cur.includes(new_item.name)) continue
+ const rkey = cur.join("-") + "#" + new_item
+
if (seen.has(rkey)) continue
seen.add(rkey)
- const parts = [...cur, i]
+ const parts = [...cur, new_item.name]
parts.sort()
- const o = parts.join("-") + "-" + container
open.push(parts)
+ const i = new Item(cur.join("-"), c)
+ const o = new Item(parts.join("-"), c)
+ if (parts.length == items.length) result = o
out({
action: "instant",
- inputs: [c, ifull],
- outputs: [o, ic]
+ inputs: [i, new_item],
+ outputs: [o, new_item.container]
})
}
}
+ return result!
+}
+function edible(...items: Item[]) {
+ for (const i of items) {
+ out({ action: "demand", inputs: [i], outputs: [i.container?.dispose ?? i.container], duration: 10 })
+ }
+}
+function either(a: Item, b: Item) {
+ if (a.name != b.name) throw new Error("either options are named differently");
+ if (a.container != b.container) throw new Error("either options are contained differently");
+ return a
+}
+function sink_fill(c: Container) {
+ const o = new Item("water", c)
+ out({ action: "instant", inputs: [c], outputs: [o], tile: "sink" })
+ return o
}
+out({ action: "active", duration: 2, tile: "sink", inputs: [new Container("dirty-plate")], outputs: [PL] })
-if (import.meta.main) {
- out({ action: "active", duration: 2, tile: "sink", inputs: ["dirty-plate"], outputs: ["plate"] })
-
- crate("tomato")
- crate("raw-steak")
- crate("flour")
- crate("leek")
-
- cut("tomato")
- cook("raw-steak", "steak")
-
- // bread
- process("flour", "dough")
- out({ action: "instant", inputs: ["dough-foodprocessor"], outputs: ["foodprocessor", "dough"] })
- bake("dough", "bread")
- cut("bread", "bread-slice", "bread-slice")
-
- // tomato soup
- process("tomato")
- combine("pot", "leek", "tomato-juice-foodprocessor")
- cook("leek-tomato-juice-pot", "tomato-soup")
- out({ action: "instant", inputs: ["tomato-soup-pot", "plate"], outputs: ["pot", "tomato-soup-plate"] })
+const tomato = crate("tomato")
+const raw_steak = crate("raw-steak")
+const flour = crate("flour")
+const leek = crate("leek")
+const rice = crate("rice")
+const fish = crate("fish")
+const coconut = crate("coconut")
+const strawberry = crate("strawberry")
- combine("plate", "steak-pot", "sliced-tomato", "bread-slice")
+// Bread
+const dough = process(flour.tr(FP)).as("dough").tr()
+const bread = bake(dough).as("bread")
+const bread_slice = cut(bread, true).as("bread-slice")
+edible(bread)
- edible("steak-plate")
- edible("bread-slice-steak-plate")
- edible("bread-slice-sliced-tomato-plate")
- edible("bread-slice-sliced-tomato-steak-plate")
- out({ action: "demand", inputs: ["bread"], outputs: [], duration: 0 })
+// Burger
+const steak_pot = cook(raw_steak.tr(POT)).as("steak")
+const sliced_tomato = cut(tomato).as("sliced-tomato")
+const burger = combine(PL, steak_pot, sliced_tomato, bread_slice)
+const tomato_toast = combine(PL, sliced_tomato, bread_slice)
+edible(burger, tomato_toast)
- crate("rice")
- crate("fish")
- crate("coconut")
- crate("strawberry")
+// Soup
+const tomato_juice = process(tomato.tr(FP)).as("tomato-juice")
+const leek_tj_pot = combine(POT, leek, tomato_juice)
+const tomato_soup_plate = cook(leek_tj_pot).as("tomato-soup").tr(PL)
+edible(tomato_soup_plate)
- // Rice and nigiri
- cut("fish")
- cook("rice")
- out({ action: "instant", inputs: ["sliced-fish", "cooked-rice-pot"], outputs: ["nigiri", "pot"] })
+// Rice and nigiri
+const nigiri = container_add(cut(fish), cook(rice.tr(POT))).as("nigiri").tr(PL)
+edible(nigiri)
- out({ action: "instant", inputs: ["plate", "cooked-rice-pot"], outputs: ["cooked-rice-plate", "pot"] })
- edible("cooked-rice-plate")
- edible("nigiri")
+// coconut milk and strawberry puree
+const strawberry_puree = process(strawberry.tr(FP)).as("strawberry-puree")
+const milk = process(coconut.tr(FP)).as("milk")
+const strawberry_shake = either(
+ process(container_add(milk, strawberry).as("coconut-strawberry-puree")).as("strawberry-shake"),
+ process(container_add(strawberry_puree, coconut).as("milk-strawberry")).as("strawberry-shake")
+)
- // coconut milk and strawberry puree
- process("strawberry", "strawberry-puree")
- process("coconut", "milk")
- out({ action: "instant", inputs: ["milk-foodprocessor", "strawberry"], outputs: ["strawberry-milk-foodprocessor"] })
- out({ action: "instant", inputs: ["strawberry-puree-foodprocessor", "coconut"], outputs: ["strawberry-milk-foodprocessor"] })
- process("strawberry-milk-foodprocessor", "strawberrymilk")
- process("coconut-strawberry-puree-foodprocessor", "strawberrymilk")
+// Icecream
+const strawberry_icecream = freeze(strawberry_shake).as("strawberry-icecream").tr(PL)
+edible(strawberry_icecream)
- // icecream
- out({ action: "passive", inputs: ["strawberrymilk-foodprocessor"], outputs: ["strawberry-icecream-foodprocessor"], tile: "freezer", duration: 20 })
- out({ action: "instant", inputs: ["strawberry-icecream-foodprocessor", "plate"], outputs: ["foodprocessor", "strawberry-icecream-plate"] })
- edible("strawberry-icecream-plate")
+// Mochi
+const rice_flour = process(rice.tr(FP)).as("rice-flour")
+const mochi_dough = cook(rice_flour.tr(POT), 5).as("mochi-dough")
+const strawberry_mochi = container_add(strawberry, mochi_dough).as("strawberry-mochi")
+edible(strawberry_mochi)
- // drinks
- out({ action: "instant", inputs: ["glass"], outputs: ["water-glass"], tile: "sink" })
- out({ action: "instant", inputs: ["glass", "milk-foodprocessor"], outputs: ["milk-glass", "foodprocessor"] })
- out({ action: "instant", inputs: ["glass", "strawberrymilk-foodprocessor"], outputs: ["strawberrymilk-glass", "foodprocessor"] })
+// Drinks
+edible(
+ strawberry_shake.tr(GL),
+ sink_fill(GL)
+)
- edible("water-glass")
- edible("strawberrymilk-glass")
+auto_trash()
+finish()
- auto_trash()
-}
diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs
index 6df60535..0f1976b9 100644
--- a/server/src/data/mod.rs
+++ b/server/src/data/mod.rs
@@ -369,3 +369,20 @@ impl Gamedata {
.map(|(i, e)| (RecipeIndex(i), e))
}
}
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2024 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/ \ No newline at end of file
diff --git a/server/src/entity/portal.rs b/server/src/entity/portal.rs
index e0195b9f..092a8da5 100644
--- a/server/src/entity/portal.rs
+++ b/server/src/entity/portal.rs
@@ -1,3 +1,20 @@
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2024 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
use super::EntityT;
use crate::{
data::Gamedata,
diff --git a/server/src/state.rs b/server/src/state.rs
index 215f9a1b..347e2a92 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -15,13 +15,12 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use std::time::Duration;
-
use crate::{data::DataIndex, game::Game};
use anyhow::{anyhow, bail, Result};
use clap::{Parser, ValueEnum};
use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID};
use log::{debug, trace};
+use std::time::Duration;
use tokio::sync::broadcast::Sender;
pub struct State {
diff --git a/test-client/tiles.ts b/test-client/tiles.ts
index 046d8297..fee27c9f 100644
--- a/test-client/tiles.ts
+++ b/test-client/tiles.ts
@@ -114,8 +114,7 @@ const foodprocessor = [circle(0.35, "rgb(86, 168, 189)", "rgb(88, 222, 255)", 0.
const burned = [circle(0.3, "rgb(61, 18, 0)"), cross(0.2, "red", 0.02)]
const leek = [circle(0.3, "rgb(50, 133, 17)")]
-export const FALLBACK_ITEM: Component[] = [circle(0.3, "#f0f")];
-export const ITEMS: { [key: string]: Component[] } = {
+const ITEMS: { [key: string]: Component[] } = {
"pot": pot,
"foodprocessor": foodprocessor,
"leek": leek,
@@ -158,8 +157,7 @@ const floor = [base("#333", "#222", 0.05)];
const counter = [base("rgb(182, 172, 164)")];
const crate = (i: string) => [base("#60701e", "#b9da37", 0.05), ...ITEMS[i]];
-export const FALLBACK_TILE: Component[] = [base("#f0f")];
-export const TILES: { [key: string]: Component[] } = {
+const TILES: { [key: string]: Component[] } = {
"floor": floor,
"table": table,
"door": [...floor, door],
@@ -184,3 +182,41 @@ export const TILES: { [key: string]: Component[] } = {
"tomato-crate": crate("tomato"),
"leek-crate": crate("leek"),
}
+
+function debug_label(ctx: CanvasRenderingContext2D, name: string) {
+ ctx.save()
+ ctx.font = "10px sans-serif"
+ ctx.fillStyle = "white"
+ ctx.strokeStyle = "black"
+ ctx.lineWidth = 1
+ ctx.textAlign = "center"
+ ctx.textBaseline = "middle"
+ ctx.scale(0.03, 0.03)
+ ctx.strokeText(name, 0, 0)
+ ctx.fillText(name, 0, 0)
+ ctx.restore()
+}
+
+export function draw_item_sprite(ctx: CanvasRenderingContext2D, name: string) {
+ const comps = ITEMS[name]
+ if (comps) {
+ for (const c of comps) {
+ c(ctx)
+ }
+ } else {
+ circle(0.4, "#f0f")(ctx)
+ debug_label(ctx, name)
+ }
+}
+export function draw_tile_sprite(ctx: CanvasRenderingContext2D, name: string) {
+ const comps = TILES[name]
+ if (comps) {
+ for (const c of comps) {
+ c(ctx)
+ }
+ } else {
+ base("#f0f")(ctx)
+ debug_label(ctx, name)
+ }
+
+} \ No newline at end of file
diff --git a/test-client/visual.ts b/test-client/visual.ts
index d3f8a8b0..a5e603c5 100644
--- a/test-client/visual.ts
+++ b/test-client/visual.ts
@@ -17,7 +17,7 @@
*/
import { ItemData, MessageData, PlayerData, TileData, camera, camera_scale, canvas, ctx, data, demands_completed, demands_failed, get_interact_target, global_message, interact_active_anim, interact_possible_anim, interact_target_anim, items_removed, keys_down, my_id, nametag_scale_anim, players, points, tiles, time_remaining } from "./main.ts";
import { PLAYER_SIZE } from "./movement.ts";
-import { FALLBACK_TILE, ITEMS, TILES, FALLBACK_ITEM } from "./tiles.ts";
+import { draw_item_sprite, draw_tile_sprite } from "./tiles.ts";
import { V2, ceil_v2, floor_v2 } from "./util.ts";
export function draw_wait(text: string) {
@@ -109,10 +109,7 @@ function draw_debug() {
function draw_tile(tile: TileData) {
ctx.save()
ctx.translate(tile.x + 0.5, tile.y + 0.5)
- const comps = TILES[data.tile_names[tile.kind]] ?? FALLBACK_TILE
- for (const c of comps) {
- c(ctx)
- }
+ draw_tile_sprite(ctx, data.tile_names[tile.kind])
ctx.restore()
}
@@ -120,10 +117,7 @@ function draw_item(item: ItemData) {
ctx.save()
ctx.translate(item.x, item.y)
if (item.remove_anim) ctx.scale(1 - item.remove_anim, 1 - item.remove_anim)
- const comps = ITEMS[data.item_names[item.kind]] ?? FALLBACK_ITEM
- for (const c of comps) {
- c(ctx)
- }
+ draw_item_sprite(ctx, data.item_names[item.kind])
if (item.progress !== null && item.progress !== undefined) {
ctx.fillStyle = item.progress_warn ? "rgba(230, 58, 58, 0.66)" : "rgba(115, 230, 58, 0.66)"
ctx.fillRect(-0.5, -0.5, 1, item.progress)
@@ -226,8 +220,7 @@ function draw_message(m: MessageData) {
ctx.fill()
ctx.translate(0, -1)
- const comps = ITEMS[data.item_names[m.inner.item]] ?? FALLBACK_ITEM
- for (const c of comps) c(ctx)
+ draw_item_sprite(ctx, data.item_names[m.inner.item])
ctx.translate(0, 1)
}
if ("text" in m.inner) {