using System.Collections; 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 bool EndGame() { bool result = false; try { result = _Socket?.Send(SocketMessageType.EndGame, "") == SocketResult.Success; } catch (Exception e) { WritelnSystemInfo(e.GetErrorInfo()); } return result; } /// /// 连接服务器 /// /// /// /// public ConnectResult Connect(string addr, int port) { ArrayList ConnectArgs = []; if (!BeforeConnect(ref addr, ref port, ConnectArgs)) { return ConnectResult.ConnectFailed; } ConnectResult result = ConnectResult.Success; string msg = ""; string servername = ""; string notice = ""; // 检查服务器IP地址和端口是否正确 if (addr == "" || port <= 0) { result = ConnectResult.FindServerFailed; } if (result == ConnectResult.Success) { // 与服务器建立连接 _Socket?.Close(); _Socket = Socket.Connect(addr, port); if (_Socket != null && _Socket.Connected) { if (_Socket.Send(SocketMessageType.Connect, ConnectArgs.Cast().ToArray()) == SocketResult.Success) { SocketObject[] objs = _Socket.Receive(); 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(); } ConnectArgs.Clear(); ConnectArgs = [result, msg, servername, notice]; AfterConnect(ConnectArgs); // 允许修改数组中的result,强行改变连接的结果 if (ConnectArgs.Count > 0) { result = (ConnectResult?)ConnectArgs[0] ?? result; } return result; } /// /// 获取服务器地址 /// /// 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); } } /// /// 此方法将在连接服务器前触发 /// 客户端可以重写此方法 /// /// 服务器IP /// 服务器端口 /// 重写时可以提供额外的连接参数 /// false:中止连接 public virtual bool BeforeConnect(ref string ip, ref int port, ArrayList args) { return true; } /// /// 此方法将在连接服务器后触发(Connect结果返回前) /// 客户端可以重写此方法 /// /// 连接服务器后返回的一些数据,可以使用也可以修改它们 /// public virtual void AfterConnect(ArrayList 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.Receive(); } return []; } /// /// 具体接收服务器信息以及处理信息的方法 /// /// 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); } }