| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import { resolve } from "node:path";
- import { describe, expect, it } from "vitest";
- import {
- createEngine,
- type AnimalEntity,
- type BuildingPlacement,
- type GrowthSystem,
- type InventorySystem,
- type PlacementSystem,
- type PlotEntity,
- type PlantingSystem,
- } from "../src/index.js";
- const repoRoot = resolve(process.cwd(), "../..");
- const contentDir = resolve(repoRoot, "examples", "sample-game", "content");
- function engineSetup() {
- return createEngine({ contentDir });
- }
- function plantingOf(engine: ReturnType<typeof createEngine>): PlantingSystem {
- const planting = engine.systems.get<PlantingSystem>("planting");
- if (!planting) throw new Error("planting system not booted");
- return planting;
- }
- function growthOf(engine: ReturnType<typeof createEngine>): GrowthSystem {
- const growth = engine.systems.get<GrowthSystem>("growth");
- if (!growth) throw new Error("growth system not booted");
- return growth;
- }
- function placementOf(engine: ReturnType<typeof createEngine>): PlacementSystem {
- const placement = engine.systems.get<PlacementSystem>("placement");
- if (!placement) throw new Error("placement system not booted");
- return placement;
- }
- function inventoryOf(engine: ReturnType<typeof createEngine>): InventorySystem {
- const inv = engine.systems.get<InventorySystem>("inventory");
- if (!inv) throw new Error("inventory system not booted");
- return inv;
- }
- function sowParsnip(engine: ReturnType<typeof createEngine>): PlotEntity {
- inventoryOf(engine).give("parsnip-seed", 3);
- const planting = plantingOf(engine);
- planting.till(3, 3);
- return planting.sow(3, 3, "parsnip-seed");
- }
- describe("entity appearance (spriteRef) maintenance", () => {
- it("engine seeds the player entity with spriteRef 'player'", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const player = engine.world.get("player") as { spriteRef?: string } | undefined;
- expect(player?.spriteRef).toBe("player");
- } finally {
- await engine.stop();
- }
- });
- it("PlantingSystem.sow sets plot.spriteRef to the crop's stage-0 spriteRef", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const plot = sowParsnip(engine);
- expect(plot.spriteRef).toBe("parsnip-sprout");
- } finally {
- await engine.stop();
- }
- });
- it("GrowthSystem.forceStage updates plot.spriteRef to the forced stage's spriteRef", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const plot = sowParsnip(engine);
- const grown = growthOf(engine).forceStage("plot:3:3", 2);
- expect(grown.spriteRef).toBe("parsnip-mature");
- } finally {
- await engine.stop();
- }
- });
- it("GrowthSystem day-boundary stage advance updates plot.spriteRef", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const plot = sowParsnip(engine);
- expect(plot.spriteRef).toBe("parsnip-sprout");
- const growth = growthOf(engine);
- const planting = plantingOf(engine);
- planting.water(3, 3);
- growth.step(480);
- planting.water(3, 3);
- growth.step(480);
- const advanced = engine.world.get("plot:3:3") as PlotEntity;
- expect(advanced.stageIndex).toBe(1);
- expect(advanced.spriteRef).toBe("parsnip-grown");
- } finally {
- await engine.stop();
- }
- });
- it("PlantingSystem.harvest clears plot.spriteRef with the crop fields", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const plot = sowParsnip(engine);
- growthOf(engine).forceStage("plot:3:3", 2);
- plantingOf(engine).harvest(3, 3);
- const cleared = engine.world.get("plot:3:3") as PlotEntity;
- expect(cleared.cropItemId).toBeUndefined();
- expect(cleared.spriteRef).toBeUndefined();
- } finally {
- await engine.stop();
- }
- });
- it("GrowthSystem.spawnAnimal sets animal.spriteRef to the animal's stage-0 spriteRef", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const animal = growthOf(engine).spawnAnimal("chicken", 9, 3);
- expect(animal.spriteRef).toBe("chicken-chick");
- } finally {
- await engine.stop();
- }
- });
- it("GrowthSystem.forceAnimalStage updates animal.spriteRef", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const animal = growthOf(engine).spawnAnimal("chicken", 9, 3);
- const laying = growthOf(engine).forceAnimalStage(animal.id, 2);
- expect(laying.spriteRef).toBe("chicken-laying");
- expect((engine.world.get(animal.id) as AnimalEntity).spriteRef).toBe("chicken-laying");
- } finally {
- await engine.stop();
- }
- });
- it("PlacementSystem.place copies the building def's spriteRef onto the entity", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- const coop = placementOf(engine).place("coop", 10, 4) as BuildingPlacement;
- expect(coop.spriteRef).toBe("coop");
- const fence = placementOf(engine).place("fence", 8, 8) as BuildingPlacement;
- expect(fence.spriteRef).toBe("fence");
- } finally {
- await engine.stop();
- }
- });
- it("spriteRef stays absent when the def has no spriteRef (fallback shape drawing)", async () => {
- const engine = engineSetup();
- await engine.start();
- try {
- engine.registry.register("item", { id: "plain-seed", name: "Plain Seed", kind: "seed", stackable: true });
- engine.registry.register("crop", {
- id: "plain",
- seedItem: "plain-seed",
- stages: [
- { name: "sprout", days: 1, waterRequired: false },
- { name: "grown", days: 1, waterRequired: false },
- ],
- seasons: ["spring"],
- drops: [{ itemId: "parsnip", qty: 1 }],
- });
- inventoryOf(engine).give("plain-seed", 1);
- const planting = plantingOf(engine);
- planting.till(6, 6);
- const plot = planting.sow(6, 6, "plain-seed");
- expect(plot.cropItemId).toBe("plain");
- expect(plot.spriteRef).toBeUndefined();
- } finally {
- await engine.stop();
- }
- });
- });
|