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) { }
}
}