-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathSharedSpacesApplication.cs
388 lines (323 loc) · 13.2 KB
/
SharedSpacesApplication.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
// Copyright (c) Facebook, Inc. and its affiliates.
// Use of the material below is subject to the terms of the MIT License
// https://github.com/oculus-samples/Unity-SharedSpaces/tree/main/Assets/SharedSpaces/LICENSE
using Unity.Netcode;
using Oculus.Platform;
using System.Collections;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[InitializeOnLoad]
public static class SharedSpacesTelemetry
{
static SharedSpacesTelemetry()
{
Collect();
}
[MenuItem("Oculus/Telemetry Settings")]
static void TelemetrySettings()
{
Collect(true);
}
static void Collect(bool force = false)
{
const string enabledKey = "OculusTelemetryEnabled";
const string privacyPolicyUrl = "https://www.oculus.com/legal/privacy-policy/";
if (force || EditorPrefs.HasKey(enabledKey) == false)
{
var response = EditorUtility.DisplayDialogComplex(
"Enable Oculus Telemetry",
$"Enabling telemetry will transmit data to Oculus about your usage of its samples and tools. This information is used by Oculus to improve our products and better serve our developers. For more information, go to this url: {privacyPolicyUrl}",
"Enable",
"Opt out",
"Open Privacy Policy");
EditorPrefs.SetBool(enabledKey, response == 0);
if (response == 2)
{
EditorPrefs.DeleteKey(enabledKey);
EditorUtility.OpenWithDefaultApp(privacyPolicyUrl);
}
}
if (EditorPrefs.GetBool(enabledKey) && SessionState.GetBool("OculusTelemetry-module_loaded-SharedSpaces", false) == false)
{
OVRPlugin.SetDeveloperMode(OVRPlugin.Bool.True);
OVRPlugin.SendEvent("module_loaded", "Unity-SharedSpaces", "integration");
SessionState.SetBool("OculusTelemetry-module_loaded-SharedSpaces", true);
}
}
}
#endif
public class SharedSpacesApplication : MonoBehaviour
{
public SharedSpacesNetworkLayer networkLayer;
public SharedSpacesSceneLoader sceneLoader;
public SharedSpacesSpawner spawner;
public SharedSpacesVoip voip;
public SharedSpacesGroupPresenceState groupPresenceState { get; private set; }
private SharedSpacesSession session;
private LaunchType launchType;
private SharedSpacesLocalPlayerState LocalPlayerState => SharedSpacesLocalPlayerState.Instance;
private void OnEnable()
{
DontDestroyOnLoad(this);
networkLayer.OnClientConnectedCallback += OnClientConnected;
networkLayer.OnClientDisconnectedCallback += OnClientDisconnected;
networkLayer.OnMasterClientSwitchedCallback = OnMasterClientSwitched;
networkLayer.StartHostCallback += OnHostStarted;
networkLayer.StartClientCallback += OnClientStarted;
networkLayer.RestoreHostCallback += OnHostRestored;
networkLayer.RestoreClientCallback += OnClientRestored;
}
private void OnClientConnected(ulong clientId)
{
if (NetworkManager.Singleton.IsHost)
{
session.DetermineFallbackHost(clientId);
session.SetPhotonVoiceRoom(clientId);
}
else if (NetworkManager.Singleton.IsClient && clientId == NetworkManager.Singleton.LocalClientId)
{
session = FindObjectOfType<SharedSpacesSession>();
if (networkLayer.clientState == SharedSpacesNetworkLayer.ClientState.RestoringClient)
{
session.RequestSpawnServerRpc(
clientId,
LocalPlayerState.transform.position,
LocalPlayerState.transform.rotation
);
}
else
{
session.RequestSpawnServerRpc(
clientId,
SharedSpacesSpawnPoint.singleton.SpawnPosition,
SharedSpacesSpawnPoint.singleton.SpawnRotation
);
}
}
}
private void OnClientDisconnected(ulong clientId)
{
session.RedetermineFallbackHost(clientId);
}
private ulong OnMasterClientSwitched()
{
return SharedSpacesSession.fallbackHostId;
}
private void OnHostStarted()
{
session = spawner.SpawnSession().GetComponent<SharedSpacesSession>();
NetworkObject player = spawner.SpawnPlayer(
NetworkManager.Singleton.LocalClientId,
SharedSpacesSpawnPoint.singleton.SpawnPosition,
SharedSpacesSpawnPoint.singleton.SpawnRotation
);
voip.StartVoip(player.transform);
}
private void OnClientStarted()
{
NetworkObject player = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
voip.StartVoip(player.transform);
}
private void OnHostRestored()
{
session = spawner.SpawnSession().GetComponent<SharedSpacesSession>();
NetworkObject player = spawner.SpawnPlayer(
NetworkManager.Singleton.LocalClientId,
LocalPlayerState.transform.position,
LocalPlayerState.transform.rotation
);
voip.StartVoip(player.transform);
}
private void OnClientRestored()
{
NetworkObject player = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
voip.StartVoip(player.transform);
}
private void Start()
{
StartCoroutine(Init());
}
private IEnumerator Init()
{
Core.AsyncInitialize().OnComplete(OnOculusPlatformInitialized);
#if !UNITY_EDITOR && !UNITY_STANDALONE_WIN
yield return new WaitUntil(() => LocalPlayerState.username != "");
#else
launchType = LaunchType.Normal;
#endif
// start in the lobby
if (launchType == LaunchType.Normal)
{
groupPresenceState = new SharedSpacesGroupPresenceState();
StartCoroutine(groupPresenceState.Set(
"Lobby",
"Lobby-" + LocalPlayerState.applicationID,
"",
true
)
);
}
yield return new WaitUntil(() => groupPresenceState != null && groupPresenceState.destination != null);
sceneLoader.LoadScene(groupPresenceState.destination);
yield return new WaitUntil(() => sceneLoader.sceneLoaded);
networkLayer.Init(GetPhotonRoomName());
}
private void OnOculusPlatformInitialized(Message<Oculus.Platform.Models.PlatformInitialize> message)
{
if (message.IsError)
{
LogError("Failed to initialize Oculus Platform SDK", message.GetError());
return;
}
Debug.Log("Oculus Platform SDK initialized successfully");
Entitlements.IsUserEntitledToApplication().OnComplete(msg =>
{
if (msg.IsError)
{
LogError("You are not entitled to use this app", msg.GetError());
return;
}
launchType = ApplicationLifecycle.GetLaunchDetails().LaunchType;
GroupPresence.SetJoinIntentReceivedNotificationCallback(OnJoinIntentReceived);
GroupPresence.SetInvitationsSentNotificationCallback(OnInvitationsSent);
Users.GetLoggedInUser().OnComplete(OnLoggedInUser);
});
// Handle the user clicking the AUI button for reports
AbuseReport.SetReportButtonPressedNotificationCallback(OnReportButtonIntentNotif);
}
private void OnLoggedInUser(Message<Oculus.Platform.Models.User> message)
{
if (message.IsError)
{
LogError("Cannot get user info", message.GetError());
return;
}
// Workaround.
// At the moment, Platform.Users.GetLoggedInUser() seems to only be returning the user ID.
// Display name is blank.
// Platform.Users.Get(ulong userID) returns the display name.
Users.Get(message.Data.ID).OnComplete(LocalPlayerState.Init);
}
// User has interacted with the AUI report button outside this app
private void OnReportButtonIntentNotif(Message<string> message)
{
if (!message.IsError)
{
// Inform SDK that we don't handle the request
AbuseReport.ReportRequestHandled(ReportRequestResponse.Unhandled);
}
}
private void OnJoinIntentReceived(Message<Oculus.Platform.Models.GroupPresenceJoinIntent> message)
{
Debug.Log("------JOIN INTENT RECEIVED------");
Debug.Log("Destination: " + message.Data.DestinationApiName);
Debug.Log("Lobby Session ID: " + message.Data.LobbySessionId);
Debug.Log("Match Session ID: " + message.Data.MatchSessionId);
Debug.Log("Deep Link Message: " + message.Data.DeeplinkMessage);
Debug.Log("--------------------------------");
string messageLobbySessionId = message.Data.LobbySessionId;
// If true, this means lobby session ID is a 128-bit hexadecimal, which was generated automatically
// by a group launch link. To remain consistent, only get the first 8 hex digits.
if (!messageLobbySessionId.Contains("Lobby"))
messageLobbySessionId = "Lobby-" + message.Data.LobbySessionId.Substring(0, 8);
// no Group Presence yet:
// app is being launched by this join intent, either
// through an in-app direct invite, or through a deeplink
if (groupPresenceState == null)
{
string lobbySessionID = message.Data.DestinationApiName == "Lobby"
? messageLobbySessionId
: "Lobby-" + LocalPlayerState.applicationID;
groupPresenceState = new SharedSpacesGroupPresenceState();
StartCoroutine(groupPresenceState.Set(
message.Data.DestinationApiName,
lobbySessionID,
GetMatchSessionID(message.Data.DestinationApiName, messageLobbySessionId),
true
)
);
}
// game was already running, meaning the user already has a Group Presence, and
// is already either hosting or a client of another host.
else
{
StartCoroutine(SwitchRoom(message.Data.DestinationApiName, messageLobbySessionId, true));
}
}
private void OnInvitationsSent(Message<Oculus.Platform.Models.LaunchInvitePanelFlowResult> message)
{
Debug.Log("-------INVITED USERS LIST-------");
Debug.Log("Size: " + message.Data.InvitedUsers.Count);
foreach (Oculus.Platform.Models.User user in message.Data.InvitedUsers)
{
Debug.Log("Username: " + user.DisplayName);
Debug.Log("User ID: " + user.ID);
}
Debug.Log("--------------------------------");
}
private void LogError(string message, Oculus.Platform.Models.Error error)
{
Debug.LogError(message);
Debug.LogError("ERROR MESSAGE: " + error.Message);
Debug.LogError("ERROR CODE: " + error.Code);
Debug.LogError("ERROR HTTP CODE: " + error.HttpCode);
}
private IEnumerator SwitchRoom(string destination, string lobbySessionID, bool resetSpawnPoint)
{
if (resetSpawnPoint)
SharedSpacesSpawnPoint.Reset();
else
SharedSpacesSpawnPoint.Move(destination);
string lobbySession = destination == "Lobby"
? lobbySessionID
: groupPresenceState.lobbySessionID;
SharedSpacesSceneLoader.Scenes destination_ = sceneLoader.scenes[destination];
sceneLoader.LoadScene(destination);
yield return new WaitUntil(() => sceneLoader.sceneLoaded);
yield return StartCoroutine(groupPresenceState.Set(
destination_.ToString(),
lobbySession,
GetMatchSessionID(destination_.ToString(), lobbySessionID),
true
)
);
networkLayer.SwitchPhotonRealtimeRoom(GetPhotonRoomName());
}
// only called locally, by owner
public void OnPortalEnter(string portalName)
{
StartCoroutine(SwitchRoom(portalName, groupPresenceState.lobbySessionID, false));
}
public void OnExternalPortalEnter(SharedSpacesExternalPortal portal)
{
var options = new ApplicationOptions();
// only add deeplink message if it's set
if (!string.IsNullOrEmpty(portal.DeepLinkMessage))
{
options.SetDeeplinkMessage(portal.DeepLinkMessage);
}
options.SetDestinationApiName(portal.DestinationAPI);
// We join the same session reference in the application
options.SetLobbySessionId(groupPresenceState.lobbySessionID);
options.SetMatchSessionId(groupPresenceState.matchSessionID);
Oculus.Platform.Application.LaunchOtherApp(portal.ApplicationId, options);
}
private string GetPhotonRoomName()
{
return groupPresenceState.matchSessionID == ""
? groupPresenceState.lobbySessionID
: groupPresenceState.matchSessionID;
}
private string GetMatchSessionID(string destination, string lobbySessionID)
{
string matchSessionID = "";
if (destination != "Lobby")
{
matchSessionID = destination == "PurpleRoom"
? destination
: destination + lobbySessionID;
}
return matchSessionID;
}
}