Skip to content

Latest commit

 

History

History
91 lines (70 loc) · 4.85 KB

File metadata and controls

91 lines (70 loc) · 4.85 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

A C# library for the Rust+ companion app API, shipped as six NuGet packages from src/. All libraries multi-target netstandard2.0 + net10.0 (usable from .NET Framework 4.6.2+ through .NET 10); Polyfills/ directories and #if NET10_0_OR_GREATER forks bridge the gap. Package versions are managed centrally in Directory.Packages.props. The default branch for PRs is develop.

Commands

dotnet build                    # strict: TreatWarningsAsErrors + latest-all analyzers (Roslynator, Sonar, VSTHRD)
dotnet test RustPlusApi.sln     # runs every test project on BOTH TFM hosts (net8.0 + net10.0)

# Single test class/method (still both TFMs):
dotnet test RustPlusApi.sln --filter "FullyQualifiedName~ClassName.MethodName"

# One TFM only (net8.0 host = exercises the netstandard2.0 build):
dotnet test RustPlusApi.sln -f net8.0
dotnet test RustPlusApi.sln -f net10.0

# Coverage with per-class gap report + CI gate (line 95 / branch 90):
tools/coverage/report.sh

# Formatting + member reordering (ReSharper CLI; whitespace rules from .editorconfig, the
# ReformatAndReorder cleanup profile + member layout live in RustPlusApi.sln.DotSettings):
dotnet tool restore
dotnet jb cleanupcode RustPlusApi.sln --profile="ReformatAndReorder"

# Mutation testing (run from the unit-test project directory):
cd tests/RustPlusApi.Fcm.UnitTests && dotnet stryker --config-file stryker-config.json --project RustPlusApi.Fcm.csproj

# Docs site (DocFX, needs `dotnet tool install --global docfx`):
docfx docs/docfx.json --serve

A committed pre-push hook (.githooks/pre-push, wired up automatically by the first dotnet build) runs the ReSharper formatter and member reordering on outgoing files and rejects the push if it changes anything — format before pushing.

Architecture

Package layering

  • RustPlusApi (core) — WebSocket client for a Rust server's app port. Two layers: RustPlusSocket (abstract: connect/dispose lifecycle, channel-based send loop, receive loop, request/response correlation by seq, raw AppRequest/AppMessage events) and RustPlus on top (typed Response<T> methods like GetInfoAsync, plus broadcast-driven events like OnTeamChatReceived). Data/ holds the public DTOs; Extensions/ holds the protobuf→DTO mappers.
  • RustPlusApi.CameraCameraController (subscribe/keep-alive/input over a RustPlus instance, capability-gated movement) and CameraRenderer (frame → image via ImageSharp).
  • RustPlusApi.Fcm — FCM push listener: RustPlusFcmSocket speaks Google's MCS protocol over TLS to mtalk.google.com:5228; RustPlusFcm decrypts notifications and raises pairing/ alarm events.
  • RustPlusApi.Fcm.Registration — native credential acquisition replacing the rustplus.js CLI: GCM check-in → Firebase/FCM/Expo registration (Steps/), Steam login via Chrome DevTools Protocol (SteamLoginService), Rust Companion registration, CredentialsStore persistence.
  • Two *.Extensions.DependencyInjection packages — AddRustPlus/AddRustPlusFcm + factories.

Protobuf contracts

Core contracts are generated at compile time by protobuf-net.BuildTools from src/RustPlusApi/Protobuf/RustPlusContracts.proto. That proto is authoritative — it is regenerated by decompiling the actual Rust dedicated server via tools/update-proto/update-proto.sh (see its README; the ProtoRefresh.yml workflow runs the diff gate). RustPlusApi.Fcm and .Fcm.Registration instead use hand-written code-first protobuf-net classes (ProtoBuf/Mcs.cs, Protobuf/CheckinContracts.cs).

Test strategy (read docs/development/testing.md before touching tests)

  • Test projects target net8.0;net10.0: the net8.0 host can't load a net10.0 library asset, so it resolves the netstandard2.0 build — the same xUnit suite validates both compiled outputs ("multi-TFM parity"). Behavioral #if forks must be pinned to agree by tests.
  • tests/RustPlusApi.MockServer is an in-process WebSocket server shared by integration tests.
  • Live-network paths (TLS connect, Steam login, MCS handshake) are [ExcludeFromCodeCoverage] with per-member justifications; the pipelines they feed are tested through internal seams (InternalsVisibleTo, e.g. RunReceiveLoopOverStream, *ForTests members). Everything else is expected at 100/100 line/branch — additions to the exclusion list need a justification in docs/development/testing.md.
  • Stryker cannot mutate the core RustPlusApi.csproj (protobuf-net.BuildTools breaks its rollback compiler); core behavior is pinned by exact-assertion unit tests instead.

Versioning

Local builds always produce version 1.0.0; real versions are injected by CD (-p:Version=<tag> on release). Don't bump versions in project files.