Files
Module-Rust/client/test/mapEvents.test.js
wtclaude 481837e937
All checks were successful
PR Checks / server-tests (pull_request) Successful in 37s
PR Checks / client-build (pull_request) Successful in 24s
PR Checks / frozen-manifest (pull_request) Successful in 49s
feat(rust): RaidableBases — feed, raids map layer, Warlord, Spawn a raid base, profiles (PLAN_REDESIGNS §11.4)
PLAN_REDESIGNS §11.4 (D202-D208, D386-D391), protocol 14. Spec: docs
rust-link/PROTOCOL.md §20.12.

- raid.started, raid.completed, raid.purchased and raid.locked public,
  raid.ended staff's; raidableBases.js reads each row per viewer (raiders'
  and a buyer's names only for the presence audience, D376/D390; Steam ids,
  position and a run's key only for staff). Feed lines in the World filter.
- The step rust.raidbase.spawn, "Spawn a raid base" (ledgered, budget
  rust.raids): difficulty, profile and base from option sources listing each
  server's own names (D386), a spot as a world call's location with a height
  adjustment or an exact height, and PvP/NPCs/lock as on/off/blank. A base
  the raids helper made is a world resource, so eventWorld's revert and
  reconcile serve it and world.expired marks it expired; one it did not make
  records nothing and the run log says it despawns on its own timer. Refused
  at verify for a server that said it cannot; a dry run with a spot returns
  the spot check as detail.warnings (MODULE_API 1.16.0, D391). rb-not-ready
  retries in ten minutes.
- Warlord: raids_completed, title category raidscompleted, the leaderboard's
  Raid bases column (sort=raidsCompleted).
- The map's raids layer (D114), public by default with its own audience; the
  run's key is dropped before any viewer gets it.
- Server settings' line for RaidableBases; its profiles in Mod configuration
  under a virtual path (D205).
- Swagger fragment, bundle and README.

Tests: server 684/684 (raidableBases.test.js new, every name in it invented);
client 99/99, build and externals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-16 15:18:52 -05:00

69 lines
3.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ── What an event marker says (runicnpc stage 8, D302, D303) ──────────────
//
// The decisions: a name and an event title, never health; a boss marked and
// drawn bigger; an unannounced event named by nothing but "an event".
import test from 'node:test'
import assert from 'node:assert/strict'
import { createRequire } from 'node:module'
import { eventTip, isBoss, pvpTip, PVP_NAMES, raidTip, titlesFrom, unknownRuns } from '../src/lib/mapEvents.js'
const CALENDAR = {
entries: [
{ kind: 'run', runId: 41, title: 'Harbour Raid' },
{ kind: 'projected', title: 'Next week' },
{ kind: 'run', runId: 42, title: '' },
],
}
test("the calendar's runs become titles by run id; a projection has none", () => {
assert.deepEqual(titlesFrom(CALENDAR), { 41: 'Harbour Raid' })
assert.deepEqual(titlesFrom(null), {})
})
test('an NPC says its name and its event; a boss and an add say which they are', () => {
const titles = titlesFrom(CALENDAR)
assert.equal(eventTip({ kind: 'npc', runId: '41', name: 'Bandit' }, titles), 'Bandit · Harbour Raid')
assert.equal(eventTip({ kind: 'npc', runId: '41', name: 'The Juggernaut', boss: true }, titles), 'The Juggernaut (boss) · Harbour Raid')
assert.equal(eventTip({ kind: 'npc', runId: '41', name: 'Bandit', add: true }, titles), "Bandit (a boss's add) · Harbour Raid")
})
test('an unannounced event, a Rust scientist and a crate', () => {
assert.equal(eventTip({ kind: 'npc', runId: '7', name: 'Bandit' }, {}), 'Bandit · an event')
assert.equal(eventTip({ kind: 'npc', runId: '41' }, { 41: 'Harbour Raid' }), 'Event NPC · Harbour Raid')
assert.equal(eventTip({ kind: 'crate', runId: '41' }, { 41: 'Harbour Raid' }), 'Event crate · Harbour Raid')
})
test('health never reaches a tooltip, even if a row carried it', () => {
assert.equal(eventTip({ kind: 'npc', runId: '41', name: 'J', boss: true, health: 0.5 }, {}).includes('50'), false)
})
test('a boss is an event boss or a world one', () => {
assert.equal(isBoss({ kind: 'npc', boss: true }), true)
assert.equal(isBoss({ kind: 'boss' }), true)
assert.equal(isBoss({ kind: 'npc' }), false)
})
test('the run ids still to look up', () => {
assert.deepEqual(unknownRuns([{ runId: '41' }, { runId: '7' }, { runId: '7' }, {}], { 41: 'x' }), ['7'])
})
// Dynamic PVP's rings (PLAN_REDESIGNS §14.3.3): its own events by a plain name,
// a monument's or an operator's as written, and nothing at all as just a zone.
test('a Dynamic PVP ring says what it is around', () => {
assert.equal(pvpTip({ event: 'Helicopter' }), 'PvP zone · Patrol helicopter')
assert.equal(pvpTip({ event: 'Airfield' }), 'PvP zone · Airfield')
assert.equal(pvpTip({}), 'PvP zone')
const { GENERAL_EVENTS } = createRequire(import.meta.url)('../../server/dynamicPvp.js')
assert.deepEqual(Object.keys(PVP_NAMES).sort(), [...GENERAL_EVENTS].sort())
})
test('a raid base’s tooltip says its own difficulty and base, PvP, when it despawns, and whether an event of this site spawned it', () => {
const now = 1_000_000
assert.equal(raidTip({ difficulty: 'Wobbly', base: 'wobble3', pvp: true, despawnAt: now + 42 * 60000 }, now), 'Raid base · Wobbly · wobble3 · PvP · despawns in 42 min')
assert.equal(raidTip({ difficulty: 'Wobbly', runId: '7' }, now), 'Raid base · Wobbly · this site’s event')
assert.equal(raidTip({ despawnAt: now - 1 }, now), 'Raid base')
})