using AOT.Boot; using HotUpdate.Net; using HotUpdate.UI; using UnityEngine; namespace HotUpdate.Gameplay { /// /// M4 玩法骨架:挂 HUD、角色、网络状态;处理公告与断线重连提示。 /// public sealed class GameplayBootstrap : MonoBehaviour { BootContext _ctx; GameNet _net; MainHudView _hud; ConfirmDialogView _dialog; bool _maintenanceLock; public void Bind(BootContext ctx, GameNet net) { _ctx = ctx; _net = net; } void Start() { EnsureUi(); WireNet(); MaybeShowBootNotice(); var spawner = gameObject.AddComponent(); spawner.Bind(_ctx); spawner.Spawn(); } void EnsureUi() { var uiRoot = new GameObject("UiRoot"); DontDestroyOnLoad(uiRoot); var mgr = uiRoot.AddComponent(); mgr.Init(uiRoot.transform, new UiPrefabLoader()); var hudGo = mgr.Open(MainHudView.PrefabName); _hud = hudGo != null ? hudGo.GetComponent() : null; if (_hud == null && hudGo != null) _hud = hudGo.AddComponent(); _hud?.Bind(); _hud?.SetStatus("启动中…"); if (_hud != null) _hud.OnReconnectClicked += () => _net?.RequestReconnect(); var dlgGo = mgr.Open(ConfirmDialogView.PrefabName); if (dlgGo != null) { dlgGo.SetActive(false); _dialog = dlgGo.GetComponent(); if (_dialog == null) _dialog = dlgGo.AddComponent(); _dialog.Bind(); } } void WireNet() { if (_net == null) return; _net.OnStatus += s => _hud?.SetStatus(s); _net.OnAuthed += session => _hud?.SetPid(session != null ? session.Pid : 0); _net.OnWsReady += () => { if (_maintenanceLock) return; _hud?.ShowReconnect(false); _hud?.SetStatus("已连接"); }; _net.OnWsDisconnected += reason => { if (_maintenanceLock) return; _hud?.ShowReconnect(true, $"网络已断开({reason}),正在重连…"); }; _net.OnReconnecting += attempt => { if (_maintenanceLock) return; _hud?.ShowReconnect(true, $"正在重连…(第 {attempt} 次)"); }; _net.OnMaintenance += msg => { _maintenanceLock = true; _hud?.ShowReconnect(false); _hud?.SetStatus("服务器维护中"); _dialog?.Show("维护公告", string.IsNullOrEmpty(msg) ? "服务器维护中,请稍后再试。" : msg); }; _net.OnWsMessage += TryHandleProtocol; } void MaybeShowBootNotice() { if (_ctx == null || string.IsNullOrEmpty(_ctx.Notice)) return; _dialog?.Show("公告", _ctx.Notice); } void TryHandleProtocol(string json) { if (string.IsNullOrEmpty(json)) return; // 轻量解析,避免引入完整 JSON 库依赖 if (json.IndexOf("\"op\":\"maintenance\"", System.StringComparison.Ordinal) >= 0 || json.IndexOf("\"op\": \"maintenance\"", System.StringComparison.Ordinal) >= 0) { var msg = ExtractJsonString(json, "message"); _net?.NotifyMaintenance(msg); } } static string ExtractJsonString(string json, string key) { var token = $"\"{key}\""; var i = json.IndexOf(token, System.StringComparison.Ordinal); if (i < 0) return null; i = json.IndexOf(':', i); if (i < 0) return null; i = json.IndexOf('"', i + 1); if (i < 0) return null; var j = json.IndexOf('"', i + 1); if (j < 0) return null; return json.Substring(i + 1, j - i - 1); } } }