diff --git a/tests/AcDream.Core.Net.Tests/Messages/AceWireWriter.cs b/tests/AcDream.Core.Net.Tests/Messages/AceWireWriter.cs
new file mode 100644
index 00000000..0b08c637
--- /dev/null
+++ b/tests/AcDream.Core.Net.Tests/Messages/AceWireWriter.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AcDream.Core.Net.Tests.Messages;
+
+///
+/// Test-only faithful mirror of ACE's server-side wire writer, so golden-byte
+/// conformance tests generate their fixtures the same way the authoritative
+/// server generates them. Hand-rolled hex would only prove that our parser
+/// agrees with whoever typed the hex; generating from the oracle's own
+/// algorithm proves it agrees with the server.
+///
+///
+/// Every primitive below is a line-for-line port of
+/// ACE/Source/ACE.Server/Network/Extensions.cs (read 2026-07-29 from
+/// the ACE checkout). Cited line numbers are that file's:
+///
+///
+/// - CalculatePadMultiple — Extensions.cs:10
+/// - WriteString16L — Extensions.cs:12-21
+/// - WritePackedDword — Extensions.cs:23-34
+/// - Pad — Extensions.cs:51
+/// - Align — Extensions.cs:55-58
+/// - WriteGuid — Extensions.cs:121 (writes guid.Full, a u32)
+///
+///
+///
+/// ACE's underlying is little-endian for
+/// the fixed-width overloads, which is what Write(uint),
+/// Write(ushort) and Write(float) reproduce here.
+///
+///
+internal sealed class AceWireWriter
+{
+ private readonly List _buffer = new();
+
+ public int Length => _buffer.Count;
+
+ /// ACE Extensions.cs:10.
+ private static uint CalculatePadMultiple(uint length, uint multiple)
+ => multiple * ((length + multiple - 1u) / multiple) - length;
+
+ /// BinaryWriter.Write(uint) — little-endian.
+ public AceWireWriter Write(uint value)
+ {
+ _buffer.Add((byte)(value & 0xFF));
+ _buffer.Add((byte)((value >> 8) & 0xFF));
+ _buffer.Add((byte)((value >> 16) & 0xFF));
+ _buffer.Add((byte)((value >> 24) & 0xFF));
+ return this;
+ }
+
+ /// BinaryWriter.Write(ushort) — little-endian.
+ public AceWireWriter Write(ushort value)
+ {
+ _buffer.Add((byte)(value & 0xFF));
+ _buffer.Add((byte)((value >> 8) & 0xFF));
+ return this;
+ }
+
+ /// BinaryWriter.Write(float) — little-endian IEEE-754.
+ public AceWireWriter Write(float value)
+ => Write((uint)BitConverter.SingleToInt32Bits(value));
+
+ ///
+ /// ACE Extensions.cs:121 — WriteGuid writes the full 32-bit
+ /// guid with no packing.
+ ///
+ public AceWireWriter WriteGuid(uint guid) => Write(guid);
+
+ ///
+ /// ACE Extensions.cs:12-21. Writes a u16 length, the CP1252 bytes,
+ /// then pads so that (2 + length) is a multiple of 4 — the comment in ACE
+ /// reads "client expects string length to be a multiple of 4 including the
+ /// 2 bytes for length".
+ ///
+ public AceWireWriter WriteString16L(string? data)
+ {
+ data ??= "";
+ byte[] bytes = Encoding.GetEncoding(1252).GetBytes(data);
+ Write((ushort)data.Length);
+ _buffer.AddRange(bytes);
+ return Pad(CalculatePadMultiple(sizeof(ushort) + (uint)data.Length, 4u));
+ }
+
+ /// ACE Extensions.cs:23-34.
+ public AceWireWriter WritePackedDword(uint value)
+ {
+ if (value <= 32767)
+ return Write((ushort)value);
+
+ uint packed = (value << 16) | ((value >> 16) | 0x8000);
+ return Write(packed);
+ }
+
+ /// ACE Extensions.cs:51.
+ public AceWireWriter Pad(uint pad)
+ {
+ for (uint i = 0; i < pad; i++)
+ _buffer.Add(0);
+ return this;
+ }
+
+ /// ACE Extensions.cs:55-58 — pad the stream to a 4-byte boundary.
+ public AceWireWriter Align() => Pad(CalculatePadMultiple((uint)_buffer.Count, 4u));
+
+ public byte[] ToArray() => _buffer.ToArray();
+
+ ///
+ /// Start a top-level GameMessage body: the 4-byte opcode, exactly as
+ /// ACE.Server.Network.GameMessages.GameMessage's constructor writes
+ /// it before the per-message payload.
+ ///
+ public static AceWireWriter GameMessage(uint opcode)
+ => new AceWireWriter().Write(opcode);
+
+ ///
+ /// Start a GameEvent body (top-level opcode 0xF7B0), mirroring
+ /// ACE/Source/ACE.Server/Network/GameEvent/GameEventMessage.cs:21-25:
+ /// WriteGuid(guid), Write(session.GameEventSequence++),
+ /// Write((uint)EventType).
+ ///
+ public static AceWireWriter GameEvent(uint guid, uint eventSequence, uint eventType)
+ => new AceWireWriter()
+ .Write(0xF7B0u)
+ .WriteGuid(guid)
+ .Write(eventSequence)
+ .Write(eventType);
+}
diff --git a/tests/AcDream.Core.Net.Tests/Messages/PlayScriptGoldenTests.cs b/tests/AcDream.Core.Net.Tests/Messages/PlayScriptGoldenTests.cs
new file mode 100644
index 00000000..64a36ed3
--- /dev/null
+++ b/tests/AcDream.Core.Net.Tests/Messages/PlayScriptGoldenTests.cs
@@ -0,0 +1,142 @@
+using System;
+using AcDream.Core.Net.Messages;
+using Xunit;
+
+namespace AcDream.Core.Net.Tests.Messages;
+
+///
+/// Golden-byte conformance for the two inbound script-playback GameMessages:
+/// PlayScriptId (0xF754) and PlayEffect (0xF755).
+///
+/// Oracle derivation. Bytes are generated by
+/// (a faithful mirror of ACE's
+/// Extensions.cs writers).
+///
+/// For 0xF755, ACE's
+/// GameMessages/Messages/GameMessageScript.cs writes:
+///
+/// Writer.WriteGuid(guid); // u32
+/// Writer.Write((uint)scriptId); // u32
+/// Writer.Write(speed); // f32, default 1.0f
+///
+/// declaring a 16-byte message (4 opcode + 12 payload), which matches
+/// .
+///
+/// For 0xF754, ACE names the opcode PlayScriptId
+/// (GameMessageOpcode.cs:63) and the retail handler is
+/// SmartBox::HandlePlayScriptID (0x00452020) — guid + script DID, no
+/// intensity, giving the 12-byte body
+/// asserts.
+///
+public class PlayScriptGoldenTests
+{
+ // ---- 0xF754 PlayScriptId -------------------------------------------------
+
+ public static TheoryData ScriptIdCases() => new()
+ {
+ { 0x50000001u, 0x0D000001u }, // player, a portal-space script DID
+ { 0x7C95B01Au, 0x00000000u }, // zero DID must survive as zero, not null
+ { 0xFFFFFFFFu, 0xFFFFFFFFu }, // full-width guid + DID
+ };
+
+ [Theory]
+ [MemberData(nameof(ScriptIdCases))]
+ public void PlayScriptId_AceGoldenBytes_DecodesGuidAndDid(uint guid, uint scriptDid)
+ {
+ byte[] body = AceWireWriter.GameMessage(PlayPhysicsScript.Opcode)
+ .WriteGuid(guid)
+ .Write(scriptDid)
+ .ToArray();
+
+ Assert.Equal(PlayPhysicsScript.WireSize, body.Length);
+
+ PlayPhysicsScript? parsed = PlayPhysicsScript.TryParse(body);
+
+ Assert.NotNull(parsed);
+ Assert.Equal(guid, parsed!.Value.Guid);
+ Assert.Equal(scriptDid, parsed.Value.ScriptDid);
+ }
+
+ [Fact]
+ public void PlayScriptId_WrongOpcode_ReturnsNull()
+ {
+ byte[] body = AceWireWriter.GameMessage(0xF755u)
+ .WriteGuid(1u).Write(2u).ToArray();
+
+ Assert.Null(PlayPhysicsScript.TryParse(body));
+ }
+
+ [Fact]
+ public void PlayScriptId_TrailingByte_ReturnsNull()
+ {
+ // The parser demands an exact length; a 13-byte body is not a
+ // truncated-but-usable 0xF754.
+ byte[] body = AceWireWriter.GameMessage(PlayPhysicsScript.Opcode)
+ .WriteGuid(1u).Write(2u).Pad(1).ToArray();
+
+ Assert.Null(PlayPhysicsScript.TryParse(body));
+ }
+
+ // ---- 0xF755 PlayEffect ---------------------------------------------------
+
+ public static TheoryData ScriptTypeCases() => new()
+ {
+ // ACE's default speed argument is 1.0f.
+ { 0x50000001u, 0x00000021u, 1.0f },
+ // Intensity is a free float on the wire; fractional values must survive.
+ { 0x7C95B01Au, 0x00000083u, 0.25f },
+ // Zero intensity is meaningful (script suppressed), not "absent".
+ { 0x800114C0u, 0x00000001u, 0f },
+ // Unknown type values are retained losslessly for the resolver to reject.
+ { 0xA9B40001u, 0xDEADBEEFu, -3.5f },
+ };
+
+ [Theory]
+ [MemberData(nameof(ScriptTypeCases))]
+ public void PlayEffect_AceGoldenBytes_DecodesGuidTypeAndIntensity(
+ uint guid, uint rawScriptType, float intensity)
+ {
+ byte[] body = AceWireWriter.GameMessage(PlayPhysicsScriptType.Opcode)
+ .WriteGuid(guid)
+ .Write(rawScriptType)
+ .Write(intensity)
+ .ToArray();
+
+ // ACE declares GameMessageScript's length as 16.
+ Assert.Equal(PlayPhysicsScriptType.WireSize, body.Length);
+ Assert.Equal(16, body.Length);
+
+ PlayPhysicsScriptType? parsed = PlayPhysicsScriptType.TryParse(body);
+
+ Assert.NotNull(parsed);
+ Assert.Equal(guid, parsed!.Value.Guid);
+ Assert.Equal(rawScriptType, parsed.Value.RawScriptType);
+ Assert.Equal(intensity, parsed.Value.Intensity);
+ }
+
+ [Fact]
+ public void PlayEffect_NonFiniteIntensity_IsRetainedLosslessly()
+ {
+ // The parser documents that non-finite floats are kept for the
+ // resolver to reject rather than being coerced at parse time.
+ byte[] body = AceWireWriter.GameMessage(PlayPhysicsScriptType.Opcode)
+ .WriteGuid(0x50000001u)
+ .Write(0x00000021u)
+ .Write(float.NaN)
+ .ToArray();
+
+ PlayPhysicsScriptType? parsed = PlayPhysicsScriptType.TryParse(body);
+
+ Assert.NotNull(parsed);
+ Assert.True(float.IsNaN(parsed!.Value.Intensity));
+ }
+
+ [Fact]
+ public void PlayEffect_WrongOpcode_ReturnsNull()
+ {
+ byte[] body = AceWireWriter.GameMessage(0xF754u)
+ .WriteGuid(1u).Write(2u).Write(1.0f).ToArray();
+
+ Assert.Null(PlayPhysicsScriptType.TryParse(body));
+ }
+}
diff --git a/tests/AcDream.Core.Net.Tests/Messages/VectorUpdateGoldenTests.cs b/tests/AcDream.Core.Net.Tests/Messages/VectorUpdateGoldenTests.cs
new file mode 100644
index 00000000..6164690b
--- /dev/null
+++ b/tests/AcDream.Core.Net.Tests/Messages/VectorUpdateGoldenTests.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Numerics;
+using AcDream.Core.Net.Messages;
+using Xunit;
+
+namespace AcDream.Core.Net.Tests.Messages;
+
+///
+/// Golden-byte conformance for inbound VectorUpdate (0xF74E).
+///
+/// Oracle derivation. Bytes are generated by
+/// , a faithful mirror of ACE's
+/// Extensions.cs writers, driven in the exact order that
+/// ACE/Source/ACE.Server/Network/GameMessages/Messages/GameMessageVectorUpdate.cs
+/// writes them:
+///
+/// Writer.WriteGuid(worldObject.Guid); // u32
+/// Writer.Write(velocity); // 3 x f32
+/// Writer.Write(omega); // 3 x f32
+/// Writer.Write(... ObjectInstance); // u16
+/// Writer.Write(... ObjectVector); // u16
+///
+/// ACE declares the message length as 36 bytes (4 opcode + 32 payload),
+/// which matches 's 4 + 32 guard.
+/// Cross-checked against holtburger's client-side reader for the same
+/// opcode (crates/holtburger-protocol/src/messages/).
+///
+public class VectorUpdateGoldenTests
+{
+ private static byte[] Golden(
+ uint guid,
+ Vector3 velocity,
+ Vector3 omega,
+ ushort instanceSequence,
+ ushort vectorSequence)
+ => AceWireWriter.GameMessage(VectorUpdate.Opcode)
+ .WriteGuid(guid)
+ .Write(velocity.X).Write(velocity.Y).Write(velocity.Z)
+ .Write(omega.X).Write(omega.Y).Write(omega.Z)
+ .Write(instanceSequence)
+ .Write(vectorSequence)
+ .ToArray();
+
+ public static TheoryData Cases() => new()
+ {
+ // A remote player jumping: +Z velocity, no spin.
+ { "jump", 0x50000001u, new Vector3(0f, 0f, 6.1f), Vector3.Zero, 355, 42 },
+ // Running with a heading change: planar velocity plus yaw omega.
+ { "run+turn", 0x7C95B01Au, new Vector3(2.94f, -1.25f, 0f), new Vector3(0f, 0f, 1.5f), 1, 2 },
+ // Rest state — every field zero except the sequences.
+ { "at-rest", 0x800114C0u, Vector3.Zero, Vector3.Zero, 0, 0 },
+ // Negative components on every axis, to pin sign handling.
+ { "negatives", 0xA9B40001u, new Vector3(-1f, -2f, -3f), new Vector3(-4f, -5f, -6f), 65535, 65534 },
+ };
+
+ [Theory]
+ [MemberData(nameof(Cases))]
+ public void TryParse_AceGoldenBytes_DecodesEveryFieldExactly(
+ string label,
+ uint guid,
+ Vector3 velocity,
+ Vector3 omega,
+ ushort instanceSequence,
+ ushort vectorSequence)
+ {
+ byte[] body = Golden(guid, velocity, omega, instanceSequence, vectorSequence);
+
+ // ACE's GameMessageVectorUpdate declares length 36 (opcode + payload).
+ Assert.Equal(36, body.Length);
+
+ VectorUpdate.Parsed? parsed = VectorUpdate.TryParse(body);
+
+ Assert.NotNull(parsed);
+ Assert.Equal(guid, parsed!.Value.Guid);
+ Assert.Equal(velocity, parsed.Value.Velocity);
+ Assert.Equal(omega, parsed.Value.Omega);
+ Assert.Equal(instanceSequence, parsed.Value.InstanceSequence);
+ Assert.Equal(vectorSequence, parsed.Value.VectorSequence);
+ Assert.False(string.IsNullOrEmpty(label));
+ }
+
+ [Fact]
+ public void TryParse_WrongOpcode_ReturnsNull()
+ {
+ byte[] body = AceWireWriter.GameMessage(0xF74Cu)
+ .WriteGuid(1u)
+ .Write(0f).Write(0f).Write(0f)
+ .Write(0f).Write(0f).Write(0f)
+ .Write((ushort)0).Write((ushort)0)
+ .ToArray();
+
+ Assert.Null(VectorUpdate.TryParse(body));
+ }
+
+ [Fact]
+ public void TryParse_TruncatedByOneByte_ReturnsNull()
+ {
+ byte[] body = Golden(1u, Vector3.One, Vector3.One, 1, 1);
+ Assert.Null(VectorUpdate.TryParse(body.AsSpan(0, body.Length - 1)));
+ }
+}