using System; using System.Collections.Generic; using HotUpdate.Net; namespace UnityEngine { public static class Time { public static float realtimeSinceStartup; } } namespace AOT.Boot { public static class WebSocketBridge { public static int LastId; public static readonly Dictionary> Events = new(); public static readonly List Sent = new(); public static int AIGame_WsCreate(string url) { Events[++LastId] = new(); return LastId; } public static string AIGame_WsPoll(int id) => Events[id].TryDequeue(out var item) ? item : null; public static void AIGame_WsSend(int id, string text) => Sent.Add(text); public static void AIGame_WsDispose(int id) => Events.Remove(id); public static void Emit(string item) => Events[LastId].Enqueue(item); } } public static class Program { static void Check(bool pass, string message) { if (!pass) throw new Exception(message); } public static void Main() { var ws = new WsClient(); int opens = 0, closes = 0, retries = 0; string message = null; ws.OnConnected += () => { opens++; ws.SendText("hello"); }; ws.OnDisconnected += _ => closes++; ws.OnReconnecting += _ => retries++; ws.OnMessage += text => message = text; ws.Connect("wss://test"); Check(ws.State == WsState.Connecting, "connect state"); AOT.Boot.WebSocketBridge.Emit("O"); AOT.Boot.WebSocketBridge.Emit("MδΈ­ζ–‡πŸ™‚"); ws.Tick(); Check(opens == 1 && message == "δΈ­ζ–‡πŸ™‚" && AOT.Boot.WebSocketBridge.Sent[0] == "hello", "open, UTF-8 and queued send"); AOT.Boot.WebSocketBridge.Emit("Eoffline"); ws.Tick(); Check(closes == 1 && retries == 1 && ws.LastError == "offline", "disconnect and retry notification"); UnityEngine.Time.realtimeSinceStartup = 1; ws.Tick(); Check(AOT.Boot.WebSocketBridge.LastId == 1, "retry must back off"); UnityEngine.Time.realtimeSinceStartup = 2; ws.Tick(); Check(ws.State == WsState.Reconnecting && AOT.Boot.WebSocketBridge.LastId == 2, "retry starts at deadline"); UnityEngine.Time.realtimeSinceStartup = 18; ws.Tick(); Check(closes == 2 && retries == 2 && ws.LastError.Contains("timed out"), "connect timeout"); ws.ForceReconnect(); AOT.Boot.WebSocketBridge.Emit("O"); ws.Tick(); Check(ws.State == WsState.Connected && opens == 2 && ws.LastError == null, "manual reconnect resets error"); ws.Close(); UnityEngine.Time.realtimeSinceStartup = 100; ws.Tick(); Check(ws.State == WsState.Disconnected && AOT.Boot.WebSocketBridge.Events.Count == 0, "manual close cancels pending reconnect"); ws.Connect("wss://test"); ws.AutoReconnect = false; AOT.Boot.WebSocketBridge.Emit("C1000 maintenance"); ws.Tick(); UnityEngine.Time.realtimeSinceStartup = 200; ws.Tick(); Check(ws.State == WsState.Disconnected && retries == 2, "maintenance must not reconnect"); ws.Dispose(); Console.WriteLine("PASS: actual UNITY_WEBGL WsClient open/send/receive/backoff/timeout/manual reconnect/close/maintenance."); } }