using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
namespace MSCO
{
/// Eine Ankündigung der MSCO-Admins (Keymaster → Wartung & News, Ziel "Spiel").
public class Announcement
{
public string Id, Title, Text, Level; // Level: info, warning, critical
}
///
/// Status vom Keymaster (/api/status?for=game): Wartungsmodus, Ankündigungen und die Mindest-Sicherheitsstufe der
/// Server. Wird im Hintergrund geladen (WinHTTP, blockiert das Spiel nicht) und alle paar Minuten aufgefrischt.
/// Ohne Verbindung gilt das Eingebaute (MSCO.MinServerSecurity), Ankündigungen fehlen dann einfach.
///
public static class SiteStatus
{
const float RefreshSeconds = 300f;
static readonly object gate = new object();
static List announcements = new List();
static bool maintenance;
static string maintenanceMessage = "";
static int minServerLevel; // vom Keymaster (0 = unbekannt)
static float nextFetch;
static bool fetching;
/// Aktuelle Ankündigungen (wichtigste zuerst).
public static List Announcements { get { lock (gate) return new List(announcements); } }
public static bool Maintenance { get { lock (gate) return maintenance; } }
public static string MaintenanceMessage { get { lock (gate) return maintenanceMessage; } }
///
/// Sicherheitsstufe, die Server und P2P-Hosts mindestens haben müssen: das Eingebaute oder - wenn höher - was die
/// MSCO-Admins im Keymaster eingestellt haben.
///
public static int RequiredServerSecurity { get { lock (gate) return Math.Max(MSCO.MinServerSecurity, minServerLevel); } }
/// Neue Ankündigung seit dem letzten Abruf (für einen Hinweis im Spiel).
public static event Action NewAnnouncement;
static readonly HashSet seen = new HashSet();
static readonly List fresh = new List(); // neu, noch nicht gemeldet (Hauptthread)
static bool firstLoad = true;
/// Jedes Frame aufrufen (MultiplayerManager): lädt beim Start und dann alle 5 Minuten neu.
public static void Tick()
{
Action handler = NewAnnouncement;
List report = null;
lock (gate)
if (fresh.Count > 0) { report = new List(fresh); fresh.Clear(); }
if (report != null && handler != null)
foreach (Announcement a in report)
try { handler(a); } catch { }
if (fetching || Time.realtimeSinceStartup < nextFetch) return;
Refresh();
}
/// Sofort neu laden (z.B. beim Öffnen des Server-Browsers).
public static void Refresh()
{
if (fetching) return;
fetching = true;
nextFetch = Time.realtimeSinceStartup + RefreshSeconds;
var thread = new Thread(() =>
{
try
{
string error;
string text = WinHttp.Get(ServerBrowser.MasterUrl + "/api/status?for=game", 8000, out error);
if (text != null) Apply(text);
}
catch { }
finally { fetching = false; }
});
thread.IsBackground = true;
thread.Start();
}
static void Apply(string text)
{
var root = MiniJson.Parse(text) as Dictionary;
if (root == null) return;
object v;
var m = root.TryGetValue("maintenance", out v) ? v as Dictionary : null;
var sec = root.TryGetValue("security", out v) ? v as Dictionary : null;
var list = new List();
var items = root.TryGetValue("announcements", out v) ? v as List