任务38:获胜判断,结束游戏与玩家结算数据保存

GameControllerComponentAwakeSystem修改Continue方法

增加游戏结束所有玩家摊牌逻辑与GameOver的调用

\Server\Hotfix\Landlords\System\GameControllerComponentSystem.cs

复制代码
        /// <summary>
        /// 判断出牌后游戏继续or结束
        /// </summary>
        public static void Continue(this GameControllerComponent self, Gamer lastGamer)
        {
            Room room = self.GetParent<Room>();
            OrderControllerComponent orderController = room.GetComponent<OrderControllerComponent>();

            //是否结束,当前出牌者手牌数为0时游戏结束
            bool isEnd = lastGamer.GetComponent<HandCardsComponent>().CardsCount == 0;
            if (isEnd)
            {
                //当前最大出牌者为赢家
                Identity winnerIdentity = room.GetGamerFromUserID(orderController.Biggest).GetComponent<HandCardsComponent>().AccessIdentity;
                List<GamerScore> gamersScore = new List<GamerScore>();

                //游戏结束所有玩家摊牌
                foreach (var gamer in room.gamers)
                {
                    //计算玩家积分
                    gamersScore.Add(new GamerScore()
                    {
                        UserID = gamer.UserID,
                        Score = self.GetGamerScore(gamer, winnerIdentity)
                    });

                    if (gamer.UserID != lastGamer.UserID)
                    {
                        //剩余玩家摊牌
                        Card[] _gamerCards = gamer.GetComponent<HandCardsComponent>().GetAll();
                        room.Broadcast(new Actor_GamerPlayCard_Ntt() { UserID = gamer.UserID, Cards = To.RepeatedField(_gamerCards) });
                    }
                }

                self.GameOver(gamersScore, winnerIdentity);
            }
            else
            {
                //轮到下位玩家出牌
                orderController.Biggest = lastGamer.UserID;
                orderController.Turn();
                room.Broadcast(new Actor_AuthorityPlayCard_Ntt() { UserID = orderController.CurrentAuthority, IsFirst = false });
            }
        }
复制代码

GameControllerComponentAwakeSystem添加游戏结束、计算积分、结算余额方法

\Server\Hotfix\Landlords\System\GameControllerComponentSystem.cs

  • public static async void GameOver  游戏结束
  • public static long GetGamerScore 计算玩家积分

  • public static async Task<long> StatisticalIntegral 结算用户余额保存更新用户信息

  • 复制代码
            /// <summary>
            /// 游戏结束
            /// </summary>
            /// <param name="self"></param>
            public static async void GameOver(this GameControllerComponent self, List<GamerScore> gamersScore, Identity winnerIdentity)
            {
                Room room = self.GetParent<Room>();
                Gamer[] gamers = room.gamers;
    
                //清理所有卡牌
                self.BackToDeck();
                room.GetComponent<DeskCardsCacheComponent>().Clear();
                
                Dictionary<long, long> gamersMoney = new Dictionary<long, long>();
                foreach (GamerScore gamerScore in gamersScore)
                {
                    //结算玩家余额
                    Gamer gamer = room.GetGamerFromUserID(gamerScore.UserID);
                    long gamerMoney = await self.StatisticalIntegral(gamer, gamerScore.Score);
                    gamersMoney[gamer.UserID] = gamerMoney;
                }
    
                //广播游戏结束消息
                room.Broadcast(new Actor_Gameover_Ntt()
                {
                    Winner = (byte)winnerIdentity,
                    BasePointPerMatch = self.BasePointPerMatch,
                    Multiples = self.Multiples,
                    GamersScore = To.RepeatedField(gamersScore)
                });
    
                //清理玩家
                foreach (var _gamer in gamers)
                {
                    //踢出离线玩家
                    if (_gamer.isOffline)
                    {
                        //ActorMessageSender actorProxy = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(_gamer.Id);
                        //await actorProxy.Call(new Actor_PlayerExitRoom_Req());
                    }
                    //踢出余额不足玩家
                    else if (gamersMoney[_gamer.UserID] < self.MinThreshold)
                    {
                        //ActorMessageSender actorProxy = _gamer.GetComponent<UnitGateComponent>().GetActorMessageSender();
                        //actorProxy.Send(new Actor_GamerMoneyLess_Ntt() { UserID = _gamer.UserID });
                    }
                }
            }
    
            /// <summary>
            /// 计算玩家积分
            /// </summary>
            public static long GetGamerScore(this GameControllerComponent self, Gamer gamer, Identity winnerIdentity)
            {
                HandCardsComponent handCards = gamer.GetComponent<HandCardsComponent>();
    
                //积分计算公式:全场底分 * 全场倍率 * 身份倍率
                long integration = self.BasePointPerMatch * self.Multiples * (int)handCards.AccessIdentity;
                //当玩家不是胜者,结算积分为负
                if (handCards.AccessIdentity != winnerIdentity)
                    integration = -integration;
                return integration;
            }
    
            /// <summary>
            /// 结算用户余额保存
            /// </summary>
            public static async Task<long> StatisticalIntegral(this GameControllerComponent self, Gamer gamer, long sorce)
            {
                DBProxyComponent dbProxy = Game.Scene.GetComponent<DBProxyComponent>();
    
                //结算用户余额
                UserInfo userInfo = await dbProxy.Query<UserInfo>(gamer.UserID);
                userInfo.Money = userInfo.Money + sorce < 0 ? 0 : userInfo.Money + sorce;
    
                //更新用户信息
                await dbProxy.Save(userInfo);
    
                return userInfo.Money;
            }
    复制代码

    本节消息定义

    \Proto\HotfixMessage.proto

  • 复制代码
    message GamerScore
    {
        int64 UserID = 1;
        int64 Score = 2;
    }
    
    message Actor_Gameover_Ntt // IActorMessage
    {
        int32 RpcId = 90;
        int64 ActorId = 93;
        int32 Winner = 1; //byte
        int64 BasePointPerMatch = 2;
        int32 Multiples = 3;
        repeated GamerScore GamersScore = 4;
    }
    
    message Actor_GamerMoneyLess_Ntt // IActorMessage
    {
        int32 RpcId = 90;
        int64 ActorId = 93;
        int64 UserID = 1;
    }
    复制代码

    下一节只需在前端让玩家显示牌局结束信息界面

    • 如果无人继续新的牌局,在服务端清除玩家与房间数据,通知所有玩家前端退出房间
    • 如果有人继续新的牌局,修改玩家匹配状态与更改房间状态为空闲房间,通知不继续玩家前端腿出房间
posted @   Domefy  阅读(32)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示