mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
Merged master
This commit is contained in:
commit
d6e81dc687
@ -57,12 +57,6 @@ void Update()
|
|||||||
|
|
||||||
void UpdateServer()
|
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
|
// apply buffered snapshots IF client authority
|
||||||
// -> in server authority, server moves the object
|
// -> in server authority, server moves the object
|
||||||
// so no need to apply any snapshots there.
|
// so no need to apply any snapshots there.
|
||||||
@ -91,6 +85,14 @@ void UpdateServer()
|
|||||||
Apply(computed);
|
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()
|
void UpdateClient()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// host mode related helper functions.
|
// host mode related helper functions.
|
||||||
// usually they set up both server & client.
|
// usually they set up both server & client.
|
||||||
// it's cleaner to keep them in one place, instead of only in server / client.
|
// it's cleaner to keep them in one place, instead of only in server / client.
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Mirror
|
namespace Mirror
|
||||||
{
|
{
|
||||||
public static class HostMode
|
public static class HostMode
|
||||||
@ -39,19 +41,8 @@ public static void InvokeOnConnected()
|
|||||||
((LocalConnectionToServer)NetworkClient.connection).QueueConnectedEvent();
|
((LocalConnectionToServer)NetworkClient.connection).QueueConnectedEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calls OnStartClient for all SERVER objects in host mode once.
|
// DEPRECATED 2023-01-28
|
||||||
// client doesn't get spawn messages for those, so need to call manually.
|
[Obsolete("ActivateHostScene did nothing, since identities all had .isClient set in NetworkServer.SpawnObjects.")]
|
||||||
// public because NetworkServer.ActivateHostScene was public before too.
|
public static void ActivateHostScene() {}
|
||||||
public static void ActivateHostScene()
|
|
||||||
{
|
|
||||||
foreach (NetworkIdentity identity in NetworkServer.spawned.Values)
|
|
||||||
{
|
|
||||||
if (!identity.isClient)
|
|
||||||
{
|
|
||||||
// Debug.Log($"ActivateHostScene {identity.netId} {identity}");
|
|
||||||
NetworkClient.CheckForStartClient(identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,7 @@ public static bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdFi
|
|||||||
uint newNetId = 0;
|
uint newNetId = 0;
|
||||||
if (newGameObject != null)
|
if (newGameObject != null)
|
||||||
{
|
{
|
||||||
if (newGameObject.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (newGameObject.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
newNetId = identity.netId;
|
newNetId = identity.netId;
|
||||||
if (newNetId == 0)
|
if (newNetId == 0)
|
||||||
@ -621,7 +621,7 @@ protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gam
|
|||||||
uint newNetId = 0;
|
uint newNetId = 0;
|
||||||
if (newGameObject != null)
|
if (newGameObject != null)
|
||||||
{
|
{
|
||||||
if (newGameObject.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (newGameObject.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
newNetId = identity.netId;
|
newNetId = identity.netId;
|
||||||
if (newNetId == 0)
|
if (newNetId == 0)
|
||||||
|
@ -383,7 +383,13 @@ internal static void OnTransportDisconnected()
|
|||||||
|
|
||||||
// Raise the event before changing ConnectState
|
// Raise the event before changing ConnectState
|
||||||
// because 'active' depends on this during shutdown
|
// 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;
|
connectState = ConnectState.Disconnected;
|
||||||
ready = false;
|
ready = false;
|
||||||
@ -572,7 +578,7 @@ public static void RegisterPrefab(GameObject prefab, uint newAssetId)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -598,7 +604,7 @@ public static void RegisterPrefab(GameObject prefab)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -634,7 +640,7 @@ public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -681,7 +687,7 @@ public static void RegisterPrefab(GameObject prefab, uint newAssetId, SpawnHandl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -747,7 +753,7 @@ public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnH
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not register handler for '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -811,7 +817,7 @@ public static void UnregisterPrefab(GameObject prefab)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prefab.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!prefab.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not unregister '{prefab.name}' since it contains no NetworkIdentity component");
|
Debug.LogError($"Could not unregister '{prefab.name}' since it contains no NetworkIdentity component");
|
||||||
return;
|
return;
|
||||||
@ -1011,12 +1017,25 @@ internal static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage me
|
|||||||
identity.transform.localPosition = message.position;
|
identity.transform.localPosition = message.position;
|
||||||
identity.transform.localRotation = message.rotation;
|
identity.transform.localRotation = message.rotation;
|
||||||
identity.transform.localScale = message.scale;
|
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.isOwned = message.isOwner;
|
||||||
identity.netId = message.netId;
|
identity.netId = message.netId;
|
||||||
|
|
||||||
if (message.isLocalPlayer)
|
if (message.isLocalPlayer)
|
||||||
InternalAddPlayer(identity);
|
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
|
// deserialize components if any payload
|
||||||
// (Count is 0 if there were no components)
|
// (Count is 0 if there were no components)
|
||||||
if (message.payload.Count > 0)
|
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.
|
// here immediately since there won't be another OnObjectSpawnFinished.
|
||||||
if (isSpawnFinished)
|
if (isSpawnFinished)
|
||||||
{
|
{
|
||||||
identity.NotifyAuthority();
|
InvokeIdentityCallbacks(identity);
|
||||||
CheckForStartClient(identity);
|
|
||||||
CheckForLocalPlayer(identity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,7 +1114,7 @@ static NetworkIdentity SpawnPrefab(SpawnMessage message)
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!obj.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Object Spawned by handler did not have a NetworkIdentity, Handler assetId '{message.assetId}'");
|
Debug.LogError($"Object Spawned by handler did not have a NetworkIdentity, Handler assetId '{message.assetId}'");
|
||||||
return null;
|
return null;
|
||||||
@ -1193,9 +1210,7 @@ internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _)
|
|||||||
// they are destroyed. for safety, let's double check here.
|
// they are destroyed. for safety, let's double check here.
|
||||||
if (identity != null)
|
if (identity != null)
|
||||||
{
|
{
|
||||||
identity.NotifyAuthority();
|
BootstrapIdentity(identity);
|
||||||
CheckForStartClient(identity);
|
|
||||||
CheckForLocalPlayer(identity);
|
|
||||||
}
|
}
|
||||||
else Debug.LogWarning("Found null entry in NetworkClient.spawned. This is unexpected. Was the NetworkIdentity not destroyed properly?");
|
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)
|
if (message.isLocalPlayer)
|
||||||
InternalAddPlayer(identity);
|
InternalAddPlayer(identity);
|
||||||
|
|
||||||
identity.isOwned = message.isOwner;
|
// set visibility before invoking OnStartClient etc. callbacks
|
||||||
identity.NotifyAuthority();
|
|
||||||
CheckForStartClient(identity);
|
|
||||||
|
|
||||||
if (aoi != null)
|
if (aoi != null)
|
||||||
aoi.SetHostVisibility(identity, true);
|
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)
|
if (identity.isLocalPlayer)
|
||||||
{
|
{
|
||||||
localPlayer = identity;
|
localPlayer = identity;
|
||||||
|
identity.connectionToServer = connection;
|
||||||
|
identity.OnStartLocalPlayer();
|
||||||
}
|
}
|
||||||
// identity's isLocalPlayer was set to false.
|
// identity's isLocalPlayer was set to false.
|
||||||
// clear our static localPlayer IF (and only IF) it was that one before.
|
// clear our static localPlayer IF (and only IF) it was that one before.
|
||||||
else if (localPlayer == identity)
|
else if (localPlayer == identity)
|
||||||
{
|
{
|
||||||
localPlayer = null;
|
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.
|
// set up NetworkIdentity flags on the client.
|
||||||
// it's cleaner to do this from NetworkClient.
|
// needs to be separate from invoking callbacks.
|
||||||
internal static void CheckForStartClient(NetworkIdentity identity)
|
// cleaner, and some places need to set flags first.
|
||||||
|
static void InitializeIdentityFlags(NetworkIdentity identity)
|
||||||
{
|
{
|
||||||
// OnStartLocalPlayer is called after OnStartClient.
|
// initialize flags before invoking callbacks.
|
||||||
// but we want the flag to be set in OnStartClient already.
|
// this way isClient/isLocalPlayer is correct during callbacks.
|
||||||
identity.isLocalPlayer = localPlayer == identity;
|
// fixes: https://github.com/MirrorNetworking/Mirror/issues/3362
|
||||||
identity.isClient = true;
|
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)
|
// invoke OnStartAuthority
|
||||||
{
|
identity.NotifyAuthority();
|
||||||
// Set isLocalPlayer to true on this NetworkIdentity and trigger
|
|
||||||
// OnStartLocalPlayer in all scripts on the same GO
|
|
||||||
identity.connectionToServer = connection;
|
|
||||||
|
|
||||||
// isLocalPlayer is already set by CheckForStartPlayer.
|
// invoke OnStartClient
|
||||||
// however, let's simply move it out of OnStartLocalPlayer for now.
|
identity.OnStartClient();
|
||||||
identity.isLocalPlayer = true;
|
|
||||||
|
// invoke OnStartLocalPlayer
|
||||||
|
if (identity.isLocalPlayer)
|
||||||
identity.OnStartLocalPlayer();
|
identity.OnStartLocalPlayer();
|
||||||
// Debug.Log($"NetworkClient.OnOwnerMessage player:{identity.name}");
|
}
|
||||||
}
|
|
||||||
|
// configure flags & invoke callbacks
|
||||||
|
static void BootstrapIdentity(NetworkIdentity identity)
|
||||||
|
{
|
||||||
|
InitializeIdentityFlags(identity);
|
||||||
|
InvokeIdentityCallbacks(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// broadcast ///////////////////////////////////////////////////////////
|
// broadcast ///////////////////////////////////////////////////////////
|
||||||
@ -1473,13 +1501,10 @@ internal static void NetworkLateUpdate()
|
|||||||
// also important for syncInterval=0 components like
|
// also important for syncInterval=0 components like
|
||||||
// NetworkTransform, so they can sync on same interval as time
|
// NetworkTransform, so they can sync on same interval as time
|
||||||
// snapshots _but_ not every single tick.
|
// snapshots _but_ not every single tick.
|
||||||
|
//
|
||||||
|
// Unity 2019 doesn't have Time.timeAsDouble yet
|
||||||
if (!Application.isPlaying ||
|
if (!Application.isPlaying ||
|
||||||
#if !UNITY_2020_3_OR_NEWER
|
|
||||||
// Unity 2019 doesn't have Time.timeAsDouble yet
|
|
||||||
AccurateInterval.Elapsed(NetworkTime.localTime, sendInterval, ref lastSendTime))
|
AccurateInterval.Elapsed(NetworkTime.localTime, sendInterval, ref lastSendTime))
|
||||||
#else
|
|
||||||
AccurateInterval.Elapsed(Time.timeAsDouble, sendInterval, ref lastSendTime))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
Broadcast();
|
Broadcast();
|
||||||
}
|
}
|
||||||
|
@ -523,7 +523,6 @@ void FinishStartHost()
|
|||||||
SetupClient();
|
SetupClient();
|
||||||
|
|
||||||
networkAddress = "localhost";
|
networkAddress = "localhost";
|
||||||
HostMode.ActivateHostScene();
|
|
||||||
RegisterClientMessages();
|
RegisterClientMessages();
|
||||||
|
|
||||||
// call OnConencted needs to be called AFTER RegisterClientMessages
|
// call OnConencted needs to be called AFTER RegisterClientMessages
|
||||||
|
@ -821,7 +821,7 @@ public static void UnregisterHandler<T>()
|
|||||||
|
|
||||||
internal static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity)
|
internal static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity)
|
||||||
{
|
{
|
||||||
if (!go.TryGetComponent<NetworkIdentity>(out identity))
|
if (!go.TryGetComponent(out identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"GameObject {go.name} doesn't have NetworkIdentity.");
|
Debug.LogError($"GameObject {go.name} doesn't have NetworkIdentity.");
|
||||||
return false;
|
return false;
|
||||||
@ -898,7 +898,7 @@ public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameOb
|
|||||||
// on this playerControllerId for this connection, this will fail.
|
// on this playerControllerId for this connection, this will fail.
|
||||||
public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameObject player)
|
public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameObject player)
|
||||||
{
|
{
|
||||||
if (!player.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!player.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"AddPlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}");
|
Debug.LogWarning($"AddPlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}");
|
||||||
return false;
|
return false;
|
||||||
@ -939,7 +939,7 @@ public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameOb
|
|||||||
// safely be used while changing scenes.
|
// safely be used while changing scenes.
|
||||||
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false)
|
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false)
|
||||||
{
|
{
|
||||||
if (!player.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!player.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}");
|
Debug.LogError($"ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to {player}");
|
||||||
return false;
|
return false;
|
||||||
@ -1288,7 +1288,7 @@ public static bool SpawnObjects()
|
|||||||
// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
|
// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
|
||||||
public static void Spawn(GameObject obj, GameObject ownerPlayer)
|
public static void Spawn(GameObject obj, GameObject ownerPlayer)
|
||||||
{
|
{
|
||||||
if (!ownerPlayer.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!ownerPlayer.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError("Player object has no NetworkIdentity");
|
Debug.LogError("Player object has no NetworkIdentity");
|
||||||
return;
|
return;
|
||||||
@ -1351,7 +1351,7 @@ static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!obj.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
Debug.LogError($"SpawnObject {obj} has no NetworkIdentity. Please add a NetworkIdentity to {obj}", obj);
|
Debug.LogError($"SpawnObject {obj} has no NetworkIdentity. Please add a NetworkIdentity to {obj}", obj);
|
||||||
return;
|
return;
|
||||||
@ -1385,6 +1385,8 @@ static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
|
|||||||
if (!identity.isServer && identity.netId == 0)
|
if (!identity.isServer && identity.netId == 0)
|
||||||
{
|
{
|
||||||
// configure NetworkIdentity
|
// configure NetworkIdentity
|
||||||
|
// this may be called in host mode, so we need to initialize
|
||||||
|
// isLocalPlayer/isClient flags too.
|
||||||
identity.isLocalPlayer = NetworkClient.localPlayer == identity;
|
identity.isLocalPlayer = NetworkClient.localPlayer == identity;
|
||||||
identity.isClient = NetworkClient.active;
|
identity.isClient = NetworkClient.active;
|
||||||
identity.isServer = true;
|
identity.isServer = true;
|
||||||
|
@ -239,7 +239,7 @@ public static void WriteTransform(this NetworkWriter writer, Transform value)
|
|||||||
writer.WriteUInt(0);
|
writer.WriteUInt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (value.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
writer.WriteUInt(identity.netId);
|
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,
|
// warn if the GameObject doesn't have a NetworkIdentity,
|
||||||
if (!value.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (!value.TryGetComponent(out NetworkIdentity identity))
|
||||||
Debug.LogWarning($"NetworkWriter {value} has no NetworkIdentity");
|
Debug.LogWarning($"NetworkWriter {value} has no NetworkIdentity");
|
||||||
|
|
||||||
// serialize the correct amount of data in any case to make sure
|
// serialize the correct amount of data in any case to make sure
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// API consistent with Microsoft's ObjectPool<T>.
|
// API consistent with Microsoft's ObjectPool<T>.
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Mirror
|
namespace Mirror
|
||||||
|
@ -72,7 +72,7 @@ IEnumerator LoadAdditive(string sceneName)
|
|||||||
isInTransition = true;
|
isInTransition = true;
|
||||||
|
|
||||||
// This will return immediately if already faded in
|
// 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();
|
yield return fadeInOut.FadeIn();
|
||||||
|
|
||||||
// host client is on server...don't load the additive scene again
|
// host client is on server...don't load the additive scene again
|
||||||
@ -91,6 +91,7 @@ IEnumerator LoadAdditive(string sceneName)
|
|||||||
|
|
||||||
OnClientSceneChanged();
|
OnClientSceneChanged();
|
||||||
|
|
||||||
|
// Reveal the new scene content.
|
||||||
yield return fadeInOut.FadeOut();
|
yield return fadeInOut.FadeOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +100,10 @@ IEnumerator UnloadAdditive(string sceneName)
|
|||||||
isInTransition = true;
|
isInTransition = true;
|
||||||
|
|
||||||
// This will return immediately if already faded in
|
// 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();
|
yield return fadeInOut.FadeIn();
|
||||||
|
|
||||||
|
// host client is on server...don't unload the additive scene here.
|
||||||
if (mode == NetworkManagerMode.ClientOnly)
|
if (mode == NetworkManagerMode.ClientOnly)
|
||||||
{
|
{
|
||||||
yield return SceneManager.UnloadSceneAsync(sceneName);
|
yield return SceneManager.UnloadSceneAsync(sceneName);
|
||||||
@ -115,8 +117,8 @@ IEnumerator UnloadAdditive(string sceneName)
|
|||||||
OnClientSceneChanged();
|
OnClientSceneChanged();
|
||||||
|
|
||||||
// There is no call to FadeOut here on purpose.
|
// There is no call to FadeOut here on purpose.
|
||||||
// Expectation is that a LoadAdditive will follow
|
// Expectation is that a LoadAdditive or full scene change
|
||||||
// that will call FadeOut after that scene loads.
|
// will follow that will call FadeOut after that scene loads.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -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}");
|
//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
|
// applies to host client on server and remote clients
|
||||||
if (other.TryGetComponent<PlayerController>(out PlayerController playerController))
|
if (other.TryGetComponent(out PlayerController playerController))
|
||||||
playerController.enabled = false;
|
playerController.enabled = false;
|
||||||
|
|
||||||
if (isServer)
|
if (isServer)
|
||||||
@ -56,7 +56,7 @@ void OnTriggerEnter(Collider other)
|
|||||||
[ServerCallback]
|
[ServerCallback]
|
||||||
IEnumerator SendPlayerToNewScene(GameObject player)
|
IEnumerator SendPlayerToNewScene(GameObject player)
|
||||||
{
|
{
|
||||||
if (player.TryGetComponent<NetworkIdentity>(out NetworkIdentity identity))
|
if (player.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
NetworkConnectionToClient conn = identity.connectionToClient;
|
NetworkConnectionToClient conn = identity.connectionToClient;
|
||||||
if (conn == null) yield break;
|
if (conn == null) yield break;
|
||||||
@ -83,7 +83,7 @@ IEnumerator SendPlayerToNewScene(GameObject player)
|
|||||||
NetworkServer.AddPlayerForConnection(conn, player);
|
NetworkServer.AddPlayerForConnection(conn, player);
|
||||||
|
|
||||||
// host client would have been disabled by OnTriggerEnter above
|
// host client would have been disabled by OnTriggerEnter above
|
||||||
if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent<PlayerController>(out PlayerController playerController))
|
if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent(out PlayerController playerController))
|
||||||
playerController.enabled = true;
|
playerController.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@ void Update()
|
|||||||
// always update health bar.
|
// always update health bar.
|
||||||
// (SyncVar hook would only update on clients, not on server)
|
// (SyncVar hook would only update on clients, not on server)
|
||||||
healthBar.text = new string('-', health);
|
healthBar.text = new string('-', health);
|
||||||
|
|
||||||
|
// take input from focused window only
|
||||||
|
if(!Application.isFocused) return;
|
||||||
|
|
||||||
// movement for local player
|
// movement for local player
|
||||||
if (isLocalPlayer)
|
if (isLocalPlayer)
|
||||||
|
@ -21,7 +21,7 @@ public void TestIntReaderNotNull()
|
|||||||
public void TestAccessingCustomWriterAndReader()
|
public void TestAccessingCustomWriterAndReader()
|
||||||
{
|
{
|
||||||
NetworkWriter writer = new NetworkWriter();
|
NetworkWriter writer = new NetworkWriter();
|
||||||
writer.Write<int>(3);
|
writer.Write(3);
|
||||||
NetworkReader reader = new NetworkReader(writer.ToArray());
|
NetworkReader reader = new NetworkReader(writer.ToArray());
|
||||||
int copy = reader.Read<int>();
|
int copy = reader.Read<int>();
|
||||||
|
|
||||||
|
@ -839,28 +839,6 @@ public void SendCommand_RequiresAuthority()
|
|||||||
Assert.That(comp.called, Is.EqualTo(0));
|
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]
|
[Test]
|
||||||
public void SendToAll()
|
public void SendToAll()
|
||||||
{
|
{
|
||||||
|
@ -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]
|
V1.27 [2023-01-08]
|
||||||
- KcpClient.Connect: invoke own events directly instead of going through peer,
|
- KcpClient.Connect: invoke own events directly instead of going through peer,
|
||||||
which calls our own events anyway
|
which calls our own events anyway
|
||||||
|
@ -60,6 +60,16 @@ public void Connect(string address, ushort port, KcpConfig config)
|
|||||||
return;
|
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
|
// create fresh peer for each new session
|
||||||
peer = new KcpPeer(RawSend, OnAuthenticatedWrap, OnData, OnDisconnectedWrap, OnError, config);
|
peer = new KcpPeer(RawSend, OnAuthenticatedWrap, OnData, OnDisconnectedWrap, OnError, config);
|
||||||
|
|
||||||
@ -83,15 +93,6 @@ void OnDisconnectedWrap()
|
|||||||
|
|
||||||
Log.Info($"KcpClient: connect to {address}:{port}");
|
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
|
// create socket
|
||||||
remoteEndPoint = new IPEndPoint(addresses[0], port);
|
remoteEndPoint = new IPEndPoint(addresses[0], port);
|
||||||
socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
@ -67,7 +67,18 @@ static Socket CreateServerSocket(bool DualMode, ushort port)
|
|||||||
{
|
{
|
||||||
// IPv6 socket with DualMode @ "::" : port
|
// IPv6 socket with DualMode @ "::" : port
|
||||||
Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
|
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));
|
socket.Bind(new IPEndPoint(IPAddress.IPv6Any, port));
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,8 @@ public class #SCRIPTNAME# : InterestManagement
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="identity">Object to be observed (or not) by clients</param>
|
/// <param name="identity">Object to be observed (or not) by clients</param>
|
||||||
/// <param name="newObservers">cached hashset to put the result into</param>
|
/// <param name="newObservers">cached hashset to put the result into</param>
|
||||||
/// <param name="initialize">true if being rebuilt for the first time</param>
|
|
||||||
[ServerCallback]
|
[ServerCallback]
|
||||||
public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers, bool initialize)
|
public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers)
|
||||||
{
|
{
|
||||||
// Default behaviour of making the identity object visible to all clients.
|
// Default behaviour of making the identity object visible to all clients.
|
||||||
// Replace this code with your own logic as appropriate.
|
// Replace this code with your own logic as appropriate.
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.2d.sprite": "1.0.0",
|
"com.unity.2d.sprite": "1.0.0",
|
||||||
"com.unity.2d.tilemap": "1.0.0",
|
"com.unity.2d.tilemap": "1.0.0",
|
||||||
"com.unity.ide.rider": "3.0.16",
|
"com.unity.ide.rider": "3.0.18",
|
||||||
"com.unity.ide.visualstudio": "2.0.16",
|
"com.unity.ide.visualstudio": "2.0.17",
|
||||||
"com.unity.ide.vscode": "1.2.5",
|
"com.unity.ide.vscode": "1.2.5",
|
||||||
"com.unity.test-framework": "1.1.31",
|
"com.unity.test-framework": "1.1.31",
|
||||||
"com.unity.testtools.codecoverage": "1.2.2",
|
"com.unity.testtools.codecoverage": "1.2.2",
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.ide.rider": {
|
"com.unity.ide.rider": {
|
||||||
"version": "3.0.16",
|
"version": "3.0.18",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -29,7 +29,7 @@
|
|||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
"com.unity.ide.visualstudio": {
|
"com.unity.ide.visualstudio": {
|
||||||
"version": "2.0.16",
|
"version": "2.0.17",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
m_EditorVersion: 2021.3.15f1
|
m_EditorVersion: 2021.3.17f1
|
||||||
m_EditorVersionWithRevision: 2021.3.15f1 (e8e88683f834)
|
m_EditorVersionWithRevision: 2021.3.17f1 (3e8111cac19d)
|
||||||
|
Loading…
Reference in New Issue
Block a user