Subsystem 2b-ii: per-server map layer toggles + monuments/vendor/players/rig-styling layers (icon render) - #16
Merged
Merged
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the missing MapIcons.Rig(RigKind, bool active) API-contract method (Task 3 "Produces" list); adds Rig_resolves_for_known_kinds Theory test covering both RigKind.Small and RigKind.Large. Suppresses RCS1163 on the reserved `active` parameter with a narrow pragma + explaining remarks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bucket
- Added MarkerKind.TravellingVendor = 5 to the enum (with XML doc)
- Wired data.TravellingVendorMarkers into GetMapMarkersAsync via AddMarkers
- Activated the deferred MapIcons.Marker TravellingVendor arm (Load("vendor"))
that was stubbed out pending the enum member; vendor.png already embedded
Adds GetMonumentsAsync(ulong guildId, Guid serverId, CancellationToken) to IRustServerQuery; ConnectionSupervisor implements it by delegating to the live socket's internal GetMonumentsAsync or returning [] when no socket is registered. Includes supervisor test asserting empty result when no live socket exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-adds the Renders_the_grid_even_with_no_markers test dropped during Task 7's MapComposer rewrite. Uses two MapComposer instances (grid-on vs grid-off, zero markers) and asserts their output PNGs differ, proving the grid still renders on low-activity / just-connected servers. Also fixes player label: alive+offline now shows (offline) instead of (dead); only dead players show (dead). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cosmetic line-wrapping applied by JetBrains CleanupCode 2026.1.2 with the ReformatAndReorder profile. All 5 touched files are 2b-ii branch files; no pre-existing drift in unrelated files. Files reformatted: - src/RustPlusBot.Features.Map/Composing/MapComposer.cs - src/RustPlusBot.Persistence/Map/MapSettingsStore.cs - tests/RustPlusBot.Features.Map.Tests/MapRendererTests.cs - tests/RustPlusBot.Persistence.Tests/Map/MapSettingsStoreTests.cs - tests/RustPlusBot.Persistence.Tests/Map/ServerMapSettingsSchemaTests.cs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er id Validate the parsed serverId exists in this guild before any persistence. Resolves the FK-violation/hung-ack edge case noted in the final review. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR completes the “Subsystem 2b-ii” map slice by adding per-server persisted layer toggles, a persistent ManageGuild map-control UI in #map, and switching the renderer from drawn glyphs to embedded icon assets while expanding the rendered layers (monuments, travelling vendor, players, rig activation styling).
Changes:
- Add
ServerMapSettingspersistence (entity + EF migration) and an EF-backedIMapSettingsStorewith “all layers on” defaults when no row exists. - Add
#mapcontrol message rendering + interaction handling to toggle layers per server and trigger immediate repaints viaMapSettingsChangedEvent. - Expand the map render pipeline to support new layers and vendored icons (plus travelling vendor marker kind).
Reviewed changes
Copilot reviewed 42 out of 83 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/RustPlusBot.Persistence.Tests/Map/ServerMapSettingsSchemaTests.cs | Verifies ServerMapSettings defaults and cascade delete behavior. |
| tests/RustPlusBot.Persistence.Tests/Map/MapSettingsStoreTests.cs | Tests IMapSettingsStore default/all-on behavior and per-layer updates. |
| tests/RustPlusBot.Features.Workspace.Tests/Messages/MapControlMessageRendererTests.cs | Tests #map control message header + button rendering and FR label. |
| tests/RustPlusBot.Features.Map.Tests/MarkerGlyphsTests.cs | Removes glyph-based marker tests (glyph rendering replaced by icons). |
| tests/RustPlusBot.Features.Map.Tests/MapRendererTests.cs | Updates renderer tests for new layer inputs and adds all-layers render coverage. |
| tests/RustPlusBot.Features.Map.Tests/MapRegistrationTests.cs | Updates DI registration test for new map dependencies (rig state + settings store). |
| tests/RustPlusBot.Features.Map.Tests/MapLayerSetTests.cs | Updates layer-set defaults to “all on” semantics. |
| tests/RustPlusBot.Features.Map.Tests/MapIconsTests.cs | Adds tests for icon resolution/mapping behavior (markers/monuments/rigs/player). |
| tests/RustPlusBot.Features.Map.Tests/MapComposerTests.cs | Expands composer tests for settings-driven gathering and new layer seams. |
| tests/RustPlusBot.Features.Connections.Tests/ServerQueryTests.cs | Adds coverage for monuments query behavior without a live socket. |
| src/RustPlusBot.Persistence/PersistenceServiceCollectionExtensions.cs | Registers IMapSettingsStore in persistence DI. |
| src/RustPlusBot.Persistence/Migrations/BotDbContextModelSnapshot.cs | Updates EF snapshot to include ServerMapSettings. |
| src/RustPlusBot.Persistence/Migrations/20260618164017_MapSettings.Designer.cs | Adds migration designer for ServerMapSettings. |
| src/RustPlusBot.Persistence/Migrations/20260618164017_MapSettings.cs | Adds migration creating ServerMapSettings table. |
| src/RustPlusBot.Persistence/Map/MapSettingsStore.cs | Implements EF-backed settings store with all-on defaults. |
| src/RustPlusBot.Persistence/Map/MapLayer.cs | Defines MapLayer enum + MapLayerSettings value object. |
| src/RustPlusBot.Persistence/Map/IMapSettingsStore.cs | Introduces settings store interface. |
| src/RustPlusBot.Persistence/Configurations/ServerMapSettingsConfiguration.cs | EF configuration for ServerMapSettings PK + cascade FK. |
| src/RustPlusBot.Persistence/BotDbContext.cs | Adds DbSet<ServerMapSettings> and applies configuration. |
| src/RustPlusBot.Features.Workspace/WorkspaceServiceCollectionExtensions.cs | Registers MapControlMessageRenderer for reconciler rendering. |
| src/RustPlusBot.Features.Workspace/WorkspaceKeys.cs | Adds WorkspaceMessageKeys.ServerMap. |
| src/RustPlusBot.Features.Workspace/WorkspaceComponentIds.cs | Adds MapTogglePrefix component ID prefix. |
| src/RustPlusBot.Features.Workspace/Specs/ServerWorkspaceSpecProvider.cs | Adds per-server map-control message spec in #map. |
| src/RustPlusBot.Features.Workspace/Modules/MapComponentModule.cs | Handles map layer toggle button interactions + triggers repaint event. |
| src/RustPlusBot.Features.Workspace/Messages/MapControlMessageRenderer.cs | Renders the persistent #map control message with six toggle buttons. |
| src/RustPlusBot.Features.Workspace/Localization/LocalizationCatalog.cs | Adds EN/FR strings for map control header and button labels. |
| src/RustPlusBot.Features.Map/RustPlusBot.Features.Map.csproj | Embeds PNG icon resources for map rendering. |
| src/RustPlusBot.Features.Map/Rendering/PlayerPlacement.cs | Adds placement records for players/monuments/rigs. |
| src/RustPlusBot.Features.Map/Rendering/MapRenderer.cs | Switches to icon rendering and adds monuments/players/rig layers. |
| src/RustPlusBot.Features.Map/Rendering/MapLayerSet.cs | Extends layer set to include players and sets “all on” default. |
| src/RustPlusBot.Features.Map/Posting/DiscordMapChannelPoster.cs | Preserves the control message by deleting only attachment-bearing prior posts. |
| src/RustPlusBot.Features.Map/Hosting/MapHostedService.cs | Adds settings-changed event loop to trigger immediate map repaints. |
| src/RustPlusBot.Features.Map/Composing/MapComposer.cs | Reads per-server settings via scoped store and gathers new layer data. |
| src/RustPlusBot.Features.Map/Assets/MonumentIconMap.cs | Maps monument tokens to icon keys (unknown tokens skipped). |
| src/RustPlusBot.Features.Map/Assets/MarkerGlyphs.cs | Removes glyph-based marker registry (replaced by icons). |
| src/RustPlusBot.Features.Map/Assets/MapIcons.cs | Loads/caches embedded PNG icons for markers/monuments/rigs/player. |
| src/RustPlusBot.Features.Connections/Supervisor/ConnectionSupervisor.cs | Implements IRustServerQuery.GetMonumentsAsync. |
| src/RustPlusBot.Features.Connections/Listening/RustPlusSocketSource.cs | Surfaces travelling vendor marker bucket from Rust+ map markers API. |
| src/RustPlusBot.Domain/Map/ServerMapSettings.cs | Adds persisted per-server map layer settings entity (defaults on). |
| src/RustPlusBot.Abstractions/Events/MapSettingsChangedEvent.cs | Adds event used to request immediate repaint after toggles. |
| src/RustPlusBot.Abstractions/Connections/MarkerKind.cs | Adds TravellingVendor marker kind. |
| src/RustPlusBot.Abstractions/Connections/IRustServerQuery.cs | Adds GetMonumentsAsync query seam. |
| NOTICE | Updates attribution/notice text for bundled icon assets. |
Files not reviewed (1)
- src/RustPlusBot.Persistence/Migrations/20260618164017_MapSettings.Designer.cs: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Copilot review (PR #16): DrawMonuments (and the sibling marker/rig/player loops) called image.Mutate once per item, building and executing a fresh ImageSharp processing pipeline each time. Refactor all four layers to draw every item inside ONE Mutate per layer, so a server with many monuments pays for one pipeline instead of N. Behaviour-preserving: same icons composited at the same coordinates in the same order; the cached MapIcons sources are still only read (drawn onto the target ctx), never mutated. 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.
Completes subsystem 2's map work, building on 2b (#15). Adds per-server layer settings with a ManageGuild toggle UI in
#map, four new render layers, and replaces 2b's drawn glyphs with bundled icon assets. All layers default on.What's in it
Data & settings
ServerMapSettingsentity (six per-server bool toggles, default on, FK→RustServercascade) +MapSettingsmigrationIMapSettingsStore/MapSettingsStore— returns all-on defaults when no row exists (no backfill needed for existing servers)Render layers (icon-based, replacing 2b's C/H/K glyphs)
MarkerKind.TravellingVendor+ surfaced from the marker shimGetTeamInfoAsync(name + alive/online styling); avatars deferredIRigState(red ring when a rig is Active)player.pngfrom rustplusplus) as embedded resources; attributed inNOTICEas Facepunch/Rust game art (companion-app fair use)Toggle UI
#map(six toggle buttons, EN/FR), reconciler-owned and separate from the delete+reposted image — the poster now deletes only its own attachment-bearing image posts so the control message survivesMapSettingsChangedEvent→MapHostedServicerepaints immediately (throttled)Architecture notes
MapLayerSettingsis Persistence-owned (Persistence does not referenceFeatures.Map); the composer maps it toMapLayerSetMapComposer(singleton) resolves the scoped settings store via a per-call scope — no captive dependencyIRustServerQuery.GetMonumentsAsyncseam (the composer reads monuments per-render; 2a-ii only consumed them transiently for rig detection)Verification
dotnet build -warnaserror: 0/0jb cleanupcode --profile=ReformatAndReorderclean; no EF model driftDeferred (Minor, non-blocking)
waterwell.png/powerstation.pngembedded without a token mapping (harmless)🤖 Generated with Claude Code