Subsystem 4c: Smart Storage Monitors (#storagemonitors channel, pair/validate, live contents embed + Refresh/Rename)#27
Merged
Conversation
…iredEvent Add StorageMonitor switch arm in PairingHandler.HandleEntityAsync and OnStorageMonitorPairing subscription in RustPlusFcmPairingSource, mirroring the SmartAlarm pattern. Includes TDD test (30 total, +1). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…upport Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n, and tests (Task 6) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add StorageMonitorEmbedRenderer (pure), StorageMonitorComponentIds, and StorageMonitorRenameModal; add 19 EN/FR localization keys (storage.* + channel.storagemonitors.name); bump parity test key count to 212. Uses inline FormatRemaining helper — no Features.Commands reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add ServerStorageMonitors channel key (order 6), ChannelSpec (Interactive/PerServer), IStorageMonitorChannelLocator interface, StorageMonitorChannelLocator (CachingChannelLocator), DI registration, and full xUnit test coverage (spec-provider + locator cache tests). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add IStorageMonitorChannelPoster, DiscordStorageMonitorChannelPoster (untested integration shim delegating to DiscordChannelMessenger), and StorageMonitorPairingCoordinator (mirrors SwitchPairingCoordinator: posts an "Add it?" prompt on paired event, persists via IStorageMonitorStore.AddAsync on accept with contents:null render, race-guarded TryAccept/TryDismiss). Five new tests cover: prompt posted for new monitor, already-managed ignored, accept persists and returns true, accept on race returns false, dismiss without pending returns false. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rageContentsAsync - Subscribe StorageMonitorTriggered in the connected window and fire-and-forget PublishStorageTriggerAsync - Add PrimeDevicesAsync third arm: list IStorageMonitorStore, call PublishStoragePrimeAsync per entity (null → skip) - Add IRustServerQuery.GetStorageContentsAsync; implement on ConnectionSupervisor via GetStorageMonitorInfoAsync - Add IStorageMonitorStore + IAlarmStore registrations to AlarmPrimingTests and SwitchQueryTests harnesses - Add FakeRustSocketSource.EnqueueStorageInfo for race-free priming test setup - Add StorageMonitorPrimingTests: priming event, no-socket null, query-path, trigger relay (69 total, +4) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion status unreachable) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add StorageMonitorsHostedService (3 bus loops: paired, triggered, connection-status), AddStorageMonitors() DI extension, IStorageMonitorStore Persistence registration, Program.cs + Host csproj wiring, and registration test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ToFrozenDictionary throws on a duplicate key; two distinct string keys in items.json can parse to the same int (NumberStyles.Integer allows a leading sign/whitespace). In the static initializer that would surface as a TypeInitializationException and hard-fault the feature on first use. Group by the parsed id (last wins) so a future regenerated/hand-edited items.json degrades instead of crashing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third smart-device slice after 4a Smart Switches (#18) and 4b Smart Alarms (#23). Adds in-game Smart Storage Monitors: pair-in-game via FCM → a user-validated "Add it?" prompt in a per-server
#storagemonitorschannel → a per-monitor live contents embed (item names + quantities, Tool-Cupboard decay-protection status, slot count) with Refresh and Rename. Contents are primed on (re)connect and updated live on the socket'sOnStorageMonitorTriggeredbroadcast.Architecture
Mirrors the 4a Switches template. The one difference is the data shape — a storage monitor carries contents (
StorageContentsSnapshot: capacity, decay-protection, item list), not a boolean on/off. Approach A: a storage-specific read seam (GetStorageMonitorInfoAsync) + bus event (StorageMonitorTriggeredEvent) sit beside the existing boolean device plumbing rather than overloadingSmartDeviceTriggeredEvent. Storage monitors have no control surface (read-only), so the only interactions are Refresh, Rename, and the pairing Accept/Dismiss.RustPlusBot.Features.StorageMonitorsproject (renderer / coordinator / poster / relay / component module / hosted service / item-name resolver).OnStorageMonitorPairing→PairingHandlerthird arm →StorageMonitorPairedEvent.ConnectionSupervisorsubscribes the socket trigger + primes persisted monitors on connect;IRustServerQuery.GetStorageContentsAsyncbacks Refresh.SmartStorageMonitorentity +StorageMonitorStore+SmartStorageMonitorsmigration (FK→RustServer cascade). Contents are live-only, never persisted.#storagemonitorschannel spec + locator; shared.resxkeys (EN/FR).items.json(id→name, names only) for human-readable contents — recycle/upkeep-cost calc + alerting deferred to subsystem 6.Verification
-warnaserror; jbReformatAndReorderidempotent-clean.SmartStorageMonitorsmigration.RustPlusSocketSourcestorage methods +DiscordStorageMonitorChannelPoster.🤖 Generated with Claude Code