using Assets.MyGame.Scripts.Net.WebResponses; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; namespace Assets.MyGame.Scripts.Net { public class WebSocketReponseList { /// 已加载(或正在加载)的游戏场景名集合,防止人机 RoomJoinNotice 触发重复 LoadSceneAsync private static readonly HashSet _loadedGameScenes = new HashSet(); /// 清除指定场景的加载标记(退出游戏时调用,下次进入可重新加载) public static void ClearLoadedGameScene(string sceneName) { if (!string.IsNullOrEmpty(sceneName)) _loadedGameScenes.Remove(sceneName); } /// /// 获取房间列表 room /// /// public static void GetRoomListChineseChessResult(string msg) { var var1 = UIManager.Instance.Show(UIPanel.MainGamePanelZGXQ, msg); } public static void GetGoldConfigSuccessChineseChessResult(string msg) { UIManager.Instance.Get(UIPanel.MainGamePanelZGXQ).subUIManager.ShowAsync(UIPanel.ZGXQGameExplain); } /// /// 获取房间列表 room /// /// public static void GetRoomListResult(string msg) { var var1 = UIManager.Instance.Get(UIPanel.HomeMainPanel); var selectRoomPanel = var1.subUIManager.Get(UIPanel.SelectRoomLeavePenel); if (selectRoomPanel != null && selectRoomPanel.isMySelectRoom) { // 手动选座:显示房间列表给玩家选 selectRoomPanel.panel_UIHome_BY_MySelectRoomPenel.Show(msg); } // 快速加入分支已迁移到 OnSelectRoom → /api/Room/QuickJoin,不再走 GetRoomList } /// /// 加入房间 room /// /// public static void RoomJoinNotice(string msg) { string sceneName = ""; UIPanel uIPanel = UIPanel.None; switch (GameManager.Instance.gameData.currGameType) { case GameType.JQQD: break; case GameType.defaultPanel: break; case GameType.FLZY: sceneName = "FLZY"; uIPanel = UIPanel.MainGamePanelFLZY; break; case GameType.YYSC: sceneName = "YYSC"; uIPanel = UIPanel.MainGamePanelYYSC; break; case GameType.ZGXQ: break; case GameType.XJMH: sceneName = "XJMH"; uIPanel = UIPanel.MainGamePanelXJMH; break; case GameType.HHWK: sceneName = "HHWK"; uIPanel = UIPanel.MainGamePanelHHWK; break; default: break; } if (UIManager.Instance.Get(uIPanel)==null) { UIManager.Instance.ShowAsync(uIPanel, UIPanel.HomeMainPanel, msg); // 卸载所有已加载的游戏地图场景(保证场景唯一性) string[] gameScenes = { "FLZY", "YYSC", "XJMH", "HHWK" }; foreach (var sn in gameScenes) { // 不卸载即将加载的目标场景 if (sn == sceneName) continue; var s = SceneManager.GetSceneByName(sn); if (s.IsValid() && s.isLoaded) { SceneManager.UnloadSceneAsync(sn); _loadedGameScenes.Remove(sn); } } // 目标场景仅加载一次:标记已加载后不再重复 LoadSceneAsync(防止人机通知触发重复加载) if (!string.IsNullOrEmpty(sceneName) && !_loadedGameScenes.Contains(sceneName)) { _loadedGameScenes.Add(sceneName); var targetScene = SceneManager.GetSceneByName(sceneName); if (!targetScene.IsValid() || !targetScene.isLoaded) SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); } UIManager.Instance.Close(UIPanel.HomeMainPanel); WebSocketManager.Instance.isGame = true; } else { // 面板已存在 → 新玩家加入,转发给现有面板激活座位 var panel = UIManager.Instance.Get(uIPanel); if (panel is GameMainPanel_FishBase fishPanel) { var v = JsonConvert.DeserializeObject>(msg); if (v.arguments.Count > 0) { var notice = v.arguments[0]; // 如果座位被bot占用则替换 var targetSit = fishPanel.list_Sits.Find(s => s.posID == notice.position); if (targetSit != null && targetSit.isBot) { targetSit.isBot = false; targetSit.ShowWaiting(); } fishPanel.JoinGame(notice.position, notice.gold, notice.diamond, notice.cannonMultiple, 0, notice.userId, notice.cannonId, notice.wingsId); // 后端动态加入的机器人也要标记 if (targetSit != null && !string.IsNullOrEmpty(notice.userId) && notice.userId.StartsWith("bot_")) targetSit.isBot = true; } } } } /// /// 房间列表 room /// /// public static void RoomInfo(string msg) { WebSocketManager.Instance.isGame = false; var roomData = JsonConvert.DeserializeObject>(msg).arguments[0]; if (roomData != null) { GameManager.Instance.gameData.currRoomData = roomData; } else { Debug.LogError("roomdata是空:" + msg); } } public static void RoomKillNotice(string msg) { // 离开倒计时期间不触发击杀/爆奖特效 var panel = UIManager.Instance.Get(UIPanel.MainGamePanelDefault) ?? UIManager.Instance.Get(UIPanel.MainGamePanelFLZY) ?? UIManager.Instance.Get(UIPanel.MainGamePanelYYSC) ?? UIManager.Instance.Get(UIPanel.MainGamePanelXJMH) ?? UIManager.Instance.Get(UIPanel.MainGamePanelHHWK); if (panel != null && panel.IsLeavingCountdown()) return; CreateFishManager.Instance.Ws_DieFish(msg); } public static void RoomFireNotice(string msg) { FireCannonSendData fireCannonSendData = JsonConvert.DeserializeObject>(msg).arguments[0]; var syncGameData = fireCannonSendData.extra; EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_FireBullet, fireCannonSendData); } public static void SyncPlayerGold(string msg) { var gold = JsonConvert.DeserializeObject>(msg).arguments[0]; switch (GameManager.Instance.gameData.currGameType) { case GameType.JQQD: break; case GameType.defaultPanel: UIManager.Instance.Get(UIPanel.MainGamePanelDefault).currSitData.goldNum = gold; break; case GameType.FLZY: UIManager.Instance.Get(UIPanel.MainGamePanelFLZY).currSitData.goldNum = gold; break; case GameType.YYSC: UIManager.Instance.Get(UIPanel.MainGamePanelYYSC).currSitData.goldNum = gold; break; case GameType.ZGXQ: break; case GameType.XJMH: UIManager.Instance.Get(UIPanel.MainGamePanelXJMH).currSitData.goldNum = gold; break; case GameType.HHWK: UIManager.Instance.Get(UIPanel.MainGamePanelHHWK).currSitData.goldNum = gold; break; default: break; } } public static void GetRoomInfoResult(string msg) { //GameManager.Instance.StartGame();RoomChangeResponse var roomData = JsonConvert.DeserializeObject>(msg).arguments[0]; UIHome_BY_SelectRoomLevelPanel.StartGame(roomData); } public static void SyncGameDataResult(string msg) { var syncGameData = JsonConvert.DeserializeObject>(msg).arguments[0]; switch (syncGameData.frameType) { case FrameDataType.none: break; case FrameDataType.rotateTurrect: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_Rotate, syncGameData); break; case FrameDataType.fireBullet: // 机器人角度同步:SyncFire_ForBot 发出的 SyncGameData(fireBullet) // 与 RoomFireNotice(FireCannonSendData) 分开处理,仅用于存储角度到 botLastAngle EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_BotFireAngle, syncGameData); break; case FrameDataType.createFish: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_CreateFish, syncGameData); break; case FrameDataType.changeAutoTarget: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_ChangeTargetMonster, syncGameData); break; case FrameDataType.randomDieFish: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_RendromDieFish, syncGameData); break; case FrameDataType.freezeFish: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_FreezeFish, syncGameData); break; case FrameDataType.changeTurretState: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_TurretState, syncGameData); break; case FrameDataType.changeTurret: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_ChangeTurret, syncGameData); break; case FrameDataType.changeCannonMultiple: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_ChangeCannonMultiple, syncGameData); break; case FrameDataType.changeWing: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_ChangeWing, syncGameData); break; case FrameDataType.requestSyncFish: EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_RequestSyncFish, syncGameData); break; default: break; } } public static void LeaveRoomResult(string msg) { //WebSocketManager.Instance.isGame = false; //GameManager.Instance.StartGame();RoomChangeResponse var response = JsonConvert.DeserializeObject>(msg); // ⭐ 数据保护:arguments 为空直接返回,避免抛异常 if (response?.arguments == null || response.arguments.Count == 0) { #if UNITY_EDITOR Debug.LogWarning("[LeaveRoomResult] arguments 为空,忽略"); #endif return; } var userid = response.arguments[0]; switch (GameManager.Instance.gameData.currGameType) { case GameType.JQQD: break; case GameType.defaultPanel: break; case GameType.FLZY: { var panel = UIManager.Instance.Get(UIPanel.MainGamePanelFLZY); if (panel == null || panel.currSitData == null) break; if (panel.currSitData.user == userid) { ExitFishingGame(UIPanel.MainGamePanelFLZY); break; } foreach (var item in panel.list_Sits) { if (item.user == userid) { item.ShowWaiting(); } } } break; case GameType.YYSC: { var panel = UIManager.Instance.Get(UIPanel.MainGamePanelYYSC); if (panel == null || panel.currSitData == null) break; if (panel.currSitData.user == userid) { ExitFishingGame(UIPanel.MainGamePanelYYSC); break; } foreach (var item in panel.list_Sits) { if (item.user == userid) { item.ShowWaiting(); } } } break; case GameType.ZGXQ: break; case GameType.XJMH: { var panel = UIManager.Instance.Get(UIPanel.MainGamePanelXJMH); if (panel == null || panel.currSitData == null) break; if (panel.currSitData.user == userid) { ExitFishingGame(UIPanel.MainGamePanelXJMH); break; } foreach (var item in panel.list_Sits) { Debug.Log(item.user + "---" + userid); if (item.user == userid) { Debug.Log("推出星际迷航"); item.ShowWaiting(); } } } break; case GameType.HHWK: { var panel = UIManager.Instance.Get(UIPanel.MainGamePanelHHWK); if (panel == null || panel.currSitData == null) break; if (panel.currSitData.user == userid) { ExitFishingGame(UIPanel.MainGamePanelHHWK); break; } foreach (var item in panel.list_Sits) { if (item.user == userid) { item.ShowWaiting(); } } } break; default: break; } } /// /// 统一退出捕鱼游戏流程: /// 1. 关闭 game socket(自己的离房通知已收到,可以正常关闭) /// 2. 拉取最新用户数据并触发 OnUserDataChanged 事件,同步大厅金币/钻石/等级等 UI /// 3. 复用游戏内 JinDuTiao 进度条卸载资源(和加入游戏流程一致,末尾保留2秒) /// 4. 进度条完成后切回大厅 /// private static void ExitFishingGame(UIPanel gamePanel) { // 标记游戏已结束 WebSocketManager.Instance.isGame = false; // 关闭游戏连接 WebSocketManager.Instance.Close(SocketType.game); // 拉取最新用户数据,触发 UI 同步更新(金币/钻石/等级/VIP等) APIRequestList.GetUser((user) => { GameManager.Instance.UpdataUserData(user); }); // ⭐ 复用游戏面板的 JinDuTiao 进度条卸载资源,完成后进入 home 界面 var panel = UIManager.Instance.Get(gamePanel); if (panel != null) { panel.UnLoadResourcesWithProgress(() => { // 进度条加载完成后进入 home 界面 UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, gamePanel); }); } else { // 兜底:拿不到面板直接切换 UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, gamePanel); } } // ---------------- LoginHub ---------------- /// /// LoginHub Broadcast — 大厅公告广播 /// public static void LoginBroadcast(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; UIManager.Instance.ShowBoardGongGao(data.message); } /// /// LoginHub AssetUpdated — 资产变动通知 /// public static void AssetUpdated(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; // 触发用户数据刷新 var userId = GameManager.Instance?.user?.id; if (!string.IsNullOrEmpty(userId)) APIRequestList.GetUser(userId, a => GameManager.Instance.UpdataUserData(a)); } /// /// LoginHub BackpackUpdated — 背包变动通知 /// public static void BackpackUpdated(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; // 刷新用户数据(道具列表在 GetUser 返回中) var userId = GameManager.Instance?.user?.id; if (!string.IsNullOrEmpty(userId)) APIRequestList.GetUser(userId, a => GameManager.Instance.UpdataUserData(a)); } /// /// LoginHub NewEmail — 新邮件通知 /// public static void NewEmail(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; UIManager.Instance.ShowBoardError($"收到新邮件:{data.title}"); } /// /// LoginHub KillAnnouncement — 全局击杀公告(特殊 Boss 击杀全服推送) /// public static void KillAnnouncement(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; // 服务端已拼好 text(格式:恭喜玩家*****在风雷之渊 高级场捕获 人鱼公主*2000倍 150000000大奖) if (data != null && !string.IsNullOrEmpty(data.text)) UIManager.Instance.ShowBoardGongGao(data.text); } /// /// LoginHub LevelChanged — 后台修改玩家等级 /// 直接调用 GetUser 刷新用户数据,触发 OnUserDataChanged 同步 UI /// public static void LevelChanged(string msg) { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; var userId = GameManager.Instance?.user?.id; if (!string.IsNullOrEmpty(userId)) APIRequestList.GetUser(userId, a => GameManager.Instance.UpdataUserData(a)); } // ---------------- LoginHub 断线房间 ---------------- /// 当前是否有待处理的断线房间弹窗(防止重复弹) private static bool _pendingRoomActive; /// /// LoginHub PendingRoomNotice — 登录后检测到有未完成的断线游戏 /// 弹窗提示用户选择"返回房间"(调 Reconnect)或"离开"(调 DismissPendingRoom) /// 60 秒无操作自动离开 /// public static void PendingRoomNotice(string msg) { if (_pendingRoomActive) return; // 防重复 var data = JsonConvert.DeserializeObject>(msg).arguments[0]; if (data == null) return; _pendingRoomActive = true; var userId = GameManager.Instance?.user?.id; if (string.IsNullOrEmpty(userId)) return; // 创建 TiShi 弹窗(直接 Instantiate 拿引用,方便 60 秒后销毁) var prefab = UIManager.Instance.TiShiParefab; if (prefab == null) { Debug.LogWarning("[PendingRoomNotice] TiShiParefab 未赋值,自动离开"); WebSocketSendList.DismissPendingRoom(userId); _pendingRoomActive = false; return; } var obj = UnityEngine.Object.Instantiate(prefab, UIManager.Instance.uiRoot); obj.transform.SetAsLastSibling(); var tishi = obj.GetComponent(); if (tishi == null) { UnityEngine.Object.Destroy(obj); _pendingRoomActive = false; return; } // 标记用户是否已操作 bool acted = false; // 确认 = 返回房间 tishi.Init($"检测到您在 {data.gameType} {data.roomName} 有未完成的游戏,是否返回房间?", () => { acted = true; WebSocketSendList.Reconnect(userId); }); // 关闭 = 离开(额外给 btn_Close 加监听;TiShi.Close 本身只销毁不触发 action) if (tishi.btn_Close != null) { tishi.btn_Close.onClick.AddListener(() => { if (acted) return; acted = true; WebSocketSendList.DismissPendingRoom(userId); }); } // 60 秒无操作自动离开 WebSocketManager.Instance.StartCoroutine(PendingRoomCountdown( 60f, () => acted, () => { acted = true; WebSocketSendList.DismissPendingRoom(userId); if (obj != null) UnityEngine.Object.Destroy(obj); _pendingRoomActive = false; })); } /// 断线房间弹窗倒计时协程(到时检查是否已操作,未操作则触发回调) private static System.Collections.IEnumerator PendingRoomCountdown( float seconds, System.Func hasActed, System.Action onTimeout) { yield return new UnityEngine.WaitForSeconds(seconds); if (!hasActed()) onTimeout?.Invoke(); } /// /// LoginHub PendingRoomNotice 数据 /// [Serializable] public class PendingRoomData { public string roomId; public string gameType; public string roomName; } /// /// LoginHub AccountKicked — 账号被顶通知 /// 该账号在其他设备登录时,旧连接收到此事件。 /// 前端应提示"账号已在其他地方登录"并清空房间 UI、断开游戏连接。 /// public static void AccountKicked(string msg) { try { var data = JsonConvert.DeserializeObject>(msg).arguments[0]; var userId = GameManager.Instance?.user?.id; // 只处理当前登录用户被顶的情况 if (data != null && !string.IsNullOrEmpty(data.userId) && !string.IsNullOrEmpty(userId) && data.userId != userId) { UIManager.Instance.ShowTiShi("账号已在其他地方登录", () => { GameManager.Instance.Logout(); return; }); } } catch (Exception e) { Debug.LogWarning("[AccountKicked] 解析失败: " + e.Message); } // 提示并登出(Logout 已封装:CloseAll WebSocket + 清空用户 + 关闭所有 UI + 回登录界面) UIManager.Instance.ShowBoardError("账号已在其他地方登录"); GameManager.Instance.Logout(); } /// /// LoginHub AccountKicked 数据 /// [Serializable] public class AccountKickedData { public string userId; } // ---------------- FishGameHub 补充 ---------------- /// /// FishGameHub BotLeaveRoomNotice — 机器人退出房间 /// 仅触发对应座位显示等待,不影响本地玩家(自己退出走 LeaveRoomResult) /// public static void BotLeaveRoom(string botUserId) { if (string.IsNullOrEmpty(botUserId)) return; switch (GameManager.Instance.gameData.currGameType) { case GameType.FLZY: ReleaseBotSit(UIPanel.MainGamePanelFLZY, botUserId); break; case GameType.YYSC: ReleaseBotSit(UIPanel.MainGamePanelYYSC, botUserId); break; case GameType.XJMH: ReleaseBotSit(UIPanel.MainGamePanelXJMH, botUserId); break; case GameType.HHWK: ReleaseBotSit(UIPanel.MainGamePanelHHWK, botUserId); break; default: break; } } /// 释放机器人座位(显示等待界面,标记为 bot) private static void ReleaseBotSit(UIPanel panelName, string botUserId) { var panel = UIManager.Instance.Get(panelName); if (panel == null) return; foreach (var sit in panel.list_Sits) { if (sit.user == botUserId) { sit.isBot = true; sit.ShowWaiting(); break; } } } /// /// FishGameHub HostDisconnect — 房主断线 /// 其他玩家可接受机器人控制权。本地房主引用若已断线则转移给本地首个非人机玩家。 /// public static void HostDisconnect() { // 房主断线 → 触发房主转移(SitPosData 已封装好转移逻辑) SitPosData.TransferRoomOwner(); } /// /// FishGameHub OnSeatChange — 座位变更 /// { type, userId, position, showWaiting? } /// type 字段后端未明确定义,先按 showWaiting 决定显示状态 /// public static void SeatChange(int seatType, string userId, int position, bool showWaiting) { if (string.IsNullOrEmpty(userId) || position < 0) return; GameMainPanel_FishBase panel = null; switch (GameManager.Instance.gameData.currGameType) { case GameType.FLZY: panel = UIManager.Instance.Get(UIPanel.MainGamePanelFLZY); break; case GameType.YYSC: panel = UIManager.Instance.Get(UIPanel.MainGamePanelYYSC); break; case GameType.XJMH: panel = UIManager.Instance.Get(UIPanel.MainGamePanelXJMH); break; case GameType.HHWK: panel = UIManager.Instance.Get(UIPanel.MainGamePanelHHWK); break; default: break; } if (panel == null) return; var targetSit = panel.list_Sits.Find(s => s.posID == position); if (targetSit == null) return; if (showWaiting) { // 显示等待界面(玩家离开该座位) targetSit.ShowWaiting(); } else { // 玩家进入该座位 targetSit.isBot = !string.IsNullOrEmpty(userId) && userId.StartsWith("bot_"); } } /// /// FishRoomHub RoomChange — 房间变化通知 /// 房间列表界面收到时刷新显示。当前仅在房间列表 UI 开启时更新数据, /// 具体刷新逻辑由 UIHome_BY_SelectRoomLevelPanel / 手动选座面板按需实现。 /// public static void RoomChangeNotice(string msg) { try { var roomData = JsonConvert.DeserializeObject>(msg).arguments[0]; if (roomData == null) return; // 通知手动选座面板刷新(若开启) var homeMain = UIManager.Instance.Get(UIPanel.HomeMainPanel); if (homeMain == null) return; var selectRoomPanel = homeMain.subUIManager.Get(UIPanel.SelectRoomLeavePenel); if (selectRoomPanel != null && selectRoomPanel.isMySelectRoom) { selectRoomPanel.panel_UIHome_BY_MySelectRoomPenel?.OnRoomChange(roomData); } } catch (Exception e) { Debug.LogWarning("[RoomChangeNotice] 解析失败: " + e.Message); } } /// /// LoginHub LevelChanged 数据(字段名对齐后端大写首字母) /// [Serializable] public class LevelChangedData { public int NewLevel; public long NewExp; public long NewGold; public int NewDiamond; public string Source; public string Remark; } // ---------------- Customer ---------------- /// /// 发起会话回调(用户端) /// isOk=false 时弹错误提示;isOk=true 时自动加入会话房间 /// public static void Customer_OnConversationStarted(CustomerConversationStartedResult result) { if (!result.isOk) { UIManager.Instance.ShowBoardError(result.msg); return; } // 加入会话房间,之后才能收发消息 //WebSocketSendList.Customer_JoinConversation(result.conversation.id); // TODO: 通知客服 UI 显示会话(替换为你的实际 Panel 调用) UIManager.Instance.Get(UIPanel.HomeMainPanel).subUIManager.Get(UIPanel.ServicePanel)?.OnConversationStarted(result); } /// /// 消息接收回调(用户端 & 客服端) /// public static void Customer_OnMessageReceived(CustomerMessageReceived msg) { // TODO: 通知客服 UI 追加消息(替换为你的实际 Panel 调用) UIManager.Instance.Get(UIPanel.HomeMainPanel).subUIManager.Get(UIPanel.ServicePanel)?.OnMessageReceived(msg); Debug.Log($"[Customer] 收到消息 from {msg.senderName}({msg.senderType}): {msg.content}"); } /// /// 新会话通知(客服端) /// public static void Customer_OnNewConversation(CustomerNewConversationNotice notice) { // 客服端自动加入会话房间 WebSocketSendList.Customer_JoinConversation(notice.conversationId); // TODO: 通知客服端 UI 显示新会话(替换为你的实际 Panel 调用) // UIManager.Instance.Get(UIPanel.CustomerServicePanel)?.OnNewConversation(notice); Debug.Log($"[Customer] 新会话来了,userId={notice.userId},userName={notice.userName}"); } /// /// LoginHub Broadcast 数据 /// [Serializable] public class LoginBroadcastData { public string userName; public string avatarUrl; public int level; public int vipLevel; public string message; public long time; } /// /// LoginHub KillAnnouncement 数据(全局击杀公告) /// [Serializable] public class KillAnnouncementData { /// 公告文本(服务端已拼接:恭喜玩家*****在风雷之渊 高级场捕获 人鱼公主*2000倍 150000000大奖) public string text; /// 玩家名(已脱敏,全部替换为*) public string userName; /// 游戏类型名(如:风雷之渊) public string gameTypeName; /// 房间名(如:高级场) public string roomName; /// 鱼名称(如:人鱼公主) public string fishName; /// 炮台倍数 public int multiple; /// 获得金币 public long gold; /// 时间戳(Unix秒) public long time; } /// /// LoginHub AssetUpdated 数据 /// [Serializable] public class LoginAssetData { public int currencyType; public int changeType; public long amount; public long newGold; public int newDiamond; public string source; public string remark; } /// /// LoginHub BackpackUpdated 数据 /// [Serializable] public class LoginBackpackData { public string action; public string propNumber; public int count; public List props; } /// /// LoginHub NewEmail 数据 /// [Serializable] public class LoginNewEmailData { public string title; public string emailId; } } } // end namespace