UE4局域网斗地主(四)
发表于2018-01-26
上一篇文章中,出现一个问题:客户端玩家新加入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
UE4局域网斗地主开发: