diff --git a/Assets/Mirror/Core/NetworkClient.cs b/Assets/Mirror/Core/NetworkClient.cs index cd702409b..2aff2d47b 100644 --- a/Assets/Mirror/Core/NetworkClient.cs +++ b/Assets/Mirror/Core/NetworkClient.cs @@ -1381,6 +1381,47 @@ internal static void OnHostClientSpawn(SpawnMessage message) } } + // configure flags & invoke callbacks + static void BootstrapIdentity(NetworkIdentity identity) + { + InitializeIdentityFlags(identity); + InvokeIdentityCallbacks(identity); + } + + // set up NetworkIdentity flags on the client. + // needs to be separate from invoking callbacks. + // cleaner, and some places need to set flags first. + static void InitializeIdentityFlags(NetworkIdentity identity) + { + // initialize flags before invoking callbacks. + // this way isClient/isLocalPlayer is correct during callbacks. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3362 + identity.isClient = true; + identity.isLocalPlayer = localPlayer == identity; + + // .connectionToServer is only available for local players. + // set it here, before invoking any callbacks. + // this way it's available in _all_ callbacks. + if (identity.isLocalPlayer) + identity.connectionToServer = connection; + } + + // invoke NetworkIdentity callbacks on the client. + // needs to be separate from configuring flags. + // cleaner, and some places need to set flags first. + static void InvokeIdentityCallbacks(NetworkIdentity identity) + { + // invoke OnStartClient + identity.OnStartClient(); + + // invoke OnStartAuthority + identity.NotifyAuthority(); + + // invoke OnStartLocalPlayer + if (identity.isLocalPlayer) + identity.OnStartLocalPlayer(); + } + // client-only mode callbacks ////////////////////////////////////////// static void OnEntityStateMessage(EntityStateMessage message) { @@ -1470,102 +1511,6 @@ internal static void ChangeOwner(NetworkIdentity identity, ChangeOwnerMessage me } } - // set up NetworkIdentity flags on the client. - // needs to be separate from invoking callbacks. - // cleaner, and some places need to set flags first. - static void InitializeIdentityFlags(NetworkIdentity identity) - { - // initialize flags before invoking callbacks. - // this way isClient/isLocalPlayer is correct during callbacks. - // fixes: https://github.com/MirrorNetworking/Mirror/issues/3362 - identity.isClient = true; - identity.isLocalPlayer = localPlayer == identity; - - // .connectionToServer is only available for local players. - // set it here, before invoking any callbacks. - // this way it's available in _all_ callbacks. - if (identity.isLocalPlayer) - identity.connectionToServer = connection; - } - - // invoke NetworkIdentity callbacks on the client. - // needs to be separate from configuring flags. - // cleaner, and some places need to set flags first. - static void InvokeIdentityCallbacks(NetworkIdentity identity) - { - // invoke OnStartClient - identity.OnStartClient(); - - // invoke OnStartAuthority - identity.NotifyAuthority(); - - // invoke OnStartLocalPlayer - if (identity.isLocalPlayer) - identity.OnStartLocalPlayer(); - } - - // configure flags & invoke callbacks - static void BootstrapIdentity(NetworkIdentity identity) - { - InitializeIdentityFlags(identity); - InvokeIdentityCallbacks(identity); - } - - // broadcast /////////////////////////////////////////////////////////// - // NetworkServer has BroadcastToConnection. - // NetworkClient has BroadcastToServer. - static void BroadcastToServer() - { - // for each entity that the client owns - foreach (NetworkIdentity identity in connection.owned) - { - // make sure it's not null or destroyed. - // (which can happen if someone uses - // GameObject.Destroy instead of - // NetworkServer.Destroy) - if (identity != null) - { - using (NetworkWriterPooled writer = NetworkWriterPool.Get()) - { - // get serialization for this entity viewed by this connection - // (if anything was serialized this time) - identity.SerializeClient(writer); - if (writer.Position > 0) - { - // send state update message - EntityStateMessage message = new EntityStateMessage - { - netId = identity.netId, - payload = writer.ToArraySegment() - }; - Send(message); - } - } - } - // spawned list should have no null entries because we - // always call Remove in OnObjectDestroy everywhere. - // if it does have null then we missed something. - else Debug.LogWarning($"Found 'null' entry in owned list for client. This is unexpected behaviour."); - } - } - - // make sure Broadcast() is only called every sendInterval. - // calling it every update() would require too much bandwidth. - static void Broadcast() - { - // joined the world yet? - if (!connection.isReady) return; - - // nothing to do in host mode. server already knows the state. - if (NetworkServer.active) return; - - // send time snapshot every sendInterval. - Send(new TimeSnapshotMessage(), Channels.Unreliable); - - // broadcast client state to server - BroadcastToServer(); - } - // update ////////////////////////////////////////////////////////////// // NetworkEarlyUpdate called before any Update/FixedUpdate // (we add this to the UnityEngine in NetworkLoop) @@ -1665,6 +1610,61 @@ void UpdateConnectionQuality() Transport.active.ClientLateUpdate(); } + // broadcast /////////////////////////////////////////////////////////// + // make sure Broadcast() is only called every sendInterval. + // calling it every update() would require too much bandwidth. + static void Broadcast() + { + // joined the world yet? + if (!connection.isReady) return; + + // nothing to do in host mode. server already knows the state. + if (NetworkServer.active) return; + + // send time snapshot every sendInterval. + Send(new TimeSnapshotMessage(), Channels.Unreliable); + + // broadcast client state to server + BroadcastToServer(); + } + + // NetworkServer has BroadcastToConnection. + // NetworkClient has BroadcastToServer. + static void BroadcastToServer() + { + // for each entity that the client owns + foreach (NetworkIdentity identity in connection.owned) + { + // make sure it's not null or destroyed. + // (which can happen if someone uses + // GameObject.Destroy instead of + // NetworkServer.Destroy) + if (identity != null) + { + using (NetworkWriterPooled writer = NetworkWriterPool.Get()) + { + // get serialization for this entity viewed by this connection + // (if anything was serialized this time) + identity.SerializeClient(writer); + if (writer.Position > 0) + { + // send state update message + EntityStateMessage message = new EntityStateMessage + { + netId = identity.netId, + payload = writer.ToArraySegment() + }; + Send(message); + } + } + } + // spawned list should have no null entries because we + // always call Remove in OnObjectDestroy everywhere. + // if it does have null then we missed something. + else Debug.LogWarning($"Found 'null' entry in owned list for client. This is unexpected behaviour."); + } + } + // destroy ///////////////////////////////////////////////////////////// /// Destroys all networked objects on the client. // Note: NetworkServer.CleanupNetworkIdentities does the same on server.