Skip to content

01 — Setup

Before any netcode, a Godot 4 project needs the lattice GDExtension, which is two things dropped into an addons/lattice/ folder:

  1. the lattice.gdextension manifest (tells Godot which native library to load and which symbol to call), and
  2. the native binaries — the extension itself (liblattice_godot.*, the node layer) and the Lattice core it loads (liblattice.so / lattice.dll).

The manifest registers the LatticeRunner and LatticeSync node types; the extension P/Invokes into the core. Without the native binaries the node types simply won't appear in Godot.

Verified against: bindings/lattice-godot/lattice.gdextension, bindings/lattice-godot/README.md ("Building the real extension").

Requirements

  • Godot 4.2 or newer. The manifest declares compatibility_minimum = "4.2"; the sample project's project.godot targets 4.2.
    Verified against: bindings/lattice-godot/lattice.gdextension:10, samples/godot-tictactoe/godot/project.godot:14.
  • A build of the GDExtension and the Lattice core for each platform you ship (see step 2).
  • To build the extension yourself: godot-cpp (the C++ bindings) checked out at branch 4.2.

1. The addon layout

Copy the manifest and binaries into your project's addons/lattice/ directory. The expected shape:

addons/lattice/ in your Godot project
addons/lattice/
├── lattice.gdextension        # the manifest Godot loads at startup
└── bin/
    ├── liblattice_godot.linux.template_debug.x86_64.so     # the GDExtension (node layer)
    ├── liblattice_godot.linux.template_release.x86_64.so
    ├── liblattice_godot.windows.template_debug.x86_64.dll
    ├── liblattice_godot.windows.template_release.x86_64.dll
    ├── liblattice.so                                        # the Lattice core (Linux)
    └── lattice.dll                                          # the Lattice core (Windows)

Verified against: samples/godot-tictactoe/godot/addons/lattice/bin/README.md, bindings/lattice-godot/lattice.gdextension:13-28.

The manifest

lattice.gdextension is a plain INI-style descriptor. The two things that matter: entry_symbol (the function the native library exports) and one library line per platform/arch. The core is listed under [dependencies] so Godot loads it next to the extension:

addons/lattice/lattice.gdextension
[configuration]
entry_symbol = "lattice_godot_library_init"
compatibility_minimum = "4.2"
reloadable = true

[libraries]
linux.debug.x86_64     = "res://addons/lattice/bin/liblattice_godot.linux.template_debug.x86_64.so"
linux.release.x86_64   = "res://addons/lattice/bin/liblattice_godot.linux.template_release.x86_64.so"
windows.debug.x86_64   = "res://addons/lattice/bin/liblattice_godot.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://addons/lattice/bin/liblattice_godot.windows.template_release.x86_64.dll"
macos.debug            = "res://addons/lattice/bin/liblattice_godot.macos.template_debug.framework"
macos.release          = "res://addons/lattice/bin/liblattice_godot.macos.template_release.framework"

[dependencies]
linux.debug.x86_64     = { "res://addons/lattice/bin/liblattice.so" : "" }
windows.debug.x86_64   = { "res://addons/lattice/bin/lattice.dll" : "" }

Verified against: bindings/lattice-godot/lattice.gdextension:8-28 (abridged; the file lists both debug and release core dependencies).

entry_symbol must match the function defined in src/register_types.cpp, which registers the two node classes at the SCENE initialization level:

register_types.cpp — what entry_symbol points at
ClassDB::register_class<LatticeRunner>();
ClassDB::register_class<LatticeSync>();

Verified against: bindings/lattice-godot/src/register_types.cpp:21-25,35-45.

2. Get the native binaries

The binaries are not committed to the repo, for two reasons: the node layer needs godot-cpp + Godot 4.2+ to build (neither is in the reference environment), and shipping prebuilt engine binaries inside a code sample is undesirable. You build them once per platform.

Verified against: samples/godot-tictactoe/godot/addons/lattice/bin/README.md (lines 16-23).

Build the GDExtension (where godot-cpp is available)

From the binding directory, clone godot-cpp, build it once, then build the extension with SConstruct, pointing LATTICE_CORE at a prebuilt core:

Build the extension
cd bindings/lattice-godot
git clone -b 4.2 https://github.com/godotengine/godot-cpp
( cd godot-cpp && scons platform=linux target=template_debug )        # build bindings once
LATTICE_CORE=../../reference/build scons platform=linux target=template_debug

The produced liblattice_godot.*.so/.dll lands under demo/addons/lattice/bin/. Copy it and the prebuilt core (reference/build/liblattice.so / lattice.dll) into your project's addons/lattice/bin/, then restart the Godot editor.

Verified against: bindings/lattice-godot/README.md:173-186 ("Building the real extension"), samples/godot-tictactoe/godot/addons/lattice/bin/README.md:27-38.

Windows / macOS variants

Re-run scons with platform=windows or platform=macos (and the matching godot-cpp build) for each target, then drop each library into bin/ alongside the matching core (lattice.dll on Windows). The binding code is identical across platforms because it targets the stable C ABI.
Verified against: bindings/lattice-godot/lattice.gdextension:13-28 (per-platform library lines), bindings/lattice-godot/README.md:180-186.

3. Verify the netcode without the editor

The Godot editor and godot-cpp are not installed in the reference environment, so the node/scene side cannot be run here. What is run — and is the load-bearing proof — is the netcode itself, exercised through the binding's godot-cpp-independent glue layer by a headless C++ harness. You can run it to confirm your core build works before touching Godot:

Headless netcode proof
cd samples/godot-tictactoe
bash harness/build.sh                              # native (g++) build + run, loopback transport
LATTICE_TRANSPORT=udp ./harness/out/ttt_harness    # same match over real localhost UDP

A healthy run reports (this environment): 60 checks, 0 failures, exit 0 on both native Linux (g++ 11) and Windows cross (mingw + wine), including over the UDP transport.

Verified against: samples/godot-tictactoe/README.md ("Run it", "Latest result: 60 checks, 0 failures, exit 0"), samples/godot-tictactoe/harness/build.sh:15-16.

You can also run the binding's own compile-check, which exercises the exact glue path the node layer routes through (schema build, spawn/dirty/tick, RPC pack/unpack, the stats snapshot):

cd bindings/lattice-godot
bash compile_check/build_check.sh

Verified against: bindings/lattice-godot/README.md:150-166 ("Compile-check", native + wine PASS).

What this proves and what it doesn't

The harness proves the netcode and rules — connect, spawn + replication, authoritative validation, chat over events — through the same glue the nodes use. It does not run the Godot nodes, scenes, or GDScript (no editor here). The node layer (lattice_runner.cpp / lattice_sync.cpp) is authored + documented; you run it by building the extension and opening the project in Godot 4.2+.
Verified against: samples/godot-tictactoe/README.md ("What is verified HEADLESSLY" vs "What needs the Godot editor + godot-cpp").


Next: 02 — Your first runner, where you add a LatticeRunner node and start a host and a client.