Own server tags in the web panel (Settings) and server.json

Tags (max. 6, normalized like the keymaster) are sent with the heartbeat;
official and featured are only given by the MSCO admins and are refused with
a note. MSCO_TAGS environment variable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 21:20:06 +02:00
co-authored by Claude Opus 5.5
parent 1ab9a01efb
commit e523e5e17b
6 changed files with 63 additions and 4 deletions
+28
View File
@@ -8,6 +8,11 @@ public sealed class ServerConfig
public string LicenseKey { get; set; } = "";
public string Name { get; set; } = "My MSCO Server";
public string Description { get; set; } = "";
/// <summary>
/// Eigene Tags für die Serverliste (z.B. "deutsch", "roleplay"), höchstens 6. "official" und "featured" vergeben
/// nur die MSCO-Admins im Keymaster.
/// </summary>
public List<string> Tags { get; set; } = new();
public int Port { get; set; } = 7777;
/// <summary>
/// Adresse, unter der Spieler den Server erreichen (IP oder Domain). Leer = die IP, von der
@@ -90,6 +95,7 @@ public sealed class ServerConfig
Name = Take("MSCO_NAME", Name);
Description = Take("MSCO_DESCRIPTION", Description);
PublicAddress = Take("MSCO_PUBLIC_ADDRESS", PublicAddress);
if (Env("MSCO_TAGS") is string tags) { Tags = NormalizeTags(tags.Split(','), out _); used.Add("MSCO_TAGS"); }
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"); }
@@ -103,6 +109,28 @@ public sealed class ServerConfig
return used;
}
public const int MaxTags = 6;
/// <summary>Diese Tags vergeben nur die MSCO-Admins (Keymaster), nicht der Server selbst.</summary>
public static readonly string[] ReservedTags = { "official", "featured" };
/// <summary>Wie der Keymaster: "Deutsch, Role Play!" -> ["deutsch", "role-play"]; reservierte fallen weg.</summary>
public static List<string> NormalizeTags(IEnumerable<string> input, out List<string> reserved)
{
reserved = new List<string>();
var tags = new List<string>();
foreach (string raw in input ?? Array.Empty<string>())
{
string t = (raw ?? "").Trim().ToLowerInvariant().Replace("ä", "ae").Replace("ö", "oe").Replace("ü", "ue").Replace("ß", "ss");
t = System.Text.RegularExpressions.Regex.Replace(t, @"\s+", "-");
t = System.Text.RegularExpressions.Regex.Replace(t, "[^a-z0-9-]", "").Trim('-');
if (t.Length > 20) t = t[..20].Trim('-');
if (t.Length == 0 || tags.Contains(t)) continue;
if (ReservedTags.Contains(t)) { if (!reserved.Contains(t)) reserved.Add(t); continue; }
if (tags.Count < MaxTags) tags.Add(t);
}
return tags;
}
static string Env(string name)
{
string value = Environment.GetEnvironmentVariable(name);