using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Library.Common.Network; using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Exception; namespace Milimoe.FunGame.Core.Controller { /// /// 此类实现服务器连接、断开连接、心跳检测、创建数据请求等功能 /// -- 需要继承并实现部分方法 -- /// public abstract class RunTimeController { /// /// 与服务器的连接套接字实例 /// public Socket? Socket => _Socket; /// /// 套接字是否已经连接 /// public bool Connected => _Socket != null && _Socket.Connected; /// /// 接收服务器信息的线程 /// protected Task? _ReceivingTask; /// /// 用于类内赋值 /// protected Socket? _Socket; /// /// 是否正在接收服务器信息 /// protected bool _IsReceiving; /// /// 断开服务器连接 /// /// public bool Disconnect() { bool result = false; try { result = _Socket?.Send(SocketMessageType.Disconnect, "") == SocketResult.Success; } catch (Exception e) { WritelnSystemInfo(e.GetErrorInfo()); } return result; } /// /// 连接服务器 /// /// /// /// public ConnectResult Connect(string ip, int port) { if (!BeforeConnect(ref ip, ref port)) { return ConnectResult.ConnectFailed; } ConnectResult result = ConnectResult.Success; string msg = ""; string servername = ""; string notice = ""; // 检查服务器IP地址和端口是否正确 if (ip == "" || port <= 0) { result = ConnectResult.FindServerFailed; } if (result == ConnectResult.Success) { // 与服务器建立连接 _Socket?.Close(); _Socket = Socket.Connect(ip, port); if (_Socket != null && _Socket.Connected) { if (_Socket.Send(SocketMessageType.Connect) == SocketResult.Success) { SocketObject[] objs = _Socket.ReceiveArray(); foreach (SocketObject obj in objs) { if (obj.SocketType == SocketMessageType.Connect) { bool success = obj.GetParam(0); msg = obj.GetParam(1) ?? ""; result = success ? ConnectResult.Success : ConnectResult.ConnectFailed; if (success) { _Socket.Token = obj.GetParam(2); servername = obj.GetParam(3) ?? ""; notice = obj.GetParam(4) ?? ""; StartReceiving(); Task.Run(() => { while (true) { if (_IsReceiving) { break; } } }); } } } } else result = ConnectResult.ConnectFailed; } else _Socket?.Close(); } object[] ConnectArgs = new object[] { result, msg, servername, notice }; AfterConnect(ConnectArgs); // 允许修改数组中的result,强行改变连接的结果 return (ConnectResult)ConnectArgs[0]; } /// /// 获取服务器地址 /// /// string:IP地址;int:端口号 /// public (string, int) GetServerAddress() { try { string? ipaddress = (string?)Implement.GetFunGameImplValue(InterfaceType.IClient, InterfaceMethod.RemoteServerIP); if (ipaddress != null) { string[] s = ipaddress.Split(':'); if (s != null && s.Length > 1) { return (s[0], Convert.ToInt32(s[1])); } } throw new FindServerFailedException(); } catch (FindServerFailedException e) { WritelnSystemInfo(e.GetErrorInfo()); return ("", 0); } } /// /// 此方法将在连接服务器前触发 /// 客户端可以重写此方法 /// /// /// /// false:中止连接 public virtual bool BeforeConnect(ref string ip, ref int port) { return true; } /// /// 此方法将在连接服务器后触发(Connect结果返回前) /// 客户端可以重写此方法 /// /// 连接服务器后返回的一些数据,可以使用也可以修改它们 /// public virtual void AfterConnect(object[] ConnectArgs) { } /// /// 客户端需要自行实现自动登录的事务 /// public abstract void AutoLogin(string Username, string Password, string AutoKey); /// /// 关闭所有连接 /// /// public bool Close() { try { if (_Socket != null) { _Socket.Close(); _Socket = null; } if (_ReceivingTask != null && !_ReceivingTask.IsCompleted) { _ReceivingTask.Wait(1); _ReceivingTask = null; _IsReceiving = false; } } catch (Exception e) { WritelnSystemInfo(e.GetErrorInfo()); return false; } return true; } /// /// 输出消息 /// /// public abstract void WritelnSystemInfo(string msg); /// /// 自定处理异常的方法 /// -- 一般放在catch中 -- /// /// public abstract void Error(Exception e); /// /// 基于本地已连接的Socket创建新的数据请求 /// /// /// /// public DataRequest NewDataRequest(DataRequestType RequestType) { if (_Socket != null) { DataRequest request = new(_Socket, RequestType); return request; } throw new ConnectFailedException(); } /// /// 基于本地已连接的Socket创建长时间运行的数据请求 /// /// /// /// public DataRequest NewLongRunningDataRequest(DataRequestType RequestType) { if (_Socket != null) { DataRequest request = new(_Socket, RequestType, true); return request; } throw new ConnectFailedException(); } /// /// 开始接收服务器信息 /// protected void StartReceiving() { _ReceivingTask = Task.Factory.StartNew(() => { Thread.Sleep(100); _IsReceiving = true; while (Connected) { Receiving(); } }); _Socket?.StartReceiving(_ReceivingTask); } /// /// 获取服务器已发送的信息为SocketObject数组 /// /// protected SocketObject[] GetServerMessage() { if (_Socket != null && _Socket.Connected) { return _Socket.ReceiveArray(); } return Array.Empty(); } /// /// 具体接收服务器信息以及处理信息的方法 /// /// protected SocketMessageType Receiving() { if (_Socket is null) return SocketMessageType.Unknown; SocketMessageType result = SocketMessageType.Unknown; try { SocketObject[] ServerMessages = GetServerMessage(); foreach (SocketObject ServerMessage in ServerMessages) { SocketMessageType type = ServerMessage.SocketType; object[] objs = ServerMessage.Parameters; result = type; switch (type) { case SocketMessageType.Disconnect: Close(); SocketHandler_Disconnect(ServerMessage); break; case SocketMessageType.System: SocketHandler_System(ServerMessage); break; case SocketMessageType.HeartBeat: SocketHandler_HeartBeat(ServerMessage); break; case SocketMessageType.ForceLogout: SocketHandler_ForceLogout(ServerMessage); break; case SocketMessageType.Chat: SocketHandler_Chat(ServerMessage); break; case SocketMessageType.UpdateRoomMaster: SocketHandler_UpdateRoomMaster(ServerMessage); break; case SocketMessageType.MatchRoom: SocketHandler_MatchRoom(ServerMessage); break; case SocketMessageType.StartGame: SocketHandler_StartGame(ServerMessage); break; case SocketMessageType.EndGame: SocketHandler_EndGame(ServerMessage); break; case SocketMessageType.Gaming: SocketHandler_Gaming(ServerMessage); break; case SocketMessageType.Unknown: default: break; } } } catch (Exception e) { // 报错中断服务器连接 Error(e); } return result; } /// /// 客户端接收到服务器断开连接的通知后的处理方法 /// /// protected abstract void SocketHandler_Disconnect(SocketObject ServerMessage); /// /// 客户端接收到服务器系统消息后的处理方法 /// /// protected abstract void SocketHandler_System(SocketObject ServerMessage); /// /// 客户端接收到服务器心跳后的处理方法 /// /// protected abstract void SocketHandler_HeartBeat(SocketObject ServerMessage); /// /// 客户端接收到强制退出登录的通知后的处理方法 /// /// protected abstract void SocketHandler_ForceLogout(SocketObject ServerMessage); /// /// 客户端接收到聊天信息后的处理方法 /// /// protected abstract void SocketHandler_Chat(SocketObject ServerMessage); /// /// 客户端接收到更换房主后的处理方法 /// /// protected abstract void SocketHandler_UpdateRoomMaster(SocketObject ServerMessage); /// /// 客户端接收到匹配房间成功后的处理方法 /// /// protected abstract void SocketHandler_MatchRoom(SocketObject ServerMessage); /// /// 客户端接收到开始游戏信息后的处理方法 /// /// protected abstract void SocketHandler_StartGame(SocketObject ServerMessage); /// /// 客户端接收到游戏结束信息后的处理方法 /// /// protected abstract void SocketHandler_EndGame(SocketObject ServerMessage); /// /// 客户端接收到局内消息后的处理方法 /// /// protected abstract void SocketHandler_Gaming(SocketObject ServerMessage); } }