Documentation for the Unreal C++ Library
Loading...
Searching...
No Matches
MultiplayerManagerComponent.cpp
Go to the documentation of this file.
1// Copyright(c) 2023 PixoVR, LLC. All Rights Reserved.
2
4#include "PVROnlineSession.h"
5#include "PVROSubsystem.h"
6
7DEFINE_LOG_CATEGORY_STATIC(LogMultiplayerManagerComponent, Verbose, All);
8
9#define Verbose(pmt, ...) UE_LOG(LogMultiplayerManagerComponent, Verbose, TEXT(pmt), ##__VA_ARGS__)
10#define Log(pmt, ...) UE_LOG(LogMultiplayerManagerComponent, Log, TEXT(pmt), ##__VA_ARGS__)
11#define Warn(pmt, ...) UE_LOG(LogMultiplayerManagerComponent, Warning, TEXT(pmt), ##__VA_ARGS__)
12#define Error(pmt, ...) UE_LOG(LogMultiplayerManagerComponent, Error, TEXT(pmt), ##__VA_ARGS__)
13#define Fatal(pmt, ...) UE_LOG(LogMultiplayerManagerComponent, Fatal, TEXT(pmt), ##__VA_ARGS__)
14
15// Sets default values for this component's properties
17{
18 // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
19 // off to improve performance if you don't need them.
20 PrimaryComponentTick.bCanEverTick = true;
21
22 Log("Multiplayer Manager Component has been created.");
23
24 // ...
25#if UE_SERVER
26 AgonesSDK = CreateDefaultSubobject<UAgonesComponent>(TEXT("AgonesSDK"));
27#endif
28}
29
30
31// Called when the game starts
33{
34 Super::BeginPlay();
35
36 Log("Are we a server?");
37#if UE_SERVER
38 Log("We are! Start Playing with Server.");
39
40 check(AgonesSDK);
41 bWasMetaDataSet = false;
42 AgonesSDK->Connect();
43 if (IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get())
44 {
45 Log("Get the online subsystem.");
46 FPVROnlineSessionPtr SessionInt = StaticCastSharedPtr<FPVROnlineSession>(OnlineSubsystem->GetSessionInterface());
47 if (SessionInt.IsValid())
48 {
49 auto NamedSession = SessionInt->GetFirstNamedSession();
50 Log("Found first named session.");
51 if (NamedSession)
52 {
53 FSetLabelDelegate SetLabelSuccessDelegate;
54 SetLabelSuccessDelegate.BindDynamic(this, &UMultiplayerManagerComponent::OnSetLabelSuccess);
55 FAgonesErrorDelegate SetLabelFailDelegate;
56 SetLabelFailDelegate.BindDynamic(this, &UMultiplayerManagerComponent::OnSetLabelFail);
57 Log("Online Session was already created!");
58 FString MapName;
59 NamedSession->SessionSettings.Get(SETTING_MAPNAME, MapName);
60 AgonesSDK->SetLabel("SessionID", NamedSession->GetSessionIdStr(), SetLabelSuccessDelegate, SetLabelFailDelegate);
61 AgonesSDK->SetLabel("MapName", MapName, SetLabelSuccessDelegate, SetLabelFailDelegate);
62 AgonesSDK->SetLabel("OwningUserName", NamedSession->OwningUserName, SetLabelSuccessDelegate, SetLabelFailDelegate);
63 AgonesSDK->SetLabel("SessionName", NamedSession->SessionName.ToString(), SetLabelSuccessDelegate, SetLabelFailDelegate);
64 }
65 else
66 {
67 SessionInt->OnCreateSessionCompleteDelegates.AddUObject(this, &UMultiplayerManagerComponent::OnSessionCreated);
68 }
69 }
70 }
72 AgonesSDK->WatchGameServer(GameServerDelegate);
73#endif
74}
75
76void UMultiplayerManagerComponent::OnSetLabelSuccess(const FEmptyResponse& Response)
77{
78 Verbose("Set label success.");
79}
80
82{
83 Verbose("Set label error: %s", *Error.ErrorMessage);
84}
85
86// Called every frame
87void UMultiplayerManagerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
88{
89 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
90
91 // ...
92}
93
94void UMultiplayerManagerComponent::OnGameServerChanged(const FGameServerResponse& Response)
95{
96 Verbose("Game server %s changed with state %s at address %s and health checks are %s", *Response.ObjectMeta.Name, *Response.Status.State, *Response.Status.Address, Response.Spec.Health.bDisabled ? TEXT("Disabled") : TEXT("Enabled"));
97
98#if UE_SERVER
99 if (Response.Status.State.Equals("Ready", ESearchCase::Type::IgnoreCase) && !bWasMetaDataSet)
100 {
101 Log("Server is ready.");
102 int ModuleID = 0;
103 if (!FParse::Value(FCommandLine::Get(), TEXT("-PIXOVR_MODULE_ID="), ModuleID))
104 {
105 // OK, we failed to find the module version reading from the terminal. Let's check the ini files.
106 if (GConfig && !GConfig->GetInt(TEXT("/Script/ApexSDK.ApexSDKSettings"), TEXT("ModuleId"), ModuleID, GEngineIni))
107 {
108 Fatal("No Module ID available.");
109 }
110 }
111
112 int OrgID = 0;
113 if (!FParse::Value(FCommandLine::Get(), TEXT("-PIXOVR_ORG_ID="), OrgID))
114 {
115 // This is likely stored already in the server data. Thanks Agones!
116 Error("No Org ID available.");
117 }
118
119 FString ModuleVersion = TEXT("0.1.0");
120 if (!FParse::Value(FCommandLine::Get(), TEXT("-PIXOVR_MODULE_VERSION="), ModuleVersion))
121 {
122 // OK, we failed to find the module version reading from the terminal. Let's check the ApexSDK.
123 if (GConfig && !GConfig->GetString(TEXT("/Script/ApexSDK.ApexSDKSettings"), TEXT("ModuleVersion"), ModuleVersion, GEngineIni))
124 {
125 Fatal("No Module Version available.");
126 }
127 }
128
129 // We won't include OrgID since we're now using Agones to fill that information out for the server.
130 AgonesSDK->SetLabel("ModuleID", FString::FromInt(ModuleID), {}, {});
131 AgonesSDK->SetLabel("ModuleVersion", ModuleVersion, {}, {});
132
133 Log("Flagging that meta data was set.");
134 bWasMetaDataSet = true;
135 }
136#endif
137}
138
139void UMultiplayerManagerComponent::OnSessionCreated(FName SessionName, bool bWasSuccessful)
140{
141 Log("Online Session was Created!");
142 if (!bWasSuccessful)
143 {
144 Warn("No session was created successfully.");
145 return;
146 }
147
148#if UE_SERVER
149 if (IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get())
150 {
151 FPVROnlineSessionPtr SessionInt = StaticCastSharedPtr<FPVROnlineSession>(OnlineSubsystem->GetSessionInterface());
152 if (SessionInt.IsValid())
153 {
154 auto NamedSession = SessionInt->GetNamedSession(SessionName);
155 if (NamedSession)
156 {
157 AgonesSDK->SetLabel("SessionID", NamedSession->GetSessionIdStr(), {}, {});
158 FString MapName;
159 NamedSession->SessionSettings.Get(SETTING_MAPNAME, MapName);
160 AgonesSDK->SetLabel("MapName", MapName, {}, {});
161 AgonesSDK->SetLabel("OwningUserName", NamedSession->OwningUserName, {}, {});
162 }
163 AgonesSDK->SetLabel("SessionName", SessionName.ToString(), {}, {});
164 }
165 }
166#endif
167}
168
169void UMultiplayerManagerComponent::SetUserInfo(FString InUserName, int InUserOrgId)
170{
171 if (IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get())
172 {
173 FPVROSubsystem* PVROSubsystem = (FPVROSubsystem*)OnlineSubsystem;
174 if (PVROSubsystem)
175 {
176 PVROSubsystem->SetUserInfo(InUserName, InUserOrgId);
177 }
178 }
179}
180
181void UMultiplayerManagerComponent::SetModuleInfo(int InModuleId, FString InModuleVersion)
182{
183 if (IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get())
184 {
185 FPVROSubsystem* PVROSubsystem = (FPVROSubsystem*)OnlineSubsystem;
186 if (PVROSubsystem)
187 {
188 PVROSubsystem->SetModuleInfo(InModuleId, InModuleVersion);
189 }
190 }
191}
192
193bool UMultiplayerManagerComponent::FindSessions(float InTimeoutInSeconds, int InOrgId, int InModuleId, FString InUserName, FString InModuleVersion)
194{
195 UGameInstance* GameInstance = GetWorld()->GetGameInstance();
196
197 if (GameInstance)
198 {
199 if (IOnlineSubsystem* const OnlineSubsystem = IOnlineSubsystem::Get())
200 {
201 IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
202 if (Session.IsValid())
203 {
204 TSharedPtr<FOnlineSessionSearch> SearchSettings = MakeShareable(new FOnlineSessionSearch());
205 SearchSettings->QuerySettings.Set(FName(TEXT("OrgID")), InOrgId, EOnlineComparisonOp::Equals);
206 SearchSettings->QuerySettings.Set(FName(TEXT("ModuleID")), InModuleId, EOnlineComparisonOp::Equals);
207 SearchSettings->QuerySettings.Set(FName(TEXT("UserName")), InUserName, EOnlineComparisonOp::Equals);
208 SearchSettings->QuerySettings.Set(FName(TEXT("ModuleVersion")), InModuleVersion, EOnlineComparisonOp::Equals);
209 SearchSettings->TimeoutInSeconds = InTimeoutInSeconds;
210
211 TSharedRef<FOnlineSessionSearch> SearchSettingsRef = SearchSettings.ToSharedRef();
212
213 ULocalPlayer* const Player = GameInstance->GetFirstGamePlayer();
214 Session->FindSessions(*Player->GetPreferredUniqueNetId().GetUniqueNetId(), SearchSettingsRef);
215 }
216 }
217 }
218
219 Warn("No suitable Online Subsystem is available.");
220 return false;
221}
222
223#undef Verbose
224#undef Log
225#undef Warn
226#undef Error
227#undef Fatal
#define Error(pmt,...)
#define Fatal(pmt,...)
DEFINE_LOG_CATEGORY_STATIC(LogMultiplayerManagerComponent, Verbose, All)
#define Warn(pmt,...)
#define Log(pmt,...)
#define Verbose(pmt,...)
TSharedPtr< FPVROnlineSession, ESPMode::ThreadSafe > FPVROnlineSessionPtr
void SetModuleInfo(int InModuleId, FString InModuleVersion)
void SetUserInfo(FString InUserName, int InUserOrgId)
void OnSetLabelFail(const FAgonesError &Error)
UFUNCTION(Category = "Multiplayer | Manager")
void SetUserInfo(FString InUserName, int InUserOrgId)
UFUNCTION(BlueprintCallable, Category = "Multiplayer | Manager")
void SetModuleInfo(int InModuleId, FString InModuleVersion)
UFUNCTION(BlueprintCallable, Category = "Multiplayer | Manager")
FGameServerDelegate GameServerDelegate
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool FindSessions(float InTimeoutInSeconds=120.f, int InOrgId=-1, int InModuleId=-1, FString InUserName="", FString InModuleVersion="")
UFUNCTION(BlueprintCallable, Category = "Multiplayer | Manager")
void OnSetLabelSuccess(const FEmptyResponse &Response)
UFUNCTION(Category = "Multiplayer | Manager")
virtual void OnSessionCreated(FName SessionName, bool bSuccessful)
UFUNCTION(BlueprintCallable, Category = "Multiplayer | Manager")
virtual void OnGameServerChanged(const FGameServerResponse &Response)
UFUNCTION(BlueprintCallable, Category = "Multiplayer | Manager")
bool bWasMetaDataSet
UPROPERTY(BlueprintReadOnly)
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override