Skip to content

Commit 09e29c6

Browse files
committed
bumping to pre.10
Fixing connection approval with new API updating comments to better reflect current state
1 parent 80b1d14 commit 09e29c6

File tree

2 files changed

+41
-38
lines changed

2 files changed

+41
-38
lines changed

Assets/Scripts/Gameplay/ConnectionManagement/ServerGameNetPortal.cs

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,27 @@ public bool AreAllClientsInServerScene()
161161
}
162162

163163
/// <summary>
164-
/// This logic plugs into the "ConnectionApprovalCallback" exposed by Netcode.NetworkManager, and is run every time a client connects to us.
165-
/// See ClientGameNetPortal.StartClient for the complementary logic that runs when the client starts its connection.
164+
/// This logic plugs into the "ConnectionApprovalResponse" exposed by Netcode.NetworkManager. It is run every time a client connects to us.
165+
/// The complementary logic that runs when the client starts its connection can be found in ClientGameNetPortal.StartClient.
166166
/// </summary>
167167
/// <remarks>
168-
/// Since our game doesn't have to interact with some third party authentication service to validate the identity of the new connection, our ApprovalCheck
169-
/// method is simple, and runs synchronously, invoking "callback" to signal approval at the end of the method. Netcode currently doesn't support the ability
170-
/// to send back more than a "true/false", which means we have to work a little harder to provide a useful error return to the client. To do that, we invoke a
171-
/// custom message in the same channel that Netcode uses for its connection callback. Since the delivery is NetworkDelivery.ReliableSequenced, we can be
172-
/// confident that our login result message will execute before any disconnect message.
168+
/// 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
169+
/// also send custom messages to connecting users before they receive their connection result (this is useful to set status messages client side
170+
/// when connection is refused, for example).
173171
/// </remarks>
174-
/// <param name="connectionData">binary data passed into StartClient. In our case this is the client's GUID, which is a unique identifier for their install of the game that persists across app restarts. </param>
175-
/// <param name="clientId">This is the clientId that Netcode assigned us on login. It does not persist across multiple logins from the same client. </param>
176-
/// <param name="connectionApprovedCallback">The delegate we must invoke to signal that the connection was approved or not. </param>
177-
void ApprovalCheck(byte[] connectionData, ulong clientId, NetworkManager.ConnectionApprovedDelegate connectionApprovedCallback)
172+
///
173+
/// <param name="request"> The initial request contains, among other things, binary data passed into StartClient. In our case, this is the client's GUID,
174+
/// which is a unique identifier for their install of the game that persists across app restarts.
175+
/// <param name="response"> Our response to the approval process. In case of connection refusal with custom return message, we delay using the Pending field.
176+
void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
178177
{
178+
var connectionData = request.Payload;
179+
var clientId = request.ClientNetworkId;
179180
if (connectionData.Length > k_MaxConnectPayload)
180181
{
181182
// If connectionData too high, deny immediately to avoid wasting time on the server. This is intended as
182183
// a bit of light protection against DOS attacks that rely on sending silly big buffers of garbage.
183-
connectionApprovedCallback(false, 0, false, null, null);
184+
response.Approved = false;
184185
return;
185186
}
186187

@@ -190,13 +191,14 @@ void ApprovalCheck(byte[] connectionData, ulong clientId, NetworkManager.Connect
190191
SessionManager<SessionPlayerData>.Instance.SetupConnectingPlayerSessionData(clientId, m_Portal.GetPlayerId(),
191192
new SessionPlayerData(clientId, m_Portal.PlayerName, m_Portal.AvatarRegistry.GetRandomAvatar().Guid.ToNetworkGuid(), 0, true));
192193

193-
connectionApprovedCallback(true, null, true, null, null);
194+
response.Approved = true;
195+
response.CreatePlayerObject = true;
194196
return;
195197
}
196198

197199
var payload = System.Text.Encoding.UTF8.GetString(connectionData);
198200
var connectionPayload = JsonUtility.FromJson<ConnectionPayload>(payload); // https://docs.unity3d.com/2020.2/Documentation/Manual/JSONSerialization.html
199-
var gameReturnStatus = GetConnectStatus(connectionPayload);
201+
var gameReturnStatus = CanClientConnect(connectionPayload);
200202

201203
if (gameReturnStatus == ConnectStatus.Success)
202204
{
@@ -207,28 +209,36 @@ void ApprovalCheck(byte[] connectionData, ulong clientId, NetworkManager.Connect
207209
//Populate our client scene map
208210
m_ClientSceneMap[clientId] = connectionPayload.clientScene;
209211

210-
// connection approval will create a player object for you
211-
connectionApprovedCallback(true, null, true, Vector3.zero, Quaternion.identity);
212-
213212
m_ConnectionEventPublisher.Publish(new ConnectionEventMessage() { ConnectStatus = ConnectStatus.Success, PlayerName = SessionManager<SessionPlayerData>.Instance.GetPlayerData(clientId)?.PlayerName });
213+
response.Approved = true;
214+
response.CreatePlayerObject = true;
215+
response.Position = Vector3.zero;
216+
response.Rotation = Quaternion.identity;
217+
return;
214218
}
215-
else
219+
220+
// In order for clients to not just get disconnected with no feedback, the server needs to tell the client why it disconnected it.
221+
// This could happen after an auth check on a service or because of gameplay reasons (server full, wrong build version, etc)
222+
// Since network objects haven't synced yet (still in the approval process), we need to send a custom message to clients, wait for
223+
// UTP to update a frame and flush that message, then give our response to NetworkManager's connection approval process, with a denied approval.
224+
IEnumerator WaitToDenyApproval(NetworkManager.ConnectionApprovalResponse response)
216225
{
217-
//TODO-FIXME:Netcode Issue #796. We should be able to send a reason and disconnect without a coroutine delay.
218-
//TODO:Netcode: In the future we expect Netcode to allow us to return more information as part of the
219-
//approval callback, so that we can provide more context on a reject. In the meantime we must provide
220-
//the extra information ourselves, and then wait a short time before manually close down the connection.
226+
response.Pending = true; // give some time for server to send connection status message to clients
227+
response.Approved = false;
221228
SendServerToClientConnectResult(clientId, gameReturnStatus);
222229
SendServerToClientSetDisconnectReason(clientId, gameReturnStatus);
223-
StartCoroutine(WaitToDenyApproval(connectionApprovedCallback));
224-
if (m_LobbyServiceFacade.CurrentUnityLobby != null)
225-
{
226-
m_LobbyServiceFacade.RemovePlayerFromLobbyAsync(connectionPayload.playerId, m_LobbyServiceFacade.CurrentUnityLobby.Id);
227-
}
230+
yield return null; // wait a frame so UTP can flush it's messages on next update
231+
response.Pending = false; // connection approval process can be finished.
232+
}
233+
234+
StartCoroutine(WaitToDenyApproval(response));
235+
if (m_LobbyServiceFacade.CurrentUnityLobby != null)
236+
{
237+
m_LobbyServiceFacade.RemovePlayerFromLobbyAsync(connectionPayload.playerId, m_LobbyServiceFacade.CurrentUnityLobby.Id);
228238
}
229239
}
230240

231-
ConnectStatus GetConnectStatus(ConnectionPayload connectionPayload)
241+
ConnectStatus CanClientConnect(ConnectionPayload connectionPayload)
232242
{
233243
if (m_Portal.NetManager.ConnectedClientsIds.Count >= CharSelectData.k_MaxLobbyPlayers)
234244
{
@@ -240,14 +250,7 @@ ConnectStatus GetConnectStatus(ConnectionPayload connectionPayload)
240250
return ConnectStatus.IncompatibleBuildType;
241251
}
242252

243-
return SessionManager<SessionPlayerData>.Instance.IsDuplicateConnection(connectionPayload.playerId) ?
244-
ConnectStatus.LoggedInAgain : ConnectStatus.Success;
245-
}
246-
247-
static IEnumerator WaitToDenyApproval(NetworkManager.ConnectionApprovedDelegate connectionApprovedCallback)
248-
{
249-
yield return new WaitForSeconds(0.5f);
250-
connectionApprovedCallback(false, 0, false, null, null);
253+
return SessionManager<SessionPlayerData>.Instance.IsDuplicateConnection(connectionPayload.playerId) ? ConnectStatus.LoggedInAgain : ConnectStatus.Success;
251254
}
252255

253256
IEnumerator WaitToShutdown()
@@ -310,4 +313,4 @@ void ServerStartedHandler()
310313
}
311314

312315
}
313-
}
316+
}

Packages/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"com.unity.ide.vscode": "1.2.5",
1010
"com.unity.learn.iet-framework": "2.2.1",
1111
"com.unity.memoryprofiler": "0.5.0-preview.1",
12-
"com.unity.netcode.gameobjects": "1.0.0-pre.9",
12+
"com.unity.netcode.gameobjects": "1.0.0-pre.10",
1313
"com.unity.multiplayer.tools": "1.0.0-pre.7",
1414
"com.unity.postprocessing": "3.2.1",
1515
"com.unity.render-pipelines.universal": "12.1.6",

0 commit comments

Comments
 (0)