diff --git a/com.unity.netcode.gameobjects/Editor/NetworkBehaviourEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkBehaviourEditor.cs index c525d121d6..d3350d395e 100644 --- a/com.unity.netcode.gameobjects/Editor/NetworkBehaviourEditor.cs +++ b/com.unity.netcode.gameobjects/Editor/NetworkBehaviourEditor.cs @@ -58,7 +58,7 @@ private void RenderNetworkVariable(int index) if (value == null) { var fieldType = m_NetworkVariableFields[m_NetworkVariableNames[index]].FieldType; - var networkVariable = (INetworkVariable)Activator.CreateInstance(fieldType, true); + var networkVariable = (NetworkVariableBase)Activator.CreateInstance(fieldType, true); m_NetworkVariableFields[m_NetworkVariableNames[index]].SetValue(target, networkVariable); } @@ -66,12 +66,7 @@ private void RenderNetworkVariable(int index) var genericType = type.GetGenericArguments()[0]; EditorGUILayout.BeginHorizontal(); - if (genericType == typeof(string)) - { - var networkVariable = (NetworkVariable)m_NetworkVariableFields[m_NetworkVariableNames[index]].GetValue(target); - networkVariable.Value = EditorGUILayout.TextField(m_NetworkVariableNames[index], networkVariable.Value); - } - else if (genericType.IsValueType) + if (genericType.IsValueType) { var method = typeof(NetworkBehaviourEditor).GetMethod("RenderNetworkVariableValueType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic); var genericMethod = method.MakeGenericMethod(genericType); @@ -86,7 +81,7 @@ private void RenderNetworkVariable(int index) EditorGUILayout.EndHorizontal(); } - private void RenderNetworkVariableValueType(int index) where T : struct + private void RenderNetworkVariableValueType(int index) where T : unmanaged { var networkVariable = (NetworkVariable)m_NetworkVariableFields[m_NetworkVariableNames[index]].GetValue(target); var type = typeof(T); diff --git a/com.unity.netcode.gameobjects/Prototyping/NetworkTransform.cs b/com.unity.netcode.gameobjects/Prototyping/NetworkTransform.cs index 0132d24e16..dfeefad15f 100644 --- a/com.unity.netcode.gameobjects/Prototyping/NetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Prototyping/NetworkTransform.cs @@ -128,12 +128,6 @@ public void NetworkSerialize(NetworkSerializer serializer) } } - /// - /// The network channel to use send updates - /// - [Tooltip("The network channel to use send updates")] - public NetworkChannel Channel = NetworkChannel.NetworkVariable; - /// /// Sets whether this transform should sync in local space or in world space. /// This is important to set since reparenting this transform could have issues, @@ -156,6 +150,7 @@ public void NetworkSerialize(NetworkSerializer serializer) public float FixedSendsPerSecond = 30f; private Transform m_Transform; // cache the transform component to reduce unnecessary bounce between managed and native + internal NetworkState LocalNetworkState; internal readonly NetworkVariable ReplNetworkState = new NetworkVariable(new NetworkState()); internal NetworkState PrevNetworkState; @@ -364,10 +359,6 @@ private void OnNetworkStateChanged(NetworkState oldState, NetworkState newState) private void Awake() { m_Transform = transform; - - ReplNetworkState.Settings.SendNetworkChannel = Channel; - ReplNetworkState.Settings.SendTickrate = FixedSendsPerSecond; - ReplNetworkState.OnValueChanged += OnNetworkStateChanged; } @@ -385,7 +376,13 @@ private void FixedUpdate() if (IsServer) { - ReplNetworkState.SetDirty(UpdateNetworkState(ref ReplNetworkState.ValueRef)); + // try to update local NetworkState + if (UpdateNetworkState(ref LocalNetworkState)) + { + // if updated (dirty), change NetVar, mark it dirty + ReplNetworkState.Value = LocalNetworkState; + ReplNetworkState.SetDirty(true); + } } // try to update previously consumed NetworkState // if we have any changes, that means made some updates locally diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs index b12cb90cb6..d871509288 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs @@ -366,7 +366,7 @@ public virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObje private readonly List> m_ChannelMappedNetworkVariableIndexes = new List>(); private readonly List m_ChannelsForNetworkVariableGroups = new List(); - internal readonly List NetworkVariableFields = new List(); + internal readonly List NetworkVariableFields = new List(); private static Dictionary s_FieldTypes = new Dictionary(); @@ -415,19 +415,19 @@ internal void InitializeVariables() { Type fieldType = sortedFields[i].FieldType; - if (fieldType.HasInterface(typeof(INetworkVariable))) + if (fieldType.IsSubclassOf(typeof(NetworkVariableBase))) { - var instance = (INetworkVariable)sortedFields[i].GetValue(this); + var instance = (NetworkVariableBase)sortedFields[i].GetValue(this); if (instance == null) { - instance = (INetworkVariable)Activator.CreateInstance(fieldType, true); + instance = (NetworkVariableBase)Activator.CreateInstance(fieldType, true); sortedFields[i].SetValue(this, instance); } - instance.SetNetworkBehaviour(this); + instance.NetworkBehaviour = this; - var instanceNameProperty = fieldType.GetProperty(nameof(INetworkVariable.Name)); + var instanceNameProperty = fieldType.GetProperty(nameof(NetworkVariableBase.Name)); var sanitizedVariableName = sortedFields[i].Name.Replace("<", string.Empty).Replace(">k__BackingField", string.Empty); instanceNameProperty?.SetValue(instance, sanitizedVariableName); @@ -442,7 +442,7 @@ internal void InitializeVariables() for (int i = 0; i < NetworkVariableFields.Count; i++) { - NetworkChannel networkChannel = NetworkVariableFields[i].GetChannel(); + var networkChannel = NetworkVariableBase.NetworkVariableChannel; if (!firstLevelIndex.ContainsKey(networkChannel)) { @@ -514,6 +514,7 @@ private void NetworkVariableUpdate(ulong clientId, int behaviourIndex) { using (var writer = PooledNetworkWriter.Get(buffer)) { + // TODO: could skip this if no variables dirty, though obsolete w/ Snapshot writer.WriteUInt64Packed(NetworkObjectId); writer.WriteUInt16Packed(NetworkObject.GetNetworkBehaviourOrderIndex(this)); @@ -537,14 +538,9 @@ private void NetworkVariableUpdate(ulong clientId, int behaviourIndex) continue; } - bool isDirty = - NetworkVariableFields[k] - .IsDirty(); // cache this here. You never know what operations users will do in the dirty methods - // if I'm dirty AND a client, write (server always has all permissions) // if I'm dirty AND the server AND the client can read me, send. - bool shouldWrite = isDirty && - (!IsServer || NetworkVariableFields[k].CanClientRead(clientId)); + bool shouldWrite = NetworkVariableFields[k].ShouldWrite(clientId, IsServer); if (NetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) { @@ -628,7 +624,7 @@ private bool CouldHaveDirtyNetworkVariables() return false; } - internal static void HandleNetworkVariableDeltas(List networkVariableList, Stream stream, ulong clientId, NetworkBehaviour logInstance, NetworkManager networkManager) + internal static void HandleNetworkVariableDeltas(List networkVariableList, Stream stream, ulong clientId, NetworkBehaviour logInstance, NetworkManager networkManager) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -655,6 +651,7 @@ internal static void HandleNetworkVariableDeltas(List networkV if (networkManager.IsServer && !networkVariableList[i].CanClientWrite(clientId)) { + // we are choosing not to fire an exception here, because otherwise a malicious client could use this to crash the server if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) @@ -674,7 +671,6 @@ internal static void HandleNetworkVariableDeltas(List networkV //A dummy read COULD be added to the interface for this situation, but it's just being too nice. //This is after all a developer fault. A critical error should be fine. // - TwoTen - if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogError($"Client wrote to {typeof(NetworkVariable<>).Name} without permission. No more variables can be read. This is critical. => {(logInstance != null ? ($"{nameof(NetworkObjectId)}: {logInstance.NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {logInstance.NetworkObject.GetNetworkBehaviourOrderIndex(logInstance)} - VariableIndex: {i}") : string.Empty)}"); @@ -683,7 +679,6 @@ internal static void HandleNetworkVariableDeltas(List networkV return; } - long readStartPos = stream.Position; networkVariableList[i].ReadDelta(stream, networkManager.IsServer); @@ -722,95 +717,7 @@ internal static void HandleNetworkVariableDeltas(List networkV } } - internal static void HandleNetworkVariableUpdate(List networkVariableList, Stream stream, ulong clientId, NetworkBehaviour logInstance, NetworkManager networkManager) - { - using (var reader = PooledNetworkReader.Get(stream)) - { - for (int i = 0; i < networkVariableList.Count; i++) - { - ushort varSize = 0; - - if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) - { - varSize = reader.ReadUInt16Packed(); - - if (varSize == 0) - { - continue; - } - } - else - { - if (!reader.ReadBool()) - { - continue; - } - } - - if (networkManager.IsServer && !networkVariableList[i].CanClientWrite(clientId)) - { - if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) - { - NetworkLog.LogWarning($"Client wrote to {typeof(NetworkVariable<>).Name} without permission. => {(logInstance != null ? ($"{nameof(NetworkObjectId)}: {logInstance.NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {logInstance.NetworkObject.GetNetworkBehaviourOrderIndex(logInstance)} - VariableIndex: {i}") : string.Empty)}"); - } - - stream.Position += varSize; - continue; - } - - //This client wrote somewhere they are not allowed. This is critical - //We can't just skip this field. Because we don't actually know how to dummy read - //That is, we don't know how many bytes to skip. Because the interface doesn't have a - //Read that gives us the value. Only a Read that applies the value straight away - //A dummy read COULD be added to the interface for this situation, but it's just being too nice. - //This is after all a developer fault. A critical error should be fine. - // - TwoTen - if (NetworkLog.CurrentLogLevel <= LogLevel.Error) - { - NetworkLog.LogError($"Client wrote to {typeof(NetworkVariable<>).Name} without permission. No more variables can be read. This is critical. => {(logInstance != null ? ($"{nameof(NetworkObjectId)}: {logInstance.NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {logInstance.NetworkObject.GetNetworkBehaviourOrderIndex(logInstance)} - VariableIndex: {i}") : string.Empty)}"); - } - - return; - } - - long readStartPos = stream.Position; - - networkVariableList[i].ReadField(stream); - - if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) - { - if (stream is NetworkBuffer networkBuffer) - { - networkBuffer.SkipPadBits(); - } - - if (stream.Position > (readStartPos + varSize)) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) - { - NetworkLog.LogWarning($"Var update read too far. {stream.Position - (readStartPos + varSize)} bytes. => {(logInstance != null ? ($"{nameof(NetworkObjectId)}: {logInstance.NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {logInstance.NetworkObject.GetNetworkBehaviourOrderIndex(logInstance)} - VariableIndex: {i}") : string.Empty)}"); - } - - stream.Position = readStartPos + varSize; - } - else if (stream.Position < (readStartPos + varSize)) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) - { - NetworkLog.LogWarning($"Var update read too little. {(readStartPos + varSize) - stream.Position} bytes. => {(logInstance != null ? ($"{nameof(NetworkObjectId)}: {logInstance.NetworkObjectId} - {nameof(NetworkObject.GetNetworkBehaviourOrderIndex)}(): {logInstance.NetworkObject.GetNetworkBehaviourOrderIndex(logInstance)} - VariableIndex: {i}") : string.Empty)}"); - } - - stream.Position = readStartPos + varSize; - } - } - } - } - } - - - internal static void WriteNetworkVariableData(List networkVariableList, Stream stream, ulong clientId, NetworkManager networkManager) + internal static void WriteNetworkVariableData(List networkVariableList, Stream stream, ulong clientId, NetworkManager networkManager) { if (networkVariableList.Count == 0) { @@ -858,7 +765,7 @@ internal static void WriteNetworkVariableData(List networkVari } } - internal static void SetNetworkVariableData(List networkVariableList, Stream stream, NetworkManager networkManager) + internal static void SetNetworkVariableData(List networkVariableList, Stream stream, NetworkManager networkManager) { if (networkVariableList.Count == 0) { diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviourUpdater.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviourUpdater.cs index d38209ad0f..522c310208 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviourUpdater.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviourUpdater.cs @@ -50,9 +50,12 @@ internal void NetworkBehaviourUpdate(NetworkManager networkManager) // when client updates the server, it tells it about all its objects foreach (var sobj in networkManager.SpawnManager.SpawnedObjectsList) { - for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + if (sobj.IsOwner) { - sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); + for (int k = 0; k < sobj.ChildNetworkBehaviours.Count; k++) + { + sobj.ChildNetworkBehaviours[k].VariableUpdate(networkManager.ServerClientId); + } } } diff --git a/com.unity.netcode.gameobjects/Runtime/Core/SnapshotSystem.cs b/com.unity.netcode.gameobjects/Runtime/Core/SnapshotSystem.cs index 78cbb9f6b0..3c435752d2 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/SnapshotSystem.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/SnapshotSystem.cs @@ -558,7 +558,7 @@ internal void ProcessSingleAck(ushort ackSequence, ulong clientId, ClientData cl /// This will look into all spawned objects /// /// The key to search for - private INetworkVariable FindNetworkVar(VariableKey key) + private NetworkVariableBase FindNetworkVar(VariableKey key) { var spawnedObjects = NetworkManager.SpawnManager.SpawnedObjects; @@ -895,7 +895,7 @@ internal void Despawn(SnapshotDespawnCommand command) /// Might not happen for all variable on every frame. Might even happen more than once. /// /// The NetworkVariable to write, or rather, its INetworkVariable - internal void Store(ulong networkObjectId, int behaviourIndex, int variableIndex, INetworkVariable networkVariable) + internal void Store(ulong networkObjectId, int behaviourIndex, int variableIndex, NetworkVariableBase networkVariable) { VariableKey k; k.NetworkObjectId = networkObjectId; @@ -914,7 +914,7 @@ internal void Store(ulong networkObjectId, int behaviourIndex, int variableIndex WriteVariableToSnapshot(m_Snapshot, networkVariable, pos); } - private void WriteVariableToSnapshot(Snapshot snapshot, INetworkVariable networkVariable, int index) + private void WriteVariableToSnapshot(Snapshot snapshot, NetworkVariableBase networkVariable, int index) { // write var into buffer, possibly adjusting entry's position and Length using (var varBuffer = PooledNetworkBuffer.Get()) diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs new file mode 100644 index 0000000000..6d5c5e03f1 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs @@ -0,0 +1,52 @@ +using System; + +namespace Unity.Netcode +{ + /// + /// A ClientNetworkVariable is special in that: + /// - only the owner of the variable can write to it + /// - not even the server can write to it + /// - it is not snapshotted + /// + /// (This class may be removed in the future when integrated into NetworkVariable natively) + /// + [Serializable] + public class ClientNetworkVariable : NetworkVariable where T : unmanaged + { + public ClientNetworkVariable() { } + + public ClientNetworkVariable(NetworkVariableSettings settings) : base(settings) { } + + public override bool CanClientWrite(ulong clientId) + { + return NetworkBehaviour.OwnerClientId == clientId; + } + + public override bool ShouldWrite(ulong clientId, bool isServer) + { + return m_IsDirty && !isServer && NetworkBehaviour.IsOwner; + } + + /// + /// The value of the NetworkVariable container + /// + public override T Value + { + get => m_InternalValue; + set + { + // this could be improved. The Networking Manager is not always initialized here + // Good place to decouple network manager from the network variable + + // Also, note this is not really very water-tight, if you are running as a host + // we cannot tell if a ClientNetworkVariable write is happening inside server-ish code + if (NetworkBehaviour.NetworkManager.IsServer) + { + throw new InvalidOperationException("Server not allowed to write to ClientNetworkVariables"); + } + + Set(value); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs.meta b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs.meta similarity index 83% rename from com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs.meta rename to com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs.meta index 8ff8391fb8..85deda8734 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs.meta +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/ClientNetworkVariable.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 87f1fd4778c2dab4b8bc02c738cade25 +guid: 2eede058d58f4493ba93dc19a82131fd MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkDictionary.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkDictionary.cs index c09985ddaf..5e533124f5 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkDictionary.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkDictionary.cs @@ -10,20 +10,9 @@ namespace Unity.Netcode /// /// The type for the dictionary keys /// The type for the dictionary values - public class NetworkDictionary : IDictionary, INetworkVariable + public class NetworkDictionary : NetworkVariableBase, IDictionary where TKey : unmanaged where TValue : unmanaged { - /// - /// Gets the last time the variable was synced - /// - public NetworkTime LastSyncedTime { get; internal set; } - - /// - /// The settings for this container - /// - public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); - private readonly IDictionary m_Dictionary = new Dictionary(); - private NetworkBehaviour m_NetworkBehaviour; private readonly List> m_DirtyEvents = new List>(); /// @@ -37,7 +26,6 @@ public class NetworkDictionary : IDictionary, INetwo /// public event OnDictionaryChangedDelegate OnDictionaryChanged; - /// /// Creates a NetworkDictionary with the default value and settings /// @@ -47,19 +35,15 @@ public NetworkDictionary() { } /// Creates a NetworkDictionary with the default value and custom settings /// /// The settings to use for the NetworkDictionary - public NetworkDictionary(NetworkVariableSettings settings) - { - Settings = settings; - } + public NetworkDictionary(NetworkVariableSettings settings) : base(settings) { } /// /// Creates a NetworkDictionary with a custom value and custom settings /// /// The settings to use for the NetworkDictionary /// The initial value to use for the NetworkDictionary - public NetworkDictionary(NetworkVariableSettings settings, IDictionary value) + public NetworkDictionary(NetworkVariableSettings settings, IDictionary value) : base(settings) { - Settings = settings; m_Dictionary = value; } @@ -72,27 +56,15 @@ public NetworkDictionary(IDictionary value) m_Dictionary = value; } - /// - /// Gets or sets the name of the network variable's instance - /// (MemberInfo) where it was declared. - /// - public string Name { get; internal set; } - /// - public void ResetDirty() + public override void ResetDirty() { + base.ResetDirty(); m_DirtyEvents.Clear(); - LastSyncedTime = m_NetworkBehaviour.NetworkManager.LocalTime; - } - - /// - public NetworkChannel GetChannel() - { - return Settings.SendNetworkChannel; } /// - public void ReadDelta(Stream stream, bool keepDirtyDelta) + public override void ReadDelta(Stream stream, bool keepDirtyDelta) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -240,7 +212,7 @@ public void ReadDelta(Stream stream, bool keepDirtyDelta) } /// - public void ReadField(Stream stream) + public override void ReadField(Stream stream) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -255,12 +227,6 @@ public void ReadField(Stream stream) } } - /// - public void SetNetworkBehaviour(NetworkBehaviour behaviour) - { - m_NetworkBehaviour = behaviour; - } - /// public bool TryGetValue(TKey key, out TValue value) { @@ -268,7 +234,7 @@ public bool TryGetValue(TKey key, out TValue value) } /// - public void WriteDelta(Stream stream) + public override void WriteDelta(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -312,7 +278,7 @@ public void WriteDelta(Stream stream) } /// - public void WriteField(Stream stream) + public override void WriteField(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -326,82 +292,11 @@ public void WriteField(Stream stream) } /// - public bool CanClientWrite(ulong clientId) + public override bool IsDirty() { - switch (Settings.WritePermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.WritePermissionCallback == null) - { - return false; - } - - return Settings.WritePermissionCallback(clientId); - } - } - - return true; - } - - /// - public bool CanClientRead(ulong clientId) - { - switch (Settings.ReadPermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.ReadPermissionCallback == null) - { - return false; - } - - return Settings.ReadPermissionCallback(clientId); - } - } - - return true; + return base.IsDirty() || m_DirtyEvents.Count > 0; } - /// - public bool IsDirty() - { - if (m_DirtyEvents.Count == 0) - { - return false; - } - - if (Settings.SendTickrate == 0) - { - return true; - } - - if (Settings.SendTickrate < 0) - { - return false; - } - - if (m_NetworkBehaviour.NetworkManager.LocalTime.FixedTime - LastSyncedTime.FixedTime >= (1.0 / Settings.SendTickrate)) - { - return true; - } - - return false; - } - - /// public TValue this[TKey key] { @@ -410,10 +305,7 @@ public TValue this[TKey key] { EnsureInitialized(); - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary[key] = value; - } + m_Dictionary[key] = value; var dictionaryEvent = new NetworkDictionaryEvent() { @@ -436,17 +328,14 @@ public TValue this[TKey key] public int Count => m_Dictionary.Count; /// + // TODO: remove w/ native containers public bool IsReadOnly => m_Dictionary.IsReadOnly; /// public void Add(TKey key, TValue value) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary.Add(key, value); - } + m_Dictionary.Add(key, value); var dictionaryEvent = new NetworkDictionaryEvent() { @@ -462,11 +351,7 @@ public void Add(TKey key, TValue value) public void Add(KeyValuePair item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary.Add(item); - } + m_Dictionary.Add(item); var dictionaryEvent = new NetworkDictionaryEvent() { @@ -482,11 +367,7 @@ public void Add(KeyValuePair item) public void Clear() { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary.Clear(); - } + m_Dictionary.Clear(); var dictionaryEvent = new NetworkDictionaryEvent() { @@ -524,11 +405,7 @@ public IEnumerator> GetEnumerator() public bool Remove(TKey key) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary.Remove(key); - } + m_Dictionary.Remove(key); TValue value; m_Dictionary.TryGetValue(key, out value); @@ -550,11 +427,7 @@ public bool Remove(TKey key) public bool Remove(KeyValuePair item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Dictionary.Remove(item); - } + m_Dictionary.Remove(item); var dictionaryEvent = new NetworkDictionaryEvent() { @@ -575,19 +448,12 @@ IEnumerator IEnumerable.GetEnumerator() private void HandleAddDictionaryEvent(NetworkDictionaryEvent dictionaryEvent) { - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - if (m_NetworkBehaviour.NetworkManager.ConnectedClients.Count > 0) - { - m_DirtyEvents.Add(dictionaryEvent); - } + if (NetworkBehaviour.NetworkManager.ConnectedClients.Count > 0) + { + m_DirtyEvents.Add(dictionaryEvent); + } - OnDictionaryChanged?.Invoke(dictionaryEvent); - } - else - { - m_DirtyEvents.Add(dictionaryEvent); - } + OnDictionaryChanged?.Invoke(dictionaryEvent); } public int LastModifiedTick @@ -601,7 +467,7 @@ public int LastModifiedTick private void EnsureInitialized() { - if (m_NetworkBehaviour == null) + if (NetworkBehaviour == null) { throw new InvalidOperationException("Cannot access " + nameof(NetworkDictionary) + " before it's initialized"); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs index ad9feda01d..e19dc4eaa0 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -9,22 +9,16 @@ namespace Unity.Netcode /// Event based NetworkVariable container for syncing Lists /// /// The type for the list - public class NetworkList : IList, INetworkVariable + public class NetworkList : NetworkVariableBase, IList where T : unmanaged { private readonly IList m_List = new List(); private readonly List> m_DirtyEvents = new List>(); - private NetworkBehaviour m_NetworkBehaviour; /// /// Gets the last time the variable was synced /// public NetworkTime LastSyncedTime { get; internal set; } - /// - /// The settings for this container - /// - public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); - /// /// Delegate type for list changed event /// @@ -45,19 +39,15 @@ public NetworkList() { } /// Creates a NetworkList with the default value and custom settings /// /// The settings to use for the NetworkList - public NetworkList(NetworkVariableSettings settings) - { - Settings = settings; - } + public NetworkList(NetworkVariableSettings settings) : base(settings) { } /// /// Creates a NetworkList with a custom value and custom settings /// /// The settings to use for the NetworkList /// The initial value to use for the NetworkList - public NetworkList(NetworkVariableSettings settings, IList value) + public NetworkList(NetworkVariableSettings settings, IList value) : base(settings) { - Settings = settings; m_List = value; } @@ -70,103 +60,23 @@ public NetworkList(IList value) m_List = value; } - /// - /// Gets or sets the name of the network variable's instance - /// (MemberInfo) where it was declared. - /// - public string Name { get; internal set; } - /// - public void ResetDirty() + public override void ResetDirty() { + base.ResetDirty(); m_DirtyEvents.Clear(); - LastSyncedTime = m_NetworkBehaviour.NetworkManager.LocalTime; - } - - /// - public bool IsDirty() - { - if (m_DirtyEvents.Count == 0) - { - return false; - } - - if (Settings.SendTickrate == 0) - { - return true; - } - - if (Settings.SendTickrate < 0) - { - return false; - } - - if (m_NetworkBehaviour.NetworkManager.LocalTime.FixedTime - LastSyncedTime.FixedTime >= (1.0 / Settings.SendTickrate)) - { - return true; - } - - return false; - } - - /// - public NetworkChannel GetChannel() - { - return Settings.SendNetworkChannel; - } - - /// - public bool CanClientWrite(ulong clientId) - { - switch (Settings.WritePermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.WritePermissionCallback == null) - { - return false; - } - - return Settings.WritePermissionCallback(clientId); - } - } - - return true; + LastSyncedTime = NetworkBehaviour.NetworkManager.LocalTime; } /// - public bool CanClientRead(ulong clientId) + public override bool IsDirty() { - switch (Settings.ReadPermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.ReadPermissionCallback == null) - { - return false; - } - - return Settings.ReadPermissionCallback(clientId); - } - } - - return true; + // we call the base class to allow the SetDirty() mechanism to work + return base.IsDirty() || m_DirtyEvents.Count > 0; } /// - public void WriteDelta(Stream stream) + public override void WriteDelta(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -214,7 +124,7 @@ public void WriteDelta(Stream stream) } /// - public void WriteField(Stream stream) + public override void WriteField(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -227,7 +137,7 @@ public void WriteField(Stream stream) } /// - public void ReadField(Stream stream) + public override void ReadField(Stream stream) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -241,7 +151,7 @@ public void ReadField(Stream stream) } /// - public void ReadDelta(Stream stream, bool keepDirtyDelta) + public override void ReadDelta(Stream stream, bool keepDirtyDelta) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -413,11 +323,6 @@ public void ReadDelta(Stream stream, bool keepDirtyDelta) } } - /// - public void SetNetworkBehaviour(NetworkBehaviour behaviour) - { - m_NetworkBehaviour = behaviour; - } /// public IEnumerator GetEnumerator() @@ -434,11 +339,7 @@ IEnumerator IEnumerable.GetEnumerator() public void Add(T item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List.Add(item); - } + m_List.Add(item); var listEvent = new NetworkListEvent() { @@ -454,11 +355,7 @@ public void Add(T item) public void Clear() { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List.Clear(); - } + m_List.Clear(); var listEvent = new NetworkListEvent() { @@ -484,11 +381,7 @@ public void CopyTo(T[] array, int arrayIndex) public bool Remove(T item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List.Remove(item); - } + m_List.Remove(item); var listEvent = new NetworkListEvent() { @@ -516,11 +409,7 @@ public int IndexOf(T item) public void Insert(int index, T item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List.Insert(index, item); - } + m_List.Insert(index, item); var listEvent = new NetworkListEvent() { @@ -536,11 +425,7 @@ public void Insert(int index, T item) public void RemoveAt(int index) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List.RemoveAt(index); - } + m_List.RemoveAt(index); var listEvent = new NetworkListEvent() { @@ -559,11 +444,7 @@ public T this[int index] set { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_List[index] = value; - } + m_List[index] = value; var listEvent = new NetworkListEvent() { @@ -578,19 +459,12 @@ public T this[int index] private void HandleAddListEvent(NetworkListEvent listEvent) { - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - if (m_NetworkBehaviour.NetworkManager.ConnectedClients.Count > 0) - { - m_DirtyEvents.Add(listEvent); - } - - OnListChanged?.Invoke(listEvent); - } - else + if (NetworkBehaviour.NetworkManager.ConnectedClients.Count > 0) { m_DirtyEvents.Add(listEvent); } + + OnListChanged?.Invoke(listEvent); } public int LastModifiedTick @@ -604,7 +478,7 @@ public int LastModifiedTick private void EnsureInitialized() { - if (m_NetworkBehaviour == null) + if (NetworkBehaviour == null) { throw new InvalidOperationException("Cannot access " + nameof(NetworkList) + " before it's initialized"); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkSet.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkSet.cs index 9e0e58953f..865e8f45fc 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkSet.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkSet.cs @@ -10,22 +10,16 @@ namespace Unity.Netcode /// Event based NetworkVariable container for syncing Sets /// /// The type for the set - public class NetworkSet : ISet, INetworkVariable + public class NetworkSet : NetworkVariableBase, ISet where T: unmanaged { private readonly ISet m_Set = new HashSet(); private readonly List> m_DirtyEvents = new List>(); - private NetworkBehaviour m_NetworkBehaviour; /// /// Gets the last time the variable was synced /// public NetworkTime LastSyncedTime { get; internal set; } - /// - /// The settings for this container - /// - public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); - /// /// Delegate type for set changed event /// @@ -46,19 +40,15 @@ public NetworkSet() { } /// Creates a NetworkSet with the default value and custom settings /// /// The settings to use for the NetworkList - public NetworkSet(NetworkVariableSettings settings) - { - Settings = settings; - } + public NetworkSet(NetworkVariableSettings settings) : base(settings) { } /// /// Creates a NetworkSet with a custom value and custom settings /// /// The settings to use for the NetworkSet /// The initial value to use for the NetworkSet - public NetworkSet(NetworkVariableSettings settings, ISet value) + public NetworkSet(NetworkVariableSettings settings, ISet value) : base(settings) { - Settings = settings; m_Set = value; } @@ -71,103 +61,22 @@ public NetworkSet(ISet value) m_Set = value; } - /// - /// Gets or sets the name of the network variable's instance - /// (MemberInfo) where it was declared. - /// - public string Name { get; internal set; } - /// - public void ResetDirty() + public override void ResetDirty() { + base.ResetDirty(); m_DirtyEvents.Clear(); - LastSyncedTime = m_NetworkBehaviour.NetworkManager.LocalTime; + LastSyncedTime = NetworkBehaviour.NetworkManager.LocalTime; } /// - public bool IsDirty() + public override bool IsDirty() { - if (m_DirtyEvents.Count == 0) - { - return false; - } - - if (Settings.SendTickrate == 0) - { - return true; - } - - if (Settings.SendTickrate < 0) - { - return false; - } - - if ((m_NetworkBehaviour.NetworkManager.LocalTime.FixedTime - LastSyncedTime.FixedTime) >= (1.0 / Settings.SendTickrate)) - { - return true; - } - - return false; - } - - /// - public NetworkChannel GetChannel() - { - return Settings.SendNetworkChannel; - } - - /// - public bool CanClientWrite(ulong clientId) - { - switch (Settings.WritePermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.WritePermissionCallback == null) - { - return false; - } - - return Settings.WritePermissionCallback(clientId); - } - } - - return true; + return base.IsDirty() || m_DirtyEvents.Count > 0; } /// - public bool CanClientRead(ulong clientId) - { - switch (Settings.ReadPermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.ReadPermissionCallback == null) - { - return false; - } - - return Settings.ReadPermissionCallback(clientId); - } - } - - return true; - } - - /// - public void WriteDelta(Stream stream) + public override void WriteDelta(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -199,7 +108,7 @@ public void WriteDelta(Stream stream) } /// - public void WriteField(Stream stream) + public override void WriteField(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -213,7 +122,7 @@ public void WriteField(Stream stream) } /// - public void ReadField(Stream stream) + public override void ReadField(Stream stream) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -228,7 +137,7 @@ public void ReadField(Stream stream) } /// - public void ReadDelta(Stream stream, bool keepDirtyDelta) + public override void ReadDelta(Stream stream, bool keepDirtyDelta) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -313,12 +222,6 @@ public void ReadDelta(Stream stream, bool keepDirtyDelta) } } - /// - public void SetNetworkBehaviour(NetworkBehaviour behaviour) - { - m_NetworkBehaviour = behaviour; - } - /// public IEnumerator GetEnumerator() { @@ -406,10 +309,7 @@ public void SymmetricExceptWith(IEnumerable other) } else { - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Set.Add(value); - } + m_Set.Add(value); var setEvent = new NetworkSetEvent() { @@ -418,7 +318,7 @@ public void SymmetricExceptWith(IEnumerable other) }; m_DirtyEvents.Add(setEvent); - if (m_NetworkBehaviour.NetworkManager.IsServer && OnSetChanged != null) + if (OnSetChanged != null) { OnSetChanged(setEvent); } @@ -435,10 +335,7 @@ public void UnionWith(IEnumerable other) { if (!m_Set.Contains(value)) { - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Set.Add(value); - } + m_Set.Add(value); var setEvent = new NetworkSetEvent() { @@ -447,7 +344,7 @@ public void UnionWith(IEnumerable other) }; m_DirtyEvents.Add(setEvent); - if (m_NetworkBehaviour.NetworkManager.IsServer && OnSetChanged != null) + if (OnSetChanged != null) { OnSetChanged(setEvent); } @@ -455,14 +352,10 @@ public void UnionWith(IEnumerable other) } } - public void Add(T item) + public bool Add(T item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Set.Add(item); - } + m_Set.Add(item); var setEvent = new NetworkSetEvent() { @@ -471,34 +364,22 @@ public void Add(T item) }; m_DirtyEvents.Add(setEvent); - if (m_NetworkBehaviour.NetworkManager.IsServer && OnSetChanged != null) + if (OnSetChanged != null) { OnSetChanged(setEvent); } - } - /// - bool ISet.Add(T item) - { - Add(item); return true; } /// - void ICollection.Add(T item) - { - Add(item); - } + void ICollection.Add(T item) => Add(item); /// public void Clear() { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Set.Clear(); - } + m_Set.Clear(); var setEvent = new NetworkSetEvent() { @@ -506,7 +387,7 @@ public void Clear() }; m_DirtyEvents.Add(setEvent); - if (m_NetworkBehaviour.NetworkManager.IsServer && OnSetChanged != null) + if (OnSetChanged != null) { OnSetChanged(setEvent); } @@ -528,11 +409,7 @@ public void CopyTo(T[] array, int arrayIndex) public bool Remove(T item) { EnsureInitialized(); - - if (m_NetworkBehaviour.NetworkManager.IsServer) - { - m_Set.Remove(item); - } + m_Set.Remove(item); var setEvent = new NetworkSetEvent() { @@ -541,7 +418,7 @@ public bool Remove(T item) }; m_DirtyEvents.Add(setEvent); - if (m_NetworkBehaviour.NetworkManager.IsServer && OnSetChanged != null) + if (OnSetChanged != null) { OnSetChanged(setEvent); } @@ -566,7 +443,7 @@ public int LastModifiedTick private void EnsureInitialized() { - if (m_NetworkBehaviour == null) + if (NetworkBehaviour == null) { throw new InvalidOperationException("Cannot access " + nameof(NetworkSet) + " before it's initialized"); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs index 57f082da62..77399a636e 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs @@ -9,13 +9,8 @@ namespace Unity.Netcode /// A variable that can be synchronized over the network. /// [Serializable] - public class NetworkVariable : INetworkVariable + public class NetworkVariable : NetworkVariableBase where T : unmanaged { - /// - /// The settings for this var - /// - public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); - /// /// Delegate type for value changed event /// @@ -27,8 +22,6 @@ public class NetworkVariable : INetworkVariable /// public OnValueChangedDelegate OnValueChanged; - private NetworkBehaviour m_NetworkBehaviour; - /// /// Creates a NetworkVariable with the default value and settings /// @@ -38,19 +31,15 @@ public NetworkVariable() { } /// Creates a NetworkVariable with the default value and custom settings /// /// The settings to use for the NetworkVariable - public NetworkVariable(NetworkVariableSettings settings) - { - Settings = settings; - } + public NetworkVariable(NetworkVariableSettings settings) : base(settings) { } /// /// Creates a NetworkVariable with a custom value and custom settings /// /// The settings to use for the NetworkVariable /// The initial value to use for the NetworkVariable - public NetworkVariable(NetworkVariableSettings settings, T value) + public NetworkVariable(NetworkVariableSettings settings, T value) : base(settings) { - Settings = settings; m_InternalValue = value; } @@ -64,7 +53,7 @@ public NetworkVariable(T value) } [SerializeField] - private T m_InternalValue; + private protected T m_InternalValue; /// /// The temporary accessor to enable struct element access until [MTT-1020] complete @@ -77,115 +66,52 @@ public ref T ValueRef /// /// The value of the NetworkVariable container /// - public T Value + public virtual T Value { get => m_InternalValue; set { - if (EqualityComparer.Default.Equals(m_InternalValue, value)) + // this could be improved. The Networking Manager is not always initialized here + // Good place to decouple network manager from the network variable + + // Also, note this is not really very water-tight, if you are running as a host + // we cannot tell if a NetworkVariable write is happening inside client-ish code + if (NetworkBehaviour && (NetworkBehaviour.NetworkManager.IsClient && !NetworkBehaviour.NetworkManager.IsHost)) { - return; + throw new InvalidOperationException("Client can't write to NetworkVariables"); } - - m_IsDirty = true; - T previousValue = m_InternalValue; - m_InternalValue = value; - OnValueChanged?.Invoke(previousValue, m_InternalValue); + Set(value); } } - private bool m_IsDirty = false; - - /// - /// Gets or sets the name of the network variable's instance - /// (MemberInfo) where it was declared. - /// - public string Name { get; internal set; } - - /// - /// Sets whether or not the variable needs to be delta synced - /// - public void SetDirty(bool isDirty) - { - m_IsDirty = isDirty; - } - - /// - public bool IsDirty() - { - return m_IsDirty; - } - - /// - public void ResetDirty() + private protected void Set(T value) { - m_IsDirty = false; - } - - /// - public bool CanClientRead(ulong clientId) - { - switch (Settings.ReadPermission) + if (EqualityComparer.Default.Equals(m_InternalValue, value)) { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.ReadPermissionCallback == null) - { - return false; - } - - return Settings.ReadPermissionCallback(clientId); - } + return; } - return true; + + m_IsDirty = true; + T previousValue = m_InternalValue; + m_InternalValue = value; + OnValueChanged?.Invoke(previousValue, m_InternalValue); } /// /// Writes the variable to the writer /// /// The stream to write the value to - public void WriteDelta(Stream stream) + public override void WriteDelta(Stream stream) { WriteField(stream); } - /// - public bool CanClientWrite(ulong clientId) - { - switch (Settings.WritePermission) - { - case NetworkVariablePermission.Everyone: - return true; - case NetworkVariablePermission.ServerOnly: - return false; - case NetworkVariablePermission.OwnerOnly: - return m_NetworkBehaviour.OwnerClientId == clientId; - case NetworkVariablePermission.Custom: - { - if (Settings.WritePermissionCallback == null) - { - return false; - } - - return Settings.WritePermissionCallback(clientId); - } - } - - return true; - } - /// /// Reads value from the reader and applies it /// /// The stream to read the value from /// Whether or not the container should keep the dirty delta, or mark the delta as consumed - public void ReadDelta(Stream stream, bool keepDirtyDelta) + public override void ReadDelta(Stream stream, bool keepDirtyDelta) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -202,50 +128,19 @@ public void ReadDelta(Stream stream, bool keepDirtyDelta) } /// - public void SetNetworkBehaviour(NetworkBehaviour behaviour) - { - m_NetworkBehaviour = behaviour; - } - - /// - public void ReadField(Stream stream) + public override void ReadField(Stream stream) { ReadDelta(stream, false); } /// - public void WriteField(Stream stream) + public override void WriteField(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { writer.WriteObjectPacked(m_InternalValue); //BOX } } - - /// - public NetworkChannel GetChannel() - { - return Settings.SendNetworkChannel; - } - } - - /// - /// A NetworkVariable that holds strings and support serialization - /// - [Serializable] - public class NetworkVariableString : NetworkVariable - { - /// - public NetworkVariableString() : base(string.Empty) { } - - /// - public NetworkVariableString(NetworkVariableSettings settings) : base(settings, string.Empty) { } - - /// - public NetworkVariableString(string value) : base(value) { } - - /// - public NetworkVariableString(NetworkVariableSettings settings, string value) : base(settings, value) { } } /// diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs similarity index 53% rename from com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs rename to com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs index 338aab906b..119dd88aa5 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/INetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -5,56 +5,105 @@ namespace Unity.Netcode /// /// Interface for network value containers /// - public interface INetworkVariable + public abstract class NetworkVariableBase { + /// + /// The name of the channel to be used for syncing + /// + public const NetworkChannel NetworkVariableChannel = NetworkChannel.NetworkVariable; + + protected NetworkVariableBase() { } + + protected NetworkVariableBase(NetworkVariableSettings settings) + { + Settings = settings; + } + + // demolish me + // or better setter? + internal protected NetworkBehaviour NetworkBehaviour { get; internal set; } + + private protected bool m_IsDirty = false; + /// /// Gets or sets the name of the network variable's instance /// (MemberInfo) where it was declared. /// - string Name { get; } + public string Name { get; internal set; } + + /// + /// The settings for this var + /// + public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); /// - /// Returns the name of the channel to be used for syncing + /// Sets whether or not the variable needs to be delta synced /// - /// The name of the channel to be used for syncing - NetworkChannel GetChannel(); + public virtual void SetDirty(bool isDirty) + { + m_IsDirty = isDirty; + } /// /// Resets the dirty state and marks the variable as synced / clean /// - void ResetDirty(); + public virtual void ResetDirty() + { + m_IsDirty = false; + } /// /// Gets Whether or not the container is dirty /// /// Whether or not the container is dirty - bool IsDirty(); + public virtual bool IsDirty() + { + return m_IsDirty; + } + + public virtual bool ShouldWrite(ulong clientId, bool isServer) + { + return IsDirty() && isServer && CanClientRead(clientId); + } /// - /// Gets Whether or not a specific client can write to the varaible + /// Gets Whether or not a specific client can read to the varaible /// /// The clientId of the remote client - /// Whether or not the client can write to the variable - bool CanClientWrite(ulong clientId); + /// Whether or not the client can read to the variable + public bool CanClientRead(ulong clientId) + { + switch (Settings.ReadPermission) + { + case NetworkVariableReadPermission.Everyone: + return true; + case NetworkVariableReadPermission.OwnerOnly: + return NetworkBehaviour.OwnerClientId == clientId; + } + return true; + } /// /// Gets Whether or not a specific client can read to the varaible /// /// The clientId of the remote client /// Whether or not the client can read to the variable - bool CanClientRead(ulong clientId); + public virtual bool CanClientWrite(ulong clientId) + { + return false; + } /// /// Writes the dirty changes, that is, the changes since the variable was last dirty, to the writer /// /// The stream to write the dirty changes to - void WriteDelta(Stream stream); + public abstract void WriteDelta(Stream stream); /// /// Writes the complete state of the variable to the writer /// /// The stream to write the state to - void WriteField(Stream stream); + public abstract void WriteField(Stream stream); /// /// Reads the complete state from the reader and applies it @@ -62,7 +111,7 @@ public interface INetworkVariable /// The stream to read the state from /// The local network tick at which this var was written, on the machine it was written /// The remote network tick at which this var was sent by the host - void ReadField(Stream stream); + public abstract void ReadField(Stream stream); /// /// Reads delta from the reader and applies them to the internal value @@ -71,12 +120,6 @@ public interface INetworkVariable /// Whether or not the delta should be kept as dirty or consumed /// The local network tick at which this var was written, on the machine it was written /// The remote network tick at which this var was sent by the host - void ReadDelta(Stream stream, bool keepDirtyDelta); - - /// - /// Sets NetworkBehaviour the container belongs to. - /// - /// The behaviour the container behaves to - void SetNetworkBehaviour(NetworkBehaviour behaviour); + public abstract void ReadDelta(Stream stream, bool keepDirtyDelta); } } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs.meta b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs.meta new file mode 100644 index 0000000000..ef85502152 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f45dec3ed9b6942d889ef48036aba763 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs index 3773bb9ba9..df2456f7e2 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs @@ -3,26 +3,16 @@ namespace Unity.Netcode /// /// Permission type /// - public enum NetworkVariablePermission + public enum NetworkVariableReadPermission { /// /// Everyone /// Everyone, - /// - /// Server-only operation - /// - ServerOnly, - /// /// Owner-ownly /// OwnerOnly, - - /// - /// Custom delegate - /// - Custom } } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableSettings.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableSettings.cs index 84ed8ac663..8bedabe0e3 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableSettings.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableSettings.cs @@ -11,38 +11,9 @@ namespace Unity.Netcode /// public class NetworkVariableSettings { - /// - /// Defines the write permissions for this var - /// - public NetworkVariablePermission WritePermission = NetworkVariablePermission.ServerOnly; /// /// Defines the read permissions for this var /// - public NetworkVariablePermission ReadPermission = NetworkVariablePermission.Everyone; - /// - /// The delegate used to evaluate write permission when the "Custom" mode is used - /// - public NetworkVariablePermissionsDelegate WritePermissionCallback = null; - /// - /// The delegate used to evaluate read permission when the "Custom" mode is used - /// - public NetworkVariablePermissionsDelegate ReadPermissionCallback = null; - /// - /// The maximum times per second this var will be synced. - /// A value of 0 will cause the variable to sync as soon as possible after being changed. - /// A value of less than 0 will cause the variable to sync only at once at spawn and not update again. - /// - public double SendTickrate = 0; - - /// - /// The name of the channel to use for this variable. - /// Variables with different channels will be split into different packets - /// - public NetworkChannel SendNetworkChannel = NetworkChannel.NetworkVariable; - - /// - /// Constructs a new NetworkVariableSettings instance - /// - public NetworkVariableSettings() { } + public NetworkVariableReadPermission ReadPermission = NetworkVariableReadPermission.Everyone; } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Components/NetworkVariableTestComponent.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Components/NetworkVariableTestComponent.cs index 639534455b..446918684c 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Components/NetworkVariableTestComponent.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Components/NetworkVariableTestComponent.cs @@ -22,7 +22,6 @@ internal class NetworkVariableTestComponent : NetworkBehaviour private NetworkVariableSByte m_NetworkVariableSByte; private NetworkVariableQuaternion m_NetworkVariableQuaternion; private NetworkVariableShort m_NetworkVariableShort; - private NetworkVariableString m_NetworkVariableString; private NetworkVariableVector4 m_NetworkVariableVector4; private NetworkVariableVector3 m_NetworkVariableVector3; private NetworkVariableVector2 m_NetworkVariableVector2; @@ -43,7 +42,6 @@ internal class NetworkVariableTestComponent : NetworkBehaviour public NetworkVariableHelper Sbyte_Var; public NetworkVariableHelper Quaternion_Var; public NetworkVariableHelper Short_Var; - public NetworkVariableHelper String_Var; public NetworkVariableHelper Vector4_Var; public NetworkVariableHelper Vector3_Var; public NetworkVariableHelper Vector2_Var; @@ -75,7 +73,6 @@ private void InitializeTest() m_NetworkVariableSByte = new NetworkVariableSByte(); m_NetworkVariableQuaternion = new NetworkVariableQuaternion(); m_NetworkVariableShort = new NetworkVariableShort(); - m_NetworkVariableString = new NetworkVariableString(); m_NetworkVariableVector4 = new NetworkVariableVector4(); m_NetworkVariableVector3 = new NetworkVariableVector3(); m_NetworkVariableVector2 = new NetworkVariableVector2(); @@ -97,7 +94,6 @@ private void InitializeTest() m_NetworkVariableSByte = new NetworkVariableSByte(0); m_NetworkVariableQuaternion = new NetworkVariableQuaternion(Quaternion.identity); m_NetworkVariableShort = new NetworkVariableShort(256); - m_NetworkVariableString = new NetworkVariableString("My String Value"); m_NetworkVariableVector4 = new NetworkVariableVector4(new Vector4(1, 1, 1, 1)); m_NetworkVariableVector3 = new NetworkVariableVector3(new Vector3(1, 1, 1)); m_NetworkVariableVector2 = new NetworkVariableVector2(new Vector2(1, 1)); @@ -109,8 +105,7 @@ private void InitializeTest() // NetworkVariable NetworkVariableSettings Constructor Test Coverage var settings = new NetworkVariableSettings(); - settings.ReadPermission = NetworkVariablePermission.ServerOnly; - settings.WritePermission = NetworkVariablePermission.ServerOnly; + settings.ReadPermission = NetworkVariableReadPermission.Everyone; m_NetworkVariableBool = new NetworkVariableBool(settings); m_NetworkVariableByte = new NetworkVariableByte(settings); m_NetworkVariableColor = new NetworkVariableColor(settings); @@ -122,7 +117,6 @@ private void InitializeTest() m_NetworkVariableSByte = new NetworkVariableSByte(settings); m_NetworkVariableQuaternion = new NetworkVariableQuaternion(settings); m_NetworkVariableShort = new NetworkVariableShort(settings); - m_NetworkVariableString = new NetworkVariableString(settings); m_NetworkVariableVector4 = new NetworkVariableVector4(settings); m_NetworkVariableVector3 = new NetworkVariableVector3(settings); m_NetworkVariableVector2 = new NetworkVariableVector2(settings); @@ -132,7 +126,6 @@ private void InitializeTest() m_NetworkVariableUShort = new NetworkVariableUShort(settings); - // NetworkVariable Value Type and NetworkVariableSettings Constructor Test Coverage m_NetworkVariableBool = new NetworkVariableBool(settings, true); m_NetworkVariableByte = new NetworkVariableByte(settings, 0); @@ -145,7 +138,6 @@ private void InitializeTest() m_NetworkVariableSByte = new NetworkVariableSByte(settings, 0); m_NetworkVariableQuaternion = new NetworkVariableQuaternion(settings, Quaternion.identity); m_NetworkVariableShort = new NetworkVariableShort(settings, 1); - m_NetworkVariableString = new NetworkVariableString(settings, "My String Value"); m_NetworkVariableVector4 = new NetworkVariableVector4(settings, new Vector4(1, 1, 1, 1)); m_NetworkVariableVector3 = new NetworkVariableVector3(settings, new Vector3(1, 1, 1)); m_NetworkVariableVector2 = new NetworkVariableVector2(settings, new Vector2(1, 1)); @@ -169,7 +161,6 @@ private void InitializeTest() Sbyte_Var = new NetworkVariableHelper(m_NetworkVariableSByte); Quaternion_Var = new NetworkVariableHelper(m_NetworkVariableQuaternion); Short_Var = new NetworkVariableHelper(m_NetworkVariableShort); - String_Var = new NetworkVariableHelper(m_NetworkVariableString); Vector4_Var = new NetworkVariableHelper(m_NetworkVariableVector4); Vector3_Var = new NetworkVariableHelper(m_NetworkVariableVector3); Vector2_Var = new NetworkVariableHelper(m_NetworkVariableVector2); @@ -185,7 +176,7 @@ private void InitializeTest() /// public bool DidAllValuesChange() { - if (BaseNetworkVariableHelper.VarChangedCount == BaseNetworkVariableHelper.InstanceCount) + if (NetworkVariableBaseHelper.VarChangedCount == NetworkVariableBaseHelper.InstanceCount) { return true; } @@ -238,7 +229,6 @@ private void Update() m_NetworkVariableSByte.Value = -127; m_NetworkVariableQuaternion.Value = new Quaternion(100, 100, 100, 100); m_NetworkVariableShort.Value = short.MaxValue; - m_NetworkVariableString.Value = "My Changed String Value"; m_NetworkVariableVector4.Value = new Vector4(1000, 1000, 1000, 1000); m_NetworkVariableVector3.Value = new Vector3(1000, 1000, 1000); m_NetworkVariableVector2.Value = new Vector2(1000, 1000); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkVariableHelper.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkVariableHelper.cs index b6d56486b3..2b3a16ab98 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkVariableHelper.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Helpers/NetworkVariableHelper.cs @@ -13,13 +13,12 @@ namespace Unity.Netcode.RuntimeTests /// From both we can then at least determine if the value indeed changed /// /// - internal class NetworkVariableHelper : BaseNetworkVariableHelper + internal class NetworkVariableHelper : NetworkVariableBaseHelper where T : unmanaged { - private NetworkVariable m_NetworkVariable; + private readonly NetworkVariable m_NetworkVariable; public delegate void OnMyValueChangedDelegateHandler(T previous, T next); public event OnMyValueChangedDelegateHandler OnValueChanged; - /// /// IEquatable Equals Check /// @@ -49,10 +48,9 @@ private void CheckVariableChanged(ValueType previous, ValueType next) /// private void OnVariableChanged(T previous, T next) { - var testValueType = previous as ValueType; - if (testValueType != null) + if (previous is ValueType testValueType) { - CheckVariableChanged(previous as ValueType, next as ValueType); + CheckVariableChanged(previous, next); } else { @@ -62,7 +60,7 @@ private void OnVariableChanged(T previous, T next) OnValueChanged?.Invoke(previous, next); } - public NetworkVariableHelper(INetworkVariable networkVariable) : base(networkVariable) + public NetworkVariableHelper(NetworkVariableBase networkVariable) : base(networkVariable) { m_NetworkVariable = networkVariable as NetworkVariable; m_NetworkVariable.OnValueChanged = OnVariableChanged; @@ -75,10 +73,10 @@ public NetworkVariableHelper(INetworkVariable networkVariable) : base(networkVar /// The number of times a specific NetworkVariable instance had its value changed (i.e. !Equal) /// Note: This could be expanded for future tests focuses around NetworkVariables /// - internal class BaseNetworkVariableHelper + internal class NetworkVariableBaseHelper { - private static Dictionary s_Instances; - private static Dictionary s_InstanceChangedCount; + private static Dictionary s_Instances; + private static Dictionary s_InstanceChangedCount; /// /// Returns the total number of registered INetworkVariables @@ -129,16 +127,16 @@ protected void ValueChanged() } } - public BaseNetworkVariableHelper(INetworkVariable networkVariable) + public NetworkVariableBaseHelper(NetworkVariableBase networkVariable) { if (s_Instances == null) { - s_Instances = new Dictionary(); + s_Instances = new Dictionary(); } if (s_InstanceChangedCount == null) { - s_InstanceChangedCount = new Dictionary(); + s_InstanceChangedCount = new Dictionary(); } // Register new instance and associated INetworkVariable diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/Utility/NetworkVariableComponent.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/Utility/NetworkVariableComponent.cs index f4eb14db88..c61f4c0845 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/Utility/NetworkVariableComponent.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/Utility/NetworkVariableComponent.cs @@ -1,17 +1,17 @@ #if MULTIPLAYER_TOOLS -using System; +using UnityEngine; namespace Unity.Netcode.RuntimeTests.Metrics.Utlity { public class NetworkVariableComponent : NetworkBehaviour { - public NetworkVariableString MyNetworkVariable { get; } = new NetworkVariableString(); + public NetworkVariable MyNetworkVariable { get; } = new NetworkVariable(); - void Update() + private void Update() { if (IsServer) { - MyNetworkVariable.Value = Guid.NewGuid().ToString(); + MyNetworkVariable.Value = Random.Range(100, 999); } } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta index 9103284456..d5b272620d 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformTests.cs.meta @@ -1,3 +1,3 @@ -fileFormatVersion: 2 +fileFormatVersion: 2 guid: cf4ff0d6357bb4474a404b9ce52b22ad timeCreated: 1620872927 \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVarBufferCopyTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVarBufferCopyTest.cs index 42ddc12774..879bcd5ec2 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVarBufferCopyTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVarBufferCopyTest.cs @@ -7,7 +7,7 @@ namespace Unity.Netcode.RuntimeTests { public class NetworkVarBufferCopyTest : BaseMultiInstanceTest { - public class DummyNetVar : INetworkVariable + public class DummyNetVar : NetworkVariableBase { private const int k_DummyValue = 0x13579BDF; public bool DeltaWritten; @@ -16,34 +16,17 @@ public class DummyNetVar : INetworkVariable public bool FieldRead; public bool Dirty = true; - public string Name { get; internal set; } - - public NetworkChannel GetChannel() - { - return NetworkChannel.NetworkVariable; - } - - public void ResetDirty() + public override void ResetDirty() { Dirty = false; } - public bool IsDirty() + public override bool IsDirty() { return Dirty; } - public bool CanClientWrite(ulong clientId) - { - return true; - } - - public bool CanClientRead(ulong clientId) - { - return true; - } - - public void WriteDelta(Stream stream) + public override void WriteDelta(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -54,7 +37,7 @@ public void WriteDelta(Stream stream) DeltaWritten = true; } - public void WriteField(Stream stream) + public override void WriteField(Stream stream) { using (var writer = PooledNetworkWriter.Get(stream)) { @@ -65,7 +48,7 @@ public void WriteField(Stream stream) FieldWritten = true; } - public void ReadField(Stream stream) + public override void ReadField(Stream stream) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -76,7 +59,7 @@ public void ReadField(Stream stream) FieldRead = true; } - public void ReadDelta(Stream stream, bool keepDirtyDelta) + public override void ReadDelta(Stream stream, bool keepDirtyDelta) { using (var reader = PooledNetworkReader.Get(stream)) { @@ -86,11 +69,6 @@ public void ReadDelta(Stream stream, bool keepDirtyDelta) DeltaRead = true; } - - public void SetNetworkBehaviour(NetworkBehaviour behaviour) - { - // nop - } } public class DummyNetBehaviour : NetworkBehaviour diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs index 660eb65c9a..60a5f0e3be 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariableTests.cs @@ -17,45 +17,33 @@ public void NetworkSerialize(NetworkSerializer serializer) serializer.Serialize(ref SomeBool); } } - - public class TestClass : INetworkSerializable - { - public uint SomeInt; - public bool SomeBool; - - public void NetworkSerialize(NetworkSerializer serializer) - { - serializer.Serialize(ref SomeInt); - serializer.Serialize(ref SomeBool); - } - } - public class NetworkVariableTest : NetworkBehaviour { - public readonly NetworkList TheList = new NetworkList( - new NetworkVariableSettings { WritePermission = NetworkVariablePermission.ServerOnly } - ); + public readonly ClientNetworkVariable ClientVar = new ClientNetworkVariable(); - public readonly NetworkSet TheSet = new NetworkSet( - new NetworkVariableSettings { WritePermission = NetworkVariablePermission.ServerOnly } - ); + public readonly ClientNetworkVariable ClientVarPrivate = + new ClientNetworkVariable(new NetworkVariableSettings { ReadPermission = NetworkVariableReadPermission.OwnerOnly }); - public readonly NetworkDictionary TheDictionary = new NetworkDictionary( - new NetworkVariableSettings { WritePermission = NetworkVariablePermission.ServerOnly } - ); + public readonly NetworkVariable TheScalar = new NetworkVariable(); + public readonly NetworkList TheList = new NetworkList(); + public readonly NetworkSet TheSet = new NetworkSet(); + public readonly NetworkDictionary TheDictionary = new NetworkDictionary(); private void ListChanged(NetworkListEvent e) { ListDelegateTriggered = true; } + private void SetChanged(NetworkSetEvent e) { SetDelegateTriggered = true; } + private void DictionaryChanged(NetworkDictionaryEvent e) { DictionaryDelegateTriggered = true; } + public void Awake() { TheList.OnListChanged += ListChanged; @@ -64,387 +52,480 @@ public void Awake() } public readonly NetworkVariable TheStruct = new NetworkVariable(); - public readonly NetworkVariable TheClass = new NetworkVariable(new TestClass()); public bool ListDelegateTriggered; public bool SetDelegateTriggered; public bool DictionaryDelegateTriggered; } - namespace Unity.Netcode.RuntimeTests + public class NetworkVariableTests : BaseMultiInstanceTest { - public class NetworkVariableTests : BaseMultiInstanceTest + protected override int NbClients => 2; + + private const uint k_TestUInt = 0x12345678; + + private const int k_TestVal1 = 111; + private const int k_TestVal2 = 222; + private const int k_TestVal3 = 333; + + private const int k_TestKey1 = 0x0f0f; + private const int k_TestKey2 = 0xf0f0; + + // Player1 component on the server + private NetworkVariableTest m_Player1OnServer; + + // Player2 component on the server + private NetworkVariableTest m_Player2OnServer; + + // Player1 component on client1 + private NetworkVariableTest m_Player1OnClient1; + + // Player2 component on client1 + private NetworkVariableTest m_Player1OnClient2; + + // client2's version of client1's player object + private NetworkVariableTest m_Player1FromClient2; + + private bool m_TestWithHost; + + [UnitySetUp] + public override IEnumerator Setup() { - protected override int NbClients => 1; + yield return StartSomeClientsAndServerWithPlayers(useHost: m_TestWithHost, nbClients: NbClients, + updatePlayerPrefab: playerPrefab => + { + var networkTransform = playerPrefab.AddComponent(); + }); + + // These are the *SERVER VERSIONS* of the *CLIENT PLAYER 1 & 2* + var result = new MultiInstanceHelpers.CoroutineResultWrapper(); + + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( + x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, + m_ServerNetworkManager, result)); + m_Player1OnServer = result.Result.GetComponent(); - private const uint k_TestUInt = 0xdeadbeef; + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( + x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[1].LocalClientId, + m_ServerNetworkManager, result)); + m_Player2OnServer = result.Result.GetComponent(); - private const int k_TestVal1 = 111; - private const int k_TestVal2 = 222; - private const int k_TestVal3 = 333; + // This is client1's view of itself + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( + x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, + m_ClientNetworkManagers[0], result)); - private const int k_TestKey1 = 0x0f0f; - private const int k_TestKey2 = 0xf0f0; + m_Player1OnClient1 = result.Result.GetComponent(); - private NetworkVariableTest m_ServerComp; - private NetworkVariableTest m_ClientComp; + // This is client2's view of itself + result = new MultiInstanceHelpers.CoroutineResultWrapper(); + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( + x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[1].LocalClientId, + m_ClientNetworkManagers[1], result)); - private readonly bool m_TestWithHost = false; + m_Player1OnClient2 = result.Result.GetComponent(); - [UnitySetUp] - public override IEnumerator Setup() + // This is client2's view of client 1's object + yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( + x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, + m_ClientNetworkManagers[1], result)); + + // var client2client1 = result.Result; + m_Player1FromClient2 = result.Result.GetComponent(); + + m_Player1OnServer.TheList.Clear(); + m_Player1OnServer.TheSet.Clear(); + m_Player1OnServer.TheDictionary.Clear(); + + if (m_Player1OnServer.TheList.Count > 0 || m_Player1OnServer.TheSet.Count > 0 || m_Player1OnServer.TheDictionary.Count > 0) + { + throw new Exception("at least one server network container not empty at start"); + } + if (m_Player1OnClient1.TheList.Count > 0 || m_Player1OnClient1.TheSet.Count > 0 || m_Player1OnClient1.TheDictionary.Count > 0) { - yield return StartSomeClientsAndServerWithPlayers(useHost: m_TestWithHost, nbClients: NbClients, - updatePlayerPrefab: playerPrefab => - { - var networkTransform = playerPrefab.AddComponent(); - }); + throw new Exception("at least one client network container not empty at start"); + } + } + + /// + /// Runs generalized tests on all predefined NetworkVariable types + /// + [UnityTest] + public IEnumerator AllNetworkVariableTypes([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - // This is the *SERVER VERSION* of the *CLIENT PLAYER* - var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); + // Create, instantiate, and host + // This would normally go in Setup, but since every other test but this one + // uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown, + // for now we put this within this one test until we migrate it to MIH + Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _)); - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ServerNetworkManager, serverClientPlayerResult)); + Guid gameObjectId = NetworkManagerHelper.AddGameNetworkObject("NetworkVariableTestComponent"); - // This is the *CLIENT VERSION* of the *CLIENT PLAYER* - var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper(); - yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation( - x => x.IsPlayerObject && x.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId, - m_ClientNetworkManagers[0], clientClientPlayerResult)); + var networkVariableTestComponent = NetworkManagerHelper.AddComponentToObject(gameObjectId); - var serverSideClientPlayer = serverClientPlayerResult.Result; - var clientSideClientPlayer = clientClientPlayerResult.Result; + NetworkManagerHelper.SpawnNetworkObject(gameObjectId); - m_ServerComp = serverSideClientPlayer.GetComponent(); - m_ClientComp = clientSideClientPlayer.GetComponent(); + // Start Testing + networkVariableTestComponent.EnableTesting = true; - m_ServerComp.TheList.Clear(); - m_ServerComp.TheSet.Clear(); - m_ServerComp.TheDictionary.Clear(); + var testsAreComplete = networkVariableTestComponent.IsTestComplete(); - if (m_ServerComp.TheList.Count > 0 || m_ServerComp.TheSet.Count > 0 || m_ServerComp.TheDictionary.Count > 0) + // Wait for the NetworkVariable tests to complete + while (!testsAreComplete) + { + yield return new WaitForSeconds(0.003f); + testsAreComplete = networkVariableTestComponent.IsTestComplete(); + } + + // Stop Testing + networkVariableTestComponent.EnableTesting = false; + + Assert.IsTrue(networkVariableTestComponent.DidAllValuesChange()); + + // Disable this once we are done. + networkVariableTestComponent.gameObject.SetActive(false); + + Assert.IsTrue(testsAreComplete); + + // This would normally go in Teardown, but since every other test but this one + // uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown, + // for now we put this within this one test until we migrate it to MIH + NetworkManagerHelper.ShutdownNetworkManager(); + } + + [Test] + public void ClientWritePermissionTest([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + + // client must not be allowed to write to a server auth variable + Assert.Throws(() => m_Player1OnClient1.TheScalar.Value = k_TestVal1); + } + + [Test] + public void ServerWritePermissionTest([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + + // server must not be allowed to write to a client auth variable + Assert.Throws(() => m_Player1OnServer.ClientVar.Value = k_TestVal1); + } + + [UnityTest] + public IEnumerator ClientTest([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnClient1.ClientVar.Value = k_TestVal2; + m_Player1OnClient2.ClientVar.Value = k_TestVal3; + }, + () => { - throw new Exception("at least one server network container not empty at start"); + // the client's values should win on the objects it owns + return + m_Player1OnServer.ClientVar.Value == k_TestVal2 && + m_Player2OnServer.ClientVar.Value == k_TestVal3 && + m_Player1OnClient1.ClientVar.Value == k_TestVal2 && + m_Player1OnClient2.ClientVar.Value == k_TestVal3; } - if (m_ClientComp.TheList.Count > 0 || m_ClientComp.TheSet.Count > 0 || m_ClientComp.TheDictionary.Count > 0) + ); + } + + [UnityTest] + public IEnumerator PrivateClientTest([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + // we are writing to the private and public variables on player 1's object... + m_Player1OnClient1.ClientVarPrivate.Value = k_TestVal1; + m_Player1OnClient1.ClientVar.Value = k_TestVal2; + }, + () => { - throw new Exception("at least one client network container not empty at start"); + // ...and we should see the writes to the private var only on the server & the owner, + // but the public variable everywhere + return + m_Player1FromClient2.ClientVarPrivate.Value != k_TestVal1 && + m_Player1OnClient1.ClientVarPrivate.Value == k_TestVal1 && + m_Player1FromClient2.ClientVar.Value != k_TestVal2 && + m_Player1OnClient1.ClientVar.Value == k_TestVal2 && + m_Player1OnServer.ClientVarPrivate.Value == k_TestVal1 && + m_Player1OnServer.ClientVar.Value == k_TestVal2; } - } + ); + } - /// - /// Runs generalized tests on all predefined NetworkVariable types - /// - [UnityTest] - public IEnumerator AllNetworkVariableTypes() - { - // Create, instantiate, and host - // This would normally go in Setup, but since every other test but this one - // uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown, - // for now we put this within this one test until we migrate it to MIH - Assert.IsTrue(NetworkManagerHelper.StartNetworkManager(out _)); + [UnityTest] + public IEnumerator NetworkListAdd([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheList.Add(k_TestVal1); + m_Player1OnServer.TheList.Add(k_TestVal2); + }, + () => + { + return m_Player1OnServer.TheList.Count == 2 && + m_Player1OnClient1.TheList.Count == 2 && + m_Player1OnServer.ListDelegateTriggered && + m_Player1OnClient1.ListDelegateTriggered && + m_Player1OnServer.TheList[0] == k_TestVal1 && + m_Player1OnClient1.TheList[0] == k_TestVal1 && + m_Player1OnServer.TheList[1] == k_TestVal2 && + m_Player1OnClient1.TheList[1] == k_TestVal2; + } + ); + } - Guid gameObjectId = NetworkManagerHelper.AddGameNetworkObject("NetworkVariableTestComponent"); + [UnityTest] + public IEnumerator NetworkListRemove([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + // first put some stuff in; re-use the add test + yield return NetworkListAdd(useHost); - var networkVariableTestComponent = NetworkManagerHelper.AddComponentToObject(gameObjectId); + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => m_Player1OnServer.TheList.RemoveAt(0), + () => + { + return m_Player1OnServer.TheList.Count == 1 && + m_Player1OnClient1.TheList.Count == 1 && + m_Player1OnServer.ListDelegateTriggered && + m_Player1OnClient1.ListDelegateTriggered && + m_Player1OnServer.TheList[0] == k_TestVal2 && + m_Player1OnClient1.TheList[0] == k_TestVal2; + } + ); + } - NetworkManagerHelper.SpawnNetworkObject(gameObjectId); + [UnityTest] + public IEnumerator NetworkListClear([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - // Start Testing - networkVariableTestComponent.EnableTesting = true; + // first put some stuff in; re-use the add test + yield return NetworkListAdd(useHost); - var testsAreComplete = networkVariableTestComponent.IsTestComplete(); + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => m_Player1OnServer.TheList.Clear(), + () => + { + return + m_Player1OnServer.ListDelegateTriggered && + m_Player1OnClient1.ListDelegateTriggered && + m_Player1OnServer.TheList.Count == 0 && + m_Player1OnClient1.TheList.Count == 0; + } + ); + } - // Wait for the NetworkVariable tests to complete - while (!testsAreComplete) + [UnityTest] + public IEnumerator NetworkSetAdd([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => { - yield return new WaitForSeconds(0.003f); - testsAreComplete = networkVariableTestComponent.IsTestComplete(); + m_Player1OnServer.TheSet.Add(k_TestVal1); + m_Player1OnServer.TheSet.Add(k_TestVal2); + }, + () => + { + return m_Player1OnServer.TheSet.Count == 2 && + m_Player1OnClient1.TheSet.Count == 2 && + m_Player1OnServer.SetDelegateTriggered && + m_Player1OnClient1.SetDelegateTriggered && + m_Player1OnServer.TheSet.Contains(k_TestVal1) && + m_Player1OnClient1.TheSet.Contains(k_TestVal1) && + m_Player1OnServer.TheSet.Contains(k_TestVal2) && + m_Player1OnClient1.TheSet.Contains(k_TestVal2); } + ); + } - // Stop Testing - networkVariableTestComponent.EnableTesting = false; + [UnityTest] + public IEnumerator NetworkSetRemove([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - Assert.IsTrue(networkVariableTestComponent.DidAllValuesChange()); + // first put some stuff in; re-use the add test + yield return NetworkSetAdd(useHost); - // Disable this once we are done. - networkVariableTestComponent.gameObject.SetActive(false); + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheSet.Remove(k_TestVal1); + }, + () => + { + return m_Player1OnServer.TheSet.Count == 1 && + m_Player1OnClient1.TheSet.Count == 1 && + m_Player1OnServer.SetDelegateTriggered && + m_Player1OnClient1.SetDelegateTriggered && + m_Player1OnServer.TheSet.Contains(k_TestVal2) && + m_Player1OnClient1.TheSet.Contains(k_TestVal2); + } + ); + } - Assert.IsTrue(testsAreComplete); + [UnityTest] + public IEnumerator NetworkSetClear([Values(true, false)] bool useHost) + { + // first put some stuff in; re-use the add test + yield return NetworkSetAdd(useHost); - // This would normally go in Teardown, but since every other test but this one - // uses MultiInstanceHelper, and it does its own NetworkManager setup / teardown, - // for now we put this within this one test until we migrate it to MIH - NetworkManagerHelper.ShutdownNetworkManager(); - } + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheSet.Clear(); + }, + () => + { + return m_Player1OnServer.TheSet.Count == 0 && + m_Player1OnClient1.TheSet.Count == 0 && + m_Player1OnServer.SetDelegateTriggered && + m_Player1OnClient1.SetDelegateTriggered; + } + ); + } - [UnityTest] - public IEnumerator NetworkListAdd() - { - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheList.Add(k_TestVal1); - m_ServerComp.TheList.Add(k_TestVal2); - }, - () => - { - return m_ServerComp.TheList.Count == 2 && - m_ClientComp.TheList.Count == 2 && - m_ServerComp.ListDelegateTriggered && - m_ClientComp.ListDelegateTriggered && - m_ServerComp.TheList[0] == k_TestVal1 && - m_ClientComp.TheList[0] == k_TestVal1 && - m_ServerComp.TheList[1] == k_TestVal2 && - m_ClientComp.TheList[1] == k_TestVal2; - } - ); - } + [UnityTest] + public IEnumerator NetworkDictionaryAdd([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - [UnityTest] - public IEnumerator NetworkListRemove() - { - // first put some stuff in; re-use the add test - yield return NetworkListAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => m_ServerComp.TheList.RemoveAt(0), - () => - { - return m_ServerComp.TheList.Count == 1 && - m_ClientComp.TheList.Count == 1 && - m_ServerComp.ListDelegateTriggered && - m_ClientComp.ListDelegateTriggered && - m_ServerComp.TheList[0] == k_TestVal2 && - m_ClientComp.TheList[0] == k_TestVal2; - } - ); - } + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheDictionary.Add(k_TestKey1, k_TestVal1); + m_Player1OnServer.TheDictionary.Add(k_TestKey2, k_TestVal2); + }, + () => + { + return m_Player1OnServer.TheDictionary.Count == 2 && + m_Player1OnClient1.TheDictionary.Count == 2 && + m_Player1OnServer.DictionaryDelegateTriggered && + m_Player1OnClient1.DictionaryDelegateTriggered && + m_Player1OnServer.TheDictionary[k_TestKey1] == k_TestVal1 && + m_Player1OnClient1.TheDictionary[k_TestKey1] == k_TestVal1 && + m_Player1OnServer.TheDictionary[k_TestKey2] == k_TestVal2 && + m_Player1OnClient1.TheDictionary[k_TestKey2] == k_TestVal2; + } + ); + } - [UnityTest] - public IEnumerator NetworkListClear() - { - // first put some stuff in; re-use the add test - yield return NetworkListAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => m_ServerComp.TheList.Clear(), - () => - { - return - m_ServerComp.ListDelegateTriggered && - m_ClientComp.ListDelegateTriggered && - m_ServerComp.TheList.Count == 0 && - m_ClientComp.TheList.Count == 0; - } - ); - } + /* Note, not adding coverage for RemovePair, because we plan to remove + * this in the next PR + */ + [UnityTest] + public IEnumerator NetworkDictionaryRemoveByKey([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - [UnityTest] - public IEnumerator NetworkSetAdd() - { - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheSet.Add(k_TestVal1); - m_ServerComp.TheSet.Add(k_TestVal2); - }, - () => - { - return m_ServerComp.TheSet.Count == 2 && - m_ClientComp.TheSet.Count == 2 && - m_ServerComp.SetDelegateTriggered && - m_ClientComp.SetDelegateTriggered && - m_ServerComp.TheSet.Contains(k_TestVal1) && - m_ClientComp.TheSet.Contains(k_TestVal1) && - m_ServerComp.TheSet.Contains(k_TestVal2) && - m_ClientComp.TheSet.Contains(k_TestVal2); - } - ); - } + // first put some stuff in; re-use the add test + yield return NetworkDictionaryAdd(useHost); - [UnityTest] - public IEnumerator NetworkSetRemove() - { - // first put some stuff in; re-use the add test - yield return NetworkSetAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheSet.Remove(k_TestVal1); - }, - () => - { - return m_ServerComp.TheSet.Count == 1 && - m_ClientComp.TheSet.Count == 1 && - m_ServerComp.SetDelegateTriggered && - m_ClientComp.SetDelegateTriggered && - m_ServerComp.TheSet.Contains(k_TestVal2) && - m_ClientComp.TheSet.Contains(k_TestVal2); - } - ); - } + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheDictionary.Remove(k_TestKey2); + }, + () => + { + return m_Player1OnServer.TheDictionary.Count == 1 && + m_Player1OnClient1.TheDictionary.Count == 1 && + m_Player1OnServer.DictionaryDelegateTriggered && + m_Player1OnClient1.DictionaryDelegateTriggered && + m_Player1OnServer.TheDictionary[k_TestKey1] == k_TestVal1 && + m_Player1OnClient1.TheDictionary[k_TestKey1] == k_TestVal1; + } + ); + } - [UnityTest] - public IEnumerator NetworkSetClear() - { - // first put some stuff in; re-use the add test - yield return NetworkSetAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheSet.Clear(); - }, - () => - { - return m_ServerComp.TheSet.Count == 0 && - m_ClientComp.TheSet.Count == 0 && - m_ServerComp.SetDelegateTriggered && - m_ClientComp.SetDelegateTriggered; - } - ); - } + [UnityTest] + public IEnumerator NetworkDictionaryChangeValue([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - [UnityTest] - public IEnumerator NetworkDictionaryAdd() - { - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheDictionary.Add(k_TestKey1, k_TestVal1); - m_ServerComp.TheDictionary.Add(k_TestKey2, k_TestVal2); - }, - () => - { - return m_ServerComp.TheDictionary.Count == 2 && - m_ClientComp.TheDictionary.Count == 2 && - m_ServerComp.DictionaryDelegateTriggered && - m_ClientComp.DictionaryDelegateTriggered && - m_ServerComp.TheDictionary[k_TestKey1] == k_TestVal1 && - m_ClientComp.TheDictionary[k_TestKey1] == k_TestVal1 && - m_ServerComp.TheDictionary[k_TestKey2] == k_TestVal2 && - m_ClientComp.TheDictionary[k_TestKey2] == k_TestVal2; - } - ); - } + // first put some stuff in; re-use the add test + yield return NetworkDictionaryAdd(useHost); - /* Note, not adding coverage for RemovePair, because we plan to remove - * this in the next PR - */ - [UnityTest] - public IEnumerator NetworkDictionaryRemoveByKey() - { - // first put some stuff in; re-use the add test - yield return NetworkDictionaryAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheDictionary.Remove(k_TestKey2); - }, - () => - { - return m_ServerComp.TheDictionary.Count == 1 && - m_ClientComp.TheDictionary.Count == 1 && - m_ServerComp.DictionaryDelegateTriggered && - m_ClientComp.DictionaryDelegateTriggered && - m_ServerComp.TheDictionary[k_TestKey1] == k_TestVal1 && - m_ClientComp.TheDictionary[k_TestKey1] == k_TestVal1; - } - ); - } + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheDictionary[k_TestKey1] = k_TestVal3; + }, + () => + { + return m_Player1OnServer.TheDictionary.Count == 2 && + m_Player1OnClient1.TheDictionary.Count == 2 && + m_Player1OnServer.DictionaryDelegateTriggered && + m_Player1OnClient1.DictionaryDelegateTriggered && + m_Player1OnServer.TheDictionary[k_TestKey1] == k_TestVal3 && + m_Player1OnClient1.TheDictionary[k_TestKey1] == k_TestVal3; + } + ); + } - [UnityTest] - public IEnumerator NetworkDictionaryChangeValue() - { - // first put some stuff in; re-use the add test - yield return NetworkDictionaryAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheDictionary[k_TestKey1] = k_TestVal3; - }, - () => - { - return m_ServerComp.TheDictionary.Count == 2 && - m_ClientComp.TheDictionary.Count == 2 && - m_ServerComp.DictionaryDelegateTriggered && - m_ClientComp.DictionaryDelegateTriggered && - m_ServerComp.TheDictionary[k_TestKey1] == k_TestVal3 && - m_ClientComp.TheDictionary[k_TestKey1] == k_TestVal3; - } - ); - } + [UnityTest] + public IEnumerator NetworkDictionaryClear([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; - [UnityTest] - public IEnumerator NetworkDictionaryClear() - { - // first put some stuff in; re-use the add test - yield return NetworkDictionaryAdd(); - - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheDictionary.Clear(); - }, - () => - { - return m_ServerComp.TheDictionary.Count == 0 && - m_ClientComp.TheDictionary.Count == 0 && - m_ServerComp.DictionaryDelegateTriggered && - m_ClientComp.DictionaryDelegateTriggered; - } - ); - } + // first put some stuff in; re-use the add test + yield return NetworkDictionaryAdd(useHost); - [UnityTest] - public IEnumerator TestNetworkVariableClass() - { - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheClass.Value.SomeBool = false; - m_ServerComp.TheClass.Value.SomeInt = k_TestUInt; - m_ServerComp.TheClass.SetDirty(true); - }, - () => - { - return - m_ClientComp.TheClass.Value.SomeBool == false && - m_ClientComp.TheClass.Value.SomeInt == k_TestUInt; - } - ); - } + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheDictionary.Clear(); + }, + () => + { + return m_Player1OnServer.TheDictionary.Count == 0 && + m_Player1OnClient1.TheDictionary.Count == 0 && + m_Player1OnServer.DictionaryDelegateTriggered && + m_Player1OnClient1.DictionaryDelegateTriggered; + } + ); + } - [UnityTest] - public IEnumerator TestNetworkVariableStruct() - { - yield return MultiInstanceHelpers.RunAndWaitForCondition( - () => - { - m_ServerComp.TheStruct.Value = - new TestStruct() { SomeInt = k_TestUInt, SomeBool = false }; - m_ServerComp.TheStruct.SetDirty(true); - }, - () => - { - return - m_ClientComp.TheStruct.Value.SomeBool == false && - m_ClientComp.TheStruct.Value.SomeInt == k_TestUInt; - } - ); - } + [UnityTest] + public IEnumerator TestNetworkVariableStruct([Values(true, false)] bool useHost) + { + m_TestWithHost = useHost; + yield return MultiInstanceHelpers.RunAndWaitForCondition( + () => + { + m_Player1OnServer.TheStruct.Value = + new TestStruct() { SomeInt = k_TestUInt, SomeBool = false }; + m_Player1OnServer.TheStruct.SetDirty(true); + }, + () => + { + return + m_Player1OnClient1.TheStruct.Value.SomeBool == false && + m_Player1OnClient1.TheStruct.Value.SomeInt == k_TestUInt; + } + ); + } - [UnityTearDown] - public override IEnumerator Teardown() - { - yield return base.Teardown(); - UnityEngine.Object.Destroy(m_PlayerPrefab); - } + [UnityTearDown] + public override IEnumerator Teardown() + { + yield return base.Teardown(); + UnityEngine.Object.DestroyImmediate(m_PlayerPrefab); } } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Profiling/NetworkVariableNameTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Profiling/NetworkVariableNameTests.cs index 82b9e559b1..5adbc4ffbf 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Profiling/NetworkVariableNameTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Profiling/NetworkVariableNameTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using NUnit.Framework; namespace Unity.Netcode.RuntimeTests @@ -27,7 +27,6 @@ public void TearDown() public void VerifyNetworkVariableNameInitialization() { // Properties have the following name format: "k__BackingField" - StringAssert.Contains(nameof(NetworkVariableNameComponent.NetworkVarString), m_NetworkVariableNameComponent.NetworkVarString.Name); StringAssert.Contains(nameof(NetworkVariableNameComponent.NetworkVarSet), m_NetworkVariableNameComponent.NetworkVarSet.Name); // Fields have regular naming @@ -37,8 +36,6 @@ public void VerifyNetworkVariableNameInitialization() private class NetworkVariableNameComponent : NetworkBehaviour { - public NetworkVariableString NetworkVarString { get; } = new NetworkVariableString(); - public NetworkSet NetworkVarSet { get; } = new NetworkSet(); public NetworkList NetworkVarList = new NetworkList(); diff --git a/testproject/Assets/Scripts/SyncTransform.cs b/testproject/Assets/Scripts/SyncTransform.cs index 9d774757f7..4b47b3b18b 100644 --- a/testproject/Assets/Scripts/SyncTransform.cs +++ b/testproject/Assets/Scripts/SyncTransform.cs @@ -68,12 +68,6 @@ private void SyncRotChanged(Quaternion before, Quaternion after) } } - private void Start() - { - m_VarPos.Settings.WritePermission = NetworkVariablePermission.Everyone; - m_VarRot.Settings.WritePermission = NetworkVariablePermission.Everyone; - } - private void FixedUpdate() { float now = Time.time; diff --git a/testproject/Assets/Tests/Manual/Scripts/BandwidthTest.cs b/testproject/Assets/Tests/Manual/Scripts/BandwidthTest.cs index 17244686f4..ddc25509b7 100644 --- a/testproject/Assets/Tests/Manual/Scripts/BandwidthTest.cs +++ b/testproject/Assets/Tests/Manual/Scripts/BandwidthTest.cs @@ -21,9 +21,7 @@ private void Start() private void Awake() { m_Ids = new NetworkList(); - m_Ids.Settings.WritePermission = NetworkVariablePermission.ServerOnly; m_Ids.OnListChanged += ListChanged; - Debug.Log("Awake"); }