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

@ -254,7 +254,7 @@ public class PaperdollControllerTests
}
[Fact]
public void HandleDropRelease_wields_optimistically_and_sends_wire()
public void HandleDropRelease_sendsWieldAndWaitsForServerPlacement()
{
var (layout, lists) = BuildLayout();
var objects = new ClientObjectTable();
@ -263,8 +263,8 @@ public class PaperdollControllerTests
var ctrl = Bind(layout, objects, wields);
var payload = new ItemDragPayload(0xD01u, ItemDragSource.Inventory, 0, lists[HeadSlot].Cell);
ctrl.HandleDropRelease(lists[HeadSlot], lists[HeadSlot].Cell, payload);
Assert.Equal(EquipMask.HeadWear, objects.Get(0xD01u)!.CurrentlyEquippedLocation); // equipped instantly
Assert.Equal(Player, objects.Get(0xD01u)!.ContainerId); // contained-by-wielder (the optimistic wield is ContainerId-based; it does NOT write WielderId)
Assert.Equal(EquipMask.None, objects.Get(0xD01u)!.CurrentlyEquippedLocation);
Assert.Equal(Pack, objects.Get(0xD01u)!.ContainerId);
Assert.Single(wields);
Assert.Equal((0xD01u, (uint)EquipMask.HeadWear), wields[0]); // GetAndWieldItem wire
}
@ -334,10 +334,10 @@ public class PaperdollControllerTests
Assert.Equal(EquipMask.None, objects.Get(sword)!.CurrentlyEquippedLocation);
Assert.Equal(new[] { "Moving Shortbow to your backpack" }, messages);
objects.MoveItem(bow, Player, 0, EquipMask.None);
Assert.True(objects.ApplyConfirmedServerMove(bow, Player, 0u, 0));
Assert.Equal(new[] { (sword, (uint)EquipMask.MeleeWeapon) }, wields);
Assert.Equal(EquipMask.MeleeWeapon,
Assert.Equal(EquipMask.None,
objects.Get(sword)!.CurrentlyEquippedLocation);
}
@ -371,7 +371,7 @@ public class PaperdollControllerTests
ctrl.HandleDropRelease(lists[ChestSlot], lists[ChestSlot].Cell, payload);
Assert.Equal((uint)coatMask, wields[0].mask);
Assert.Equal(coatMask, objects.Get(0xE02u)!.CurrentlyEquippedLocation);
Assert.Equal(EquipMask.None, objects.Get(0xE02u)!.CurrentlyEquippedLocation);
}
[Fact]
@ -392,7 +392,7 @@ public class PaperdollControllerTests
ctrl.HandleDropRelease(lists[ChestArmorSlot], lists[ChestArmorSlot].Cell, payload);
Assert.Equal((uint)hauberkMask, wields[0].mask);
Assert.Equal(hauberkMask, objects.Get(0xE03u)!.CurrentlyEquippedLocation);
Assert.Equal(EquipMask.None, objects.Get(0xE03u)!.CurrentlyEquippedLocation);
}
[Fact]