Skip to main content

Overview

FFXIVClientStructs is a community effort to reverse engineer the object layout of native classes in Final Fantasy XIV. This library provides C# representations of native game structures and functions for use with Dalamud and other third-party tools.

Prerequisites

Required Knowledge

  • C# and .NET: Understanding of C# structs, pointers, and unsafe code
  • Reverse Engineering: Familiarity with IDA Pro or Ghidra for analyzing game binaries
  • C++ Knowledge: Understanding of C++ class layouts, vtables, and memory layout
  • Game Architecture: FFXIV is built with MSVC 64-bit compiler

Required Tools

  • .NET SDK: Version required by the project (check the .csproj files)
  • IDA Pro or Ghidra: For reverse engineering and finding signatures
  • Git: For version control and submitting pull requests
  • Visual Studio or Rider: Recommended IDEs with C# support

Development Setup

Cloning the Repository

git clone https://github.com/aers/FFXIVClientStructs.git
cd FFXIVClientStructs

Building the Project

The solution file is located at source/FFXIVClientStructs.sln.
cd source
dotnet build FFXIVClientStructs.sln

Project Structure

  • FFXIVClientStructs/: Main library with game struct definitions
  • InteropGenerator/: Source generator for function wrappers
  • InteropGenerator.Runtime/: Runtime support and attributes
  • InteropGenerator.Tests/: Tests for the generator
  • FFXIVClientStructs.ResolverTester/: Test project for signature resolution
  • FFXIVClientStructs.StdContainerTester/: Test project for STD containers
  • ida/: Rename database for IDA Pro and Ghidra

Code Style Guidelines

Struct Layout Requirements

All native game classes must follow these rules:
  1. Explicit Layout: Use [StructLayout(LayoutKind.Explicit, Size = 0xXXX)]
  2. Unsafe Marking: Mark the struct unsafe if it contains unsafe members (pointers, etc.)
  3. Partial Keyword: Use partial when using source generators
  4. FieldOffset: Every field must have a [FieldOffset(0xXX)] attribute

Naming Conventions

Struct Names

  • Official Names First: Use official RTTI names from the rename database when available
  • Descriptive Names: For new classes without RTTI, use descriptive, appropriate names
  • Namespace: Follow the game’s namespace structure (e.g., FFXIVClientStructs.FFXIV.Component.GUI)
Example:
namespace FFXIVClientStructs.FFXIV.Component.GUI;

// Component::GUI::AtkUnitBase
//   Component::GUI::AtkEventListener
[GenerateInterop(isInherited: true)]
[Inherits<AtkEventListener>]
[StructLayout(LayoutKind.Explicit, Size = 0x238)]
public unsafe partial struct AtkUnitBase : ICreatable { }

Field Names

  • Use PascalCase for public fields
  • Use descriptive names based on function or known purpose
  • Add comments with the offset in hex: // 0x20
  • Prefix internal backing fields with underscore for arrays: _name, _resNodeArray

Function Names

  • Use PascalCase for method names
  • Use descriptive names that indicate what the function does
  • Follow C# naming conventions, not C++ naming

Comments and Documentation

  • Add namespace comments showing the C++ hierarchy:
    // Client::Game::Character::Character
    //   Client::Game::Object::GameObject
    //   Client::Game::Character::CharacterData
    
  • Document important fields with XML comments
  • Include warnings for fields that should be used with caution
  • Add <remarks> tags for additional context

Pull Request Process

Before Submitting

  1. Build Successfully: Ensure dotnet build succeeds without errors
  2. Test Your Changes: Use the test projects to verify struct layouts
  3. Verify Signatures: Test that signatures resolve correctly
  4. Check Formatting: Follow the code style guidelines
  5. Update Tests: Add tests if introducing new generator features

PR Guidelines

  1. Clear Description: Explain what you’re adding or fixing
  2. Reference Issues: Link related issues if applicable
  3. Small PRs: Keep changes focused and reviewable
  4. One Feature Per PR: Don’t mix unrelated changes
  5. Follow Conventions: Maintain consistency with existing code

PR Title Format

  • Add [StructName] - For new structs
  • Update [StructName] - For updates to existing structs
  • Fix [StructName].[FunctionName] - For bug fixes
  • Add functions to [StructName] - For adding functions

What to Include

  • New struct definitions with all known fields
  • Member and virtual functions with valid signatures
  • Comments showing the C++ class hierarchy
  • FieldOffsets for all fields
  • Proper attributes ([GenerateInterop], [Inherits], etc.)

What to Avoid

  • Don’t commit secrets or credentials (.env, credentials.json, etc.)
  • Don’t submit PRs with failing builds
  • Don’t include unrelated formatting changes
  • Don’t use placeholder/dummy values
  • Don’t skip testing your changes

Struct Layout Best Practices

Required Attributes

[GenerateInterop(isInherited: true)]  // If struct has inheritance
[Inherits<BaseClass>]                 // For each base class
[StructLayout(LayoutKind.Explicit, Size = 0xXXX)]
[VirtualTable("signature", offset)]  // If struct has virtual functions
public unsafe partial struct MyStruct { }

ICreatable Interface

Add ICreatable if the struct:
  • Has a Ctor function
  • Is a UI object you might want to create
  • Should be creatable via game allocators
public unsafe partial struct AtkUnitBase : ICreatable {
    [MemberFunction("E8 ?? ?? ?? ?? 33 D2 48 8D 9F")]
    public partial void Ctor();
}

Size Determination

Getting the exact struct size:
  1. From RTTI: Check the RTTI information in IDA/Ghidra
  2. From Constructor: Look at memory allocation in constructors
  3. From Last Field: Calculate from the last known field offset + field size
  4. Best Estimate: If unsure, use your best estimate and add a comment

Testing Changes

See the Testing Guide for detailed information on:
  • Building the project
  • Running test projects
  • Verifying struct layouts
  • Testing signatures
  • Validating function definitions

Getting Help

  • GitHub Issues: Report bugs or ask questions
  • Pull Requests: For discussions about proposed changes
  • Dalamud Discord: Community support and discussion

Additional Resources

Build docs developers (and LLMs) love