import { thoriumContext } from "@thorium/utils/.server/context"; import { createMockDataContext } from "@thorium/utils/.server/createMockDataContext"; import { testDataStoreProps } from "@thorium/utils/.server/db-fs/testDataStoreProps"; import { getReactorInventory } from "@thorium/utils/.server/ship/getSystemInventory"; import { ECS, Entity } from "@thorium/utils/ecs"; import { aroundEach, beforeEach, describe, expect, it } from "vitest"; import { FilterInventorySystem } from "../FilterInventorySystem"; import { FilterShipsWithReactors } from "../FilterShipsWithReactors"; import { ReactorFuelSystem } from "../ReactorFuelSystem"; aroundEach(async (runTest) => { await thoriumContext.run(testDataStoreProps, async () => { await runTest(); }); }); describe("ReactorFuelSystem", () => { let ecs: ECS; let reactorFuelSystem: ReactorFuelSystem; let filterShipsWithReactorSystem: FilterShipsWithReactors; let filterInventorySystem: FilterInventorySystem; let fuel: Entity; let reactor: Entity; let system: Entity; let ship: Entity; beforeEach(() => { const mockDataContext = createMockDataContext(); ecs = new ECS(mockDataContext.server); reactorFuelSystem = new ReactorFuelSystem(); filterShipsWithReactorSystem = new FilterShipsWithReactors(); filterInventorySystem = new FilterInventorySystem(); // Set up the initial state for each of the tests fuel = new Entity(); fuel.addComponent("isInventory", { volume: 1e-6, abundance: 1, continuous: true, flags: { fuel: { fuelDensity: 14.3 } }, }); fuel.addComponent("identity", { name: `Deuterium`, }); ecs.addEntity(fuel); reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor", }); const reactorComponent = { currentOutput: 6, maxOutput: 8, optimalOutputPercent: 0.7, }; reactor.addComponent("isReactor", reactorComponent); ship = new Entity(); ship.addComponent("isShip", {}); ship.addComponent("shipMap", { decks: [ { name: "Deck 1", backgroundUrl: "", }, ], deckNodes: [ { id: 1, deckIndex: 0, x: 0, y: 0, volume: 12000, flags: [], systems: ["reactor"], isRoom: true, contents: { Deuterium: { count: 100, }, }, }, ], }); ship.addComponent("shipSystems"); ship.components.shipSystems?.shipSystems.set(reactor.id, { roomId: 1 }); system = new Entity(); system.addComponent("isShipSystem", { type: "generic", }); const powerDraw = Math.ceil(reactorComponent.maxOutput * reactorComponent.optimalOutputPercent); system.addComponent("power", { powerDraw, }); ship.components.shipSystems?.shipSystems.set(system.id, { roomId: 1 }); ecs.addEntity(system); ecs.addEntity(reactor); ecs.addEntity(ship); ecs.addSystem(filterShipsWithReactorSystem); ecs.addSystem(filterInventorySystem); ecs.addSystem(reactorFuelSystem); }); it("should create a list of ships with reactor systems", () => { const ship2 = new Entity(); ship2.addComponent("isShip", {}); ship2.addComponent("shipSystems"); ecs.addEntity(ship2); expect(filterShipsWithReactorSystem.entities.size).toEqual(1); expect(filterShipsWithReactorSystem.entities.values().next().value).toEqual(ship); }); it("should detect the correct amount of items related to a system", () => { const fuelList = getReactorInventory(reactor); expect(fuelList).toHaveLength(1); expect(fuelList?.[0].name).toEqual("Deuterium"); }); it("should generate power from the unusedFuel every frame", () => { if (!reactor.components.isReactor) throw new Error("not reactor"); reactor.components.isReactor.unusedFuel = { amount: 0.33, density: 1 }; if (ship.components.shipMap) { ship.components.shipMap.deckNodes[0].contents.Deuterium.count = 0; } const reactorComponent = reactor.components.isReactor; expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.33`); for (let i = 0; i < 60; i++) { ecs.update(16); } expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.3284571428571423`); for (let i = 0; i < 60 * 9 + 50; i++) { ecs.update(16); } expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.3132857142857079`); ecs.update(16); expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.3132599999999936`); }); it("should use inventory fuel if it ever runs out of regular fuel", () => { if (!reactor.components.isReactor) throw new Error("not reactor"); reactor.components.isReactor.unusedFuel = { amount: 0.01, density: 1, }; const reactorComponent = reactor.components.isReactor; expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.01`); expect(ship.components.shipMap?.deckNodes[0].contents.Deuterium.count).toMatchInlineSnapshot( `100`, ); for (let i = 0; i < 60; i++) { ecs.update(16); } expect(reactorComponent.currentOutput).toMatchInlineSnapshot("6"); expect(reactorComponent.unusedFuel.amount).toMatchInlineSnapshot(`0.00845714285714289`); expect(ship.components.shipMap?.deckNodes[0].contents.Deuterium.count).toMatchInlineSnapshot( "100", ); }); });