上一篇文章中,出现一个问题:客户端玩家新加入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");
OutCardsSucc