Summary
Add a first-class configuration model for Freven mods and experiences.
The goal is to separate:
- mod package metadata/capabilities
- mod-declared config schema and defaults
- instance/world/user editable config
- experience and stack-level overrides
- resolved runtime config passed to guests through StartInput.config
This would make configuration work for vanilla mods, custom experiences, modpacks, servers, and standalone games without hardcoding gameplay concepts into the engine.
Problem / Motivation
Runtime-loaded Wasm mods can receive StartInput.config, but the long-term configuration ownership model is not clear enough for larger mods, servers, modpacks, custom experiences, and standalone games.
A mod author may want to ship one artifact with tunable settings. Different users or experiences should be able to run the same artifact with different values without rebuilding the Wasm module.
Examples:
- A Life/infection simulation mod wants configurable tick rate, seed, faction count, and mutation budget.
- A tree/ecology mod wants growth speed, decay rules, disease spread, and worldgen integration options.
- A gas simulation mod wants diffusion speed, pressure behavior, visible/invisible gas settings, and performance budgets.
- A server owner wants to tune balance.
- A modpack/experience author wants to override defaults for a specific game mode.
- A standalone game author may not use vanilla at all, but still needs the same config foundation.
Current behavior from testing:
- putting [config] in mod.toml does not populate StartInput.config
- this is expected because mod.toml is treated as manifest/capabilities, not runtime config
- putting [config."yunnwi.infection"] in experience.stack.toml also did not appear to affect StartInput.config
- the mod continued receiving code defaults
The immediate UX issue is stack config, but the larger architectural issue is that Freven needs a stable layered config model that can grow without being rewritten later.
Current state
Current known behavior:
- mod.toml is the mod manifest/capabilities surface
- StartInput.config is intended to come from the resolved per-mod config document from the active experience
- experience.stack.toml is useful for layering mods over freven.vanilla
- stack/layer config does not currently appear to feed into StartInput.config, or the supported path is not obvious
- mods can fall back to code defaults, but that is not enough for reusable content
This is directionally good in one way: mod.toml should not become an arbitrary runtime config dump.
However, Freven still needs a clearer model for:
- declaring config schema/defaults
- generating editable config for installed mods
- resolving config from instance/world/experience/stack layers
- deciding server/client/per-player ownership
- passing the final effective config into guest mods
- validating and documenting precedence
Proposed direction
Introduce a first-class layered mod config model.
Suggested architecture:
- Mod package declares config schema and defaults
The mod package should be able to declare available config keys, types, defaults, validation, and metadata.
This could live in mod.toml or a separate config schema file referenced by mod.toml.
Important distinction:
- mod.toml / package schema declares what settings exist and their defaults
- it should not be the only active runtime config source
Example concepts:
- key
- type: bool, int, float, string, enum
- default value
- min/max or allowed values
- description
- scope
- whether changing it requires restart/world reload/reconnect
- whether it is server-authoritative or client-local
- Platform/devkit generates editable config from schema
When a mod is installed into an instance, server, world, or project, Freven should be able to generate an editable config document from the mod's declared schema/defaults.
Possible locations:
- instance-level config for installed mods
- world/server config for world-specific gameplay state
- project/experience config for standalone games
- client-local config for client-only settings
The mod itself should not need to write config files from Wasm. The platform should own config file generation, validation, and loading.
- Experience and experience.stack.toml provide overrides
Experiences and stacks should be able to override mod defaults and instance config for a specific game mode or modpack.
This allows the same mod artifact to be reused in multiple experiences with different balance/settings.
For example:
[config."yunnwi.infection"]
step_every_ticks = 1
max_mutations_per_tick = 128
faction_count = 4
seed = 424242
cluster_count = 3
or a layer-scoped equivalent if that is better for the stack model.
- Runtime receives resolved effective config
StartInput.config should contain the final resolved config for that mod, after applying the configured precedence.
The guest should not need to know where the value came from.
- Define scopes clearly
A long-term model should distinguish at least:
- startup config: affects content registration, worldgen, prototypes, or compatibility; requires restart/reload
- server/world config: authoritative gameplay settings; saved with or owned by world/server
- runtime-global config: server-owned settings that can potentially change while running
- client/user config: local presentation/control/accessibility preferences
- per-player config: player-specific runtime settings, if supported later
Not all scopes need to be implemented immediately, but the base model should not block them.
- Define deterministic precedence
Suggested precedence, from lowest to highest:
- engine/platform defaults
- mod-declared schema defaults
- generated instance/world config
- base experience config
- experience.stack.toml layer overrides
- command-line/admin/session overrides, if supported
The exact order can be different, but it should be documented and deterministic.
Alternatives considered
- Put runtime config directly in mod.toml
This is simple for small mods, but it mixes package manifest/capabilities with active runtime configuration.
For long-term use, mod.toml should describe the package and its config schema/defaults, while active values should come from the selected instance/world/experience/server context.
- Require every configurable mod to fork/copy a full experience.toml
This works for custom games, but it is awkward for users who simply want to install a mod into an existing vanilla-like experience.
It also weakens the experience.stack.toml workflow, which is otherwise a good way to layer mods over vanilla without copying the whole experience.
- Keep config only as code defaults
This works for demos, but it does not scale to reusable mods, servers, modpacks, or standalone games.
Users should not need to rebuild a Wasm artifact to change balance or behavior.
- Let each mod invent its own config files
This would be flexible, but bad for long-term platform quality.
It would make validation, UI, sync, server authority, save ownership, and troubleshooting inconsistent across mods.
Ownership / boundary impact
Engine/platform:
- owns config resolution pipeline
- owns validation and diagnostics
- owns save/load/config file lifecycle
- owns server/client authority rules
- does not own gameplay-specific settings
SDK:
- exposes config schema declaration format
- exposes typed config access to guests
- documents config scopes and precedence
DevKit/launcher/server:
- generates editable config from schema
- shows effective config and diagnostics
- may eventually expose config UI
Vanilla:
- declares vanilla mod settings using the same system
- should not require special engine-only config paths
Mods:
- declare their config schema/defaults
- read resolved effective config
- do not need to hardcode paths or write config files themselves
Experience/modpack authors:
- compose mods
- override settings for a specific mode, pack, server, or standalone game
Non-goals
- Hardcoding trees, gases, crops, ores, biomes, or other gameplay concepts into engine core
- Making mod.toml an arbitrary mutable runtime config file
- Implementing a full graphical config UI immediately
- Supporting every possible config scope in the first implementation
- Replacing StartInput.config; the goal is to define how it is produced and layered
Open questions
- Should config schema live inside mod.toml, beside it as config.schema.toml, or both?
- What should the initial supported scopes be?
- Should experience.stack.toml config be root-level [config."mod.id"] or layer-scoped?
- How should conflicts between base experience config and stack overrides be resolved?
- Should generated config files be copied into instances, worlds, or both?
- Which settings should be synchronized from server to client?
- Should runtime config reload be supported initially, or only startup config?
- How should config validation errors be surfaced in DevKit logs and load plans?
Expected follow-up work
If accepted, likely follow-up issues:
- Add config schema declaration support for mod packages
- Generate editable instance/world config files from mod config schema
- Support per-mod config overrides in experience.stack.toml layers
- Document config resolution precedence and scopes
- Add diagnostics showing effective resolved config per mod
- Add typed guest-side helpers for validated config access
- Later: add config UI/editor support
- Later: add runtime reload/change events for supported scopes
Summary
Add a first-class configuration model for Freven mods and experiences.
The goal is to separate:
This would make configuration work for vanilla mods, custom experiences, modpacks, servers, and standalone games without hardcoding gameplay concepts into the engine.
Problem / Motivation
Runtime-loaded Wasm mods can receive StartInput.config, but the long-term configuration ownership model is not clear enough for larger mods, servers, modpacks, custom experiences, and standalone games.
A mod author may want to ship one artifact with tunable settings. Different users or experiences should be able to run the same artifact with different values without rebuilding the Wasm module.
Examples:
Current behavior from testing:
The immediate UX issue is stack config, but the larger architectural issue is that Freven needs a stable layered config model that can grow without being rewritten later.
Current state
Current known behavior:
This is directionally good in one way: mod.toml should not become an arbitrary runtime config dump.
However, Freven still needs a clearer model for:
Proposed direction
Introduce a first-class layered mod config model.
Suggested architecture:
The mod package should be able to declare available config keys, types, defaults, validation, and metadata.
This could live in mod.toml or a separate config schema file referenced by mod.toml.
Important distinction:
Example concepts:
When a mod is installed into an instance, server, world, or project, Freven should be able to generate an editable config document from the mod's declared schema/defaults.
Possible locations:
The mod itself should not need to write config files from Wasm. The platform should own config file generation, validation, and loading.
Experiences and stacks should be able to override mod defaults and instance config for a specific game mode or modpack.
This allows the same mod artifact to be reused in multiple experiences with different balance/settings.
For example:
[config."yunnwi.infection"]
step_every_ticks = 1
max_mutations_per_tick = 128
faction_count = 4
seed = 424242
cluster_count = 3
or a layer-scoped equivalent if that is better for the stack model.
StartInput.config should contain the final resolved config for that mod, after applying the configured precedence.
The guest should not need to know where the value came from.
A long-term model should distinguish at least:
Not all scopes need to be implemented immediately, but the base model should not block them.
Suggested precedence, from lowest to highest:
The exact order can be different, but it should be documented and deterministic.
Alternatives considered
This is simple for small mods, but it mixes package manifest/capabilities with active runtime configuration.
For long-term use, mod.toml should describe the package and its config schema/defaults, while active values should come from the selected instance/world/experience/server context.
This works for custom games, but it is awkward for users who simply want to install a mod into an existing vanilla-like experience.
It also weakens the experience.stack.toml workflow, which is otherwise a good way to layer mods over vanilla without copying the whole experience.
This works for demos, but it does not scale to reusable mods, servers, modpacks, or standalone games.
Users should not need to rebuild a Wasm artifact to change balance or behavior.
This would be flexible, but bad for long-term platform quality.
It would make validation, UI, sync, server authority, save ownership, and troubleshooting inconsistent across mods.
Ownership / boundary impact
Engine/platform:
SDK:
DevKit/launcher/server:
Vanilla:
Mods:
Experience/modpack authors:
Non-goals
Open questions
Expected follow-up work
If accepted, likely follow-up issues: