fix(client): restore retail interaction parity
All checks were successful
CI / linux-portable (push) Successful in 3m27s
CI / windows-gate (push) Successful in 6m42s
CI / release (push) Successful in 2m12s

Harden keyboard and camera routing, inventory and vendor interactions, chat/emotes, relog portal flow, and paperdoll rendering. Add retail research, connected gate coverage, and release-gate validation.
This commit is contained in:
Erik 2026-08-26 20:45:11 +02:00
parent 0c699240e0
commit f6fe0f2a4f
151 changed files with 10162 additions and 1211 deletions

View file

@ -101,6 +101,22 @@ public class InputDispatcherTests
fired);
}
[Fact]
public void Same_scope_retail_duplicate_chord_fires_every_distinct_action()
{
var (_, kb, _, bindings, fired) = Build();
var chord = new KeyChord(Key.Number1, ModifierMask.Alt);
bindings.Add(new Binding(chord, InputAction.ToggleFloatingChatWindow1));
bindings.Add(new Binding(chord, InputAction.UseQuickSlot_10));
kb.EmitKeyDown(Key.Number1, ModifierMask.Alt);
Assert.Equal(
[(InputAction.ToggleFloatingChatWindow1, ActivationType.Press),
(InputAction.UseQuickSlot_10, ActivationType.Press)],
fired);
}
[Fact]
public void Changing_combat_scope_releases_hold_resolved_in_previous_scope()
{
@ -188,6 +204,30 @@ public class InputDispatcherTests
Assert.Empty(fired); // no longer held
}
[Fact]
public void RetailBareLeftShiftBinding_NormalizesSilkSelfModifierBit()
{
var kb = new FakeKeyboardSource();
var mouse = new FakeMouseSource();
var dispatcher = InputDispatcher.CreateDetached(
kb,
mouse,
KeyBindings.RetailDefaults());
dispatcher.Attach();
var fired = new List<(InputAction, ActivationType)>();
dispatcher.Fired += (action, activation) => fired.Add((action, activation));
kb.EmitKeyDown(Key.ShiftLeft, ModifierMask.Shift);
kb.EmitKeyUp(Key.ShiftLeft, ModifierMask.Shift);
Assert.Contains(
(InputAction.MovementWalkMode, ActivationType.Press),
fired);
Assert.Contains(
(InputAction.MovementWalkMode, ActivationType.Release),
fired);
}
[Fact]
public void Hold_callback_scope_change_DoesNotDispatchStaleSnapshotChord()
{