107 lines
5.6 KiB
C#
107 lines
5.6 KiB
C#
namespace MSCO.Server;
|
|
|
|
/// <summary>
|
|
/// server.json im Web-Panel lesen und ändern - bei laufendem Server (dann sofort wirksam) und wenn er aus ist
|
|
/// (z.B. Lizenzschlüssel eintragen, damit er überhaupt starten kann).
|
|
/// </summary>
|
|
public static class ConfigEditor
|
|
{
|
|
public static object Build(ServerConfig config) => new
|
|
{
|
|
name = config.Name,
|
|
description = config.Description,
|
|
maxPlayers = config.MaxPlayers,
|
|
isPublic = config.Public,
|
|
requireSteam = config.RequireSteam,
|
|
publicAddress = config.PublicAddress,
|
|
saveSyncMinutes = config.SaveSyncMinutes,
|
|
autosaveSeconds = config.AutosaveSeconds,
|
|
port = config.Port,
|
|
panelEnabled = config.PanelEnabled,
|
|
panelPort = config.PanelPort,
|
|
panelBindAddress = config.PanelBindAddress,
|
|
panelTrustProxy = config.PanelTrustProxy,
|
|
panelBasePath = config.PanelBasePath,
|
|
licenseKeySet = !string.IsNullOrWhiteSpace(config.LicenseKey),
|
|
steamWebApiKeySet = !string.IsNullOrWhiteSpace(config.SteamWebApiKey),
|
|
environmentOverrides = config.EnvironmentOverrides,
|
|
// In Docker muss ein anderer Port zusätzlich in docker-compose.yml freigegeben werden (Warnung im Panel)
|
|
inDocker = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"
|
|
};
|
|
|
|
/// <summary>Einstellungen ändern. Schlüssel (Lizenz, Steam Web API) nur als Owner; leer = unverändert.</summary>
|
|
public static string Apply(ServerConfig config, string configPath, System.Text.Json.JsonElement b, bool owner, string by)
|
|
{
|
|
if (b.ValueKind != System.Text.Json.JsonValueKind.Object) return "Invalid settings";
|
|
var changed = new List<string>();
|
|
bool restartNeeded = false;
|
|
|
|
string Text(string name, string current, int max)
|
|
{
|
|
if (!b.TryGetProperty(name, out var v) || v.ValueKind != System.Text.Json.JsonValueKind.String) return current;
|
|
string s = v.GetString().Trim();
|
|
if (s.Length > max) s = s[..max];
|
|
if (s != current) changed.Add(name);
|
|
return s;
|
|
}
|
|
int Number(string name, int current, int min, int max)
|
|
{
|
|
if (!b.TryGetProperty(name, out var v) || !v.TryGetInt32(out int n)) return current;
|
|
n = Math.Clamp(n, min, max);
|
|
if (n != current) changed.Add(name);
|
|
return n;
|
|
}
|
|
bool Flag(string name, bool current)
|
|
{
|
|
if (!b.TryGetProperty(name, out var v) || (v.ValueKind != System.Text.Json.JsonValueKind.True && v.ValueKind != System.Text.Json.JsonValueKind.False)) return current;
|
|
bool f = v.GetBoolean();
|
|
if (f != current) changed.Add(name);
|
|
return f;
|
|
}
|
|
|
|
string name = Text("name", config.Name, 60);
|
|
if (name.Length == 0) return "The server name cannot be empty";
|
|
config.Name = name;
|
|
config.Description = Text("description", config.Description, 300);
|
|
config.MaxPlayers = Number("maxPlayers", config.MaxPlayers, 1, 64);
|
|
config.Public = Flag("isPublic", config.Public);
|
|
config.RequireSteam = Flag("requireSteam", config.RequireSteam);
|
|
config.PublicAddress = Text("publicAddress", config.PublicAddress, 200);
|
|
config.SaveSyncMinutes = Number("saveSyncMinutes", config.SaveSyncMinutes, 0, 240);
|
|
config.AutosaveSeconds = Number("autosaveSeconds", config.AutosaveSeconds, 10, 3600);
|
|
|
|
int before = changed.Count;
|
|
int oldPort = config.Port, oldPanelPort = config.PanelPort;
|
|
config.Port = Number("port", config.Port, 1, 65535);
|
|
config.PanelEnabled = Flag("panelEnabled", config.PanelEnabled);
|
|
config.PanelPort = Number("panelPort", config.PanelPort, 0, 65535);
|
|
config.PanelBindAddress = Text("panelBindAddress", config.PanelBindAddress, 60);
|
|
config.PanelTrustProxy = Flag("panelTrustProxy", config.PanelTrustProxy);
|
|
config.PanelBasePath = Text("panelBasePath", config.PanelBasePath, 60);
|
|
if (changed.Count > before) restartNeeded = true;
|
|
// Ports gehören dem Programm, nicht dem Gameserver: "Restart" im Panel reicht dafür nicht
|
|
bool portChanged = config.Port != oldPort || config.PanelPort != oldPanelPort;
|
|
|
|
foreach (string secret in new[] { "licenseKey", "steamWebApiKey" })
|
|
{
|
|
if (!b.TryGetProperty(secret, out var v) || v.ValueKind != System.Text.Json.JsonValueKind.String || v.GetString().Trim().Length == 0) continue;
|
|
if (!owner) return "Only the owner can change keys";
|
|
string value = v.GetString().Trim();
|
|
if (value.Length > 200) return "Key too long";
|
|
if (secret == "licenseKey") config.LicenseKey = value; else config.SteamWebApiKey = value;
|
|
changed.Add(secret);
|
|
restartNeeded = true;
|
|
}
|
|
|
|
if (changed.Count == 0) return "Nothing changed";
|
|
try { config.Save(configPath); }
|
|
catch (Exception e) { return "Could not save server.json: " + e.Message; }
|
|
GameServer.Log($"Settings changed by {by}: {string.Join(", ", changed)}");
|
|
var overridden = changed.Where(c => config.EnvironmentOverrides.Any(e => e.Replace("_", "").Contains(c.ToUpperInvariant().Replace("ISPUBLIC", "PUBLIC")))).ToList();
|
|
return "Settings saved" +
|
|
(portChanged ? " - the new port only applies after the whole program restarts (docker compose restart); in Docker publish it in docker-compose.yml first"
|
|
: restartNeeded ? " - some changes need a restart" : "") +
|
|
(overridden.Count > 0 ? " (note: " + string.Join(", ", overridden) + " is also set by an environment variable, which wins on restart)" : "");
|
|
}
|
|
}
|