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局域网斗地主开发:
