118 lines
6.3 KiB
C#
118 lines
6.3 KiB
C#
using System.Text.Json;
|
|
|
|
namespace MSCO.Server;
|
|
|
|
/// <summary>server.json - wird beim ersten Start mit Standardwerten angelegt.</summary>
|
|
public sealed class ServerConfig
|
|
{
|
|
public string LicenseKey { get; set; } = "";
|
|
public string Name { get; set; } = "My MSCO Server";
|
|
public string Description { get; set; } = "";
|
|
public int Port { get; set; } = 7777;
|
|
/// <summary>
|
|
/// Adresse, unter der Spieler den Server erreichen (IP oder Domain). Leer = die IP, von der
|
|
/// sich der Server beim Master meldet. Nötig z.B. wenn Master und Server im selben Docker-Netz laufen.
|
|
/// </summary>
|
|
public string PublicAddress { get; set; } = "";
|
|
public int MaxPlayers { get; set; } = 8;
|
|
/// <summary>In der Serverliste anzeigen.</summary>
|
|
public bool Public { get; set; } = true;
|
|
/// <summary>Nur Spieler mit Steam zulassen (false = auch ohne Steam, "Non-Steam"-Server).</summary>
|
|
public bool RequireSteam { get; set; } = true;
|
|
/// <summary>Weltzustand so oft auf die Festplatte schreiben.</summary>
|
|
public int AutosaveSeconds { get; set; } = 60;
|
|
/// <summary>
|
|
/// So oft (Minuten) lässt sich der Server von einem Spieler im Spiel den aktuellen Spielstand hochladen
|
|
/// (Schrauben, Teile, alles wie im Spiel gespeichert). Zusätzlich immer, wenn jemand beitritt. 0 = nur beim Beitreten.
|
|
/// </summary>
|
|
public int SaveSyncMinutes { get; set; } = 10;
|
|
/// <summary>Optional: Steam Web API Key, um Steam-Tickets der Spieler bei Steam zu prüfen.</summary>
|
|
public string SteamWebApiKey { get; set; } = "";
|
|
/// <summary>Gesperrte SteamID64s.</summary>
|
|
public List<string> BannedSteamIds { get; set; } = new();
|
|
/// <summary>Admins (SteamID64): dürfen im Spiel mit /admin Spieler kicken und bannen.</summary>
|
|
public List<string> Admins { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// So lange (Stunden) läuft bzw. startet der Server weiter, wenn der Master den Lizenzschlüssel nicht bestätigen
|
|
/// kann (nicht erreichbar oder lehnt ihn ab). Danach wird der Gameserver gestoppt, bis der Master ihn wieder bestätigt.
|
|
/// </summary>
|
|
public int LicenseGraceHours { get; set; } = 72;
|
|
|
|
// ---------------------------------------------------------------- Web-Panel
|
|
/// <summary>Web-Panel einschalten.</summary>
|
|
public bool PanelEnabled { get; set; } = true;
|
|
/// <summary>0 = derselbe Port wie der Gameserver (Browser und Spiel werden automatisch unterschieden), sonst eigener Port.</summary>
|
|
public int PanelPort { get; set; } = 0;
|
|
/// <summary>Nur bei eigenem PanelPort: Adresse, auf der gelauscht wird ("0.0.0.0" = alle, "127.0.0.1" = nur lokal, z.B. hinter einem Proxy).</summary>
|
|
public string PanelBindAddress { get; set; } = "0.0.0.0";
|
|
/// <summary>Hinter einem Reverse-Proxy: X-Forwarded-For/-Proto/-Prefix übernehmen (echte IP, HTTPS, Unterpfad).</summary>
|
|
public bool PanelTrustProxy { get; set; } = false;
|
|
/// <summary>Unterpfad, unter dem das Panel läuft, z.B. "/panel" (leer = direkt unter /).</summary>
|
|
public string PanelBasePath { get; set; } = "";
|
|
|
|
static readonly JsonSerializerOptions Options = new() { WriteIndented = true };
|
|
|
|
public static ServerConfig LoadOrCreate(string path, out bool created)
|
|
{
|
|
created = !File.Exists(path);
|
|
if (created)
|
|
{
|
|
var fresh = new ServerConfig();
|
|
fresh.Save(path);
|
|
return fresh;
|
|
}
|
|
var config = JsonSerializer.Deserialize<ServerConfig>(File.ReadAllText(path), Options) ?? new ServerConfig();
|
|
// Neue Einstellungen (z.B. Admins) auch in ältere server.json schreiben, damit man sie sieht
|
|
try { config.Save(path); } catch (Exception) { } // z.B. schreibgeschützt - dann eben nicht
|
|
return config;
|
|
}
|
|
|
|
public void Save(string path) => File.WriteAllText(path, JsonSerializer.Serialize(this, Options));
|
|
|
|
/// <summary>
|
|
/// Umgebungsvariablen überschreiben server.json (praktisch für Docker/systemd):
|
|
/// MSCO_LICENSE_KEY, MSCO_NAME, MSCO_DESCRIPTION, MSCO_PORT, MSCO_MAX_PLAYERS, MSCO_PUBLIC,
|
|
/// MSCO_PUBLIC_ADDRESS, MSCO_STEAM_WEB_API_KEY (die Master-Adresse ist fest, siehe MasterServer)
|
|
/// </summary>
|
|
/// <returns>Namen der gesetzten Umgebungsvariablen (fürs Log, damit klar ist, woher ein Wert kommt).</returns>
|
|
/// <summary>Per Umgebungsvariable gesetzte Einstellungen (nicht in server.json gespeichert).</summary>
|
|
[System.Text.Json.Serialization.JsonIgnore]
|
|
public List<string> EnvironmentOverrides { get; private set; } = new();
|
|
|
|
public List<string> ApplyEnvironment()
|
|
{
|
|
var used = new List<string>();
|
|
EnvironmentOverrides = used;
|
|
string Take(string name, string current)
|
|
{
|
|
string value = Env(name);
|
|
if (value == null) return current;
|
|
used.Add(name);
|
|
return value;
|
|
}
|
|
|
|
LicenseKey = Take("MSCO_LICENSE_KEY", LicenseKey);
|
|
Name = Take("MSCO_NAME", Name);
|
|
Description = Take("MSCO_DESCRIPTION", Description);
|
|
PublicAddress = Take("MSCO_PUBLIC_ADDRESS", PublicAddress);
|
|
SteamWebApiKey = Take("MSCO_STEAM_WEB_API_KEY", SteamWebApiKey);
|
|
if (int.TryParse(Env("MSCO_PORT"), out int port)) { Port = port; used.Add("MSCO_PORT"); }
|
|
if (int.TryParse(Env("MSCO_MAX_PLAYERS"), out int max)) { MaxPlayers = max; used.Add("MSCO_MAX_PLAYERS"); }
|
|
if (bool.TryParse(Env("MSCO_PUBLIC"), out bool isPublic)) { Public = isPublic; used.Add("MSCO_PUBLIC"); }
|
|
if (bool.TryParse(Env("MSCO_REQUIRE_STEAM"), out bool requireSteam)) { RequireSteam = requireSteam; used.Add("MSCO_REQUIRE_STEAM"); }
|
|
if (bool.TryParse(Env("MSCO_PANEL_ENABLED"), out bool panel)) { PanelEnabled = panel; used.Add("MSCO_PANEL_ENABLED"); }
|
|
if (int.TryParse(Env("MSCO_PANEL_PORT"), out int panelPort)) { PanelPort = panelPort; used.Add("MSCO_PANEL_PORT"); }
|
|
if (bool.TryParse(Env("MSCO_PANEL_TRUST_PROXY"), out bool trustProxy)) { PanelTrustProxy = trustProxy; used.Add("MSCO_PANEL_TRUST_PROXY"); }
|
|
PanelBindAddress = Take("MSCO_PANEL_BIND", PanelBindAddress);
|
|
PanelBasePath = Take("MSCO_PANEL_BASE_PATH", PanelBasePath);
|
|
return used;
|
|
}
|
|
|
|
static string Env(string name)
|
|
{
|
|
string value = Environment.GetEnvironmentVariable(name);
|
|
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
|
}
|
|
}
|