From 33a415139b66a7afb123c40739c5ae0d5edb0f3e Mon Sep 17 00:00:00 2001 From: Nico Meister Date: Sun, 27 Sep 2026 23:55:46 +0200 Subject: [PATCH] Server browser: featured servers (gold row + FEATURED badge, pinned to the top by the master) and key tags in the server profile; search matches tags Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 8 ++++++++ LobbyUI.cs | 19 ++++++++++++++++--- ServerBrowser.cs | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d787225..471702a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Nächste Version + +**Server-Browser** +- **Hervorgehobene Server**: vom Keymaster-Admin markierte Server (Tag `featured`) stehen ganz oben, mit goldener + Zeile und **FEATURED**-Abzeichen (Liste und Profil) +- **Tags** der Server (z.B. `OFFICIAL`) erscheinen im Server-Profil; die Suche findet auch Tags +- Braucht keinen neuen Server: die Infos kommen vom Master (msco.mbm.wtf) und funktionieren mit 2.8-Servern + ## 2.8 Server und Mod müssen beide 2.8 sein (Server: `git pull && docker compose up -d --build`). diff --git a/LobbyUI.cs b/LobbyUI.cs index a1276dd..18c7c9d 100644 --- a/LobbyUI.cs +++ b/LobbyUI.cs @@ -29,6 +29,7 @@ namespace MSCO static readonly Color Muted = Hex(0x8e, 0x8e, 0x99); static readonly Color Online = Hex(0x3d, 0xd6, 0x8c); static readonly Color Pending = Hex(0xf2, 0xc2, 0x1d); + static readonly Color Gold = Hex(0xff, 0xb4, 0x5a); // hervorgehobene (featured) Server Page page = Page.P2P; Vector2 profileScroll; @@ -54,6 +55,7 @@ namespace MSCO string layoutError; GUIStyle dangerStyle; GUIStyle windowBox, sidebarBox, rowBox, accentBox, pillStyle, pillMutedStyle, chipOnStyle, chipOffStyle; + GUIStyle featuredRowBox, pillFeaturedStyle; GUIStyle logoStyle, taglineStyle, navStyle, navActiveStyle, titleStyle, textStyle, captionStyle, fieldStyle, primaryStyle, secondaryStyle, statusStyle, tabStyle, headerCellStyle, rowNameStyle, rowTagStyle, badgeStyle, toggleStyle, placeholderStyle; @@ -219,7 +221,8 @@ namespace MSCO shownServers = all.FindAll(s => (s.RequireSteam ? showSteam : showNonSteam) && (!hideFull || s.Players < s.MaxPlayers) && - (search.Length == 0 || (s.Name ?? "").ToLower().Contains(search) || (s.Owner ?? "").ToLower().Contains(search))); + (search.Length == 0 || (s.Name ?? "").ToLower().Contains(search) || (s.Owner ?? "").ToLower().Contains(search) || + (s.Tags != null && s.Tags.Exists(t => (t ?? "").Contains(search))))); List servers = shownServers; string shownError = Event.current.type == EventType.Layout ? (layoutError = browser.Error) : layoutError; @@ -238,7 +241,8 @@ namespace MSCO foreach (ServerListEntry s in servers) { Rect row = GUILayoutUtility.GetRect(10, 34, GUILayout.ExpandWidth(true)); - GUI.Box(new Rect(row.x, row.y + 2, row.width, row.height - 4), GUIContent.none, rowBox); + // Hervorgehobene Server (Keymaster-Admin) stehen oben - der Master liefert sie zuerst + GUI.Box(new Rect(row.x, row.y + 2, row.width, row.height - 4), GUIContent.none, s.Featured ? featuredRowBox : rowBox); // Herz: als Favorit merken / entfernen (vor dem Zeilen-Knopf, damit es den Klick bekommt) Heart(new Rect(row.xMax - 58, row.y + 7, 20, 20), s); @@ -250,6 +254,7 @@ namespace MSCO GUI.DrawTexture(new Rect(row.x + 10, row.y + 13, 8, 8), s.Ping < 0 ? texPending : texOnline); float nameX = row.x + 26; Favorites.Favorite fav = Favorites.FindByAddress(s.Address, s.Port); + if (s.Featured) nameX += Pill(nameX, row, "FEATURED", pillFeaturedStyle); if (fav != null) nameX += Pill(nameX, row, fav.Nickname, pillMutedStyle); if (s.IsLocal) { @@ -501,9 +506,13 @@ namespace MSCO GUILayout.BeginHorizontal(); Rect badgeRow = GUILayoutUtility.GetRect(10, 20, GUILayout.ExpandWidth(true)); float bx = badgeRow.x; + if (s.Featured) bx += Pill(bx, badgeRow, "FEATURED", pillFeaturedStyle); bx += Pill(bx, badgeRow, s.RequireSteam ? "STEAM" : "NON-STEAM", s.RequireSteam ? pillStyle : pillMutedStyle); if (s.IsLocal) bx += Pill(bx, badgeRow, "LOCAL", pillStyle); - if (s.Version != MSCO.ModVersion) Pill(bx, badgeRow, "v" + s.Version, pillStyle); + if (s.Version != MSCO.ModVersion) bx += Pill(bx, badgeRow, "v" + s.Version, pillStyle); + if (s.Tags != null) + foreach (string tag in s.Tags) + if (!string.IsNullOrEmpty(tag) && tag != "featured") bx += Pill(bx, badgeRow, tag.ToUpper(), pillMutedStyle); GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Space(12); @@ -815,6 +824,10 @@ namespace MSCO pillMutedStyle = new GUIStyle(pillStyle); pillMutedStyle.normal.background = UiTheme.Rounded(new Color(1f, 1f, 1f, 0.08f), 4); pillMutedStyle.normal.textColor = Muted; + pillFeaturedStyle = new GUIStyle(pillStyle); + pillFeaturedStyle.normal.background = UiTheme.Rounded(Gold, 4); + pillFeaturedStyle.normal.textColor = Hex(0x1a, 0x12, 0x06); + featuredRowBox = UiTheme.Panel9(Color.Lerp(Field, Gold, 0.16f), UiTheme.Radius); chipOnStyle = Button(new Color(Accent.r, Accent.g, Accent.b, 0.22f), new Color(Accent.r, Accent.g, Accent.b, 0.32f), AccentHover, 11, FontStyle.Bold); chipOffStyle = Button(Field, FieldFocus, Muted, 11, FontStyle.Bold); diff --git a/ServerBrowser.cs b/ServerBrowser.cs index e979f60..b951d2e 100644 --- a/ServerBrowser.cs +++ b/ServerBrowser.cs @@ -23,6 +23,8 @@ namespace MSCO public string Version; public bool RequireSteam = true; // false = Non-Steam-Server public string Owner; // Besitzer des Lizenzschlüssels + public bool Featured; // vom Keymaster-Admin hervorgehoben (steht in der Liste oben) + public List Tags = new List(); // Tags des Lizenzschlüssels (Keymaster-Admin), z.B. "official" [JsonIgnore] public int UptimeSeconds = -1; [JsonIgnore] public List PlayerNames = new List();