99 lines
2.9 KiB
C#
99 lines
2.9 KiB
C#
using System.Buffers.Binary;
|
|
using System.Text;
|
|
using AcDream.Core.Items;
|
|
using AcDream.Core.Net.Messages;
|
|
|
|
namespace AcDream.Core.Net.Tests.Messages;
|
|
|
|
public sealed class CreateObjectTests
|
|
{
|
|
[Fact]
|
|
public void TryParse_WeenieHeaderPrefix_ReturnsNameAndItemType()
|
|
{
|
|
byte[] body = BuildMinimalCreateObjectWithWeenieHeader(
|
|
guid: 0x50000002u,
|
|
name: "Drudge",
|
|
itemType: (uint)ItemType.Creature);
|
|
|
|
var parsed = CreateObject.TryParse(body);
|
|
|
|
Assert.NotNull(parsed);
|
|
Assert.Equal(0x50000002u, parsed.Value.Guid);
|
|
Assert.Equal("Drudge", parsed.Value.Name);
|
|
Assert.Equal((uint)ItemType.Creature, parsed.Value.ItemType);
|
|
}
|
|
|
|
private static byte[] BuildMinimalCreateObjectWithWeenieHeader(
|
|
uint guid,
|
|
string name,
|
|
uint itemType)
|
|
{
|
|
var bytes = new List<byte>();
|
|
WriteU32(bytes, CreateObject.Opcode);
|
|
WriteU32(bytes, guid);
|
|
|
|
// ModelData header: marker, subpalette count, texture count, animpart count.
|
|
bytes.Add(0x11);
|
|
bytes.Add(0);
|
|
bytes.Add(0);
|
|
bytes.Add(0);
|
|
|
|
// PhysicsData: no flags, empty physics state, then 9 sequence stamps.
|
|
WriteU32(bytes, 0);
|
|
WriteU32(bytes, 0);
|
|
for (int i = 0; i < 9; i++)
|
|
WriteU16(bytes, 0);
|
|
Align4(bytes);
|
|
|
|
// Fixed WeenieHeader prefix per ACE SerializeCreateObject.
|
|
WriteU32(bytes, 0); // weenieFlags
|
|
WriteString16L(bytes, name);
|
|
WritePackedDword(bytes, 0x1234); // WeenieClassId
|
|
WritePackedDword(bytes, 0); // IconId via known-type writer
|
|
WriteU32(bytes, itemType);
|
|
WriteU32(bytes, 0); // ObjectDescriptionFlags
|
|
Align4(bytes);
|
|
|
|
return bytes.ToArray();
|
|
}
|
|
|
|
private static void WriteU32(List<byte> bytes, uint value)
|
|
{
|
|
Span<byte> tmp = stackalloc byte[4];
|
|
BinaryPrimitives.WriteUInt32LittleEndian(tmp, value);
|
|
bytes.AddRange(tmp.ToArray());
|
|
}
|
|
|
|
private static void WriteU16(List<byte> bytes, ushort value)
|
|
{
|
|
Span<byte> tmp = stackalloc byte[2];
|
|
BinaryPrimitives.WriteUInt16LittleEndian(tmp, value);
|
|
bytes.AddRange(tmp.ToArray());
|
|
}
|
|
|
|
private static void WritePackedDword(List<byte> bytes, uint value)
|
|
{
|
|
if (value <= 0x7FFF)
|
|
{
|
|
WriteU16(bytes, (ushort)value);
|
|
return;
|
|
}
|
|
|
|
WriteU16(bytes, (ushort)(((value >> 16) & 0x7FFF) | 0x8000));
|
|
WriteU16(bytes, (ushort)(value & 0xFFFF));
|
|
}
|
|
|
|
private static void WriteString16L(List<byte> bytes, string value)
|
|
{
|
|
byte[] encoded = Encoding.GetEncoding(1252).GetBytes(value);
|
|
WriteU16(bytes, checked((ushort)encoded.Length));
|
|
bytes.AddRange(encoded);
|
|
Align4(bytes);
|
|
}
|
|
|
|
private static void Align4(List<byte> bytes)
|
|
{
|
|
while ((bytes.Count & 3) != 0)
|
|
bytes.Add(0);
|
|
}
|
|
}
|