UE4局域网斗地主(四)

发表于2018-01-26
评论0 1.8k浏览
上一篇文章中,出现一个问题:客户端玩家新加入session的时候,如果马上点加入房间会出现不能同步的问题,原因是玩家新加入的时候建立连接是需要时间的,在这过程中,RPC函数还未启动,所以解决方法是,加入session后,延迟一段时间后再执行带有同步的逻辑。

下面是出牌的流程图,顶部的client和server代表在客户端上和服务器上执行的逻辑。

注:提示牌部分涉及到单机类型的AI,先放一边,代替为强制出牌。
C++中,两个接口,一个是出牌逻辑,返回的是出牌结果,结果分为出牌成功,出牌失败且重新出,出牌失败且过下一个,直接过下一个
UENUM(BlueprintType)  
enum class FPlayerOperationResultType:uint8  
{  
    //determine to operate falied  
    OperResNothing,  
    //operate successfully  
    OperResSuccess,    
    //operate falied ,continue doing  
    OperResFalied_NotPass,  
    //operate falied,pass  
    OperResFailed_Pass,  
    //operate successfully and be winner  
    OperResWinner  
};  

另外,数据传输过程中需要代码里的计算牌数据和客户端UI显示的牌数据之间的一个转换函数:
TArray<AMyCard*> AMyNewPlayer::GetCardsByUICardsFromClientCards(TArray<AMyCard*> _cardsOnClient, TArray<FCardUIData> _cardsUIData)  
{  
    TArray<AMyCard*> t_res;  
    TArray<AMyCard*> t_resNull;  
    if (_cardsUIData.Num() > 0 && _cardsOnClient.Num() > 0)  
    {  
        int t_needNum = _cardsUIData.Num();  
        for (int i=0;i<_cardsOnClient.Num();i++)  
        {  
            AMyCard* t_card = _cardsOnClient[i];  
            if (t_card)  
            {                 
                for (int j = 0; j < _cardsUIData.Num(); j++)  
                {  
                    FCardUIData t_uicard = _cardsUIData[j];               
                    if (t_uicard.m_type == t_card->m_type&&t_uicard.m_numStr == t_card->m_numStr)  
                    {                         
                        t_res.Add(t_card);  
                        break;  
                    }  
                }  
                if (t_res.Num()== t_needNum)  
                    return t_res;  
            }             
        }  
    }  
    return t_res;  
}  

出牌逻辑:
FPlayerOperationResultData AMyNewPlayer::OutCards(FPlayerOperationData _operationData)  
{  
    FPlayerOperationResultData t_res;  
    if (Role == ROLE_Authority&&_operationData.m_index == m_indexPlayer)  
    {  
        if (_operationData.m_type == FPlayerOperationType::OutCards&&_operationData.NotNull())  
        {  
            TArray<AMyCard*> t_cards = GetCardsByUICardsFromClientCards(m_cardsClient, _operationData.m_cards);  
            if (t_cards.Num() > 0)  
            {  
                FCurrentGameData_Server t_dataServer = GetCurrentGameDataOnServer();  
                CardGroupType t_type = GetCardGroupTypeFromCards(t_cards);  
                //first out cards  
                if (!t_dataServer.NotNull())  
                {  
                    if (CheckOutCardsIfReliable(t_cards))  
                    {  
                        t_res.Init(FPlayerOperationResultType::OperResSuccess, _operationData.m_cards, _operationData.m_index, "out cards successfully");  
                        OutCardsSuccessFully(t_cards, t_type);  
                    }  
                    else  
                    {                         
                        //wrong cards type ,out cards again  
                        TArray<FCardUIData> t_tt;  
                        t_res.Init(FPlayerOperationResultType::OperResFalied_NotPass, t_tt, _operationData.m_index, "wrong cards type ,out cards again!!!");  
                    }                     
                }  
                else  
                {  
                    //过了一轮,覆盖服务器出牌数据  
                    if (t_dataServer.m_index == m_indexPlayer)  
                    {  
                        t_res.Init(FPlayerOperationResultType::OperResSuccess, _operationData.m_cards, _operationData.m_index, "out cards successfully");  
                        OutCardsSuccessFully(t_cards, t_type);                        
                    }  
                    //和当前出牌数据比较  
                    else  
                    {  
                        if (t_type != CardGroupType::Nothing)  
                        {  
                            if (t_type == t_dataServer.m_type)  
                            {  
                                if (CompareTwoCardsWithSameType(t_cards, t_dataServer.m_cards) == 1)  
                                {  
                                    t_res.Init(FPlayerOperationResultType::OperResSuccess, _operationData.m_cards, _operationData.m_index, "out cards successfully");  
                                    OutCardsSuccessFully(t_cards, t_type);  
                                }  
                            }  
                            else  
                            {  
                                int t_res1 = CompareTwoCards(t_cards, t_dataServer.m_cards);  
                                if (t_res1==1)  
                                {  
                                    t_res.Init(FPlayerOperationResultType::OperResSuccess, _operationData.m_cards, _operationData.m_index, "out cards successfully");  
                                    OutCardsSuccessFully(t_cards, t_type);                                    
                                }  
                                else if(t_res1==2)  
                                {  
                                    //actual num of cards is too small,out cards again  
                                    t_res.Init(FPlayerOperationResultType::OperResFalied_NotPass, _operationData.m_cards, _operationData.m_index, "actual num of cards is too small,out cards again!!!");  
                                }  
                                else  
                                {  
                                    t_res.Init(FPlayerOperationResultType::OperResFalied_NotPass, _operationData.m_cards, _operationData.m_index, "wrong cards type ,out cards again!!!");  
                                }  
                            }                                             
                        }  
                        else  
                        {  
                            //wrong cards type ,out cards again  
                            TArray<FCardUIData> t_tt;  
                            t_res.Init(FPlayerOperationResultType::OperResFalied_NotPass, t_tt, _operationData.m_index, "wrong cards type ,out cards again!!!");  
                        }  
                    }                     
                }  
            }  
        }  
        else if (_operationData.m_type == FPlayerOperationType::Pass)  
        {  
            //if force to out cards  
            if(CheckIfForceOutCards())  
                t_res.Init(FPlayerOperationResultType::OperResFalied_NotPass, _operationData.m_cards, _operationData.m_index, "force to out cards");  
            else  
            {  
                TArray<FCardUIData> t_tt;  
                t_res.Init(FPlayerOperationResultType::OperResFailed_Pass, t_tt, _operationData.m_index, "pass~~~~~");  
            }             
        }  
    }     
    return t_res;  
}  

另外一个接口就是控制出牌玩家。在服务器上根据下标来决定哪个玩家轮到出牌。
FPlayerOperationData AMyNewPlayer::TurnToOutCards()  
{  
    FPlayerOperationData t_res;  
    if (Role == ROLE_Authority)  
    {  
        int t_next= GetNextPlayer(m_indexPlayer);  
        if (t_next >= 0)  
        {  
            TArray<FCardUIData> tt;  
            t_res.Init(FPlayerOperationType::ReadyToOutCards, tt, t_next);  
        }  
    }  
    return t_res;  
}  

显示到客户端UI的思路和之前一样,牌型的判断算法下一篇文章具体说明,因为之前写好的,所以这里就暂且跳过。
下面是出牌示例流程:





流程log:

LogBlueprintUserMessages: [MainLevel_C_1] Client 2: this is mainMap levelBluepritn
LogBlueprintUserMessages: [MainModule_C_29] Client -2: 玩家自己更新自己信息UI
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: BP_MyNewPlayer客户端加入玩家:1
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: BP_MyNewPlayer1客户端加入玩家:0
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: BP_MyNewPlayer1客户端加入玩家:2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: BP_MyNewPlayer2客户端加入玩家:1
LogBlueprintUserMessages: [MainModule_C_25] Server: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_29] Client 1: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_31] Client 2: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_31] Client -2: 玩家自己更新自己信息UI
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: BP_MyNewPlayer客户端加入玩家:2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: this player contain new index,add index failed
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: BP_MyNewPlayer2客户端加入玩家:0
LogBlueprintUserMessages: [MainModule_C_25] Server: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_29] Client 1: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_31] Client 2: player join room ,update ui
LogBlueprintUserMessages: [MainModule_C_25] Server: 选地主结束
LogBlueprintUserMessages: [MainModule_C_25] Server: 地主下标:1
LogBlueprintUserMessages: [MainModule_C_29] Client 1: 选地主结束
LogBlueprintUserMessages: [MainModule_C_29] Client 1: 地主下标:1
LogBlueprintUserMessages: [MainModule_C_31] Client 2: 选地主结束
LogBlueprintUserMessages: [MainModule_C_31] Client 2: 地主下标:1
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_25] Server: remove cards num:   5
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 1: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_29] Client 1: remove cards num:   5
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 2: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_31] Client 2: remove cards num:   5
LogEditorViewport: Clicking on Actor (LMB): BP_Sky_Sphere_C (Sky Sphere)
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_25] Server: remove cards num:   4
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 1: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_29] Client 1: remove cards num:   4
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_31] Client 2: remove cards num:   4
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Server: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 1: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 2: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: 1:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 1: 1:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 2: 1:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: force to out cards
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_25] Server: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 1: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_29] Client 1: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: 2:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_31] Client 2: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Server: 0:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_25] Server: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 1: 0:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_29] Client 1: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 2: 0:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_31] Client 2: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Server: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_25] Server: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 1: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_29] Client 1: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 2: 1:      out cards successfully
LogBlueprintUserMessages: [MainModule_C_31] Client 2: remove cards num:   2
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Server: 2:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_2] Client 1: 2:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 2: 2:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Server: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 1: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_1] Client 2: 0:      pass~~~~~
LogBlueprintUserMessages: [BP_MyNewPlayer_C_0] Client 1: force to out cards

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引