Favorites: heart toggle, Favorites tab with nicknames, /switch <nickname> quick server switch, fav command

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 18:24:00 +02:00
co-authored by Claude Opus 5.5
parent 8dae3ac13d
commit 8e00640732
6 changed files with 395 additions and 2 deletions
+114
View File
@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace MSCO
{
/// <summary>
/// Lieblings-Server mit eigenem Kurznamen (z.B. "mbm"). Gespeichert in den PlayerPrefs, eine Zeile pro Server:
/// Kurzname, Adresse, Port, Servername (Tab-getrennt). Mit "switch <kurzname>" wechselt man schnell den Server.
/// </summary>
public static class Favorites
{
public class Favorite
{
public string Nickname;
public string Host;
public int Port;
public string ServerName;
public string Address { get { return Host + ":" + Port; } }
}
const string Pref = "MSCO_Favorites";
const int MaxFavorites = 30;
static List<Favorite> list;
public static List<Favorite> All { get { Load(); return list; } }
static void Load()
{
if (list != null) return;
list = new List<Favorite>();
string raw = PlayerPrefs.GetString(Pref, "");
foreach (string line in raw.Split('\n'))
{
string[] p = line.Split('\t');
int port;
if (p.Length < 3 || p[0].Length == 0 || p[1].Length == 0 || !int.TryParse(p[2], out port)) continue;
list.Add(new Favorite { Nickname = p[0], Host = p[1], Port = port, ServerName = p.Length > 3 ? p[3] : "" });
}
}
static void Save()
{
var sb = new StringBuilder();
foreach (Favorite f in list)
sb.Append(Clean(f.Nickname)).Append('\t').Append(Clean(f.Host)).Append('\t').Append(f.Port).Append('\t').Append(Clean(f.ServerName)).Append('\n');
PlayerPrefs.SetString(Pref, sb.ToString());
PlayerPrefs.Save();
}
static string Clean(string s) { return (s ?? "").Replace("\t", " ").Replace("\n", " ").Trim(); }
/// <summary>Kurzname: Buchstaben, Zahlen, - und _ (ohne Leerzeichen, damit "switch name" eindeutig ist).</summary>
public static string CleanNickname(string nickname)
{
var sb = new StringBuilder();
foreach (char c in (nickname ?? "").Trim())
if (char.IsLetterOrDigit(c) || c == '-' || c == '_') sb.Append(c);
string s = sb.ToString();
return s.Length > 20 ? s.Substring(0, 20) : s;
}
public static Favorite Find(string nickname)
{
Load();
return list.Find(f => string.Equals(f.Nickname, nickname, StringComparison.OrdinalIgnoreCase));
}
public static Favorite FindByAddress(string host, int port)
{
Load();
return list.Find(f => f.Port == port && string.Equals(f.Host, host, StringComparison.OrdinalIgnoreCase));
}
/// <summary>Hinzufügen oder (gleiche Adresse) umbenennen. Gibt einen Fehler zurück oder null.</summary>
public static string Set(string nickname, string host, int port, string serverName)
{
Load();
nickname = CleanNickname(nickname);
if (nickname.Length == 0) return "Nickname: letters, numbers, - and _";
if (string.IsNullOrEmpty(host) || port <= 0 || port > 65535) return "Invalid server address";
Favorite sameName = Find(nickname);
Favorite existing = FindByAddress(host, port);
if (sameName != null && sameName != existing) return "The nickname '" + nickname + "' is already used for " + sameName.Address;
if (existing == null)
{
if (list.Count >= MaxFavorites) return "Too many favorites (max " + MaxFavorites + ")";
existing = new Favorite { Host = host, Port = port };
list.Add(existing);
}
existing.Nickname = nickname;
if (!string.IsNullOrEmpty(serverName)) existing.ServerName = serverName;
Save();
return null;
}
public static bool Remove(Favorite f)
{
Load();
if (f == null || !list.Remove(f)) return false;
Save();
return true;
}
/// <summary>Vorschlag für den Kurznamen aus dem Servernamen (erstes Wort, klein).</summary>
public static string SuggestNickname(string serverName)
{
string first = (serverName ?? "").Trim().Split(' ')[0];
string nick = CleanNickname(first).ToLower();
return nick.Length > 0 ? nick : "server";
}
}
}