using System; using GameDAL.FriendRoom; using Server.Data.Module; using Server.Data; using GameData; using Server.Pack; using MrWu.Debug; using Server.MQ; using Game.Player; using MrWu.Basic; using System.Collections; using System.Threading.Tasks; using System.Collections.Generic; using StackExchange.Redis; using System.Linq; using GameDAL; using GameMessage; using Server.AliyunSDK.SLSLog; using Server.Config; namespace Server { /// /// 朋友房管理 /// public partial class FriendRoomManager { /// /// 实例 /// public static FriendRoomManager instance { get; private set; } private FriendRoomManager() { int len = allDesks.Length; for (int i = 0; i < len; i++) { allDesks[i] = new Dictionary(); } } static FriendRoomManager() { instance = new FriendRoomManager(); } /// /// 朋友房所在的厅 /// private TingManager_Friend ting; /// /// 朋友房所在的城堡 /// private RoomManager_Friend room; /// /// 朋友房的桌子 /// public readonly Dictionary[] allDesks = new Dictionary[10]; /// /// 初始化 /// /// /// public void Init(RoomManager room, TingManager ting) { this.room = room as RoomManager_Friend; this.ting = ting as TingManager_Friend; } /// /// 得到一个新的房间号 /// /// private int GetNewRoomNum() { int roomnum = Room.GetRoomNum(); return CheckRoom(roomnum, 0); } /// /// 检查房间号是否可用 循环检查连续100个房间,检查到可用即返回 /// /// 房间号 /// 检查次数 /// 小于0表示未查到可用房间(这时候应该把修改上次检查房间的值,以便下次检查) 大于表示查到某房间可用 private int CheckRoom(int roomNum, int checkCount) { if (checkCount >= 100) //没有查询到 return -1; checkCount++; string weiyima = null; ServerNode node = null; if (!Room.GetWeiyima(roomNum, ref weiyima, ref node)) { //房间号可用 return roomNum; } else { DeskInfo dt = null; if (Room.LoadRoom(weiyima, out dt)) { int isSendDis = dt.CheckDisBank(); if (isSendDis > 0) { //发送解散命令 PackHead head = PackHead.Create(ServerPackAgreement.disbank); if (ServerHeart.instanece.IsDie(node.id, node.nodeNum)) { Debug.Error("管理该房间的模块不在线!"); } else { GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, JsonPack.GetJson(new KeyValuePair(roomNum, 2 + isSendDis))), true); Debug.Warning("发送解散命令!" + roomNum); } head.Dispose(); head = null; } } else { Debug.Warning("房间数据未加载成功!" + weiyima); } do { roomNum++; roomNum = roomNum % Room.MaxCnt; } while (roomNum == 0); //房间号从1开始 return CheckRoom(roomNum, checkCount); // 继续找 } } /// /// 玩家退出 /// /// private bool QuitGame(int userid) { var tmp = PlayerCollection.Instance.FindPlayerByUserId(userid); if (tmp == null) { Debug.Error("玩家退出未找到玩家:" + userid); return false; } else GameManager.instance.QuitGame(tmp, "QuitGame"); return true; } /// /// 获取朋友房房间号 /// /// /// /// true 表示可以创建 private bool GetFriendRoomNum(PackHead head, CreateRoomPack rmdata) { //判断是否被锁,被锁,提示玩家被锁,并提示玩家去被锁的游戏 try { int roomnum = GetNewRoomNum(); //房间号 if (roomnum < 0) { //服务器爆满,创建失败,回包给玩家 提示玩家 GeneralSendPack.SendErrorInfo_Socket(head.userid, 0, 3, head.GetUtil()); if (rmdata.isAuto == 1) { QuitGame(head.userid); } return false; } else { Debug.Info("创建的房间号:" + roomnum + "," + rmdata.deskinfo.weiyima); //按照房间号分发给模块处理,如果是本模块的直接处理 rmdata.deskinfo.roomNum = roomnum.ToString(); return true; } } catch (Exception e) { Debug.Error("C480D7D2-B680-4321-924F-5C8AF7DAA2B6:" + e.ToString()); GeneralSendPack.SendErrorInfo_Socket(head.userid, 1, 37, head.GetUtil()); return false; } } /// /// 处理创建朋友房的包 /// /// 包裹 public void CreatFriendRoom(GamePack pack) { if (ting == null) { Debug.Error("游戏未开启朋友房功能!"); return; } PackHead head = pack.Head; CreateRoomPack rmdata = JsonPack.GetData(pack.JsonData); if (head == null || rmdata == null) { Debug.Error("客户端发送的数据有问题!创建失败!"); return; } //判断是否被锁,被锁,提示玩家被锁,并提示玩家去被锁的游戏 if (GetFriendRoomNum(head, rmdata)) CreatRoomLogin(head, rmdata, false, true); } /// /// 俱乐部踢出玩家 /// /// 状态码 public int DoClubOutPlayer(string weiyima, int userId) { string roomnumStr = Room.GetRoomNum(weiyima); int roomnum = 0; if (!int.TryParse(roomnumStr, out roomnum)) { return MessageErrCode.KickOutPlayerOfDesk_NoDesk; } Desk desk = FindDesk(roomnum); if (desk == null || desk.deskinfo.weiyima != weiyima) { return MessageErrCode.KickOutPlayerOfDesk_NoDesk; } if (!desk.deskinfo.noWar) { return MessageErrCode.KickOutPlayerOfDesk_GameInWar; } for (int i = 0; i < desk.Count; i++) { if (desk[i] == null) continue; if (desk[i].userid == userId) { PackHead headp = PackHead.Create(); headp.userid = userId; headp.packlx = GamePackAgreement.autoTipInfo; headp.otherString = new string[] { "您被管理员踢出房间!" }; GeneralSendPack.SendPackToPlayer(headp, desk[i], null); GameManager.instance.DoComBack(desk[i]); headp.Dispose(); break; } } return MessageErrCode.Success; } /// /// 竞技比赛踢出玩家 /// /// public void DoClubOutPlayer(GamePack pack) { var head = pack.Head; string weiyima = head.otherString[0]; int userid = head.otherInt[0]; string roomnumStr = Room.GetRoomNum(weiyima); int roomnum = 0; if (!int.TryParse(roomnumStr, out roomnum)) { head.transfer = ServerPackAgreement.OutPlayer; head.packlx = ServerPackAgreement.TransFerHttp; head.otherString = new string[] { "房间不存在!"}; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); return; } Desk desk = FindDesk(roomnum); if (desk == null || desk.deskinfo.weiyima != weiyima) { head.transfer = ServerPackAgreement.OutPlayer; head.packlx = ServerPackAgreement.TransFerHttp; head.otherString = new string[] { "房间不存在!"}; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); return; } if (!desk.deskinfo.noWar) { head.transfer = ServerPackAgreement.OutPlayer; head.packlx = ServerPackAgreement.TransFerHttp; head.otherString = new string[] { "桌子已开战,踢出失败!"}; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); return; } for (int i = 0; i < desk.Count; i++) { if (desk[i] == null) continue; if (desk[i].userid == userid) { PackHead headp = PackHead.Create(); headp.userid = userid; headp.packlx = GamePackAgreement.autoTipInfo; headp.otherString = new string[] { "您被管理员踢出房间!" }; GeneralSendPack.SendPackToPlayer(headp, desk[i], null); GameManager.instance.DoComBack(desk[i]); head.Dispose(); break; } } head.transfer = ServerPackAgreement.OutPlayer; head.packlx = ServerPackAgreement.TransFerHttp; head.otherString = new string[] { "踢出成功!"}; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); } public void QuitGameJoinOther(GamePack pack) { var head = pack.Head; if (head.otherInt == null || head.otherInt.Length <= 0) { SendManager.SendErrotInfo_Http(head, 0, "数据错误!"); return; } var player = PlayerCollection.Instance.FindPlayerByUserId(head.userid); if (player == null) { Debug.Error("未找到玩家!" + head.userid); SendManager.SendErrotInfo_Http(head, 0, "未找到玩家!"); return; } JoinFriendRoom jfr = JsonPack.GetData(pack.JsonData); if (head == null || jfr == null) { Debug.Error("客户端发来的数据有问题,加入玩法失败!"); return; } PlayerState playerState = (PlayerState)player.state; if (playerState == PlayerState.Desk || playerState == PlayerState.Ready) { if (string.IsNullOrEmpty(player.friendWeiYiMa) || player.friendRoomNum == 0) { SendManager.SendErrotInfo_Http(head, 0, $"你不在朋友房,不能切换房间!"); } else { //玩家退出当前游戏 GameManager.instance.DoComBack(player); //去处理进入房间 head.packlx = head.otherInt[0]; int dealModuleId = head.packlx / Game.Data.GameData.PackCardInt; Debug.Log("转发给游戏服务器:" + head.packlx); GlobalMQ.instance.DeliveryEveryOne(dealModuleId, GlobalMQ.CreateMessage(head, jfr), true); } } else { SendManager.SendErrotInfo_Http(head, 0, $"当前状态{playerState}不能切换玩法!"); } } /// /// 竞技比赛会长解散房间 /// public int ClubDisBankCmd(string weiyima) { string roomnumStr = Room.GetRoomNum(weiyima); int roomnum = 0; if (!int.TryParse(roomnumStr, out roomnum)) { return MessageErrCode.ClubDisbandNotFindDesk; } Desk desk = FindDesk(roomnum); if (desk == null || desk.deskinfo.weiyima != weiyima) { return MessageErrCode.ClubDisbandNotFindDesk; } DisBank(desk, 7); return MessageErrCode.Success; } /// /// 竞技比赛会长解散房间 /// /// public void ClubDisBankCmd(GamePack pack) { var head = pack.Head; string weiyima = head.otherString[0]; string roomnumStr = Room.GetRoomNum(weiyima); int roomnum = 0; if (!int.TryParse(roomnumStr, out roomnum)) { SendManager.SendErrotInfo_Http(head, 2, 74); return; } Desk desk = FindDesk(roomnum); if (desk == null || desk.deskinfo.weiyima != weiyima) { SendManager.SendErrotInfo_Http(head, 2, 74); return; } DisBank(desk, 7); SendManager.SendErrotInfo_Http(head, 2, 75); } /// /// 竞技比赛因玩家比赛积分不够解散桌子 /// /// public void ClubMatchDisBankByBurs(GamePack pack) { var head = pack.Head; string weiyima = head.otherString[0]; string roomnumStr = Room.GetRoomNum(weiyima); int roomnum = 0; if (!int.TryParse(roomnumStr, out roomnum)) { return; } Desk desk = FindDesk(roomnum); if (desk == null || desk.deskinfo.weiyima != weiyima) { return; } DisBank(desk, 8); } /// /// 竞技比赛创建桌子 /// /// public void DoClubCreateDesk(GamePack pack) { if (ting == null) { Debug.Error("游戏未开启朋友房功能!"); return; } PackHead head = pack.Head; JoinFriendRoom jfr = JsonPack.GetData(pack.JsonData); if (head == null || jfr == null) { Debug.Error("客户端发来的数据有问题,加入玩法失败!"); return; } DeskInfo dskinfo = new DeskInfo(); dskinfo.wayid = jfr.way.weiyima; dskinfo.creatStyle = 5; dskinfo.creatUserid = jfr.way.Clubid; dskinfo.rule = jfr.way.dskrule; if (dskinfo.rule.RuleEx == null) dskinfo.rule.RuleEx = new DeskRuleEx(); dskinfo.rule.RuleEx.ReadyTimeout = jfr.ReadyTimeOut; CreateRoomPack crp = new CreateRoomPack(); crp.deskinfo = dskinfo; crp.deviceInfo = jfr.deviceInfo; crp.isAuto = jfr.isAuto; crp.ClubId = jfr.ClubId; crp.TaskId = jfr.TaskId; //获取到房间号,去创建房间 if (instance.GetFriendRoomNum(head, crp)) { instance.CreatRoomLogin(head, crp, true, true); } } public async Task JoinClubDesk(GamePack pack) { PackHead head = pack.Head; JoinFriendRoom jfr = JsonPack.GetData(pack.JsonData); if (head == null || jfr == null) { Debug.Error("客户端发来的数据有问题,加入玩法失败!"); return; } if (DoingUserIds.Contains(head.userid)) { Debug.Error($"正在处理别的事务:{head.userid}"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskDoing); return; } if (ting == null) { Debug.Error("游戏未开启朋友房功能!"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotOpenFriend); return; } int userid = head.userid; try { DoingUserIds.Add(userid); //有则尝试加入房间! //先把房间找到-> string strRoomNum = Room.GetRoomNum(jfr.joinweiyima); Debug.Info("找到房间:" + strRoomNum + "," + jfr.joinweiyima); //管理该房间的节点 ServerNode node = null; string weiyima = null; //拿到房间号,先看本地有没有,没有的话则加载起来 int roomnum = 0; if (int.TryParse(strRoomNum, out roomnum)) { //有房间号 if (Room.GetWeiyima(roomnum, ref weiyima, ref node)) { //拿到唯一码 if (weiyima == jfr.joinweiyima) { //唯一码一致 if (!GameBase.instance.myUtil.Equals(node)) { //交给管理模块处理 GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true); } else { //本模块处理 //没在本地加载到本地 Debug.Info("本地处理"); DoJoinFriendRoom djfr = new DoJoinFriendRoom(head, new JoinRoom(roomnum.ToString(), weiyima) { deviceinfo = jfr.deviceInfo }, jfr, false, true); await djfr.Start(); if (!djfr.result) { //进入失败 再来一次 /* jfr.lastjoinweiyima = weiyima; jfr.joinweiyima = null; */ Debug.Log("加入失败的提示:" + djfr.errinfo); if (jfr.TaskId <= 0) { if (string.IsNullOrEmpty(djfr.errinfo)) { SendManager.SendErrotInfo_Http(head, 1, 73); } else { SendManager.SendErrotInfo_Http(head, 0, djfr.errinfo); } } else { GeneralSendPack.SendJoinDeskResult(jfr.TaskId, djfr.errorCode); } /* head.packlx = GlobalManager.instance.myUtil.id * 10000 + head.packlx; GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true); */ Debug.Warning("进入失败,发包再试!" + head.ip); } else { if (jfr.TaskId <= 0) { //把玩家拉入桌子 head.transfer = ServerPackAgreement.ReConnection; head.packlx = ServerPackAgreement.TransFerHttp; head.otherInt = new int[] { ServerConfigManager.Instance.ClientId }; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); } else { GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.Success); } } } return; } } } } finally { DoingUserIds.Remove(userid); } } /// /// 处理加入玩法包 /// /// public void DoWanFa(GamePack pack) { PackHead head = pack.Head; JoinFriendRoom jfr = JsonPack.GetData(pack.JsonData); if (head == null || jfr == null) { Debug.Error("客户端发来的数据有问题,加入玩法失败!"); return; } if (ting == null) { Debug.Error("加入玩法失败,游戏未开启朋友房功能!"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotOpenFriend); return; } JoinWanFa djfr = new JoinWanFa(head, jfr); djfr.Start(head); } /// /// 处理加入房间包 /// /// public async Task DoJoinRoom(GamePack pack) { if (ting == null) { Debug.Error("加入房间失败,游戏未开启朋友房功能!"); return; } PackHead head = pack.Head; JoinRoom jr = JsonPack.GetData(pack.JsonData); if (head == null || jr == null) { Debug.Error("客户端发来的数据有问题,加入房间失败!"); return; } DoJoinFriendRoom djfr = new DoJoinFriendRoom(head, jr, null, true, false); await djfr.Start(); if (!djfr.result) { head.otherString = new string[] { djfr.errinfo }; head.packlx = GamePackAgreement.TransFerPack; head.transfer = GameSeverAgreement.notJoinFriendRoom; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head), true); } /* * TTTT补: 加入房间房间的处理修改,需要外部发包通知 * * * */ } /// /// 处理回放 /// /// [Obsolete("过时,不使用")] public void DoHuiFang(GamePack pack) { //过时,不使用 //Task task = Task.Factory.StartNew( // () => // { // FightRecordData frd = JsonPack.GetData(pack.jsondata); // frd.data = Room.LoadFightRecord(frd.weiyima, frd.index); // pack.head.packlx = GameSeverAgreement.friendfightdata; // //回放数据可能是空! // GameNet.SendPack_Userid(pack.head.GetModuleUtil(), pack.head, frd); // } //); } /// /// 创建房间并登陆 /// /// /// protected async Task CreatRoomLogin(PackHead head, CreateRoomPack data, bool isClub, bool isCheckDoing) { Debug.Info("创建房间 赔率:" + data.deskinfo.rule.peilv); await new FriendRoomManager.CreateRoom(head, head.userid, data, isClub, isCheckDoing).Start(); } /// /// 解散房间包 /// /// public void DisBankDesk(GamePack pk) { if (ting == null) { Debug.Error("朋友房未开启!"); return; } if (pk.pl.tingid != ting.id) { Debug.Error("解散房间失败,没有这个房间!" + ting.id); return; } DisBank(pk.pl); } /// /// 请求解散包 /// public void placeDisBank(GamePack pk) { placeDisBank(pk.pl); } /// /// 请求解散回复包 /// /// public void DisReponse(GamePack pk) { bool dis = JsonPack.GetData(pk.JsonData); DisReponse(pk.pl, dis, false); } /// /// 解散房间命令 /// public void DisBankCmd(int roomnum, int style) { //先判断房间存在不存在,再判断是否是过期房间 //满足条件,解散房间 if (ting != null) { Desk desk = FindDesk(roomnum); if (desk == null) { Debug.Warning("无此房间,可能已经被解散了!"); } else { //判断房间是否过期解散 if (desk.deskinfo == null) { Debug.Error("大错误,桌子数据为空!"); return; } if (style == 7) { Debug.Info("收到强制解散房间命令!"); DisBank(desk, style); } else { int isDisBank = desk.deskinfo.CheckDisBank(); if (isDisBank > 0) { Debug.Info("检查解散房间!"); //解散 DisBank(desk, 2 + isDisBank); } else { Debug.Warning("收到假的解散指令!"); } } } } else { Debug.Error("未开启朋友房,收到解散指令!"); } } /// /// 获取玩家的桌子 /// /// /// public Desk GetPlayerDesk(PlayerDataAsyc pl) { //内存中如果没有桌子 Desk desk = FindDesk(pl.friendRoomNum); if (desk != null) return desk; //去数据库中加载桌子 if (LoadFriendRoom(pl.friendRoomNum, pl.friendWeiYiMa)) { desk = FindDesk(pl.friendRoomNum); //再从内存中加载起来 } return desk; } /// /// 加载房间 /// /// protected bool LoadFriendRoom(int roomnum, string weiyima) { DeskInfo dskInfo = null; //释放房间 void FreeRoom() { //没开启朋友房 Debug.Info("没开启朋友房!"); string _weiyima = null; ServerNode node = null; if (Room.GetWeiyima(roomnum, ref _weiyima, ref node) && weiyima == _weiyima) { if (Room.LoadRoom(_weiyima, out dskInfo)) { //把数据从硬盘上加载起来 Debug.Info("加载朋友房数据:删除他!"); Desk.DisBank(dskInfo); } } } if (ting == null) { Debug.Error("未开启朋友房!"); FreeRoom(); //朋友房未开启,释放房间 return false; } //加载朋友房到内存 Desk dsk = FindDesk(roomnum); if (dsk == null) { //内存中没有--去加载朋友房 Debug.Log("没找到这个朋友房:" + roomnum); //去数据库中拿 DeskInfo dskinfo; if (Room.LoadRoom(weiyima, out dskinfo)) { //桌子数据处理完成! Debug.Info($"加载朋友房数据! {dskinfo.weiyima}"); LoadDesk(dskinfo); } else { //数据库中也没有 return false; } } return true; } private void SetPlayerScoreRecord(DeskInfo deskInfo) { try { if (!deskInfo.isAllOver || deskInfo.creatStyle != 5 || string.IsNullOrEmpty(deskInfo.wayid)) { return; } LuckPlayerManager.FightScore[] fightScore = new LuckPlayerManager.FightScore[deskInfo.seat.Length]; for (int i = 0; i < deskInfo.seat.Length; i++) { fightScore[i] = new LuckPlayerManager.FightScore() { UserId = deskInfo.pls[i].userid, Value = (int)deskInfo.SumBurs[i].Score }; FriendRoomStatistics.Instance.AddSessionFight(deskInfo.wayid, deskInfo.rule.peilv, deskInfo.pls[i].userid, (int)deskInfo.SumBurs[i].Score); } LuckPlayerManager.Instance.AddScoreRecord(deskInfo.wayid, deskInfo.rule.peilv, deskInfo.overCnt, fightScore); } catch (Exception e) { Debug.Error($"SetPlayerScoreRecord:{e.Message}"); } } /// /// 解散桌子逻辑 /// /// 要解散的桌子 /// 1局数打完解散 2开战过-玩家申请解散 3超时解散(24小时未打完) 4超时解散(1小时内还没满员) 5房主解散 6玩法被删除 7竞技比赛管理解散房间 8因小局分不够解散 9托管自动解散 public void DisBank(Desk desk, int style) { // 上报 if (desk.deskinfo != null && !desk.deskinfo.noWar) { desk.AddWarTime(); // 重新计算一下战局时长,防止漏计算 List eLogs = new List(); for (int i = 0; i < desk.PlayerCnt; i++) { if (desk[i] != null) { // 用户游玩时长 eLogs.Add(StatisticsTrackingLogData.Create( desk[i].userid.ToString(), EventTrackConst.GameFriendPlayTime, desk.totalWarTime, ServerConfigManager.Instance.GameId.ToString() )); } } if (desk.deskinfo.creatStyle == 5) { // 公会游玩局数 var clubIds = desk.Select(x => x.ClubId).Distinct(); foreach (var clubId in clubIds) { eLogs.Add(StatisticsTrackingLogData.Create( clubId.ToString(), EventTrackConst.GameClubPlayCount, 1, ServerConfigManager.Instance.GameId.ToString() )); } } // 解散原因 eLogs.Add(StatisticsTrackingLogData.Create( ServerConfigManager.Instance.GameId.ToString(), EventTrackConst.GameDisCount, 1, style.ToString() )); EventTrackingUtil.OnEvent(eLogs); } desk.DisBank(style); DeskInfo deskinfo = desk.deskinfo; //只要是解散,都应该要算输赢分 Room.SetSumBurs(deskinfo); SetPlayerScoreRecord(deskinfo); deskinfo.isClose = 1; //先发包 desk.SendFriendRoomOver(style); //Debug.Info($"解散原因:{deskinfo.GetDisBankMemo(style)}"); //修改玩家数据,修改桌子数据 --执行完玩家就离线了! desk.DisBankAfter(style); //修改链表数据 //添加到闲置的桌子! ting.AddIdleing(desk); if (deskinfo.creatStyle == 5) { WayManager.instance.WayDeskChangeSend(deskinfo.creatUserid, deskinfo.wayid, deskinfo.weiyima, 1); } int rm = 0; if (!int.TryParse(desk.deskinfo.roomNum, out rm)) { Debug.Error("房间号竟然不是数字!"); return; } Debug.Info("获取到房间号:" + rm); int idx = rm % 10; if (!allDesks[idx].Remove(rm)) { Debug.Error("alldesk中竟然没有此房间!"); return; } } /// /// 根据房间号查找桌子 /// /// public Desk FindDesk(int deskNum) { if (ting == null) return null; if (deskNum < 0) return null; int idx = deskNum % 10; Desk desk = null; if (allDesks[idx].TryGetValue(deskNum, out desk)) return desk; return null; } /// /// 请求解散房间包 /// /// private void placeDisBank(PlayerDataAsyc pl) { if (pl.friendRoomNum <= 0) { Debug.Error("此玩家没有朋友房!"); return; } Desk dsk = FindDesk(pl.friendRoomNum); if (dsk == null) { Debug.Error("逻辑错误,没找到这个桌子" + pl.friendRoomNum); return; } if (dsk.deskinfo.noWar) { Debug.Error("未开战不处理!"); return; } if (dsk.deskinfo.isDising) { Debug.Warning("正在处理解散房间!"); return; } if (dsk.deskinfo.rule.RuleEx != null && dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt < 0) { Debug.Log("不支持解散!"); return; } if (dsk.deskinfo.rule.RuleEx != null && dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt > 0 && dsk.deskinfo.RequestDissolveCnt >= dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt) { Debug.Log("请求解散的次数达到上限!"); return; } dsk.deskinfo.isDising = true; dsk.deskinfo.DisCount = DeskInfo.DisTimeOut; dsk.deskinfo.RequestDissolveCnt++; int len = dsk.deskinfo.plsDis.Length; DisReponse(pl, true, true); } /// /// 请求立即开战 /// /// public void placeOnceFight(GamePack pack) { Debug.Info("得到立即开战包:"); placeOnceFight(pack.pl, pack.Head); } /// /// 请求开战 /// /// 玩家数据 /// 包头 private void placeOnceFight(PlayerDataAsyc pl, PackHead head) { if (ting == null) return; if (pl.friendRoomNum <= 0) { Debug.Error("玩家没有朋友房!"); return; } Desk dsk = FindDesk(pl.friendRoomNum); if (dsk == null) { Debug.Error("逻辑错误,没找到这个桌子" + pl.friendRoomNum); return; } if (dsk.deskinfo.rule.minCnt >= dsk.deskinfo.rule.maxCnt) { Debug.Error("没有设置立即开战!"); return; } if (!dsk.deskinfo.noWar) { Debug.Error("开战了不处理!"); return; } if (head.otherInt == null || head.otherInt.Length < 1) return; dsk.deskinfo.OnceFight[dsk.deskinfo.seat[pl.seat]] = head.otherInt[0]; dsk.SendOnceFight(); } /// /// 解散回复包 /// /// 回复的玩家 /// 是否同意解散 /// 是否是发起者 public void DisReponse(PlayerDataAsyc pl, bool Dis, bool source) { if (pl.friendRoomNum <= 0) return; Desk dsk = FindDesk(pl.friendRoomNum); if (!dsk.deskinfo.isDising) return; int len = dsk.deskinfo.plsDis.Length; for (int i = 0; i < len; i++) { //这个位置有人 没投票过 是这个玩家 if (dsk.deskinfo.pls[i] != null && dsk.deskinfo.plsDis[i] == 0 && dsk.deskinfo.pls[i].userid == pl.userid) { if (Dis) { if (source) { dsk.deskinfo.DisUserId = pl.userid; } dsk.deskinfo.plsDis[i] = 1; dsk.SendDisInfo(source ? 1 : 2, pl.userid, pl.nickname); } else { dsk.deskinfo.DisUserId = 0; //拒绝解散 //dsk.deskinfo.plsDis[i] = -1; dsk.deskinfo.isDising = false; dsk.SendDisInfo(3, pl.userid, pl.nickname); for (int j = 0; j < len; j++) { dsk.deskinfo.plsDis[j] = 0; } Debug.Log("告诉玩家,谁谁谁拒绝解散!"); return; } break; } } //检查是否全部人都同意解散 bool isDis = true; for (int i = 0; i < len; i++) { if (dsk.deskinfo.pls[i] != null) { //这个位置有人且不是同意 if (dsk.deskinfo.plsDis[i] != 1) { isDis = false; break; } } } if (isDis) { //解散房间 Debug.Info("所有人同意解散!"); DisBank(dsk,2); } } public void DeductCard(PlayerDataAsyc pl, DeskInfo info) { if (info.fangka == 0) { return; } if (info.creatStyle == 5) { //通知竞技比赛扣除竞技比赛房卡 ClubDataChange cdc = new ClubDataChange() { style = 1, clubid = info.creatUserid, value = -info.fangka }; // PackHead head = PackHead.Create(ServerPackAgreement.ClubDataChange); // ClubDataManager.AddClubCardAsyn(info.creatUserid, -info.fangka); // GlobalMQ.instance.DeliveryEveryOne((int)ModuleType.ClubModule, GlobalMQ.CreateMessage(head, cdc), true, // true); // head.Dispose(); // 埋点 EventTrackingUtil.OnEvent(StatisticsTrackingLogData.Create( info.creatUserid.ToString(), EventTrackConst.GamePlayCardCount, info.fangka, ServerConfigManager.Instance.GameId.ToString() )); } else { if (pl == null) { return; } //通知数据中心,扣除玩家的房卡 if (info.fangka != 0) { PlayerDataChange pdc = PlayerDataChange.Create(info.creatUserid); pdc.fangkaChange = -info.fangka; PlayerFun.WritePlayerDataAsync(pdc); pl.fangka -= info.fangka; } } GameManager.instance.DelFangKa += info.fangka; } /// /// 创建桌子--这种是新创建的 /// /// 创建者 /// 桌子信息 /// public int CreateDesk(PlayerDataAsyc pl, DeskInfo info, ref string errinfo, ref int errcode) { //DeductCard(pl, info); Debug.Info("创建所需的房卡数值:" + info.fangka); Desk desk = ting.GetDesk(DeskState.Idle, info); desk.Init(); Debug.Info("创建桌子实例!" + info.creatStyle + "," + info.creatUserid + "," + desk.id); int deskNum = int.Parse(info.roomNum); AddDesk(deskNum, desk); Debug.Info("获取到房间号:" + deskNum); ting.RemoveIdle(desk); ting.AddQueueing(desk); if (EnterDesk(deskNum, pl, info.rule.pwd, info.creatStyle == 5, ref errinfo, ref errcode) == 1) { Debug.Info("玩家进入房间成功! cccdd:" + pl.ClubId); } else { Debug.Error("自己创建的房间怎么还有进不去的情况?????" + info.roomNum + "," + errinfo); return 0; } //Debug.Log("创建成功!"); Debug.Log(info.ToString()); return 1; } /// /// 添加desk /// /// /// protected void AddDesk(int deskNum, Desk desk) { if (ting == null) { Debug.Error("非朋友房不得使用!"); return; } int idx = deskNum % 10; Debug.Info("添加房间...." + deskNum); allDesks[idx].Add(deskNum, desk); } /// /// 处理玩家解散房间包 /// /// public void DisBank(PlayerDataAsyc pl) { //先判断 if (pl.outline == 1) { Debug.Error("玩家离线哪里来的包!"); return; } if (pl.friendRoomNum <= 0) { Debug.Error("玩家没有房间号!"); return; } if (pl.state == (int)PlayerState.Desk || pl.state == (int)PlayerState.Ready) { if (!ting.isExists(pl.deskid)) { Debug.Error("解散桌子错误!没有这个桌子!"); return; } var desk = ting[pl.deskid]; if (desk.CheckDisbank(pl)) { Debug.Info("解散房间的收包!"); DisBank(desk, 5); } else { Debug.Warning("解散失败!"); } } else { Debug.Warning("玩家状态不符合解散桌子!"); return; } } /// /// 本来就有的桌子 /// /// /// public void LoadDesk(DeskInfo info) { Desk desk = ting.GetDesk(DeskState.Idle, info); desk.Init(); desk.LoadDesk(); AddDesk(int.Parse(info.roomNum), desk); ting.RemoveIdle(desk); if (desk.deskinfo.nowCnt == 0) { //0表示未开战 不等于0表示开战 ting.AddQueueing(desk); } else { desk.waitRecover = true; ting.AddWaring(desk); } } /// /// 删除玩法 /// public void DelWay(int clubid, string wayid) { //思路 把这个玩法的所有桌子的唯一码拿到手。 //获取到桌子信息, 判断桌子是否已经开战,如果没有开战则解散桌子 var weiyimaArray = WayManager.instance.GetDesksWeiYiMa(clubid, wayid).Select(p => (string)p.Name) .ToArray(); //用这个得到唯一码 foreach (var weiyima in weiyimaArray) { if (!string.IsNullOrEmpty(weiyima)) { var roomNum = Room.GetRoomNum(weiyima); //Room.GetRoomNum 传递唯一码获取房间号 if (int.TryParse(roomNum, out var roomnum)) { var weiyimaOrig = string.Empty; ServerNode node = null; //再根据房间号获取到唯一码 与 node. 返回值表示是否有这个房间。如果没这个房间输出错误信息。 if (Room.GetWeiyima(roomnum, ref weiyimaOrig, ref node)) { //这个唯一码要与 刚才得到的唯一码进行对比,验证是否是同一个桌子 。 房间号是可以重复的, 桌子的唯一码却不会重复。 if (weiyima.Equals(weiyimaOrig)) { //验证成功的话,FindDesk 查找到桌子 var desk = FindDesk(roomnum); //桌子是空输出错误信息 if (desk == null) { Debug.Error( $"DelWay desk is null! clubid: {clubid}, wayid: {wayid}, weiyima: {weiyima}, roomNum: {roomNum}."); } else if (!desk.isWar) { //再判断桌子是否已经开战 isWar 属性。 DisBank(desk, 6); //已经开战不处理,未开战调用 DisBank() 调用解散桌子 } } } } } } } /* * redis中的数据解构 * * friendroom.lastRoomNum hash类型 lastDateTime 上次创建的时间 lastDateRoomNum 上次创建房间的房间号 * friendroom.room.num string类型 房间号表 -> 存储唯一吗值 * friendroom.唯一码 -> 房间数据 * friendroom.唯一码_playerdata_idx -> 存储房间的玩家数据 * friendroom.唯一码_score_idx -> 存储房间分数 * * */ /* * * 朋友房唯一码 = 日期+时间+毫秒+房间号 * {创建房间的算法} { 1.房间号的算法{ --混淆游戏的火爆程度 变量 房间增量 当前检测房间号 1.房间增量 = 上次创建房间与当前时间的时间差 / 10 % 1000 2.当前检测的房间号 = (上次创建房间的房间号+房间增量) % 1000000 3.对比是否与上次创建的房间号一样,房间号+1 } 2.检测房间可用 传入检查的房间号 检查次数{ 拿到房间号->去检查 检查次数+1; 如果检查房间号发现已经检查 100 次 返回未检查到可用房间->发包玩家重试 第一种情况2.1 房间号表有值 { 根据房间的唯一码去获取朋友房数据 { 1.房间已经超时 应该解散(未开战,过了半个小时->执行解散(发送解散命令) 开战了->过了24小时未战斗完(解散)) 去执行解散房间 检查的房间号+1 -> 继续调用检测房间方法 2.房间正常 检查的房间号+1 -> 继续调用检测房间方法 } 第二种情况2.2 房间号表中没值 { 执行创建房间; } } 3.创建房间->检测次数 分布式加锁 再做检查,已防万一已被别的程序创建! 3.1检查发现不可用 返回创建失败->执行检查房间号,检测次数+1 cha 3.2检查可用 1. 根据房间数据创建桌子,生成房间数据 2. 根据房间数据,保存到房间分数表、房间玩家数据表,房间数据表,房间唯一吗表,上次创建房间的房间号表 分布式解锁 4.解散房间 判断房间号是否是自己模块管理的 1.不是本模块管理,发包给管理的模块处理 ->有可能模块不在线,(或者不开了.....手动清楚数据,一般不应该出现这种情况) 2.是本模块管理{ 清楚桌子内存数据, 分布式 加锁 1.删除房间号表中的值, 分布式 借锁 2.redis桌子数据异步存储到sql.存储完成后删除redis中的桌子数据 } } */ /// /// 快速加入 /// public class JoinWanFa { /// /// 包头 /// public readonly PackHead head; /// /// 加入房间 /// public readonly JoinFriendRoom jfr; /// /// 加入玩法 /// /// /// public JoinWanFa(PackHead head, JoinFriendRoom jfr) { this.head = head; this.jfr = jfr; } /// /// 获取本次要计算的房间唯一码值 /// /// /// protected void GetRoomWeiYiMa(JoinFriendRoom jfr, HashEntry[] rooms) { bool isLast = jfr.lastjoinweiyima == null; foreach (var item in rooms) { if (!isLast) { //还没找到上次计算的房间 isLast = item.Name == jfr.lastjoinweiyima; } //else { //找到了,找本次要运算的房间 2020-06-17 号修改,这个应该写错了,会跳过第一个房间 int cnt = 0; if (!item.Value.TryParse(out cnt)) { Debug.Fatal("存储的值错误,怎么存储的值非整数类型!" + jfr.way.weiyima + "," + jfr.way.Clubid); continue; } if (isLast && cnt < jfr.way.dskrule.maxCnt) { //房间没满人 jfr.joinweiyima = item.Name; //选定要运算的房间 break; } //} } } /// /// 开始房间 /// /// public async Task Start(PackHead head) { if (jfr == null) { Debug.Error("936983A9-02C9-4B81-A7F4-C06C7385B06B:"); return; } if (jfr.deviceInfo == null) { Debug.Error("加入玩法时设备信息为空!!!"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotDeviceInfo); return; } if (head.ip == null) { Debug.Error("玩家的ip 是 空!!!"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotIp); return; } int userid = head.userid; if (DoingUserIds.Contains(userid)) { Debug.Error($"正在处理别的事务:{head.userid}"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskDoing); return; } Debug.Info("进入玩法!"); HashEntry[] rooms = null; try { DoingUserIds.Add(userid); //如果当前进入房间有值,尝试进入房间 //如果当前进入房间没值,尝试计算当前要进入的房间 if (jfr.joinweiyima == null) { //没有想进入的房间,说明是从竞技比赛过来的 if (string.IsNullOrEmpty(jfr.way.weiyima)) { Debug.Error("玩法的唯一码竟是空值!!!!"); GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskParamError); return; } //去找一个房间 rooms = WayManager.instance.GetDesksWeiYiMa(jfr.way.Clubid, jfr.way.weiyima); Debug.Info("找到所有的房间:" + jfr.way.Clubid + "," + jfr.way.weiyima); GetRoomWeiYiMa(jfr, rooms); } if (jfr.joinweiyima != null) { //有则尝试加入房间! //先把房间找到-> string strRoomNum = Room.GetRoomNum(jfr.joinweiyima); Debug.Info("找到房间:" + strRoomNum + "," + jfr.joinweiyima); //管理该房间的节点 ServerNode node = null; string weiyima = null; //拿到房间号,先看本地有没有,没有的话则加载起来 int roomnum = 0; if (int.TryParse(strRoomNum, out roomnum)) { //有房间号 if (Room.GetWeiyima(roomnum, ref weiyima, ref node)) { //拿到唯一码 if (weiyima == jfr.joinweiyima) { //唯一码一致 if (!GameBase.instance.myUtil.Equals(node)) { //交给管理模块处理 GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true); } else { //本模块处理 //没在本地加载到本地 Debug.Info("本地处理"); DoJoinFriendRoom djfr = new DoJoinFriendRoom(head, new JoinRoom(roomnum.ToString(), weiyima) { deviceinfo = jfr.deviceInfo }, jfr, false, true); djfr.IsTestPack = jfr.IsTestPack; await djfr.Start(); if (!djfr.result) { //进入失败 再来一次 Debug.Warning("进入失败,去创建一个房间!"); jfr.lastjoinweiyima = weiyima; jfr.joinweiyima = null; var crp1 = new CreateRoomPack() { deviceInfo = jfr.deviceInfo, isAuto = jfr.isAuto, ClubId = jfr.ClubId, Score = jfr.Score, TaskId = jfr.TaskId, IsTestPack = jfr.IsTestPack, deskinfo = new DeskInfo() { wayid = jfr.way.weiyima, creatStyle = 5, creatUserid = jfr.way.Clubid, rule = jfr.way.dskrule } }; if (instance.GetFriendRoomNum(head, crp1)) { await instance.CreatRoomLogin(head, crp1, true, false); } /* head.otherString = new string[] { djfr.errinfo}; head.packlx = ServerPackAgreement.TransFerHttp; head.transfer = GameSeverAgreement.notJoinFriendRoom; */ /* head.packlx = GlobalManager.instance.myUtil.id * 10000 + head.packlx; GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true); Debug.Warning("进入失败,发包再试!" + head.ip);*/ } else { if (jfr.TaskId > 0) { GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.Success); } else { Debug.Info("把玩家拉入桌子!!!"); //把玩家拉入桌子 head.transfer = ServerPackAgreement.ReConnection; head.packlx = ServerPackAgreement.TransFerHttp; head.otherInt = new int[] { ServerConfigManager.Instance.ClientId }; GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head, null), true); } } } return; } } } } DeskInfo dskinfo = new DeskInfo(); dskinfo.wayid = jfr.way.weiyima; dskinfo.creatStyle = 5; dskinfo.creatUserid = jfr.way.Clubid; dskinfo.rule = jfr.way.dskrule; if (dskinfo.rule.RuleEx == null) dskinfo.rule.RuleEx = new DeskRuleEx(); dskinfo.rule.RuleEx.ReadyTimeout = jfr.ReadyTimeOut; Debug.Info("去创建朋友房!" + dskinfo.wayid); CreateRoomPack crp = new CreateRoomPack(); crp.deskinfo = dskinfo; crp.deviceInfo = jfr.deviceInfo; crp.isAuto = jfr.isAuto; crp.ClubId = jfr.ClubId; crp.Score = jfr.Score; crp.TaskId = jfr.TaskId; crp.IsTestPack = jfr.IsTestPack; //获取到房间号,去创建房间 if (instance.GetFriendRoomNum(head, crp)) { await instance.CreatRoomLogin(head, crp, true, false); } //(head, crp); } catch (Exception e) { Debug.Error($"报错:{e.Message} {e.StackTrace}"); } finally { DoingUserIds.Remove(userid); } } } } }