Files
UnrealEngine/Engine/Plugins/Online/OnlineFramework/Source/Lobby/Private/LobbyBeaconClient.cpp
2025-05-18 13:04:45 +08:00

382 lines
11 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LobbyBeaconClient.h"
#include "Engine/GameInstance.h"
#include "GameFramework/PlayerController.h"
#include "Engine/NetConnection.h"
#include "GameFramework/PlayerState.h"
#include "Engine/LocalPlayer.h"
#include "Net/UnrealNetwork.h"
#include "LobbyBeaconHost.h"
#include "LobbyBeaconPlayerState.h"
#include "OnlineSubsystemUtils.h"
#include "OnlineSessionClient.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(LobbyBeaconClient)
ALobbyBeaconClient::ALobbyBeaconClient(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer),
LobbyState(nullptr),
PlayerState(nullptr),
bLoggedIn(false),
LobbyJoinServerState(ELobbyBeaconJoinState::None)
{
bOnlyRelevantToOwner = true;
}
void ALobbyBeaconClient::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ALobbyBeaconClient, LobbyState);
DOREPLIFETIME(ALobbyBeaconClient, PlayerState);
}
void ALobbyBeaconClient::EndPlay(EEndPlayReason::Type Reason)
{
Super::EndPlay(Reason);
if (PlayerState)
{
if (PlayerState->ClientActor == this)
{
PlayerState->ClientActor = nullptr;
}
if (PlayerState->GetOwner() == this)
{
PlayerState->SetOwner(nullptr);
}
}
}
void ALobbyBeaconClient::OnConnected()
{
UE_LOG(LogLobbyBeacon, Verbose, TEXT("Lobby beacon connection established."));
OnLobbyConnectionEstablished().ExecuteIfBound();
LoginLocalPlayers();
}
void ALobbyBeaconClient::ConnectToLobby(const FOnlineSessionSearchResult& DesiredHost)
{
// Make this stuff common?
bool bSuccess = false;
IOnlineSubsystem* OnlineSub = Online::GetSubsystem(GetWorld());
if (OnlineSub)
{
IOnlineSessionPtr SessionInt = OnlineSub->GetSessionInterface();
if (SessionInt.IsValid())
{
FString ConnectInfo;
if (SessionInt->GetResolvedConnectString(DesiredHost, NAME_BeaconPort, ConnectInfo))
{
FURL ConnectURL(NULL, *ConnectInfo, TRAVEL_Absolute);
if (InitClient(ConnectURL) && DesiredHost.Session.SessionInfo.IsValid())
{
DestSessionId = DesiredHost.Session.SessionInfo->GetSessionId().ToString();
bSuccess = true;
}
else
{
UE_LOG(LogLobbyBeacon, Warning, TEXT("ConnectToLobby: Failure to init client beacon with %s."), *ConnectURL.ToString());
}
}
}
}
if (!bSuccess)
{
OnFailure();
}
}
void ALobbyBeaconClient::ClientJoinGame_Implementation()
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ClientJoinGame signal %d"), bLoggedIn);
if (bLoggedIn)
{
OnJoiningGame().ExecuteIfBound();
}
}
void ALobbyBeaconClient::ClientSetInviteFlags_Implementation(const FJoinabilitySettings& Settings)
{
UGameInstance* GameInstance = GetGameInstance();
check(GameInstance);
UOnlineSessionClient* OnlineSessionClient = Cast<UOnlineSessionClient>(GameInstance->GetOnlineSession());
if (OnlineSessionClient)
{
OnlineSessionClient->SetInviteFlags(GetWorld(), Settings);
}
}
void ALobbyBeaconClient::SetPartyOwnerId(const FUniqueNetIdRepl& InUniqueId, const FUniqueNetIdRepl& InPartyOwnerId)
{
if (bLoggedIn)
{
ServerSetPartyOwner(InUniqueId, InPartyOwnerId);
if (PlayerState)
{
PlayerState->PartyOwnerUniqueId = InPartyOwnerId;
}
}
else
{
UE_LOG(LogLobbyBeacon, Warning, TEXT("Not logged in when calling SetPartyOwnerId"));
}
}
void ALobbyBeaconClient::DisconnectFromLobby()
{
if (bLoggedIn)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("DisconnectFromLobby %s Id: %s"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"));
ServerDisconnectFromLobby();
bLoggedIn = false;
}
else
{
UE_LOG(LogLobbyBeacon, Verbose, TEXT("Not logged in when calling DisconnectFromLobby"));
}
}
void ALobbyBeaconClient::JoiningServer()
{
if (bLoggedIn)
{
if (LobbyJoinServerState == ELobbyBeaconJoinState::None)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("JoiningServer %s Id: %s"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"));
LobbyJoinServerState = ELobbyBeaconJoinState::SentJoinRequest;
ServerNotifyJoiningServer();
}
else
{
UE_LOG(LogLobbyBeacon, Warning, TEXT("Already joining server, skipping %d"), static_cast<int32>(LobbyJoinServerState));
}
}
else
{
UE_LOG(LogLobbyBeacon, Warning, TEXT("Not logged in when calling JoiningServer"));
}
}
void ALobbyBeaconClient::KickPlayer(const FUniqueNetIdRepl& PlayerToKick, const FText& Reason)
{
if (bLoggedIn)
{
ServerKickPlayer(PlayerToKick, Reason);
}
else
{
UE_LOG(LogLobbyBeacon, Warning, TEXT("Not logged in when calling KickPlayer"));
}
}
void ALobbyBeaconClient::LoginLocalPlayers()
{
FURL URL(nullptr, TEXT(""), TRAVEL_Absolute);
FUniqueNetIdRepl UniqueIdRepl;
UWorld* World = GetWorld();
for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
APlayerController* PC = Iterator->Get();
if (PC && PC->PlayerState && PC->PlayerState->GetUniqueId().IsValid())
{
ULocalPlayer* LP = Cast<ULocalPlayer>(PC->Player);
if (LP)
{
// Send the player nickname if available
FString OverrideName = LP->GetNickname();
if (OverrideName.Len() > 0)
{
URL.AddOption(*FString::Printf(TEXT("Name=%s"), *OverrideName));
}
// Send any game-specific url options for this player
FString GameUrlOptions = LP->GetGameLoginOptions();
if (GameUrlOptions.Len() > 0)
{
URL.AddOption(*FString::Printf(TEXT("%s"), *GameUrlOptions));
}
// Send the player unique Id at login
UniqueIdRepl = LP->GetPreferredUniqueNetId();
FString UrlString = URL.ToString();
if (UniqueIdRepl.IsValid())
{
ServerLoginPlayer(DestSessionId, UniqueIdRepl, UrlString);
}
}
}
}
}
void ALobbyBeaconClient::SetLobbyState(ALobbyBeaconState* InLobbyState)
{
AOnlineBeaconHostObject* BeaconHost = GetBeaconOwner();
if (BeaconHost)
{
LobbyState = InLobbyState;
}
}
bool ALobbyBeaconClient::ServerLoginPlayer_Validate(const FString& InSessionId, const FUniqueNetIdRepl& InUniqueId, const FString& UrlString)
{
return !InSessionId.IsEmpty() && InUniqueId.IsValid() && !UrlString.IsEmpty();
}
void ALobbyBeaconClient::ServerLoginPlayer_Implementation(const FString& InSessionId, const FUniqueNetIdRepl& InUniqueId, const FString& UrlString)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ServerLoginPlayer %s %s."), *InUniqueId.ToString(), *UrlString);
ALobbyBeaconHost* BeaconHost = Cast<ALobbyBeaconHost>(GetBeaconOwner());
if (BeaconHost)
{
BeaconHost->ProcessLogin(this, InSessionId, InUniqueId, UrlString);
}
}
void ALobbyBeaconClient::ClientLoginComplete_Implementation(const FUniqueNetIdRepl& InUniqueId, bool bWasSuccessful)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ClientLoginComplete %s %s."), *InUniqueId.ToString(), bWasSuccessful ? TEXT("Success") : TEXT("Failure"));
bLoggedIn = bWasSuccessful;
OnLoginComplete().ExecuteIfBound(bLoggedIn);
}
void ALobbyBeaconClient::ClientWasKicked_Implementation(const FText& KickReason)
{
}
bool ALobbyBeaconClient::ServerDisconnectFromLobby_Validate()
{
return true;
}
void ALobbyBeaconClient::ServerDisconnectFromLobby_Implementation()
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ServerDisconnectFromLobby %s Id: %s"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"));
ALobbyBeaconHost* BeaconHost = Cast<ALobbyBeaconHost>(GetBeaconOwner());
if (BeaconHost)
{
BeaconHost->ProcessDisconnect(this);
}
}
bool ALobbyBeaconClient::ServerNotifyJoiningServer_Validate()
{
return true;
}
void ALobbyBeaconClient::ServerNotifyJoiningServer_Implementation()
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ServerNotifyJoiningGame %s Id: %s"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"));
ALobbyBeaconHost* BeaconHost = Cast<ALobbyBeaconHost>(GetBeaconOwner());
if (BeaconHost)
{
BeaconHost->ProcessJoinServer(this);
}
}
void ALobbyBeaconClient::AckJoiningServer()
{
if (GetNetMode() < NM_Client)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("AckJoiningServer %s Id: %s"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"));
LobbyJoinServerState = ELobbyBeaconJoinState::JoinRequestAcknowledged;
ClientAckJoiningServer();
}
}
void ALobbyBeaconClient::ClientAckJoiningServer_Implementation()
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ClientAckJoiningServer %s Id: %s LoggedIn: %d"), *GetName(), PlayerState ? *PlayerState->UniqueId->ToString() : TEXT("Unknown"), bLoggedIn);
LobbyJoinServerState = ELobbyBeaconJoinState::JoinRequestAcknowledged;
OnJoiningGameAck().ExecuteIfBound();
}
bool ALobbyBeaconClient::ServerKickPlayer_Validate(const FUniqueNetIdRepl& PlayerToKick, const FText& Reason)
{
return true;
}
void ALobbyBeaconClient::ServerKickPlayer_Implementation(const FUniqueNetIdRepl& PlayerToKick, const FText& Reason)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ServerKickPlayer %s -> %s"), (PlayerState != nullptr ? *PlayerState->UniqueId.ToString() : TEXT("")),
*PlayerToKick.ToString());
ALobbyBeaconHost* BeaconHost = Cast<ALobbyBeaconHost>(GetBeaconOwner());
if (BeaconHost)
{
BeaconHost->ProcessKickPlayer(this, PlayerToKick, Reason);
}
}
bool ALobbyBeaconClient::ServerSetPartyOwner_Validate(const FUniqueNetIdRepl& InUniqueId, const FUniqueNetIdRepl& InPartyOwnerId)
{
return InUniqueId.IsValid() && InPartyOwnerId.IsValid();
}
void ALobbyBeaconClient::ServerSetPartyOwner_Implementation(const FUniqueNetIdRepl& InUniqueId, const FUniqueNetIdRepl& InPartyOwnerId)
{
}
void ALobbyBeaconClient::ClientPlayerJoined_Implementation(const FText& NewPlayerName, const FUniqueNetIdRepl& InUniqueId)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ClientPlayerJoined %s %s."), *NewPlayerName.ToString(), *InUniqueId.ToDebugString());
if (GetNetMode() != NM_Standalone)
{
IOnlineSessionPtr SessionInt = Online::GetSessionInterface(GetWorld());
if (SessionInt.IsValid() && InUniqueId.IsValid())
{
// Register the player as part of the session
SessionInt->RegisterPlayer(NAME_GameSession, *InUniqueId, false);
}
}
OnPlayerJoined().ExecuteIfBound(NewPlayerName, InUniqueId);
}
void ALobbyBeaconClient::ClientPlayerLeft_Implementation(const FUniqueNetIdRepl& InUniqueId)
{
UE_LOG(LogLobbyBeacon, Log, TEXT("ClientPlayerLeft %s"), *InUniqueId.ToDebugString());
if (GetNetMode() != NM_Standalone)
{
IOnlineSessionPtr SessionInt = Online::GetSessionInterface(GetWorld());
if (SessionInt.IsValid() && InUniqueId.IsValid())
{
// Register the player as part of the session
SessionInt->UnregisterPlayer(NAME_GameSession, *InUniqueId);
}
}
OnPlayerLeft().ExecuteIfBound(InUniqueId);
}
bool ALobbyBeaconClient::ServerCheat_Validate(const FString& Msg)
{
return !UE_BUILD_SHIPPING;
}
void ALobbyBeaconClient::ServerCheat_Implementation(const FString& Msg)
{
#if !UE_BUILD_SHIPPING
UNetConnection* NetConnection = GetNetConnection();
if (NetConnection)
{
NetConnection->ConsoleCommand(Msg);
}
#endif
}