The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.0.0-pre.8] - 2022-04-27 ### Changed - `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy<T>`. (#1901) ### Removed - Removed `SIPTransport` (#1870) - Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs). ### Fixed - Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890) - Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884) - Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883) - Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854) - Passing generic types to RPCs no longer causes a native crash (#1901) - Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)
124 lines
9.7 KiB
C#
124 lines
9.7 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.Netcode
|
|
{
|
|
/// <summary>
|
|
/// Two-way serializer wrapping FastBufferReader or FastBufferWriter.
|
|
///
|
|
/// Implemented as a ref struct for two reasons:
|
|
/// 1. The BufferSerializer cannot outlive the FBR/FBW it wraps or using it will cause a crash
|
|
/// 2. The BufferSerializer must always be passed by reference and can't be copied
|
|
///
|
|
/// Ref structs help enforce both of those rules: they can't ref live the stack context in which they were
|
|
/// created, and they're always passed by reference no matter what.
|
|
///
|
|
/// BufferSerializer doesn't wrapp FastBufferReader or FastBufferWriter directly because it can't.
|
|
/// ref structs can't implement interfaces, and in order to be able to have two different implementations with
|
|
/// the same interface (which allows us to avoid an "if(IsReader)" on every call), the thing directly wrapping
|
|
/// the struct has to implement an interface. So IReaderWriter exists as the interface,
|
|
/// which is implemented by a normal struct, while the ref struct wraps the normal one to enforce the two above
|
|
/// requirements. (Allowing direct access to the IReaderWriter struct would allow dangerous
|
|
/// things to happen because the struct's lifetime could outlive the Reader/Writer's.)
|
|
/// </summary>
|
|
/// <typeparam name="TReaderWriter">The implementation struct</typeparam>
|
|
public ref struct BufferSerializer<TReaderWriter> where TReaderWriter : IReaderWriter
|
|
{
|
|
private TReaderWriter m_Implementation;
|
|
|
|
/// <summary>
|
|
/// Check if the contained implementation is a reader
|
|
/// </summary>
|
|
public bool IsReader => m_Implementation.IsReader;
|
|
|
|
/// <summary>
|
|
/// Check if the contained implementation is a writer
|
|
/// </summary>
|
|
public bool IsWriter => m_Implementation.IsWriter;
|
|
|
|
internal BufferSerializer(TReaderWriter implementation)
|
|
{
|
|
m_Implementation = implementation;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the FastBufferReader instance. Only valid if IsReader = true, throws
|
|
/// InvalidOperationException otherwise.
|
|
/// </summary>
|
|
/// <returns>Reader instance</returns>
|
|
public FastBufferReader GetFastBufferReader()
|
|
{
|
|
return m_Implementation.GetFastBufferReader();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the FastBufferWriter instance. Only valid if IsWriter = true, throws
|
|
/// InvalidOperationException otherwise.
|
|
/// </summary>
|
|
/// <returns>Writer instance</returns>
|
|
public FastBufferWriter GetFastBufferWriter()
|
|
{
|
|
return m_Implementation.GetFastBufferWriter();
|
|
}
|
|
|
|
public void SerializeValue(ref string s, bool oneByteChars = false) => m_Implementation.SerializeValue(ref s, oneByteChars);
|
|
public void SerializeValue(ref byte value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T value, FastBufferWriter.ForPrimitives unused = default) where T : unmanaged, IComparable, IConvertible, IComparable<T>, IEquatable<T> => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T[] value, FastBufferWriter.ForPrimitives unused = default) where T : unmanaged, IComparable, IConvertible, IComparable<T>, IEquatable<T> => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T value, FastBufferWriter.ForEnums unused = default) where T : unmanaged, Enum => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T[] value, FastBufferWriter.ForEnums unused = default) where T : unmanaged, Enum => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T value, FastBufferWriter.ForStructs unused = default) where T : unmanaged, INetworkSerializeByMemcpy => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T[] value, FastBufferWriter.ForStructs unused = default) where T : unmanaged, INetworkSerializeByMemcpy => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T value, FastBufferWriter.ForNetworkSerializable unused = default) where T : INetworkSerializable, new() => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue<T>(ref T[] value, FastBufferWriter.ForNetworkSerializable unused = default) where T : INetworkSerializable, new() => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector2 value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector2[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector3 value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector3[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector4 value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Vector4[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Quaternion value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Quaternion[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Color value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Color[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Color32 value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Color32[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Ray value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Ray[] value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Ray2D value) => m_Implementation.SerializeValue(ref value);
|
|
public void SerializeValue(ref Ray2D[] value) => m_Implementation.SerializeValue(ref value);
|
|
|
|
public void SerializeNetworkSerializable<T>(ref T value) where T : INetworkSerializable, new() => m_Implementation.SerializeNetworkSerializable(ref value);
|
|
|
|
public bool PreCheck(int amount)
|
|
{
|
|
return m_Implementation.PreCheck(amount);
|
|
}
|
|
|
|
public void SerializeValuePreChecked(ref string s, bool oneByteChars = false) => m_Implementation.SerializeValuePreChecked(ref s, oneByteChars);
|
|
public void SerializeValuePreChecked(ref byte value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T value, FastBufferWriter.ForPrimitives unused = default) where T : unmanaged, IComparable, IConvertible, IComparable<T>, IEquatable<T> => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T[] value, FastBufferWriter.ForPrimitives unused = default) where T : unmanaged, IComparable, IConvertible, IComparable<T>, IEquatable<T> => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T value, FastBufferWriter.ForEnums unused = default) where T : unmanaged, Enum => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T[] value, FastBufferWriter.ForEnums unused = default) where T : unmanaged, Enum => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T value, FastBufferWriter.ForStructs unused = default) where T : unmanaged, INetworkSerializeByMemcpy => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked<T>(ref T[] value, FastBufferWriter.ForStructs unused = default) where T : unmanaged, INetworkSerializeByMemcpy => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector2 value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector2[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector3 value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector3[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector4 value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Vector4[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Quaternion value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Quaternion[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Color value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Color[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Color32 value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Color32[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Ray value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Ray[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Ray2D value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
public void SerializeValuePreChecked(ref Ray2D[] value) => m_Implementation.SerializeValuePreChecked(ref value);
|
|
}
|
|
}
|