Extracts ClassNetCache data from Unreal Engine 5 games: SerializeInt Max values and per-field handle indices. These values are required by netcode implementations that replicate UE5 network traffic outside the engine.
The pipeline consists of two stages:
- z_construct_parser.py — Static analysis of the game binary (PE) to extract Max values and field indices for all C++ native classes
- MaxExtractor — 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 https://github.com/Mokocoder/UE5_ClassNetCache_Extractor.git
cd UE5_ClassNetCache_Extractor
dotnet build MaxExtractor/MaxExtractor.csproj -c Releasepython z_construct_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 z_construct_parser.py "LyraStarterGame/Binaries/Win64/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 (43.1s)
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": 43.1
},
"seed_values": {
"AIController": 15,
"Actor": 29,
"Character": 35,
...
},
"per_class": {
"Actor": {
"fields_base": 0,
"fields": {
"0": { "name": "RemoteRole", "type": "property" },
"1": { "name": "Owner", "type": "property" },
...
}
},
...
},
"flat_index": {
"Actor::RemoteRole": 0,
"Actor::Owner": 1,
...
}
}MaxExtractor <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 MaxExtractor -c Release -- \
"LyraStarterGame/Saved/StagedBuilds/Windows/LyraStarterGame/Content/Paks" \
lyra_cpp_seed.json \
GAME_UE5_7
[*] Loaded 5523 C++ seed values, 198 field entries
[*] Mounted 6 containers, 9828 files (194ms)
[*] Scanning 3834 packages...
[*] Scan complete: 292 BPs in 3834 packages (1812ms)
[*] 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": 29,
"Character": 35,
...
},
"per_class": {
"Actor": {
"fields_base": 0,
"fields": {
"0": { "name": "RemoteRole", "type": "property" },
...
}
},
...
},
"flat_index": {
"Actor::RemoteRole": 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)
├── z_construct_parser.py # Step 1: PE binary → C++ seed data
├── MaxExtractor/
│ ├── MaxExtractor.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.