|
@@ -1,5 +1,6 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.Data;
|
|
|
using System.Linq;
|
|
|
|
|
|
namespace ET.Server
|
|
@@ -30,9 +31,11 @@ namespace ET.Server
|
|
|
self.GangType = -1;
|
|
|
self.AdmitDefeatList = new List<long>();
|
|
|
self.CanPgIds = new List<long>();
|
|
|
+ self.GangHuIds = new List<long>();
|
|
|
self.CanHuIds = new List<long>();
|
|
|
self.OperableList = new List<long>();
|
|
|
- self.ClickHuIds = new List<Player>();
|
|
|
+ self.ClickHuIds = new List<long>();
|
|
|
+ self.HuResult = -1;
|
|
|
self.CardList = new List<int>();
|
|
|
self.UpdateTime = 0;
|
|
|
|
|
@@ -132,23 +135,51 @@ namespace ET.Server
|
|
|
// 强制操作
|
|
|
if (self.Time >= 15)
|
|
|
{
|
|
|
- if (self.OperableList != null && self.OperableList.Count > 0)
|
|
|
+ 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (self.DrawCardPlayer.Id == self.CurrentPlayer.Id)
|
|
|
+ self.Time = 15;
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // todo 自动托管逻辑
|
|
|
+ if (self.CurrentPlayer != null && self.CurrentPlayer.State != 3 && self.CurrentPlayer.IsAuto)
|
|
|
{
|
|
|
- // 出牌
|
|
|
- self.DisCard(room, self.CurrentPlayer, 0, true);
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
|
|
@@ -602,7 +633,9 @@ namespace ET.Server
|
|
|
// 广播
|
|
|
foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null))
|
|
|
{
|
|
|
- MessageHelper.SendToClient(p, new G2C_OperationPush(){info = ProtoHelper.RoomToProto(room, p, p)});
|
|
|
+ RoomInfo info = ProtoHelper.RoomToProto(room, p, player);
|
|
|
+ info.Time = 15;
|
|
|
+ MessageHelper.SendToClient(p, new G2C_OperationPush(){info = info});
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -681,10 +714,141 @@ namespace ET.Server
|
|
|
// 广播
|
|
|
foreach (Player p in room.GetAllPlayers().Values.Where(p => p != null))
|
|
|
{
|
|
|
- MessageHelper.SendToClient(p, new G2C_OperationPush(){info = ProtoHelper.RoomToProto(room, p, player)});
|
|
|
+ RoomInfo info = ProtoHelper.RoomToProto(room, p, player);
|
|
|
+ info.Time = 15;
|
|
|
+ MessageHelper.SendToClient(p, new G2C_OperationPush(){info = info});
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 摸牌杠(暗杠或者回杠)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ /// <param name="card"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private static int GangPaiDraw(this HGHuangHuangComponent self, Room room, Player player, int card)
|
|
|
+ {
|
|
|
+ int type = (int)HGHuangHuangConst.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)HGHuangHuangConst.KeziType.AN_GANG, card, player.Id));
|
|
|
+
|
|
|
+ self.GangPlayer = player;
|
|
|
+ self.GangPai = card;
|
|
|
+ self.GangType = (int)HGHuangHuangConst.KeziType.AN_GANG;
|
|
|
+ type = (int)HGHuangHuangConst.KeziType.AN_GANG;
|
|
|
+ }
|
|
|
+ else if (num == 1)
|
|
|
+ {
|
|
|
+ List<Struct.Kezi> templist = new List<Struct.Kezi>();
|
|
|
+ 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)HGHuangHuangConst.KeziType.PENG } || kz.Card != card)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ player.KeZi.RemoveAt(i);
|
|
|
+ remainCards = CardHelper.Remove(remainCards, card);
|
|
|
+ player.KeZi.Add(new Struct.Kezi((int)HGHuangHuangConst.KeziType.HUI_GANG, card, player.Id));
|
|
|
+ }
|
|
|
+
|
|
|
+ player.RemainCards = remainCards;
|
|
|
+ self.GangPlayer = player;
|
|
|
+ self.GangPai = card;
|
|
|
+ self.GangType = (int)HGHuangHuangConst.KeziType.HUI_GANG;
|
|
|
+ type = (int)HGHuangHuangConst.KeziType.HUI_GANG;
|
|
|
+ }
|
|
|
+ return type;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 出牌杠(明杠)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ /// <param name="card"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private static int GangPaiDisCard(this HGHuangHuangComponent self, Room room, Player player, int card)
|
|
|
+ {
|
|
|
+ const int type = (int)HGHuangHuangConst.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)HGHuangHuangConst.KeziType.MING_GANG, card, self.DisCardPlayer.Id));
|
|
|
+
|
|
|
+ self.GangPlayer = player;
|
|
|
+ self.GangPai = card;
|
|
|
+ self.GangType = (int)HGHuangHuangConst.KeziType.MING_GANG;
|
|
|
+
|
|
|
+ return (int)HGHuangHuangConst.KeziType.MING_GANG;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 检测是否有抢杠胡
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ /// <param name="card">杠的牌</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private static bool CheckQangGangHu(this HGHuangHuangComponent 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 = HGHuangHuangHelper.CheckHu(tmpCards);
|
|
|
+ if (result.Type != HGHuangHuangConst.HU_DEFAULT) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 玩家操作杠
|
|
|
/// </summary>
|
|
@@ -694,9 +858,200 @@ namespace ET.Server
|
|
|
/// <param name="card"></param>
|
|
|
public static void Gang(this HGHuangHuangComponent self, Room room, Player player, int card)
|
|
|
{
|
|
|
-
|
|
|
+ if (card > 0 && self.IsCanPengGang(player))
|
|
|
+ {
|
|
|
+ int type = (int)HGHuangHuangConst.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)HGHuangHuangConst.KeziType.DEFAULT)
|
|
|
+ {
|
|
|
+ self.OperableList.Clear();
|
|
|
+ // bool flag = true;
|
|
|
+ if (self.GangType == (int)HGHuangHuangConst.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];
|
|
|
+ }
|
|
|
+
|
|
|
+ self.Time = 15;
|
|
|
+ // flag = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 广播
|
|
|
+ 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_OperationPush(){info = info});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 自摸胡牌(手动/自动)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ private static void ZimoHuPai(this HGHuangHuangComponent self, Room room, Player player)
|
|
|
+ {
|
|
|
+ if (self.OperableList.Contains(player.Id) && self.CanHuIds.Contains(player.Id))
|
|
|
+ {
|
|
|
+ Struct.HuRes res = HGHuangHuangHelper.CheckHuType(player.KeZi, player.RemainCards, self.DrawCard);
|
|
|
+ if (res.Type != HGHuangHuangConst.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)HGHuangHuangConst.Result.GANGKAI : (int)HGHuangHuangConst.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_OperationPush(){info = info});
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自摸胡牌结算
|
|
|
+ self.SettlementHu();
|
|
|
+ }
|
|
|
+
|
|
|
+ self.GameOver(room);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Log.Error($"自摸胡牌出错, playerId={player.Id}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 点炮胡牌广播
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ /// <param name="huType">牌型</param>
|
|
|
+ /// <param name="isGangHu">是否抢杠胡</param>
|
|
|
+ private static void DianPaoHuPaiBroadcast(this HGHuangHuangComponent 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)HGHuangHuangConst.KeziType.HUI_GANG))
|
|
|
+ {
|
|
|
+ kezi.Type = (int)HGHuangHuangConst.KeziType.PENG;
|
|
|
+ }
|
|
|
+
|
|
|
+ self.HuResult = (int)HGHuangHuangConst.Result.QIANGGANG;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 将玩家打出的牌从出牌集合中删除
|
|
|
+ if (self.DisCardPlayer.DisCards.Contains(self.DisCard))
|
|
|
+ {
|
|
|
+ self.DisCardPlayer.DisCards = CardHelper.Remove(self.DisCardPlayer.DisCards, self.DisCard);
|
|
|
+ }
|
|
|
+
|
|
|
+ self.HuResult = (int)HGHuangHuangConst.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_OperationPush(){info = info});
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 点炮胡牌(手动/自动)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ /// <param name="room"></param>
|
|
|
+ /// <param name="player"></param>
|
|
|
+ private static void DianPaoHuPai(this HGHuangHuangComponent 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 = HGHuangHuangHelper.CheckHuType(player.KeZi, tmpCards, card);
|
|
|
+ if (res.Type != HGHuangHuangConst.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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 玩家操作胡
|
|
|
/// </summary>
|
|
@@ -705,7 +1060,16 @@ namespace ET.Server
|
|
|
/// <param name="player"></param>
|
|
|
public static void Hu(this HGHuangHuangComponent 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -733,6 +1097,15 @@ namespace ET.Server
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 胡牌结算
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="self"></param>
|
|
|
+ private static void SettlementHu(this HGHuangHuangComponent self)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 结束
|
|
|
/// </summary>
|
|
@@ -740,7 +1113,17 @@ namespace ET.Server
|
|
|
/// <param name="room"></param>
|
|
|
private static void GameOver(this HGHuangHuangComponent 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}");
|
|
|
}
|
|
|
}
|
|
|
}
|