using Assets.MyGame.Scripts.Net.API;
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)
{
// ⭐ 只反序列化一次复用(金币流水 / currRoomData.players 补齐 / 座位激活)
RoomJoinNotice notice = null;
try
{
notice = JsonConvert.DeserializeObject>(msg).arguments[0];
}
catch { }
// ⭐ 记录金币流水:收到加钱信息(RoomJoinNotice 推送,尚未执行)—— 只记录自己
try
{
string myId = GameManager.Instance.user?.id;
if (notice != null && !string.IsNullOrEmpty(myId) && notice.UserId == myId)
{
GameManager.LogGoldFlowReceiveGain("RoomJoinNotice", $"推送金币={notice.Gold} 钻石={notice.Diamond} 炮台消耗={notice.CannonMultiple} 座位={notice.Position}");
}
}
catch { }
// ⭐ 修复:把加入玩家 upsert 进 currRoomData.players。
// JoinGame 里 SetUserInfo 按 userId 从 currRoomData.players 查显示信息
// (昵称/头像/VIP/短编号),而 currRoomData 只在本地进房收到 RoomInfo 时写一次,
// 后加入的玩家不在快照里 → 老客户端把他显示成匿名(无昵称/默认头像/原始32位长ID)。
// RoomJoinNotice 自带完整玩家数据,这里补进快照后再走 JoinGame。
UpsertPlayerToCurrRoom(notice);
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 && notice != null)
{
// 如果座位被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, notice.WarGodId);
// 后端动态加入的机器人也要标记
if (targetSit != null && !string.IsNullOrEmpty(notice.UserId) && notice.UserId.StartsWith("bot_"))
targetSit.isBot = true;
}
}
}
///
/// 把 RoomJoinNotice 玩家数据写入 currRoomData.players(存在则更新,不存在则添加)。
/// JoinGame 里 SetUserInfo 按 userId 从 currRoomData.players 查显示信息
/// (昵称/头像/VIP/短编号),后加入的玩家不在快照里会显示成匿名玩家。
///
private static void UpsertPlayerToCurrRoom(RoomJoinNotice notice)
{
if (notice == null || string.IsNullOrEmpty(notice.UserId)) return;
var roomData = GameManager.Instance.gameData?.currRoomData;
if (roomData == null) return;
if (roomData.players == null) roomData.players = new List();
var p = roomData.players.Find(x => x.userId == notice.UserId);
if (p == null)
{
p = new RoomPlayerInfo();
roomData.players.Add(p);
}
p.userId = notice.UserId;
p.userName = notice.UserName;
p.userNumber = notice.UserNumber;
p.avatar = notice.Avatar;
p.isRedName = notice.IsRedName;
p.level = notice.Level;
p.exp = notice.Exp;
p.maxExp = notice.MaxExp;
p.vipLevel = notice.VipLevel;
p.cId = notice.CId;
p.gold = notice.Gold;
p.diamond = notice.Diamond;
p.position = notice.Position;
p.cannonId = notice.CannonId;
p.wingsId = notice.WingsId;
p.warGodId = notice.WarGodId;
p.cannonMultiple = notice.CannonMultiple;
p.beginCoin = notice.BeginCoin;
p.beginTime = notice.BeginTime;
p.state = notice.State;
p.playerFactor = notice.PlayerFactor;
p.totalRechargeGold = notice.TotalRechargeGold;
p.safeBoxGold = notice.SafeBoxGold;
p.isBot = notice.IsBot;
p.isAfk = notice.IsAfk;
}
///
/// 房间列表 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:
UpdateLocalPlayerGold(UIPanel.MainGamePanelDefault, gold);
break;
case GameType.FLZY:
UpdateLocalPlayerGold(UIPanel.MainGamePanelFLZY, gold);
break;
case GameType.YYSC:
UpdateLocalPlayerGold(UIPanel.MainGamePanelYYSC, gold);
break;
case GameType.ZGXQ:
break;
case GameType.XJMH:
UpdateLocalPlayerGold(UIPanel.MainGamePanelXJMH, gold);
break;
case GameType.HHWK:
UpdateLocalPlayerGold(UIPanel.MainGamePanelHHWK, gold);
break;
default:
break;
}
}
///
/// 炮倍变更通知:服务端确认玩家炮倍切换后广播给房间内所有玩家。
/// 客户端收到后才应用新炮倍到 consumeGoldNum 和 UI,避免开火扣费不一致。
///
public static void ChangeGunMultipleNotice(string msg)
{
var data = JsonConvert.DeserializeObject>(msg).arguments[0];
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) return;
panel.ApplyCannonMultiple(data.userId, data.multiple);
}
///
/// 后端推送 SyncPlayerGold 时同步本地玩家金币(底层值 + UI 显示)。
/// 之前只更新 goldNum 不刷新 tMP_GoldNum.text,导致 UI 显示和后端 authoritative 值不同步,
/// 后续杀鱼累加基于修正值但 UI 显示旧值,差距越拉越大。
///
private static void UpdateLocalPlayerGold(UIPanel panelType, long gold)
{
var panel = UIManager.Instance.Get(panelType);
if (panel == null || panel.currSitData == null) return;
long oldGold = panel.currSitData.goldNum;
long diff = gold - oldGold;
// ⭐ 记录金币流水:收到后端推送 SyncPlayerGold(尚未执行)
if (diff > 0)
GameManager.LogGoldFlowReceiveGain("SyncPlayerGold", $"推送金币={gold} 修正前金币={oldGold} 差值=+{diff} 座位={panel.currSitData.posID}");
else if (diff < 0)
GameManager.LogGoldFlowReceiveCost("SyncPlayerGold", $"推送金币={gold} 修正前金币={oldGold} 差值={diff} 座位={panel.currSitData.posID}");
panel.currSitData.goldNum = gold;
if (panel.currSitData.tMP_GoldNum != null)
panel.currSitData.tMP_GoldNum.text = gold.ToString();
// ⭐ 记录金币流水:已执行修正(本地已写入)
if (diff > 0)
GameManager.LogGoldFlowAppliedGain("SyncPlayerGold", $"已修正金币={gold} 修正前金币={oldGold} 增加金币=+{diff} 座位={panel.currSitData.posID}");
else if (diff < 0)
GameManager.LogGoldFlowAppliedCost("SyncPlayerGold", $"已修正金币={gold} 修正前金币={oldGold} 扣除金币={diff} 座位={panel.currSitData.posID}");
}
public static void GetRoomInfoResult(string msg)
{
//GameManager.Instance.StartGame();RoomChangeResponse
var roomData = JsonConvert.DeserializeObject>(msg).arguments[0];
// ⭐ 记录金币流水:收到加钱信息(RoomInfo 推送玩家金币,尚未执行)—— 只记录自己
if (roomData?.players != null)
{
string myId = GameManager.Instance.user?.id;
foreach (var p in roomData.players)
{
if (string.IsNullOrEmpty(myId) || p.userId != myId) continue;
GameManager.LogGoldFlowReceiveGain("RoomInfo", $"推送金币={p.gold} 钻石={p.diamond} 炮台消耗={p.cannonMultiple} 座位={p.position} 房间={roomData.roomId}");
}
}
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;
// createFish=3 已废弃:鱼创建改由服务端 OnFishSpawn 事件下发
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.changeZhanShen:
EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_ChangeZhanShen, syncGameData);
break;
case FrameDataType.biaoQing:
EventCenter.Instance.EventTrigger(ConstEventString.SyncGameData_BiaoQing, syncGameData);
break;
// requestSyncFish=11 已废弃:鱼同步改由服务端 OnFishSpawn(type=sync) 下发
case FrameDataType.baoJiangEnd:
EventCenter.Instance.EventTrigger(ConstEventString.BaoJiangEnd, syncGameData);
break;
default:
break;
}
}
// ================================================================
// 新协议事件分发 (OnFishSpawn / PlayerAfk / FishFrozen / KillNotice 等)
// ================================================================
///
/// 服务端出鱼事件 OnFishSpawn 处理。
/// 破坏性替代旧 createFish 帧同步:服务端统一出鱼,客户端只接收并生成。
///
public static void OnFishSpawn(string msg)
{
var data = JsonConvert.DeserializeObject>(msg).arguments[0];
if (data == null) return;
EventCenter.Instance.EventTrigger(ConstEventString.OnFishSpawn, data);
NetLog.Log("出鱼:", msg);
}
/// 鱼列表刷新
public static void OnFishList(string msg)
{
var fishList = JsonConvert.DeserializeObject>(msg).arguments[0];
EventCenter.Instance.EventTrigger