fix(rust): send reward notices, and keep a downed line's credit rule (W21, W4)
All checks were successful
PR Checks / client-build (pull_request) Successful in 21s
PR Checks / frozen-manifest (pull_request) Successful in 48s
PR Checks / server-tests (pull_request) Successful in 7m16s

W21: the permission push named its fields one by one and left out
`notices`, so no kit reward, lend or give ever told its player
anything (D333). The body is now built by `pushBody`, which carries
every field the payload has; a test fails if a payload field is
dropped again.

W4: a downed patrol helicopter, Chinook or Bradley is stored with the
credit rule in force when it arrived, and the feed reads that stamp.
Before, the line re-credited past rows with the server's current rule
while the Rotorbane/Tankbreaker counts kept the old one. Rows stored
before this change keep today's reading.

PLAN_LAST_FIXES.md stage 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-21 06:16:32 -05:00
parent 5decd5cc05
commit 8aff9b33a6
7 changed files with 92 additions and 15 deletions

View File

@@ -178,7 +178,8 @@ function columnName(index) {
* `staff` the viewer is an admin or a moderator: Steam ids, and a type this
* build does not know
* `presence` the viewer is in the server's presence audience: names
* `rule` the server's credit rule
* `rule` the server's credit rule, for a row stored before the frame
* carried its own (`stampRule`)
* `geometry` the server's map geometry, for the grid
*
* What comes back keeps the plugin's own fields for what it describes (`event`,
@@ -215,8 +216,8 @@ function shapeFor(frame, { staff = false, presence = false, rule = DEFAULT_CREDI
// Credit, by the server's rule.
if (known && TYPES[event].credit) {
out.creditRule = creditRuleOf(rule)
const ids = credited(frame, rule)
out.creditRule = ruleOf(frame, rule)
const ids = credited(frame, out.creditRule)
out.creditedCount = ids.length
if (presence || staff) {
out.credited = ids.map((id) => ({
@@ -235,6 +236,25 @@ function shapeFor(frame, { staff = false, presence = false, rule = DEFAULT_CREDI
return out
}
/**
* The frame as it is stored: a downed helicopter, Chinook or Bradley carries
* the rule that credited it when it arrived (`creditRule`), so the feed line
* keeps naming who the counts were given to after the server's rule changes
* (W4). Every other frame is stored as sent.
*/
function stampRule(frame, rule) {
if (!frame || frame.kind !== 'world.event' || !isKnownType(frame.event) || !TYPES[frame.event].credit) return frame
return { ...frame, creditRule: creditRuleOf(rule) }
}
/**
* The rule a stored line is read by: its own stamp, or — for a row from before
* the stamp — the server's rule now, which is how those rows always read.
*/
function ruleOf(frame, rule) {
return frame && CREDIT_RULE_IDS.includes(frame.creditRule) ? frame.creditRule : creditRuleOf(rule)
}
/**
* What one `world.event` adds to the counts: a credited kill of a helicopter,
* a Chinook or a Bradley, for each player the server's rule names. `[{ steamId,
@@ -270,6 +290,8 @@ module.exports = {
creditRuleOf,
isKnownType,
credited,
stampRule,
ruleOf,
nameOf,
gridOf,
shapeFor,