Skip to content

#198 Allow players to set color via adding dye on signs - #205

Merged
tpwalke2 merged 6 commits into
mainfrom
feature/tpwalke2/198-dye-colors
Sep 7, 2026
Merged

#198 Allow players to set color via adding dye on signs#205
tpwalke2 merged 6 commits into
mainfrom
feature/tpwalke2/198-dye-colors

Conversation

@tpwalke2

@tpwalke2 tpwalke2 commented Sep 7, 2026

Copy link
Copy Markdown
Owner

What

Lets players set a LINE/SHAPE/EXTRUDE marker's colour by dyeing one of its member signs, instead of only an admin editing lineColor/fillColor in config.

Why

Player-placed trails/regions/buildings currently all render in one admin-chosen colour per group; this gives players a way to customize their own markers' colour in-game without touching config.

Changes

  • New opt-in allowPlayerColors field on marker groups (LINE/SHAPE/EXTRUDE only; default false), wired through MarkerGroup, ConfigProvider (parsing, defaults, type-mismatch warning), and config persistence models.
  • New ColorResolver: among a marker's current members, the earliest-placed member with a non-undyed (non-black) colour wins; only hue comes from the dye, alpha still comes from the group's configured lineColor/fillColor. Re-evaluated on every membership/dye change.
  • ActionFactory's line/shape/extrude action builders now take resolved lineColor/fillColor instead of reading them straight off the MarkerGroup.
  • SignEntry gains persisted front/back dye fields; SignEntryHelper gains dye read/compare helpers (UNDYED_DYE sentinel, getDye).
  • New SignBlockEntityInject mixin hook on SignBlockEntity.updateText (in addition to the existing updateSignText hook) to detect dye/ink-sac/glow-ink-sac applications, which don't go through updateSignText; a reentrancy flag prevents double-dispatch when a plain text edit also passes through updateText internally.
  • New sign-persistence version: SignEntryV5 → V6 via Version6Converter (adds the two dye fields, backfilled to UNDYED_DYE for older entries); SignFileVersions, Version1SignEntryLoader, Version5Converter, VersionedFileSignEntryLoader updated for the new version.
  • ColorUtils.toHex(r,g,b,a) added as the inverse of parseHex.
  • agent-context/ docs and .scratch/ issue files updated/added for this feature; README.md documents the new field and adds allowPlayerColors: true to the LINE/SHAPE/EXTRUDE examples.

Testing

  • ./gradlew test — full unit suite, including new ColorResolverTest and Version6ConverterTest, plus updates to existing tests touched by the new MarkerGroup/SignEntry fields (ConfigProviderTest, ActionFactoryTest, SignEntryTest, SignEntryHelperTest, SignTransitionResolverTest, VersionedFileSignEntryLoaderTest, etc.)
  • Manual: ./gradlew runServer, place LINE/SHAPE/EXTRUDE signs with allowPlayerColors: true, dye a member sign and confirm the marker's colour updates; verify a black dye has no visible effect and falls back to the group's configured colour.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

V5 migration can discard valid entries when one entry is null, and disabled groups still perform unnecessary dye recomputation.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds opt-in, player-controlled colors for multi-point markers using sign dyes.

Changes:

  • Adds allowPlayerColors and dye-based color resolution.
  • Persists front/back dye state through the V6 format.
  • Adds live dye detection, tests, and documentation.
File summaries
File Description
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignTransitionResolverTest.java Tests dye-triggered transitions.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignManagerTest.java Updates dye-aware fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignLinesParserTest.java Updates marker-group fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignEntryTest.java Tests dye equality behavior.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignEntryHelperTest.java Tests side-specific dye selection.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/ShapeGroupResolverTest.java Updates sign fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/SignRegionPartitionerTest.java Updates persisted-entry fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/RegionShardedSignEntryWriterTest.java Verifies V6 output.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/RegionShardedSignEntryLoaderTest.java Updates V6 fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/VersionedFileSignEntryLoaderTest.java Tests V5-to-V6 migration.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version6ConverterTest.java Tests dye backfilling.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version3ConverterTest.java Updates marker-group fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version1SignEntryLoaderTest.java Updates legacy fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/LegacySignFileMigratorTest.java Updates migration fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/ParsingContextTest.java Updates marker-group fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/LineGroupResolverTest.java Updates sign fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/ExtrudeGroupResolverTest.java Updates sign fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/ColorResolverTest.java Tests dye color resolution.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/markers/MarkerSetIdentifierCollectionTest.java Updates group fixtures.
src/test/java/com/tpwalke2/bluemapsignmarkers/core/bluemap/actions/ActionFactoryTest.java Tests explicit color parameters.
src/test/java/com/tpwalke2/bluemapsignmarkers/config/ConfigProviderTest.java Tests player-color configuration.
src/main/java/com/tpwalke2/bluemapsignmarkers/mixin/SignBlockEntityInject.java Detects live sign mutations.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignTransitionResolver.java Resolves colors during transitions.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignManager.java Preserves incoming dye state.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignHelper.java Reads sign-side dyes.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignEntryHelper.java Selects the effective dye.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/SignEntry.java Adds persisted dye fields.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/SignFileVersions.java Adds persistence V6.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/RegionShardedSignEntryWriter.java Writes V6 files.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/models/SignEntryV5.java Freezes the V5 schema.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/VersionedFileSignEntryLoader.java Adds V6 migration paths.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version6Converter.java Backfills undyed values.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version5Converter.java Produces frozen V5 entries.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/Version1SignEntryLoader.java Extends legacy migration to V6.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/ColorResolver.java Implements dye precedence and alpha preservation.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/markers/MarkerGroup.java Adds allowPlayerColors.
src/main/java/com/tpwalke2/bluemapsignmarkers/core/bluemap/actions/ActionFactory.java Accepts resolved colors.
src/main/java/com/tpwalke2/bluemapsignmarkers/config/persistence/LoadingMarkerGroupV2.java Loads the new option.
src/main/java/com/tpwalke2/bluemapsignmarkers/config/persistence/LoadingBMSMConfigV2.java Supplies its default value.
src/main/java/com/tpwalke2/bluemapsignmarkers/config/ConfigProvider.java Resolves and validates the option.
src/main/java/com/tpwalke2/bluemapsignmarkers/common/ColorUtils.java Adds RGBA hex formatting.
README.md Documents player colors and examples.
agent-context/README.md Updates the context index.
agent-context/plans/player-marker-colors/spec.md Defines the feature specification.
agent-context/plans/player-marker-colors/map.md Records design decisions.
agent-context/plans/player-marker-colors/issues/08-end-to-end-player-dyed-markers.md Tracks integration work.
agent-context/plans/player-marker-colors/issues/07-colour-resolution-logic.md Tracks resolver work.
agent-context/plans/player-marker-colors/issues/06-live-dye-change-detection.md Tracks mutation detection.
agent-context/plans/player-marker-colors/issues/05-config-flag-and-persisted-dye.md Tracks configuration and persistence.
agent-context/plans/player-marker-colors/issues/04-write-spec-document.md Records specification completion.
agent-context/plans/player-marker-colors/issues/03-recompute-trigger-design.md Documents recomputation design.
agent-context/plans/player-marker-colors/issues/02-config-schema-for-opt-in-flag.md Documents configuration design.
agent-context/plans/player-marker-colors/issues/01-dye-glow-event-hooks-research.md Documents hook research.
agent-context/context/testing.md Updates testing guidance.
agent-context/context/core-pipeline.md Documents dye processing.
agent-context/context/config-and-persistence.md Documents configuration and V6 storage.
agent-context/context/architecture.md Updates verification metadata.
Review details

Suppressed comments (3)

agent-context/context/testing.md:276

  • This coverage summary states the opposite of the tested and implemented behavior. v2ContentStillMigratesWhenTheBackupFails asserts a non-null converted result, and every V2–V5 branch logs the backup failure and continues migration. Update the summary so future maintainers do not infer that backup failure triggers the V1 fallback.
  relying on Gson's nulls to coincidentally route there (ticket 05); and the `V2`/`V3`/`V4`/`V5` branches returning
  `null` (falls through to the V1 loader) rather than proceeding, if backing up to
  `.v2.bak`/`.v3.bak`/`.v4.bak`/`.v5.bak` fails (ticket 02).

agent-context/plans/player-marker-colors/spec.md:32

  • The listed interaction items contradict the next paragraph: ink sacs and glow ink sacs only toggle glowing text, and hasGlowingText() is not consumed by this feature. Only dye items alter SignText.getColor(), so describe those as the color input.
A player dyes a member sign (right-clicking it with a dye, ink sac, or glow ink sac item — vanilla mechanic,
no new UI). The sign's dye is read from `SignText.getColor()` (a `DyeColor`, default `BLACK` for an undyed

src/test/java/com/tpwalke2/bluemapsignmarkers/core/signs/ColorResolverTest.java:76

  • The feature specification explicitly calls for coverage of winner removal handing off to the next-earliest dyed member, but the new tests only cover choosing the earliest winner while it remains present. Add the removal case so this core conflict-resolution guarantee cannot regress.
  • Files reviewed: 57/57 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread README.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are two confirmed null-safety/robustness issues in core logic/persistence loading that can cause runtime exceptions or processing failures on malformed persisted data.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

src/main/java/com/tpwalke2/bluemapsignmarkers/core/signs/persistence/loaders/VersionedFileSignEntryLoader.java:103

  • The V6+ load path returns the deserialized array as-is, which can include null elements if the JSON array contains null. Downstream code iterates and dereferences entries (e.g., membership resolvers), so filtering null elements here prevents a single bad entry from breaking loading/processing.
  • Files reviewed: 57/57 changed files
  • Comments generated: 1
  • Review effort level: Lite

@tpwalke2
tpwalke2 merged commit d201c9e into main Sep 7, 2026
1 check passed
@tpwalke2
tpwalke2 deleted the feature/tpwalke2/198-dye-colors branch September 7, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants