-
Notifications
You must be signed in to change notification settings - Fork 1
/
ApplicationController.cs
142 lines (120 loc) · 6.08 KB
/
ApplicationController.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
using System;
using System.Collections;
using Unity.BossRoom.ApplicationLifecycle.Messages;
using Unity.BossRoom.ConnectionManagement;
using Unity.BossRoom.Gameplay.GameState;
using Unity.BossRoom.Gameplay.Messages;
using Unity.BossRoom.Infrastructure;
using Unity.BossRoom.UnityServices;
using Unity.BossRoom.UnityServices.Auth;
using Unity.BossRoom.UnityServices.Lobbies;
using Unity.BossRoom.Utils;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.SceneManagement;
using VContainer;
using VContainer.Unity;
namespace Unity.BossRoom.ApplicationLifecycle
{
/// <summary>
/// An entry point to the application, where we bind all the common dependencies to the root DI scope.
/// </summary>
public class ApplicationController : LifetimeScope
{
[SerializeField] UpdateRunner m_UpdateRunner;
[SerializeField] ConnectionManager m_ConnectionManager;
[SerializeField] NetworkManager m_NetworkManager;
LocalLobby m_LocalLobby;
LobbyServiceFacade m_LobbyServiceFacade;
IDisposable m_Subscriptions;
protected override void Configure(IContainerBuilder builder)
{
base.Configure(builder);
builder.RegisterComponent(m_UpdateRunner);
builder.RegisterComponent(m_ConnectionManager);
builder.RegisterComponent(m_NetworkManager);
//the following singletons represent the local representations of the lobby that we're in and the user that we are
//they can persist longer than the lifetime of the UI in MainMenu where we set up the lobby that we create or join
builder.Register<LocalLobbyUser>(Lifetime.Singleton);
builder.Register<LocalLobby>(Lifetime.Singleton);
builder.Register<ProfileManager>(Lifetime.Singleton);
builder.Register<PersistentGameState>(Lifetime.Singleton);
//these message channels are essential and persist for the lifetime of the lobby and relay services
// Registering as instance to prevent code stripping on iOS
builder.RegisterInstance(new MessageChannel<QuitApplicationMessage>()).AsImplementedInterfaces();
builder.RegisterInstance(new MessageChannel<UnityServiceErrorMessage>()).AsImplementedInterfaces();
builder.RegisterInstance(new MessageChannel<ConnectStatus>()).AsImplementedInterfaces();
builder.RegisterInstance(new MessageChannel<DoorStateChangedEventMessage>()).AsImplementedInterfaces();
//these message channels are essential and persist for the lifetime of the lobby and relay services
//they are networked so that the clients can subscribe to those messages that are published by the server
builder.RegisterComponent(new NetworkedMessageChannel<LifeStateChangedEventMessage>()).AsImplementedInterfaces();
builder.RegisterComponent(new NetworkedMessageChannel<ConnectionEventMessage>()).AsImplementedInterfaces();
#if UNITY_EDITOR || DEVELOPMENT_BUILD
builder.RegisterComponent(new NetworkedMessageChannel<CheatUsedMessage>()).AsImplementedInterfaces();
#endif
//this message channel is essential and persists for the lifetime of the lobby and relay services
builder.RegisterInstance(new MessageChannel<ReconnectMessage>()).AsImplementedInterfaces();
//buffered message channels hold the latest received message in buffer and pass to any new subscribers
builder.RegisterInstance(new BufferedMessageChannel<LobbyListFetchedMessage>()).AsImplementedInterfaces();
//all the lobby service stuff, bound here so that it persists through scene loads
builder.Register<AuthenticationServiceFacade>(Lifetime.Singleton); //a manager entity that allows us to do anonymous authentication with unity services
//LobbyServiceFacade is registered as entrypoint because it wants a callback after container is built to do it's initialization
builder.RegisterEntryPoint<LobbyServiceFacade>(Lifetime.Singleton).AsSelf();
}
private void Start()
{
m_LocalLobby = Container.Resolve<LocalLobby>();
m_LobbyServiceFacade = Container.Resolve<LobbyServiceFacade>();
var quitApplicationSub = Container.Resolve<ISubscriber<QuitApplicationMessage>>();
var subHandles = new DisposableGroup();
subHandles.Add(quitApplicationSub.Subscribe(QuitGame));
m_Subscriptions = subHandles;
Application.wantsToQuit += OnWantToQuit;
DontDestroyOnLoad(gameObject);
DontDestroyOnLoad(m_UpdateRunner.gameObject);
Application.targetFrameRate = 120;
SceneManager.LoadScene("MainMenu");
}
protected override void OnDestroy()
{
m_Subscriptions?.Dispose();
m_LobbyServiceFacade?.EndTracking();
base.OnDestroy();
}
/// <summary>
/// In builds, if we are in a lobby and try to send a Leave request on application quit, it won't go through if we're quitting on the same frame.
/// So, we need to delay just briefly to let the request happen (though we don't need to wait for the result).
/// </summary>
private IEnumerator LeaveBeforeQuit()
{
// We want to quit anyways, so if anything happens while trying to leave the Lobby, log the exception then carry on
try
{
m_LobbyServiceFacade.EndTracking();
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
yield return null;
Application.Quit();
}
private bool OnWantToQuit()
{
var canQuit = string.IsNullOrEmpty(m_LocalLobby?.LobbyID);
if (!canQuit)
{
StartCoroutine(LeaveBeforeQuit());
}
return canQuit;
}
private void QuitGame(QuitApplicationMessage msg)
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
}
}