/// <summary> /// 斗地主游戏开始 /// </summary> public static void GameStart(this Room self) { //更改房间状态 从空闲房间移除 添加到游戏中房间列表 LandMatchComponent Match = Game.Scene.GetComponent <LandMatchComponent>(); Match.FreeLandlordsRooms.Remove(self.Id); Match.GamingLandlordsRooms.Add(self.Id, self); //出牌控制组件 self.AddComponent <OrderControllerComponent>(); //更该玩家状态 for (int i = 0; i < self.gamers.Length; i++) { Gamer gamer = self.gamers[i]; Match.Waiting.Remove(gamer.UserID); Match.Playing.Add(gamer.UserID, self); } //添加开始斗地主游戏需要的组件 //牌库组件 self.AddComponent <DeckComponent>(); //添加开始斗地主游戏需要的组件 self.AddComponent <GameControllerComponent, RoomConfig>(GateHelper.GetLandlordsConfig(RoomLevel.Lv100)); //开始游戏 self.GetComponent <GameControllerComponent>().StartGame(); }
/// <summary> /// 检查匹配状态 每当有新排队玩家加入时执行一次 /// </summary> /// <param name="self"></param> public static async void MatchingCheck(this LandMatchComponent self) { //如果有空房间 且 正在排队的玩家>0 Room room = self.GetFreeLandlordsRoom(); if (room != null) { while (self.MatchingQueue.Count > 0 && room.Count < 3) { self.JoinRoom(room, self.MatchingQueue.Dequeue()); } } //else 如果没有空房间 且 正在排队的玩家>=1 else if (room == null && self.MatchingQueue.Count >= 1) { //创建新房间 room = ComponentFactory.Create <Room>(); await room.AddComponent <MailBoxComponent>().AddLocation(); self.FreeLandlordsRooms.Add(room.Id, room); while (self.MatchingQueue.Count > 0 && room.Count < 3) { //Dequeue():在队列的头部读取和删除一个元素,注意,这里读取元素的同时也删除了这个元素。如果队列中不再有任何元素。就抛出异常 self.JoinRoom(room, self.MatchingQueue.Dequeue()); } } }
protected override async ETTask Run(Gamer gamer, Actor_GamerReady_Landlords message) { LandMatchComponent landordsMatchComponent = Game.Scene.GetComponent <LandMatchComponent>(); //请求的gamer目前所在等待中的房间 Room room = landordsMatchComponent.GetWaitingRoom(gamer); if (room != null) { //找到玩家的座位顺序 int seatIndex = room.GetGamerSeat(gamer.UserID); if (seatIndex >= 0) { //由等待状态设置为准备状态 room.isReadys[seatIndex] = true; //广播通知全房间玩家此gamer已经准备好 room.Broadcast(new Actor_GamerReady_Landlords() { UserID = gamer.UserID }); //检测开始游戏,判断如果房间内三个人都是准备状态就开始游戏和发牌 room.CheckGameStart(); } else { Log.Error("玩家不在正确的座位上"); } } await ETTask.CompletedTask; }
/// <summary> /// 返回未开始游戏的房间 用于处理准备消息 /// </summary> public static Room GetWaitingRoom(this LandMatchComponent self, Gamer gamer) { Room room; if (!self.Waiting.TryGetValue(gamer.UserID, out room)) { Log.Error("玩家不在待机的房间中"); } return(room); }
/// <summary> /// 匹配队列广播 /// </summary> public static void Broadcast(this LandMatchComponent self, IActorMessage message) { foreach (Gamer gamer in self.MatchingQueue) { //向客户端User发送Actor消息 ActorMessageSenderComponent actorProxyComponent = Game.Scene.GetComponent <ActorMessageSenderComponent>(); ActorMessageSender actorProxy = actorProxyComponent.Get(gamer.CActorID); Log.Debug("转发给了客户端一条消息,客户端Session:" + gamer.CActorID.ToString()); actorProxy.Send(message); } }
/// <summary> /// 斗地主匹配队列人数加一 /// 队列模式 所以没有插队/离队操作 /// 队列满足匹配条件时 创建新房间 /// </summary> public static void AddGamerToMatchingQueue(this LandMatchComponent self, Gamer gamer) { //添加玩家到队列 self.MatchingQueue.Enqueue(gamer); Log.Debug("一位玩家加入队列"); //检查匹配状态 self.MatchingCheck(); //广播通知所有匹配中的玩家 self.Broadcast(new Actor_LandMatcherPlusOne_NTT() { MatchingNumber = self.MatchingQueue.Count }); ////检查匹配状态 //self.MatchingCheck(); }
/// <summary> /// 加入房间 /// </summary> public static void JoinRoom(this LandMatchComponent self, Room room, Gamer gamer) { //玩家可能掉线 if (gamer == null) { return; } //玩家加入房间 成为已经进入房间的玩家 //绑定玩家与房间 以后可以通过玩家UserID找到所在房间 self.Waiting[gamer.UserID] = room; //为玩家添加座位 room.Add(gamer); //房间广播 Log.Info($"玩家{gamer.UserID}进入房间"); Actor_GamerEnterRoom_Ntt broadcastMessage = new Actor_GamerEnterRoom_Ntt(); foreach (Gamer _gamer in room.gamers) { if (_gamer == null) { //添加空位 broadcastMessage.Gamers.Add(new GamerInfo()); continue; } //添加玩家信息 //GamerInfo info = new GamerInfo() { UserID = _gamer.UserID, IsReady = room.IsGamerReady(gamer) }; GamerInfo info = new GamerInfo() { UserID = _gamer.UserID }; broadcastMessage.Gamers.Add(info); } //广播房间内玩家消息 每次有人进入房间都会收到一次广播 room.Broadcast(broadcastMessage); //向Gate上的User发送匹配成功 //ActorMessageSender actorProxy = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(gamer.GActorID); //actorProxy.Send(new Actor_MatchSucess_M2G() { GamerID = gamer.InstanceId }); Session GetGateSession = MapHelper.GetGateSession(); GetGateSession.Send(new T_MatchSucess_M2G() { UserID = gamer.UserID, GamerID = gamer.InstanceId }); }
protected override async ETTask Run(Session session, EnterMatchs_G2M message) { //Log.Debug("Map服务器收到第一条消息"); LandMatchComponent matchComponent = Game.Scene.GetComponent <LandMatchComponent>(); //玩家是否在房间中待机 if (matchComponent.Waiting.ContainsKey(message.UserID)) { Room room; //通过UserID获取matchComponent中相对应的键,即找到此User所在的Room matchComponent.Waiting.TryGetValue(message.UserID, out room); //房间中的玩家对象,获取获取其UserID的座位索引 Gamer gamer = room.GetGamerFromUserID(message.UserID); //设置GateActorID,ClientActorID gamer.GActorID = message.GActorID; gamer.CActorID = message.CActorID; //向Gate发送消息更新Gate上user的ActorID //这样不论玩家到了哪个地图服务器,Gate上的user都持有所在地图服务器上gamer的InstanceId ActorMessageSender actorProxy = Game.Scene.GetComponent <ActorMessageSenderComponent>().Get(gamer.GActorID); actorProxy.Send(new Actor_MatchSucess_M2G() { GamerID = gamer.InstanceId }); } else { //新建玩家,用UserID构建Gamer Gamer newgamer = ComponentFactory.Create <Gamer, long>(message.UserID); newgamer.GActorID = message.GActorID; newgamer.CActorID = message.CActorID; //为Gamer添加MailBoxComponent组件,可以通过MailBox进行actor通信 await newgamer.AddComponent <MailBoxComponent>().AddLocation(); //添加玩家到匹配队列 广播一遍正在匹配中的玩家 matchComponent.AddGamerToMatchingQueue(newgamer); } }
/// <summary> /// 获取一个可以添加座位的房间 没有则返回null /// </summary> public static Room GetFreeLandlordsRoom(this LandMatchComponent self) { return(self.FreeLandlordsRooms.Where(p => p.Value.Count < 3).FirstOrDefault().Value); }