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
Building the Project
The solution file is located atsource/FFXIVClientStructs.sln.
Project Structure
FFXIVClientStructs/: Main library with game struct definitionsInteropGenerator/: Source generator for function wrappersInteropGenerator.Runtime/: Runtime support and attributesInteropGenerator.Tests/: Tests for the generatorFFXIVClientStructs.ResolverTester/: Test project for signature resolutionFFXIVClientStructs.StdContainerTester/: Test project for STD containersida/: Rename database for IDA Pro and Ghidra
Code Style Guidelines
Struct Layout Requirements
All native game classes must follow these rules:- Explicit Layout: Use
[StructLayout(LayoutKind.Explicit, Size = 0xXXX)] - Unsafe Marking: Mark the struct
unsafeif it contains unsafe members (pointers, etc.) - Partial Keyword: Use
partialwhen using source generators - 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)
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:
- 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
- Build Successfully: Ensure
dotnet buildsucceeds without errors - Test Your Changes: Use the test projects to verify struct layouts
- Verify Signatures: Test that signatures resolve correctly
- Check Formatting: Follow the code style guidelines
- Update Tests: Add tests if introducing new generator features
PR Guidelines
- Clear Description: Explain what you’re adding or fixing
- Reference Issues: Link related issues if applicable
- Small PRs: Keep changes focused and reviewable
- One Feature Per PR: Don’t mix unrelated changes
- Follow Conventions: Maintain consistency with existing code
PR Title Format
Add [StructName]- For new structsUpdate [StructName]- For updates to existing structsFix [StructName].[FunctionName]- For bug fixesAdd 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
ICreatable Interface
AddICreatable if the struct:
- Has a Ctor function
- Is a UI object you might want to create
- Should be creatable via game allocators
Size Determination
Getting the exact struct size:- From RTTI: Check the RTTI information in IDA/Ghidra
- From Constructor: Look at memory allocation in constructors
- From Last Field: Calculate from the last known field offset + field size
- 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