[Add] FishNet
This commit is contained in:
@@ -0,0 +1,468 @@
|
||||
using System;
|
||||
using FishNet.CodeGenerating;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FishNet.Managing;
|
||||
using FishNet.Object;
|
||||
using FishNet.Object.Prediction;
|
||||
using FishNet.Serializing.Helping;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
public partial class Reader
|
||||
{
|
||||
internal double DOUBLE_ACCURACY => Writer.DOUBLE_ACCURACY;
|
||||
internal decimal DECIMAL_ACCURACY => Writer.DECIMAL_ACCURACY;
|
||||
|
||||
#region Other.
|
||||
/// <summary>
|
||||
/// Reads a boolean.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public bool ReadDeltaBoolean(bool valueA)
|
||||
{
|
||||
return !valueA;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Whole values.
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public sbyte ReadDeltaInt8(sbyte valueA) => (sbyte)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public byte ReadDeltaUInt8(byte valueA) => (byte)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public short ReadDeltaInt16(short valueA) => (short)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public ushort ReadDeltaUInt16(ushort valueA) => (ushort)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public int ReadDeltaInt32(int valueA) => (int)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public uint ReadDeltaUInt32(uint valueA) => (uint)ReadDifference8_16_32(valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public long ReadDeltaInt64(long valueA) => (long)ReadDeltaUInt64((ulong)valueA);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public ulong ReadDeltaUInt64(ulong valueA)
|
||||
{
|
||||
bool bLargerThanA = ReadBoolean();
|
||||
ulong diff = ReadUnsignedPackedWhole();
|
||||
|
||||
return bLargerThanA ? valueA + diff : valueA - diff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new result by reading and applying a difference to a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
private long ReadDifference8_16_32(long valueA)
|
||||
{
|
||||
long diff = ReadSignedPackedWhole();
|
||||
return valueA + diff;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Single.
|
||||
/// <summary>
|
||||
/// Reads a value.
|
||||
/// </summary>
|
||||
public float ReadDeltaSingle(UDeltaPrecisionType dpt, bool unsigned)
|
||||
{
|
||||
if (dpt.FastContains(UDeltaPrecisionType.UInt8))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt8Unpacked() / (float)DOUBLE_ACCURACY;
|
||||
else
|
||||
return ReadInt8Unpacked() / (float)DOUBLE_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt16))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt16Unpacked() / (float)DOUBLE_ACCURACY;
|
||||
else
|
||||
return ReadInt16Unpacked() / (float)DOUBLE_ACCURACY;
|
||||
}
|
||||
// Everything else is unpacked.
|
||||
else
|
||||
{
|
||||
return ReadSingleUnpacked();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
public float ReadDeltaSingle(UDeltaPrecisionType dpt, float valueA, bool unsigned)
|
||||
{
|
||||
float diff = ReadDeltaSingle(dpt, unsigned);
|
||||
|
||||
if (unsigned)
|
||||
{
|
||||
bool bLargerThanA = dpt.FastContains(UDeltaPrecisionType.NextValueIsLarger);
|
||||
return bLargerThanA ? valueA + diff : valueA - diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return valueA + diff;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
public float ReadDeltaSingle(float valueA)
|
||||
{
|
||||
const bool unsigned = false;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaSingle(dpt, valueA, unsigned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public float ReadUDeltaSingle(float valueA)
|
||||
{
|
||||
const bool unsigned = true;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaSingle(dpt, valueA, unsigned);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Double.
|
||||
/// <summary>
|
||||
/// Reads a value.
|
||||
/// </summary>
|
||||
public double ReadDeltaDouble(UDeltaPrecisionType dpt, bool unsigned)
|
||||
{
|
||||
if (dpt.FastContains(UDeltaPrecisionType.UInt8))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt8Unpacked() / DOUBLE_ACCURACY;
|
||||
else
|
||||
return ReadInt8Unpacked() / DOUBLE_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt16))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt16Unpacked() / DOUBLE_ACCURACY;
|
||||
else
|
||||
return ReadInt16Unpacked() / DOUBLE_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt32))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt32Unpacked() / DOUBLE_ACCURACY;
|
||||
else
|
||||
return ReadInt32Unpacked() / DOUBLE_ACCURACY;
|
||||
}
|
||||
// Unpacked.
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.Unset))
|
||||
{
|
||||
return ReadDoubleUnpacked();
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkManager.LogError($"Unhandled precision type of {dpt}.");
|
||||
return 0d;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
public double ReadDeltaDouble(UDeltaPrecisionType dpt, double valueA, bool unsigned)
|
||||
{
|
||||
double diff = ReadDeltaDouble(dpt, unsigned);
|
||||
// 8.
|
||||
|
||||
if (unsigned)
|
||||
{
|
||||
bool bLargerThanA = dpt.FastContains(UDeltaPrecisionType.NextValueIsLarger);
|
||||
return bLargerThanA ? valueA + diff : valueA - diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return valueA + diff;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
public double ReadDeltaDouble(double valueA)
|
||||
{
|
||||
const bool unsigned = false;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaDouble(dpt, valueA, unsigned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public double ReadUDeltaDouble(double valueA)
|
||||
{
|
||||
const bool unsigned = true;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaDouble(dpt, valueA, unsigned);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Decimal.
|
||||
/// <summary>
|
||||
/// Reads a value.
|
||||
/// </summary>
|
||||
public decimal ReadDeltaDecimal(UDeltaPrecisionType dpt, bool unsigned)
|
||||
{
|
||||
if (dpt.FastContains(UDeltaPrecisionType.UInt8))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt8Unpacked() / DECIMAL_ACCURACY;
|
||||
else
|
||||
return ReadInt8Unpacked() / DECIMAL_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt16))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt16Unpacked() / DECIMAL_ACCURACY;
|
||||
else
|
||||
return ReadInt16Unpacked() / DECIMAL_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt32))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt32Unpacked() / DECIMAL_ACCURACY;
|
||||
else
|
||||
return ReadInt32Unpacked() / DECIMAL_ACCURACY;
|
||||
}
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.UInt64))
|
||||
{
|
||||
if (unsigned)
|
||||
return ReadUInt64Unpacked() / DECIMAL_ACCURACY;
|
||||
else
|
||||
return ReadInt64Unpacked() / DECIMAL_ACCURACY;
|
||||
}
|
||||
// Unpacked.
|
||||
else if (dpt.FastContains(UDeltaPrecisionType.Unset))
|
||||
{
|
||||
return ReadDecimalUnpacked();
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkManager.LogError($"Unhandled precision type of {dpt}.");
|
||||
return 0m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
public decimal ReadDeltaDecimal(UDeltaPrecisionType dpt, decimal valueA, bool unsigned)
|
||||
{
|
||||
decimal diff = ReadDeltaDecimal(dpt, unsigned);
|
||||
|
||||
if (unsigned)
|
||||
{
|
||||
bool bLargerThanA = dpt.FastContains(UDeltaPrecisionType.NextValueIsLarger);
|
||||
return bLargerThanA ? valueA + diff : valueA - diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return valueA + diff;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public decimal ReadDeltaDecimal(decimal valueA)
|
||||
{
|
||||
const bool unsigned = false;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaDecimal(dpt, valueA, unsigned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public decimal ReadUDeltaDecimal(decimal valueA)
|
||||
{
|
||||
const bool unsigned = true;
|
||||
UDeltaPrecisionType dpt = (UDeltaPrecisionType)ReadUInt8Unpacked();
|
||||
|
||||
return ReadDeltaDecimal(dpt, valueA, unsigned);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FishNet Types.
|
||||
/// <summary>
|
||||
/// Reads a delta value.
|
||||
/// </summary>
|
||||
/// <returns>True if written.</returns>
|
||||
[DefaultDeltaReader]
|
||||
public NetworkBehaviour WriteDeltaNetworkBehaviour(NetworkBehaviour valueA)
|
||||
{
|
||||
return ReadNetworkBehaviour();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Unity.
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// (not really for Quaternion).
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public Quaternion ReadDeltaQuaternion(Quaternion valueA, float precision = Writer.QUATERNION_PRECISION) => QuaternionDeltaPrecisionCompression.Decompress(this, valueA, precision);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public Vector2 ReadDeltaVector2(Vector2 valueA)
|
||||
{
|
||||
byte allFlags = ReadUInt8Unpacked();
|
||||
|
||||
if ((allFlags & 1) == 1)
|
||||
valueA.x = ReadUDeltaSingle(valueA.x);
|
||||
if ((allFlags & 2) == 2)
|
||||
valueA.y = ReadUDeltaSingle(valueA.y);
|
||||
|
||||
return valueA;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a difference, appending it onto a value.
|
||||
/// </summary>
|
||||
[DefaultDeltaReader]
|
||||
public Vector3 ReadDeltaVector3(Vector3 valueA)
|
||||
{
|
||||
byte allFlags = ReadUInt8Unpacked();
|
||||
|
||||
if ((allFlags & 1) == 1)
|
||||
valueA.x = ReadUDeltaSingle(valueA.x);
|
||||
if ((allFlags & 2) == 2)
|
||||
valueA.y = ReadUDeltaSingle(valueA.y);
|
||||
if ((allFlags & 4) == 4)
|
||||
valueA.z = ReadUDeltaSingle(valueA.z);
|
||||
|
||||
return valueA;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Prediction.
|
||||
/// <summary>
|
||||
/// Reads a reconcile.
|
||||
/// </summary>
|
||||
internal T ReadDeltaReconcile<T>(T lastReconcile) => ReadDelta(lastReconcile);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a replicate.
|
||||
/// </summary>
|
||||
internal int ReadDeltaReplicate<T>(T lastReadReplicate, ref T[] collection, uint tick) where T : IReplicateData
|
||||
{
|
||||
int startRemaining = Remaining;
|
||||
|
||||
// Number of entries written.
|
||||
int count = (int)ReadUInt8Unpacked();
|
||||
if (collection == null || collection.Length < count)
|
||||
collection = new T[count];
|
||||
|
||||
/* Subtract count total minus 1
|
||||
* from starting tick. This sets the tick to what the first entry would be.
|
||||
* EG packet came in as tick 100, so that was passed as tick.
|
||||
* if there are 3 replicates then 2 would be subtracted (count - 1).
|
||||
* The new tick would be 98.
|
||||
* Ticks would be assigned to read values from oldest to
|
||||
* newest as 98, 99, 100. Which is the correct result. In order for this to
|
||||
* work properly past replicates cannot skip ticks. This will be ensured
|
||||
* in another part of the code. */
|
||||
tick -= (uint)(count - 1);
|
||||
|
||||
uint lastReadTick = lastReadReplicate.GetTick();
|
||||
|
||||
T prev = lastReadReplicate;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Tick read is for.
|
||||
uint readTick = tick + (uint)i;
|
||||
/* If readTick is equal or lesser than lastReadReplicate
|
||||
* then there is no reason to process the data other than getting
|
||||
* it out of the reader. */
|
||||
if (readTick <= lastReadTick)
|
||||
{
|
||||
ReadDelta(prev);
|
||||
}
|
||||
else
|
||||
{
|
||||
T value = ReadDelta(prev);
|
||||
// Apply tick.
|
||||
value.SetTick(readTick);
|
||||
// Assign to collection.
|
||||
collection[i] = value;
|
||||
// Update previous.
|
||||
prev = value;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Generic.
|
||||
/// <summary>
|
||||
/// Reads a delta of any time.
|
||||
/// </summary>
|
||||
public T ReadDelta<T>(T prev)
|
||||
{
|
||||
Func<Reader, T, T> del = GenericDeltaReader<T>.Read;
|
||||
|
||||
if (del == null)
|
||||
{
|
||||
NetworkManager.LogError($"Read delta method not found for {typeof(T).FullName}. Use a supported type or create a custom serializer.");
|
||||
return default;
|
||||
}
|
||||
else
|
||||
{
|
||||
return del.Invoke(this, prev);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user