acdream/tests/AcDream.Core.Tests/Physics/MotionCommandResolverTests.cs

57 lines
2.1 KiB
C#

using AcDream.Core.Physics;
using Xunit;
namespace AcDream.Core.Tests.Physics;
/// <summary>
/// Validates MotionCommandResolver — reconstructs the class byte (0x10, 0x13,
/// 0x41, 0x80, etc) from a 16-bit wire value. Without this, the sequencer
/// routes commands to the wrong MotionTable dict and NPC emotes/attacks
/// silently fail.
/// </summary>
public class MotionCommandResolverTests
{
[Theory]
// SubState / Ready / Movement commands
[InlineData(0x0003, 0x41000003u)] // Ready
[InlineData(0x0005, 0x45000005u)] // WalkForward
[InlineData(0x0007, 0x44000007u)] // RunForward
[InlineData(0x0006, 0x45000006u)] // WalkBackward
[InlineData(0x000D, 0x6500000Du)] // TurnRight
[InlineData(0x000E, 0x6500000Eu)] // TurnLeft
[InlineData(0x000F, 0x6500000Fu)] // SideStepRight
[InlineData(0x0015, 0x40000015u)] // Falling
[InlineData(0x0011, 0x40000011u)] // Dead
[InlineData(0x0012, 0x41000012u)] // Crouch
[InlineData(0x0013, 0x41000013u)] // Sitting
[InlineData(0x0014, 0x41000014u)] // Sleeping
// Action-class one-shots: melee attacks, death, portals
[InlineData(0x0057, 0x10000057u)] // Sanctuary (death)
[InlineData(0x0058, 0x10000058u)] // ThrustMed
[InlineData(0x005B, 0x1000005Bu)] // SlashHigh
[InlineData(0x0061, 0x10000061u)] // Shoot
[InlineData(0x004B, 0x1000004Bu)] // Jumpup
[InlineData(0x0050, 0x10000050u)] // FallDown
// ChatEmotes (class 0x13)
[InlineData(0x0087, 0x13000087u)] // Wave
[InlineData(0x0080, 0x13000080u)] // Laugh
[InlineData(0x007D, 0x1300007Du)] // BowDeep
public void ReconstructsKnownCommands(ushort wire, uint expected)
{
uint got = MotionCommandResolver.ReconstructFullCommand(wire);
Assert.Equal(expected, got);
}
[Fact]
public void ZeroWireReturnsZero()
{
Assert.Equal(0u, MotionCommandResolver.ReconstructFullCommand(0));
}
[Fact]
public void UnknownWireReturnsZero()
{
// 0xFFFF is not a real MotionCommand low-16.
Assert.Equal(0u, MotionCommandResolver.ReconstructFullCommand(0xFFFF));
}
}