Parse and route the complete 0x0264 guid/fraction/valid response, send exact 0x0263 item-mana queries, and reproduce retail meter visibility plus guid-zero cancellation for mana and health selection changes. Keep the behavior in Core state and the retained selected-object controller with wire/state/UI conformance coverage. Co-Authored-By: Codex <codex@openai.com>
127 lines
4.7 KiB
C#
127 lines
4.7 KiB
C#
using System;
|
|
using System.Buffers.Binary;
|
|
using System.Text;
|
|
using AcDream.Core.Net.Messages;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Net.Tests.Messages;
|
|
|
|
public sealed class SocialActionsTests
|
|
{
|
|
[Fact]
|
|
public void BuildQueryHealth_HasOpcode0x01BFAndGuid()
|
|
{
|
|
byte[] body = SocialActions.BuildQueryHealth(seq: 3, targetGuid: 0xCAFE);
|
|
Assert.Equal(SocialActions.QueryHealthOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(0xCAFEu,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildQueryItemMana_HasOpcode0x0263AndGuid()
|
|
{
|
|
// CM_Item::Event_QueryItemMana @ 0x006A8610: F7B1, seq, 0x0263, guid.
|
|
byte[] body = SocialActions.BuildQueryItemMana(seq: 4, itemGuid: 0x50000A01u);
|
|
|
|
Assert.Equal(16, body.Length);
|
|
Assert.Equal(SocialActions.GameActionEnvelope,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body));
|
|
Assert.Equal(4u, BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(4)));
|
|
Assert.Equal(SocialActions.QueryItemManaOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(0x50000A01u,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildPingRequest_HasOpcode0x01E9()
|
|
{
|
|
byte[] body = SocialActions.BuildPingRequest(seq: 1, clientId: 42);
|
|
Assert.Equal(SocialActions.PingRequestOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(42u,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildFellowshipCreate_StringThenBools()
|
|
{
|
|
byte[] body = SocialActions.BuildFellowshipCreate(
|
|
seq: 1, fellowshipName: "Team", openness: true, shareXp: false);
|
|
|
|
Assert.Equal(SocialActions.FellowshipCreateOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
// String at offset 12: u16 length = 4
|
|
ushort len = BinaryPrimitives.ReadUInt16LittleEndian(body.AsSpan(12));
|
|
Assert.Equal(4, len);
|
|
Assert.Equal("Team", Encoding.ASCII.GetString(body.AsSpan(14, 4)));
|
|
// string16L record = 2+4=6, pad 2 → advance by 8.
|
|
// Then 2 bools at offset 20,21.
|
|
Assert.Equal(1, body[20]); // openness true
|
|
Assert.Equal(0, body[21]); // shareXp false
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildFellowshipQuit_CarriesDisbandFlag()
|
|
{
|
|
byte[] body = SocialActions.BuildFellowshipQuit(seq: 1, disband: true);
|
|
Assert.Equal(SocialActions.FellowshipQuitOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(1, body[12]);
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildFellowshipDismiss_HasGuid()
|
|
{
|
|
byte[] body = SocialActions.BuildFellowshipDismiss(seq: 1, targetGuid: 0xDEAD);
|
|
Assert.Equal(SocialActions.FellowshipDismissOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(0xDEADu,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildFellowshipRecruit_HasGuid()
|
|
{
|
|
byte[] body = SocialActions.BuildFellowshipRecruit(seq: 1, targetGuid: 0xBEEF);
|
|
Assert.Equal(SocialActions.FellowshipRecruitOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildFellowshipUpdate_HasOpenBool()
|
|
{
|
|
byte[] body = SocialActions.BuildFellowshipUpdate(seq: 1, open: true);
|
|
Assert.Equal(SocialActions.FellowshipUpdateOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
Assert.Equal(1, body[12]);
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildSetCharacterOptions_HasBitmap()
|
|
{
|
|
byte[] body = SocialActions.BuildSetCharacterOptions(seq: 1, optionsBitmap: 0xDEADBEEFu);
|
|
Assert.Equal(0xDEADBEEFu,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildAddChannel_ContainsName()
|
|
{
|
|
byte[] body = SocialActions.BuildAddChannel(seq: 1, channelName: "Trade");
|
|
Assert.Equal(SocialActions.AddChannelOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
ushort len = BinaryPrimitives.ReadUInt16LittleEndian(body.AsSpan(12));
|
|
Assert.Equal(5, len);
|
|
Assert.Equal("Trade", Encoding.ASCII.GetString(body.AsSpan(14, 5)));
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildRemoveChannel_HasOpcode0x0146()
|
|
{
|
|
byte[] body = SocialActions.BuildRemoveChannel(seq: 1, channelName: "General");
|
|
Assert.Equal(SocialActions.RemoveChannelOpcode,
|
|
BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8)));
|
|
}
|
|
}
|