fix(ui): port live experience quality updates (#217)
Parse retail PrivateUpdatePropertyInt64 and route authoritative Total/Available Experience through both local-player projections so Attributes, the level meter, and Skills refresh together. Preserve the existing retail XP curve and right-align the Total XP value. Close the user-confirmed item-give gate for #216 and record the named-retail/ACE/holtburger conformance evidence. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
30d294506c
commit
84b7d2d7cd
15 changed files with 391 additions and 29 deletions
|
|
@ -0,0 +1,49 @@
|
|||
using System.Buffers.Binary;
|
||||
using AcDream.Core.Net.Messages;
|
||||
|
||||
namespace AcDream.Core.Net.Tests.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// Golden layout from retail
|
||||
/// <c>CM_Qualities::DispatchUI_PrivateUpdateInt64 @ 0x006AEAD0</c>,
|
||||
/// cross-checked against ACE and holtburger.
|
||||
/// </summary>
|
||||
public sealed class PrivateUpdatePropertyInt64Tests
|
||||
{
|
||||
private static byte[] Build(
|
||||
uint property,
|
||||
long value,
|
||||
byte sequence = 1,
|
||||
uint opcode = PrivateUpdatePropertyInt64.Opcode)
|
||||
{
|
||||
var body = new byte[PrivateUpdatePropertyInt64.BodySize];
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(body, opcode);
|
||||
body[4] = sequence;
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(5), property);
|
||||
BinaryPrimitives.WriteInt64LittleEndian(body.AsSpan(9), value);
|
||||
return body;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1u, 1_234_567_890L)]
|
||||
[InlineData(2u, 987_654_321L)]
|
||||
[InlineData(6u, -1L)]
|
||||
public void TryParse_RetailBody_ReturnsSignedPropertyValue(uint property, long value)
|
||||
{
|
||||
var parsed = PrivateUpdatePropertyInt64.TryParse(Build(property, value, sequence: 0x7B));
|
||||
|
||||
Assert.NotNull(parsed);
|
||||
Assert.Equal(property, parsed.Value.Property);
|
||||
Assert.Equal(value, parsed.Value.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParse_WrongOpcode_ReturnsNull()
|
||||
=> Assert.Null(PrivateUpdatePropertyInt64.TryParse(
|
||||
Build(1u, 100L, opcode: 0x02D0u)));
|
||||
|
||||
[Fact]
|
||||
public void TryParse_Truncated_ReturnsNull()
|
||||
=> Assert.Null(PrivateUpdatePropertyInt64.TryParse(
|
||||
new byte[PrivateUpdatePropertyInt64.BodySize - 1]));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue