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.

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]

Example (Lyra Starter Game, UE 5.7):

python rep_layout_parser.py "LyraGame.exe" lyra_rep_layout_seed.json
[*] Loading LyraGame.exe...
[*] ImageBase = 0x140000000
[*] ConstructUClass targets: 0x142362C20(5516), 0x142362C80(273)  (5789 total classes, score=3)
[*] FClassParams bitfield @ 0x38  (deps=0x18 funcs=0x20 props=0x28)
[*] FFunctionParams.FunctionFlags @ 0x28  (score=62/66)
[*] FPropertyParamsBase: validated OK
[*] FStructParams: validated OK (e.g. struct 'StructCookedMetaDataStore')
[*] Detected offsets: ...
[*] 5789 classes, 5516 named
[*] Parsing properties & computing handle expansion...
[*] Pass 2: fixed 1 parent chains via secondary groups
[*] Struct types resolved: 74
[*] Built detail maps for 5516 classes
[*] Written 5789 classes -> lyra_rep_layout_seed.json (44.0s)

Output format:

{
  "stats": {
    "total_classes": 5789,
    "struct_types_resolved": 74,
    "elapsed_sec": 44.0
  },
  "handle_counts": {
    "Actor": 15,
    "Character": 48,
    ...
  },
  "handle_maps": {
    "Actor": [
      { "h": 1, "name": "bReplicateMovement", "class": "Actor", "type": "bool" },
      { "h": 5, "name": "RemoteRole", "class": "Actor", "type": "byte", "enum": "ENetRole", "max": 5 },
      { "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 Optional .usmap mappings file (needed only for some 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 5789 C++ seed classes, 5516 handle maps
[*] Mounted 6 containers, 8499 files (190ms)
[*] Scanning 3826 packages...
[*] Scan complete: 292 BPs in 3826 packages (475ms)
[*] Skipped 3534 packages (no BP exports), 0 errors
[*] Resolved: 289, Unresolved: 0
[*] BP classes with own rep properties: 11
[*] Written 6078 classes (5789 C++ + 289 BP), 11 with own rep properties -> rep_layout.json

Output format:

{
  "stats": {
    "cpp_classes": 5789,
    "bp_classes": 289,
    "resolved": 289,
    "unresolved": 0,
    "with_rep_properties": 11,
    "packages": 3826,
    "skipped": 3534,
    "errors": 0
  },
  "handle_counts": {
    "AbilitySystemComponent": 18,
    "Actor": 15,
    "Character": 48,
    ...
  },
  "handle_maps": {
    "Actor": [
      { "h": 1, "name": "bReplicateMovement", "class": "Actor", "type": "bool" },
      { "h": 5, "name": "RemoteRole", "class": "Actor", "type": "byte", "enum": "ENetRole", "max": 5 },
      { "h": 6, "name": "AttachmentReplication.AttachParent", "class": "Actor", "type": "object" },
      { "h": 12, "name": "ReplicatedMovement", "class": "Actor", "type": "struct:RepMovement" },
      ...
    ]
  },
  "parent_map": {
    "B_HeroShooter_Mannequin_C": "LyraCharacter",
    ...
  }
}

Notes

  • Unversioned packages: If package metadata is unversioned and mappings are not embedded, provide a .usmap file for Step 2. Otherwise it can be omitted.
  • UE version support: Struct offsets are auto-detected from the binary. Tested on UE 5.7.

Example Output

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

  • lyra_rep_layout_seed.json — 5,789 C++ native classes (handle counts + detail maps for named classes, 74 struct types resolved)
  • lyra_rep_layout.json — 6,078 merged classes (C++ + Blueprint, 11 BP classes with own rep properties)

Project Structure

├── pe_analyzer.py                      # Shared PE binary analysis module
├── layout_detector.py                  # Auto-detect struct offsets from Construct* code patterns
├── 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