Configuration - Aukio 3D
Table of Contents
1. One YAML file for the whole family
All Aukio programs — the engine, the workspace application, and environment plugins — share a single configuration file:
~/.config/aukio/config.yaml
A missing file is not an error: every setting falls back to its
built-in default. Override the location with
-Daukio.config=/path/to.yaml (the legacy -De3d.config= is honored
as a fallback for engine-only tooling).
The file is divided into sections, one per tenant, with flat camelCase keys inside each:
e3d: # the engine (this page) ipdCm: 6.3 telemetryIntervalSeconds: 10 fo4: # the Fallout 4 environment plugin path: /home/you/games/Fallout 4 app: # the workspace application state: ... # written by the app at runtime
Keys a consumer does not recognize are preserved verbatim through writes, so sections can evolve independently.
2. Engine keys
The engine reads its settings through EngineConfig, a thin facade
over the shared file. Every key can also be set as a system
property, and the property always wins:
Config key (e3d section) |
System property | Default | Controls |
|---|---|---|---|
ipdCm |
-De3d.ipd |
6.5 | interpupillary distance for stereo rendering |
bugReportDir |
-De3d.bugreport.dir |
~/.local/share/aukio/bugreports |
where bug reports are written |
logDir |
-De3d.log.dir |
~/.cache/aukio/logs |
persistent rolling log location |
telemetryIntervalSeconds |
-De3d.telemetry.interval |
5 | seconds between telemetry log lines |
giStage2Radius |
-De3d.gi.stage2Radius |
0 (unlimited) | GI centroid-bounce bubble radius (world units) |
giStage3Radius |
-De3d.gi.stage3Radius |
0 (unlimited) | GI coarse-lightmap bubble radius; also enables mesh-block lightmaps when > 0 |
giStage4Radius |
-De3d.gi.stage4Radius |
0 (unlimited) | GI fine-refinement bubble radius |
giMeshUnitsPerTexel |
-De3d.gi.meshUnitsPerTexel |
2.1 | mesh-block lightmap texel density at final resolution |
giLightmapCacheEntries |
-De3d.gi.lightmapCacheEntries |
65536 | cap on the baked-lightmap cache (stream-out survival) |
Figure 1: Resolution order for every engine key: the system property wins; otherwise the config file; otherwise the built-in default.
So a permanent preference goes in the file, a one-off experiment on the command line:
java -De3d.ipd=6.3 -jar my-app.jar # this run only
3. Live reload and safe writes
Reads check the file's (mtime, size, file-key) stamp and re-parse only when it changed — a hand edit made while an application is running becomes visible on the next read, with no restart and no polling cost when nothing changed.
Writes (an application storing a setting at runtime) go through
AukioConfig.setString and friends, and are engineered so that
concurrent human edits survive:
Figure 2: The write path. The sidecar lock serializes cooperating processes; the fresh re-read under the lock means a hand edit made between the writer's read and write is merged, not clobbered.
Two honest limitations:
- SnakeYAML rewrites the whole file on the first
set, so human-written header comments are lost once an application writes. Keep conventions in documentation, not in the file's comments. - An editor saving a stale buffer over newer YAML is the one race no file format can solve — your editor's changed-on-disk warning (Emacs has one) is the only guard.
Instances are cached per resolved path in a per-JVM registry:
AukioConfig.get() returns the same instance to every caller in the
process (engine, app, plugins), so the stamp cache is shared and a
re-parse happens at most once per change per JVM.
4. Writing a consumer
import eu.svjatoslav.aukio.cfg.AukioConfig; // read (dotted path, caller-supplied fallback): double ipd = AukioConfig.get().getDouble("e3d.ipdCm", 6.5); String dir = AukioConfig.get().getString("e3d.logDir", "~/.cache/aukio/logs"); // write (locks, re-reads, merges, atomic rename): AukioConfig.get().setString("e3d.ipdCm", "6.3");
The class is covered by AukioConfigTest (9 tests) in the engine
repository, including the concurrent-write and unknown-key
preservation behavior.