using System; using MapServer; using System.Net; using System.Net.Sockets; using pb = global::Google.Protobuf; using NetData; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Diagnostics; using System.Linq; using System.Text; internal class MapTcpProxy : MonoSingleton { const int Port = 2333; static string IP = "192.168.10.86"; public MapPeer2 Peer { get; set; } private bool netFailed = false; protected override void OnAwake() { base.OnAwake(); ReConnect(); //if (GlobalConfig.netType != eNetType.LAN) //{ // var uri = "ylsjtt.game7000.com"; // IPHostEntry entry = Dns.GetHostEntry(uri); // if (entry != null && entry.AddressList != null && entry.AddressList.Length > 0) // { // IPAddress addr = entry.AddressList[0]; //使用时使用AddressList[0]即可 // IP = addr.ToString(); // } // //IP = "ylsjtt.game7000.com"; //} //this.Peer = new MapPeer2(IP, GlobalConfig.MapServerPort); //// todu: 重新登录时怎么处理重新连接的问题? --gwang //this.Peer.OnConnectClosed += Peer_OnConnectClosed; //this.Peer.OnReconnect += ()=> { Login(); return true; } ; } private void OnDisable() { this.Peer.OnConnectClosed -= Peer_OnConnectClosed; } private void OnEnable() { this.Peer.OnConnectClosed += Peer_OnConnectClosed; } private void Peer_OnConnectClosed() { LogHelper.Log("连接关闭事件:"); netFailed = true; } public event Func OnReconnect; public void ReConnect() { if (GlobalConfig.netType != eNetType.LAN) { var uri = "ylsjtt.game7000.com"; IPHostEntry entry = Dns.GetHostEntry(uri); if (entry != null && entry.AddressList != null && entry.AddressList.Length > 0) { IPAddress addr = entry.AddressList[0]; //使用时使用AddressList[0]即可 IP = addr.ToString(); } //IP = "ylsjtt.game7000.com"; } LogHelper.Log("创建连接"); this.Peer = new MapPeer2(IP, GlobalConfig.MapServerPort); // todu: 重新登录时怎么处理重新连接的问题? --gwang this.Peer.OnConnectClosed += Peer_OnConnectClosed; } private void OnApplicationFocus(bool focus) { LogHelper.Log("OnApplicationFocus" + focus); LogHelper.Log(TraceBack()); } private void OnApplicationPause(bool pause) { //this.Peer. LogHelper.Log("OnApplicationPause" + pause); LogHelper.Log(TraceBack()); } static string TraceBack() // 打印调用到这里的栈信息 { var sb = new StringBuilder(); StackTrace st = new StackTrace(); StackFrame[] sf = st.GetFrames(); sf.ToList().ForEach(curSf => sb.AppendLine($"{curSf}")); return sb.ToString(); } // public void Login() { try { netFailed = false; this.Peer?.Login(); LogHelper.Log("身份认证!"); } catch(Exception e) { LogHelper.Log(e.Message); } } public void LogOut() { this.Peer.LogOut(); } public void Update() { Peer?.Update(); //LogHelper.Log($"tts: {Peer.tts}ms"); if (netFailed) { UI_CueDialog.Instance().Open("与服务器的连接断开, 尝试重新建立连接", "网络故障", E_DialogType.OneButton, () => { ReConnect(); Login(); }); //UI_CueDialog.Instance().Open("与游戏服务器的连接断开, 请检查网络.", "网络故障", E_DialogType.OneButton, UnityEngine.Application.Quit); } } protected override void DoOnDestroy() { base.DoOnDestroy(); this.Peer?.Close(); } } /// /// 地图长连服务器3代 /// internal class MapPeer2 : PeerBase { /// /// (玩家数据)模块名称 /// public enum EModName { Unkowm = 0, MapData = 1, CmptMgr, NpcMgr, SpawnerMgr, SpawnerMgr_Spawner, SpawnerMgr_Spawner_Role, Player = 100, Player_hero, } protected readonly Random r = new Random(); // 随机数 private string ip; private int port; public MapPeer2(string Ip, int Port) : base(Ip, Port) { ip = Ip; port = Port; //OnDisconnect += MapPeer2_OnDisconnect; // 添加重连处理机制 } #region //virtual protected bool OnConnectReset() //{ // if (UnityEngine.Application.isPlaying) // { // Log("断线重连"); // Login(); // return true; // } // else // { // Log("停止播放断线不重连"); // return false; // } //} #endregion public Info_Map? MapData { get; private set; } public Info_Map_Player Player { get; private set; } /// /// 注册服务端消息处理逻辑 /// protected override void InitDispatch() { base.InitDispatch(); this.callbacks[eProtocalCommand.ScMapLoginRet] = On_LoginOk; // 登录成功 this.callbacks[eProtocalCommand.ScMapLogOutRet] = On_GameOver; // 登出成功 this.callbacks[eProtocalCommand.ScMapDataChange] = On_update; // 数据更新 this.callbacks[eProtocalCommand.ScMapSwitchMapRet] = On_SwitchMapReturn; // 地图切换 } #region 消息处理逻辑 /// /// 处理服务端登录成功消息 /// /// void On_LoginOk(byte[] data) { var msg = SC_login_ret.Parser.ParseFrom(data); // todo: 这里目前就只有mapdata一个模块, 后面可以考虑拆分多个模块 var jobj = JObject.Parse(msg.MapJsonData); this.MapData = jobj.ToObject();// Newtonsoft.Json.JsonConvert.DeserializeObject(msg.MapJsonData); this.Player = JObject.Parse(msg.PlayerJsonData).ToObject(); // 玩家数据 this.MapData.PropertyChanged += (s, e) => ReportDataChange(this.MapData); // 当数据有变化的时候上报 // todo: 这里是设置一个状态值, 还是说做个message通知给前端? LogHelper.Log("地图登录成功: " + msg.MapJsonData); //LogHelper.LogWarning("测试warning文本颜色"); //LogHelper.LogError("测试Error文本颜色"); } /// /// 处理服务端更新数据消息 /// void On_update(byte[] data) { var msg = SC_DataChange.Parser.ParseFrom(data); // todo: 这里目前就只有mapdata一个模块, 后面可以考虑拆分多个模块 foreach (var kv in msg.ChangedMods) { var mod = Enum.Parse(kv.Key); switch (mod) { case EModName.MapData: // 地图数据模块 // this.MapData = Newtonsoft.Json.JsonConvert.DeserializeObject(kv.Value); var jobj = JObject.Parse(kv.Value); this.MapData = jobj.ToObject();// Newtonsoft.Json.JsonConvert.DeserializeObject(msg.MapJsonData); //this.MapData.CheckJsonRaw(jobj); break; default: LogHelper.Log("未知模块!"); break; } } LogHelper.Log("地图数据有更新: " + msg.ChangedMods); } /// /// 处理服务端返回登出成功消息 /// void On_GameOver(byte[] data) { var msg = SC_LogOut_ret.Parser.ParseFrom(data); LogHelper.Log("地图模块退出成功: " + msg.ToString()); Close(); // 通知recv协程退出循环 } void On_SwitchMapReturn(byte[] data) { var msg = SC_SwitchMap_ret.Parser.ParseFrom(data); LogHelper.Log("切换到新地图成功:" + msg.ToString()); var jobj = JObject.Parse(msg.MapJsonData); this.MapData = jobj.ToObject(); // Newtonsoft.Json.JsonConvert.DeserializeObject(msg.MapJsonData); this.MapData.PropertyChanged += (s, e) => ReportDataChange(this.MapData); // 当数据有变化的时候上报 this.Player = JsonConvert.DeserializeObject(msg.PlayerJsonData); if (OnSwitchedNextMap != null) { OnSwitchedNextMap.Invoke(MapData); OnSwitchedNextMap = null; } } /// /// 暂存回调函数. /// private Action OnSwitchedNextMap; #endregion #region 客户端访问接口 public void LogOut() { SendMsg(eProtocalCommand.CsMapLogOut, new CS_LogOut()); LogHelper.Log("地图 登出"); } public void Login() { var p = UserProxy.Instance.player; var msg = new CS_login() { Uid = p.uid, Zoneid = p.zoneid, CurMapId = p.newMap.curMapId }; SendMsg(eProtocalCommand.CsMapLogin, msg); LogHelper.Log("地图 登录"); } #region 上报数据接口(多个重载) /// /// 上报数据发生变化 /// public void ReportDataChange(Info_Map mapInfo) { this.MapData = mapInfo; this.MapData.PropertyChanged += (s, e) => ReportDataChange(this.MapData); // 当数据有变化的时候上报 if (sm_gate.GetMoById(mapInfo.mapId)?.mapType < 4) { var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.MapData.ToString(), mapInfo.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); } } /// /// 上报数据发生变化 /// public void ReportDataChange(Info_Map_CmptMgr cpmMgr) { var p = UserProxy.Instance.player; if (sm_gate.GetMoById(p.newMap.curMapId)?.mapType < 4) { var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.CmptMgr.ToString(), cpmMgr.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); MapData.cmptMgr = cpmMgr; } } /// /// 上报数据发生变化 /// public void ReportDataChange(Info_Map_NpcMgr npcMgr) { var p = UserProxy.Instance.player; if (sm_gate.GetMoById(p.newMap.curMapId)?.mapType < 4) { var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.NpcMgr.ToString(), npcMgr.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); MapData.npcMgr = npcMgr; } } /// /// 上报数据发生变化 /// public void ReportDataChange(Info_Map_SpawnerMgr spwMgr) { var p = UserProxy.Instance.player; if (sm_gate.GetMoById(p.newMap.curMapId)?.mapType < 4) { var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.SpawnerMgr.ToString(), spwMgr.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); MapData.spnSys = spwMgr; } } /// /// 上报数据发生变化 /// public void ReportDataChange(Info_Map_Spawner spwnr) { var p = UserProxy.Instance.player; if (sm_gate.GetMoById(p.newMap.curMapId)?.mapType < 4) { var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.SpawnerMgr_Spawner.ToString(), spwnr.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); MapData.spnSys._spawnerDict[spwnr.spawnerId] = spwnr; } } internal class Msg_SwawnerRoleInfo { public int SpawnerId; public int RoleId; public Info_Map_RoleData roleData; } /// /// 上报数据发生变化(roleInfo:hp,pos等) /// public void ReportDataChange(int spwnrId, int roleId) { var data = new Msg_SwawnerRoleInfo(); data.SpawnerId = spwnrId; data.RoleId = roleId; if (MapData.spnSys._spawnerDict.ContainsKey(spwnrId) && MapData.spnSys._spawnerDict[spwnrId].roleDict.ContainsKey(roleId)) // 防御对象已被移除 { data.roleData = MapData.spnSys._spawnerDict[spwnrId]?.roleDict[roleId] ?? null; var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.SpawnerMgr_Spawner_Role.ToString(), JsonConvert.SerializeObject(data) } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); MapData.spnSys._spawnerDict[spwnrId].roleDict[roleId] = data.roleData; } } /// /// 上报数据发生变化(玩家信息) /// /// public void ReportDataChange(Info_Map_Player player) { var p = UserProxy.Instance.player; var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.Player.ToString(), player.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); this.Player = player; } /// /// /// /// public void ReportDataChange(Info_Map_Player_Hero hero) { var p = UserProxy.Instance.player; var msg = new CS_DataChange(); var kv = new pb.Collections.MapField() { { EModName.Player_hero.ToString(), hero.Json() } };// 地图模块数据 msg.ChangedMods.Add(kv); LogHelper.Log($"上报地图信息{msg}"); SendMsg(eProtocalCommand.CsMapDataChange, msg); if (hero.hp <= 0) { hero.hp = hero.hpMax; } Player.heroDict[hero.uid] = hero; } #endregion /// /// 切换到下一个地图 /// /// /// 唤灵师当前点位(再回这张地图时用) /// public void SwitchNextMap(int targetMapId, int curPoint, Action callback) { if (callback != null) { OnSwitchedNextMap = callback; } var msg = new CS_SwitchMap() { TargetMapId = targetMapId, CurBirthPoint = curPoint }; LogHelper.Log($"切换到下一地图{targetMapId}"); SendMsg(eProtocalCommand.CsMapSwitchMap, msg); } #endregion }