fix(net): Campaign LA LA7a review fixes — AD-97 register row, corrected restore justification

The Opus retail-lens review decoded the PDB-paired binary at
CPlayerSystem::RestoreCharacter@0x0055d760 and refuted the
uninitialized-edx justification: the two extra arguments are real
push imm32 of a constant PStringBase (BN mis-renders them, but they
pack to >=4 bytes each), so retail 0xF7D9 is >=16 bytes where ours
is 8. The guid-only CODE stands (ACE reads only the guid; holtburger
consensus) but it is an adaptation, not a corrected decompile — filed
as divergence register AD-97 and the doc comment now states the true
mechanism.

Also from the review: the 0xF643 conditional-parse doc now names BOTH
ACE flag-only failure branches (NameInUse + Corrupt); CharacterError
0x08 doc corrected (ACE misnames it ServerCrash2 — the port corrects
an ACE misnaming; ACE omits three values, not four); LA7b hazard notes
added (ACE silent no-reply on unknown restore guid; retail SendToLogon
vs SendToControl routing; NumErrors never rendered); two review-nit
tests (flag=0 Undef flag-only, non-Ok body with trailing bytes
ignored).

Core.Net suite: 953 passed / 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-14 16:01:52 +02:00
parent 6a32f37589
commit 4338b1c1f3
5 changed files with 100 additions and 34 deletions

View file

@ -74,6 +74,45 @@ public sealed class CharacterRestoreTests
Assert.Null(parsed.SecondsGreyedOut);
}
[Fact]
public void Parse_UndefFlagZero_FlagOnlyBody_LeavesTrailingFieldsNull()
{
// LA7a review test-coverage nit: flag 0 (Undef) is a non-Ok value
// distinct from the NameInUse case — the conditional must treat it
// as flag-only too.
var w = AceWireWriter.GameMessage(CharacterRestore.ResponseOpcode)
.Write(0u); // CharacterGenerationVerificationResponse.Undef
CharacterRestore.Parsed parsed = CharacterRestore.Parse(w.ToArray());
Assert.Equal(0u, parsed.VerificationFlag);
Assert.False(parsed.IsOk);
Assert.Null(parsed.Guid);
Assert.Null(parsed.Name);
Assert.Null(parsed.SecondsGreyedOut);
}
[Fact]
public void Parse_NonOkBodyWithTrailingBytes_IgnoresRatherThanMisreads()
{
// LA7a review test-coverage nit: a non-Ok body that DOES carry
// trailing bytes (unknown server variant / padding) must not be
// misread as character fields — the conditional stops at the flag
// and the extra bytes are ignored.
var w = AceWireWriter.GameMessage(CharacterRestore.ResponseOpcode)
.Write(3u) // NameInUse
.Write(0xDEADBEEFu)
.Write(0x12345678u);
CharacterRestore.Parsed parsed = CharacterRestore.Parse(w.ToArray());
Assert.Equal(3u, parsed.VerificationFlag);
Assert.False(parsed.IsOk);
Assert.Null(parsed.Guid);
Assert.Null(parsed.Name);
Assert.Null(parsed.SecondsGreyedOut);
}
[Fact]
public void Parse_WrongOpcode_Throws()
{