Modern open-source C# .NET 10 Asheron's Call client. Faithful port of retail client behaviour to Silk.NET with a plugin API.
Find a file
Erik 18e308fe85 feat(net): PacketHeader + PacketHeaderFlags + Hash32 checksum (Phase 4.2)
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>
2026-04-11 14:17:37 +02:00
docs/plans docs(plan): Phase 3c terrain blending plan 2026-04-10 23:43:04 +02:00
src feat(net): PacketHeader + PacketHeaderFlags + Hash32 checksum (Phase 4.2) 2026-04-11 14:17:37 +02:00
tests feat(net): PacketHeader + PacketHeaderFlags + Hash32 checksum (Phase 4.2) 2026-04-11 14:17:37 +02:00
.gitignore chore: phase 0 — skeleton + dat asset inventory 2026-04-10 09:02:56 +02:00
AcDream.slnx feat(net): AcDream.Core.Net scaffold + ISAAC keystream (Phase 4.1) 2026-04-11 14:14:28 +02:00
CLAUDE.md docs(claude): project goal + lead-developer operating instructions 2026-04-11 13:39:21 +02:00
README.md chore: phase 0 — skeleton + dat asset inventory 2026-04-10 09:02:56 +02:00

acdream

Experimental modern open-source Asheron's Call client in C# / .NET 10.

Status: pre-alpha, not playable. Phase 0 only — dat file asset inventory.

Stack: .NET 10, Chorizite.DatReaderWriter for dat parsing. Silk.NET + Avalonia planned for rendering/UI (not yet wired up).

Requires: A retail Asheron's Call install (Turbine/Microsoft property — supply your own). Set ACDREAM_DAT_DIR environment variable to the directory containing client_portal.dat, client_cell_1.dat, client_highres.dat, and client_local_English.dat, or pass it as the first CLI argument.

Layout

  • src/AcDream.Cli/ — console app that dumps asset counts from a dat directory
  • references/ — local read-only reference material (ACE, ACViewer, WorldBuilder, DatReaderWriter, holtburger, retail AC install). Gitignored.

Run

dotnet run --project src/AcDream.Cli -- "C:\path\to\Asheron's Call"

Or set ACDREAM_DAT_DIR and run without args.