using System; using System.Collections.Generic; using System.Data; using System.Linq; namespace ET.Server { [FriendOf(typeof (HGHHComponent))] public static class HGHHComponentSystem { [ObjectSystem] public class HGHuangHuangComponentAwakeSystem: AwakeSystem { protected override void Awake(HGHHComponent self) { Room room = self.GetParent(); if (room == null) { Log.Error($"黄冈晃晃主逻辑组件获取不到主实体..."); return; } Log.Info($"创建黄冈晃晃主逻辑组件..."); self.Flag = false; self.Time = 0; self.State = 0; self.Players = new Player[room.MaxNum]; self.CurrentRound = 0; self.ZhuangPos = 0; self.Rand = new[] { 0, 0 }; self.GangType = -1; self.AdmitDefeatList = new List(); self.CanPgIds = new List(); self.GangHuIds = new List(); self.CanHuIds = new List(); self.OperableList = new List(); self.ClickHuIds = new List(); self.HuResult = -1; self.CardList = new List(); self.UpdateTime = 0; // 初始化牌库 for (int i = 0; i < 4; i++) { foreach (int value in HGHHConst.Values) { self.CardList.Add(value); } RandomGenerator.Shuffle(self.CardList); } } } [ObjectSystem] public class HGHHComponentDestroySystem: DestroySystem { protected override void Destroy(HGHHComponent self) { Log.Info($"销毁黄冈晃晃主逻辑组件..."); } } [ObjectSystem] [FriendOf(typeof(Room))] public class HGHuangHuangComponentUpdateSystem : UpdateSystem { protected override void Update(HGHHComponent self) { long timeNow = TimeHelper.ClientNow(); // 每秒执行一次 if (timeNow - self.UpdateTime <= 1000) { return; } self.UpdateTime = timeNow; Room room = self.GetParent(); if (room == null) { Log.Error($"黄冈晃晃主逻辑组件获取不到主实体..."); return; } switch (self.State) { case 0: // 等待状态 Log.Debug($"检测: 黄冈晃晃-房间号:{room.RoomId}, 房间人数:{room.Players.Count}, 状态:检测是否可开局..."); if (self.CheckReadyStart(room)) { self.State = 1; self.Flag = false; self.Time = 0; } // 120秒未开始直接解散 if (self.Time >= 120) { room.Dispose(); } break; case 1: // 开局 if (!self.Flag) { if (self.Time >= 3) { self.Start(room); self.Flag = true; self.Time = 0; Log.Debug($"检测: 黄冈晃晃-房间号:{room.RoomId}, 房间人数:{room.Players.Count}, 状态:开局...VS动画..."); } } else { if (self.Time >= 4) { self.State = 2; self.Flag = false; self.Time = 0; } } break; case 2: // 进行中 if (!self.Flag) { self.Flag = true; self.Time = 0; // 摸牌 self.DrawCard(room); } else { // 强制操作 // if (self.Time >= 30) // { // if (self.DrawCardPlayer.Id == self.CurrentPlayer.Id) // { // if (self.OperableList.Count > 0) // { // self.Guo(room, self.CurrentPlayer); // } // self.DisCard(room, self.CurrentPlayer, 0, true); // } // else // { // if (self.OperableList.Count > 0) // { // self.Guo(room, self.CurrentPlayer); // } // } // // self.Time = 30; // // } // else // { // // todo 自动托管逻辑 // if (self.CurrentPlayer != null && self.CurrentPlayer.State != 3 && self.CurrentPlayer.IsAuto) // { // // } // } } break; case 3: // 已结束 if (!self.Flag) { self.Flag = true; self.Time = 0; Log.Debug($"游戏结束: 黄冈晃晃-房间号:{room.RoomId}, 房间人数:{room.Players.Count}"); } else { // todo 超时删除房间 if (self.Time >= 60) { room.Dispose(); } } break; } self.Time++; } } /// /// 检测是否可开始 3秒倒计时开始 /// /// /// /// private static bool CheckReadyStart(this HGHHComponent self, Room room) { if (!room.IsStart() || self.State != 0) { return false; } // 通知客户端3秒倒计时 foreach (Player player in room.GetAllPlayers().Values.Where(player => player != null)) { MessageHelper.SendToClient(player, new G2C_HGHHReadyStartPush(){ReadyStartTime = 3}); } return true; } /// /// 发牌 /// /// /// private static void SendCard(this HGHHComponent self, Room room) { foreach (Player player in room.GetAllPlayers().Values.Where(player => player != null)) { for (int i = 0; i < 13; i++) { int card = self.CardList[0]; player.RemainCards = CardHelper.Add(player.RemainCards, card); self.CardList.RemoveAt(0); } } } /// /// 游戏开局 /// /// /// private static void Start(this HGHHComponent self, Room room) { self.CurrentRound += 1; // 摇骰子 int rand1 = RandomGenerator.RandomNumber(1, 7); int rand2 = RandomGenerator.RandomNumber(1, 7); self.Rand = new[] { rand1, rand2 }; // 定庄 // self.ZhuangPos = (rand1 + rand2) % 4; self.ZhuangPos = (rand1 + rand2) % room.MaxNum; // 设置当前操作玩家 self.CurrentPlayer = self.Players[self.ZhuangPos]; // 设置当前摸牌玩家 self.DrawCardPlayer = self.Players[self.ZhuangPos]; // 发牌 self.SendCard(room); // 广播 foreach (Player player in room.GetAllPlayers().Values.Where(player => player != null)) { player.State = 2; MessageHelper.SendToClient(player, new G2C_HGHHStartPush(){info = ProtoHelper.RoomToProto(room, player, self.CurrentPlayer)}); Log.Info($"游戏开局, 房间id={room.RoomId}, 玩家id={player.Id}, 玩家={player.Name}, 手牌信息={string.Join(", ", player.RemainCards)}"); } } /// /// 摸牌 /// /// /// private static void DrawCard(this HGHHComponent self, Room room) { // 2个以上玩家认输或牌库没牌了直接结束 if (self.AdmitDefeatList.Count > 2 || self.CardList.Count <= 0) { self.GameOver(room); return; } Player drawCardPlayer = self.DrawCardPlayer; if (drawCardPlayer == null) { Log.Error($"房间id={room.RoomId}, 摸牌玩家为空..."); return; } // 摸牌 int card = self.CardList[0]; drawCardPlayer.RemainCards = CardHelper.Add(drawCardPlayer.RemainCards, card); self.CardList.RemoveAt(0); // 当前摸的牌 self.DrawCard = card; drawCardPlayer.Act = new int[5]; drawCardPlayer.ActInfo.Clear(); // 吃,碰,杠,胡,过 bool hasAct = false; // 检测摸牌人动作, 校验摸牌是否胡 Struct.HuRes huRes = HGHHHelper.CheckHu(drawCardPlayer.RemainCards); if (huRes.Type != HGHHConst.HU_DEFAULT) { hasAct = true; drawCardPlayer.Act[3] = 1; self.CanHuIds.Add(drawCardPlayer.Id); if (!self.OperableList.Contains(drawCardPlayer.Id)) { self.OperableList.Add(drawCardPlayer.Id); } } // todo 玩家听牌状态不允许杠 // 检测摸牌人动作, 校验摸牌是否杠 List gang = HGHHHelper.IsDrawGang(drawCardPlayer); if (gang is { Count: > 0 }) { hasAct = true; drawCardPlayer.Act[2] = 1; if (!self.OperableList.Contains(drawCardPlayer.Id)) { self.OperableList.Add(drawCardPlayer.Id); } if (!self.CanPgIds.Contains(drawCardPlayer.Id)) { self.CanPgIds.Add(drawCardPlayer.Id); } } // 过牌 drawCardPlayer.Act[4] = hasAct? 1 : 0; if (drawCardPlayer.HuCards.Any(_card => _card > 0 && _card == self.DrawCard)) { drawCardPlayer.Act[4] = 0; } // 设置当前操作玩家 self.CurrentPlayer = drawCardPlayer; // 重置时间和流程标记 self.Time = 30; self.Flag = true; Log.Info($"摸牌... 玩家ID:{drawCardPlayer.Id}, 位置:{drawCardPlayer.Pos}, 手牌大小:{drawCardPlayer.RemainCards.Length}, 手牌信息:{string.Join(", ", drawCardPlayer.RemainCards)}, 摸的牌:{card}"); // 推送摸牌广播 foreach (Player player in room.GetAllPlayers().Values.Where(player => player != null)) { MessageHelper.SendToClient(player, new G2C_HGHHDrawCardPush(){info = ProtoHelper.RoomToProto(room, player, drawCardPlayer)}); } } /// /// 出牌 /// /// /// /// /// 出的牌(0.当前摸牌玩家自动出牌 -1.非当前摸牌玩家自动出牌 >0.玩家手动出牌) /// 是否自动出牌 public static async void DisCard(this HGHHComponent self, Room room, Player player, int card, bool flag) { if (player == null) { Log.Error($"出牌错误,player is null."); return; } using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.PlayerOperation, player.Id)) { if (self.CurrentPlayer.Id == player.Id && self.DrawCardPlayer.Id == player.Id) { Log.Info($"出牌... 玩家ID:{player.Id}, 位置:{player.Pos}, 手牌大小:{player.RemainCards.Length}, 手牌信息: {string.Join(", ", player.RemainCards)}"); // 自动出牌 if (flag) { if (self.PengPlayer != null && self.PengPlayer.Id == player.Id) { self.PengPlayer = null; int[] tmpCard = new int[player.RemainCards.Length]; Array.Copy(player.RemainCards, 0, tmpCard, 0, player.RemainCards.Length); Array.Sort(tmpCard); card = tmpCard[^1]; } else { card = player.RemainCards[^1]; } // todo 真人托管状态 } if (!player.RemainCards.Contains(card)) { Log.Error($"出牌错误,玩家的牌不在手中..."); return; } // 玩家出牌 player.RemainCards = CardHelper.Remove(player.RemainCards, card); player.DisCards = CardHelper.Add(player.DisCards, card); player.DiscardCount += 1; self.DisCard = card; self.DisCardPlayer = player; self.PengPlayer = null; // // 给出牌人广播 // MessageHelper.SendToClient(player, new G2C_HGHHDisCardPush(){info = ProtoHelper.RoomToProto(room, player, player)}); self.CanHuIds.Clear(); self.ClickHuIds.Clear(); self.OperableList.Clear(); self.CanPgIds.Clear(); self.CleanUserAct(); // 检测其它三家的动作 int[] nextPos = room.GetSorcPos(player.Pos); foreach (int index in nextPos) { Player otherPlayer = self.Players[index]; if (otherPlayer is not { State: 2 }) { continue; } // 吃,碰,杠,胡,过 int[] act = new int[5]; List gangs = new List(); List pengs = new List(); List chis = new List(); // todo 玩家听牌状态不允许有动作 // 出牌是否杠 gangs = HGHHHelper.IsDiscardGang(otherPlayer, card, player.Id); // 出牌是否碰 pengs = HGHHHelper.IsDiscardPeng(otherPlayer, card, player.Id); // 出牌是否吃 if (otherPlayer.Pos == nextPos[0]) { chis = HGHHHelper.IsDiscardChi(otherPlayer, card, player.Id); } bool hasAct = false; int[] tmpCards = new int[otherPlayer.RemainCards.Length]; Array.Copy(otherPlayer.RemainCards, 0, tmpCards, 0, otherPlayer.RemainCards.Length); tmpCards = CardHelper.Add(tmpCards, card); // 校验胡牌 Struct.HuRes huType = HGHHHelper.CheckHu(tmpCards); if (huType.Type != HGHHConst.HU_DEFAULT) { hasAct = true; act[3] = 1; // 放入可胡玩家列表 if (!self.CanHuIds.Contains(otherPlayer.Id)) { self.CanHuIds.Add(otherPlayer.Id); } // 加入可操作玩家list if (!self.OperableList.Contains(otherPlayer.Id)) { self.OperableList.Add(otherPlayer.Id); } } // 是否杠 if (gangs.Count > 0) { hasAct = true; act[2] = 1; foreach (Struct.Kezi kezi in gangs.Where(kezi => kezi is { Card: >= 0 })) { otherPlayer.ActInfo.Add(new Struct.Kezi(kezi.Type, kezi.Card, kezi.PlayerId)); } } // 是否碰 if (pengs.Count > 0) { hasAct = true; act[1] = 1; foreach (Struct.Kezi kezi in pengs.Where(kezi => kezi is { Card: >= 0 })) { otherPlayer.ActInfo.Add(new Struct.Kezi(kezi.Type, kezi.Card, kezi.PlayerId)); } } // 是否吃 if (chis.Count > 0) { hasAct = true; act[0] = 1; foreach (Struct.Kezi kezi in chis.Where(kezi => kezi is { Card: >= 0 })) { otherPlayer.ActInfo.Add(new Struct.Kezi(kezi.Type, kezi.Card, kezi.PlayerId)); } } // 是否过 if (hasAct) { act[4] = 1; } if (act[2] == 1 || act[1] == 1 || act[0] == 1) { // 加入可操作玩家list if (!self.OperableList.Contains(otherPlayer.Id)) { self.OperableList.Add(otherPlayer.Id); } // 加入可碰杠玩家集合 if (!self.CanPgIds.Contains(otherPlayer.Id)) { self.CanPgIds.Add(otherPlayer.Id); } } // 设置玩家动作 otherPlayer.Act = act; // // 广播其它三家 // MessageHelper.SendToClient(otherPlayer, new G2C_HGHHDisCardPush(){info = ProtoHelper.RoomToProto(room, otherPlayer, player)}); } if (self.CanHuIds.Count <= 0) { self.GangPlayer = null; } // 判断是否下家摸牌, 指定下家摸牌 if (self.OperableList.Count == 0) { Player nextPlayer = null; foreach (int index in nextPos) { Player tempPlayer = self.Players[index]; if (tempPlayer is { State: 2 } && tempPlayer.Id != player.Id) { nextPlayer = tempPlayer; break; } } // 有三家认输,就会有null if (nextPlayer == null) { self.GameOver(room); } else { // 设置摸牌玩家 self.DrawCardPlayer = nextPlayer; // 设置操作玩家 self.CurrentPlayer = nextPlayer; // 摸牌 self.Flag = false; } } else { long id = 0; if (self.CanHuIds.Count > 0) { id = self.CanHuIds.First(); } else if (self.CanPgIds.Count > 0) { id = self.CanPgIds.First(); } else { id = self.OperableList.First(); } Player tmpPlayer = room.GetPlayer(id); if (tmpPlayer != null) { self.CurrentPlayer = self.Players[tmpPlayer.Pos]; } } // 重置时间和流程标记 self.Time = 30; self.Flag = false; // 给出牌人广播 MessageHelper.SendToClient(player, new G2C_HGHHDisCardPush(){info = ProtoHelper.RoomToProto(room, player, self.CurrentPlayer)}); // 给其他三家广播 foreach (int index in nextPos) { Player otherPlayer = self.Players[index]; if (otherPlayer != null) { // 广播其它三家 MessageHelper.SendToClient(otherPlayer, new G2C_HGHHDisCardPush(){info = ProtoHelper.RoomToProto(room, otherPlayer, self.CurrentPlayer)}); } } } } } /// /// 玩家是否可以操作吃 /// /// /// /// private static bool IsCanChi(this HGHHComponent self, Player player) { if (self.ClickHuIds.Count > 0) { return false; } if (self.CanHuIds.Count > 1) { return false; } else { if (self.CanHuIds.Count == 1) { if (self.CanPgIds.Count > 0) { if (self.CanPgIds.Any(id => id > 0 && id != player.Id)) { return false; } } return self.CanHuIds.Contains(player.Id); } else { if (self.CanPgIds.Count > 0) { return self.CanPgIds.Contains(player.Id); } else { return true; } } } } /// /// 玩家操作吃 /// /// /// /// /// public static void Chi(this HGHHComponent self, Room room, Player player, int card) { if (!self.IsCanChi(player)) { return; } if (self.DisCard >= HGHHConst.DONG_FENG) { return; } // 删除出牌人打出的牌堆 self.DisCardPlayer.DisCards = CardHelper.Remove(self.DisCardPlayer.DisCards, self.DisCard); // 吃牌玩家的手牌 int[] temp = CardHelper.Add(player.RemainCards, self.DisCard); for (int i = 0; i < 3; i++) { temp = CardHelper.Remove(temp, card + i); } player.RemainCards = temp; // 刻子 player.KeZi.Add(new Struct.Kezi((int)HGHHConst.KeziType.CHI, card, self.DisCardPlayer.Id)); // 重置摸牌人 self.DrawCardPlayer = player; self.PengPlayer = player; self.OperableList.Clear(); // 重置时间和流程标记 self.Time = 30; self.Flag = true; Log.Info($"玩家吃牌... 玩家ID:{player.Id}, 位置:{player.Pos}, 手牌大小:{player.RemainCards.Length}, 手牌信息:{string.Join(", ", player.RemainCards)}, 吃的牌:{card}"); // 广播 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 1}); } } /// /// 玩家是否可以操作碰 /// /// /// /// private static bool IsCanPengGang(this HGHHComponent self, Player player) { if (!self.CanPgIds.Contains(player.Id)) { return false; } if (self.ClickHuIds.Count > 0) { return false; } return self.CanHuIds.Count switch { > 1 => false, 1 => self.CanHuIds.Contains(player.Id), _ => true }; } /// /// 玩家操作碰 /// /// /// /// public static void Peng(this HGHHComponent self, Room room, Player player) { if (!self.IsCanPengGang(player)) { return; } int num = CardHelper.CountCardNum(player.RemainCards, self.DisCard); if (num < 2) { return; } // 删除出牌人打出的牌堆 int[] temp = CardHelper.Remove(self.DisCardPlayer.DisCards, self.DisCard); self.DisCardPlayer.DisCards = temp; // 碰牌玩家的手牌 int[] remainCards = player.RemainCards; for (int i = 0; i < 2; i++) { remainCards = CardHelper.Remove(remainCards, self.DisCard); } player.RemainCards = remainCards; // 刻子 player.KeZi.Add(new Struct.Kezi((int)HGHHConst.KeziType.PENG, self.DisCard, self.DisCardPlayer.Id)); // 重置摸牌人 self.DrawCardPlayer = player; self.PengPlayer = player; self.OperableList.Clear(); // 重置时间和摸牌标记 self.Time = 30; self.Flag = true; Log.Info($"玩家碰牌... 玩家ID:{player.Id}, 位置:{player.Pos}, 手牌大小:{player.RemainCards.Length}, 手牌信息:{string.Join(", ", player.RemainCards)}, 碰的牌:{self.DisCard}"); // 广播 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 2}); } } /// /// 摸牌杠(暗杠或者回杠) /// /// /// /// /// /// private static int GangPaiDraw(this HGHHComponent self, Room room, Player player, int card) { int type = (int)HGHHConst.KeziType.DEFAULT; int[] remainCards = player.RemainCards; int num = CardHelper.CountCardNum(remainCards, card); if (num == 4) { for (int i = 0; i < 4; i++) { remainCards = CardHelper.Remove(remainCards, card); } player.RemainCards = remainCards; player.KeZi.Add(new Struct.Kezi((int)HGHHConst.KeziType.AN_GANG, card, player.Id)); self.GangPlayer = player; self.GangPai = card; self.GangType = (int)HGHHConst.KeziType.AN_GANG; type = (int)HGHHConst.KeziType.AN_GANG; } else if (num == 1) { List templist = new List(); if (player.KeZi.Count > 0) { templist = player.KeZi; } for (int i = 0; i < templist.Count; i++) { Struct.Kezi kz = templist[i]; if (kz is not { Type: (int)HGHHConst.KeziType.PENG } || kz.Card != card) { continue; } player.KeZi.RemoveAt(i); remainCards = CardHelper.Remove(remainCards, card); player.KeZi.Add(new Struct.Kezi((int)HGHHConst.KeziType.HUI_GANG, card, player.Id)); } player.RemainCards = remainCards; self.GangPlayer = player; self.GangPai = card; self.GangType = (int)HGHHConst.KeziType.HUI_GANG; type = (int)HGHHConst.KeziType.HUI_GANG; } return type; } /// /// 出牌杠(明杠) /// /// /// /// /// /// private static int GangPaiDisCard(this HGHHComponent self, Room room, Player player, int card) { const int type = (int)HGHHConst.KeziType.DEFAULT; if (self.DisCardPlayer == null) { return type; } self.DisCardPlayer.DisCards = CardHelper.Remove(self.DisCardPlayer.DisCards, self.DisCard); for (int i = 0; i < 3; i++) { player.RemainCards = CardHelper.Remove(player.RemainCards, card); } player.KeZi.Add(new Struct.Kezi((int)HGHHConst.KeziType.MING_GANG, card, self.DisCardPlayer.Id)); self.GangPlayer = player; self.GangPai = card; self.GangType = (int)HGHHConst.KeziType.MING_GANG; return (int)HGHHConst.KeziType.MING_GANG; } /// /// 检测是否有抢杠胡 /// /// /// /// /// 杠的牌 /// private static bool CheckQangGangHu(this HGHHComponent self, Room room, Player player, int card) { bool flag = false; int[] nextPos = room.GetSorcPos(player.Pos); foreach (int index in nextPos) { Player p = self.Players[index]; if (p == null) { continue; } // 玩家手牌 int[] tmpCards = new int[p.RemainCards.Length]; Array.Copy(p.RemainCards, 0, tmpCards, 0, p.RemainCards.Length); tmpCards = CardHelper.Add(tmpCards, card); Struct.HuRes result = HGHHHelper.CheckHu(tmpCards); if (result.Type == HGHHConst.HU_DEFAULT) { continue; } flag = true; if (!self.CanHuIds.Contains(p.Id)) { self.CanHuIds.Add(p.Id); } if (!self.OperableList.Contains(p.Id)) { self.OperableList.Add(p.Id); } if (!self.GangHuIds.Contains(p.Id)) { self.GangHuIds.Add(p.Id); } p.Act = new [] { 0, 0, 0, 1, 1 }; } return flag; } /// /// 玩家操作杠 /// /// /// /// /// public static void Gang(this HGHHComponent self, Room room, Player player, int card) { if (card <= 0 || !self.IsCanPengGang(player)) { return; } int type = (int)HGHHConst.KeziType.DEFAULT; if (self.DrawCardPlayer.Id == player.Id) { type = self.GangPaiDraw(room, player, card); } else if (self.DrawCardPlayer.Id != player.Id && self.DisCard == card) { type = self.GangPaiDisCard(room, player, card); } if (type == (int)HGHHConst.KeziType.DEFAULT) { return; } self.OperableList.Clear(); // 重置时间和摸牌标记 self.Time = 30; self.Flag = false; // bool flag = true; if (self.GangType == (int)HGHHConst.KeziType.HUI_GANG) { if (self.CheckQangGangHu(room, self.GangPlayer, self.GangPai)) { // 当前操作玩家 Player tmpPlayer = room.GetPlayer(self.CanHuIds.First()); if (tmpPlayer != null) { self.CurrentPlayer = self.Players[tmpPlayer.Pos]; } // flag = false; } } // 广播 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 3}); } } /// /// 自摸胡牌(手动/自动) /// /// /// /// private static void ZimoHuPai(this HGHHComponent self, Room room, Player player) { if (self.OperableList.Contains(player.Id) && self.CanHuIds.Contains(player.Id)) { Struct.HuRes res = HGHHHelper.CheckHuType(player.KeZi, player.RemainCards, self.DrawCard); if (res.Type != HGHHConst.HU_DEFAULT) { self.OperableList.Remove(player.Id); self.CanHuIds.Remove(player.Id); self.ClickHuIds.Remove(player.Id); // 将摸的牌从手牌中移除 player.RemainCards = CardHelper.Remove(player.RemainCards, self.DrawCard); self.HuResult = self.GangPlayer != null && player.Id == self.GangPlayer.Id ? (int)HGHHConst.Result.GANGKAI : (int)HGHHConst.Result.ZIMO; // 广播 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); info.Time = 15; MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 4}); } // 自摸胡牌结算 self.SettlementHu(); } self.GameOver(room); } else { Log.Error($"自摸胡牌出错, playerId={player.Id}"); } } /// /// 点炮胡牌广播 /// /// /// /// /// 牌型 /// 是否抢杠胡 private static void DianPaoHuPaiBroadcast(this HGHHComponent self, Room room, Player player, int huType, bool isGangHu) { if (isGangHu) { // 移除抢杠胡集合玩家 self.GangHuIds.Remove(player.Id); // 获取杠玩家 Player gangPlayer = self.GangPlayer; if (gangPlayer == null) { return; } foreach (Struct.Kezi kezi in gangPlayer.KeZi.Where(kezi => kezi.Card == self.GangPai && kezi.Type == (int)HGHHConst.KeziType.HUI_GANG)) { kezi.Type = (int)HGHHConst.KeziType.PENG; } self.HuResult = (int)HGHHConst.Result.QIANGGANG; } else { // 将玩家打出的牌从出牌集合中删除 if (self.DisCardPlayer.DisCards.Contains(self.DisCard)) { self.DisCardPlayer.DisCards = CardHelper.Remove(self.DisCardPlayer.DisCards, self.DisCard); } self.HuResult = (int)HGHHConst.Result.DIANPAO; } player.HuCards.Add(self.GangPai); // 广播 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); info.Time = 15; MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 4}); } } /// /// 点炮胡牌(手动/自动) /// /// /// /// private static void DianPaoHuPai(this HGHHComponent self, Room room, Player player) { int card = 0; bool isGangHU = false; if (self.GangHuIds.Contains(player.Id)) { card = self.GangPai; isGangHU = true; } else { card = self.DisCard; } if (self.CanHuIds.Contains(player.Id)) { int[] userCards = player.RemainCards; int[] tmpCards = new int[userCards.Length]; Array.Copy(userCards, 0, tmpCards, 0, userCards.Length); tmpCards = CardHelper.Add(tmpCards, card); Struct.HuRes res = HGHHHelper.CheckHuType(player.KeZi, tmpCards, card); if (res.Type != HGHHConst.HU_DEFAULT) { if (!self.ClickHuIds.Contains(player.Id)) { self.ClickHuIds.Add(player.Id); } self.CanPgIds.Clear(); self.OperableList.Remove(player.Id); self.CanHuIds.Remove(player.Id); // 广播 self.DianPaoHuPaiBroadcast(room, player, res.Type, isGangHU); if (self.CanHuIds.Count == 0) { // 点炮胡结算 self.SettlementHu(); self.GameOver(room); } else { long id = self.CanHuIds.First(); Player tmpPlayer = room.GetPlayer(id); if (tmpPlayer != null) { self.CurrentPlayer = tmpPlayer; } self.Time = 15; } } } } /// /// 玩家操作胡 /// /// /// /// public static void Hu(this HGHHComponent self, Room room, Player player) { int r = player.RemainCards.Length % 3; switch (r) { case 2: self.ZimoHuPai(room, player); break; case 1: self.DianPaoHuPai(room, player); break; } } /// /// 玩家操作过 /// /// /// /// public static void Guo(this HGHHComponent self, Room room, Player player) { // 玩家必须在可操作列表里 if (!self.OperableList.Contains(player.Id)) { return; } // 从碰杠集合中移除 self.CanPgIds.Remove(player.Id); // 从可操作玩家集合中移除 self.OperableList.Remove(player.Id); player.Act = new int[5]; player.ActInfo.Clear(); // 不是摸牌人,改time if (self.DrawCardPlayer.Id != player.Id) { if (self.CanHuIds.Contains(player.Id)) { self.CanHuIds.Remove(player.Id); } if (self.GangHuIds.Count > 0) { self.GangHuIds.Remove(player.Id); if (self.GangHuIds.Count > 0) { // 设置操作动作玩家 if (self.CurrentPlayer.Id == player.Id) { self.CurrentPlayer = room.GetPlayer(self.GangHuIds.First()); self.Time = 15; // 广播过 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); info.Time = 15; MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 5}); } } } else { if (self.ClickHuIds.Count == 0) { self.DrawCardPlayer = self.GangPlayer; self.Flag = false; } else { // 没有其他人可以胡,且有人点击胡 结算胡 游戏结束 self.SettlementHu(); self.GameOver(room); } } } else { if (self.OperableList.Count == 0) { if (self.ClickHuIds.Count > 0) { // 没有其他人有胡 且有人点击胡 结算胡 游戏结束 self.SettlementHu(); self.GameOver(room); } else { self.DrawCardPlayer = self.GetNextPlayer(self.DisCardPlayer.Pos); self.Flag = false; } } else { if (self.CurrentPlayer.Id == player.Id) { long opId = 0; if (self.CanHuIds.Count > 0) { self.CurrentPlayer = self.Players[room.GetPlayer(self.CanHuIds.First()).Pos]; opId = self.CanHuIds.First(); } else if (self.CanPgIds.Count > 0) { self.CurrentPlayer = self.Players[room.GetPlayer(self.CanPgIds.First()).Pos]; opId = self.CanPgIds.First(); } else { self.CurrentPlayer = self.Players[room.GetPlayer(self.OperableList.First()).Pos]; opId = self.OperableList.First(); } self.Time = 15; // 广播过 foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null)) { RoomInfo info = ProtoHelper.RoomToProto(room, p, player); info.Time = 15; MessageHelper.SendToClient(p, new G2C_HGHHOperationPush(){info = info, OpType = 5}); } } } if (self.CanHuIds.Count == 0) { self.GangPlayer = null; } } } else { if (self.CanHuIds.Contains(player.Id)) { // 从胡牌集合中移除 self.CanHuIds.Remove(player.Id); } } } /// /// 获取下个玩家 /// /// /// 当前玩家位置 /// private static Player GetNextPlayer(this HGHHComponent self, int curPos) { return self.Players[(curPos + 1) % self.GetParent().MaxNum]; } /// /// 清空玩家可操作动作 /// /// private static void CleanUserAct(this HGHHComponent self) { foreach (Player player in self.Players) { if (player != null) { player.Act = new int[5]; } } } /// /// 胡牌结算 /// /// private static void SettlementHu(this HGHHComponent self) { } /// /// 结束 /// /// /// private static void GameOver(this HGHHComponent self, Room room) { self.State = 3; self.Time = 60; self.Flag = false; foreach (Player player in self.Players) { if (player != null) { player.State = 3; } } Log.Info($"牌局结束...roomId={room.RoomId}"); } } }