fix(client): restore retail interaction parity
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:
parent
0c699240e0
commit
f6fe0f2a4f
151 changed files with 10162 additions and 1211 deletions
|
|
@ -59,4 +59,69 @@ public sealed class LiveChatCommandRouteTests
|
|||
route.Publish(new SendServerCommandCmd("@stale"));
|
||||
Assert.Equal(6, sent.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Say_ConsumesValidDatPoseAndLeavesUnknownTokenAsSpeech()
|
||||
{
|
||||
using var communication = new RuntimeCommunicationState();
|
||||
using var character = new RuntimeCharacterState();
|
||||
var sent = new List<string>();
|
||||
var route = new LiveChatCommandRoute(new LiveChatCommandBindings(
|
||||
_ => { },
|
||||
communication,
|
||||
communication.Chat,
|
||||
communication.TurbineChat,
|
||||
character,
|
||||
() => 0x50000001u,
|
||||
text => sent.Add($"talk:{text}"),
|
||||
(_, _) => { },
|
||||
(_, _) => { },
|
||||
(_, _, _, _, _, _) => { },
|
||||
ResolvePose: command => string.Equals(
|
||||
command,
|
||||
"wave",
|
||||
StringComparison.OrdinalIgnoreCase)
|
||||
? new RetailChatPose(0x13000087u, "wave.", "waves.")
|
||||
: null,
|
||||
ExecuteMotion: motion => sent.Add($"motion:{motion:X8}"),
|
||||
SendSoulEmote: text => sent.Add($"soul:{text}")));
|
||||
route.Activate();
|
||||
|
||||
route.Publish(new SendChatCmd(
|
||||
ChatChannelKind.Say,
|
||||
null,
|
||||
"hello *WAVE* there *not-a-pose*"));
|
||||
|
||||
Assert.Equal(
|
||||
[
|
||||
"motion:13000087",
|
||||
"soul:waves.",
|
||||
"talk:hello there *not-a-pose*",
|
||||
],
|
||||
sent);
|
||||
ChatEntry local = Assert.Single(communication.Chat.Snapshot());
|
||||
Assert.Equal(ChatKind.SoulEmote, local.Kind);
|
||||
Assert.Equal("You", local.Sender);
|
||||
Assert.Equal("wave.", local.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Say_ContainingOnlyValidPoseDoesNotSendEmptyTalk()
|
||||
{
|
||||
using var communication = new RuntimeCommunicationState();
|
||||
using var character = new RuntimeCharacterState();
|
||||
var sent = new List<string>();
|
||||
var route = new LiveChatCommandRoute(new LiveChatCommandBindings(
|
||||
_ => { }, communication, communication.Chat,
|
||||
communication.TurbineChat, character, () => 1u,
|
||||
text => sent.Add($"talk:{text}"), (_, _) => { }, (_, _) => { },
|
||||
(_, _, _, _, _, _) => { },
|
||||
ResolvePose: _ => new RetailChatPose(7u, string.Empty, string.Empty),
|
||||
ExecuteMotion: motion => sent.Add($"motion:{motion}")));
|
||||
route.Activate();
|
||||
|
||||
route.Publish(new SendChatCmd(ChatChannelKind.Say, null, " *wave* "));
|
||||
|
||||
Assert.Equal(["motion:7"], sent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
using AcDream.Runtime.Chat;
|
||||
|
||||
namespace AcDream.Runtime.Tests.Chat;
|
||||
|
||||
public sealed class RetailPublicChatParserTests
|
||||
{
|
||||
[Fact]
|
||||
public void InvalidAndUnmatchedTokensRemainLiteral()
|
||||
{
|
||||
string text = RetailPublicChatParser.ExtractPoses(
|
||||
"*unknown* and *unfinished",
|
||||
_ => null,
|
||||
_ => throw new Xunit.Sdk.XunitException("must not execute"));
|
||||
|
||||
Assert.Equal("*unknown* and *unfinished", text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleValidStarAndAngleTokensAreRemovedInOrder()
|
||||
{
|
||||
var motions = new List<uint>();
|
||||
string text = RetailPublicChatParser.ExtractPoses(
|
||||
"a *one* b <two> c",
|
||||
command => command switch
|
||||
{
|
||||
"one" => new RetailChatPose(1u, "", ""),
|
||||
"two" => new RetailChatPose(2u, "", ""),
|
||||
_ => null,
|
||||
},
|
||||
pose => motions.Add(pose.MotionCommand));
|
||||
|
||||
Assert.Equal("a b c", text);
|
||||
Assert.Equal([1u, 2u], motions);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue