diff --git a/Content/RWTHVRGameMode.uasset b/Content/RWTHVRGameMode.uasset index 98183e89f709fbd7dbeb90756e70a0a14c67982d..5d31dc4d676d23d7815db315ca8d567445a51385 100644 Binary files a/Content/RWTHVRGameMode.uasset and b/Content/RWTHVRGameMode.uasset differ diff --git a/Source/RWTHVRToolkit/Private/Core/RWTHVRGameModeBase.cpp b/Source/RWTHVRToolkit/Private/Core/RWTHVRGameModeBase.cpp index bb25b4095a8f707d54de38852acb5dcad5ed6d9a..745b2275555f25098a56944835f59ea17afdf01a 100644 --- a/Source/RWTHVRToolkit/Private/Core/RWTHVRGameModeBase.cpp +++ b/Source/RWTHVRToolkit/Private/Core/RWTHVRGameModeBase.cpp @@ -4,8 +4,10 @@ #include "Core/RWTHVRGameModeBase.h" #include "Core/RWTHVRPlayerState.h" +#include "GameFramework/SpectatorPawn.h" #include "Kismet/GameplayStatics.h" #include "Logging/StructuredLog.h" +#include "Utility/VirtualRealityUtilities.h" FString ARWTHVRGameModeBase::InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, @@ -19,9 +21,9 @@ FString ARWTHVRGameModeBase::InitNewPlayer(APlayerController* NewPlayerControlle // Check if we're using our custom PlayerState so that we can save the player type there. // If not, just ingore all related args. ARWTHVRPlayerState* State = Cast<ARWTHVRPlayerState>(NewPlayerController->PlayerState); - + if (State != nullptr) - { + { if (UGameplayStatics::HasOption(Options, PrimaryNodeIdKey)) { const FString PrimaryNodeId = UGameplayStatics::ParseOption(Options, PrimaryNodeIdKey); @@ -31,11 +33,53 @@ FString ARWTHVRGameModeBase::InitNewPlayer(APlayerController* NewPlayerControlle const FString NodeName = UGameplayStatics::HasOption(Options, NodeNameKey) ? UGameplayStatics::ParseOption(Options, NodeNameKey) : PrimaryNodeId; - - const EPlayerType Type = NodeName == PrimaryNodeId ? EPlayerType::nDisplayPrimary : EPlayerType::nDisplaySecondary; - State->RequestSetPlayerType(Type); + + const EPlayerType Type = NodeName == PrimaryNodeId + ? EPlayerType::nDisplayPrimary + : EPlayerType::nDisplaySecondary; + State->RequestSetPlayerType(Type); + } + } + + return Super::InitNewPlayer(NewPlayerController, UniqueId, Options, Portal); +} + +void ARWTHVRGameModeBase::PostLogin(APlayerController* NewPlayer) +{ + if (const ARWTHVRPlayerState* State = Cast<ARWTHVRPlayerState>(NewPlayer->PlayerState); State != nullptr) + { + // If the new player is a secondary nDisplay node, spawn it only as a Spectator + // Potentially we can use MustSpectate instead. + UClass* PawnClass; + if (State->GetPlayerType() == EPlayerType::nDisplaySecondary) + { + // For now, simply use the BP approach of spawning the pawn here. Can do this in a better way potentially. + PawnClass = SpectatorClass; + } + else + PawnClass = DefaultPawnClass; + + FActorSpawnParameters SpawnInfo; + SpawnInfo.Instigator = GetInstigator(); + SpawnInfo.ObjectFlags |= RF_Transient; + const AActor* StartSpot = FindPlayerStart(NewPlayer); + + // If a start spot wasn't found, + if (StartSpot == nullptr) + { + // Check for a previously assigned spot + if (NewPlayer->StartSpot != nullptr) + { + StartSpot = NewPlayer->StartSpot.Get(); + UE_LOG(Toolkit, Warning, TEXT("RestartPlayer: Player start not found, using last start spot")); + } } + + // Spawn and possess the pawn + APawn* ResultPawn = GetWorld()->SpawnActor<APawn>(PawnClass, StartSpot->GetTransform(), SpawnInfo); + NewPlayer->Possess(ResultPawn); } - - return Super::InitNewPlayer(NewPlayerController, UniqueId, Options, Portal); + + + Super::PostLogin(NewPlayer); } diff --git a/Source/RWTHVRToolkit/Public/Core/RWTHVRGameModeBase.h b/Source/RWTHVRToolkit/Public/Core/RWTHVRGameModeBase.h index 9e84c8aa895da5dbc1ec31f1cbdb0f95d1e3da42..16e0efcefd41472fe45dcd209d89935a7bca5d1f 100644 --- a/Source/RWTHVRToolkit/Public/Core/RWTHVRGameModeBase.h +++ b/Source/RWTHVRToolkit/Public/Core/RWTHVRGameModeBase.h @@ -17,6 +17,16 @@ class RWTHVRTOOLKIT_API ARWTHVRGameModeBase : public AGameModeBase GENERATED_BODY() protected: + /** + * Checks the connection options to see whether we're running in a cave multi user environment. + * If we are, set the player types correspondingly. + */ virtual FString InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal) override; + + /** + * Checks the player type of the NewPlayer. If it has been set to nDisplaySecondary, spawn a spectator pawn and possess. + * If not, spawn a DefaultPawnClass Pawn and Possess it (Should be BP_VirtualRealityPawn to make sense). + */ + virtual void PostLogin(APlayerController* NewPlayer) override; };