using System.Collections.Generic; using UnityEngine; using System.IO; using System; using MLAPI.Serialization.Pooled; using MLAPI.Transports; namespace MLAPI.NetworkVariable { /// /// A variable that can be synchronized over the network. /// [Serializable] public class NetworkVariable : INetworkVariable { /// /// The settings for this var /// public readonly NetworkVariableSettings Settings = new NetworkVariableSettings(); /// /// The last time the variable was written to locally /// public ushort LocalTick { get; internal set; } /// /// The last time the variable was written to remotely. Uses the remote timescale /// public ushort RemoteTick { get; internal set; } /// /// Delegate type for value changed event /// /// The value before the change /// The new value public delegate void OnValueChangedDelegate(T previousValue, T newValue); /// /// The callback to be invoked when the value gets changed /// public OnValueChangedDelegate OnValueChanged; private NetworkBehaviour m_NetworkBehaviour; /// /// Creates a NetworkVariable with the default value and settings /// 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; } /// /// 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) { Settings = settings; m_InternalValue = value; } /// /// Creates a NetworkVariable with a custom value and the default settings /// /// The initial value to use for the NetworkVariable public NetworkVariable(T value) { m_InternalValue = value; } [SerializeField] private T m_InternalValue; /// /// The value of the NetworkVariable container /// public T Value { get => m_InternalValue; set { if (EqualityComparer.Default.Equals(m_InternalValue, value)) return; // Setter is assumed to be called locally, by game code. // When used by the host, it is its responsibility to set the RemoteTick RemoteTick = NetworkTickSystem.NoTick; m_IsDirty = true; T previousValue = m_InternalValue; m_InternalValue = value; OnValueChanged?.Invoke(previousValue, m_InternalValue); } } private bool m_IsDirty = false; /// /// 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() { m_IsDirty = false; } /// 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; } /// /// Writes the variable to the writer /// /// The stream to write the value to public 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, ushort localTick, ushort remoteTick) { // todo: This allows the host-returned value to be set back to an old value // this will need to be adjusted to check if we're have a most recent value LocalTick = localTick; RemoteTick = remoteTick; using (var reader = PooledNetworkReader.Get(stream)) { T previousValue = m_InternalValue; m_InternalValue = (T)reader.ReadObjectPacked(typeof(T)); if (keepDirtyDelta) m_IsDirty = true; OnValueChanged?.Invoke(previousValue, m_InternalValue); } } /// public void SetNetworkBehaviour(NetworkBehaviour behaviour) { m_NetworkBehaviour = behaviour; } /// public void ReadField(Stream stream, ushort localTick, ushort remoteTick) { ReadDelta(stream, false, localTick, remoteTick); } /// public void WriteField(Stream stream) { // Store the local tick at which this NetworkVariable was modified LocalTick = NetworkBehaviour.CurrentTick; 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) { } } /// /// A NetworkVariable that holds bools and support serialization /// [Serializable] public class NetworkVariableBool : NetworkVariable { /// public NetworkVariableBool() { } /// public NetworkVariableBool(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableBool(bool value) : base(value) { } /// public NetworkVariableBool(NetworkVariableSettings settings, bool value) : base(settings, value) { } } /// /// A NetworkVariable that holds bytes and support serialization /// [Serializable] public class NetworkVariableByte : NetworkVariable { /// public NetworkVariableByte() { } /// public NetworkVariableByte(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableByte(byte value) : base(value) { } /// public NetworkVariableByte(NetworkVariableSettings settings, byte value) : base(settings, value) { } } /// /// A NetworkVariable that holds sbytes and support serialization /// [Serializable] public class NetworkVariableSByte : NetworkVariable { /// public NetworkVariableSByte() { } /// public NetworkVariableSByte(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableSByte(sbyte value) : base(value) { } /// public NetworkVariableSByte(NetworkVariableSettings settings, sbyte value) : base(settings, value) { } } /// /// A NetworkVariable that holds ushorts and support serialization /// [Serializable] public class NetworkVariableUShort : NetworkVariable { /// public NetworkVariableUShort() { } /// public NetworkVariableUShort(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableUShort(ushort value) : base(value) { } /// public NetworkVariableUShort(NetworkVariableSettings settings, ushort value) : base(settings, value) { } } /// /// A NetworkVariable that holds shorts and support serialization /// [Serializable] public class NetworkVariableShort : NetworkVariable { /// public NetworkVariableShort() { } /// public NetworkVariableShort(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableShort(short value) : base(value) { } /// public NetworkVariableShort(NetworkVariableSettings settings, short value) : base(settings, value) { } } /// /// A NetworkVariable that holds uints and support serialization /// [Serializable] public class NetworkVariableUInt : NetworkVariable { /// public NetworkVariableUInt() { } /// public NetworkVariableUInt(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableUInt(uint value) : base(value) { } /// public NetworkVariableUInt(NetworkVariableSettings settings, uint value) : base(settings, value) { } } /// /// A NetworkVariable that holds ints and support serialization /// [Serializable] public class NetworkVariableInt : NetworkVariable { /// public NetworkVariableInt() { } /// public NetworkVariableInt(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableInt(int value) : base(value) { } /// public NetworkVariableInt(NetworkVariableSettings settings, int value) : base(settings, value) { } } /// /// A NetworkVariable that holds ulongs and support serialization /// [Serializable] public class NetworkVariableULong : NetworkVariable { /// public NetworkVariableULong() { } /// public NetworkVariableULong(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableULong(ulong value) : base(value) { } /// public NetworkVariableULong(NetworkVariableSettings settings, ulong value) : base(settings, value) { } } /// /// A NetworkVariable that holds longs and support serialization /// [Serializable] public class NetworkVariableLong : NetworkVariable { /// public NetworkVariableLong() { } /// public NetworkVariableLong(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableLong(long value) : base(value) { } /// public NetworkVariableLong(NetworkVariableSettings settings, long value) : base(settings, value) { } } /// /// A NetworkVariable that holds floats and support serialization /// [Serializable] public class NetworkVariableFloat : NetworkVariable { /// public NetworkVariableFloat() { } /// public NetworkVariableFloat(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableFloat(float value) : base(value) { } /// public NetworkVariableFloat(NetworkVariableSettings settings, float value) : base(settings, value) { } } /// /// A NetworkVariable that holds doubles and support serialization /// [Serializable] public class NetworkVariableDouble : NetworkVariable { /// public NetworkVariableDouble() { } /// public NetworkVariableDouble(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableDouble(double value) : base(value) { } /// public NetworkVariableDouble(NetworkVariableSettings settings, double value) : base(settings, value) { } } /// /// A NetworkVariable that holds vector2s and support serialization /// [Serializable] public class NetworkVariableVector2 : NetworkVariable { /// public NetworkVariableVector2() { } /// public NetworkVariableVector2(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableVector2(Vector2 value) : base(value) { } /// public NetworkVariableVector2(NetworkVariableSettings settings, Vector2 value) : base(settings, value) { } } /// /// A NetworkVariable that holds vector3s and support serialization /// [Serializable] public class NetworkVariableVector3 : NetworkVariable { /// public NetworkVariableVector3() { } /// public NetworkVariableVector3(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableVector3(Vector3 value) : base(value) { } /// public NetworkVariableVector3(NetworkVariableSettings settings, Vector3 value) : base(settings, value) { } } /// /// A NetworkVariable that holds vector4s and support serialization /// [Serializable] public class NetworkVariableVector4 : NetworkVariable { /// public NetworkVariableVector4() { } /// public NetworkVariableVector4(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableVector4(Vector4 value) : base(value) { } /// public NetworkVariableVector4(NetworkVariableSettings settings, Vector4 value) : base(settings, value) { } } /// /// A NetworkVariable that holds colors and support serialization /// [Serializable] public class NetworkVariableColor : NetworkVariable { /// public NetworkVariableColor() { } /// public NetworkVariableColor(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableColor(Color value) : base(value) { } /// public NetworkVariableColor(NetworkVariableSettings settings, Color value) : base(settings, value) { } } /// /// A NetworkVariable that holds color32s and support serialization /// [Serializable] public class NetworkVariableColor32 : NetworkVariable { /// public NetworkVariableColor32() { } /// public NetworkVariableColor32(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableColor32(Color32 value) : base(value) { } /// public NetworkVariableColor32(NetworkVariableSettings settings, Color32 value) : base(settings, value) { } } /// /// A NetworkVariable that holds rays and support serialization /// [Serializable] public class NetworkVariableRay : NetworkVariable { /// public NetworkVariableRay() { } /// public NetworkVariableRay(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableRay(Ray value) : base(value) { } /// public NetworkVariableRay(NetworkVariableSettings settings, Ray value) : base(settings, value) { } } /// /// A NetworkVariable that holds quaternions and support serialization /// [Serializable] public class NetworkVariableQuaternion : NetworkVariable { /// public NetworkVariableQuaternion() { } /// public NetworkVariableQuaternion(NetworkVariableSettings settings) : base(settings) { } /// public NetworkVariableQuaternion(Quaternion value) : base(value) { } /// public NetworkVariableQuaternion(NetworkVariableSettings settings, Quaternion value) : base(settings, value) { } } }