Moved a couple of folders and wrote some code
This commit is contained in:
21
Assets/Packages/FishNet/Runtime/Serializing/AutoPackType.cs
Normal file
21
Assets/Packages/FishNet/Runtime/Serializing/AutoPackType.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
/// <summary>
|
||||
/// How to pack data when using serialization.
|
||||
/// </summary>
|
||||
public enum AutoPackType
|
||||
{
|
||||
/// <summary>
|
||||
/// Data will not be compressed.
|
||||
/// </summary>
|
||||
Unpacked = 0,
|
||||
/// <summary>
|
||||
/// Data will be compressed to use the least amount of data possible.
|
||||
/// </summary>
|
||||
Packed = 1,
|
||||
/// <summary>
|
||||
/// Data will be compressed but not as much as Packed.
|
||||
/// </summary>
|
||||
PackedLess = 2
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e94ebaa8f7024845a7e90ebd8246ac6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Packages/FishNet/Runtime/Serializing/Helping.meta
Normal file
8
Assets/Packages/FishNet/Runtime/Serializing/Helping.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29ef966943829104e8b9d8b7fd225599
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,26 @@
|
||||
using FishNet.Utility.Constant;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)]
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
/// <summary>
|
||||
/// Method is a comparer for a value type.
|
||||
/// </summary>
|
||||
public class CustomComparerAttribute : Attribute { }
|
||||
/// <summary>
|
||||
/// Method or type will be made public by codegen.
|
||||
/// </summary>
|
||||
internal class CodegenMakePublicAttribute : Attribute { }
|
||||
/// <summary>
|
||||
/// Field or type will be excluded from codegen serialization.
|
||||
/// </summary>
|
||||
public class CodegenExcludeAttribute : Attribute { }
|
||||
/// <summary>
|
||||
/// THIS DOES NOT DO ANYTHING AT THIS TIME.
|
||||
/// It would do -> Type will be included in codegen serialization.
|
||||
/// </summary>
|
||||
internal class CodegenIncludeAttribute : Attribute { }
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce079c8f32bf87b46a44681ccc8578fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,38 @@
|
||||
using FishNet.Managing.Scened;
|
||||
using FishNet.Managing.Server;
|
||||
using FishNet.Object.Helping;
|
||||
using FishNet.Transporting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
|
||||
internal static class Broadcasts
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes a broadcast to writer.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns></returns>
|
||||
internal static PooledWriter WriteBroadcast<T>(PooledWriter writer, T message, Channel channel)
|
||||
{
|
||||
writer.WritePacketId(PacketId.Broadcast);
|
||||
writer.WriteUInt16(typeof(T).FullName.GetStableHash16()); //muchlater codegen this to pass in hash. use technique similar to rpcs to limit byte/shorts.
|
||||
//Write data to a new writer.
|
||||
PooledWriter dataWriter = WriterPool.GetWriter();
|
||||
dataWriter.Write<T>(message);
|
||||
//Write length of data.
|
||||
writer.WriteLength(dataWriter.Length);
|
||||
//Write data.
|
||||
writer.WriteArraySegment(dataWriter.GetArraySegment());
|
||||
|
||||
dataWriter.Dispose();
|
||||
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0636e29429649a24795091f80edbd892
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
|
||||
public class GeneratedComparer<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Compare if T is default.
|
||||
/// </summary>
|
||||
public static Func<T, bool> IsDefault { internal get; set; }
|
||||
/// <summary>
|
||||
/// Compare if T is the same as T2.
|
||||
/// </summary>
|
||||
public static Func<T, T, bool> Compare { internal get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Comparers
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns if A equals B using EqualityCompare.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool EqualityCompare<T>(T a, T b)
|
||||
{
|
||||
return EqualityComparer<T>.Default.Equals(a, b);
|
||||
}
|
||||
|
||||
public static bool IsDefault<T>(T t)
|
||||
{
|
||||
return t.Equals(default(T));
|
||||
}
|
||||
|
||||
public static bool IsEqualityCompareDefault<T>(T a)
|
||||
{
|
||||
return EqualityComparer<T>.Default.Equals(a, default(T));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class SceneComparer : IEqualityComparer<Scene>
|
||||
{
|
||||
public bool Equals(Scene a, Scene b)
|
||||
{
|
||||
if (!a.IsValid() || !b.IsValid())
|
||||
return false;
|
||||
|
||||
if (a.handle != 0 || b.handle != 0)
|
||||
return (a.handle == b.handle);
|
||||
|
||||
return (a.name == b.name);
|
||||
}
|
||||
|
||||
public int GetHashCode(Scene obj)
|
||||
{
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e912d0645f10b2c458cc2f01e24ecc27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,163 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
public static class Quaternion32Compression
|
||||
{
|
||||
private const float Maximum = +1.0f / 1.414214f;
|
||||
|
||||
private const int BitsPerAxis = 10;
|
||||
private const int LargestComponentShift = BitsPerAxis * 3;
|
||||
private const int AShift = BitsPerAxis * 2;
|
||||
private const int BShift = BitsPerAxis * 1;
|
||||
private const int IntScale = (1 << (BitsPerAxis - 1)) - 1;
|
||||
private const int IntMask = (1 << BitsPerAxis) - 1;
|
||||
|
||||
public static uint Compress(Quaternion quaternion)
|
||||
{
|
||||
float absX = Mathf.Abs(quaternion.x);
|
||||
float absY = Mathf.Abs(quaternion.y);
|
||||
float absZ = Mathf.Abs(quaternion.z);
|
||||
float absW = Mathf.Abs(quaternion.w);
|
||||
|
||||
ComponentType largestComponent = ComponentType.X;
|
||||
float largestAbs = absX;
|
||||
float largest = quaternion.x;
|
||||
|
||||
if (absY > largestAbs)
|
||||
{
|
||||
largestAbs = absY;
|
||||
largestComponent = ComponentType.Y;
|
||||
largest = quaternion.y;
|
||||
}
|
||||
if (absZ > largestAbs)
|
||||
{
|
||||
largestAbs = absZ;
|
||||
largestComponent = ComponentType.Z;
|
||||
largest = quaternion.z;
|
||||
}
|
||||
if (absW > largestAbs)
|
||||
{
|
||||
largestComponent = ComponentType.W;
|
||||
largest = quaternion.w;
|
||||
}
|
||||
|
||||
float a = 0;
|
||||
float b = 0;
|
||||
float c = 0;
|
||||
switch (largestComponent)
|
||||
{
|
||||
case ComponentType.X:
|
||||
a = quaternion.y;
|
||||
b = quaternion.z;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.Y:
|
||||
a = quaternion.x;
|
||||
b = quaternion.z;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.Z:
|
||||
a = quaternion.x;
|
||||
b = quaternion.y;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.W:
|
||||
a = quaternion.x;
|
||||
b = quaternion.y;
|
||||
c = quaternion.z;
|
||||
break;
|
||||
}
|
||||
|
||||
if (largest < 0)
|
||||
{
|
||||
a = -a;
|
||||
b = -b;
|
||||
c = -c;
|
||||
}
|
||||
|
||||
uint integerA = ScaleToUint(a);
|
||||
uint integerB = ScaleToUint(b);
|
||||
uint integerC = ScaleToUint(c);
|
||||
|
||||
return (((uint)largestComponent) << LargestComponentShift) | (integerA << AShift) | (integerB << BShift) | integerC;
|
||||
}
|
||||
|
||||
private static uint ScaleToUint(float v)
|
||||
{
|
||||
float normalized = v / Maximum;
|
||||
return (uint)Mathf.RoundToInt(normalized * IntScale) & IntMask;
|
||||
}
|
||||
|
||||
private static float ScaleToFloat(uint v)
|
||||
{
|
||||
float unscaled = v * Maximum / IntScale;
|
||||
|
||||
if (unscaled > Maximum)
|
||||
unscaled -= Maximum * 2;
|
||||
return unscaled;
|
||||
}
|
||||
|
||||
public static Quaternion Decompress(uint compressed)
|
||||
{
|
||||
var largestComponentType = (ComponentType)(compressed >> LargestComponentShift);
|
||||
uint integerA = (compressed >> AShift) & IntMask;
|
||||
uint integerB = (compressed >> BShift) & IntMask;
|
||||
uint integerC = compressed & IntMask;
|
||||
|
||||
float a = ScaleToFloat(integerA);
|
||||
float b = ScaleToFloat(integerB);
|
||||
float c = ScaleToFloat(integerC);
|
||||
|
||||
Quaternion rotation;
|
||||
switch (largestComponentType)
|
||||
{
|
||||
case ComponentType.X:
|
||||
// (?) y z w
|
||||
rotation.y = a;
|
||||
rotation.z = b;
|
||||
rotation.w = c;
|
||||
rotation.x = Mathf.Sqrt(1 - rotation.y * rotation.y
|
||||
- rotation.z * rotation.z
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.Y:
|
||||
// x (?) z w
|
||||
rotation.x = a;
|
||||
rotation.z = b;
|
||||
rotation.w = c;
|
||||
rotation.y = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.z * rotation.z
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.Z:
|
||||
// x y (?) w
|
||||
rotation.x = a;
|
||||
rotation.y = b;
|
||||
rotation.w = c;
|
||||
rotation.z = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.y * rotation.y
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.W:
|
||||
// x y z (?)
|
||||
rotation.x = a;
|
||||
rotation.y = b;
|
||||
rotation.z = c;
|
||||
rotation.w = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.y * rotation.y
|
||||
- rotation.z * rotation.z);
|
||||
break;
|
||||
default:
|
||||
// Should never happen!
|
||||
throw new ArgumentOutOfRangeException("Unknown rotation component type: " +
|
||||
largestComponentType);
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f71e61ed84064a0429577ec462a8fa79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,192 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
/// <summary>
|
||||
/// Credit to https://github.com/viliwonka
|
||||
/// https://github.com/FirstGearGames/FishNet/pull/23
|
||||
/// </summary>
|
||||
public static class Quaternion64Compression
|
||||
{
|
||||
// 64 bit quaternion compression
|
||||
// [4 bits] largest component
|
||||
// [21 bits] higher res
|
||||
// [21 bits] higher res
|
||||
// [20 bits] higher res
|
||||
// sum is 64 bits
|
||||
private const float Maximum = +1.0f / 1.414214f;
|
||||
private const int BitsPerAxis_H = 21; // higher res, 21 bits
|
||||
private const int BitsPerAxis_L = 20; // lower res, 20 bits
|
||||
private const int LargestComponentShift = BitsPerAxis_H * 2 + BitsPerAxis_L * 1;
|
||||
private const int AShift = BitsPerAxis_H + BitsPerAxis_L;
|
||||
private const int BShift = BitsPerAxis_L;
|
||||
private const int IntScale_H = (1 << (BitsPerAxis_H - 1)) - 1;
|
||||
private const int IntMask_H = (1 << BitsPerAxis_H) - 1;
|
||||
private const int IntScale_L = (1 << (BitsPerAxis_L - 1)) - 1;
|
||||
private const int IntMask_L = (1 << BitsPerAxis_L) - 1;
|
||||
|
||||
public static ulong Compress(Quaternion quaternion)
|
||||
{
|
||||
float absX = Mathf.Abs(quaternion.x);
|
||||
float absY = Mathf.Abs(quaternion.y);
|
||||
float absZ = Mathf.Abs(quaternion.z);
|
||||
float absW = Mathf.Abs(quaternion.w);
|
||||
|
||||
ComponentType largestComponent = ComponentType.X;
|
||||
float largestAbs = absX;
|
||||
float largest = quaternion.x;
|
||||
|
||||
if (absY > largestAbs)
|
||||
{
|
||||
largestAbs = absY;
|
||||
largestComponent = ComponentType.Y;
|
||||
largest = quaternion.y;
|
||||
}
|
||||
if (absZ > largestAbs)
|
||||
{
|
||||
largestAbs = absZ;
|
||||
largestComponent = ComponentType.Z;
|
||||
largest = quaternion.z;
|
||||
}
|
||||
if (absW > largestAbs)
|
||||
{
|
||||
largestComponent = ComponentType.W;
|
||||
largest = quaternion.w;
|
||||
}
|
||||
|
||||
float a = 0;
|
||||
float b = 0;
|
||||
float c = 0;
|
||||
|
||||
switch (largestComponent)
|
||||
{
|
||||
case ComponentType.X:
|
||||
a = quaternion.y;
|
||||
b = quaternion.z;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.Y:
|
||||
a = quaternion.x;
|
||||
b = quaternion.z;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.Z:
|
||||
a = quaternion.x;
|
||||
b = quaternion.y;
|
||||
c = quaternion.w;
|
||||
break;
|
||||
case ComponentType.W:
|
||||
a = quaternion.x;
|
||||
b = quaternion.y;
|
||||
c = quaternion.z;
|
||||
break;
|
||||
}
|
||||
|
||||
if (largest < 0)
|
||||
{
|
||||
a = -a;
|
||||
b = -b;
|
||||
c = -c;
|
||||
}
|
||||
|
||||
ulong integerA = ScaleToUint_H(a);
|
||||
ulong integerB = ScaleToUint_H(b);
|
||||
ulong integerC = ScaleToUint_L(c);
|
||||
|
||||
return (((ulong)largestComponent) << LargestComponentShift) | (integerA << AShift) | (integerB << BShift) | integerC;
|
||||
}
|
||||
|
||||
private static ulong ScaleToUint_H(float v)
|
||||
{
|
||||
float normalized = v / Maximum;
|
||||
return (ulong)Mathf.RoundToInt(normalized * IntScale_H) & IntMask_H;
|
||||
}
|
||||
|
||||
private static ulong ScaleToUint_L(float v)
|
||||
{
|
||||
float normalized = v / Maximum;
|
||||
return (ulong)Mathf.RoundToInt(normalized * IntScale_L) & IntMask_L;
|
||||
}
|
||||
|
||||
private static float ScaleToFloat_H(ulong v)
|
||||
{
|
||||
float unscaled = v * Maximum / IntScale_H;
|
||||
|
||||
if (unscaled > Maximum)
|
||||
unscaled -= Maximum * 2;
|
||||
return unscaled;
|
||||
}
|
||||
|
||||
private static float ScaleToFloat_L(ulong v)
|
||||
{
|
||||
float unscaled = v * Maximum / IntScale_L;
|
||||
|
||||
if (unscaled > Maximum)
|
||||
unscaled -= Maximum * 2;
|
||||
return unscaled;
|
||||
}
|
||||
|
||||
public static Quaternion Decompress(ulong compressed)
|
||||
{
|
||||
var largestComponentType = (ComponentType)(compressed >> LargestComponentShift);
|
||||
ulong integerA = (compressed >> AShift) & IntMask_H;
|
||||
ulong integerB = (compressed >> BShift) & IntMask_H;
|
||||
ulong integerC = compressed & IntMask_L;
|
||||
|
||||
float a = ScaleToFloat_H(integerA);
|
||||
float b = ScaleToFloat_H(integerB);
|
||||
float c = ScaleToFloat_L(integerC);
|
||||
|
||||
Quaternion rotation;
|
||||
switch (largestComponentType)
|
||||
{
|
||||
case ComponentType.X:
|
||||
// (?) y z w
|
||||
rotation.y = a;
|
||||
rotation.z = b;
|
||||
rotation.w = c;
|
||||
rotation.x = Mathf.Sqrt(1 - rotation.y * rotation.y
|
||||
- rotation.z * rotation.z
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.Y:
|
||||
// x (?) z w
|
||||
rotation.x = a;
|
||||
rotation.z = b;
|
||||
rotation.w = c;
|
||||
rotation.y = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.z * rotation.z
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.Z:
|
||||
// x y (?) w
|
||||
rotation.x = a;
|
||||
rotation.y = b;
|
||||
rotation.w = c;
|
||||
rotation.z = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.y * rotation.y
|
||||
- rotation.w * rotation.w);
|
||||
break;
|
||||
case ComponentType.W:
|
||||
// x y z (?)
|
||||
rotation.x = a;
|
||||
rotation.y = b;
|
||||
rotation.z = c;
|
||||
rotation.w = Mathf.Sqrt(1 - rotation.x * rotation.x
|
||||
- rotation.y * rotation.y
|
||||
- rotation.z * rotation.z);
|
||||
break;
|
||||
default:
|
||||
// Should never happen!
|
||||
throw new ArgumentOutOfRangeException("Unknown rotation component type: " +
|
||||
largestComponentType);
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7afd33d2ca5433f4f831dfaf0169423c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,126 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used for fast conversion of quaternion structs. Not thread safe!
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct QuaternionConverter
|
||||
{
|
||||
// [FieldOffset(0)]
|
||||
// public Quaternion Q;
|
||||
// [FieldOffset(0)]
|
||||
// public Quaternion64 Q64;
|
||||
// [FieldOffset(0)]
|
||||
// public Quaternion128 Q128;
|
||||
|
||||
// public static QuaternionConverter StaticRef = new QuaternionConverter();
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static Quaternion64 QtoQ64(Quaternion quaternion64)
|
||||
// {
|
||||
// StaticRef.Q = quaternion64;
|
||||
// return StaticRef.Q64;
|
||||
// }
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static Quaternion Q64toQ(Quaternion64 quaternion)
|
||||
// {
|
||||
// StaticRef.Q64 = quaternion;
|
||||
// return StaticRef.Q;
|
||||
// }
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static Quaternion128 QtoQ128(Quaternion quaternion128)
|
||||
// {
|
||||
// StaticRef.Q = quaternion128;
|
||||
// return StaticRef.Q128;
|
||||
// }
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static Quaternion Q128toQ(Quaternion128 quaternion)
|
||||
// {
|
||||
// StaticRef.Q128 = quaternion;
|
||||
// return StaticRef.Q;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public struct Quaternion64
|
||||
//{
|
||||
// public float x;
|
||||
// public float y;
|
||||
// public float z;
|
||||
// public float w;
|
||||
|
||||
// public Quaternion64(float x, float y, float z, float w)
|
||||
// {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// this.z = z;
|
||||
// this.w = w;
|
||||
// }
|
||||
|
||||
// public Quaternion64(Quaternion q)
|
||||
// {
|
||||
// this.x = q.x;
|
||||
// this.y = q.y;
|
||||
// this.z = q.z;
|
||||
// this.w = q.w;
|
||||
// }
|
||||
|
||||
// /*[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static implicit operator Quaternion64(Quaternion q) => new Quaternion64(q);
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static implicit operator Quaternion(Quaternion64 q) => new Quaternion(q.x, q.y, q.z, q.w);*/
|
||||
//}
|
||||
|
||||
//public struct Quaternion128
|
||||
//{
|
||||
// public float x;
|
||||
// public float y;
|
||||
// public float z;
|
||||
// public float w;
|
||||
// public Quaternion128(float x, float y, float z, float w)
|
||||
// {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// this.z = z;
|
||||
// this.w = w;
|
||||
// }
|
||||
|
||||
// public Quaternion128(Quaternion q)
|
||||
// {
|
||||
// x = q.x;
|
||||
// y = q.y;
|
||||
// z = q.z;
|
||||
// w = q.w;
|
||||
// }
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static implicit operator Quaternion128(Quaternion q) => new Quaternion128(q);
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static implicit operator Quaternion(Quaternion128 q) => new Quaternion(q.x, q.y, q.z, q.w);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Credit to this man for converting gaffer games c code to c#
|
||||
/// https://gist.github.com/fversnel/0497ad7ab3b81e0dc1dd
|
||||
/// </summary>
|
||||
}
|
||||
|
||||
public enum ComponentType : uint
|
||||
{
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2,
|
||||
W = 3
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7ac59ce12259104fa28fc837fb17ccf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,41 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
|
||||
|
||||
// -- helpers for float conversion without allocations --
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct UIntFloat
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public float FloatValue;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public uint UIntValue;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct UIntDouble
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public double DoubleValue;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public ulong LongValue;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct UIntDecimal
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public ulong LongValue1;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public ulong LongValue2;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public decimal DecimalValue;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 008e79d0f22a2674189acc7eff64408f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1421
Assets/Packages/FishNet/Runtime/Serializing/Reader.cs
Normal file
1421
Assets/Packages/FishNet/Runtime/Serializing/Reader.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/Packages/FishNet/Runtime/Serializing/Reader.cs.meta
Normal file
11
Assets/Packages/FishNet/Runtime/Serializing/Reader.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 680939c6cee93b64ba149da2029f4308
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,18 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Documenting;
|
||||
using FishNet.Object;
|
||||
using FishNet.Serializing.Helping;
|
||||
using FishNet.Transporting;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions to Read methods. Used by Read<T>.
|
||||
/// </summary>
|
||||
[APIExclude]
|
||||
public static class ReaderExtensions
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abcc77fe436138b4082ee27da3055bb3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
68
Assets/Packages/FishNet/Runtime/Serializing/ReaderPool.cs
Normal file
68
Assets/Packages/FishNet/Runtime/Serializing/ReaderPool.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using FishNet.Managing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader which is reused to save on garbage collection and performance.
|
||||
/// </summary>
|
||||
public sealed class PooledReader : Reader, IDisposable
|
||||
{
|
||||
internal PooledReader(byte[] bytes, NetworkManager networkManager) : base(bytes, networkManager) { }
|
||||
internal PooledReader(ArraySegment<byte> segment, NetworkManager networkManager) : base(segment, networkManager) { }
|
||||
public void Dispose() => ReaderPool.Recycle(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection of PooledReader. Stores and gets PooledReader.
|
||||
/// </summary>
|
||||
public static class ReaderPool
|
||||
{
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Pool of readers.
|
||||
/// </summary>
|
||||
private static readonly Stack<PooledReader> _pool = new Stack<PooledReader>();
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Get the next reader in the pool
|
||||
/// <para>If pool is empty, creates a new Reader</para>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledReader GetReader(byte[] bytes, NetworkManager networkManager)
|
||||
{
|
||||
return GetReader(new ArraySegment<byte>(bytes), networkManager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the next reader in the pool or creates a new one if none are available.
|
||||
/// </summary>
|
||||
public static PooledReader GetReader(ArraySegment<byte> segment, NetworkManager networkManager)
|
||||
{
|
||||
PooledReader result;
|
||||
if (_pool.Count > 0)
|
||||
{
|
||||
result = _pool.Pop();
|
||||
result.Initialize(segment, networkManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new PooledReader(segment, networkManager);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts reader back into pool
|
||||
/// <para>When pool is full, the extra reader is left for the GC</para>
|
||||
/// </summary>
|
||||
public static void Recycle(PooledReader reader)
|
||||
{
|
||||
_pool.Push(reader);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 318b117dd2ebd1b4b9e2021796b45eee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
47
Assets/Packages/FishNet/Runtime/Serializing/ReaderStatics.cs
Normal file
47
Assets/Packages/FishNet/Runtime/Serializing/ReaderStatics.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using FishNet.Documenting;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to a buffer.
|
||||
/// </summary>
|
||||
[APIExclude]
|
||||
internal class ReaderStatics
|
||||
{
|
||||
/* Since serializing occurs on the main thread this value may
|
||||
* be shared among all readers. //multithread
|
||||
*/
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Buffer to copy Guids into.
|
||||
/// </summary>
|
||||
private static byte[] _guidBuffer = new byte[16];
|
||||
/// <summary>
|
||||
/// Used to encode strings.
|
||||
/// </summary>
|
||||
private static readonly UTF8Encoding _encoding = new UTF8Encoding(false, true);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID Buffer.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static byte[] GetGuidBuffer()
|
||||
{
|
||||
return _guidBuffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string from data.
|
||||
/// </summary>
|
||||
public static string GetString(ArraySegment<byte> data)
|
||||
{
|
||||
return _encoding.GetString(data.Array, data.Offset, data.Count);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1f98beaf8f697d4b8bb1e6b6ef32d42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
18
Assets/Packages/FishNet/Runtime/Serializing/SceneComparer.cs
Normal file
18
Assets/Packages/FishNet/Runtime/Serializing/SceneComparer.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace FishNet.Serializing.Helping
|
||||
{
|
||||
internal sealed class SceneHandleEqualityComparer : EqualityComparer<Scene>
|
||||
{
|
||||
public override bool Equals(Scene a, Scene b)
|
||||
{
|
||||
return (a.handle == b.handle);
|
||||
}
|
||||
|
||||
public override int GetHashCode(Scene obj)
|
||||
{
|
||||
return obj.handle;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 161dbbe3995ff53479fc4e259f86549d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,10 @@
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
[System.Serializable]
|
||||
internal class TransformPackingData
|
||||
{
|
||||
public AutoPackType Position = AutoPackType.Packed;
|
||||
public AutoPackType Rotation = AutoPackType.Packed;
|
||||
public AutoPackType Scale = AutoPackType.Packed;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80a80dabe02daf6428cce0f16ea49877
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1331
Assets/Packages/FishNet/Runtime/Serializing/Writer.cs
Normal file
1331
Assets/Packages/FishNet/Runtime/Serializing/Writer.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/Packages/FishNet/Runtime/Serializing/Writer.cs.meta
Normal file
11
Assets/Packages/FishNet/Runtime/Serializing/Writer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2633f927065d9d43b8a4da09240266c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
113
Assets/Packages/FishNet/Runtime/Serializing/WriterExtensions.cs
Normal file
113
Assets/Packages/FishNet/Runtime/Serializing/WriterExtensions.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Documenting;
|
||||
using FishNet.Object;
|
||||
using FishNet.Serializing.Helping;
|
||||
using FishNet.Transporting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Extensions to Write methods. Used by Write<T>.
|
||||
/// </summary>
|
||||
[APIExclude]
|
||||
public static class WriterExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Types which are are set to auto pack by default.
|
||||
/// </summary>
|
||||
internal static HashSet<System.Type> DefaultPackedTypes = new HashSet<System.Type>();
|
||||
|
||||
static WriterExtensions()
|
||||
{
|
||||
DefaultPackedTypes.Add(typeof(int));
|
||||
DefaultPackedTypes.Add(typeof(uint));
|
||||
DefaultPackedTypes.Add(typeof(long));
|
||||
DefaultPackedTypes.Add(typeof(ulong));
|
||||
DefaultPackedTypes.Add(typeof(Color));
|
||||
DefaultPackedTypes.Add(typeof(Vector2Int));
|
||||
DefaultPackedTypes.Add(typeof(Vector3Int));
|
||||
DefaultPackedTypes.Add(typeof(Quaternion));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes value to dst without error checking.
|
||||
/// </summary>
|
||||
[CodegenExclude]
|
||||
internal static void WriteUInt32(byte[] dst, uint value, ref int position)
|
||||
{
|
||||
dst[position++] = (byte)value;
|
||||
dst[position++] = (byte)(value >> 8);
|
||||
dst[position++] = (byte)(value >> 16);
|
||||
dst[position++] = (byte)(value >> 24);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes value to dst without error checking.
|
||||
/// </summary>
|
||||
[CodegenExclude]
|
||||
internal static void WriteUInt64(byte[] dst, ulong value, ref int position)
|
||||
{
|
||||
dst[position++] = (byte)value;
|
||||
dst[position++] = (byte)(value >> 8);
|
||||
dst[position++] = (byte)(value >> 16);
|
||||
dst[position++] = (byte)(value >> 24);
|
||||
dst[position++] = (byte)(value >> 32);
|
||||
dst[position++] = (byte)(value >> 40);
|
||||
dst[position++] = (byte)(value >> 48);
|
||||
dst[position++] = (byte)(value >> 56);
|
||||
}
|
||||
|
||||
|
||||
//public static void WriteDictionary<TKey, TValue>(this Writer writer, Dictionary<TKey, TValue> dict) => writer.WriteDictionary(dict);
|
||||
//public static void WriteByte(this Writer writer, byte value) => writer.WriteByte(value);
|
||||
//[CodegenExclude]
|
||||
//public static void WriteBytes(this Writer writer, byte[] buffer, int offset, int count) => writer.WriteBytes(buffer, offset, count);
|
||||
//[CodegenExclude]
|
||||
//public static void WriteBytesAndSize(this Writer writer, byte[] buffer, int offset, int count) => writer.WriteBytesAndSize(buffer, offset, count);
|
||||
//public static void WriteBytesAndSize(this Writer writer, byte[] value) => writer.WriteBytesAndSize(value);
|
||||
|
||||
//public static void WriteSByte(this Writer writer, sbyte value) => writer.WriteSByte(value);
|
||||
//public static void WriteChar(this Writer writer, char value) => writer.WriteChar(value);
|
||||
//public static void WriteBoolean(this Writer writer, bool value) => writer.WriteBoolean(value);
|
||||
//public static void WriteUInt16(this Writer writer, ushort value) => writer.WriteUInt16(value);
|
||||
//public static void WriteInt16(this Writer writer, short value) => writer.WriteInt16(value);
|
||||
//public static void WriteInt32(this Writer writer, int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteInt32(value, packType);
|
||||
//public static void WriteUInt32(this Writer writer, uint value, AutoPackType packType = AutoPackType.Packed) => writer.WriteUInt32(value, packType);
|
||||
//public static void WriteInt64(this Writer writer, long value, AutoPackType packType = AutoPackType.Packed) => writer.WriteInt64(value, packType);
|
||||
//public static void WriteUInt64(this Writer writer, ulong value, AutoPackType packType = AutoPackType.Packed) => writer.WriteUInt64(value, packType);
|
||||
//public static void WriteSingle(this Writer writer, float value, AutoPackType packType = AutoPackType.Unpacked) => writer.WriteSingle(value, packType);
|
||||
//public static void WriteDouble(this Writer writer, double value) => writer.WriteDouble(value);
|
||||
//public static void WriteDecimal(this Writer writer, decimal value) => writer.WriteDecimal(value);
|
||||
//public static void WriteString(this Writer writer, string value) => writer.WriteString(value);
|
||||
//public static void WriteArraySegmentAndSize(this Writer writer, ArraySegment<byte> value) => writer.WriteArraySegmentAndSize(value);
|
||||
//[CodegenExclude]
|
||||
//public static void WriteArraySegment(this Writer writer, ArraySegment<byte> value) => writer.WriteArraySegment(value);
|
||||
//public static void WriteVector2(this Writer writer, Vector2 value) => writer.WriteVector2(value);
|
||||
//public static void WriteVector3(this Writer writer, Vector3 value) => writer.WriteVector3(value);
|
||||
//public static void WriteVector4(this Writer writer, Vector4 value) => writer.WriteVector4(value);
|
||||
//public static void WriteVector2Int(this Writer writer, Vector2Int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteVector2Int(value, packType);
|
||||
//public static void WriteVector3Int(this Writer writer, Vector3Int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteVector3Int(value, packType);
|
||||
//public static void WriteColor(this Writer writer, Color value, AutoPackType packType) => writer.WriteColor(value, packType);
|
||||
//public static void WriteColor32(this Writer writer, Color32 value) => writer.WriteColor32(value);
|
||||
//public static void WriteQuaternion(this Writer writer, Quaternion value, AutoPackType packType = AutoPackType.Packed) => writer.WriteQuaternion(value, packType);
|
||||
//public static void WriteRect(this Writer writer, Rect value) => writer.WriteRect(value);
|
||||
//public static void WritePlane(this Writer writer, Plane value) => writer.WritePlane(value);
|
||||
//public static void WriteRay(this Writer writer, Ray value) => writer.WriteRay(value);
|
||||
//public static void WriteRay2D(this Writer writer, Ray2D value) => writer.WriteRay2D(value);
|
||||
//public static void WriteMatrix4x4(this Writer writer, Matrix4x4 value) => writer.WriteMatrix4x4(value);
|
||||
//public static void WriteGuidAllocated(this Writer writer, System.Guid value) => writer.WriteGuidAllocated(value);
|
||||
//public static void WriteGameObject(this Writer writer, GameObject value) => writer.WriteGameObject(value);
|
||||
//public static void WriteTransform(this Writer writer, Transform value) => writer.WriteTransform(value);
|
||||
//public static void WriteNetworkObject(this Writer writer, NetworkObject value) => writer.WriteNetworkObject(value);
|
||||
//public static void WriteNetworkBehaviour(this Writer writer, NetworkBehaviour value) => writer.WriteNetworkBehaviour(value);
|
||||
//public static void WriteChannel(this Writer writer, Channel value) => writer.WriteChannel(value);
|
||||
//public static void WriteNetworkConnection(this Writer writer, NetworkConnection value) => writer.WriteNetworkConnection(value);
|
||||
//[CodegenExclude]
|
||||
//public static void Write<T>(this Writer writer, T value) => writer.Write<T>(value);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 493e880d63e9372449c0f0e63890aaef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
159
Assets/Packages/FishNet/Runtime/Serializing/WriterPool.cs
Normal file
159
Assets/Packages/FishNet/Runtime/Serializing/WriterPool.cs
Normal file
@ -0,0 +1,159 @@
|
||||
using FishNet.Managing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
/// <summary>
|
||||
/// Writer which is reused to save on garbage collection and performance.
|
||||
/// </summary>
|
||||
public sealed class PooledWriter : Writer, IDisposable
|
||||
{
|
||||
public void Dispose() => WriterPool.Recycle(this);
|
||||
public void DisposeLength() => WriterPool.RecycleLength(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection of PooledWriter. Stores and gets PooledWriter.
|
||||
/// </summary>
|
||||
public static class WriterPool
|
||||
{
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Pool of writers where length is the minimum and increased at runtime.
|
||||
/// </summary>
|
||||
private static readonly Stack<PooledWriter> _pool = new Stack<PooledWriter>();
|
||||
/// <summary>
|
||||
/// Pool of writers where length is of minimum key and may be increased at runtime.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<int, Stack<PooledWriter>> _lengthPool = new Dictionary<int, Stack<PooledWriter>>();
|
||||
#endregion
|
||||
|
||||
#region Const.
|
||||
/// <summary>
|
||||
/// Length of each bracket when using the length based writer pool.
|
||||
/// </summary>
|
||||
internal const int LENGTH_BRACKET = 1000;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets a writer from the pool.
|
||||
/// </summary>
|
||||
public static PooledWriter GetWriter(NetworkManager networkManager)
|
||||
{
|
||||
PooledWriter result = (_pool.Count > 0) ? _pool.Pop() : new PooledWriter();
|
||||
result.Reset(networkManager);
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a writer from the pool.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledWriter GetWriter()
|
||||
{
|
||||
return GetWriter(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets which index to use for length based pooled readers based on length.
|
||||
/// </summary>
|
||||
private static int GetDictionaryIndex(int length)
|
||||
{
|
||||
return (length / LENGTH_BRACKET);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the next writer in the pool of minimum length.
|
||||
/// </summary>
|
||||
/// <param name="length">Minimum length the writer buffer must be.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledWriter GetWriter(int length)
|
||||
{
|
||||
return GetWriter(null, length);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the next writer in the pool of minimum length.
|
||||
/// </summary>
|
||||
/// <param name="length">Minimum length the writer buffer must be.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static PooledWriter GetWriter(NetworkManager networkManager, int length)
|
||||
{
|
||||
//Ensure length is the minimum.
|
||||
if (length < LENGTH_BRACKET)
|
||||
length = LENGTH_BRACKET;
|
||||
|
||||
/* The index returned will be for writers which have
|
||||
* length as a minimum capacity.
|
||||
* EG: if length is 1200 / 1000 (length_bracket) result
|
||||
* will be index 1. Index 0 will be up to 1000, while
|
||||
* index 1 will be up to 2000. */
|
||||
int dictIndex = GetDictionaryIndex(length);
|
||||
Stack<PooledWriter> stack;
|
||||
//There is already one pooled.
|
||||
if (_lengthPool.TryGetValue(dictIndex, out stack) && stack.Count > 0)
|
||||
{
|
||||
PooledWriter result = stack.Pop();
|
||||
result.Reset(networkManager);
|
||||
return result;
|
||||
}
|
||||
//Not pooled yet.
|
||||
else
|
||||
{
|
||||
//Get any ol' writer.
|
||||
PooledWriter writer = GetWriter(networkManager);
|
||||
/* Ensure length to fill it's bracket.
|
||||
* Increase index by 1 since 0 index would
|
||||
* just return 0 as the capacity. */
|
||||
int requiredCapacity = (dictIndex + 1) * LENGTH_BRACKET;
|
||||
writer.EnsureBufferCapacity(requiredCapacity);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a writer to the appropriate length pool.
|
||||
/// Writers must be a minimum of 1000 bytes in length to be sorted by length.
|
||||
/// Writers which do not meet the minimum will be resized to 1000 bytes.
|
||||
/// </summary>
|
||||
public static void RecycleLength(PooledWriter writer)
|
||||
{
|
||||
int capacity = writer.Capacity;
|
||||
/* If capacity is less than 1000 then the writer
|
||||
* does not meet the minimum length bracket. This should never
|
||||
* be the case unless the user perhaps manually calls this method. */
|
||||
if (capacity < LENGTH_BRACKET)
|
||||
{
|
||||
capacity = LENGTH_BRACKET;
|
||||
writer.EnsureBufferCapacity(LENGTH_BRACKET);
|
||||
}
|
||||
|
||||
/* When getting the recycle index subtract one from
|
||||
* the dictionary index. This is because the writer being
|
||||
* recycled must meet the minimum for that index.
|
||||
* EG: if LENGTH_BRACKET is 1000....
|
||||
* 1200 / 1000 = 1(after flooring).
|
||||
* However, each incremeent in index should have a capacity
|
||||
* of 1000, so index 1 should have a minimum capacity of 2000,
|
||||
* which 1200 does not meet. By subtracting 1 from the index
|
||||
* 1200 will now be placed in index 0 meeting the capacity for that index. */
|
||||
int dictIndex = GetDictionaryIndex(capacity) - 1;
|
||||
Stack<PooledWriter> stack;
|
||||
if (!_lengthPool.TryGetValue(dictIndex, out stack))
|
||||
{
|
||||
stack = new Stack<PooledWriter>();
|
||||
_lengthPool[dictIndex] = stack;
|
||||
}
|
||||
|
||||
stack.Push(writer);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a writer to the pool.
|
||||
/// </summary>
|
||||
public static void Recycle(PooledWriter writer)
|
||||
{
|
||||
_pool.Push(writer);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99b13ccd24eb7264abf67780ef86e44a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
61
Assets/Packages/FishNet/Runtime/Serializing/WriterStatics.cs
Normal file
61
Assets/Packages/FishNet/Runtime/Serializing/WriterStatics.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using FishNet.Documenting;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace FishNet.Serializing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to a buffer.
|
||||
/// </summary>
|
||||
[APIExclude]
|
||||
internal class WriterStatics
|
||||
{
|
||||
/* Since serializing occurs on the main thread this value may
|
||||
* be shared among all writers. //multithread
|
||||
*/
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Encoder for strings.
|
||||
/// </summary>
|
||||
private static readonly UTF8Encoding _encoding = new UTF8Encoding(false, true);
|
||||
/// <summary>
|
||||
/// StringBuffer to use with encoding.
|
||||
/// </summary>
|
||||
private static byte[] _stringBuffer = new byte[64];
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string buffer ensuring proper length, and outputs size in bytes of string.
|
||||
/// </summary>
|
||||
public static byte[] GetStringBuffer(string str, out int size)
|
||||
{
|
||||
int strLength = str.Length;
|
||||
int valueMaxBytes = _encoding.GetMaxByteCount(strLength);
|
||||
if (valueMaxBytes >= _stringBuffer.Length)
|
||||
{
|
||||
int nextSize = (_stringBuffer.Length * 2) + valueMaxBytes;
|
||||
Array.Resize(ref _stringBuffer, nextSize);
|
||||
}
|
||||
|
||||
size = _encoding.GetBytes(str, 0, strLength, _stringBuffer, 0);
|
||||
return _stringBuffer;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Ensures the string buffer is of a minimum length and returns the buffer.
|
||||
/// </summary>
|
||||
public static byte[] GetStringBuffer(string str)
|
||||
{
|
||||
int valueMaxBytes = _encoding.GetMaxByteCount(str.Length);
|
||||
if (valueMaxBytes >= _stringBuffer.Length)
|
||||
{
|
||||
int nextSize = (_stringBuffer.Length * 2) + valueMaxBytes;
|
||||
Array.Resize(ref _stringBuffer, nextSize);
|
||||
}
|
||||
|
||||
return _stringBuffer;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 264951af6d87de34e8809b550a7956b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user