diff --git a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs index 5445b0d8e8..b93e7d90d5 100644 --- a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs +++ b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs @@ -48,6 +48,12 @@ public class NetworkManagerEditor : NetcodeEditorBase private SerializedProperty m_NetworkProfileMetrics; private SerializedProperty m_NetworkMessageMetrics; +#if CMB_SERVICE_DEVELOPMENT + private SerializedProperty m_MajorVersion; + private SerializedProperty m_MinorVersion; + private SerializedProperty m_PatchVersion; +#endif + private NetworkManager m_NetworkManager; private bool m_Initialized; @@ -120,8 +126,11 @@ private void Initialize() #if MULTIPLAYER_TOOLS m_NetworkMessageMetrics = m_NetworkConfigProperty.FindPropertyRelative("NetworkMessageMetrics"); #endif - - +#if CMB_SERVICE_DEVELOPMENT + m_MajorVersion = serializedObject.FindProperty(nameof(NetworkManager.MajorVersion)); + m_MinorVersion = serializedObject.FindProperty(nameof(NetworkManager.MinorVersion)); + m_PatchVersion = serializedObject.FindProperty(nameof(NetworkManager.PatchVersion)); +#endif m_RpcHashSizeProperty = m_NetworkConfigProperty.FindPropertyRelative("RpcHashSize"); m_PrefabsList = m_NetworkConfigProperty .FindPropertyRelative(nameof(NetworkConfig.Prefabs)) @@ -161,6 +170,11 @@ private void CheckNullProperties() #if MULTIPLAYER_TOOLS m_NetworkMessageMetrics = m_NetworkConfigProperty.FindPropertyRelative("NetworkMessageMetrics"); #endif +#if CMB_SERVICE_DEVELOPMENT + m_MajorVersion = serializedObject.FindProperty(nameof(NetworkManager.MajorVersion)); + m_MinorVersion = serializedObject.FindProperty(nameof(NetworkManager.MinorVersion)); + m_PatchVersion = serializedObject.FindProperty(nameof(NetworkManager.PatchVersion)); +#endif m_RpcHashSizeProperty = m_NetworkConfigProperty.FindPropertyRelative("RpcHashSize"); m_PrefabsList = m_NetworkConfigProperty @@ -173,10 +187,18 @@ private void DisplayNetworkManagerProperties() if (!m_NetworkManager.IsServer && !m_NetworkManager.IsClient) { serializedObject.Update(); + EditorGUILayout.PropertyField(m_RunInBackgroundProperty); EditorGUILayout.PropertyField(m_LogLevelProperty); + EditorGUILayout.Space(); +#if CMB_SERVICE_DEVELOPMENT + EditorGUILayout.LabelField("Version:", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(m_MajorVersion); + EditorGUILayout.PropertyField(m_MinorVersion); + EditorGUILayout.PropertyField(m_PatchVersion); EditorGUILayout.Space(); +#endif EditorGUILayout.LabelField("Network Settings", EditorStyles.boldLabel); #if MULTIPLAYER_SERVICES_SDK_INSTALLED EditorGUILayout.PropertyField(m_NetworkTopologyProperty); diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs index b9d8eabab3..d4d1f93a98 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs @@ -1463,8 +1463,6 @@ private bool ShouldSynchronizeHalfFloat(ulong targetClientId) // For test logging purposes internal NetworkTransformState SynchronizeState; - // DANGO-TODO: We will want to remove this when we migrate NetworkTransforms to a dedicated internal message - private const ushort k_NetworkTransformStateMagic = 0xf48d; #endregion #region ONSYNCHRONIZE @@ -1494,14 +1492,6 @@ protected override void OnSynchronize(ref BufferSerializer serializer) if (serializer.IsWriter) { - // DANGO-TODO: This magic value is sent to the server in order to identify the network transform. - // The server discards it before forwarding synchronization data to other clients. - if (NetworkManager.DistributedAuthorityMode && NetworkManager.CMBServiceConnection) - { - var writer = serializer.GetFastBufferWriter(); - writer.WriteValueSafe(k_NetworkTransformStateMagic); - } - SynchronizeState.IsTeleportingNextFrame = true; var transformToCommit = transform; // If we are using Half Float Precision, then we want to only synchronize the authority's m_HalfPositionState.FullPosition in order for diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index b02248009f..33098f36c2 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -564,9 +564,6 @@ private void SendConnectionRequest() var message = new ConnectionRequestMessage { CMBServiceConnection = NetworkManager.CMBServiceConnection, - TickRate = NetworkManager.NetworkConfig.TickRate, - EnableSceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement, - // Since only a remote client will send a connection request, we should always force the rebuilding of the NetworkConfig hash value ConfigHash = NetworkManager.NetworkConfig.GetConfig(false), ShouldSendConnectionData = NetworkManager.NetworkConfig.ConnectionApproval, @@ -574,6 +571,13 @@ private void SendConnectionRequest() MessageVersions = new NativeArray(MessageManager.MessageHandlers.Length, Allocator.Temp) }; + if (NetworkManager.CMBServiceConnection) + { + message.ClientConfig.NGOVersion = NetworkManager.GetNGOVersion(); + message.ClientConfig.TickRate = NetworkManager.NetworkConfig.TickRate; + message.ClientConfig.EnableSceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement; + } + for (int index = 0; index < MessageManager.MessageHandlers.Length; index++) { if (MessageManager.MessageTypes[index] != null) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index 28ad916f55..0bb73b3a37 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -5,6 +5,7 @@ using UnityEngine; #if UNITY_EDITOR using UnityEditor; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; #endif using UnityEngine.SceneManagement; using Debug = UnityEngine.Debug; @@ -885,6 +886,30 @@ internal T Value internal Override PortOverride; + + [HideInInspector] + [SerializeField] + [Range(0, 255)] + internal byte MajorVersion; + [HideInInspector] + [SerializeField] + [Range(0, 255)] + internal byte MinorVersion; + [HideInInspector] + [SerializeField] + [Range(0, 255)] + internal byte PatchVersion; + + internal NGOVersion GetNGOVersion() + { + return new NGOVersion() + { + Major = MajorVersion, + Minor = MinorVersion, + Patch = PatchVersion + }; + } + #if UNITY_EDITOR internal static INetworkManagerHelper NetworkManagerHelper; @@ -911,6 +936,26 @@ protected virtual void OnValidateComponent() } + private PackageInfo GetPackageInfo(string packageName) + { + return AssetDatabase.FindAssets("package").Select(AssetDatabase.GUIDToAssetPath).Where(x => AssetDatabase.LoadAssetAtPath(x) != null).Select(PackageInfo.FindForAssetPath).Where(x => x != null).First(x => x.name == packageName); + } + + private void SetPackageVersion() + { + var packageInfo = GetPackageInfo("com.unity.netcode.gameobjects"); + if (packageInfo != null) + { + var versionSplit = packageInfo.version.Split("."); + if (versionSplit.Length == 3) + { + MajorVersion = byte.Parse(versionSplit[0]); + MinorVersion = byte.Parse(versionSplit[1]); + PatchVersion = byte.Parse(versionSplit[2]); + } + } + } + internal void OnValidate() { if (NetworkConfig == null) @@ -918,6 +963,12 @@ internal void OnValidate() return; // May occur when the component is added } +#if !CMB_SERVICE_DEVELOPMENT + SetPackageVersion(); +#else + Debug.Log($"Major:({MajorVersion}) Minor({MinorVersion}) Patch({PatchVersion})"); +#endif + if (GetComponentInChildren() != null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs index bb3e446817..7b9a87fe9c 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs @@ -3,14 +3,39 @@ namespace Unity.Netcode { + internal struct ServiceConfig : INetworkSerializable + { + public uint Version; + public bool IsRestoredSession; + public ulong CurrentSessionOwner; + + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter + { + if (serializer.IsWriter) + { + BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), Version); + serializer.SerializeValue(ref IsRestoredSession); + BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), CurrentSessionOwner); + } + else + { + ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out Version); + serializer.SerializeValue(ref IsRestoredSession); + ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out CurrentSessionOwner); + } + } + } + internal struct ConnectionApprovedMessage : INetworkMessage { + private const int k_AddCMBServiceConfig = 2; private const int k_VersionAddClientIds = 1; - public int Version => k_VersionAddClientIds; + public int Version => k_AddCMBServiceConfig; public ulong OwnerClientId; public int NetworkTick; // The cloud state service should set this if we are restoring a session + public ServiceConfig ServiceConfig; public bool IsRestoredSession; public ulong CurrentSessionOwner; // Not serialized @@ -25,6 +50,32 @@ internal struct ConnectionApprovedMessage : INetworkMessage public NativeArray ConnectedClientIds; + private int m_ReceiveMessageVersion; + + private ulong GetSessionOwner() + { + if (m_ReceiveMessageVersion >= k_AddCMBServiceConfig) + { + return ServiceConfig.CurrentSessionOwner; + } + else + { + return CurrentSessionOwner; + } + } + + private bool GetIsSessionRestor() + { + if (m_ReceiveMessageVersion >= k_AddCMBServiceConfig) + { + return ServiceConfig.IsRestoredSession; + } + else + { + return IsRestoredSession; + } + } + public void Serialize(FastBufferWriter writer, int targetVersion) { // ============================================================ @@ -45,8 +96,17 @@ public void Serialize(FastBufferWriter writer, int targetVersion) BytePacker.WriteValueBitPacked(writer, NetworkTick); if (IsDistributedAuthority) { - writer.WriteValueSafe(IsRestoredSession); - BytePacker.WriteValueBitPacked(writer, CurrentSessionOwner); + if (targetVersion >= k_AddCMBServiceConfig) + { + ServiceConfig.IsRestoredSession = false; + ServiceConfig.CurrentSessionOwner = CurrentSessionOwner; + writer.WriteNetworkSerializable(ServiceConfig); + } + else + { + writer.WriteValueSafe(IsRestoredSession); + BytePacker.WriteValueBitPacked(writer, CurrentSessionOwner); + } } if (targetVersion >= k_VersionAddClientIds) @@ -122,13 +182,20 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int // ============================================================ // END FORBIDDEN SEGMENT // ============================================================ - + m_ReceiveMessageVersion = receivedMessageVersion; ByteUnpacker.ReadValueBitPacked(reader, out OwnerClientId); ByteUnpacker.ReadValueBitPacked(reader, out NetworkTick); if (networkManager.DistributedAuthorityMode) { - reader.ReadValueSafe(out IsRestoredSession); - ByteUnpacker.ReadValueBitPacked(reader, out CurrentSessionOwner); + if (receivedMessageVersion >= k_AddCMBServiceConfig) + { + reader.ReadNetworkSerializable(out ServiceConfig); + } + else + { + reader.ReadValueSafe(out IsRestoredSession); + ByteUnpacker.ReadValueBitPacked(reader, out CurrentSessionOwner); + } } if (receivedMessageVersion >= k_VersionAddClientIds) @@ -157,7 +224,7 @@ public void Handle(ref NetworkContext context) if (networkManager.DistributedAuthorityMode) { - networkManager.SetSessionOwner(CurrentSessionOwner); + networkManager.SetSessionOwner(GetSessionOwner()); if (networkManager.LocalClient.IsSessionOwner && networkManager.NetworkConfig.EnableSceneManagement) { networkManager.SceneManager.InitializeScenesLoaded(); @@ -233,9 +300,9 @@ public void Handle(ref NetworkContext context) // Mark the client being connected networkManager.IsConnectedClient = true; - networkManager.SceneManager.IsRestoringSession = IsRestoredSession; + networkManager.SceneManager.IsRestoringSession = GetIsSessionRestor(); - if (!IsRestoredSession) + if (!networkManager.SceneManager.IsRestoringSession) { // Synchronize the service with the initial session owner's loaded scenes and spawned objects networkManager.SceneManager.SynchronizeNetworkObjects(NetworkManager.ServerClientId); diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionRequestMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionRequestMessage.cs index 790791dd24..87d49cb332 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionRequestMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionRequestMessage.cs @@ -2,16 +2,56 @@ namespace Unity.Netcode { - internal struct ConnectionRequestMessage : INetworkMessage + internal struct NGOVersion : INetworkSerializable { - public int Version => 0; + public byte Major; + public byte Minor; + public byte Patch; - public ulong ConfigHash; + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter + { + serializer.SerializeValue(ref Major); + serializer.SerializeValue(ref Minor); + serializer.SerializeValue(ref Patch); + } + } - public bool CMBServiceConnection; + internal struct ClientConfig : INetworkSerializable + { + public NGOVersion NGOVersion; public uint TickRate; public bool EnableSceneManagement; + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter + { + serializer.SerializeNetworkSerializable(ref NGOVersion); + if (serializer.IsWriter) + { + var writer = serializer.GetFastBufferWriter(); + writer.WriteValueSafe(TickRate); + writer.WriteValueSafe(EnableSceneManagement); + } + else + { + var reader = serializer.GetFastBufferReader(); + reader.ReadValueSafe(out TickRate); + reader.ReadValueSafe(out EnableSceneManagement); + } + } + } + + internal struct ConnectionRequestMessage : INetworkMessage + { + // This version update is unidirectional (client to service) and version + // handling occurs on the service side. This serialized data is never sent + // to a host or server. + private const int k_SendClientConfigToService = 1; + public int Version => k_SendClientConfigToService; + + public ulong ConfigHash; + public bool CMBServiceConnection; + public ClientConfig ClientConfig; + public byte[] ConnectionData; public bool ShouldSendConnectionData; @@ -36,8 +76,7 @@ public void Serialize(FastBufferWriter writer, int targetVersion) if (CMBServiceConnection) { - writer.WriteValueSafe(TickRate); - writer.WriteValueSafe(EnableSceneManagement); + writer.WriteNetworkSerializable(ClientConfig); } if (ShouldSendConnectionData)