using System;
namespace Unity.Netcode
{
///
/// Support methods for reading/writing NetworkVariables
/// Because there are multiple overloads of WriteValue/ReadValue based on different generic constraints,
/// but there's no way to achieve the same thing with a class, this sets up various read/write schemes
/// based on which constraints are met by `T` using reflection, which is done at module load time.
///
/// The type the associated NetworkVariable is templated on
[Serializable]
public static class NetworkVariableSerialization
{
internal static INetworkVariableSerializer Serializer = new FallbackSerializer();
internal static bool IsDistributedAuthority => NetworkManager.IsDistributedAuthority;
///
/// A callback to check if two values are equal.
///
public delegate bool EqualsDelegate(ref T a, ref T b);
///
/// Uses the most efficient mechanism for a given type to determine if two values are equal.
/// For types that implement , it will call the Equals() method.
/// For unmanaged types, it will do a bytewise memory comparison.
/// For other types, it will call the == operator.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to check their equality yourself.
///
public static EqualsDelegate AreEqual { get; internal set; }
///
/// Serialize a value using the best-known serialization method for a generic value.
/// Will reliably serialize any value that is passed to it correctly with no boxing.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to use FastBufferWriter directly.
///
///
/// If the codegen is unable to determine a serializer for a type,
/// . is called, which, by default,
/// will throw an exception, unless you have assigned a user serialization callback to it at runtime.
///
///
///
public static void Write(FastBufferWriter writer, ref T value)
{
if (IsDistributedAuthority)
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized)
{
NetworkManager.LogSerializedTypeNotOptimized();
}
#endif
Serializer.WriteDistributedAuthority(writer, ref value);
}
else
{
Serializer.Write(writer, ref value);
}
}
///
/// Deserialize a value using the best-known serialization method for a generic value.
/// Will reliably deserialize any value that is passed to it correctly with no boxing.
/// For types whose deserialization can be determined by codegen (which is most types),
/// GC will only be incurred if the type is a managed type and the ref value passed in is `null`,
/// in which case a new value is created; otherwise, it will be deserialized in-place.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to use FastBufferReader directly.
///
///
/// If the codegen is unable to determine a serializer for a type,
/// . is called, which, by default,
/// will throw an exception, unless you have assigned a user deserialization callback to it at runtime.
///
///
///
public static void Read(FastBufferReader reader, ref T value)
{
if (IsDistributedAuthority)
{
Serializer.ReadDistributedAuthority(reader, ref value);
}
else
{
Serializer.Read(reader, ref value);
}
}
///
/// Serialize a value using the best-known serialization method for a generic value.
/// Will reliably serialize any value that is passed to it correctly with no boxing.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to use FastBufferWriter directly.
///
///
/// If the codegen is unable to determine a serializer for a type,
/// . is called, which, by default,
/// will throw an exception, unless you have assigned a user serialization callback to it at runtime.
///
///
///
public static void WriteDelta(FastBufferWriter writer, ref T value, ref T previousValue)
{
if (IsDistributedAuthority)
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
if (!NetworkManager.DisableNotOptimizedSerializedType && !Serializer.IsDistributedAuthorityOptimized)
{
NetworkManager.LogSerializedTypeNotOptimized();
}
#endif
Serializer.WriteDeltaDistributedAuthority(writer, ref value, ref previousValue);
}
else
{
Serializer.WriteDelta(writer, ref value, ref previousValue);
}
}
///
/// Deserialize a value using the best-known serialization method for a generic value.
/// Will reliably deserialize any value that is passed to it correctly with no boxing.
/// For types whose deserialization can be determined by codegen (which is most types),
/// GC will only be incurred if the type is a managed type and the ref value passed in is `null`,
/// in which case a new value is created; otherwise, it will be deserialized in-place.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to use FastBufferReader directly.
///
///
/// If the codegen is unable to determine a serializer for a type,
/// . is called, which, by default,
/// will throw an exception, unless you have assigned a user deserialization callback to it at runtime.
///
///
///
public static void ReadDelta(FastBufferReader reader, ref T value)
{
if (IsDistributedAuthority)
{
Serializer.ReadDeltaDistributedAuthority(reader, ref value);
}
else
{
Serializer.ReadDelta(reader, ref value);
}
}
///
/// Duplicates a value using the most efficient means of creating a complete copy.
/// For most types this is a simple assignment or memcpy.
/// For managed types, this is will serialize and then deserialize the value to ensure
/// a correct copy.
///
///
/// Note: If you are using this in a custom generic class, please make sure your class is
/// decorated with so that codegen can
/// initialize the serialization mechanisms correctly. If your class is NOT
/// generic, it is better to duplicate it directly.
///
///
/// If the codegen is unable to determine a serializer for a type,
/// . is called, which, by default,
/// will throw an exception, unless you have assigned a user duplication callback to it at runtime.
///
///
///
public static void Duplicate(in T value, ref T duplicatedValue)
{
Serializer.Duplicate(value, ref duplicatedValue);
}
}
}