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; }