Skip to content

Extracts RepLayout data from UE5 binaries and cooked packages

Notifications You must be signed in to change notification settings

Mokocoder/UE5_RepLayout_Extractor

Repository files navigation

UE5 RepLayout Extractor

Extracts RepLayout handle assignments from Unreal Engine 5 games via static analysis of the PE binary and cooked .pak archives. RepLayout handles are required by netcode implementations that replicate UE5 property data outside the engine.

RepLayout handles differ from ClassNetCache field indices:

  • Properties only (no functions)
  • Struct expansion: structs without NetSerializer flatten to sub-field handles
  • ArrayDim expansion: properties with ArrayDim > 1 produce multiple handles

Pipeline:

  1. rep_layout_parser.py — Static analysis of the game binary (PE) to compute RepLayout handle assignments for all C++ native classes
  2. RepLayoutExtractor — Reads cooked .pak archives via CUE4Parse to extract data for Blueprint classes, then merges both into a single output

Requirements

  • Python 3.10+ with pefile
  • .NET 8.0 SDK

Build

git clone --recurse-submodules <repo-url>
cd rep_layout_extractor
dotnet build RepLayoutExtractor/RepLayoutExtractor.csproj -c Release

Usage

Step 1: Extract C++ Seed Data

python rep_layout_parser.py <Game.exe> [output.json] [--detail=Class1,Class2,...]

The --detail flag generates per-handle breakdowns with struct expansion, inheritance chain, and type info. Use --detail or --detail=* for all classes, or --detail=Class1,Class2,... for specific classes.

Example (Lyra Starter Game, UE 5.7):

python rep_layout_parser.py "LyraGame.exe" lyra_rep_layout_seed.json --detail
[*] Loading LyraGame.exe...
[*] ImageBase = 0x140000000
[*] ConstructUClass @ 0x142183CF0  (5523 classes, score=3)
[*] 5523 classes, 5523 named
[*] Parsing properties & computing handle expansion...
[*] Struct types resolved: 65
[*] Built detail maps for 5523 classes
[*] Written 5523 classes → lyra_rep_layout_seed.json (49.9s)

Output format:

{
  "stats": {
    "total_classes": 5523,
    "struct_types_resolved": 65,
    "elapsed_sec": 49.9
  },
  "handle_counts": {
    "Actor": 15,
    "Character": 53,
    ...
  },
  "handle_maps": {
    "Actor": [
      { "h": 1, "name": "bReplicateMovement", "class": "Actor", "type": "bool" },
      { "h": 5, "name": "RemoteRole", "class": "Actor", "type": "byte" },
      { "h": 7, "name": "AttachmentReplication.LocationOffset", "class": "Actor", "type": "struct:Vector_NetQuantize100" },
      { "h": 12, "name": "ReplicatedMovement", "class": "Actor", "type": "struct:RepMovement" },
      ...
    ]
  }
}

Step 2: Merge Blueprint Data

RepLayoutExtractor <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: ./rep_layout.json)

Example (Lyra Starter Game, UE 5.7):

dotnet run --project RepLayoutExtractor -c Release -- \
  "LyraStarterGame/Content/Paks" \
  lyra_rep_layout_seed.json \
  GAME_UE5_7
[*] Loaded 5523 C++ seed classes, 5523 handle maps
[*] Mounted 6 containers, 9828 files (235ms)
[*] Scanning 3834 packages...
[*] Scan complete: 292 BPs in 3834 packages (888ms)
[*] Resolved: 289, Unresolved: 0
[*] BP classes with own rep properties: 11
[*] Written 5812 classes (5523 C++ + 289 BP), 11 with own rep properties → rep_layout.json

Output format:

{
  "stats": {
    "cpp_classes": 5523,
    "bp_classes": 289,
    "resolved": 289,
    "unresolved": 0,
    "with_rep_properties": 11,
    "packages": 3834,
    "skipped": 3542,
    "errors": 0
  },
  "handle_counts": {
    "AbilitySystemComponent": 57,
    "Actor": 15,
    "Character": 53,
    ...
  },
  "handle_maps": {
    "Actor": [
      { "h": 1, "name": "bReplicateMovement", "class": "Actor", "type": "bool" },
      { "h": 6, "name": "AttachmentReplication.AttachParent", "class": "Actor", "type": "object" },
      { "h": 7, "name": "AttachmentReplication.LocationOffset", "class": "Actor", "type": "struct:Vector_NetQuantize100" },
      { "h": 12, "name": "ReplicatedMovement", "class": "Actor", "type": "struct:RepMovement" },
      ...
    ]
  },
  "parent_map": {
    "B_HeroShooter_Mannequin_C": "LyraCharacter",
    ...
  }
}

Notes

  • Unversioned packages: Most shipping builds use unversioned property serialization. In this case, a .usmap mappings 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.

Example Output

The example/ directory contains extraction results from Lyra Starter Game (UE 5.7):

  • lyra_rep_layout_seed.json — 5,523 C++ native classes (handle counts + detail maps for all classes, 65 struct types resolved)
  • lyra_rep_layout.json — 5,812 merged classes (C++ + Blueprint, 11 BP classes with own rep properties)

Project Structure

├── pe_analyzer.py                      # Shared PE binary analysis module
├── rep_layout_parser.py                # Step 1: PE binary → C++ seed data
├── RepLayoutExtractor/
│   ├── RepLayoutExtractor.csproj
│   └── Program.cs                      # Step 2: .pak archives → merged output
├── CUE4Parse/                          # Git submodule
└── example/
    ├── lyra_rep_layout_seed.json
    └── lyra_rep_layout.json

License

This project uses CUE4Parse (Apache-2.0) as a git submodule.

About

Extracts RepLayout data from UE5 binaries and cooked packages

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published