Configuration

Altruist uses YAML configuration files to define server behavior. No builder pattern, no fluent API — just a clean config.yml that drives everything.

Config File Loading

On startup, AppConfigLoader loads configuration in this order (later sources override earlier ones):

  1. config.yml (required)
  2. config.{DOTNET_ENVIRONMENT}.yml (optional, e.g., config.Development.yml)
  3. Environment variables prefixed with ALTRUIST__
  4. Command-line arguments

Note:

Config files are loaded from AppContext.BaseDirectory — typically your build output directory. Make sure config.yml is copied to the output.

Full Configuration Reference

Server & HTTP

altruist:
  server:
    http:
      host: "0.0.0.0"    # Bind address
      port: 8080          # HTTP port
      path: "/"           # Base path for HTTP controllers

Transport

Enable any combination of transports. Each has its own enabled flag:

altruist:
  server:
    transport:
      codec:
        provider: json       # json or messagepack (shared across all transports)
      websocket:
        enabled: true        # Enable WebSocket
        path: /ws            # WebSocket endpoint path
      tcp:
        enabled: true        # Enable TCP
        port: 13000          # TCP listen port
      udp:
        enabled: false       # Disable UDP
        port: 13001          # UDP listen port

Persistence

altruist:
  persistence:
    cache:
      provider: inmemory     # In-memory cache (default)
    database:
      provider: postgres     # Database provider
      host: localhost
      port: 5432
      username: myuser
      password: mypassword
      database: mydb

Security

altruist:
  security:
    mode: "jwt"              # Enables JWT authentication

Game Engine

altruist:
  environment:
    mode: "3D"               # 2D or 3D mode

  game:
    engine:
      diagnostics: true      # Enable engine diagnostics logging
      framerateHz: 30        # Engine tick rate
      unit: "hz"             # Cycle unit
      gravity: { x: 0, y: -9.81 }

    worlds:
      partitioner: { width: 256, height: 256, depth: 256 }
      items:
        - index: 0
          id: "main-world"
          size: { x: 1000, y: 1000, z: 1000 }
          gravity: { x: 0, y: -9.81, z: 0 }
          position: { x: 0, y: 0, z: 0 }
          data-path: "Resources/world.json"  # Optional world data file

Environment Variables

Any config value can be overridden with environment variables using the ALTRUIST__ prefix with double underscores as path separators:

# Override the HTTP port
ALTRUIST__server__http__port=9090

# Override the database host
ALTRUIST__persistence__database__host=db.example.com

Binding Config to Classes

Use [ConfigurationProperties] to automatically bind a YAML section to a class:

[ConfigurationProperties("myapp:smtp")]
public class SmtpOptions
{
    public string Host { get; set; } = "";
    public int Port { get; set; } = 587;
    public bool EnableSsl { get; set; } = true;
    public string From { get; set; } = "";
}
myapp:
  smtp:
    host: "smtp.example.com"
    port: 587
    enableSsl: true
    from: "noreply@example.com"

The bound class is automatically registered as a singleton in DI and can be injected anywhere.

Conditional Service Registration

Services can be conditionally registered based on config values using [ConditionalOnConfig]:

// Only registered when transport mode is "websocket"
[Service(typeof(ITransport))]
[ConditionalOnConfig("altruist:server:transport:mode", havingValue: "websocket")]
public class WebSocketTransport : ITransport { ... }

// Only registered when the transport section exists
[Service(typeof(IConnectionManager))]
[ConditionalOnConfig("altruist:server:transport")]
public class ConnectionManager : IConnectionManager { ... }

Injecting Config Values

Individual config values can be injected into constructors using [AppConfigValue]:

public class MyService
{
    public MyService(
        [AppConfigValue("altruist:server:http:port", "8080")] string port,
        [AppConfigValue("altruist:server:transport:timeout", "10")] int timeout)
    {
        // port and timeout are resolved from config with fallback defaults
    }
}