using System; using System.Collections.Generic; using System.Linq; namespace ET.Server { [FriendOf(typeof (HGHuangHuangComponent))] public static class HGHuangHuangComponentSystem { [ObjectSystem] public class HGHuangHuangComponentAwakeSystem: AwakeSystem { protected override void Awake(HGHuangHuangComponent 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.CanHuIds = new List(); self.CanPgIds = new List(); self.OperableList = new List(); self.ClickHuIds = new List(); self.CanPgIds = new List(); self.OperableList = new List(); self.ClickHuIds = new List(); self.CardList = new List(); self.UpdateTime = 0; // 初始化牌库 for (int i = 0; i < 4; i++) { foreach (int value in HGHuangHuangConst.Values) { self.CardList.Add(value); } RandomGenerator.Shuffle(self.CardList); } } } [ObjectSystem] public class HGHuangHuangComponentDestroySystem: DestroySystem { protected override void Destroy(HGHuangHuangComponent self) { Log.Info($"销毁黄冈晃晃主逻辑组件..."); } } [ObjectSystem] [FriendOf(typeof(Room))] public class HGHuangHuangComponentUpdateSystem : UpdateSystem { protected override void Update(HGHuangHuangComponent 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 >= 15) { if (self.OperableList != null && self.OperableList.Count > 0) { // 过 } if (self.DrawCardPlayer.Id == self.CurrentPlayer.Id) { // 出牌 self.DisCard(room, self.CurrentPlayer, 0, true); } } } break; case 3: // 已结束 break; } self.Time++; } } /// /// 检测是否可开始 3秒倒计时开始 /// /// /// /// private static bool CheckReadyStart(this HGHuangHuangComponent 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_ReadyStartPush(){ReadyStartTime = 3}); } return true; } /// /// 发牌 /// /// /// private static void SendCard(this HGHuangHuangComponent 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 HGHuangHuangComponent 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_StartPush(){info = ProtoHelper.RoomToProto(room, player, null)}); Log.Info($"游戏开局, 房间id={room.RoomId}, 玩家id={player.Id}, 玩家={player.Name}, 手牌信息={player.RemainCards}"); } } /// /// 摸牌 /// /// /// private static void DrawCard(this HGHuangHuangComponent 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; // 吃,碰,杠,胡,过 bool hasAct = false; // 检测摸牌人动作, 校验摸牌是否胡 Struct.HuRes huRes = HGHuangHuangHelper.CheckHu(drawCardPlayer.RemainCards); if (huRes.Type != HGHuangHuangConst.HU_DEFAULT) { hasAct = true; drawCardPlayer.Act[3] = 1; self.CanHuIds.Add(drawCardPlayer); if (!self.OperableList.Contains(drawCardPlayer)) { self.OperableList.Add(drawCardPlayer); } } // todo 玩家听牌状态不允许杠 // 检测摸牌人动作, 校验摸牌是否杠 List gang = HGHuangHuangHelper.IsDrawGang(drawCardPlayer); if (gang is { Count: > 0 }) { hasAct = true; drawCardPlayer.Act[2] = 1; if (!self.OperableList.Contains(drawCardPlayer)) { self.OperableList.Add(drawCardPlayer); } if (!self.CanPgIds.Contains(drawCardPlayer)) { self.CanPgIds.Add(drawCardPlayer); } } // 过牌 drawCardPlayer.Act[4] = hasAct? 1 : 0; if (drawCardPlayer.HuCards.Any(_card => _card > 0 && _card == self.DrawCard)) { drawCardPlayer.Act[4] = 0; } // 推送摸牌广播 foreach (Player player in room.GetAllPlayers().Values.Where(player => player != null)) { MessageHelper.SendToClient(player, new G2C_DrawCardPush(){info = ProtoHelper.RoomToProto(room, player, drawCardPlayer)}); Log.Info($"摸牌... 玩家ID:{player.Id}, 位置:{player.Pos}, 摸牌玩家:{player.Id == drawCardPlayer.Id}, 手牌大小:{player.RemainCards.Length}, 手牌信息:{string.Join(", ", player.RemainCards)}, 摸的牌:{card}"); } } /// /// 出牌 /// /// /// /// /// 出的牌(0.当前摸牌玩家自动出牌 -1.非当前摸牌玩家自动出牌 >0.玩家手动出牌) /// 是否自动出牌 public static async void DisCard(this HGHuangHuangComponent self, Room room, Player player, int card, bool flag) { if (player == null) { Log.Error($"出牌错误,player is null."); return; } using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.DisCard, 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_DisCardPush(){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 != null) { // 吃,碰,杠,胡,过 int[] act = new int[5]; List gangs = new List(); List pengs = new List(); List chis = new List(); // todo 玩家听牌状态不允许有动作 // 出牌是否杠 gangs = HGHuangHuangHelper.IsDiscardGang(otherPlayer, card, player.Id); // 出牌是否碰 pengs = HGHuangHuangHelper.IsDiscardPeng(otherPlayer, card, player.Id); // 出牌是否吃 if (otherPlayer.Pos == nextPos[0]) { chis = HGHuangHuangHelper.IsDiscardChi(otherPlayer, card, player.Id); } // 游戏中才会动作 if (otherPlayer.State == 2) { 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 = HGHuangHuangHelper.CheckHu(tmpCards); if (huType.Type != HGHuangHuangConst.HU_DEFAULT) { hasAct = true; act[3] = 1; // 放入可胡玩家列表 if (!self.CanHuIds.Contains(otherPlayer)) { self.CanHuIds.Add(otherPlayer); } // 加入可操作玩家list if (!self.OperableList.Contains(otherPlayer)) { self.OperableList.Add(otherPlayer); } } // 是否杠 if (gangs.Count > 0) { hasAct = true; act[2] = 1; } // 是否碰 if (pengs.Count > 0) { hasAct = true; act[1] = 1; } // 是否吃 if (chis.Count > 0) { hasAct = true; act[0] = 1; } // 是否过 if (hasAct) { act[4] = 1; } if (act[2] == 1 || act[1] == 1) { // 加入可操作玩家list if (!self.OperableList.Contains(otherPlayer)) { self.OperableList.Add(otherPlayer); } // 加入可碰杠玩家集合 if (!self.CanPgIds.Contains(otherPlayer)) { self.CanPgIds.Add(otherPlayer); } } // 设置玩家动作 otherPlayer.Act = act; } // 广播其它三家 MessageHelper.SendToClient(otherPlayer, new G2C_DisCardPush(){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 { if (self.CanHuIds.Count > 0) { self.CurrentPlayer = self.Players[self.CanHuIds.First().Pos]; } else if (self.CanPgIds.Count > 0) { self.CurrentPlayer = self.Players[self.CanPgIds.First().Pos]; } else { self.CurrentPlayer = self.Players[self.OperableList.First().Pos]; } } } } } /// /// 清空玩家可操作动作 /// /// private static void CleanUserAct(this HGHuangHuangComponent self) { foreach (Player player in self.Players) { if (player != null) { player.Act = new int[5]; } } } /// /// 结束 /// /// /// private static void GameOver(this HGHuangHuangComponent self, Room room) { } } }