using Fleck; namespace BattleServer { /// /// 客户端链接对象 /// class Client { private IWebSocketConnection socket; public Client(IWebSocketConnection _socket) { socket = _socket; socket.OnBinary = doBinary; // socket.OnClose = close; socket.OnError = onError; } private void onError(Exception e) { Console.WriteLine("onError {0}", e.Message); socket.Close(); Service.Instance.Shutdown(this); } // private void close() // { // Console.WriteLine("close !"); // Service.Instance.Shutdown(this); // } /// /// 接收rpc数据 /// /// private void doBinary(byte[] message) { BattleRpcMessage msg = ProtoDeSerialize(message); // if (msg.method != "Heartbeat") // Console.WriteLine("接收到消息 {0}", msg.method); // Pb.BattleRpcMessage msg = Deserialize(message); Task t = Task.Run(() => { handle(msg); }); t.ContinueWith(r => { string Exception = Convert.ToString(t.Exception); Console.WriteLine("消息处理异常:" + Exception); }, TaskContinuationOptions.OnlyOnFaulted); } /// /// 处理远程请求 /// /// private void handle(BattleRpcMessage msg) { byte[] _msg; // long ts = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; // Console.WriteLine("接收到战斗消息 1 {0}|{1}",msg.method,ts); switch (msg.method) { case "Check": //校验战报 BattleReport report = ProtoDeSerialize(msg.data.value); // DateTime startTime = DateTime.Now; bool issucc = HotUpdateScripts.FightRunnerMgr.Instance.VerifyOnceFight(report); // DateTime endTime = DateTime.Now; // Console.WriteLine($"耗时: {(endTime - startTime).TotalMilliseconds} 毫秒"); msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleCheckResults", value = ProtoSerialize(new BattleCheckResults { ischeck = issucc }), }; _msg = ProtoSerialize(msg); // ts = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; // Console.WriteLine("接收到战斗消息 4 |{0}",ts); socket.Send(_msg); break; case "Run": //运行战斗 BattleRunReq runreq = ProtoDeSerialize(msg.data.value); BattleReport[] reports = new BattleReport[runreq.info.Count]; for (int i = 0; i < runreq.info.Count; i++) { var respaction = () => { bool isfinsh = true; for (int i = 0; i < reports.Length; i++) { if (reports[i] == null) { isfinsh = false; } } if (isfinsh) { msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleRunResp", value = ProtoSerialize(new BattleRunResp { reports = reports.ToList() }), }; _msg = ProtoSerialize(msg); socket.Send(_msg); } }; HotUpdateScripts.FightRunnerMgr.Instance.RunOnceFight(runreq.info[i], (issucc) => { if (!issucc) { int index = i; reports[index] = new BattleReport() { info = runreq.info[index], winSide = 2, }; respaction(); } }, (report) => { int index = i; reports[index] = report; respaction(); }); } break; case "GetInfo": //获取战斗场景 // Console.WriteLine("处理GetInfoPVP !"); BattleGetInfoReq req = ProtoDeSerialize(msg.data.value); BattleStateInfo info = HotUpdateScripts.FightRunnerMgr.Instance.GetPvpStateInfo(req.battleid); msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleGetInfoResp", value = ProtoSerialize(new BattleGetInfoResp { battleid = req.battleid, info = info, }), }; _msg = ProtoSerialize(msg); socket.Send(_msg); // Console.WriteLine("处理GetInfo end !"); break; case "Create": //创建战斗场景 // Console.WriteLine("处理CreatePVP !"); BattleCreateServerReq CreateReq = ProtoDeSerialize(msg.data.value); HotUpdateScripts.FightRunnerMgr.Instance.StartPvp(CreateReq.info, this.OnOutCmd, this.OnFinish, (issucc) => { msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleCreateServerResp", value = ProtoSerialize(new BattleCreateServerResp { issucc = issucc }), }; _msg = ProtoSerialize(msg); socket.Send(_msg); // Console.WriteLine("处理CreatePVP end !"); }); break; case "InCmd": //向战斗场景输入指令 // Console.WriteLine("处理InCmd !"); BattleInCmdReq InCmdReq = ProtoDeSerialize(msg.data.value); HotUpdateScripts.FightRunnerMgr.Instance.PvpInput(InCmdReq.battleid, InCmdReq.side, InCmdReq.@in, (issucc) => { // Console.WriteLine("处理InCmd 1------- end !"); msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleInCmdResp", value = ProtoSerialize(new BattleInCmdResp { issucc = issucc }), }; _msg = ProtoSerialize(msg); socket.Send(_msg); // Console.WriteLine("处理InCmd 1------- end !"); }); break; case "Concede": //向战斗场景输入指令 // Console.WriteLine("处理 Concede !"); BattleConcedeReq ConcedeReq = ProtoDeSerialize(msg.data.value); HotUpdateScripts.FightRunnerMgr.Instance.InitiativeFail(ConcedeReq.battleid, ConcedeReq.side, (issucc) => { msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleConcedeResp", value = ProtoSerialize(new BattleConcedeResp { issucc = issucc }), }; _msg = ProtoSerialize(msg); socket.Send(_msg); // Console.WriteLine("处理 Concede end !"); }); break; } } private void OnOutCmd(string bid, List cmd) { // Console.WriteLine("----------------------OnOutCmd {0}:{1}", bid, cmd.cmdtype); // foreach (var item in cmd) // { // Console.WriteLine("----------------------OnOutCmd {0}:{1}", bid, item.cmdtype); // } BattleRpcMessage msg = new BattleRpcMessage(); msg.method = "BattleOutCmd"; msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleOutCmdPush", value = ProtoSerialize(new BattleOutCmdPush { battleid = bid, cmd = cmd, }), }; byte[] data = ProtoSerialize(msg); socket.Send(data); } private void OnFinish(BattleCmd cmd) { ComEndFight _cmd = HotUpdateScripts.FightCmdUtil.PasreCmd(cmd) as ComEndFight; // Console.WriteLine("----------------------OnFinish {0}", _cmd.fightId); BattleRpcMessage msg = new BattleRpcMessage(); msg.method = "BattleFished"; msg.data = new Google.Protobuf.WellKnownTypes.Any { type_url = "type.googleapis.com/BattleFinishPush", value = ProtoSerialize(new BattleFinishPush { battleid = _cmd.fightId, winSide = _cmd.winSide }), }; byte[] data = ProtoSerialize(msg); Task t = Task.Run(() => { Thread.Sleep(1000); socket.Send(data); }); t.ContinueWith(r => { string Exception = Convert.ToString(t.Exception); // Console.WriteLine("OnFinish 异常处理:" + Exception); }, TaskContinuationOptions.OnlyOnFaulted); } /// /// 序列化并返回二进制 /// Serialize an Object and return byte[] /// /// /// public static byte[] ProtoSerialize(T obj) where T : class { using (var stream = new MemoryStream()) { ProtoBuf.Serializer.Serialize(stream, obj); return stream.ToArray(); } } /// /// 通过二进制反序列化 /// Deserialize with byte[] /// /// /// /// public static T ProtoDeSerialize(byte[] msg) where T : class { msg = msg == null ? new byte[] { } : msg; using (var ms = new MemoryStream(msg)) { var data = ProtoBuf.Serializer.Deserialize(ms); return data; } } } }