feat(rust): Rust's own world events — feed, credit rule, triggers, Call a world event (PLAN_REDESIGNS §14.3.1)
The site half of stage 1, on protocol 14: - server/worldEvents.js: the 24 types, D372's four credit rules, the grid from the map's geometry (none off the map), and the per-viewer reading. - The feed serves `world.event` (a public kind): an unknown type is staff's; the event and its grid are public; names only for the presence audience (D376); Steam ids and positions only for staff (D353). A downed one carries `credited`/`creditedCount` by the server's rule. Client lines for all 24 types and a World events filter. - rust_servers.credit_rule (blow, last, most, all; default blow), set on the server's settings. Ingest counts heli_kills (patrol helicopters and Chinooks, D379) and apc_kills from `world.event` by that rule, so the line and Rotorbane / Tankbreaker agree. A protocol-13 tally's heliKills/apcKills still add as before. - The tally's cratesHacked / dropsLooted → crates_hacked / drops_looted; title categories Safecracker and Scavenger (D356); leaderboard columns Crates hacked and Drops looted, sortable (D377). - 24 engagement triggers rust.world.<event> (D355): ceiling everyone, cooldown subject the server and event (crates add where), names only. - server/eventWorldCall.js: rust.world.call, "Call a world event" (risk change, reversible none, budget rust.world.calls). A position for an airdrop or a patrol helicopter only; the Chinook takes none (D378). Server 585/585 (22 new in test/worldEvents.test.js), client 84/84, every check; booted against the pinned core (43 triggers, 12 actions, 10 budgets, 20 option sources), routes.manifest unchanged at 89. Engagement manifest and swagger fragment regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -113,6 +113,11 @@ async function putServer(req, res) {
|
||||
})
|
||||
if (schedule) await db.setSchedule(id, schedule)
|
||||
|
||||
// D372: written only when the save carries one, like the schedule. The router
|
||||
// has already refused a word this build does not know.
|
||||
const creditRule = req.body.creditRule === undefined ? null : req.body.creditRule
|
||||
if (creditRule) await db.setCreditRule(id, creditRule)
|
||||
|
||||
await core.activity.log({
|
||||
req,
|
||||
action: 'rust.server.save',
|
||||
@@ -125,6 +130,8 @@ async function putServer(req, res) {
|
||||
// The schedule as written, when the save carried one. Nothing in it is a
|
||||
// secret, and "who moved the wipe" is a question players will ask.
|
||||
...(schedule ? { schedule: { ...schedule, wipeOnceAt: schedule.wipeOnceAt ? schedule.wipeOnceAt.toISOString() : null } } : {}),
|
||||
// The credit rule as written, when the save carried one (D372).
|
||||
...(creditRule ? { creditRule } : {}),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const core = require('../../core')
|
||||
|
||||
const express = core.express
|
||||
const admin = require('./rust.controller')
|
||||
const worldEvents = require('../../worldEvents')
|
||||
const { requireRole, validate } = core.middleware
|
||||
const { body, param } = core.validator
|
||||
|
||||
@@ -63,7 +64,7 @@ adminRustRouter.put(
|
||||
'/servers/:id',
|
||||
// #swagger.tags = ['Admin · Rust']
|
||||
// #swagger.summary = 'Create or update a Rust server'
|
||||
// #swagger.description = 'Writes one server row. `sidecarToken` is write-only — send it to set or rotate the credential, and omit it or send an empty string to leave the stored one untouched. The id is the slug every URL under the module carries. The wipe schedule (`wipeRule`, `wipeDay`, `wipeTime`, `wipeTz`, `wipeAnchor`, `wipeOnceAt`) is written only when `wipeRule` is present, so a body without it leaves the stored schedule alone. `wipeRule` is `none`, `forced`, `weekly` or `biweekly`; a weekly or biweekly rule needs `wipeDay` (0 = Sunday), `wipeTime` (`HH:MM`) and an IANA `wipeTz`, and a biweekly rule a `wipeAnchor` date on that day. `wipeOnceAt` is a one-off wipe in the future. A 400 carries one sentence per problem in `errors`.'
|
||||
// #swagger.description = 'Writes one server row. `sidecarToken` is write-only — send it to set or rotate the credential, and omit it or send an empty string to leave the stored one untouched. The id is the slug every URL under the module carries. The wipe schedule (`wipeRule`, `wipeDay`, `wipeTime`, `wipeTz`, `wipeAnchor`, `wipeOnceAt`) is written only when `wipeRule` is present, so a body without it leaves the stored schedule alone. `wipeRule` is `none`, `forced`, `weekly` or `biweekly`; a weekly or biweekly rule needs `wipeDay` (0 = Sunday), `wipeTime` (`HH:MM`) and an IANA `wipeTz`, and a biweekly rule a `wipeAnchor` date on that day. `wipeOnceAt` is a one-off wipe in the future. `creditRule` (protocol 14, D372) is who a downed patrol helicopter, Chinook or Bradley credits, for the feed line and for the Rotorbane and Tankbreaker counts alike: `blow` (the killing blow, the default; for the patrol helicopter the crippling hit, else the last hit), `last`, `most` (the most damage) or `all` (everyone who hurt it, one each). It is written only when present, and applies from then on. A 400 carries one sentence per problem in `errors`.'
|
||||
/* #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/RustServerSave" } } } } */
|
||||
/* #swagger.responses[204] = { description: 'Saved' } */
|
||||
/* #swagger.responses[400] = { description: 'Invalid body' } */
|
||||
@@ -91,6 +92,8 @@ adminRustRouter.put(
|
||||
body('wipeTz').optional({ values: 'null' }).isString().isLength({ max: 64 }),
|
||||
body('wipeAnchor').optional({ values: 'falsy' }).isISO8601({ strict: true }).isLength({ max: 10 }),
|
||||
body('wipeOnceAt').optional({ values: 'falsy' }).isISO8601({ strict: true }),
|
||||
// Protocol 14 (D372): who a downed helicopter, Chinook or Bradley credits.
|
||||
body('creditRule').optional().isIn(worldEvents.CREDIT_RULE_IDS),
|
||||
validate,
|
||||
admin.putServer,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user