示例#1
0
EPartyReservationResult::Type APartyBeaconHost::AddPartyReservation(const FPartyReservation& ReservationRequest)
{
    EPartyReservationResult::Type Result = EPartyReservationResult::GeneralError;

    if (!State || GetBeaconState() == EBeaconState::DenyRequests)
    {
        return EPartyReservationResult::ReservationDenied;
    }

    if (ReservationRequest.IsValid())
    {
        if (State->DoesReservationFit(ReservationRequest))
        {
            bool bContinue = true;
            if (ValidatePlayers.IsBound())
            {
                bContinue = ValidatePlayers.Execute(ReservationRequest.PartyMembers);
            }

            if (bContinue)
            {
                const int32 ExistingReservationIdx = State->GetExistingReservation(ReservationRequest.PartyLeader);
                if (ExistingReservationIdx != INDEX_NONE)
                {
                    TArray<FPartyReservation>& Reservations = State->GetReservations();
                    FPartyReservation& ExistingReservation = Reservations[ExistingReservationIdx];
                    if (ReservationRequest.PartyMembers.Num() == ExistingReservation.PartyMembers.Num())
                    {
                        // Verify the reservations are the same
                        int32 NumMatchingReservations = 0;
                        for (const FPlayerReservation& NewPlayerRes : ReservationRequest.PartyMembers)
                        {
                            FPlayerReservation* PlayerRes = ExistingReservation.PartyMembers.FindByPredicate(
                                                                [NewPlayerRes](const FPlayerReservation& ExistingPlayerRes)
                            {
                                return NewPlayerRes.UniqueId == ExistingPlayerRes.UniqueId;
                            });

                            if (PlayerRes)
                            {
                                NumMatchingReservations++;
                            }
                        }

                        if (NumMatchingReservations == ExistingReservation.PartyMembers.Num())
                        {
                            for (const FPlayerReservation& NewPlayerRes : ReservationRequest.PartyMembers)
                            {
                                FPlayerReservation* PlayerRes = ExistingReservation.PartyMembers.FindByPredicate(
                                                                    [NewPlayerRes](const FPlayerReservation& ExistingPlayerRes)
                                {
                                    return NewPlayerRes.UniqueId == ExistingPlayerRes.UniqueId;
                                });

                                if (PlayerRes)
                                {
                                    // Update the validation auth strings because they may have changed with a new login
                                    PlayerRes->ValidationStr = NewPlayerRes.ValidationStr;
                                }
                            }

                            SendReservationUpdates();

                            // Clean up the game entities for these duplicate players
                            DuplicateReservation.ExecuteIfBound(ReservationRequest);

                            // Add all players back into the pending join list
                            for (int32 Count = 0; Count < ReservationRequest.PartyMembers.Num(); Count++)
                            {
                                NewPlayerAdded(ReservationRequest.PartyMembers[Count]);
                            }

                            Result = EPartyReservationResult::ReservationDuplicate;
                        }
                        else
                        {
                            // Existing reservation doesn't match incoming duplicate reservation
                            Result = EPartyReservationResult::IncorrectPlayerCount;
                        }
                    }
                    else
                    {
                        // Existing reservation doesn't match incoming duplicate reservation
                        Result = EPartyReservationResult::IncorrectPlayerCount;
                    }
                }
                else
                {
                    if (State->AreTeamsAvailable(ReservationRequest))
                    {
                        if (State->AddReservation(ReservationRequest))
                        {
                            // Keep track of newly added players
                            for (const FPlayerReservation& PartyMember : ReservationRequest.PartyMembers)
                            {
                                NewPlayerAdded(PartyMember);
                            }

                            SendReservationUpdates();

                            NotifyReservationEventNextFrame(ReservationChanged);
                            if (State->IsBeaconFull())
                            {
                                NotifyReservationEventNextFrame(ReservationsFull);
                            }

                            Result = EPartyReservationResult::ReservationAccepted;
                        }
                        else
                        {
                            Result = EPartyReservationResult::IncorrectPlayerCount;
                        }
                    }
                    else
                    {
                        // New reservation doesn't fit with existing players
                        Result = EPartyReservationResult::PartyLimitReached;
                    }
                }
            }
            else
            {
                Result = EPartyReservationResult::ReservationDenied_Banned;
            }
        }
        else
        {
            Result = EPartyReservationResult::IncorrectPlayerCount;
        }
    }
    else
    {
        Result = EPartyReservationResult::IncorrectPlayerCount;
    }

    return Result;
}
EPartyReservationResult::Type APartyBeaconHost::UpdatePartyReservation(const FPartyReservation& ReservationUpdateRequest)
{
	EPartyReservationResult::Type Result = EPartyReservationResult::GeneralError;

	if (!State || GetBeaconState() == EBeaconState::DenyRequests)
	{
		return EPartyReservationResult::ReservationDenied;
	}

	if (ReservationUpdateRequest.IsValid())
	{
		if (!State->IsBeaconFull())
		{
			const int32 ExistingReservationIdx = State->GetExistingReservation(ReservationUpdateRequest.PartyLeader);
			if (ExistingReservationIdx != INDEX_NONE)
			{
				// Count the number of available slots for the existing reservation's team
				TArray<FPartyReservation>& Reservations = State->GetReservations();
				FPartyReservation& ExistingReservation = Reservations[ExistingReservationIdx];
				const int32 NumTeamMembers = GetNumPlayersOnTeam(ExistingReservation.TeamNum);
				const int32 NumAvailableSlotsOnTeam = FMath::Max<int32>(0, GetMaxPlayersPerTeam() - NumTeamMembers);

				// Read the list of new players and remove the ones that have existing reservation entries
				TArray<FPlayerReservation> NewPlayers;
				for (int32 PlayerIdx = 0; PlayerIdx < ReservationUpdateRequest.PartyMembers.Num(); PlayerIdx++)
				{
					const FPlayerReservation& NewPlayerRes = ReservationUpdateRequest.PartyMembers[PlayerIdx];

					FPlayerReservation* PlayerRes = ExistingReservation.PartyMembers.FindByPredicate(
						[NewPlayerRes](const FPlayerReservation& ExistingPlayerRes)
					{
						return NewPlayerRes.UniqueId == ExistingPlayerRes.UniqueId;
					});

					if (!PlayerRes)
					{
						// player reservation doesn't exist so add it as a new player
						NewPlayers.Add(NewPlayerRes);
					}
					else
					{
						// duplicate entry for this player
						UE_LOG(LogBeacon, Log, TEXT("Skipping player %s"),
							*NewPlayerRes.UniqueId.ToString());
					}
				}

				// Validate that adding the new party members to this reservation entry still fits within the team size
				if (NewPlayers.Num() <= NumAvailableSlotsOnTeam)
				{
					if (NewPlayers.Num() > 0)
					{
						// Copy new player entries into existing reservation
						for (int32 PlayerIdx = 0; PlayerIdx < NewPlayers.Num(); PlayerIdx++)
						{
							const FPlayerReservation& PlayerRes = NewPlayers[PlayerIdx];
							ExistingReservation.PartyMembers.Add(PlayerRes);
							// Keep track of newly added players
							NewPlayerAdded(PlayerRes);
						}

						// Update the reservation count before sending the response
						State->NumConsumedReservations += NewPlayers.Num();

						// Tell any UI and/or clients that there has been a change in the reservation state
						SendReservationUpdates();

						// Tell the owner that we've received a reservation so the UI can be updated
						NotifyReservationEventNextFrame(ReservationChanged);
						if (State->IsBeaconFull())
						{
							// If we've hit our limit, fire the delegate so the host can do the
							// next step in getting parties together
							NotifyReservationEventNextFrame(ReservationsFull);
						}

						Result = EPartyReservationResult::ReservationAccepted;
					}
					else
					{
						// Duplicate entries (or zero) so existing reservation not updated
						Result = EPartyReservationResult::ReservationDuplicate;
					}
				}
				else
				{
					// Send an invalid party size response
					Result = EPartyReservationResult::IncorrectPlayerCount;
				}
			}
			else
			{
				// Send a not found reservation response
				Result = EPartyReservationResult::ReservationNotFound;
			}
		}
		else
		{
			// Send a session full response
			Result = EPartyReservationResult::PartyLimitReached;
		}
	}
	else
	{
		// Invalid reservation
		Result = EPartyReservationResult::ReservationInvalid;
	}	

	return Result;
}