import assert from "node:assert/strict"; import test from "node:test"; import { ARENA_STAGES } from "./arena-stages.mjs"; import { ArenaSimulation, ARENA_TICK_RATE, arenaDynamicObjectState } from "./arena-simulation.mjs"; function participants() { return [ { actorId: "left-healer", name: "Left Healer", team: 0, role: "healer", isBot: false, rating: 1200 }, { actorId: "left-damage", name: "Left Damage", team: 0, role: "damage", isBot: true, rating: 1200 }, { actorId: "right-healer", name: "Right Healer", team: 1, role: "healer", isBot: true, rating: 1200 }, { actorId: "right-damage", name: "Right Damage", team: 1, role: "damage", isBot: true, rating: 1200 }, ]; } test("authoritative simulation seals ten seconds, runs 20 Hz, and rejects duplicate packets", () => { const stage = ARENA_STAGES.find((entry) => entry.id === "warnorken-arena"); const simulation = new ArenaSimulation({ id: "sim", stage, bracket: "2v2", mode: "rated-ai", ruleset: "wow", participants: participants(), random: () => 0 }); for (let index = 0; index < ARENA_TICK_RATE * 10 - 1; index += 1) simulation.step(); assert.equal(simulation.snapshot().phase, "preparation"); simulation.step(); assert.equal(simulation.snapshot().phase, "active"); assert.equal(simulation.receiveIntent("left-healer", { sequence: 1, type: "movement", movement: { x: 1, z: 0 } }).accepted, true); assert.equal(simulation.receiveIntent("left-healer", { sequence: 1, type: "movement", movement: { x: 1, z: 0 } }).reason, "stale-sequence"); const before = simulation.actor("left-healer").position[0]; simulation.step(); assert.ok(simulation.actor("left-healer").position[0] > before); }); test("a deferred practice start receives a fresh preparation clock", () => { const stage = ARENA_STAGES.find((entry) => entry.id === "warnorken-arena"); const simulation = new ArenaSimulation({ id: "deferred", stage, bracket: "2v2", mode: "practice", ruleset: "wow", participants: participants(), startedAt: 1_000 }); assert.equal(simulation.resetPreparationClock(20_000), true); assert.equal(simulation.snapshot().serverTime, 20_000); assert.equal(simulation.snapshot().phaseEndsAt, 30_000); }); test("Dalaran and Ring of Valor mechanics synchronize collision state", () => { const dalaran = ARENA_STAGES.find((entry) => entry.id === "dalaran-sewers"); const warning = arenaDynamicObjectState(dalaran, 27_000).find((entry) => entry.id === "waterfall"); const active = arenaDynamicObjectState(dalaran, 31_000).find((entry) => entry.id === "waterfall"); assert.equal(warning.state, "warning"); assert.equal(active.state, "active"); assert.equal(active.collisionEnabled, true); const ring = ARENA_STAGES.find((entry) => entry.id === "ring-of-valor"); assert.equal(arenaDynamicObjectState(ring, 20_000).find((entry) => entry.id === "elevators").state, "raised"); assert.equal(arenaDynamicObjectState(ring, 21_000).find((entry) => entry.id === "elevators").state, "moving"); assert.equal(arenaDynamicObjectState(ring, 22_500).find((entry) => entry.id === "elevators").state, "open"); assert.equal(arenaDynamicObjectState(ring, 24_000).find((entry) => entry.id === "pillars-north").state, "lowered"); assert.equal(arenaDynamicObjectState(ring, 26_000).find((entry) => entry.id === "pillars-north").state, "raised"); });