Outbound GameActions for XP-spending + combat-mode-change. These complete the wire surface for the character-sheet UI: the player clicks "spend XP on Strength," the panel calls BuildRaiseAttribute, the session sends it, the server responds with updated PlayerDescription or PrivateUpdateAttribute GameEvents. Wire layer: - BuildRaiseAttribute (0x0045): attrId u32, xpSpent u64. - BuildRaiseVital (0x0044): vitalId u32, xpSpent u64. - BuildRaiseSkill (0x0046): skillId u32, xpSpent u64. - BuildTrainSkill (0x0047): skillId u32, credits u32 (note: credits is u32 here, NOT u64 like the xpSpent variants). - BuildChangeCombatMode (0x0053): mode enum as u32 (Undef=0, NonCombat=1, Melee=2, Missile=3, Magic=4, Peaceful=5). Tests (5 new): byte-exact encoding of each, including the Train/ Raise size difference due to u32 vs u64 payloads. Build green, 621 tests pass (up from 616). Ref: r08 §3 rows 0x0044 / 0x0045 / 0x0046 / 0x0047 / 0x0053. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
60 lines
2.2 KiB
C#
60 lines
2.2 KiB
C#
using System;
|
|
using System.Buffers.Binary;
|
|
using AcDream.Core.Net.Messages;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Net.Tests.Messages;
|
|
|
|
public sealed class CharacterActionsTests
|
|
{
|
|
[Fact]
|
|
public void BuildRaiseAttribute_HasOpcode0x0045AndXp64()
|
|
{
|
|
byte[] body = CharacterActions.BuildRaiseAttribute(seq: 1, attrId: 5, xpSpent: 12345678);
|
|
Assert.Equal(24, body.Length);
|
|
Assert.Equal(CharacterActions.RaiseAttributeOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(5u,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
Assert.Equal(12345678u,
|
|
BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(16)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildRaiseVital_HasOpcode0x0044()
|
|
{
|
|
byte[] body = CharacterActions.BuildRaiseVital(seq: 1, vitalId: 1, xpSpent: 100);
|
|
Assert.Equal(CharacterActions.RaiseVitalOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildRaiseSkill_HasOpcode0x0046()
|
|
{
|
|
byte[] body = CharacterActions.BuildRaiseSkill(seq: 1, skillId: 8, xpSpent: 500);
|
|
Assert.Equal(CharacterActions.RaiseSkillOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildTrainSkill_U32CreditsNotU64()
|
|
{
|
|
byte[] body = CharacterActions.BuildTrainSkill(seq: 1, skillId: 8, credits: 4);
|
|
Assert.Equal(20, body.Length); // 12 + 4 + 4 vs 16 for 4+8
|
|
Assert.Equal(CharacterActions.TrainSkillOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(4u,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(16)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildChangeCombatMode_EnumSerialises()
|
|
{
|
|
byte[] body = CharacterActions.BuildChangeCombatMode(
|
|
seq: 1, CharacterActions.CombatMode.Melee);
|
|
Assert.Equal(CharacterActions.ChangeCombatModeOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(2u, // Melee = 2
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
}
|