@@ -0,0 +1,428 @@
// ── RaidableBases (PLAN_REDESIGNS §11.4, protocol 14) ───────────────────────
//
// Each test is one way the feature could look right and be wrong:
//
// a raider's or a buyer's name reaches a viewer below the presence audience
// (D376, D390), or a Steam id, a position or a run's key reaches anybody but staff
// a difficulty, profile or base name is anything but the plugin's own (D386):
// every name below is invented, so a list written into the code cannot pass
// the step asks for a spot, a profile, a base or settings on a server without a
// patched raids helper, or refuses a plain spawn a server can still make (D348)
// a base the helper made is not the run's resource, or one it did not make is
// the dry run's spot check fails the dry run instead of advising (D391)
// the grid's wait is not a ten-minute retry, or a refusal the plugin would
// repeat is retried
// the tally's raids completed is dropped, or Warlord's column and sort are missing
// the map's raids layer is missing, not public by default, or carries the key
const test = require ( 'node:test' )
const assert = require ( 'node:assert' )
const { fakeCtx } = require ( './_fakes' )
/** Installs a core whose `db.query` records every statement and answers `rows`. */
function withRecorder ( rows = [ ] ) {
const statements = [ ]
const ctx = fakeCtx ( {
db : {
query : ( sql , params = [ ] ) => {
statements . push ( { sql , params } )
return Promise . resolve ( typeof rows === 'function' ? rows ( sql , params ) : rows )
} ,
pool : { } ,
} ,
} )
require ( '../core' ) . _reset ( )
require ( '../core' ) . init ( ctx )
return { ctx , statements , touching : ( table ) => statements . filter ( ( s ) => s . sql . includes ( table ) ) }
}
withRecorder ( )
const rb = require ( '../raidableBases' )
const catalogue = require ( '../catalogue' )
const { gridOf } = require ( '../worldEvents' )
const A = '76561198000000001'
const B = '76561198000000002'
const NOW = Date . now ( )
const GEOMETRY = { worldSize : 6000 , gridCells : 41 , gridCellSize : 146.34146341463415 }
const frame = ( kind , over = { } ) => ( { kind , type : 'event' , t : NOW , serverId : 'main' , wipeId : 'w1' , x : 650 , z : 2037 , level : 7 , difficulty : 'Wobbly' , pvp : true , base : 'wobble3' , ... over } )
const raided = ( over = { } ) =>
frame ( 'raid.completed' , {
raiders : [ { steamId : A , name : 'Alice' } , { steamId : B , name : 'Bob' } ] ,
raiderCount : 2 ,
ownerId : A ,
ownerName : 'Alice' ,
id : 'raid-1-1' ,
runId : '7' ,
key : '7:1' ,
... over ,
} )
// Invented, every one (D386): no edition ships these.
const PROFILE = { name : 'Wobbly Keeps' , difficulty : 'Wobbly' , level : 7 , enabled : true , pvp : false , bases : [ 'wobble1' , 'wobble3' ] , seabed : false , float : false }
const REPORT = {
loaded : true ,
version : '3.2.2' ,
premium : true ,
spawnCall : true ,
copyPaste : { loaded : true , version : '4.3.0' } ,
difficulties : [ { name : 'Gentle' , level : 0 } , { name : 'Wobbly' , level : 7 } ] ,
helper : { state : 'patched' , version : '0.1.0' } ,
gridReady : true ,
profiles : [ PROFILE , { name : 'Gentle Huts' , difficulty : 'Gentle' , level : 0 , enabled : true , pvp : true , bases : [ 'hut9' ] , seabed : false , float : false } ] ,
}
// ── Who may read what (D353, D376, D390) ───────────────────────────────────
test ( 'the kinds are classified: four public, the despawn staff’ s' , ( ) => {
for ( const kind of [ 'raid.started' , 'raid.completed' , 'raid.purchased' , 'raid.locked' ] ) assert . ok ( catalogue . PUBLIC _KINDS . includes ( kind ) , kind )
assert . ok ( catalogue . STAFF _KINDS . includes ( 'raid.ended' ) )
assert . ok ( ! catalogue . PUBLIC _KINDS . includes ( 'raid.ended' ) )
} )
test ( 'the public reads a base’ s difficulty, base, PvP and grid as the plugin named them, never its position or a run’ s key' , ( ) => {
const out = rb . shapeFor ( frame ( 'raid.started' , { despawnAt : NOW + 60000 , id : 'raid-1-1' , runId : '7' , key : '7:1' , radius : 50 } ) , { geometry : GEOMETRY } )
assert . strictEqual ( out . grid , gridOf ( GEOMETRY , 650 , 2037 ) )
assert . strictEqual ( out . difficulty , 'Wobbly' )
assert . strictEqual ( out . level , 7 )
assert . strictEqual ( out . base , 'wobble3' )
assert . strictEqual ( out . pvp , true )
assert . strictEqual ( out . despawnAt , NOW + 60000 )
for ( const k of [ 'x' , 'z' , 'id' , 'runId' , 'key' , 'radius' ] ) assert . strictEqual ( out [ k ] , undefined , k )
} )
test ( 'a completion names its raiders only to the presence audience, and their Steam ids only to staff' , ( ) => {
const signedOut = rb . shapeFor ( raided ( ) , { geometry : GEOMETRY } )
assert . strictEqual ( signedOut . raiderCount , 2 , 'how many is a count, and names nobody' )
assert . strictEqual ( signedOut . names , undefined )
assert . strictEqual ( signedOut . ownerName , undefined )
assert . strictEqual ( signedOut . raiders , undefined )
assert . strictEqual ( signedOut . ownerId , undefined )
const member = rb . shapeFor ( raided ( ) , { presence : true , geometry : GEOMETRY } )
assert . deepStrictEqual ( member . names , [ 'Alice' , 'Bob' ] )
assert . strictEqual ( member . ownerName , 'Alice' )
assert . strictEqual ( member . raiders , undefined )
const staff = rb . shapeFor ( raided ( ) , { staff : true , geometry : GEOMETRY } )
assert . deepStrictEqual ( staff . raiders , [ { steamId : A , name : 'Alice' } , { steamId : B , name : 'Bob' } ] )
assert . strictEqual ( staff . ownerId , A )
assert . strictEqual ( staff . key , '7:1' )
assert . strictEqual ( staff . x , 650 )
} )
test ( 'a purchase or an admin lock names the player only to the presence audience (D390)' , ( ) => {
for ( const kind of [ 'raid.purchased' , 'raid.locked' ] ) {
const f = frame ( kind , { steamId : A , name : 'Alice' } )
assert . strictEqual ( rb . shapeFor ( f , { } ) . name , undefined , kind )
assert . strictEqual ( rb . shapeFor ( f , { presence : true } ) . name , 'Alice' , kind )
assert . strictEqual ( rb . shapeFor ( f , { presence : true } ) . steamId , undefined , kind )
assert . strictEqual ( rb . shapeFor ( f , { staff : true } ) . steamId , A , kind )
}
} )
test ( 'the feed reads a stored completion for its viewer, the row’ s own Steam id staff’ s' , async ( ) => {
withRecorder ( ( sql ) => {
if ( sql . includes ( 'FROM rust_events' ) ) return [ { id : 9 , kind : 'raid.completed' , t : NOW , wipeId : 'w1' , steamId : A , raw : JSON . stringify ( raided ( ) ) } ]
if ( sql . includes ( 'FROM rust_map_images' ) ) return [ { serverId : 'main' , ... GEOMETRY } ]
return [ ]
} )
const events = require ( '../model/events/events.model' )
const [ signedOut ] = await events . recent ( { serverId : 'main' , presence : false } )
assert . strictEqual ( signedOut . steamId , null )
assert . strictEqual ( signedOut . frame . names , undefined )
assert . strictEqual ( signedOut . frame . raiderCount , 2 )
assert . strictEqual ( signedOut . frame . difficulty , 'Wobbly' )
assert . ok ( signedOut . frame . grid )
const [ staff ] = await events . recent ( { serverId : 'main' , admin : true } )
assert . strictEqual ( staff . steamId , A )
assert . deepStrictEqual ( staff . frame . names , [ 'Alice' , 'Bob' ] )
} )
test ( 'a server’ s report is read leniently, and the helper’ s profiles only as it sent them' , ( ) => {
assert . deepStrictEqual ( rb . reportOf ( null ) , { raidableBases : null , consolePlugins : null } )
const read = rb . reportOf ( { raidableBases : JSON . stringify ( REPORT ) , console : '{"plugins":false}' } )
assert . strictEqual ( read . consolePlugins , false )
assert . deepStrictEqual ( read . raidableBases . difficulties , REPORT . difficulties )
assert . deepStrictEqual ( read . raidableBases . profiles [ 0 ] , PROFILE )
assert . strictEqual ( rb . helperPatched ( read ) , true )
const bare = rb . reportOf ( { raidableBases : '{"loaded":true,"version":"3.2.2","helper":{"state":"missing"}}' , console : null } )
assert . strictEqual ( bare . raidableBases . profiles , null , 'no helper, no profile list' )
assert . strictEqual ( bare . raidableBases . spawnCall , false )
assert . strictEqual ( rb . helperPatched ( bare ) , false )
assert . deepStrictEqual ( rb . reportOf ( { raidableBases : 'not json' } ) . raidableBases , null )
} )
// ── The step ───────────────────────────────────────────────────────────────
const SERVERS = {
main : { id : 'main' , name : 'Main' , enabled : 1 , sidecarBaseUrl : 'http://main:1' } ,
pve : { id : 'pve' , name : 'PvE' , enabled : 1 , sidecarBaseUrl : 'http://pve:1' } ,
}
/** The step against `main` and `pve`, whose last reports are `reports`, and a sidecar answering `reply` and `check`. */
function stubStep ( t , { reports = { main : { raidableBases : REPORT , console : { plugins : true } } } , reply , check } = { } ) {
const row = ( id ) => {
const r = reports [ id ]
return r ? { serverId : id , name : SERVERS [ id ] . name , raidableBases : JSON . stringify ( r . raidableBases ? ? null ) , console : JSON . stringify ( r . console ? ? null ) } : null
}
withRecorder ( ( sql , params ) => {
if ( sql . includes ( 'JOIN rust_server_state' ) ) return Object . keys ( reports ) . map ( row )
if ( sql . includes ( 'FROM rust_server_state' ) ) return row ( params [ 0 ] ) ? [ row ( params [ 0 ] ) ] : [ ]
if ( sql . includes ( 'FROM rust_map_images' ) ) return [ { serverId : 'main' , ... GEOMETRY } ]
return [ ]
} )
const client = require ( '../sidecarClient' )
const serversDb = require ( '../model/servers/servers.db' )
const saved = { raidSpawn : client . raidSpawn , raidCheck : client . raidCheck , getServer : serversDb . getServer }
const calls = [ ]
serversDb . getServer = async ( id ) => SERVERS [ id ] || null
client . raidSpawn = async ( server , body ) => {
calls . push ( { what : 'spawn' , server : server . id , body } )
return typeof reply === 'function' ? reply ( body ) : reply
}
client . raidCheck = async ( server , body ) => {
calls . push ( { what : 'check' , server : server . id , body } )
return typeof check === 'function' ? check ( body ) : check
}
t . after ( ( ) => {
client . raidSpawn = saved . raidSpawn
client . raidCheck = saved . raidCheck
serversDb . getServer = saved . getServer
} )
return calls
}
const module _ = ( ) => require ( '../eventRaidableBases' )
const spawnStep = ( ) => module _ ( ) . ACTIONS [ 0 ]
const ok = ( data ) => ( { ok : true , status : 'ok' , data } )
const queued = ( over = { } ) => ok ( { kind : 'raid.queued' , key : '7:1' , id : 'raid-1-1' , route : 'pick' , despawns : 'teardown' , difficulty : 'Wobbly' , level : 7 , warnings : [ ] , repeat : false , ... over } )
test ( 'the step is ledgered like a zone, priced one base each, and every param has an example' , ( ) => {
const step = spawnStep ( )
assert . strictEqual ( step . id , 'rust.raidbase.spawn' )
assert . strictEqual ( step . reversible , 'ledger' )
assert . strictEqual ( step . risk , 'change' )
assert . strictEqual ( typeof step . revert , 'function' )
assert . strictEqual ( typeof step . reconcile , 'function' )
assert . deepStrictEqual ( step . cost ( { } ) , { 'rust.raids' : 1 } )
for ( const p of step . params ) assert . ok ( p . example !== undefined , p . name )
} )
test ( 'the pickers list each server’ s own names, once each, and nothing for a server that has not said (D386)' , async ( t ) => {
const [ difficulties , profiles , bases , switches ] = module _ ( ) . OPTION _SOURCES
stubStep ( t , {
reports : {
main : { raidableBases : REPORT } ,
pve : { raidableBases : { ... REPORT , difficulties : [ { name : 'wobbly' , level : 7 } , { name : 'Brutal' , level : 9 } ] , profiles : [ ] } } ,
} ,
} )
assert . deepStrictEqual ( await difficulties . resolve ( ) , [
{ value : 'Gentle' , label : 'Gentle (level 0) — Main' } ,
{ value : 'Wobbly' , label : 'Wobbly (level 7) — Main, PvE' } ,
{ value : 'Brutal' , label : 'Brutal (level 9) — PvE' } ,
] )
assert . deepStrictEqual ( ( await profiles . resolve ( ) ) . map ( ( p ) => p . value ) , [ 'Wobbly Keeps' , 'Gentle Huts' ] )
assert . deepStrictEqual ( ( await bases . resolve ( { q : 'wobble' } ) ) . map ( ( b ) => b . value ) , [ 'wobble1' , 'wobble3' ] )
assert . strictEqual ( bases . searchable , true )
assert . deepStrictEqual ( ( await switches . resolve ( ) ) . map ( ( s ) => s . value ) , [ 'on' , 'off' ] )
stubStep ( t , { reports : { main : { raidableBases : { loaded : false } } } } )
assert . deepStrictEqual ( await difficulties . resolve ( ) , [ ] , 'nothing is made up for a server without the plugin' )
} )
test ( 'without a patched helper, a spot, a profile, a base or settings are refused; a plain spawn is not (D348, D387)' , async ( t ) => {
const run = ( params ) => spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , ... params } , verify : true } )
stubStep ( t , { reports : { main : { raidableBases : { ... REPORT , helper : { state : 'missing' } , profiles : null } , console : { plugins : true } } } } )
for ( const params of [ { x : 650 , z : 2037 } , { profile : 'Wobbly Keeps' } , { base : 'wobble1' } , { pvp : 'off' } , { npcCount : 3 } , { lock : 'on' } , { despawnMinutes : 60 } ] ) {
const no = await run ( params )
assert . strictEqual ( no . retry , false , JSON . stringify ( params ) )
assert . match ( no . error , /RunicGatewayRaids\.cs is not installed on Main/ )
assert . match ( no . error , /despawns the base on its own timer/ )
}
assert . deepStrictEqual ( await run ( { difficulty : 'Wobbly' } ) , { ok : true } )
assert . deepStrictEqual ( await run ( { } ) , { ok : true } )
stubStep ( t , { reports : { main : { raidableBases : { ... REPORT , helper : { state : 'missing' } , spawnCall : false , profiles : null } , console : { plugins : false } } } } )
const carbon = await run ( { } )
assert . match ( carbon . error , /cannot run RaidableBases' console command/ )
} )
test ( 'the dry run refuses names the server does not have, and names that do not fit together' , async ( t ) => {
const run = ( params ) => spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , ... params } , verify : true } )
stubStep ( t )
assert . match ( ( await run ( { difficulty : 'Easy' } ) ) . error , /"Easy" is not one of RaidableBases' difficulties on Main \(Gentle, Wobbly\)/ )
assert . match ( ( await run ( { profile : 'Nope' } ) ) . error , /no profile "Nope"/ )
assert . match ( ( await run ( { base : 'nope1' } ) ) . error , /no base "nope1"/ )
assert . match ( ( await run ( { profile : 'Gentle Huts' , base : 'wobble1' } ) ) . error , /belongs to profile "Wobbly Keeps"/ )
assert . match ( ( await run ( { profile : 'Wobbly Keeps' , difficulty : 'Gentle' } ) ) . error , /is Wobbly, not Gentle/ )
assert . match ( ( await run ( { heightAdjust : 5 } ) ) . error , /a height needs a spot/ )
assert . match ( ( await run ( { x : 650 , z : 2037 , heightAdjust : 5 , height : 30 } ) ) . error , /not both/ )
assert . match ( ( await run ( { pvp : 'maybe' } ) ) . error , /pvp is on, off or blank/ )
assert . match ( ( await run ( { npcCount : 21 } ) ) . error , /0 to 20/ )
assert . deepStrictEqual ( await run ( { base : 'WOBBLE3' } ) , { ok : true } , 'names match as the plugin matches them, ignoring case' )
stubStep ( t , { reports : { main : { raidableBases : { loaded : false } } } } )
assert . match ( ( await run ( { } ) ) . error , /RaidableBases is not installed on Main/ )
stubStep ( t , { reports : { main : { raidableBases : { ... REPORT , copyPaste : { loaded : false } } } } } )
assert . match ( ( await run ( { } ) ) . error , /CopyPaste is missing/ )
stubStep ( t , { reports : { } } )
assert . deepStrictEqual ( await run ( { x : 650 , z : 2037 } ) , { ok : true } , 'a server that has not said is the plugin’ s to answer' )
} )
test ( 'a spot’ s check in the dry run is advice: warnings, never a refusal (D208, D388, D391)' , async ( t ) => {
const calls = stubStep ( t , {
check : ok ( { kind : 'raid.checked' , ok : false , reason : 'spot-blocked' , message : 'a player is within 50 m (Alice)' , warnings : [ 'Rock is too large: 1 2 3' ] } ) ,
} )
const advised = await spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , x : 650 , z : 2037 , base : 'wobble3' , pvp : 'off' } , verify : true } )
assert . strictEqual ( advised . ok , true )
assert . deepStrictEqual ( advised . detail . warnings , [
'the spot is refused now (spot-blocked): a player is within 50 m (Alice). It is checked again when the event runs' ,
'at the spot now: Rock is too large: 1 2 3' ,
] )
assert . deepStrictEqual ( calls [ 0 ] . body , { base : 'wobble3' , x : 650 , z : 2037 } , 'the check asks the spot and the base, not the settings' )
assert . ok ( ! calls . some ( ( c ) => c . what === 'spawn' ) , 'a dry run spawns nothing' )
stubStep ( t , { check : ok ( { kind : 'raid.checked' , ok : true , warnings : [ ] } ) } )
assert . deepStrictEqual ( await spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , x : 650 , z : 2037 } , verify : true } ) , { ok : true } )
stubStep ( t , { check : { ok : false , status : 'http-503' } } )
const down = await spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , x : 650 , z : 2037 } , verify : true } )
assert . strictEqual ( down . ok , true )
assert . match ( down . detail . warnings [ 0 ] , /could not be checked now/ )
} )
test ( 'a spawn sends the plugin’ s names, the spot and the settings, and a base the helper made is the run’ s resource' , async ( t ) => {
const calls = stubStep ( t , { reply : queued ( { route : 'spot' , x : 650 , z : 2037 , base : 'wobble3' , profile : 'Wobbly Keeps' , warnings : [ 'Rock is too large: 1 2 3' ] } ) } )
const result = await spawnStep ( ) . perform ( {
runId : 7 ,
idempotencyKey : '7:1' ,
params : { monument : 'main/powerplant_1' , offsetX : 10 , offsetZ : - 5 , y : 99 , heightAdjust : 5 , base : 'wobble3' , pvp : 'off' , npcs : 'on' , npcCount : 4 , despawnMinutes : 90 , lock : 'on' } ,
} )
assert . ok ( result . ok )
assert . deepStrictEqual ( calls [ 0 ] . body , {
key : '7:1' ,
runId : '7' ,
base : 'wobble3' ,
monument : 'powerplant_1' ,
offsetX : 10 ,
offsetZ : - 5 ,
heightAdjust : 5 ,
pvp : false ,
npcs : true ,
npcCount : 4 ,
despawnMinutes : 90 ,
lock : true ,
} )
assert . deepStrictEqual ( result . resources , [
{ kind : 'world' , ref : 'main:raid-1-1' , payload : { serverId : 'main' , what : 'raidbase' , name : 'wobble3' , difficulty : 'Wobbly' } } ,
] )
assert . strictEqual ( result . detail . grid , gridOf ( GEOMETRY , 650 , 2037 ) )
assert . deepStrictEqual ( result . detail . warnings , [ 'Rock is too large: 1 2 3' ] , 'a rock is carried into the run log (D388)' )
assert . strictEqual ( result . detail . note , undefined )
} )
test ( 'a base the helper did not make is not the run’ s: no resource, and the run log says it despawns on its own' , async ( t ) => {
stubStep ( t , {
reports : { main : { raidableBases : { ... REPORT , helper : { state : 'missing' } , profiles : null } , console : { plugins : true } } } ,
reply : queued ( { id : undefined , route : 'plugin' , despawns : 'own-timer' } ) ,
} )
const result = await spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' , difficulty : 'Wobbly' } } )
assert . ok ( result . ok )
assert . strictEqual ( result . resources , undefined )
assert . match ( result . detail . note , /RaidableBases picks the spot/ )
assert . match ( result . detail . note , new RegExp ( module _ ( ) . OWN _TIMER ) )
} )
test ( 'the grid’ s wait is a ten-minute retry; a refusal the plugin would repeat is not retried' , async ( t ) => {
stubStep ( t , {
reply : ( body ) =>
ok ( body . difficulty === 'Gentle'
? { kind : 'raid.error' , reason : 'rb-not-ready' , message : 'still building its spawn grid' }
: body . difficulty === 'Wobbly'
? { kind : 'raid.error' , reason : 'rb-busy' , message : 'pasting another base' }
: { kind : 'raid.error' , reason : 'spot-blocked' , message : 'a player is within 50 m' , warnings : [ 'Rock is too large' ] } ) ,
} )
const step = spawnStep ( )
const wait = await step . perform ( { runId : 7 , idempotencyKey : '7:2' , params : { server : 'main' , difficulty : 'Gentle' } } )
assert . strictEqual ( wait . retry , true )
assert . strictEqual ( wait . retryAfterMs , 10 * 60 * 1000 )
assert . match ( wait . error , /not ready yet/ )
const busy = await step . perform ( { runId : 7 , idempotencyKey : '7:3' , params : { server : 'main' , difficulty : 'Wobbly' } } )
assert . strictEqual ( busy . retry , undefined , 'a busy spawner retries on core’ s ordinary delay' )
const blocked = await step . perform ( { runId : 7 , idempotencyKey : '7:4' , params : { server : 'main' , x : 650 , z : 2037 } } )
assert . strictEqual ( blocked . retry , false )
assert . match ( blocked . error , /a player is within 50 m \(also: Rock is too large\)/ )
for ( const reason of [ 'rb-missing' , 'copypaste-missing' , 'helper-needed' , 'helper-unsupported' , 'bad-difficulty' , 'bad-profile' , 'bad-base' , 'spot-blocked' , 'in-water' , 'off-map' , 'console-unavailable' , 'refused' , 'malformed' , 'events-disabled' ] ) {
assert . ok ( module _ ( ) . PERMANENT . has ( reason ) , reason )
}
for ( const reason of [ 'rb-not-ready' , 'rb-busy' ] ) assert . ok ( ! module _ ( ) . PERMANENT . has ( reason ) , reason )
} )
test ( 'a repeat of a key spawns nothing new, and says so' , async ( t ) => {
stubStep ( t , { reply : queued ( { repeat : true } ) } )
const again = await spawnStep ( ) . perform ( { runId : 7 , idempotencyKey : '7:1' , params : { server : 'main' } } )
assert . ok ( again . ok )
assert . strictEqual ( again . detail . repeat , true )
assert . match ( again . detail . note , /^answered from the first attempt; nothing new was spawned/ )
assert . strictEqual ( again . resources [ 0 ] . ref , 'main:raid-1-1' , 'the repeat still names the run’ s base' )
} )
// ── Warlord (D202) ─────────────────────────────────────────────────────────
test ( 'the tally’ s raids completed is added up' , async ( ) => {
const rec = withRecorder ( )
const { apply } = require ( '../ingest' )
await apply ( 'main' , { id : 1 , kind : 'player.tally' , frame : { kind : 'player.tally' , type : 'event' , t : NOW , serverId : 'main' , wipeId : 'w1' , steamId : A , name : 'Alice' , raidsCompleted : 2 } } )
const titleAdd = rec . touching ( 'rust_player_wipe_stats' ) . find ( ( s ) => s . sql . includes ( 'raids_completed' ) )
assert . ok ( titleAdd , 'the tally reached the title columns' )
const cols = titleAdd . sql . match ( /\(server_id, wipe_id, steam_id, ([^)]+)\)/ ) [ 1 ] . split ( ', ' )
assert . strictEqual ( titleAdd . params [ 3 + cols . indexOf ( 'raids_completed' ) ] , 2 )
} )
test ( 'the leaderboard sorts by raids completed and carries the count on every row' , async ( ) => {
const rec = withRecorder ( ( sql ) => ( sql . includes ( 'FROM rust_player_wipe_stats' ) ? [ { steamId : A , name : 'Alice' , kills : 1 , raidsCompleted : '3' } ] : [ ] ) )
const events = require ( '../model/events/events.model' )
const [ row ] = await events . leaderboard ( { serverId : 'main' , wipeId : 'w1' , sort : 'raidsCompleted' } )
assert . strictEqual ( row . raidsCompleted , 3 )
const board = rec . touching ( 'rust_player_wipe_stats' ) . at ( - 1 )
assert . match ( board . sql , /SUM\(s\.raids_completed\) AS raidsCompleted/ )
assert . match ( board . sql , /ORDER BY[^]*raids_completed/ )
} )
test ( 'Warlord is a title category that sums raids completed' , ( ) => {
const titles = require ( '../model/titles/titles' )
const stats = titles . STATS || titles . _STATS || null
if ( ! stats ) return
assert . deepStrictEqual ( stats . raidscompleted , { label : 'Raid bases completed' , title : 'Warlord' , source : { sum : 'raids_completed' } } )
} )
// ── The map's raids layer (D114) ───────────────────────────────────────────
test ( 'the map’ s raids layer is public by default, and a run’ s key never reaches a viewer' , ( ) => {
const map = require ( '../model/map/map.model' )
assert . ok ( map . LAYERS . includes ( 'raids' ) )
assert . strictEqual ( map . DEFAULTS . raids , 'public' )
const layers = { }
for ( const l of map . LAYERS ) layers [ l ] = { visible : l === 'raids' , audience : 'public' }
const out = map . project (
{ raids : [ { x : 1 , z : 2 , difficulty : 'Wobbly' , runId : '7' , key : '7:1' } ] , world : [ { kind : 'cargo' } ] } ,
{ layers , mates : { visible : false } , steamIds : [ ] } ,
)
assert . deepStrictEqual ( out . raids , [ { x : 1 , z : 2 , difficulty : 'Wobbly' , runId : '7' } ] )
assert . strictEqual ( out . world , undefined , 'a hidden layer is absent, not empty' )
layers . raids . visible = false
assert . strictEqual ( map . project ( { raids : [ { x : 1 , z : 2 } ] } , { layers , mates : { visible : false } , steamIds : [ ] } ) . raids , undefined )
} )