Release 4.3.x#204
Open
logicallysynced wants to merge 7 commits into
Open
Conversation
…(v4.2.73 -> v4.3.1) Multi-agent audit of the full codebase (67 raw findings, adversarially verified down to 47; 3 build-script credential items handled separately by the owner). Fixes by area: Core: lock discipline for _runningEffects and _activeDevices, _layergroups swapped to ConcurrentDictionary (game loop vs RGB.NET timer thread race), dead CPU-throttle branch removed, Sentry heartbeat no longer blocks a thread-pool thread. Layers: DamageFlash min-opacity clamp inverted the whole (0,1) range, JobGaugeA/B/C interpolate mode rebuilt LED groups every tick, missing _disposed guard in TargetCastbar, per-tick brush and dictionary allocations hoisted across nine processors, CutsceneAnimation dead decorator allocation removed, GetLedArray O(n*m) scan now a HashSet. Decorators: ArenaLightShow blended a 0-1 base color into a 0-255 scale (base color invisible), Strobe/Pulse detach race guards, RectangularGradient bottom-edge interpolation typo. Devices: Yeelight dedup state no longer poisoned by failed sends (bulb recovers after Wi-Fi drops, errors surface once per outage), Music Mode accept task leak fixed, LIFX and QMK inter-chunk sleeps moved outside the device lock (UI no longer freezes on multizone re-enable), per-frame buffer allocations removed in DynamicLighting, Alienware, EVision, Redragon and QMK queues. Helpers: settings deserialization NRE in DictionaryConverter, Blacksmith job used Black Mage palette colors, palette/effects/settings saves now atomic (tmp + replace), GetMaxCpuUsage read a memory counter. UI: Hue adoption dialog mutated ObservableCollection off the UI thread, LocalizationService subscription leaks in layer items and adoption dialogs, console trim no longer fires 500 list shifts, registry key in SettingsViewModel now scoped and disposed. Harness: SavePreset now round-trips all 28 effect parameters. Build clean, 133/133 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…203) The retry v4 major only moves the action to the node24 runtime; inputs and retry behaviour are unchanged, and windows-latest runners ship node24. Applied here so the release branch carries it; dependabot closes #203 once this reaches master. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion (v4.3.1 -> v4.3.2) Sharlayan 9.1.1 is the full-codebase-audit release (74 verified fixes plus an FFXIVClientStructs submodule refresh, FFXIVAPP/sharlayan PR #116). Referenced via NuGet in both Chromatics.csproj and Chromatics.Tests.csproj as before. Compile fixes for the one breaking change Chromatics touches: AstrologianResources.DrawnCards went from List<AstrologianCard> to AstrologianCard[], so the two .Count reads became .Length - JobGaugeB.cs (AST next-card gauge) and JobGaugeC.cs (AST draw-state gauge). The [0] indexer and null checks compile unchanged. Verified non-impacts per the migration notes: - ActionContainers / InventoryContainers ConcurrentBag -> List: Keybinds.cs uses null check + foreach only, compiles unchanged. The ConcurrentBag in LifxDiscovery.cs is Chromatics' own and unrelated. - DancerResources.Steps -> DanceStep[]: no Chromatics usage. - MonkResources.BeastChakra now get-only: no Chromatics usage (JobMNKBeastChakra is a palette entry, not the Sharlayan type). - MateriaType ushort-backed: no (byte) casts anywhere in Chromatics. User-visible wins inherited from the Sharlayan fixes, called out in the 4.3.2 CHANGELOG entry: - RPR / SGE levels and EXP now populate, so the Experience Tracker layer works for Reaper and Sage (previously read 0). - Hotbar action ids above 32767 read correctly, fixing Keybinds layer dispatch on high-id actions. - Party member Coordinate.Y no longer mirrors Z. Build clean, 133/133 xUnit tests pass.
… forward-compat guard, schemaVersion 6 (v4.3.2 -> v4.3.3) Two new dynamic layer types mirroring TargetHP / TargetCastbar but reading TargetInfo.FocusTarget instead of CurrentTarget: - DynamicLayerType.FocusTargetHP = 16, FocusTargetCastbar = 17. Enum values equal their _dynamicLayerOrder positions per the position == enum-value invariant; both order arrays (LayerItemViewModel + CopyLayersDialogViewModel) got the matching appends and LayerProcessorFactory.CreateDynamicProcessor got the two cases. The stale DynamicLayerProcessorFactory map in LayerProcessor.cs has no callers (it already lacks JobGaugeC) and was left untouched. - FocusTargetHPProcessor clones the TargetHP structure: per-layerID model, claimed / friendly / idle brush selection from InCombat + IsAggressive, empty bar painted when nothing is focus targeted, Interpolate bar fill + Fade blend with the requestUpdate rebuild guard. - FocusTargetCastbarProcessor clones TargetCastbar but fixes the no-target path while at it: instead of the early return that freezes the last cast frame, it tracks the focus-target id, casts at 0.0 with no focus target, and repaints the empty bar on target change. Same requestUpdate guard on both modes. - Six new palette entries under Target/Enemy: Focus Target Cast Bar Charge Build / Empty and Focus Target HP Friendly / Claimed / Empty / Idle. Palette files saved by older versions load fine - missing fields fall back to the field initialisers. - LayerDisplay names + descriptions localised: 4 new en.json keys, all six locale files regenerated via translate.py. Forward-compat guard (per request): layers.chromatics4 written by a newer Chromatics can carry dynamic positions this build's enum doesn't define. MappingLayers.SanitizeLayerTypeIndexes validates layerTypeindex against the matching enum for the layer's rootLayerType and resets unknown positions to 0 (None) with a console line naming the layer. Runs in LoadMappings (startup path) and ImportMappings (Mapping-tab import + migration path). Without it, an unknown position flows into GameController's (DynamicLayerType) cast and the processor factory throws on every frame. schemaVersion bumped 5 -> 6 in MappingFileV3, SaveLayerMappings, and ExportLayerMappings to mark files that can carry the new positions. Build clean, 133/133 xUnit tests pass.
…maps (v4.3.3 -> v4.3.4) Neither static factory map had a single caller - GameController dispatches base and dynamic layers through LayerProcessorFactory.GetProcessor. Both maps had also drifted out of date: BaseLayerProcessorFactory was missing AudioVisualizer, DynamicLayerProcessorFactory was missing JobGaugeC and the new focus-target layers. Worse than harmless, their static initialisers eagerly built every processor singleton the moment anything touched the class. EffectLayerProcessorFactory stays - GameController iterates its map for effect-layer dispatch (GameController.cs:744). A comment above it records why its two siblings are gone so they don't get reintroduced by pattern-matching. CHANGELOG header renamed 4.3.3 -> 4.3.4 to track the version (also fixes the "Castbasr" typo in the focus-target bullet); the existing "Various performance improvements and bug fixes" line covers this cleanup. Build clean, 133/133 xUnit tests pass.
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.
Brings master from 4.1.38 to 4.3.1 - 475 commits covering the 4.1.44 to 4.2.73 releases plus the 4.3.1 audit pass. Everything here has already shipped to users through the Velopack update channel except 4.3.1, which is the release this PR prepares.
What each version added
The 4.3.1 audit, by area
Thread safety
_runningEffectsand_activeDevicesin RGBController were plain collections written from device-SDK callback threads while the game loop and UI thread read them. Both now sit behind dedicated locks; teardown paths snapshot before detaching._layergroupswas a plain Dictionary mutated by the game loop while the RGB.NET timer thread read it throughsurface.Updating. It is now a ConcurrentDictionary, with all 24 processor write sites and 4 removal sites converted.Thread.Sleep(1500)every minute. It is now async end to end.Logic bugs
ConfigureAwait(false). Continuations now resume on the UI thread._disposedguard.Performance
GetLedArrayran an O(n*m) LINQ scan per frame; it now uses a HashSet.Resource leaks
Dead code
Two findings needed no change on inspection (one was already in the recommended form, one targets an app-lifetime object where unsubscription buys nothing), and the harness gained a fix of its own: effect presets now round-trip all 28 parameters instead of a third of them.
Every fix was re-reviewed against the diff before commit. That second pass caught and corrected two regressions in the first round of fixes (a snapshot return that broke effect registration, and a stale-buffer repaint in Dynamic Lighting), one log-spam path, and one compile error.
CI
nick-fields/retrybumped v3 to v4 in ci.yml (supersedes Bump nick-fields/retry from 3 to 4 #203; the v4 major only moves the action to the node24 runtime, which windows-latest runners already ship). Dependabot will close Bump nick-fields/retry from 3 to 4 #203 when this merges.Verification
🤖 Generated with Claude Code