No description
  • C# 85%
  • Python 15%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-12 19:42:23 +01:00
tests feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
tools/Extractor feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
.gitattributes feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
.gitignore feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
AGENTS.md feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
manifest.json feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
packetIds.json feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
protos.proto feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00
README.md feat: reconstruct named client protocols 2026-11-12 19:42:23 +01:00

wuwa-protos

Reconstruct named Wuthering Waves protobuf definitions and packet IDs from the installed PC client's Aki.Protocol.dll. The extractor reads metadata and serialization IL; it never loads or executes the game assembly.

The generated artifacts are at the repository root:

  • protos.proto: messages, fields, enums, oneofs, optional presence, maps, and repeated fields with their actual packing settings.
  • packetIds.json: numeric packet ID to canonical message name, from EMessageId.
  • manifest.json: game/resource versions, assembly MVID, SHA-256 hashes, and counts.

The current snapshot targets game 3.8.0, resources 3.8.9.

Extract an update

Requires the .NET 10 SDK (or a newer SDK supporting net10.0) and protoc on PATH. NuGet dependencies are pinned in tools/Extractor/packages.lock.json. Use dotnet restore tools/Extractor --locked-mode for a locked restore.

From this repository:

dotnet run --project tools/Extractor -- --game 'C:/Games/Wuthering Waves/Client'

--game is the Client directory containing Content/Paks. The extractor mounts base and downloaded patch archives and selects the latest protocol assembly, comparing resource versions numerically. It infers the game and resource versions from that archive. If the assembly is only in a base PAK, provide --game-version explicitly.

PAK AES keys come from the public wuwa-keys endpoint by default. Use --keys keys.json or --keys <URL> to override it. The file format is {"mainKey":"...","dynamicKeys":[{"guid":"...","key":"..."}]}. Keys are never written to the outputs. Extraction stops if any archive cannot be mounted, since an unreadable patch could contain a newer protocol.

An already extracted DLL also works, including the client's prefixed PE format:

dotnet run --project tools/Extractor -- --assembly Aki.Protocol.dll --game-version 3.8.0 --resource-version 3.8.9

--output <directory> changes the output directory. --protoc <path> or the PROTOC environment variable selects the compiler. --check reconstructs, compiles, and compares all three artifacts without replacing them. It needs the same version/source arguments used for the snapshot; when using --game these are inferred automatically:

dotnet run --project tools/Extractor -- --game 'C:/Games/Wuthering Waves/Client' --check

The extracted DLL is cached in .cache/ and is ignored by Git. DLLs, private keys, and packet captures do not belong in this repository.

Stable naming and validation

Names come directly from managed type names, property names, and field-number constants. Packet IDs are regenerated independently of those names. Scalar types come from Write* and FieldCodec.For* calls, preserving distinctions such as int32 versus sint32 or fixed32. The extractor checks serialized field tags against the field constants. Oneof case enums identify membership; Has<Field> properties identify optional presence.

Proto names are flattened for package-less consumers such as Spectrum. Generated nested ENUMS types include their containing type in the name; enum values are prefixed to satisfy protobuf's file-level enum scoping. Namespace-qualified names resolve type collisions deterministically. Enums missing zero get a synthetic zero value, and aliases are preserved.

Unsupported metadata, ambiguous names, invalid IDs, missing serialization evidence, tag disagreements, and protoc failures stop generation before the pinned artifacts are replaced. If a future client removes readable names or changes its code generator, update the extractor; it deliberately does not guess names from payload shapes. This tool does not extract RSA keys.

Mornye Tools

This repository is the data/wuwa-protos submodule in Mornye Tools. From the Mornye Tools root, extract and publish its build snapshot with:

bun run update:protos --game 'C:/Games/Wuthering Waves/Client'

That command validates hashes and the schema, copies the three artifacts to src-tauri/protocol/, and updates data/VERSION.json. Rust builds generate packet constants from that snapshot, so consumers use message names instead of hard-coded IDs. Normal app builds need neither this private checkout nor .NET/the installed game. Changes to message semantics can still require app converter changes.

Tests

python -S tests/run.py

The integration tests generate and compile a synthetic C# assembly using real protoc/Google.Protobuf. They check all scalar encodings, packing, maps, enums, oneofs, optional presence, prefixed assemblies, deterministic output, failed input preservation, and a simulated patch changing an ID and field number. No game installation or account capture is needed.