feat: raise OnTeamChanged for AppTeamChanged broadcasts - #107
Conversation
The AppBroadcast.team_changed variant (proto field 4) was defined and code-generated but never handled in ParseNotification, so every team snapshot change fell through to LogUnknownBroadcast and was silently dropped. Wire up the full slice, mirroring the existing ClanChanged pattern: - TeamChangedEventArg (PlayerId + TeamInfo) - AppTeamChanged.ToTeamChangedEvent() mapper (reuses ToTeamInfo) - OnTeamChanged event on RustPlus and IRustPlus - dispatch branch in ParseNotification Also documents the event in the client reference table and subscribes the console sample's LiveEvents to it. Adds unit tests covering the mapper and both dispatch branches (subscriber + no-subscriber). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds first-class support for the AppBroadcast.team_changed (AppTeamChanged) broadcast in the core RustPlusApi client, exposing it as a new OnTeamChanged event with model mapping and unit test coverage (plus sample + docs updates).
Changes:
- Introduced
TeamChangedEventArg,AppTeamChanged.ToTeamChangedEvent(), and a newRustPlus.OnTeamChangeddispatch branch inParseNotification. - Extended the public
IRustPluscontract withOnTeamChanged, and updated docs + console sample to surface the new event. - Added unit tests covering both mapper correctness and subscriber/no-subscriber dispatch behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/RustPlusApi.UnitTests/TeamInfoMapperTests.cs | Adds mapper test for AppTeamChanged → TeamChangedEventArg. |
| tests/RustPlusApi.UnitTests/RustPlusParseNotificationTests.cs | Adds notification-dispatch tests for the new TeamChanged branch. |
| src/RustPlusApi/RustPlus.cs | Adds OnTeamChanged event and dispatch branch in ParseNotification. |
| src/RustPlusApi/Interfaces/IRustPlus.cs | Exposes OnTeamChanged on the public interface contract. |
| src/RustPlusApi/Extensions/AppTeamInfoToModel.cs | Adds ToTeamChangedEvent() mapping extension. |
| src/RustPlusApi/Data/Events/TeamChangedEventArg.cs | Introduces new event-arg type for team snapshot changes. |
| samples/RustPlus.ConsoleApp/Features/LiveEvents.cs | Subscribes to and displays OnTeamChanged in the sample console app. |
| docs/articles/rustplus-client.md | Documents the new public event in the events table. |
| /// <summary>Raised when the team snapshot changes.</summary> | ||
| event EventHandler<TeamChangedEventArg>? OnTeamChanged; | ||
|
|
There was a problem hiding this comment.
Correct that adding an interface member is source-breaking for external implementers, but this follows the established convention of the library: all seven existing broadcast events (OnEntityChanged, OnSmartDeviceTriggered, OnStorageMonitorTriggered, OnTeamChatReceived, OnClanChatReceived, OnClanChanged, OnCameraRaysReceived) are declared directly on IRustPlus — OnEntityChanged was added the same way in #95. IRustPlus is the single canonical contract here; introducing a separate IRustPlusTeamChangedEvents would fragment it and break that consistency for no real gain while the package is still in beta. Keeping it on IRustPlus intentionally.
| @@ -0,0 +1,11 @@ | |||
| namespace RustPlusApi.Data.Events; | |||
There was a problem hiding this comment.
This is a false positive — the code compiles as-is (clean build + all unit tests pass). TeamInfo lives in RustPlusApi.Data, and this file's namespace is RustPlusApi.Data.Events, a child namespace, so the parent RustPlusApi.Data is already in scope for name resolution. ClanChangedEventArg needs its explicit using RustPlusApi.Data.Clans only because ClanInfo sits in a sibling namespace, not an ancestor. Adding using RustPlusApi.Data; here would be a redundant using directive that the ReSharper cleanup profile strips. No change needed.
Problem
The
AppBroadcast.team_changedvariant (proto field 4,AppTeamChanged) was defined and code-generated, butRustPlus.ParseNotificationhad no branch for it — so every team-snapshot change broadcast fell straight through toLogger.LogUnknownBroadcast(broadcast)and was silently dropped. Unlike the five sibling broadcasts (EntityChanged,TeamMessage,ClanMessage,ClanChanged,CameraRays), the entire vertical slice was missing.Fix
Mirrors the existing
ClanChangedpattern end-to-end:TeamChangedEventArgrecord —PlayerId(ulong) +TeamInfo?AppTeamChanged.ToTeamChangedEvent()(reuses existingToTeamInfo())OnTeamChangedevent + dispatch branch inParseNotificationOnTeamChangeddeclared onIRustPlusrustplus-client.mdLiveEventsconsole feature now subscribes toOnTeamChangedTests
TeamInfoMapperTests.ToTeamChangedEvent_MapsPlayerIdAndTeamInfoRustPlusParseNotificationTests.TeamChanged_WithSubscriber_InvokesHandlerRustPlusParseNotificationTests.TeamChanged_NoSubscriber_DoesNotThrowBoth dispatch branches (subscriber / no-subscriber) and the mapper are covered.
Verification
dotnet build RustPlusApi.sln— clean (TreatWarningsAsErrors)#ifforks.🤖 Generated with Claude Code