From 3fe3043599ad952fb2268216a0dc56d2aedc5e8f Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2026 18:02:07 +0200 Subject: [PATCH] =?UTF-8?q?fix(vtank):=20slice=207=20round=20E=20item=20D-?= =?UTF-8?q?2=20=E2=80=94=20recall=20combo=20shows=20VTank=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RouteRecallNames/SelectedRouteRecall used Enum.GetNames/ToString(), showing bare C# identifiers ("PrimaryPortalRecall", "ParadoxTouchedOlthoiInfestedAreaRecall", ...) in the Route tab's recall combo instead of VTank's real recall names. Both now route through RouteWaypoint.RecallDisplayName (the same table AddRouteRecallCore/RecallLabel already use), matching how RouteInsertModeNames/RouteModeNames already show dedicated display captions rather than raw enum text. SelectRouteRecall now parses that same display string back (Enum.TryParse against the enum identifier no longer matches what the combo sends). mosstank.xml's cmbRecallType widened 120 -> 300: VTank's own combo is also 120 wide, but only because its captions are hand-abbreviated ("LS", "Mt. Lethe", "PtOIA"); RecallDisplayName deliberately keeps metaf's full names (round D item 3), so the box needs real room for the longest one, "Paradox-touched Olthoi Infested Area Recall". Nothing else shares that row past x=474 and the group floors at ~848 wide even at the panel's minw, so 300 has ample clearance. Mutation shown to fail first: reverting MossTankPanel.cs's fix (git checkout, patch saved and reapplied) reproduced the bare-identifier list and the "PrimaryPortalRecall" default selection. MossTank suite 720 -> 721; App markup/plugin filter holds 243/243 (no overlap from the widened menu). Co-Authored-By: Claude Fable 5.1 --- src/AcDream.Plugins.MossTank/MossTankPanel.cs | 36 +++++++++++++--- src/AcDream.Plugins.MossTank/mosstank.xml | 11 ++++- .../MossTankPanelTests.cs | 43 +++++++++++++++++++ 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/AcDream.Plugins.MossTank/MossTankPanel.cs b/src/AcDream.Plugins.MossTank/MossTankPanel.cs index 32fc9133..830b1a03 100644 --- a/src/AcDream.Plugins.MossTank/MossTankPanel.cs +++ b/src/AcDream.Plugins.MossTank/MossTankPanel.cs @@ -1033,9 +1033,26 @@ internal sealed partial class MossTankPanel public string SelectedRouteMode => _navigationSettings.Mode == RouteMode.Target ? "Follow" : _navigationSettings.Mode.ToString(); - public IReadOnlyList RouteRecallNames => - Enum.GetNames(); - public string SelectedRouteRecall => _routeRecallKind.ToString(); + // D-2 (round E architecture re-check): the combo used to show + // Enum.GetNames' bare C# identifiers ("PrimaryPortalRecall", + // "ParadoxTouchedOlthoiInfestedAreaRecall", ...) instead of VTank's + // real recall names — RouteInsertModeNames/RouteModeNames above + // already route their own display captions through a dedicated + // string, not the enum's own ToString(); this brings Recall in line + // via the same RecallDisplayName table AddRouteRecallCore/RecallLabel + // already use. + public IReadOnlyList RouteRecallNames + { + get + { + RouteRecallKind[] values = Enum.GetValues(); + var names = new string[values.Length]; + for (int i = 0; i < values.Length; i++) + names[i] = RouteWaypoint.RecallDisplayName(values[i]); + return names; + } + } + public string SelectedRouteRecall => RouteWaypoint.RecallDisplayName(_routeRecallKind); public IReadOnlyList RouteProfileNames => _routeProfiles.AvailableNames; public string SelectedRouteProfile => _routeProfiles.Selected; @@ -1116,10 +1133,19 @@ internal sealed partial class MossTankPanel RefreshRouteEditor(); SaveRouteProfile(); }; + // D-2: parses the SAME display string RouteRecallNames/SelectedRouteRecall + // now show (Enum.TryParse against the bare C# identifier no longer + // matches what the combo actually sends back). public Action SelectRouteRecall => value => { - if (Enum.TryParse(value, ignoreCase: true, out RouteRecallKind recall)) - _routeRecallKind = recall; + foreach (RouteRecallKind kind in Enum.GetValues()) + { + if (RouteWaypoint.RecallDisplayName(kind).Equals(value, StringComparison.OrdinalIgnoreCase)) + { + _routeRecallKind = kind; + return; + } + } }; public Action SelectRouteWaypoint => index => _selectedRouteWaypoint = ClampRow(index, _navigationSettings.Waypoints.Count); diff --git a/src/AcDream.Plugins.MossTank/mosstank.xml b/src/AcDream.Plugins.MossTank/mosstank.xml index fc318aab..e33c5c2a 100644 --- a/src/AcDream.Plugins.MossTank/mosstank.xml +++ b/src/AcDream.Plugins.MossTank/mosstank.xml @@ -709,7 +709,16 @@ VTank's one slash-command entry) in VTank's own combo order — see RouteRecallKind's own doc comment for the deviation from the earlier 4-entry model. --> - + diff --git a/tests/AcDream.Plugins.MossTank.Tests/MossTankPanelTests.cs b/tests/AcDream.Plugins.MossTank.Tests/MossTankPanelTests.cs index d88fbfee..3b74dd81 100644 --- a/tests/AcDream.Plugins.MossTank.Tests/MossTankPanelTests.cs +++ b/tests/AcDream.Plugins.MossTank.Tests/MossTankPanelTests.cs @@ -2475,6 +2475,49 @@ public sealed class MossTankPanelTests Assert.Contains("77", panel.RouteWaypointTextColumn[1]); } + /// + /// D-2 (round E architecture re-check): the combo used to show + /// Enum.GetNames' bare C# identifiers ("PrimaryPortalRecall", + /// "ParadoxTouchedOlthoiInfestedAreaRecall", ...) — RouteRecallNames/ + /// SelectedRouteRecall must show VTank's real recall names (the same + /// RecallDisplayName table AddRouteRecallCore already uses), in + /// VTank's own combo order, and SelectRouteRecall must parse THAT + /// display string back rather than the enum identifier. + /// + [Fact] + public void RouteRecallComboShowsVtankNamesNotEnumIdentifiers() + { + var automation = new FakeAutomation { NavigationSnapshot = NavigationAt(0f) }; + var panel = new MossTankPanel(new FakeHost(automation)); + + Assert.Equal( + [ + "Primary Portal Recall", "Secondary Portal Recall", "Lifestone Recall", + "Lifestone Sending", "Portal Recall", "Recall Aphus Lassel", + "Recall the Sanctuary", "Recall to the Singularity Caul", + "Glenden Wood Recall", "Aerlinthe Recall", "Mount Lethe Recall", + "Ulgrim's Recall", "Bur Recall", + "Paradox-touched Olthoi Infested Area Recall", + "Call of the Mhoire Forge", "Colosseum Recall", "Facility Hub Recall", + "Gear Knight Invasion Area Camp Recall", "Lost City of Neftet Recall", + "Return to the Keep", "Rynthid Recall", "Viridian Rise Recall", + "Viridian Rise Great Tree Recall", "Celestial Hand Stronghold Recall", + "Radiant Blood Stronghold Recall", "Eldrytch Web Stronghold Recall", + "Marketplace Recall", + ], + panel.RouteRecallNames); + + // Default selection reads as a real name, not "PrimaryPortalRecall". + Assert.Equal("Primary Portal Recall", panel.SelectedRouteRecall); + + panel.SelectRouteRecall("Lifestone Recall"); + Assert.Equal("Lifestone Recall", panel.SelectedRouteRecall); + + panel.AddRouteRecall(); + Assert.Contains("Lifestone Recall", panel.RouteNotice, StringComparison.Ordinal); + Assert.Contains("Lifestone Recall", Assert.Single(panel.RouteWaypointTextColumn)); + } + [Fact] public void RoutePauseSecondsFieldParsesAndClampsInput() {