Extracts ClassNetCache data (SerializeInt Max values + field indices) from Unreal Engine 5 games via static analysis of the PE binary and cooked .pak archives. These values are required by netcode implementations that replicate UE5 network traffic outside the engine.
Pipeline:
- class_net_cache_parser.py — Static analysis of the game binary (PE) to extract Max values and field indices for all C++ native classes
- ClassNetCacheExtractor — Reads cooked
.pakarchives via CUE4Parse to extract data for Blueprint classes, then merges both into a single output
- Python 3.10+ with
pefile - .NET 8.0 SDK
git clone --recurse-submodules <repo-url>
cd class_net_cache_extractor
dotnet build ClassNetCacheExtractor/ClassNetCacheExtractor.csproj -c Releasepython class_net_cache_parser.py <Game.exe> [output.json]
Scans Z_Construct_UClass static registration stubs in the .text section, identifies ConstructUClass via fingerprint scoring, and computes Max values + field indices by walking the class hierarchy. Tested on UE 5.7.
Example (Lyra Starter Game, UE 5.7):
python class_net_cache_parser.py "LyraGame.exe" lyra_cpp_seed.json
[*] Loading LyraGame.exe...
[*] ImageBase = 0x140000000
[*] ConstructUClass @ 0x142183CF0 (5523 classes, score=3)
[*] Mapping class names...
[*] 5523/5523 names resolved
[*] Parsing class metadata...
[*] Computing Max values and field indices...
[*] Written 5523 Max values + 472 fields (334p + 138f) → lyra_cpp_seed.json (48.6s)
Output format:
{
"stats": {
"total_classes": 5523,
"named": 5523,
"resolved_max": 5523,
"resolved_fields": 198,
"total_fields": 472,
"total_props": 334,
"total_funcs": 138,
"elapsed_sec": 48.6
},
"seed_values": {
"AIController": 15,
"Actor": 11,
"Character": 17,
...
},
"per_class": {
"Actor": {
"fields_base": 0,
"fields": {
"0": { "name": "bReplicateMovement", "type": "property" },
"1": { "name": "bHidden", "type": "property" },
...
}
},
...
},
"flat_index": {
"Actor::bReplicateMovement": 0,
"Actor::bHidden": 1,
...
}
}ClassNetCacheExtractor <PaksDir> <SeedJson> [GameName] [UsmapPath] [OutputPath]
| Argument | Required | Description |
|---|---|---|
PaksDir |
Yes | Directory containing .pak / .utoc / .ucas files |
SeedJson |
Yes | Output from Step 1 |
GameName |
No | CUE4Parse EGame enum value (default: GAME_UE5_7) |
UsmapPath |
No | Path to .usmap mappings file, required for unversioned packages |
OutputPath |
No | Output JSON path (default: ./class_net_cache.json) |
Example (Lyra Starter Game, UE 5.7):
dotnet run --project ClassNetCacheExtractor -c Release -- \
"LyraStarterGame/Content/Paks" \
lyra_cpp_seed.json \
GAME_UE5_7
[*] Loaded 5523 C++ seed values, 198 field entries
[*] Mounted 6 containers, 9828 files (209ms)
[*] Scanning 3834 packages...
[*] Scan complete: 292 BPs in 3834 packages (1968ms)
[*] Resolved: 289, Unresolved: 0
[*] Field indices: 472 C++ + 30 BP = 502 total
[*] Written 5812 Max values (5523 C++ + 289 BP), 502 fields → class_net_cache.json
Output format:
{
"stats": {
"cpp_classes": 5523,
"bp_classes": 289,
"resolved": 5812,
"unresolved": 0,
"total_fields": 502,
"packages": 3834,
"skipped": 3542,
"errors": 0
},
"max_values": {
"AIController": 15,
"Actor": 11,
"Character": 17,
...
},
"per_class": {
"Actor": {
"fields_base": 0,
"fields": {
"0": { "name": "bReplicateMovement", "type": "property" },
...
}
},
...
},
"flat_index": {
"Actor::bReplicateMovement": 0,
...
}
}- Unversioned packages: Most shipping builds use unversioned property serialization. In this case, a
.usmapmappings file is required for Step 2. Use UnrealMappingsDumper to generate one from a running process. - UE version support: Tested on UE 5.7. Other versions may work but are not verified.
The example/ directory contains extraction results from Lyra Starter Game (UE 5.7):
lyra_cpp_seed.json— 5,523 C++ native classes (Max values + 472 field indices)lyra_class_net_cache.json— 5,812 merged classes (C++ + Blueprint, 502 field indices)
├── pe_analyzer.py # Shared PE binary analysis module
├── class_net_cache_parser.py # Step 1: PE binary → C++ seed data
├── ClassNetCacheExtractor/
│ ├── ClassNetCacheExtractor.csproj
│ └── Program.cs # Step 2: .pak archives → merged output
├── CUE4Parse/ # Git submodule
└── example/
├── lyra_cpp_seed.json
└── lyra_class_net_cache.json
This project uses CUE4Parse (Apache-2.0) as a git submodule.