feat(core): adopt retail's SoundType catalog; retire AC2D
SoundId was not a subset of retail's table, the way its comment claimed. It was an invention: 23 acdream-local names on acdream-local values, and the values were wrong in the way that matters. FootstepDefault = 0x02 is retail's Random. SwingSword = 0x10 is retail's Death2. Death = 0x60 is retail's Explode. Anyone who reached for one of those names to compare against a wire or dat value would have got a different sound. Nothing referenced any of them by name -- grep for `SoundId.` across src and tests returns nothing -- so this was a trap rather than a live defect, the same shape the enum campaign found in DamageType. All 22 invented names are deleted and retail's 205 replace them. Three oracles agree exactly, on every name and every value: retail acclient.h:4569 enum SoundType, ACE's Sound, and DatReaderWriter's Sound. The third matters most. AudioHookSink already resolves SoundTable lookups through DatReaderWriter.Enums.Sound, so that is the enum acdream actually reads at runtime; our catalog now agrees with the values already flowing through the dat path, and a conformance test pins the two so they cannot drift apart. On the "206 sounds" figure: retail's block holds 207 entries, being 205 sounds followed by NUM_SOUND_TYPES = 0xCD and FORCE_SoundType_32_BIT. The first is a count and the second a width pin. Counting the former is where 206 came from. Neither is a member here, matching how the campaign treated NUM_ATTACK_HEIGHTS and Num_HoldKeys -- a count is not a value the wire can carry. Behaviour is unchanged and could not be otherwise: the enum had no consumers. IAudioEngine's three SoundId overloads are no-op stubs and the live path takes wave ids and DatReaderWriter values. The user's separate report that sound is "not working that good" is a triggering, selection and attenuation question rather than a catalog one, and is filed as its own Bucket B row in the post-Vulkan intake. Also in this commit, by user decision: AC2D is retired as a reference. Its clone and directory are gone and it must not be re-cloned. Everything we took from it still stands and is written down -- the FSplitNESW terrain split constants, the 0xF61C movement packet layout, the finding that a client need not compute terrain Z itself -- so CLAUDE.md's reference list, its hierarchy table, and the architecture doc's protocol row now point at docs/research/2026-04-12-movement-deep-dive.md rather than erasing the history. The reference count drops from six to five. Core tests 3907 passed / 2 skipped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f27ad9ee43
commit
39c1737bda
7 changed files with 601 additions and 58 deletions
30
CLAUDE.md
30
CLAUDE.md
|
|
@ -1473,8 +1473,8 @@ already-running ACE session via the handshake race.
|
|||
|
||||
## Reference repos: cross-check the relevant ones
|
||||
|
||||
The `references/` tree holds **six** vendored projects (ACE, ACViewer,
|
||||
WorldBuilder, Chorizite.ACProtocol, holtburger, AC2D). They overlap in
|
||||
The `references/` tree holds **five** vendored projects (ACE, ACViewer,
|
||||
WorldBuilder, Chorizite.ACProtocol, holtburger). They overlap in
|
||||
some areas and disagree in others. Before committing to an approach,
|
||||
**cross-reference at least two of them** for the domain you're working
|
||||
in — the per-domain hierarchy in the next section tells you which to
|
||||
|
|
@ -1483,7 +1483,7 @@ the relevant references is almost always the truth. The user has
|
|||
repeatedly had to remind me about this when I narrowly searched one ref
|
||||
and missed obvious answers in another.
|
||||
|
||||
The six references:
|
||||
The five references:
|
||||
|
||||
- **`references/ACE/`** — ACEmulator server. Authority on the wire
|
||||
protocol (packet framing, ISAAC, game message opcodes, serialization
|
||||
|
|
@ -1533,15 +1533,15 @@ The six references:
|
|||
the message-builder layer. ACE shows what the server expects;
|
||||
holtburger shows what a real client actually sends.
|
||||
|
||||
- **`references/AC2D/`** — **C++ AC client emulator.** Oldest reference,
|
||||
fixed-function OpenGL, but has the **real AC terrain split formula**
|
||||
(`FSplitNESW` with constants `0x0CCAC033`, `0x421BE3BD`, `0x6C1AC587`,
|
||||
`0x519B8F25`) which differs from WorldBuilder's physics-path formula.
|
||||
Also has the complete `0xF61C` movement packet format with flag bits
|
||||
and the `stMoveInfo` sequence counters. Key lesson from AC2D: it does
|
||||
NOT do client-side terrain Z — it sends movement keys to the server
|
||||
and uses the server's authoritative Z. See
|
||||
`docs/research/2026-04-12-movement-deep-dive.md` for the full analysis.
|
||||
**AC2D is a retired reference (2026-07-29).** It was a C++ AC client demo
|
||||
and the sixth entry in this list; it is no longer vendored under
|
||||
`references/` and must not be re-cloned. Everything we took from it is
|
||||
already written down and still stands: the terrain split formula
|
||||
`FSplitNESW` (constants `0x0CCAC033`, `0x421BE3BD`, `0x6C1AC587`,
|
||||
`0x519B8F25`), the `0xF61C` movement packet layout, and the finding that a
|
||||
client need not compute terrain Z itself. The historical analysis lives in
|
||||
`docs/research/2026-04-12-movement-deep-dive.md`; the UI dat-id work it fed
|
||||
is in `docs/research/retail-ui/`. Cite those, not the repo.
|
||||
|
||||
### Reference hierarchy by domain
|
||||
|
||||
|
|
@ -1566,9 +1566,9 @@ decompiled client code and would have fixed it in minutes.
|
|||
| **EnvCell / dungeon rendering** (cell geometry, portal visibility, collision mesh) | **WorldBuilder `EnvCellRenderManager.cs` + `PortalRenderManager.cs`** | ACME `EnvCellManager.cs` (more complete for collision); ACViewer `Physics/Common/EnvCell.cs` | WB is acdream's geometry base; ACME for collision until ported. |
|
||||
| **Particles / sky** (particle systems, weather, sky particles) | **WorldBuilder `SkyboxRenderManager.cs` + `ParticleEmitterRenderer.cs` + `ParticleBatcher.cs`** | retail decomp | WB is acdream's particle base. |
|
||||
| **Visibility / culling** (frustum, cell visibility) | **WorldBuilder `VisibilityManager.cs` + `Frustum.cs`** | — | WB. |
|
||||
| **Network protocol** (wire format, packet framing, fragment assembly, ISAAC) | **holtburger** `crates/holtburger-session/` | AC2D `cNetwork.cpp` (simpler, good for cross-check) | ACE shows the server side; holtburger + AC2D show the client side. |
|
||||
| **Client behavior** (what to send when, login flow, ack pattern, keepalive) | **holtburger** `crates/holtburger-core/src/client/` | AC2D `cNetwork.cpp` + `cInterface.cpp` | holtburger is the most complete; AC2D is simpler but confirmed working. |
|
||||
| **Movement** (MoveToState format, AutonomousPosition, sequence counters, speed) | **holtburger** `client/movement/` | AC2D `cNetwork.cpp:2592-2664` (0xF61C format) | See `docs/research/2026-04-12-movement-deep-dive.md` for the full cross-reference. |
|
||||
| **Network protocol** (wire format, packet framing, fragment assembly, ISAAC) | **holtburger** `crates/holtburger-session/` | `docs/research/named-retail/` | ACE shows the server side; holtburger shows the client side. AC2D was the second client-side cross-check here — retired reference; historical analysis remains in `docs/research/2026-04-12-movement-deep-dive.md`. |
|
||||
| **Client behavior** (what to send when, login flow, ack pattern, keepalive) | **holtburger** `crates/holtburger-core/src/client/` | `docs/research/named-retail/` | holtburger is the most complete. AC2D was the simpler confirmed-working cross-check — retired reference; historical analysis remains in `docs/research/2026-04-12-movement-deep-dive.md`. |
|
||||
| **Movement** (MoveToState format, AutonomousPosition, sequence counters, speed) | **holtburger** `client/movement/` | `docs/research/named-retail/` | AC2D `cNetwork.cpp:2592-2664` was the `0xF61C` format secondary — retired reference; historical analysis remains in `docs/research/2026-04-12-movement-deep-dive.md`, which carries the packet layout and the terrain-split formula verbatim. |
|
||||
| **Server expectations** (what ACE accepts/rejects, validation thresholds) | **ACE** `Source/ACE.Server/Network/` | — | Only ACE knows what the server actually validates. |
|
||||
| **Silk.NET / .NET 10 idioms** (GL calls, shader setup, VAO patterns) | **WorldBuilder original** | ACME (same stack) | Both use the same backend; original has cleaner isolated examples. |
|
||||
| **Protocol field order** (packed dwords, type prefixes, flag enums) | **Chorizite.ACProtocol** `Types/*.cs` | holtburger (cross-check) | Generated from protocol XML; has accurate field comments. |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue