Adds the 20-byte AC UDP packet header struct + pack/unpack + its
checksum helper, and the Hash32 primitive the checksum uses.
Hash32 (Cryptography/Hash32.cs):
- Seeds accumulator with length << 16
- Sums input as little-endian uint32s word-aligned
- Folds any trailing 1-3 bytes via descending shift (24 → 16 → 8)
- Hand-computed golden values for 4-byte, 5-byte, and each 1/2/3
tail-byte case — no oracle needed, algorithm is simple enough to
verify by tracing
PacketHeader (Packets/PacketHeader.cs):
- Pack/Unpack: Sequence, Flags, Checksum, Id, Time, DataSize, Iteration
(20 bytes, little-endian on the wire)
- CalculateHeaderHash32: substitutes the 0xBADD70DD sentinel for the
Checksum field before hashing (matches AC retail + ACE convention —
without it the checksum would chicken-and-egg on itself). Uses a
local struct copy so the real Checksum isn't mutated on the caller.
- HasFlag for bitmask queries
PacketHeaderFlags (Packets/PacketHeaderFlags.cs):
- Full flag enum from ACE reference: Retransmission, EncryptedChecksum,
BlobFragments, ServerSwitch, ConnectRequest/Response, LoginRequest,
AckSequence, TimeSync, Disconnect, NetError, EchoRequest/Response,
Flow, and friends
Tests (15 new, 20 total in net project, 97 across both projects):
Hash32 (7):
- Empty returns 0
- 4-byte known value (hand-computed from bit layout)
- 5-byte value with one tail byte
- 1/2/3 tail-byte boundary cases (verifies 24/16/8 shift ordering)
- Determinism
PacketHeader (8):
- Pack/Unpack round-trip preserving all 7 fields
- Pack writes little-endian wire format in byte order
- HasFlag single and multi-bit
- CalculateHeaderHash32 invariance under Checksum field changes
(the critical property — verifies the BADD sentinel substitution)
- CalculateHeaderHash32 doesn't mutate
- CalculateHeaderHash32 determinism
- Unpack/Pack size-check throw
User confirmed an ACE server is running on localhost for the future
Phase 4.6 live integration step. Credentials will be read from env
vars at runtime, never committed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
First step of Phase 4 (networking). Adds a new AcDream.Core.Net project
for the AC UDP protocol implementation and a matching AcDream.Core.Net.Tests
project. Keeps networking isolated from rendering and the dat layer,
which also keeps the AGPL-reference-material hygiene cleaner.
AcDream.Core.Net/NOTICE.md documents the attribution policy: we read
ACE's AGPL network code (and holtburger's Rust ac-protocol crate) to
understand AC's wire format, but we reimplement everything in acdream's
own style. Wire-format facts aren't copyrightable; specific code is.
This commit adds one component: IsaacRandom — AC's variant of Bob
Jenkins' ISAAC PRNG, used to XOR a keystream into the CRC field of
every outbound packet for authentication. Clean-room reimplementation
based on reading:
- references/ACE/Source/ACE.Common/Cryptography/ISAAC.cs (AGPL oracle)
- Bob Jenkins' public ISAAC algorithm description
Implementation notes:
- 256 uint32 mm[] state, 256 uint32 rsl[] output buffer, a/b/c regs
- Initialize() runs 4 golden-ratio Mix() warmup rounds then two fold-in
passes over rsl[] and mm[] (fresh instance → both start as zeroes)
- AC variant: seed is exactly 4 bytes, interpreted as little-endian
uint32 assigned to a = b = c before the first Scramble()
- Scramble() produces 256 output words in one pass; Next() consumes
them backwards from offset 255 → 0, re-scrambling at offset -1
- Test seed 0x12345678 matches ACE's reference output byte-for-byte
across the first 16 values (golden vectors transcribed from a
throwaway oracle harness that compiled ACE's ISAAC.cs and printed
its output; the harness was deleted after extracting the values)
Tests (5, all passing):
- Next_Seed12345678_MatchesAceGoldenVectors: 16 golden uint32 values
- Next_TwoInstancesSameSeed_ProduceIdenticalSequence: 1000 outputs
- Next_DifferentSeeds_ProduceDifferentFirstOutput
- Next_512Calls_SpansTwoScrambleBatches: >400 distinct values in 512
outputs (catches all-zero / stuck-at-one bugs at scramble boundary)
- Ctor_ShortSeed_Throws
Both test projects still green: 77 core + 5 net = 82/82.
Phase 4.2 (packet framing + checksum) next.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>