@@ -13,154 +13,31 @@ namespace Unity.Multiplayer.Samples.BossRoom
13
13
/// Connection state corresponding to a listening host. Handles incoming client connections. When shutting down or
14
14
/// being timed out, transitions to the Offline state.
15
15
/// </summary>
16
- class HostingState : ConnectionState
16
+ class HostingState : ServerListeningState
17
17
{
18
- [ Inject ]
19
- LobbyServiceFacade m_LobbyServiceFacade ;
20
- [ Inject ]
21
- IPublisher < ConnectionEventMessage > m_ConnectionEventPublisher ;
22
-
23
- // used in ApprovalCheck. This is intended as a bit of light protection against DOS attacks that rely on sending silly big buffers of garbage.
24
- const int k_MaxConnectPayload = 1024 ;
25
-
26
- public override void Enter ( )
27
- {
28
- var gameState = UnityEngine . Object . Instantiate ( m_ConnectionManager . GameState ) ;
29
-
30
- gameState . Spawn ( ) ;
31
-
32
- SceneLoaderWrapper . Instance . AddOnSceneEventCallback ( ) ;
33
-
34
- //The "BossRoom" server always advances to CharSelect immediately on start. Different games
35
- //may do this differently.
36
- SceneLoaderWrapper . Instance . LoadScene ( "CharSelect" , useNetworkSceneManager : true ) ;
37
- }
38
-
39
- public override void Exit ( )
40
- {
41
- SessionManager < SessionPlayerData > . Instance . OnServerEnded ( ) ;
42
- }
43
-
44
- public override void OnClientConnected ( ulong clientId )
45
- {
46
- m_ConnectionEventPublisher . Publish ( new ConnectionEventMessage ( ) { ConnectStatus = ConnectStatus . Success , PlayerName = SessionManager < SessionPlayerData > . Instance . GetPlayerData ( clientId ) ? . PlayerName } ) ;
47
- }
48
-
49
- public override void OnClientDisconnect ( ulong clientId )
50
- {
51
- if ( clientId == m_ConnectionManager . NetworkManager . LocalClientId )
52
- {
53
- m_ConnectionManager . ChangeState ( m_ConnectionManager . m_Offline ) ;
54
- }
55
- else
56
- {
57
- var playerId = SessionManager < SessionPlayerData > . Instance . GetPlayerId ( clientId ) ;
58
- if ( playerId != null )
59
- {
60
- if ( m_LobbyServiceFacade . CurrentUnityLobby != null )
61
- {
62
- m_LobbyServiceFacade . RemovePlayerFromLobbyAsync ( playerId , m_LobbyServiceFacade . CurrentUnityLobby . Id ) ;
63
- }
64
-
65
- var sessionData = SessionManager < SessionPlayerData > . Instance . GetPlayerData ( playerId ) ;
66
- if ( sessionData . HasValue )
67
- {
68
- m_ConnectionEventPublisher . Publish ( new ConnectionEventMessage ( ) { ConnectStatus = ConnectStatus . GenericDisconnect , PlayerName = sessionData . Value . PlayerName } ) ;
69
- }
70
- SessionManager < SessionPlayerData > . Instance . DisconnectClient ( clientId ) ;
71
- }
72
- }
73
- }
74
-
75
18
public override void OnUserRequestedShutdown ( )
76
19
{
77
20
ConnectionManager . SendServerToAllClientsSetDisconnectReason ( ConnectStatus . HostEndedSession ) ;
78
21
// Wait before shutting down to make sure clients receive that message before they are disconnected
79
22
m_ConnectionManager . StartCoroutine ( WaitToShutdown ( ) ) ;
80
23
}
81
24
82
- /// <summary>
83
- /// This logic plugs into the "ConnectionApprovalResponse" exposed by Netcode.NetworkManager. It is run every time a client connects to us.
84
- /// The complementary logic that runs when the client starts its connection can be found in ClientConnectingState.
85
- /// </summary>
86
- /// <remarks>
87
- /// Multiple things can be done here, some asynchronously. For example, it could authenticate your user against an auth service like UGS' auth service. It can
88
- /// also send custom messages to connecting users before they receive their connection result (this is useful to set status messages client side
89
- /// when connection is refused, for example).
90
- /// </remarks>
91
- /// <param name="request"> The initial request contains, among other things, binary data passed into StartClient. In our case, this is the client's GUID,
92
- /// which is a unique identifier for their install of the game that persists across app restarts.
93
- /// <param name="response"> Our response to the approval process. In case of connection refusal with custom return message, we delay using the Pending field.
94
- public override void ApprovalCheck ( NetworkManager . ConnectionApprovalRequest request , NetworkManager . ConnectionApprovalResponse response )
25
+ IEnumerator WaitToShutdown ( )
95
26
{
96
- var connectionData = request . Payload ;
97
- var clientId = request . ClientNetworkId ;
98
- if ( connectionData . Length > k_MaxConnectPayload )
99
- {
100
- // If connectionData too high, deny immediately to avoid wasting time on the server. This is intended as
101
- // a bit of light protection against DOS attacks that rely on sending silly big buffers of garbage.
102
- response . Approved = false ;
103
- return ;
104
- }
105
-
106
- var payload = System . Text . Encoding . UTF8 . GetString ( connectionData ) ;
107
- var connectionPayload = JsonUtility . FromJson < ConnectionPayload > ( payload ) ; // https://docs.unity3d.com/2020.2/Documentation/Manual/JSONSerialization.html
108
- var gameReturnStatus = GetConnectStatus ( connectionPayload ) ;
109
-
110
- if ( gameReturnStatus == ConnectStatus . Success )
111
- {
112
- SessionManager < SessionPlayerData > . Instance . SetupConnectingPlayerSessionData ( clientId , connectionPayload . playerId ,
113
- new SessionPlayerData ( clientId , connectionPayload . playerName , new NetworkGuid ( ) , 0 , true ) ) ;
114
-
115
- // connection approval will create a player object for you
116
- response . Approved = true ;
117
- response . CreatePlayerObject = true ;
118
- response . Position = Vector3 . zero ;
119
- response . Rotation = Quaternion . identity ;
120
- return ;
121
- }
122
-
123
- // In order for clients to not just get disconnected with no feedback, the server needs to tell the client why it disconnected it.
124
- // This could happen after an auth check on a service or because of gameplay reasons (server full, wrong build version, etc)
125
- // Since network objects haven't synced yet (still in the approval process), we need to send a custom message to clients, wait for
126
- // UTP to update a frame and flush that message, then give our response to NetworkManager's connection approval process, with a denied approval.
127
- IEnumerator WaitToDenyApproval ( )
128
- {
129
- response . Pending = true ; // give some time for server to send connection status message to clients
130
- response . Approved = false ;
131
- ConnectionManager . SendServerToClientSetDisconnectReason ( clientId , gameReturnStatus ) ;
132
- yield return null ; // wait a frame so UTP can flush it's messages on next update
133
- response . Pending = false ; // connection approval process can be finished.
134
- }
135
-
136
- ConnectionManager . SendServerToClientSetDisconnectReason ( clientId , gameReturnStatus ) ;
137
- m_ConnectionManager . StartCoroutine ( WaitToDenyApproval ( ) ) ;
138
- if ( m_LobbyServiceFacade . CurrentUnityLobby != null )
139
- {
140
- m_LobbyServiceFacade . RemovePlayerFromLobbyAsync ( connectionPayload . playerId , m_LobbyServiceFacade . CurrentUnityLobby . Id ) ;
141
- }
27
+ yield return null ;
28
+ m_ConnectionManager . ChangeState ( m_ConnectionManager . m_Offline ) ;
142
29
}
143
30
144
- ConnectStatus GetConnectStatus ( ConnectionPayload connectionPayload )
31
+ public override void OnClientDisconnect ( ulong clientId )
145
32
{
146
- if ( m_ConnectionManager . NetworkManager . ConnectedClientsIds . Count >= m_ConnectionManager . MaxConnectedPlayers )
33
+ if ( clientId == m_ConnectionManager . NetworkManager . LocalClientId )
147
34
{
148
- return ConnectStatus . ServerFull ;
35
+ m_ConnectionManager . ChangeState ( m_ConnectionManager . m_Offline ) ;
149
36
}
150
-
151
- if ( connectionPayload . isDebug != Debug . isDebugBuild )
37
+ else
152
38
{
153
- return ConnectStatus . IncompatibleBuildType ;
39
+ base . OnClientDisconnect ( clientId ) ;
154
40
}
155
-
156
- return SessionManager < SessionPlayerData > . Instance . IsDuplicateConnection ( connectionPayload . playerId ) ?
157
- ConnectStatus . LoggedInAgain : ConnectStatus . Success ;
158
- }
159
-
160
- IEnumerator WaitToShutdown ( )
161
- {
162
- yield return null ;
163
- m_ConnectionManager . ChangeState ( m_ConnectionManager . m_Offline ) ;
164
41
}
165
42
}
166
43
}
0 commit comments