acdream/tests/AcDream.Core.Tests/Meshing/TranslucencyKindTests.cs
Erik a71db90310 feat(net): Phase 6.6 — parse UpdateMotion (0xF74C) into MotionUpdated event
Server sends UpdateMotion whenever an entity's motion state changes:
NPCs starting a walk cycle, creatures switching to a combat stance,
doors opening, a player waving, etc. Phase 6.1-6.4 already handles
rendering different (stance, forward-command) pairs for the INITIAL
CreateObject, but without this message NPCs freeze in whatever pose
they spawned with and never transition to walking/fighting.

Added UpdateMotion.TryParse with the same ServerMotionState the
CreateObject path uses, reached via a slightly different outer
layout (guid + instance seq + header'd MovementData; the MovementData
starts with the 8-byte sequence/autonomous header this time rather
than being preceded by a length field). Only the (stance, forward-
command) pair is extracted — same subset CreateObject grabs.

WorldSession dispatches MotionUpdated(guid, state) when a 0xF74C
body parses successfully. The App-side wiring (guid→entity lookup
and AnimatedEntity cycle swap) is intentionally deferred to a
separate commit because it touches GameWindow which is currently
being edited by the Phase 9.1 translucent-pass work.

89 Core.Net tests (was 83, +6 for UpdateMotion coverage).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:33:26 +02:00

81 lines
4 KiB
C#

using AcDream.Core.Meshing;
using DatReaderWriter.Enums;
namespace AcDream.Core.Tests.Meshing;
/// <summary>
/// Verifies that <see cref="TranslucencyKindExtensions.FromSurfaceType"/> maps
/// SurfaceType flag combinations to the correct <see cref="TranslucencyKind"/>
/// according to the documented priority order:
/// Additive &gt; InvAlpha &gt; AlphaBlend (Alpha|Translucent) &gt; ClipMap &gt; Opaque
/// </summary>
public class TranslucencyKindTests
{
// ── Opaque cases ────────────────────────────────────────────────────────
[Fact]
public void Opaque_FromZeroFlags_ReturnsOpaque()
=> Assert.Equal(TranslucencyKind.Opaque, TranslucencyKindExtensions.FromSurfaceType((SurfaceType)0));
[Fact]
public void Opaque_FromBase1SolidFlag_ReturnsOpaque()
=> Assert.Equal(TranslucencyKind.Opaque, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Base1Solid));
[Fact]
public void Opaque_FromBase1ImageFlag_ReturnsOpaque()
=> Assert.Equal(TranslucencyKind.Opaque, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Base1Image));
// ── ClipMap cases ───────────────────────────────────────────────────────
[Fact]
public void ClipMap_FromBase1ClipMapFlag_ReturnsClipMap()
=> Assert.Equal(TranslucencyKind.ClipMap, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Base1ClipMap));
[Fact]
public void ClipMap_WithOtherOpaqueFlags_ReturnsClipMap()
=> Assert.Equal(TranslucencyKind.ClipMap,
TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Base1ClipMap | SurfaceType.Gouraud));
// ── AlphaBlend cases ────────────────────────────────────────────────────
[Fact]
public void AlphaBlend_FromAlphaFlag_ReturnsAlphaBlend()
=> Assert.Equal(TranslucencyKind.AlphaBlend, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Alpha));
[Fact]
public void AlphaBlend_FromTranslucentFlag_ReturnsAlphaBlend()
=> Assert.Equal(TranslucencyKind.AlphaBlend, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Translucent));
[Fact]
public void AlphaBlend_FromAlphaAndTranslucentFlags_ReturnsAlphaBlend()
=> Assert.Equal(TranslucencyKind.AlphaBlend,
TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Alpha | SurfaceType.Translucent));
[Fact]
public void AlphaBlend_AlphaWithClipMap_AlphaWins()
=> Assert.Equal(TranslucencyKind.AlphaBlend,
TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Alpha | SurfaceType.Base1ClipMap));
// ── InvAlpha cases ──────────────────────────────────────────────────────
[Fact]
public void InvAlpha_FromInvAlphaFlag_ReturnsInvAlpha()
=> Assert.Equal(TranslucencyKind.InvAlpha, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.InvAlpha));
[Fact]
public void InvAlpha_InvAlphaBeatsAlpha()
=> Assert.Equal(TranslucencyKind.InvAlpha,
TranslucencyKindExtensions.FromSurfaceType(SurfaceType.InvAlpha | SurfaceType.Alpha));
// ── Additive cases ──────────────────────────────────────────────────────
[Fact]
public void Additive_FromAdditiveFlag_ReturnsAdditive()
=> Assert.Equal(TranslucencyKind.Additive, TranslucencyKindExtensions.FromSurfaceType(SurfaceType.Additive));
[Fact]
public void Additive_AdditiveBeatsAllOther()
=> Assert.Equal(TranslucencyKind.Additive,
TranslucencyKindExtensions.FromSurfaceType(
SurfaceType.Additive | SurfaceType.InvAlpha | SurfaceType.Alpha | SurfaceType.Base1ClipMap));
}