79 lines
4.1 KiB
C#
79 lines
4.1 KiB
C#
using Ananta.SDK.Serialization;
|
|||
|
|
|
||
|
|
namespace Ananta.Server.Protocol.Client4229938;
|
||
|
|
|
||
|
|
// Native 4229938 S002PlayerNet / S002.Interact.SInteractNet. Shares the story
|
||
|
|
// channel's cumulative RPC acknowledgement with S011; never resets it here.
|
||
|
|
internal static class StoryS002Codec4229938
|
||
|
|
{
|
||
|
|
// Wire names come from the native constructors, NOT the C# member names.
|
||
|
|
// S002PlayerNet ctor RVA 0x15F77A30: MsgrNpcInteract => "NpcInteract".
|
||
|
|
// SInteractNet ctor RVA 0x15F6D120: ObsInteractEnd => "InteractEnd";
|
||
|
|
// MsgrInteraction/MsgrReaction/MsgrClient => "Interaction"/"Reaction"/"Messenger".
|
||
|
|
// A wrong observable name throws in NetNode.ApplyEnableData before OnEnable.
|
||
|
|
internal const string NpcInteract = "NpcInteract";
|
||
|
|
internal const string InteractEnd = "InteractEnd";
|
||
|
|
internal const string InteractionMessage = "Interaction";
|
||
|
|
internal const string ReactionMessage = "Reaction";
|
||
|
|
internal const string ClientMessage = "Messenger";
|
||
|
|
|
||
|
|
// Root NpcInteract payload marks, NOT child InteractionId values.
|
||
|
|
// Verified in the actual client's generated serialization instructions:
|
||
|
|
// WriteS002EscortFromRequestPayload_Check 0x9F56600 (+0x93) writes 0x14;
|
||
|
|
// WriteS002EscortRequestPayload_Check 0x9F56710 (+0x93) writes 0x15.
|
||
|
|
// Their declaration/TypeDef order is different from their wire mark order.
|
||
|
|
internal const byte EnterExamRequestTag = 19;
|
||
|
|
internal const byte EscortFromVehicleRequestTag = 20;
|
||
|
|
internal const byte EscortRequestTag = 21;
|
||
|
|
|
||
|
|
internal static byte[] Root(uint nid)
|
||
|
|
{
|
||
|
|
var w = new UxWriter(); List(w, 3);
|
||
|
|
Create(w, nid, "StoryServer.Story.World.S002.S002PlayerNet");
|
||
|
|
Validate(w, nid, [], [], [NpcInteract]);
|
||
|
|
w.U8(6); w.U32(nid); w.U8(0); w.U8(0); w.U8(0); Tail(w);
|
||
|
|
return w.ToArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static byte[] Interaction(uint nid, ulong agent, bool start, bool escort = false, bool serverInitiate = false)
|
||
|
|
{
|
||
|
|
var w = new UxWriter(); List(w, 3);
|
||
|
|
Create(w, nid, "StoryServer.Story.World.S002.Interact.SInteractNet");
|
||
|
|
Validate(w, nid, ["ExamEmotionId", InteractEnd],
|
||
|
|
["AgentId", "IsEscort", "IsFakePerson", "ServerInitiate", "StartInteract"],
|
||
|
|
[InteractionMessage, ReactionMessage, ClientMessage]);
|
||
|
|
w.U8(6); w.U32(nid);
|
||
|
|
List(w, 2);
|
||
|
|
Named(w, "ExamEmotionId", b => { b.U8(43); b.U32(0); });
|
||
|
|
Named(w, InteractEnd, b => { b.U8(5); b.Bool(false); });
|
||
|
|
List(w, 5);
|
||
|
|
Named(w, "AgentId", b => { b.U8(44); b.U64(agent); });
|
||
|
|
Named(w, "IsEscort", b => { b.U8(5); b.Bool(escort); });
|
||
|
|
Named(w, "IsFakePerson", b => { b.U8(5); b.Bool(false); });
|
||
|
|
Named(w, "ServerInitiate", b => { b.U8(5); b.Bool(serverInitiate); });
|
||
|
|
Named(w, "StartInteract", b => { b.U8(5); b.Bool(start); });
|
||
|
|
w.U8(0); Tail(w);
|
||
|
|
return w.ToArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static byte[] Reaction(uint nid, uint section, uint reaction, uint escortToWardIndex = 0)
|
||
|
|
{
|
||
|
|
var w = new UxWriter(); List(w, 1);
|
||
|
|
w.U8(7); w.U32(nid); w.UxString(ReactionMessage);
|
||
|
|
// S002ReactionResponsePayload: SectionId, ReactionId, EscortToWardIndex,
|
||
|
|
// EscortToHearCaseId. The ward index is consumed by SEscortToWard.
|
||
|
|
w.U8(26); w.U32(section); w.U32(reaction); w.U32(escortToWardIndex); w.U64(0); Tail(w);
|
||
|
|
return w.ToArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void Create(UxWriter w, uint nid, string type)
|
||
|
|
{ w.U8(3); w.U32(nid); w.UxString(type); w.UxString(""); w.Bool(false); Tail(w); }
|
||
|
|
private static void Validate(UxWriter w, uint nid, string[] obs, string[] repl, string[] msg)
|
||
|
|
{ w.U8(9); w.U32(nid); Strings(w, obs); Strings(w, repl); Strings(w, msg); w.U8(0); Tail(w); }
|
||
|
|
private static void Strings(UxWriter w, string[] values)
|
||
|
|
{ List(w, values.Length); foreach (var value in values) w.UxString(value); }
|
||
|
|
private static void Named(UxWriter w, string name, Action<UxWriter> payload)
|
||
|
|
{ w.U8(255); w.UxString(name); payload(w); }
|
||
|
|
private static void List(UxWriter w, int count) { w.U8(255); w.Int7(count); }
|
||
|
|
private static void Tail(UxWriter w) { w.I64(0); w.Bool(false); }
|
||
|
|
}
|