The walk found that a hot reload of this plugin emptied every title, and
the site never re-sent them: it re-sends on a new boot id or wipe id, and a
reload is neither, because the boot id names the server process. The set
is now written to titles.json with the wipe it was pushed on, and read at
OnServerInitialized only when that wipe is still the current one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
- titles.set: a whole set of chat titles, swapped in by reference and read
by a BetterChat third-party title getter (one lookup, no socket). The
getter is registered at load and again whenever BetterChat loads.
- perm.sync: a group may carry its BetterChat style. Each field is written
through API_SetGroupField only when the game still holds what the site
last pushed (or BetterChat's default); anything else is reported as
drift. One `chat group set` per touched group saves it, because the API
never does (D143). A retired style removes the group with `chat group
remove` (D139). The report gains `chat`.
- chat.say: delivery chat|popup and an optional voice format. A popup with
PopupNotifications absent is refused `popup-unavailable`. Every line said
is logged, since the game logs neither a broadcast nor a popup.
- server.hello/status carry `integrations`; `rg.titles [steamId]` prints
what BetterChat would render for a player.
- overlay.toml: protocol 12; PopupNotifications leaves requires_plugins
(D141).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY