View on GitHub

FOnline Engine

Flexible cross-platform isometric game engine

Generated API and Metadata

This document explains the engine code-generation and metadata-registration flow. Use it when changing generated source, metadata annotations, property definitions, or script-visible API contracts.

Ownership model

The engine owns the reusable metadata/codegen machinery. An embedding project supplies project configuration, extra metadata sources, common headers, and script/content inputs through CMake options and project files.

Generated files are build artifacts. Document the source annotations, templates, generator inputs, and validation flow; do not treat generated output as hand-authored engine source.

Source paths inspected

CMake codegen stage

BuildTools/cmake/stages/Codegen.cmake constructs the generator command and output list.

Important command arguments include:

The stage creates normal and forced code-generation command targets and appends CodeGeneration to FO_GEN_DEPENDENCIES.

Generated outputs

Codegen.cmake declares generated outputs under GeneratedSource/, including:

These file names are useful for understanding build flow, but changes should usually be made in templates, annotations, metadata sources, or generator scripts rather than in generated output.

Metadata registration entry points

Hand-authored declarations live in Source/Common/MetadataRegistration.h:

Source/Common/MetadataRegistration-Template.cpp is the template used to generate side-specific registration files. It contains code-generation markers such as ///@ CodeGen RegisterHelpers and ///@ CodeGen Register.

Source/Common/GenericCode-Template.cpp is the template for generated common code.

Engine hook tags

Project/native extension code can mark selected C++ functions with ///@ EngineHook. BuildTools/codegen.py validates hook names and emits no-op stubs for hooks that the embedding project does not implement. Current hook names recognized by the generator are:

ClientStartupSettingsHook is called by app entry points immediately before constructing a client engine. Use it for project-owned startup setting adjustments; do not use it as a gameplay authority bypass.

ApplicationShutdownHook is a native lifecycle hook for project-owned process integrations that must be stopped before a client runtime DLL is unloaded. It is intentionally not part of the compatibility hash because it does not change script metadata, saved data, or the network contract.

Dynamic metadata

Source/Common/MetadataRegistration.cpp implements RegisterDynamicMetadata(). It reads binary metadata sections and dispatches them into typed registration steps such as:

This is the runtime side of metadata that can be loaded from generated/baked data rather than compiled static registration alone.

Migration rules are generic (kind, extra-info, target → replacement) remaps with transitive resolution, authored as ///@ MigrationRule <Kind> .... Beyond Proto/Property (applied at proto lookup and property-name resolution), the Enum kind is consulted by PropertiesSerializator when a persisted enum value name no longer resolves on load: the rule remaps the old name to a current value — for scalar enum properties and enum dict keys — instead of throwing EnumResolveException. This keeps removed/renamed enum values from bricking old saves.

Properties and generated contracts

Source/Common/Properties.h and Source/Common/Properties.cpp define the property runtime model used by entities and metadata. Key concepts include:

When property metadata changes, inspect both the property runtime and the generator inputs/templates. Script-visible nullability or API changes should also update Scripting.md, ScriptMethodsMap.md, and Nullability.md as applicable.

Public API relationship

../PUBLIC_API.md documents public build/API knobs such as build toggles and project helper functions like resource/package additions. Keep public API docs high-level and stable; put generator internals here.

Metadata and baker relationship

Metadata generation and metadata baking are related but not identical:

For resource baking details, see BakingPipeline.md.

Tests to inspect

Relevant tests include:

If a generated script API change is involved, inspect AngelScript-related tests as well.

Change routing

Validation checklist

  1. Configure from an embedding project root so project metadata sources are available.
  2. Run normal code generation and verify generated files are updated as expected.
  3. Run forced code generation when generator caching/dependency behavior changes.
  4. Build the smallest target that compiles the generated files.
  5. Run metadata/property tests relevant to the change.
  6. If metadata is baked, run the relevant baker test and bake target.
  7. Update docs that expose changed public contracts, especially Scripting.md, ScriptMethodsMap.md, Nullability.md, and ../PUBLIC_API.md when applicable.