Something went wrong. Try again.
Starship Simulator Controls thoriumsim.com
Something went wrong. Try again.
11 kB · 323 lines
TypeScript
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324import { PowerDistributionSystem } from "@thorium/.server/systems/PowerDistributionSystem";import { thoriumContext } from "@thorium/utils/.server/context";import { createMockDataContext } from "@thorium/utils/.server/createMockDataContext";import { testDataStoreProps } from "@thorium/utils/.server/db-fs/testDataStoreProps";import { ECS, Entity } from "@thorium/utils/ecs";import { randomFromList } from "@thorium/utils/operations/randomFromList";import { aroundEach, beforeEach, describe, expect, it } from "vitest";
aroundEach(async (runTest) => { await thoriumContext.run(testDataStoreProps, async () => { await runTest(); });});
describe("PowerDistributionSystem", () => { let ecs: ECS; let ship: Entity; beforeEach(() => { const mockDataContext = createMockDataContext();
ecs = new ECS(mockDataContext.server); ecs.addSystem(new PowerDistributionSystem()); ship = new Entity(); ship.addComponent("isShip"); ship.addComponent("isPlayerShip"); ship.addComponent("shipSystems"); ecs.addEntity(ship); }); it("should work with a simple setup", () => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 6, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor);
const system = new Entity(); system.addComponent("isShipSystem", { type: "generic" }); system.addComponent("power", { powerDraw: 4, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system.id, {}); ecs.addEntity(system);
expect(system.components.power?.currentPower).toEqual(0);
ecs.update(16); expect(system.components.power?.currentPower).toEqual(4);
ecs.update(16); expect(system.components.power?.currentPower).toEqual(4); expect(reactor.components.isReactor?.currentOutput).toEqual(6);
system.updateComponent("power", { powerDraw: 2 }); ecs.update(16); expect(system.components.power?.currentPower).toEqual(2); expect(reactor.components.isReactor?.currentOutput).toEqual(6); });
it("should properly distribute power from a single reactor to multiple systems", () => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 6, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor);
const system1 = new Entity(); system1.addComponent("isShipSystem", { type: "generic" }); system1.addComponent("power", { powerDraw: 3, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system1.id, {}); ecs.addEntity(system1); const system2 = new Entity(); system2.addComponent("isShipSystem", { type: "generic" }); system2.addComponent("power", { powerDraw: 3, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system2.id, {}); ecs.addEntity(system2);
ecs.update(16); expect(system1.components.power?.currentPower).toEqual(3); expect(system2.components.power?.currentPower).toEqual(3);
system1.updateComponent("power", { powerDraw: 1 }); ecs.update(16); expect(system1.components.power?.currentPower).toEqual(1); expect(system2.components.power?.currentPower).toEqual(3); });
it("should work with multiple reactors connected to multiple systems", () => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 10, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor);
const system1 = new Entity(); system1.addComponent("isShipSystem", { type: "generic" }); system1.addComponent("power", { powerDraw: 4, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system1.id, {}); ecs.addEntity(system1); const system2 = new Entity(); system2.addComponent("isShipSystem", { type: "generic" }); system2.addComponent("power", { powerDraw: 4, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system2.id, {}); ecs.addEntity(system2); const system3 = new Entity(); system3.addComponent("isShipSystem", { type: "generic" }); system3.addComponent("power", { powerDraw: 4, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system3.id, {}); ecs.addEntity(system3); const system4 = new Entity(); system4.addComponent("isShipSystem", { type: "generic" }); system4.addComponent("power", { powerDraw: 4, currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system4.id, {}); ecs.addEntity(system4);
ecs.update(16); expect(system1.components.power?.currentPower).toEqual(4); expect(system2.components.power?.currentPower).toEqual(4); expect(system3.components.power?.currentPower).toEqual(2); expect(system4.components.power?.currentPower).toEqual(0); expect(system3.components.power?.powerActivated).toEqual(true); expect(system4.components.power?.powerActivated).toEqual(true);
const reactor2 = new Entity(); reactor2.addComponent("isShipSystem", { type: "reactor" }); reactor2.addComponent("isReactor", { currentOutput: 2, }); ship.components.shipSystems?.shipSystems.set(reactor2.id, {}); ecs.addEntity(reactor2); system3.updateComponent("power", { powerActivated: true }); system4.updateComponent("power", { powerActivated: true });
ecs.update(16); expect(system1.components.power?.currentPower).toEqual(4); expect(system2.components.power?.currentPower).toEqual(4); expect(system3.components.power?.currentPower).toEqual(4); expect(system4.components.power?.currentPower).toEqual(0); expect(system3.components.power?.powerActivated).toEqual(true); expect(system4.components.power?.powerActivated).toEqual(true); }); it("should properly charge and discharge batteries", () => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 8, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor);
const battery = new Entity(); battery.addComponent("isShipSystem", { type: "battery" }); battery.addComponent("isBattery", { storage: 0, }); ship.components.shipSystems?.shipSystems.set(battery.id, {}); ecs.addEntity(battery);
const system = new Entity(); system.addComponent("isShipSystem", { type: "generic" }); system.addComponent("power", { powerDraw: 2, currentPower: 0 }); ship.components.shipSystems?.shipSystems.set(system.id, {}); ecs.addEntity(system);
expect(battery.components.isBattery?.storage).toEqual(0); for (let i = 0; i < 60; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toMatchInlineSnapshot(`0.0010666666666666676`); for (let i = 0; i < 30; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toMatchInlineSnapshot(`0.0016000000000000016`);
battery.updateComponent("isBattery", { storage: 0, }); ecs.update(16); const storage = battery.components.isBattery?.storage; expect(storage).toBeGreaterThan(0);
battery.updateComponent("isBattery", { storage: 0, }); ecs.update(16); expect(storage).toEqual(battery.components.isBattery?.storage);
battery.updateComponent("isBattery", { storage: 0 }); ecs.update(16); expect(battery.components.isBattery?.chargeAmount).toEqual(4);
// It should take about 32 minutes to fully charge a battery at this rate. for (let i = 0; i < 60 * 60 * 32; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toBeCloseTo( battery.components.isBattery!.capacity, );
// It should take about 10 1/2 minutes to fully discharge a battery at this rate. expect(battery.components.isBattery?.storage).toEqual(2); system.updateComponent("power", { batterySource: battery.id, powerDraw: 6 }); reactor.updateComponent("isReactor", { currentOutput: 0 }); ecs.update(16); expect(battery.components.isBattery?.storage).toEqual(1.9999733333333334); expect(battery.components.isBattery?.outputAmount).toEqual(6); expect(system.components.power?.currentPower).toEqual(6); for (let i = 0; i < 60 * 60 * 21; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toEqual(0); expect(battery.components.isBattery?.outputAmount).toEqual(0); expect(system.components.power?.currentPower).toEqual(0); });
it("should not charge batteries when their powerActivated is false", () => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 8, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor);
const battery = new Entity(); battery.addComponent("isShipSystem", { type: "battery" }); battery.addComponent("isBattery", { storage: 0, }); ship.components.shipSystems?.shipSystems.set(battery.id, {}); ecs.addEntity(battery);
expect(battery.components.isBattery?.storage).toEqual(0); for (let i = 0; i < 60; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toMatchInlineSnapshot(`0.0010666666666666676`); for (let i = 0; i < 30; i++) { ecs.update(16); } expect(battery.components.isBattery?.storage).toMatchInlineSnapshot(`0.0016000000000000016`); const previousStorage = battery.components.isBattery?.storage; expect(typeof previousStorage).toBe("number"); battery.updateComponent("isBattery", { powerActivated: false, }); ecs.update(16); const storage = battery.components.isBattery?.storage; expect(storage).toEqual(previousStorage); });
it("should perform decently well", () => { Array.from({ length: 5 }).map(() => { const reactor = new Entity(); reactor.addComponent("isShipSystem", { type: "reactor" }); reactor.addComponent("isReactor", { currentOutput: 10, }); ship.components.shipSystems?.shipSystems.set(reactor.id, {}); ecs.addEntity(reactor); return reactor; });
const batteries = Array.from({ length: 4 }).map(() => { const battery = new Entity(); battery.addComponent("isShipSystem", { type: "battery" }); battery.addComponent("isBattery", { storage: 0, });
ship.components.shipSystems?.shipSystems.set(battery.id, {}); ecs.addEntity(battery); return battery; });
Array.from({ length: 50 }).map(() => { const system = new Entity(); system.addComponent("isShipSystem", { type: "generic" }); system.addComponent("power", { powerDraw: Math.ceil(Math.random() * 6), currentPower: 0, }); ship.components.shipSystems?.shipSystems.set(system.id, {}); ecs.addEntity(system); for (let i = 0; i < (system.components.power?.powerDraw || 0); i++) { system.updateComponent("power", { batterySource: Math.random() > 0.5 ? randomFromList(batteries).id : null, }); }
return system; });
const time = ecs.now(); ecs.update(16); const now = ecs.now(); expect(now - time).toBeLessThan(2); });});