feat(rust): Dynamic PVP's zones on the feed and the map (PLAN_REDESIGNS §14.3.3)
All checks were successful
PR Checks / client-build (pull_request) Successful in 25s
PR Checks / server-tests (pull_request) Successful in 31s
PR Checks / frozen-manifest (pull_request) Successful in 44s

Stage 4 of the §14.3 integration plan, on protocol 14 (docs
rust-link/PROTOCOL.md §20.7).

- pvp.zone.created is a public kind, pvp.zone.deleted a staff kind. Each row
  is read per viewer by the new dynamicPvp.js: grid for everyone, the event's
  name only for Dynamic PVP's own vanilla events, position and zone id for
  staff only.
- The feed's world filter carries the opening: "A PvP zone opened around the
  downed patrol helicopter · G7 · for 10 min". It names nobody.
- The map gains a fifth layer, `pvp` (PvP zones), public by default with its
  own audience in Admin → Rust visibility, drawn as a red ring with its
  event's name.
- Server settings' plugin line names Dynamic PVP; the swagger schemas and
  route descriptions carry the layer and the integration (fragment
  regenerated); ci/bundle.json ships dynamicPvp.js; README lists it.

Tests: server 611/611 (dynamicPvp.test.js new, catalogue and map extended)
and every check; client 89/89 (feed and map tooltip), build and externals.

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-15 06:12:06 -05:00
parent b5f7fa0f13
commit 549b3a5ffd
20 changed files with 569 additions and 30 deletions

View File

@@ -265,6 +265,11 @@ module.exports = {
description: 'Protocol 14 (PLAN_REDESIGNS §14.3.2): where loaded, a zone step may turn off PvP protection or name a TruePVE ruleset.',
properties: { loaded: { type: 'boolean', example: true }, version: { type: 'string', example: '2.4.6' } },
},
dynamicPvp: {
type: 'object',
description: 'Protocol 14 (PLAN_REDESIGNS §14.3.3): where loaded, its PvP zones reach the feed and the map’s pvp layer.',
properties: { loaded: { type: 'boolean', example: true }, version: { type: 'string', example: '5.2.0' } },
},
},
},
},
@@ -771,7 +776,7 @@ module.exports = {
type: 'object',
description: 'The live map’s switches and each server’s picture (phase 14).',
properties: {
layers: { type: 'array', items: { type: 'string' }, example: ['world', 'events', 'players', 'bases'] },
layers: { type: 'array', items: { type: 'string' }, example: ['world', 'events', 'players', 'bases', 'pvp'] },
minorLabels: {
type: 'array',
items: { type: 'string' },
@@ -785,6 +790,7 @@ module.exports = {
events: { $ref: '#/components/schemas/RustAudience' },
players: { $ref: '#/components/schemas/RustAudience' },
bases: { $ref: '#/components/schemas/RustAudience' },
pvp: { $ref: '#/components/schemas/RustAudience' },
mates: { type: 'boolean', example: true },
markers: { type: 'object', description: 'D196: a monument label key (lower case) to true (drawn) or false (hidden). Only the labels somebody switched; every other label follows the default.', additionalProperties: { type: 'boolean' }, example: { substation: true } },
},
@@ -922,6 +928,7 @@ module.exports = {
events: { $ref: '#/components/schemas/RustMapLayer' },
players: { $ref: '#/components/schemas/RustMapLayer' },
bases: { $ref: '#/components/schemas/RustMapLayer' },
pvp: { $ref: '#/components/schemas/RustMapLayer' },
},
},
mates: {
@@ -1004,6 +1011,21 @@ module.exports = {
},
},
basesTruncated: { type: 'boolean', description: 'More than the plugin’s MapMaxBases.' },
pvp: {
type: 'array',
description: 'Protocol 14 (§14.3.3): Dynamic PVP’s own PvP zones, where each is now (cargo’s moves with the ship). A cube zone’s radius is half its longer side.',
items: {
type: 'object',
properties: {
zoneId: { type: 'string', example: '1412203045' },
event: { type: 'string', description: 'Dynamic PVP’s event name: one of its own (Helicopter, Bradley, CargoShip …), a monument’s, or an operator’s.', example: 'Helicopter' },
radius: { type: 'number', example: 100 },
shape: { type: 'string', enum: ['sphere', 'cube'], example: 'sphere' },
x: { type: 'number' },
z: { type: 'number' },
},
},
},
mates: {
type: 'array',
description: 'The viewer’s own positions (their sleeper too) and their online first-party clan mates on this server.',