fix(net): honor retail graceful logout handshake
Send the active character id, drain until the authoritative server confirmation, then emit retail's zero-sequence connection disconnect with the negotiated receiver iteration. The connected gate now waits for ACE to remove the exact UDP session before reconnecting, eliminating fixed-delay races.
This commit is contained in:
parent
b03371c03d
commit
68578fa5fa
10 changed files with 372 additions and 41 deletions
|
|
@ -0,0 +1,36 @@
|
|||
using System.Buffers.Binary;
|
||||
using AcDream.Core.Net.Messages;
|
||||
|
||||
namespace AcDream.Core.Net.Tests.Messages;
|
||||
|
||||
public sealed class CharacterLogOffTests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildRequestBody_MatchesRetailOpcodeThenCharacterId()
|
||||
{
|
||||
byte[] body = CharacterLogOff.BuildRequestBody(0x5000000Au);
|
||||
|
||||
Assert.Equal(8, body.Length);
|
||||
Assert.Equal(
|
||||
CharacterLogOff.Opcode,
|
||||
BinaryPrimitives.ReadUInt32LittleEndian(body));
|
||||
Assert.Equal(
|
||||
0x5000000Au,
|
||||
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(4)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsConfirmation_AcceptsServerOpcodeOnlyBody()
|
||||
{
|
||||
byte[] body = BitConverter.GetBytes(CharacterLogOff.Opcode);
|
||||
|
||||
Assert.True(CharacterLogOff.IsConfirmation(body));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsConfirmation_RejectsTruncatedOrDifferentMessage()
|
||||
{
|
||||
Assert.False(CharacterLogOff.IsConfirmation([0x53, 0xF6, 0x00]));
|
||||
Assert.False(CharacterLogOff.IsConfirmation(BitConverter.GetBytes(0xF654u)));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue