Coding Style
The conventions the code base actually follows, checked against the tree on 2026-11-10. There is no formatter: follow the surrounding file.
Language and layout
- C++23 (
CMAKE_CXX_STANDARD 23, required).[[nodiscard]],constexpr,noexceptandenum classare used freely. - There is no
.clang-formator.editorconfig. Every header starts with#pragma once; indentation is four spaces. - Brace style differs by area:
src/GalaxyEggbert/Game/,Editor/and the host (src/GalaxyEggbertCNA/) put braces on their own line; the voxel container ininclude/GalaxyEggbert/Worlds/opensnamespace GalaxyEggbert::Worlds {on the same line and documents its API with Doxygen/** @brief ... */blocks.
Namespaces
| Namespace | Where | What lives there |
|---|---|---|
GalaxyEggbert | include/GalaxyEggbert/, src/GalaxyEggbert/*.cpp | Record codecs and tables: BlockDefinitionRegistry, MoveObjectRecord, BigDecorRecord, HintZoneRecord, HubDoors |
GalaxyEggbert::Worlds | include/GalaxyEggbert/Worlds/, src/GalaxyEggbert/Worlds/ | The voxel container (World, Chunk, Block, bit packing, binary I/O) |
GalaxyEggbert::Def | include/GalaxyEggbert/Def/ | The original's enums: ObjectType, SoundChannel, GamePhase, BlupiAction... |
GalaxyEggbert::Game | src/GalaxyEggbert/Game/ | The game: BlupiController, InteractionSystem, WorldRuntime, renderers, Hud, InputPad, Sound, SaveData, Autoplay... |
GalaxyEggbert::Editor | src/GalaxyEggbert/Editor/ | The in-game 3D world editor |
GalaxyEggbert::CNA | src/GalaxyEggbertCNA/ | The application host only: GalaxyEggbertGame, main.cpp, Android asset copying |
Header-only helpers often get a nested namespace of their own: Game::CratePush,
Game::BrickEdges, Game::TextMetrics, Editor::AutoTile.
Naming
- Types and member functions are PascalCase (
BlupiController::SettleOnGround,WorldRuntime::TryActivateSwitch), except the voxel container, whose member functions are lower camel case (World::getBlock,saveToFile,blockChangesSince). - Constants start with
k:kMoveSpeed,kCheatsEnabled,kSolidBigDecorIcons. - Data members come in two styles: a trailing underscore (
phase_; the host, the editor,InputPad,SaveData,WorldRuntime,World) and anm_prefix (m_yaw;BlupiController,TerrainRenderer,CameraShake, the shader and effect classes). Use the one the file uses. - No
GEprefix on game-owned or editor-owned names. The classes were renamed (GEWorldRuntimeisWorldRuntime,GETerrainRendererisTerrainRenderer, and so on). A few historic names keep it: the verifier executablesVerifyGE..., the CMake variableGE_SHARED_SOURCES, the object libraryGEEditorVerifySupportand the functionge_add_editor_verify. Do not add new ones, and do not rename those without a reason.
Headers and dependencies
- Public engine-independent headers live in
include/GalaxyEggbert/and are included as<GalaxyEggbert/...>; sibling headers insidesrc/GalaxyEggbert/Game/as"...". - No CNA or cna-engine include in
include/GalaxyEggbert/orsrc/GalaxyEggbert/Worlds/. These use plain floats and standard types, so the world model can be tested without a graphics context. - Many rules are header-only helpers: 45 of the 80 headers in
src/GalaxyEggbert/Game/have no.cpp(for exampleCratePush.hpp,TerrainLighting.hpp,TileCoverage.hpp,DebugOverlay.hpp,FocusNavigator.hpp,SceneEffectsLogic.hpp). Pureinline/constexprfunctions with no GPU make a cheapVerify*test possible; prefer that shape for new logic. - Per-type facts belong in the two registries (BlockDefinitionRegistry,
ObjectDefinitionRegistry), not in
switchstatements spread over files.
Comments cite the original and the ledgers
Comments in this code base are long and carry dates and ids. When you copy behaviour from the
original, cite the reference file and line; when you deviate, say so and point at the ledger row. A real
example, from src/GalaxyEggbert/Game/CratePush.hpp:
namespace GalaxyEggbert::Game::CratePush
{
// How Blupi moves a crate (ObjectType12), from Mobile Eggbert's Decor.cpp (2026-11-01, the
// fidelity audit's GP-crate rows, plans/audit/behavior_differences.md BD-0001):
//
// - While pushing (action Push) he walks CaisseGetMove(5) pixels a 20 Hz tick
// (Decor.cpp:3388/3446); while pulling (Pop) he backs away CaisseGetMove(3) (:3410/3468).
...
// The original's 64-pixel block is one Galaxy cell.
inline constexpr float kPixelsPerCell = 64.0f;
inline constexpr float kOriginalTicksPerSecond = 20.0f;
...
// A 3D adaptation (M3D-0002): a crate that cannot go only because it lies off the lane of its
// move by up to this much across ... first slides into the lane, at the same speed.
When you change behaviour that a comment documents, fix the comment. Some long comments (for example
at the top of SaveData.hpp and GalaxyEggbertGame.hpp) describe earlier states;
trust the code and the ledgers over them.
Determinism
The simulation runs on a fixed 1/60 s tick, and the golden trace, the autoplay playthroughs, the demo replays and the resume feature all depend on it replaying identically. No wall-clock time, unseeded randomness or frame-rate dependence in the simulation. Presentation-only work (the 3D effects, interpolated drawing above 60 frames a second) must leave the simulation untouched.
Generated files and stable IDs
avatars3d/** (model converters), tools/data/blocks.csv
(DumpBlockDefinitions), BoltPaths.hpp, GlueStrands.hpp,
LavaSurfaceData.hpp, plans/inventory/*.md, the generated ledger tables, and every
worlds3d/*.vwr that has a script in tools/worlds/.Def::ObjectType values, block icon
numbers (the index into Content/icons/object-m.png) and sound channel numbers are the
original's and are stored in world files, demos and resume logs.Python
- Python 3, run from the repository root with
python3 tools/...; paths are resolved from__file__; options viaargparse. - A module docstring says what the tool does, how to run it and which brief or ledger it serves (see
tools/levelcheck.pyortools/worlds/world012.py). Some modules, such astools/worldkit.py, start withfrom __future__ import annotations; most world generators do not. - World generators import the kits with the
sys.path.insert(...)+# noqa: E402pattern and seed any randomness (random.Random(12)inworld012.py), so the output is byte-for-byte reproducible. - Third-party dependencies are limited to
numpyandPillow; Blender andffmpegare used as external programs by some asset tools.
Shell
bash with set -u (or set -euo pipefail), a header comment with
the usage that the script prints when called without arguments (sed -n '2,12p' "$0"), paths
derived from BASH_SOURCE, and scratch output in the git-ignored build-probe/
directory of the repository, never /tmp.
Related pages
- Development: rules, ledgers and commit messages
- Testing & QA: how to add a
Verify*test - Project Structure