using System;
using UnityEngine;
namespace Unity.Netcode
{
///
/// Interface for network value containers
///
public abstract class NetworkVariableBase : IDisposable
{
///
/// The delivery type (QoS) to send data with
///
internal const NetworkDelivery Delivery = NetworkDelivery.ReliableFragmentedSequenced;
///
/// Maintains a link to the associated NetworkBehaviour
///
private protected NetworkBehaviour m_NetworkBehaviour;
private NetworkManager m_InternalNetworkManager;
internal virtual NetworkVariableType Type => NetworkVariableType.Custom;
private protected NetworkManager m_NetworkManager
{
get
{
if (m_InternalNetworkManager == null && m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
{
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
}
return m_InternalNetworkManager;
}
}
public NetworkBehaviour GetBehaviour()
{
return m_NetworkBehaviour;
}
///
/// Initializes the NetworkVariable
///
/// The NetworkBehaviour the NetworkVariable belongs to
public void Initialize(NetworkBehaviour networkBehaviour)
{
m_InternalNetworkManager = null;
m_NetworkBehaviour = networkBehaviour;
if (m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
{
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
// When in distributed authority mode, there is no such thing as server write permissions
InternalWritePerm = m_InternalNetworkManager.DistributedAuthorityMode ? NetworkVariableWritePermission.Owner : InternalWritePerm;
}
}
///
/// The default read permissions
///
public const NetworkVariableReadPermission DefaultReadPerm = NetworkVariableReadPermission.Everyone;
///
/// The default write permissions
///
public const NetworkVariableWritePermission DefaultWritePerm = NetworkVariableWritePermission.Server;
///
/// The default constructor for that can be used to create a
/// custom NetworkVariable.
///
/// the access settings
/// the access settings
protected NetworkVariableBase(
NetworkVariableReadPermission readPerm = DefaultReadPerm,
NetworkVariableWritePermission writePerm = DefaultWritePerm)
{
ReadPerm = readPerm;
InternalWritePerm = writePerm;
}
///
/// The property is used to determine if the
/// value of the `NetworkVariable` has changed.
///
private bool m_IsDirty;
///
/// Gets or sets the name of the network variable's instance
/// (MemberInfo) where it was declared.
///
public string Name { get; internal set; }
///
/// The read permission for this var
///
public readonly NetworkVariableReadPermission ReadPerm;
///
/// The write permission for this var
///
public NetworkVariableWritePermission WritePerm
{
get
{
return InternalWritePerm;
}
}
// We had to change the Write Permission in distributed authority.
// (It is too bad we initially declared it as readonly)
internal NetworkVariableWritePermission InternalWritePerm;
///
/// Sets whether or not the variable needs to be delta synced
///
/// Whether or not the var is dirty
public virtual void SetDirty(bool isDirty)
{
m_IsDirty = isDirty;
if (m_IsDirty)
{
MarkNetworkBehaviourDirty();
}
}
internal static bool IgnoreInitializeWarning;
protected void MarkNetworkBehaviourDirty()
{
if (m_NetworkBehaviour == null)
{
if (!IgnoreInitializeWarning)
{
Debug.LogWarning($"NetworkVariable is written to, but doesn't know its NetworkBehaviour yet. " +
"Are you modifying a NetworkVariable before the NetworkObject is spawned?");
}
return;
}
if (m_NetworkBehaviour.NetworkManager.ShutdownInProgress)
{
if (m_NetworkBehaviour.NetworkManager.LogLevel <= LogLevel.Developer)
{
Debug.LogWarning($"NetworkVariable is written to during the NetworkManager shutdown! " +
"Are you modifying a NetworkVariable within a NetworkBehaviour.OnDestroy or NetworkBehaviour.OnDespawn method?");
}
return;
}
m_NetworkBehaviour.NetworkManager.BehaviourUpdater?.AddForUpdate(m_NetworkBehaviour.NetworkObject);
}
///
/// Resets the dirty state and marks the variable as synced / clean
///
public virtual void ResetDirty()
{
m_IsDirty = false;
}
///
/// Gets Whether or not the container is dirty
///
/// Whether or not the container is dirty
public virtual bool IsDirty()
{
return m_IsDirty;
}
///
/// Gets if a specific client has permission to read the var or not
///
/// The client id
/// Whether or not the client has permission to read
public bool CanClientRead(ulong clientId)
{
// When in distributed authority mode, everyone can read (but only the owner can write)
if (m_NetworkManager != null && m_NetworkManager.DistributedAuthorityMode)
{
return true;
}
switch (ReadPerm)
{
default:
case NetworkVariableReadPermission.Everyone:
return true;
case NetworkVariableReadPermission.Owner:
return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId || NetworkManager.ServerClientId == clientId;
}
}
///
/// Gets if a specific client has permission to write the var or not
///
/// The client id
/// Whether or not the client has permission to write
public bool CanClientWrite(ulong clientId)
{
switch (WritePerm)
{
default:
case NetworkVariableWritePermission.Server:
return clientId == NetworkManager.ServerClientId;
case NetworkVariableWritePermission.Owner:
return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId;
}
}
///
/// Returns the ClientId of the owning client
///
internal ulong OwnerClientId()
{
return m_NetworkBehaviour.NetworkObject.OwnerClientId;
}
///
/// 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
public abstract void WriteDelta(FastBufferWriter writer);
///
/// Writes the complete state of the variable to the writer
///
/// The stream to write the state to
public abstract void WriteField(FastBufferWriter writer);
///
/// Reads the complete state from the reader and applies it
///
/// The stream to read the state from
public abstract void ReadField(FastBufferReader reader);
///
/// Reads delta from the reader and applies them to the internal value
///
/// The stream to read the delta from
/// Whether or not the delta should be kept as dirty or consumed
public abstract void ReadDelta(FastBufferReader reader, bool keepDirtyDelta);
///
/// Virtual implementation
///
public virtual void Dispose()
{
m_InternalNetworkManager = null;
}
}
///
/// Enum representing the different types of Network Variables.
///
public enum NetworkVariableType : byte
{
///
/// Value
/// Used for all of the basic NetworkVariables that contain a single value
///
Value = 0,
///
/// Custom
/// For any custom implemented extension of the NetworkVariableBase
///
Custom = 1,
///
/// NetworkList
///
NetworkList = 2
}
public enum CollectionItemType : byte
{
///
/// For any type that is not valid inside a NetworkVariable collection
///
Unknown = 0,
///
/// The following types are valid types inside of NetworkVariable collections
///
Short = 1,
UShort = 2,
Int = 3,
UInt = 4,
Long = 5,
ULong = 6,
Unmanaged = 7,
}
}