import { describe, expect, it } from "vitest"; import type { Entity } from "@nengine/core"; import { CROP_STAGE_COLORS, ENTITY_COLORS, PLOT_COLORS, UNKNOWN_ENTITY_COLOR, cropColor, entityShapes, } from "../src/shapes.js"; const TILE = 32; describe("entityShapes (viewport entity drawing)", () => { it("draws a tilled plot as a full tile rect", () => { const shapes = entityShapes([{ id: "plot:4:4", type: "plot", x: 4, y: 4, tilled: true }], TILE); expect(shapes).toEqual([ { kind: "rect", x: 128, y: 128, w: 32, h: 32, color: PLOT_COLORS.tilled }, ]); }); it("draws an untilled plot darker", () => { const shapes = entityShapes([{ id: "plot:1:1", type: "plot", x: 1, y: 1, tilled: false }], TILE); expect(shapes[0]).toMatchObject({ color: PLOT_COLORS.untilled }); }); it("adds a watered inset rect on watered plots", () => { const shapes = entityShapes([{ id: "plot:2:2", type: "plot", x: 2, y: 2, watered: true }], TILE); expect(shapes).toHaveLength(2); expect(shapes[1]).toMatchObject({ kind: "rect", x: 64 + TILE * 0.15, y: 64 + TILE * 0.15, w: TILE * 0.7, h: TILE * 0.7, color: PLOT_COLORS.watered, }); }); it("draws a crop-stage dot whose size grows with stageIndex", () => { const early = entityShapes([{ id: "plot:0:0", type: "plot", x: 0, y: 0, stageIndex: 0 }], TILE); const late = entityShapes([{ id: "plot:0:0", type: "plot", x: 0, y: 0, stageIndex: 2 }], TILE); expect(early[1]).toMatchObject({ kind: "circle", color: CROP_STAGE_COLORS[0] }); expect(late[1]).toMatchObject({ kind: "circle", color: CROP_STAGE_COLORS[2] }); expect((late[1] as { w: number }).w).toBeGreaterThan((early[1] as { w: number }).w); }); it("falls back to the mature color for out-of-range stages", () => { expect(cropColor(9)).toBe(CROP_STAGE_COLORS[2]); }); it("draws buildings as footprint-sized blocks", () => { const shapes = entityShapes([{ id: "building:shed:3:3", type: "building", x: 3, y: 3, w: 2, h: 2 }], TILE); expect(shapes).toEqual([ { kind: "rect", x: 96, y: 96, w: 64, h: 64, color: ENTITY_COLORS.building }, ]); }); it("draws npc/player/animal entities as colored dots", () => { const entities: Entity[] = [ { id: "npc:mayor", type: "npc", x: 6, y: 5 }, { id: "player", type: "player", x: 2, y: 4 }, { id: "animal:chicken:1", type: "animal", x: 9, y: 3 }, ]; const shapes = entityShapes(entities, TILE); expect(shapes).toEqual([ { kind: "circle", x: 6 * TILE + 16, y: 5 * TILE + 16, w: TILE * 0.32, h: TILE * 0.32, color: ENTITY_COLORS.npc }, { kind: "circle", x: 2 * TILE + 16, y: 4 * TILE + 16, w: TILE * 0.32, h: TILE * 0.32, color: ENTITY_COLORS.player }, { kind: "circle", x: 9 * TILE + 16, y: 3 * TILE + 16, w: TILE * 0.32, h: TILE * 0.32, color: ENTITY_COLORS.animal }, ]); }); it("skips entities without numeric coordinates", () => { const shapes = entityShapes([{ id: "ghost", type: "npc" }], TILE); expect(shapes).toEqual([]); }); it("draws statemachine/mod-state entities as nothing (no coords) but neutral dots for unknown positioned kinds", () => { const noCoord = entityShapes([{ id: "sm:quest", type: "statemachine" }], TILE); expect(noCoord).toEqual([]); const dot = entityShapes([{ id: "weird", type: "mystery", x: 0, y: 0 }], TILE); expect(dot).toEqual([ { kind: "circle", x: 16, y: 16, w: TILE * 0.32, h: TILE * 0.32, color: UNKNOWN_ENTITY_COLOR }, ]); }); });