diff --git a/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs b/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs index e42507375..718335b4c 100644 --- a/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs +++ b/Assets/Mirror/Components/NetworkTransformReliable/NetworkTransformReliable.cs @@ -57,12 +57,6 @@ void Update() void UpdateServer() { - // set dirty to trigger OnSerialize. either always, or only if changed. - // technically snapshot interpolation requires constant sending. - // however, with reliable it should be fine without constant sends. - if (!onlySyncOnChange || Changed(Construct())) - SetDirty(); - // apply buffered snapshots IF client authority // -> in server authority, server moves the object // so no need to apply any snapshots there. @@ -91,6 +85,14 @@ void UpdateServer() Apply(computed); } } + + // set dirty to trigger OnSerialize. either always, or only if changed. + // technically snapshot interpolation requires constant sending. + // however, with reliable it should be fine without constant sends. + // + // detect changes _after_ all changes were applied above. + if (!onlySyncOnChange || Changed(Construct())) + SetDirty(); } void UpdateClient() diff --git a/Assets/Mirror/Core/HostMode.cs b/Assets/Mirror/Core/HostMode.cs index 0b2d8b35d..e5bb2c056 100644 --- a/Assets/Mirror/Core/HostMode.cs +++ b/Assets/Mirror/Core/HostMode.cs @@ -1,6 +1,8 @@ // host mode related helper functions. // usually they set up both server & client. // it's cleaner to keep them in one place, instead of only in server / client. +using System; + namespace Mirror { public static class HostMode @@ -39,19 +41,8 @@ public static void InvokeOnConnected() ((LocalConnectionToServer)NetworkClient.connection).QueueConnectedEvent(); } - // calls OnStartClient for all SERVER objects in host mode once. - // client doesn't get spawn messages for those, so need to call manually. - // public because NetworkServer.ActivateHostScene was public before too. - public static void ActivateHostScene() - { - foreach (NetworkIdentity identity in NetworkServer.spawned.Values) - { - if (!identity.isClient) - { - // Debug.Log($"ActivateHostScene {identity.netId} {identity}"); - NetworkClient.CheckForStartClient(identity); - } - } - } + // DEPRECATED 2023-01-28 + [Obsolete("ActivateHostScene did nothing, since identities all had .isClient set in NetworkServer.SpawnObjects.")] + public static void ActivateHostScene() {} } } diff --git a/Assets/Mirror/Core/NetworkBehaviour.cs b/Assets/Mirror/Core/NetworkBehaviour.cs index 42613bed7..630d3af7f 100644 --- a/Assets/Mirror/Core/NetworkBehaviour.cs +++ b/Assets/Mirror/Core/NetworkBehaviour.cs @@ -598,7 +598,7 @@ public static bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdFi uint newNetId = 0; if (newGameObject != null) { - if (newGameObject.TryGetComponent(out NetworkIdentity identity)) + if (newGameObject.TryGetComponent(out NetworkIdentity identity)) { newNetId = identity.netId; if (newNetId == 0) @@ -621,7 +621,7 @@ protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gam uint newNetId = 0; if (newGameObject != null) { - if (newGameObject.TryGetComponent(out NetworkIdentity identity)) + if (newGameObject.TryGetComponent(out NetworkIdentity identity)) { newNetId = identity.netId; if (newNetId == 0) diff --git a/Assets/Mirror/Core/NetworkClient.cs b/Assets/Mirror/Core/NetworkClient.cs index 6497845d6..c94eea14e 100644 --- a/Assets/Mirror/Core/NetworkClient.cs +++ b/Assets/Mirror/Core/NetworkClient.cs @@ -383,7 +383,13 @@ internal static void OnTransportDisconnected() // Raise the event before changing ConnectState // because 'active' depends on this during shutdown - if (connection != null) OnDisconnectedEvent?.Invoke(); + // + // previously OnDisconnected was only invoked if connection != null. + // however, if DNS resolve fails in Transport.Connect(), + // OnDisconnected would never be called because 'connection' is only + // created after the Transport.Connect() call. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3365 + OnDisconnectedEvent?.Invoke(); connectState = ConnectState.Disconnected; ready = false; @@ -572,7 +578,7 @@ public static void RegisterPrefab(GameObject prefab, uint newAssetId) return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -598,7 +604,7 @@ public static void RegisterPrefab(GameObject prefab) return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -634,7 +640,7 @@ public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -681,7 +687,7 @@ public static void RegisterPrefab(GameObject prefab, uint newAssetId, SpawnHandl return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -747,7 +753,7 @@ public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnH return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -811,7 +817,7 @@ public static void UnregisterPrefab(GameObject prefab) return; } - if (!prefab.TryGetComponent(out NetworkIdentity identity)) + if (!prefab.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Could not unregister '{prefab.name}' since it contains no NetworkIdentity component"); return; @@ -1011,12 +1017,25 @@ internal static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage me identity.transform.localPosition = message.position; identity.transform.localRotation = message.rotation; identity.transform.localScale = message.scale; + + // configure flags + // the below DeserializeClient call invokes SyncVarHooks. + // flags always need to be initialized before that. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3259 identity.isOwned = message.isOwner; identity.netId = message.netId; if (message.isLocalPlayer) InternalAddPlayer(identity); + // configure isClient/isLocalPlayer flags. + // => after InternalAddPlayer. can't initialize .isLocalPlayer + // before InternalAddPlayer sets .localPlayer + // => before DeserializeClient, otherwise SyncVar hooks wouldn't + // have isClient/isLocalPlayer set yet. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3259 + InitializeIdentityFlags(identity); + // deserialize components if any payload // (Count is 0 if there were no components) if (message.payload.Count > 0) @@ -1038,9 +1057,7 @@ internal static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage me // here immediately since there won't be another OnObjectSpawnFinished. if (isSpawnFinished) { - identity.NotifyAuthority(); - CheckForStartClient(identity); - CheckForLocalPlayer(identity); + InvokeIdentityCallbacks(identity); } } @@ -1097,7 +1114,7 @@ static NetworkIdentity SpawnPrefab(SpawnMessage message) return null; } - if (!obj.TryGetComponent(out NetworkIdentity identity)) + if (!obj.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"Object Spawned by handler did not have a NetworkIdentity, Handler assetId '{message.assetId}'"); return null; @@ -1193,9 +1210,7 @@ internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _) // they are destroyed. for safety, let's double check here. if (identity != null) { - identity.NotifyAuthority(); - CheckForStartClient(identity); - CheckForLocalPlayer(identity); + BootstrapIdentity(identity); } else Debug.LogWarning("Found null entry in NetworkClient.spawned. This is unexpected. Was the NetworkIdentity not destroyed properly?"); } @@ -1238,14 +1253,12 @@ internal static void OnHostClientSpawn(SpawnMessage message) if (message.isLocalPlayer) InternalAddPlayer(identity); - identity.isOwned = message.isOwner; - identity.NotifyAuthority(); - CheckForStartClient(identity); - + // set visibility before invoking OnStartClient etc. callbacks if (aoi != null) aoi.SetHostVisibility(identity, true); - CheckForLocalPlayer(identity); + identity.isOwned = message.isOwner; + BootstrapIdentity(identity); } } @@ -1340,43 +1353,58 @@ internal static void ChangeOwner(NetworkIdentity identity, ChangeOwnerMessage me if (identity.isLocalPlayer) { localPlayer = identity; + identity.connectionToServer = connection; + identity.OnStartLocalPlayer(); } // identity's isLocalPlayer was set to false. // clear our static localPlayer IF (and only IF) it was that one before. else if (localPlayer == identity) { localPlayer = null; + // TODO set .connectionToServer to null for old local player? + // since we set it in the above 'if' case too. } - - // call OnStartLocalPlayer if it's the local player now. - CheckForLocalPlayer(identity); } - // OnStartClient used to initialize isClient / isLocalPlayer. - // it's cleaner to do this from NetworkClient. - internal static void CheckForStartClient(NetworkIdentity 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) { - // OnStartLocalPlayer is called after OnStartClient. - // but we want the flag to be set in OnStartClient already. - identity.isLocalPlayer = localPlayer == 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.OnStartClient(); + 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; } - internal static void CheckForLocalPlayer(NetworkIdentity identity) + // 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) { - if (identity == localPlayer) - { - // Set isLocalPlayer to true on this NetworkIdentity and trigger - // OnStartLocalPlayer in all scripts on the same GO - identity.connectionToServer = connection; + // invoke OnStartAuthority + identity.NotifyAuthority(); - // isLocalPlayer is already set by CheckForStartPlayer. - // however, let's simply move it out of OnStartLocalPlayer for now. - identity.isLocalPlayer = true; + // invoke OnStartClient + identity.OnStartClient(); + + // invoke OnStartLocalPlayer + if (identity.isLocalPlayer) identity.OnStartLocalPlayer(); - // Debug.Log($"NetworkClient.OnOwnerMessage player:{identity.name}"); - } + } + + // configure flags & invoke callbacks + static void BootstrapIdentity(NetworkIdentity identity) + { + InitializeIdentityFlags(identity); + InvokeIdentityCallbacks(identity); } // broadcast /////////////////////////////////////////////////////////// @@ -1473,13 +1501,10 @@ internal static void NetworkLateUpdate() // also important for syncInterval=0 components like // NetworkTransform, so they can sync on same interval as time // snapshots _but_ not every single tick. + // + // Unity 2019 doesn't have Time.timeAsDouble yet if (!Application.isPlaying || -#if !UNITY_2020_3_OR_NEWER - // Unity 2019 doesn't have Time.timeAsDouble yet AccurateInterval.Elapsed(NetworkTime.localTime, sendInterval, ref lastSendTime)) -#else - AccurateInterval.Elapsed(Time.timeAsDouble, sendInterval, ref lastSendTime)) -#endif { Broadcast(); } diff --git a/Assets/Mirror/Core/NetworkManager.cs b/Assets/Mirror/Core/NetworkManager.cs index 270bc9b55..5b536958f 100644 --- a/Assets/Mirror/Core/NetworkManager.cs +++ b/Assets/Mirror/Core/NetworkManager.cs @@ -523,7 +523,6 @@ void FinishStartHost() SetupClient(); networkAddress = "localhost"; - HostMode.ActivateHostScene(); RegisterClientMessages(); // call OnConencted needs to be called AFTER RegisterClientMessages diff --git a/Assets/Mirror/Core/NetworkServer.cs b/Assets/Mirror/Core/NetworkServer.cs index 71398ac66..8784fa2d5 100644 --- a/Assets/Mirror/Core/NetworkServer.cs +++ b/Assets/Mirror/Core/NetworkServer.cs @@ -821,7 +821,7 @@ public static void UnregisterHandler() internal static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity) { - if (!go.TryGetComponent(out identity)) + if (!go.TryGetComponent(out identity)) { Debug.LogError($"GameObject {go.name} doesn't have NetworkIdentity."); return false; @@ -898,7 +898,7 @@ public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameOb // on this playerControllerId for this connection, this will fail. public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameObject player) { - if (!player.TryGetComponent(out NetworkIdentity identity)) + if (!player.TryGetComponent(out NetworkIdentity identity)) { Debug.LogWarning($"AddPlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}"); return false; @@ -939,7 +939,7 @@ public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameOb // safely be used while changing scenes. public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false) { - if (!player.TryGetComponent(out NetworkIdentity identity)) + if (!player.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}"); return false; @@ -1288,7 +1288,7 @@ public static bool SpawnObjects() // This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object. public static void Spawn(GameObject obj, GameObject ownerPlayer) { - if (!ownerPlayer.TryGetComponent(out NetworkIdentity identity)) + if (!ownerPlayer.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError("Player object has no NetworkIdentity"); return; @@ -1351,7 +1351,7 @@ static void SpawnObject(GameObject obj, NetworkConnection ownerConnection) return; } - if (!obj.TryGetComponent(out NetworkIdentity identity)) + if (!obj.TryGetComponent(out NetworkIdentity identity)) { Debug.LogError($"SpawnObject {obj} has no NetworkIdentity. Please add a NetworkIdentity to {obj}", obj); return; @@ -1385,6 +1385,8 @@ static void SpawnObject(GameObject obj, NetworkConnection ownerConnection) if (!identity.isServer && identity.netId == 0) { // configure NetworkIdentity + // this may be called in host mode, so we need to initialize + // isLocalPlayer/isClient flags too. identity.isLocalPlayer = NetworkClient.localPlayer == identity; identity.isClient = NetworkClient.active; identity.isServer = true; diff --git a/Assets/Mirror/Core/NetworkWriterExtensions.cs b/Assets/Mirror/Core/NetworkWriterExtensions.cs index 3c91a198f..d55a7beb5 100644 --- a/Assets/Mirror/Core/NetworkWriterExtensions.cs +++ b/Assets/Mirror/Core/NetworkWriterExtensions.cs @@ -239,7 +239,7 @@ public static void WriteTransform(this NetworkWriter writer, Transform value) writer.WriteUInt(0); return; } - if (value.TryGetComponent(out NetworkIdentity identity)) + if (value.TryGetComponent(out NetworkIdentity identity)) { writer.WriteUInt(identity.netId); } @@ -259,7 +259,7 @@ public static void WriteGameObject(this NetworkWriter writer, GameObject value) } // warn if the GameObject doesn't have a NetworkIdentity, - if (!value.TryGetComponent(out NetworkIdentity identity)) + if (!value.TryGetComponent(out NetworkIdentity identity)) Debug.LogWarning($"NetworkWriter {value} has no NetworkIdentity"); // serialize the correct amount of data in any case to make sure diff --git a/Assets/Mirror/Core/NetworkWriterPool.cs b/Assets/Mirror/Core/NetworkWriterPool.cs index 1517a4830..693517fc3 100644 --- a/Assets/Mirror/Core/NetworkWriterPool.cs +++ b/Assets/Mirror/Core/NetworkWriterPool.cs @@ -1,5 +1,4 @@ // API consistent with Microsoft's ObjectPool. -using System; using System.Runtime.CompilerServices; namespace Mirror diff --git a/Assets/Mirror/Examples/AdditiveLevels/Scripts/AdditiveLevelsNetworkManager.cs b/Assets/Mirror/Examples/AdditiveLevels/Scripts/AdditiveLevelsNetworkManager.cs index 7dffafea7..51406751d 100644 --- a/Assets/Mirror/Examples/AdditiveLevels/Scripts/AdditiveLevelsNetworkManager.cs +++ b/Assets/Mirror/Examples/AdditiveLevels/Scripts/AdditiveLevelsNetworkManager.cs @@ -72,7 +72,7 @@ IEnumerator LoadAdditive(string sceneName) isInTransition = true; // This will return immediately if already faded in - // e.g. by UnloadAdditive above or by default startup state + // e.g. by UnloadAdditive or by default startup state yield return fadeInOut.FadeIn(); // host client is on server...don't load the additive scene again @@ -91,6 +91,7 @@ IEnumerator LoadAdditive(string sceneName) OnClientSceneChanged(); + // Reveal the new scene content. yield return fadeInOut.FadeOut(); } @@ -99,9 +100,10 @@ IEnumerator UnloadAdditive(string sceneName) isInTransition = true; // This will return immediately if already faded in - // e.g. by LoadAdditive above or by default startup state + // e.g. by LoadAdditive above or by default startup state. yield return fadeInOut.FadeIn(); + // host client is on server...don't unload the additive scene here. if (mode == NetworkManagerMode.ClientOnly) { yield return SceneManager.UnloadSceneAsync(sceneName); @@ -115,8 +117,8 @@ IEnumerator UnloadAdditive(string sceneName) OnClientSceneChanged(); // There is no call to FadeOut here on purpose. - // Expectation is that a LoadAdditive will follow - // that will call FadeOut after that scene loads. + // Expectation is that a LoadAdditive or full scene change + // will follow that will call FadeOut after that scene loads. } /// diff --git a/Assets/Mirror/Examples/AdditiveLevels/Scripts/Portal.cs b/Assets/Mirror/Examples/AdditiveLevels/Scripts/Portal.cs index 704f6a618..0a022e1d8 100644 --- a/Assets/Mirror/Examples/AdditiveLevels/Scripts/Portal.cs +++ b/Assets/Mirror/Examples/AdditiveLevels/Scripts/Portal.cs @@ -46,7 +46,7 @@ void OnTriggerEnter(Collider other) //Debug.Log($"{System.DateTime.Now:HH:mm:ss:fff} Portal::OnTriggerEnter {gameObject.name} in {gameObject.scene.name}"); // applies to host client on server and remote clients - if (other.TryGetComponent(out PlayerController playerController)) + if (other.TryGetComponent(out PlayerController playerController)) playerController.enabled = false; if (isServer) @@ -56,7 +56,7 @@ void OnTriggerEnter(Collider other) [ServerCallback] IEnumerator SendPlayerToNewScene(GameObject player) { - if (player.TryGetComponent(out NetworkIdentity identity)) + if (player.TryGetComponent(out NetworkIdentity identity)) { NetworkConnectionToClient conn = identity.connectionToClient; if (conn == null) yield break; @@ -83,7 +83,7 @@ IEnumerator SendPlayerToNewScene(GameObject player) NetworkServer.AddPlayerForConnection(conn, player); // host client would have been disabled by OnTriggerEnter above - if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent(out PlayerController playerController)) + if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent(out PlayerController playerController)) playerController.enabled = true; } } diff --git a/Assets/Mirror/Examples/Tanks/Scripts/Tank.cs b/Assets/Mirror/Examples/Tanks/Scripts/Tank.cs index dc8bfe5b9..80ef0cd5f 100644 --- a/Assets/Mirror/Examples/Tanks/Scripts/Tank.cs +++ b/Assets/Mirror/Examples/Tanks/Scripts/Tank.cs @@ -27,6 +27,9 @@ void Update() // always update health bar. // (SyncVar hook would only update on clients, not on server) healthBar.text = new string('-', health); + + // take input from focused window only + if(!Application.isFocused) return; // movement for local player if (isLocalPlayer) diff --git a/Assets/Mirror/Tests/Editor/NetworkReaderWriterTest.cs b/Assets/Mirror/Tests/Editor/NetworkReaderWriterTest.cs index 32fa7838f..f9f37356a 100644 --- a/Assets/Mirror/Tests/Editor/NetworkReaderWriterTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkReaderWriterTest.cs @@ -21,7 +21,7 @@ public void TestIntReaderNotNull() public void TestAccessingCustomWriterAndReader() { NetworkWriter writer = new NetworkWriter(); - writer.Write(3); + writer.Write(3); NetworkReader reader = new NetworkReader(writer.ToArray()); int copy = reader.Read(); diff --git a/Assets/Mirror/Tests/Editor/NetworkServerTest.cs b/Assets/Mirror/Tests/Editor/NetworkServerTest.cs index 5642f6611..0f6d5b90f 100644 --- a/Assets/Mirror/Tests/Editor/NetworkServerTest.cs +++ b/Assets/Mirror/Tests/Editor/NetworkServerTest.cs @@ -839,28 +839,6 @@ public void SendCommand_RequiresAuthority() Assert.That(comp.called, Is.EqualTo(0)); } - [Test] - public void ActivateHostSceneCallsOnStartClient() - { - // listen & connect - NetworkServer.Listen(1); - ConnectClientBlockingAuthenticatedAndReady(out _); - - // spawn identity with a networkbehaviour. - // (needs to be in .spawned for ActivateHostScene) - CreateNetworkedAndSpawn( - out _, out NetworkIdentity serverIdentity, out OnStartClientTestNetworkBehaviour serverComp, - out _, out _, out _); - - // ActivateHostScene calls OnStartClient for spawned objects where - // isClient is still false. set it to false first. - serverIdentity.isClient = false; - HostMode.ActivateHostScene(); - - // was OnStartClient called for all .spawned networkidentities? - Assert.That(serverComp.called, Is.EqualTo(1)); - } - [Test] public void SendToAll() { diff --git a/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt index e0b7d483a..b0f1290cd 100755 --- a/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt +++ b/Assets/Mirror/Transports/KCP/kcp2k/VERSION.txt @@ -1,3 +1,11 @@ +V1.29 [2023-01-28] +- fix: KcpServer.CreateServerSocket now handles NotSupportedException when setting DualMode + https://github.com/MirrorNetworking/Mirror/issues/3358 + +V1.28 [2023-01-28] +- fix: KcpClient.Connect now resolves hostname before creating peer + https://github.com/MirrorNetworking/Mirror/issues/3361 + V1.27 [2023-01-08] - KcpClient.Connect: invoke own events directly instead of going through peer, which calls our own events anyway diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs index 48d976f03..46ee0e411 100644 --- a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpClient.cs @@ -60,6 +60,16 @@ public void Connect(string address, ushort port, KcpConfig config) return; } + // resolve host name before creating peer. + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3361 + if (!Common.ResolveHostname(address, out IPAddress[] addresses)) + { + // pass error to user callback. no need to log it manually. + OnError(ErrorCode.DnsResolve, $"Failed to resolve host: {address}"); + OnDisconnected(); + return; + } + // create fresh peer for each new session peer = new KcpPeer(RawSend, OnAuthenticatedWrap, OnData, OnDisconnectedWrap, OnError, config); @@ -83,15 +93,6 @@ void OnDisconnectedWrap() Log.Info($"KcpClient: connect to {address}:{port}"); - // try resolve host name - if (!Common.ResolveHostname(address, out IPAddress[] addresses)) - { - // pass error to user callback. no need to log it manually. - OnError(ErrorCode.DnsResolve, $"Failed to resolve host: {address}"); - OnDisconnected(); - return; - } - // create socket remoteEndPoint = new IPEndPoint(addresses[0], port); socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); diff --git a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs index f960d6826..fd2056896 100644 --- a/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs +++ b/Assets/Mirror/Transports/KCP/kcp2k/highlevel/KcpServer.cs @@ -67,7 +67,18 @@ static Socket CreateServerSocket(bool DualMode, ushort port) { // IPv6 socket with DualMode @ "::" : port Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); - socket.DualMode = true; + // settings DualMode may throw: + // https://learn.microsoft.com/en-us/dotnet/api/System.Net.Sockets.Socket.DualMode?view=net-7.0 + // attempt it, otherwise log but continue + // fixes: https://github.com/MirrorNetworking/Mirror/issues/3358 + try + { + socket.DualMode = true; + } + catch (NotSupportedException e) + { + Log.Warning($"Failed to set Dual Mode, continuing with IPv6 without Dual Mode. Error: {e}"); + } socket.Bind(new IPEndPoint(IPAddress.IPv6Any, port)); return socket; } diff --git a/Assets/ScriptTemplates/53-Mirror__Custom Interest Management-CustomInterestManagement.cs.txt b/Assets/ScriptTemplates/53-Mirror__Custom Interest Management-CustomInterestManagement.cs.txt index 37df416d6..a47caf1bc 100644 --- a/Assets/ScriptTemplates/53-Mirror__Custom Interest Management-CustomInterestManagement.cs.txt +++ b/Assets/ScriptTemplates/53-Mirror__Custom Interest Management-CustomInterestManagement.cs.txt @@ -32,9 +32,8 @@ public class #SCRIPTNAME# : InterestManagement /// /// Object to be observed (or not) by clients /// cached hashset to put the result into - /// true if being rebuilt for the first time [ServerCallback] - public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers, bool initialize) + public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers) { // Default behaviour of making the identity object visible to all clients. // Replace this code with your own logic as appropriate. diff --git a/Packages/manifest.json b/Packages/manifest.json index 8c553ff86..67c7303a6 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -2,8 +2,8 @@ "dependencies": { "com.unity.2d.sprite": "1.0.0", "com.unity.2d.tilemap": "1.0.0", - "com.unity.ide.rider": "3.0.16", - "com.unity.ide.visualstudio": "2.0.16", + "com.unity.ide.rider": "3.0.18", + "com.unity.ide.visualstudio": "2.0.17", "com.unity.ide.vscode": "1.2.5", "com.unity.test-framework": "1.1.31", "com.unity.testtools.codecoverage": "1.2.2", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index e0fb4d319..95c67e93f 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -20,7 +20,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "3.0.16", + "version": "3.0.18", "depth": 0, "source": "registry", "dependencies": { @@ -29,7 +29,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.visualstudio": { - "version": "2.0.16", + "version": "2.0.17", "depth": 0, "source": "registry", "dependencies": { diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index eabd63377..1a9f85a68 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2021.3.15f1 -m_EditorVersionWithRevision: 2021.3.15f1 (e8e88683f834) +m_EditorVersion: 2021.3.17f1 +m_EditorVersionWithRevision: 2021.3.17f1 (3e8111cac19d)