package config import ( "os" "gopkg.in/yaml.v3" ) type Config struct { TickLength int `yaml:"tick_length"` StartingRoom int `yaml:"starting_room"` StartupValidation ValidationConfig `yaml:"startup_validation"` GameConstants GameConstants `yaml:"game_constants"` DefaultColors ColorsConfig `yaml:"default_colors"` TLS TLSConfig `yaml:"tls"` Telnet TelnetConfig `yaml:"telnet"` TelnetTLS TelnetTLSConfig `yaml:"telnet_tls"` HTTP HTTPConfig `yaml:"http"` HTTPS HTTPSConfig `yaml:"https"` AdminHTTP AdminHTTPConfig `yaml:"admin_http"` AdminHTTPS AdminHTTPSConfig `yaml:"admin_https"` } // GameConstants holds tunable game-wide numbers that would otherwise be // hardcoded in the engine. type GameConstants struct { // ShopDefaultRestock is the fallback restock interval (in ticks) for a shop // item that does not set its own restock_ticks. ShopDefaultRestock float64 `yaml:"shop_default_restock"` } type ColorsConfig map[string]string func DefaultColors() ColorsConfig { return ColorsConfig{ "room_name": "74 bold", "room_number": "F0", "room_desc": "FF", "direction": "49", "exit_direction": "49", "exit_name": "74", "protected_mob": "off", "mob": "off", "damage_dealt": "B4", "damage_taken": "A7", "damage": "A7", "xp": "B3", "level_up": "B4 bold", "item": "6E", "player_name": "74", "death": "A7 bold", "victory": "6C", "miss": "F5", "error": "A7", "say": "FF", "global": "49", "dialog": "6E", "dialog_options": "bold", "broadcast": "89", "sequence": "off", "fire": "B4", "eat_food": "6C", "drop_message": "89", "credits_pickup": "B3", "chips_pickup": "8B", "visual_tick": "49 dim", "visual_first_tick": "B4 bold", "battery": "6C", "tech_depleted": "A7", "science_mod": "8B", "assassin_task": "8B", "dim": "F5 dim", "warning": "B3", "farm_grow": "6C", "farm_disease": "A7", "map_at": "B4 bold", "map_blocked": "A7", "map_course": "43", "safespot_alert": "A7 bold", } } type ValidationConfig struct { RootRooms []int `yaml:"root_rooms"` IgnoreUnreachable []int `yaml:"ignore_unreachable"` } type TelnetConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } type TLSConfig struct { CertFile string `yaml:"cert_file"` KeyFile string `yaml:"key_file"` } type TelnetTLSConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } type HTTPConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } type HTTPSConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } type AdminHTTPConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } type AdminHTTPSConfig struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` } func Default() *Config { return &Config{ TickLength: 600, StartingRoom: 1001, StartupValidation: ValidationConfig{ RootRooms: []int{1}, IgnoreUnreachable: []int{}, }, GameConstants: GameConstants{ ShopDefaultRestock: 1000, }, DefaultColors: DefaultColors(), TLS: TLSConfig{ CertFile: "", KeyFile: "", }, Telnet: TelnetConfig{ Enabled: true, Port: 4000, }, TelnetTLS: TelnetTLSConfig{ Enabled: false, Port: 4001, }, HTTP: HTTPConfig{ Enabled: false, Port: 8080, }, HTTPS: HTTPSConfig{ Enabled: false, Port: 8443, }, AdminHTTP: AdminHTTPConfig{ Enabled: false, Port: 9091, }, AdminHTTPS: AdminHTTPSConfig{ Enabled: false, Port: 9090, }, } } func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } cfg := Default() if err := yaml.Unmarshal(data, cfg); err != nil { return nil, err } return cfg, nil } func SaveDefault(path string) error { cfg := Default() data, err := yaml.Marshal(cfg) if err != nil { return err } return os.WriteFile(path, data, 0644) }