mirror of
https://github.com/DerTyp7/defrain-shooter-unity.git
synced 2025-10-30 13:07:10 +01:00
CHANGED TO MIRROR
This commit is contained in:
12
Assets/Mirror/Runtime/AssemblyInfo.cs
Normal file
12
Assets/Mirror/Runtime/AssemblyInfo.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests.Common")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests")]
|
||||
// need to use Unity.*.CodeGen assembly name to import Unity.CompilationPipeline
|
||||
// for ILPostProcessor tests.
|
||||
[assembly: InternalsVisibleTo("Unity.Mirror.Tests.CodeGen")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests.Generated")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests.Runtime")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Editor")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Runtime")]
|
||||
[assembly: InternalsVisibleTo("Mirror.Editor")]
|
||||
11
Assets/Mirror/Runtime/AssemblyInfo.cs.meta
Normal file
11
Assets/Mirror/Runtime/AssemblyInfo.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e28d5f410e25b42e6a76a2ffc10e4675
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
85
Assets/Mirror/Runtime/Attributes.cs
Normal file
85
Assets/Mirror/Runtime/Attributes.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
/// <summary>
|
||||
/// SyncVars are used to synchronize a variable from the server to all clients automatically.
|
||||
/// <para>Value must be changed on server, not directly by clients. Hook parameter allows you to define a client-side method to be invoked when the client gets an update from the server.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class SyncVarAttribute : PropertyAttribute
|
||||
{
|
||||
public string hook;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this from a client to run this function on the server.
|
||||
/// <para>Make sure to validate input etc. It's not possible to call this from a server.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class CommandAttribute : Attribute
|
||||
{
|
||||
public int channel = Channels.Reliable;
|
||||
public bool requiresAuthority = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The server uses a Remote Procedure Call (RPC) to run this function on clients.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ClientRpcAttribute : Attribute
|
||||
{
|
||||
public int channel = Channels.Reliable;
|
||||
public bool includeOwner = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The server uses a Remote Procedure Call (RPC) to run this function on a specific client.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class TargetRpcAttribute : Attribute
|
||||
{
|
||||
public int channel = Channels.Reliable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents clients from running this method.
|
||||
/// <para>Prints a warning if a client tries to execute this method.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ServerAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents clients from running this method.
|
||||
/// <para>No warning is thrown.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ServerCallbackAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the server from running this method.
|
||||
/// <para>Prints a warning if the server tries to execute this method.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ClientAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the server from running this method.
|
||||
/// <para>No warning is printed.</para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ClientCallbackAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string property into a Scene property in the inspector
|
||||
/// </summary>
|
||||
public class SceneAttribute : PropertyAttribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Used to show private SyncList in the inspector,
|
||||
/// <para> Use instead of SerializeField for non Serializable types </para>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class ShowInInspectorAttribute : Attribute {}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/Attributes.cs.meta
Normal file
11
Assets/Mirror/Runtime/Attributes.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c04c722ee2ffd49c8a56ab33667b10b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Mirror/Runtime/Batching.meta
Normal file
8
Assets/Mirror/Runtime/Batching.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c38e1bebe9947f8b842a8a57aa2b71c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
97
Assets/Mirror/Runtime/Batching/Batcher.cs
Normal file
97
Assets/Mirror/Runtime/Batching/Batcher.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
// batching functionality encapsulated into one class.
|
||||
// -> less complexity
|
||||
// -> easy to test
|
||||
//
|
||||
// IMPORTANT: we use THRESHOLD batching, not MAXED SIZE batching.
|
||||
// see threshold comments below.
|
||||
//
|
||||
// includes timestamp for tick batching.
|
||||
// -> allows NetworkTransform etc. to use timestamp without including it in
|
||||
// every single message
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
public class Batcher
|
||||
{
|
||||
// batching threshold instead of max size.
|
||||
// -> small messages are fit into threshold sized batches
|
||||
// -> messages larger than threshold are single batches
|
||||
//
|
||||
// in other words, we fit up to 'threshold' but still allow larger ones
|
||||
// for two reasons:
|
||||
// 1.) data races: skipping batching for larger messages would send a
|
||||
// large spawn message immediately, while others are batched and
|
||||
// only flushed at the end of the frame
|
||||
// 2) timestamp batching: if each batch is expected to contain a
|
||||
// timestamp, then large messages have to be a batch too. otherwise
|
||||
// they would not contain a timestamp
|
||||
readonly int threshold;
|
||||
|
||||
// TimeStamp header size for those who need it
|
||||
public const int HeaderSize = sizeof(double);
|
||||
|
||||
// batched messages
|
||||
// IMPORTANT: we queue the serialized messages!
|
||||
// queueing NetworkMessage would box and allocate!
|
||||
Queue<PooledNetworkWriter> messages = new Queue<PooledNetworkWriter>();
|
||||
|
||||
public Batcher(int threshold)
|
||||
{
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
// add a message for batching
|
||||
// we allow any sized messages.
|
||||
// caller needs to make sure they are within max packet size.
|
||||
public void AddMessage(ArraySegment<byte> message)
|
||||
{
|
||||
// put into a (pooled) writer
|
||||
// -> WriteBytes instead of WriteSegment because the latter
|
||||
// would add a size header. we want to write directly.
|
||||
// -> will be returned to pool when making the batch!
|
||||
// IMPORTANT: NOT adding a size header / msg saves LOTS of bandwidth
|
||||
PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
|
||||
writer.WriteBytes(message.Array, message.Offset, message.Count);
|
||||
messages.Enqueue(writer);
|
||||
}
|
||||
|
||||
// batch as many messages as possible into writer
|
||||
// returns true if any batch was made.
|
||||
public bool MakeNextBatch(NetworkWriter writer, double timeStamp)
|
||||
{
|
||||
// if we have no messages then there's nothing to do
|
||||
if (messages.Count == 0)
|
||||
return false;
|
||||
|
||||
// make sure the writer is fresh to avoid uncertain situations
|
||||
if (writer.Position != 0)
|
||||
throw new ArgumentException($"MakeNextBatch needs a fresh writer!");
|
||||
|
||||
// write timestamp first
|
||||
// -> double precision for accuracy over long periods of time
|
||||
writer.WriteDouble(timeStamp);
|
||||
|
||||
// do start no matter what
|
||||
do
|
||||
{
|
||||
// add next message no matter what. even if > threshold.
|
||||
// (we do allow > threshold sized messages as single batch)
|
||||
PooledNetworkWriter message = messages.Dequeue();
|
||||
ArraySegment<byte> segment = message.ToArraySegment();
|
||||
writer.WriteBytes(segment.Array, segment.Offset, segment.Count);
|
||||
|
||||
// return the writer to pool
|
||||
NetworkWriterPool.Recycle(message);
|
||||
}
|
||||
// keep going as long as we have more messages,
|
||||
// AND the next one would fit into threshold.
|
||||
while (messages.Count > 0 &&
|
||||
writer.Position + messages.Peek().Position <= threshold);
|
||||
|
||||
// we had messages, so a batch was made
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/Batching/Batcher.cs.meta
Normal file
11
Assets/Mirror/Runtime/Batching/Batcher.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0afaaa611a2142d48a07bdd03b68b2b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
142
Assets/Mirror/Runtime/Batching/Unbatcher.cs
Normal file
142
Assets/Mirror/Runtime/Batching/Unbatcher.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
// un-batching functionality encapsulated into one class.
|
||||
// -> less complexity
|
||||
// -> easy to test
|
||||
//
|
||||
// includes timestamp for tick batching.
|
||||
// -> allows NetworkTransform etc. to use timestamp without including it in
|
||||
// every single message
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
public class Unbatcher
|
||||
{
|
||||
// supporting adding multiple batches before GetNextMessage is called.
|
||||
// just in case.
|
||||
Queue<PooledNetworkWriter> batches = new Queue<PooledNetworkWriter>();
|
||||
|
||||
public int BatchesCount => batches.Count;
|
||||
|
||||
// NetworkReader is only created once,
|
||||
// then pointed to the first batch.
|
||||
NetworkReader reader = new NetworkReader(new byte[0]);
|
||||
|
||||
// timestamp that was written into the batch remotely.
|
||||
// for the batch that our reader is currently pointed at.
|
||||
double readerRemoteTimeStamp;
|
||||
|
||||
// helper function to start reading a batch.
|
||||
void StartReadingBatch(PooledNetworkWriter batch)
|
||||
{
|
||||
// point reader to it
|
||||
reader.SetBuffer(batch.ToArraySegment());
|
||||
|
||||
// read remote timestamp (double)
|
||||
// -> AddBatch quarantees that we have at least 8 bytes to read
|
||||
readerRemoteTimeStamp = reader.ReadDouble();
|
||||
}
|
||||
|
||||
// add a new batch.
|
||||
// returns true if valid.
|
||||
// returns false if not, in which case the connection should be disconnected.
|
||||
public bool AddBatch(ArraySegment<byte> batch)
|
||||
{
|
||||
// IMPORTANT: ArraySegment is only valid until returning. we copy it!
|
||||
//
|
||||
// NOTE: it's not possible to create empty ArraySegments, so we
|
||||
// don't need to check against that.
|
||||
|
||||
// make sure we have at least 8 bytes to read for tick timestamp
|
||||
if (batch.Count < Batcher.HeaderSize)
|
||||
return false;
|
||||
|
||||
// put into a (pooled) writer
|
||||
// -> WriteBytes instead of WriteSegment because the latter
|
||||
// would add a size header. we want to write directly.
|
||||
// -> will be returned to pool when sending!
|
||||
PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
|
||||
writer.WriteBytes(batch.Array, batch.Offset, batch.Count);
|
||||
|
||||
// first batch? then point reader there
|
||||
if (batches.Count == 0)
|
||||
StartReadingBatch(writer);
|
||||
|
||||
// add batch
|
||||
batches.Enqueue(writer);
|
||||
//Debug.Log($"Adding Batch {BitConverter.ToString(batch.Array, batch.Offset, batch.Count)} => batches={batches.Count} reader={reader}");
|
||||
return true;
|
||||
}
|
||||
|
||||
// get next message, unpacked from batch (if any)
|
||||
// timestamp is the REMOTE time when the batch was created remotely.
|
||||
public bool GetNextMessage(out NetworkReader message, out double remoteTimeStamp)
|
||||
{
|
||||
// getting messages would be easy via
|
||||
// <<size, message, size, message, ...>>
|
||||
// but to save A LOT of bandwidth, we use
|
||||
// <<message, message, ...>
|
||||
// in other words, we don't know where the current message ends
|
||||
//
|
||||
// BUT: it doesn't matter!
|
||||
// -> we simply return the reader
|
||||
// * if we have one yet
|
||||
// * and if there's more to read
|
||||
// -> the caller can then read one message from it
|
||||
// -> when the end is reached, we retire the batch!
|
||||
//
|
||||
// for example:
|
||||
// while (GetNextMessage(out message))
|
||||
// ProcessMessage(message);
|
||||
//
|
||||
message = null;
|
||||
|
||||
// do nothing if we don't have any batches.
|
||||
// otherwise the below queue.Dequeue() would throw an
|
||||
// InvalidOperationException if operating on empty queue.
|
||||
if (batches.Count == 0)
|
||||
{
|
||||
remoteTimeStamp = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// was our reader pointed to anything yet?
|
||||
if (reader.Length == 0)
|
||||
{
|
||||
remoteTimeStamp = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// no more data to read?
|
||||
if (reader.Remaining == 0)
|
||||
{
|
||||
// retire the batch
|
||||
PooledNetworkWriter writer = batches.Dequeue();
|
||||
NetworkWriterPool.Recycle(writer);
|
||||
|
||||
// do we have another batch?
|
||||
if (batches.Count > 0)
|
||||
{
|
||||
// point reader to the next batch.
|
||||
// we'll return the reader below.
|
||||
PooledNetworkWriter next = batches.Peek();
|
||||
StartReadingBatch(next);
|
||||
}
|
||||
// otherwise there's nothing more to read
|
||||
else
|
||||
{
|
||||
remoteTimeStamp = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// use the current batch's remote timestamp
|
||||
// AFTER potentially moving to the next batch ABOVE!
|
||||
remoteTimeStamp = readerRemoteTimeStamp;
|
||||
|
||||
// if we got here, then we have more data to read.
|
||||
message = reader;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/Batching/Unbatcher.cs.meta
Normal file
11
Assets/Mirror/Runtime/Batching/Unbatcher.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 328562d71e1c45c58581b958845aa7a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
357
Assets/Mirror/Runtime/Compression.cs
Normal file
357
Assets/Mirror/Runtime/Compression.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
// Quaternion compression from DOTSNET
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
/// <summary>Functions to Compress Quaternions and Floats</summary>
|
||||
public static class Compression
|
||||
{
|
||||
// quaternion compression //////////////////////////////////////////////
|
||||
// smallest three: https://gafferongames.com/post/snapshot_compression/
|
||||
// compresses 16 bytes quaternion into 4 bytes
|
||||
|
||||
// helper function to find largest absolute element
|
||||
// returns the index of the largest one
|
||||
public static int LargestAbsoluteComponentIndex(Vector4 value, out float largestAbs, out Vector3 withoutLargest)
|
||||
{
|
||||
// convert to abs
|
||||
Vector4 abs = new Vector4(Mathf.Abs(value.x), Mathf.Abs(value.y), Mathf.Abs(value.z), Mathf.Abs(value.w));
|
||||
|
||||
// set largest to first abs (x)
|
||||
largestAbs = abs.x;
|
||||
withoutLargest = new Vector3(value.y, value.z, value.w);
|
||||
int largestIndex = 0;
|
||||
|
||||
// compare to the others, starting at second value
|
||||
// performance for 100k calls
|
||||
// for-loop: 25ms
|
||||
// manual checks: 22ms
|
||||
if (abs.y > largestAbs)
|
||||
{
|
||||
largestIndex = 1;
|
||||
largestAbs = abs.y;
|
||||
withoutLargest = new Vector3(value.x, value.z, value.w);
|
||||
}
|
||||
if (abs.z > largestAbs)
|
||||
{
|
||||
largestIndex = 2;
|
||||
largestAbs = abs.z;
|
||||
withoutLargest = new Vector3(value.x, value.y, value.w);
|
||||
}
|
||||
if (abs.w > largestAbs)
|
||||
{
|
||||
largestIndex = 3;
|
||||
largestAbs = abs.w;
|
||||
withoutLargest = new Vector3(value.x, value.y, value.z);
|
||||
}
|
||||
|
||||
return largestIndex;
|
||||
}
|
||||
|
||||
// scale a float within min/max range to an ushort between min/max range
|
||||
// note: can also use this for byte range from byte.MinValue to byte.MaxValue
|
||||
public static ushort ScaleFloatToUShort(float value, float minValue, float maxValue, ushort minTarget, ushort maxTarget)
|
||||
{
|
||||
// note: C# ushort - ushort => int, hence so many casts
|
||||
// max ushort - min ushort only fits into something bigger
|
||||
int targetRange = maxTarget - minTarget;
|
||||
float valueRange = maxValue - minValue;
|
||||
float valueRelative = value - minValue;
|
||||
return (ushort)(minTarget + (ushort)(valueRelative / valueRange * targetRange));
|
||||
}
|
||||
|
||||
// scale an ushort within min/max range to a float between min/max range
|
||||
// note: can also use this for byte range from byte.MinValue to byte.MaxValue
|
||||
public static float ScaleUShortToFloat(ushort value, ushort minValue, ushort maxValue, float minTarget, float maxTarget)
|
||||
{
|
||||
// note: C# ushort - ushort => int, hence so many casts
|
||||
float targetRange = maxTarget - minTarget;
|
||||
ushort valueRange = (ushort)(maxValue - minValue);
|
||||
ushort valueRelative = (ushort)(value - minValue);
|
||||
return minTarget + (valueRelative / (float)valueRange * targetRange);
|
||||
}
|
||||
|
||||
const float QuaternionMinRange = -0.707107f;
|
||||
const float QuaternionMaxRange = 0.707107f;
|
||||
const ushort TenBitsMax = 0x3FF;
|
||||
|
||||
// helper function to access 'nth' component of quaternion
|
||||
static float QuaternionElement(Quaternion q, int element)
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case 0: return q.x;
|
||||
case 1: return q.y;
|
||||
case 2: return q.z;
|
||||
case 3: return q.w;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// note: assumes normalized quaternions
|
||||
public static uint CompressQuaternion(Quaternion q)
|
||||
{
|
||||
// note: assuming normalized quaternions is enough. no need to force
|
||||
// normalize here. we already normalize when decompressing.
|
||||
|
||||
// find the largest component index [0,3] + value
|
||||
int largestIndex = LargestAbsoluteComponentIndex(new Vector4(q.x, q.y, q.z, q.w), out float _, out Vector3 withoutLargest);
|
||||
|
||||
// from here on, we work with the 3 components without largest!
|
||||
|
||||
// "You might think you need to send a sign bit for [largest] in
|
||||
// case it is negative, but you don’t, because you can make
|
||||
// [largest] always positive by negating the entire quaternion if
|
||||
// [largest] is negative. in quaternion space (x,y,z,w) and
|
||||
// (-x,-y,-z,-w) represent the same rotation."
|
||||
if (QuaternionElement(q, largestIndex) < 0)
|
||||
withoutLargest = -withoutLargest;
|
||||
|
||||
// put index & three floats into one integer.
|
||||
// => index is 2 bits (4 values require 2 bits to store them)
|
||||
// => the three floats are between [-0.707107,+0.707107] because:
|
||||
// "If v is the absolute value of the largest quaternion
|
||||
// component, the next largest possible component value occurs
|
||||
// when two components have the same absolute value and the
|
||||
// other two components are zero. The length of that quaternion
|
||||
// (v,v,0,0) is 1, therefore v^2 + v^2 = 1, 2v^2 = 1,
|
||||
// v = 1/sqrt(2). This means you can encode the smallest three
|
||||
// components in [-0.707107,+0.707107] instead of [-1,+1] giving
|
||||
// you more precision with the same number of bits."
|
||||
// => the article recommends storing each float in 9 bits
|
||||
// => our uint has 32 bits, so we might as well store in (32-2)/3=10
|
||||
// 10 bits max value: 1023=0x3FF (use OSX calc to flip 10 bits)
|
||||
ushort aScaled = ScaleFloatToUShort(withoutLargest.x, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
|
||||
ushort bScaled = ScaleFloatToUShort(withoutLargest.y, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
|
||||
ushort cScaled = ScaleFloatToUShort(withoutLargest.z, QuaternionMinRange, QuaternionMaxRange, 0, TenBitsMax);
|
||||
|
||||
// now we just need to pack them into one integer
|
||||
// -> index is 2 bit and needs to be shifted to 31..32
|
||||
// -> a is 10 bit and needs to be shifted 20..30
|
||||
// -> b is 10 bit and needs to be shifted 10..20
|
||||
// -> c is 10 bit and needs to be at 0..10
|
||||
return (uint)(largestIndex << 30 | aScaled << 20 | bScaled << 10 | cScaled);
|
||||
}
|
||||
|
||||
// Quaternion normalizeSAFE from ECS math.normalizesafe()
|
||||
// => useful to produce valid quaternions even if client sends invalid
|
||||
// data
|
||||
static Quaternion QuaternionNormalizeSafe(Quaternion value)
|
||||
{
|
||||
// The smallest positive normal number representable in a float.
|
||||
const float FLT_MIN_NORMAL = 1.175494351e-38F;
|
||||
|
||||
Vector4 v = new Vector4(value.x, value.y, value.z, value.w);
|
||||
float length = Vector4.Dot(v, v);
|
||||
return length > FLT_MIN_NORMAL
|
||||
? value.normalized
|
||||
: Quaternion.identity;
|
||||
}
|
||||
|
||||
// note: gives normalized quaternions
|
||||
public static Quaternion DecompressQuaternion(uint data)
|
||||
{
|
||||
// get cScaled which is at 0..10 and ignore the rest
|
||||
ushort cScaled = (ushort)(data & TenBitsMax);
|
||||
|
||||
// get bScaled which is at 10..20 and ignore the rest
|
||||
ushort bScaled = (ushort)((data >> 10) & TenBitsMax);
|
||||
|
||||
// get aScaled which is at 20..30 and ignore the rest
|
||||
ushort aScaled = (ushort)((data >> 20) & TenBitsMax);
|
||||
|
||||
// get 2 bit largest index, which is at 31..32
|
||||
int largestIndex = (int)(data >> 30);
|
||||
|
||||
// scale back to floats
|
||||
float a = ScaleUShortToFloat(aScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
|
||||
float b = ScaleUShortToFloat(bScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
|
||||
float c = ScaleUShortToFloat(cScaled, 0, TenBitsMax, QuaternionMinRange, QuaternionMaxRange);
|
||||
|
||||
// calculate the omitted component based on a²+b²+c²+d²=1
|
||||
float d = Mathf.Sqrt(1 - a*a - b*b - c*c);
|
||||
|
||||
// reconstruct based on largest index
|
||||
Vector4 value;
|
||||
switch (largestIndex)
|
||||
{
|
||||
case 0: value = new Vector4(d, a, b, c); break;
|
||||
case 1: value = new Vector4(a, d, b, c); break;
|
||||
case 2: value = new Vector4(a, b, d, c); break;
|
||||
default: value = new Vector4(a, b, c, d); break;
|
||||
}
|
||||
|
||||
// ECS Rotation only works with normalized quaternions.
|
||||
// make sure that's always the case here to avoid ECS bugs where
|
||||
// everything stops moving if the quaternion isn't normalized.
|
||||
// => NormalizeSafe returns a normalized quaternion even if we pass
|
||||
// in NaN from deserializing invalid values!
|
||||
return QuaternionNormalizeSafe(new Quaternion(value.x, value.y, value.z, value.w));
|
||||
}
|
||||
|
||||
// varint compression //////////////////////////////////////////////////
|
||||
// compress ulong varint.
|
||||
// same result for int, short and byte. only need one function.
|
||||
// NOT an extension. otherwise weaver might accidentally use it.
|
||||
public static void CompressVarUInt(NetworkWriter writer, ulong value)
|
||||
{
|
||||
if (value <= 240)
|
||||
{
|
||||
writer.Write((byte)value);
|
||||
return;
|
||||
}
|
||||
if (value <= 2287)
|
||||
{
|
||||
writer.Write((byte)(((value - 240) >> 8) + 241));
|
||||
writer.Write((byte)((value - 240) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 67823)
|
||||
{
|
||||
writer.Write((byte)249);
|
||||
writer.Write((byte)((value - 2288) >> 8));
|
||||
writer.Write((byte)((value - 2288) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 16777215)
|
||||
{
|
||||
writer.Write((byte)250);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 4294967295)
|
||||
{
|
||||
writer.Write((byte)251);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 1099511627775)
|
||||
{
|
||||
writer.Write((byte)252);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
writer.Write((byte)((value >> 32) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 281474976710655)
|
||||
{
|
||||
writer.Write((byte)253);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
writer.Write((byte)((value >> 32) & 0xFF));
|
||||
writer.Write((byte)((value >> 40) & 0xFF));
|
||||
return;
|
||||
}
|
||||
if (value <= 72057594037927935)
|
||||
{
|
||||
writer.Write((byte)254);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
writer.Write((byte)((value >> 32) & 0xFF));
|
||||
writer.Write((byte)((value >> 40) & 0xFF));
|
||||
writer.Write((byte)((value >> 48) & 0xFF));
|
||||
return;
|
||||
}
|
||||
|
||||
// all others
|
||||
{
|
||||
writer.Write((byte)255);
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
writer.Write((byte)((value >> 32) & 0xFF));
|
||||
writer.Write((byte)((value >> 40) & 0xFF));
|
||||
writer.Write((byte)((value >> 48) & 0xFF));
|
||||
writer.Write((byte)((value >> 56) & 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba
|
||||
public static void CompressVarInt(NetworkWriter writer, long i)
|
||||
{
|
||||
ulong zigzagged = (ulong)((i >> 63) ^ (i << 1));
|
||||
CompressVarUInt(writer, zigzagged);
|
||||
}
|
||||
|
||||
// NOT an extension. otherwise weaver might accidentally use it.
|
||||
public static ulong DecompressVarUInt(NetworkReader reader)
|
||||
{
|
||||
byte a0 = reader.ReadByte();
|
||||
if (a0 < 241)
|
||||
{
|
||||
return a0;
|
||||
}
|
||||
|
||||
byte a1 = reader.ReadByte();
|
||||
if (a0 >= 241 && a0 <= 248)
|
||||
{
|
||||
return 240 + ((a0 - (ulong)241) << 8) + a1;
|
||||
}
|
||||
|
||||
byte a2 = reader.ReadByte();
|
||||
if (a0 == 249)
|
||||
{
|
||||
return 2288 + ((ulong)a1 << 8) + a2;
|
||||
}
|
||||
|
||||
byte a3 = reader.ReadByte();
|
||||
if (a0 == 250)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16);
|
||||
}
|
||||
|
||||
byte a4 = reader.ReadByte();
|
||||
if (a0 == 251)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24);
|
||||
}
|
||||
|
||||
byte a5 = reader.ReadByte();
|
||||
if (a0 == 252)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32);
|
||||
}
|
||||
|
||||
byte a6 = reader.ReadByte();
|
||||
if (a0 == 253)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40);
|
||||
}
|
||||
|
||||
byte a7 = reader.ReadByte();
|
||||
if (a0 == 254)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48);
|
||||
}
|
||||
|
||||
byte a8 = reader.ReadByte();
|
||||
if (a0 == 255)
|
||||
{
|
||||
return a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56);
|
||||
}
|
||||
|
||||
throw new IndexOutOfRangeException($"DecompressVarInt failure: {a0}");
|
||||
}
|
||||
|
||||
// zigzag decoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba
|
||||
public static long DecompressVarInt(NetworkReader reader)
|
||||
{
|
||||
ulong data = DecompressVarUInt(reader);
|
||||
return ((long)(data >> 1)) ^ -((long)data & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/Compression.cs.meta
Normal file
11
Assets/Mirror/Runtime/Compression.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c28963f9c4b97e418252a55500fb91e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Mirror/Runtime/Empty.meta
Normal file
3
Assets/Mirror/Runtime/Empty.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a99666a026b14cf6ba1a2b65946b1b27
|
||||
timeCreated: 1615288671
|
||||
1
Assets/Mirror/Runtime/Empty/ClientScene.cs
Normal file
1
Assets/Mirror/Runtime/Empty/ClientScene.cs
Normal file
@@ -0,0 +1 @@
|
||||
// moved into NetworkClient on 2021-03-07
|
||||
11
Assets/Mirror/Runtime/Empty/ClientScene.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/ClientScene.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96fc7967f813e4960b9119d7c2118494
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Mirror/Runtime/Empty/Cloud.meta
Normal file
8
Assets/Mirror/Runtime/Empty/Cloud.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73a9bb2dacafa8141bce8feef34e33a7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ApiConnector.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ApiConnector.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ApiConnector.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ApiConnector.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bdb99a29e179d14cb0acc43f175d9ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ApiUpdater.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ApiUpdater.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ApiUpdater.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ApiUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f6e5d5acb5879f45a2235ae0f44dc92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/Ball.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/Ball.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/Ball.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/Ball.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4e9cc0829b13e54594a80883836bda7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/BallManager.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/BallManager.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/BallManager.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/BallManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cc796972dc396a42ba3686bd952e329
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/BaseApi.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/BaseApi.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/BaseApi.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/BaseApi.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70f563b7a7210ae43bbcde5cb7721a94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/Events.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/Events.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/Events.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/Events.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7c472a3ea1bc4348bd5a0b05bf7cc3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/Extensions.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/Extensions.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/Extensions.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/Extensions.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97501e783fc67a4459b15d10e6c63563
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ICoroutineRunner.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ICoroutineRunner.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ICoroutineRunner.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ICoroutineRunner.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43472c60a7c72e54eafe559290dd0fc6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/IRequestCreator.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/IRequestCreator.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/IRequestCreator.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/IRequestCreator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b80b95532a9d6e8418aa676a261e4f69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/IUnityEqualCheck.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/IUnityEqualCheck.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/IUnityEqualCheck.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/IUnityEqualCheck.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05185b973ba389a4588fc8a99c75a4f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbabb497385c20346a3c8bda4ae69508
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/JsonStructs.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/JsonStructs.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/JsonStructs.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/JsonStructs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0688c0fdae5376e4ea74d5c3904eed17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ListServer.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ListServer.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ListServer.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ListServer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f0311899162c5b49a3c11fa9bd9c133
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerBaseApi.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerBaseApi.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ListServerBaseApi.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ListServerBaseApi.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6838f9df45594d48873518cbb75b329
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerClientApi.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerClientApi.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d49649fb32cb96b46b10f013b38a4b50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerJson.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerJson.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ListServerJson.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ListServerJson.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a963606335eae0f47abe7ecb5fd028ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerServerApi.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ListServerServerApi.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 675f0d0fd4e82b04290c4d30c8d78ede
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/Logger.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/Logger.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/Logger.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/Logger.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 457ba2df6cb6e1542996c17c715ee81b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95bebb8e810e2954485291a26324f7d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 068feff770f710141afa4a90063a5e6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/Player.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/Player.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/Player.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/Player.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b6cfd54b79bb464dbc6ae7f331ed45f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07d1ea5260bc06e4d831c4b61d494bff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/QuitButtonHUD.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/QuitButtonHUD.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/QuitButtonHUD.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/QuitButtonHUD.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76dab753e7255254687cd57985d8d675
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/RequestCreator.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/RequestCreator.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/RequestCreator.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/RequestCreator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfaa626443cc7c94eae138a2e3a04d7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListManager.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListManager.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListManager.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfc354d4a7f63ca45a653bf5d479afa0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListUI.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListUI.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListUI.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListUI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed11184fcffcdc04c9850d82c8014926
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListUIItem.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Cloud/ServerListUIItem.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListUIItem.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Cloud/ServerListUIItem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c67eda1b451338a428df87fda1e3a7c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/DotNetCompatibility.cs
Normal file
1
Assets/Mirror/Runtime/Empty/DotNetCompatibility.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
11
Assets/Mirror/Runtime/Empty/DotNetCompatibility.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/DotNetCompatibility.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b307f850ccbbe450295acf24d70e5c28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/FallbackTransport.cs
Normal file
1
Assets/Mirror/Runtime/Empty/FallbackTransport.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-05-13
|
||||
11
Assets/Mirror/Runtime/Empty/FallbackTransport.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/FallbackTransport.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 330c9aab13d2d42069c6ebbe582b73ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/LogFactory.cs
Normal file
1
Assets/Mirror/Runtime/Empty/LogFactory.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
11
Assets/Mirror/Runtime/Empty/LogFactory.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/LogFactory.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 353c7c9e14e82f349b1679112050b196
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/LogFilter.cs
Normal file
1
Assets/Mirror/Runtime/Empty/LogFilter.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-03-08
|
||||
11
Assets/Mirror/Runtime/Empty/LogFilter.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/LogFilter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6928b080072948f7b2909b4025fcc79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Mirror/Runtime/Empty/Logging.meta
Normal file
8
Assets/Mirror/Runtime/Empty/Logging.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63d647500ca1bfa4a845bc1f4cff9dcc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a9618569c20a504aa86feb5913c70e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a39aa1e48aa54eb4e964f0191c1dcdce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/Logging/LogFactory.cs
Normal file
1
Assets/Mirror/Runtime/Empty/Logging/LogFactory.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
11
Assets/Mirror/Runtime/Empty/Logging/LogFactory.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Logging/LogFactory.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d06522432d5a44e1587967a4731cd279
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
2
Assets/Mirror/Runtime/Empty/Logging/LogSettings.cs
Normal file
2
Assets/Mirror/Runtime/Empty/Logging/LogSettings.cs
Normal file
@@ -0,0 +1,2 @@
|
||||
// removed 2021-02-16
|
||||
|
||||
11
Assets/Mirror/Runtime/Empty/Logging/LogSettings.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/Logging/LogSettings.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 633889a39717fde4fa28dd6b948dfac7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7627623f2b9fad4484082517cd73e67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac6e8eccf4b6f4dc7b24c276ef47fde8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Mirror/Runtime/Empty/StringHash.cs
Normal file
1
Assets/Mirror/Runtime/Empty/StringHash.cs
Normal file
@@ -0,0 +1 @@
|
||||
// removed 2021-02-16
|
||||
11
Assets/Mirror/Runtime/Empty/StringHash.cs.meta
Normal file
11
Assets/Mirror/Runtime/Empty/StringHash.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 733f020f9b76d453da841089579fd7a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/Mirror/Runtime/ExponentialMovingAverage.cs
Normal file
37
Assets/Mirror/Runtime/ExponentialMovingAverage.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace Mirror
|
||||
{
|
||||
// implementation of N-day EMA
|
||||
// it calculates an exponential moving average roughly equivalent to the last n observations
|
||||
// https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
||||
public class ExponentialMovingAverage
|
||||
{
|
||||
readonly float alpha;
|
||||
bool initialized;
|
||||
|
||||
public double Value { get; private set; }
|
||||
public double Var { get; private set; }
|
||||
|
||||
public ExponentialMovingAverage(int n)
|
||||
{
|
||||
// standard N-day EMA alpha calculation
|
||||
alpha = 2.0f / (n + 1);
|
||||
}
|
||||
|
||||
public void Add(double newValue)
|
||||
{
|
||||
// simple algorithm for EMA described here:
|
||||
// https://en.wikipedia.org/wiki/Moving_average#Exponentially_weighted_moving_variance_and_standard_deviation
|
||||
if (initialized)
|
||||
{
|
||||
double delta = newValue - Value;
|
||||
Value += alpha * delta;
|
||||
Var = (1 - alpha) * (Var + alpha * delta * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = newValue;
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/ExponentialMovingAverage.cs.meta
Normal file
11
Assets/Mirror/Runtime/ExponentialMovingAverage.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05e858cbaa54b4ce4a48c8c7f50c1914
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Assets/Mirror/Runtime/Extensions.cs
Normal file
40
Assets/Mirror/Runtime/Extensions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
// string.GetHashCode is not guaranteed to be the same on all machines, but
|
||||
// we need one that is the same on all machines. simple and stupid:
|
||||
public static int GetStableHashCode(this string text)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 23;
|
||||
foreach (char c in text)
|
||||
hash = hash * 31 + c;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
// previously in DotnetCompatibility.cs
|
||||
// leftover from the UNET days. supposedly for windows store?
|
||||
internal static string GetMethodName(this Delegate func)
|
||||
{
|
||||
#if NETFX_CORE
|
||||
return func.GetMethodInfo().Name;
|
||||
#else
|
||||
return func.Method.Name;
|
||||
#endif
|
||||
}
|
||||
|
||||
// helper function to copy to List<T>
|
||||
// C# only provides CopyTo(T[])
|
||||
public static void CopyTo<T>(this IEnumerable<T> source, List<T> destination)
|
||||
{
|
||||
// foreach allocates. use AddRange.
|
||||
destination.AddRange(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/Extensions.cs.meta
Normal file
11
Assets/Mirror/Runtime/Extensions.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: decf32fd053744d18f35712b7a6f5116
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
89
Assets/Mirror/Runtime/InterestManagement.cs
Normal file
89
Assets/Mirror/Runtime/InterestManagement.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
// interest management component for custom solutions like
|
||||
// distance based, spatial hashing, raycast based, etc.
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public abstract class InterestManagement : MonoBehaviour
|
||||
{
|
||||
// Awake configures InterestManagement in NetworkServer/Client
|
||||
void Awake()
|
||||
{
|
||||
if (NetworkServer.aoi == null)
|
||||
{
|
||||
NetworkServer.aoi = this;
|
||||
}
|
||||
else Debug.LogError($"Only one InterestManagement component allowed. {NetworkServer.aoi.GetType()} has been set up already.");
|
||||
|
||||
if (NetworkClient.aoi == null)
|
||||
{
|
||||
NetworkClient.aoi = this;
|
||||
}
|
||||
else Debug.LogError($"Only one InterestManagement component allowed. {NetworkClient.aoi.GetType()} has been set up already.");
|
||||
}
|
||||
|
||||
// Callback used by the visibility system to determine if an observer
|
||||
// (player) can see the NetworkIdentity. If this function returns true,
|
||||
// the network connection will be added as an observer.
|
||||
// conn: Network connection of a player.
|
||||
// returns True if the player can see this object.
|
||||
public abstract bool OnCheckObserver(NetworkIdentity identity, NetworkConnection newObserver);
|
||||
|
||||
// rebuild observers for the given NetworkIdentity.
|
||||
// Server will automatically spawn/despawn added/removed ones.
|
||||
// newObservers: cached hashset to put the result into
|
||||
// initialize: true if being rebuilt for the first time
|
||||
//
|
||||
// IMPORTANT:
|
||||
// => global rebuild would be more simple, BUT
|
||||
// => local rebuild is way faster for spawn/despawn because we can
|
||||
// simply rebuild a select NetworkIdentity only
|
||||
// => having both .observers and .observing is necessary for local
|
||||
// rebuilds
|
||||
//
|
||||
// in other words, this is the perfect solution even though it's not
|
||||
// completely simple (due to .observers & .observing).
|
||||
//
|
||||
// Mirror maintains .observing automatically in the background. best of
|
||||
// both worlds without any worrying now!
|
||||
public abstract void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnection> newObservers, bool initialize);
|
||||
|
||||
// helper function to trigger a full rebuild.
|
||||
// most implementations should call this in a certain interval.
|
||||
// some might call this all the time, or only on team changes or
|
||||
// scene changes and so on.
|
||||
//
|
||||
// IMPORTANT: check if NetworkServer.active when using Update()!
|
||||
protected void RebuildAll()
|
||||
{
|
||||
foreach (NetworkIdentity identity in NetworkServer.spawned.Values)
|
||||
{
|
||||
NetworkServer.RebuildObservers(identity, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback used by the visibility system for objects on a host.
|
||||
// Objects on a host (with a local client) cannot be disabled or
|
||||
// destroyed when they are not visible to the local client. So this
|
||||
// function is called to allow custom code to hide these objects. A
|
||||
// typical implementation will disable renderer components on the
|
||||
// object. This is only called on local clients on a host.
|
||||
// => need the function in here and virtual so people can overwrite!
|
||||
// => not everyone wants to hide renderers!
|
||||
public virtual void SetHostVisibility(NetworkIdentity identity, bool visible)
|
||||
{
|
||||
foreach (Renderer rend in identity.GetComponentsInChildren<Renderer>())
|
||||
rend.enabled = visible;
|
||||
}
|
||||
|
||||
/// <summary>Called on the server when a new networked object is spawned.</summary>
|
||||
// (useful for 'only rebuild if changed' interest management algorithms)
|
||||
public virtual void OnSpawned(NetworkIdentity identity) {}
|
||||
|
||||
/// <summary>Called on the server when a networked object is destroyed.</summary>
|
||||
// (useful for 'only rebuild if changed' interest management algorithms)
|
||||
public virtual void OnDestroyed(NetworkIdentity identity) {}
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/InterestManagement.cs.meta
Normal file
11
Assets/Mirror/Runtime/InterestManagement.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41d809934003479f97e992eebb7ed6af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
169
Assets/Mirror/Runtime/LocalConnections.cs
Normal file
169
Assets/Mirror/Runtime/LocalConnections.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
{
|
||||
// a server's connection TO a LocalClient.
|
||||
// sending messages on this connection causes the client's handler function to be invoked directly
|
||||
public class LocalConnectionToClient : NetworkConnectionToClient
|
||||
{
|
||||
internal LocalConnectionToServer connectionToServer;
|
||||
|
||||
public LocalConnectionToClient() : base(LocalConnectionId) {}
|
||||
|
||||
public override string address => "localhost";
|
||||
|
||||
// Send stage two: serialized NetworkMessage as ArraySegment<byte>
|
||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||
{
|
||||
// get a writer to copy the message into since the segment is only
|
||||
// valid until returning.
|
||||
// => pooled writer will be returned to pool when dequeuing.
|
||||
// => WriteBytes instead of WriteArraySegment because the latter
|
||||
// includes a 4 bytes header. we just want to write raw.
|
||||
//Debug.Log($"Enqueue {BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}");
|
||||
PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
|
||||
writer.WriteBytes(segment.Array, segment.Offset, segment.Count);
|
||||
connectionToServer.queue.Enqueue(writer);
|
||||
}
|
||||
|
||||
// true because local connections never timeout
|
||||
internal override bool IsAlive(float timeout) => true;
|
||||
|
||||
internal void DisconnectInternal()
|
||||
{
|
||||
// set not ready and handle clientscene disconnect in any case
|
||||
// (might be client or host mode here)
|
||||
isReady = false;
|
||||
RemoveFromObservingsObservers();
|
||||
}
|
||||
|
||||
/// <summary>Disconnects this connection.</summary>
|
||||
public override void Disconnect()
|
||||
{
|
||||
DisconnectInternal();
|
||||
connectionToServer.DisconnectInternal();
|
||||
}
|
||||
}
|
||||
|
||||
// a localClient's connection TO a server.
|
||||
// send messages on this connection causes the server's handler function to be invoked directly.
|
||||
public class LocalConnectionToServer : NetworkConnectionToServer
|
||||
{
|
||||
internal LocalConnectionToClient connectionToClient;
|
||||
|
||||
// packet queue
|
||||
internal readonly Queue<PooledNetworkWriter> queue = new Queue<PooledNetworkWriter>();
|
||||
|
||||
public override string address => "localhost";
|
||||
|
||||
// see caller for comments on why we need this
|
||||
bool connectedEventPending;
|
||||
bool disconnectedEventPending;
|
||||
internal void QueueConnectedEvent() => connectedEventPending = true;
|
||||
internal void QueueDisconnectedEvent() => disconnectedEventPending = true;
|
||||
|
||||
// Send stage two: serialized NetworkMessage as ArraySegment<byte>
|
||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||
{
|
||||
if (segment.Count == 0)
|
||||
{
|
||||
Debug.LogError("LocalConnection.SendBytes cannot send zero bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
// OnTransportData assumes batching.
|
||||
// so let's make a batch with proper timestamp prefix.
|
||||
Batcher batcher = GetBatchForChannelId(channelId);
|
||||
batcher.AddMessage(segment);
|
||||
|
||||
// flush it to the server's OnTransportData immediately.
|
||||
// local connection to server always invokes immediately.
|
||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
||||
{
|
||||
// make a batch with our local time (double precision)
|
||||
if (batcher.MakeNextBatch(writer, NetworkTime.localTime))
|
||||
{
|
||||
NetworkServer.OnTransportData(connectionId, writer.ToArraySegment(), channelId);
|
||||
}
|
||||
else Debug.LogError("Local connection failed to make batch. This should never happen.");
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// should we still process a connected event?
|
||||
if (connectedEventPending)
|
||||
{
|
||||
connectedEventPending = false;
|
||||
NetworkClient.OnConnectedEvent?.Invoke();
|
||||
}
|
||||
|
||||
// process internal messages so they are applied at the correct time
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
// call receive on queued writer's content, return to pool
|
||||
PooledNetworkWriter writer = queue.Dequeue();
|
||||
ArraySegment<byte> message = writer.ToArraySegment();
|
||||
|
||||
// OnTransportData assumes a proper batch with timestamp etc.
|
||||
// let's make a proper batch and pass it to OnTransportData.
|
||||
Batcher batcher = GetBatchForChannelId(Channels.Reliable);
|
||||
batcher.AddMessage(message);
|
||||
|
||||
using (PooledNetworkWriter batchWriter = NetworkWriterPool.GetWriter())
|
||||
{
|
||||
// make a batch with our local time (double precision)
|
||||
if (batcher.MakeNextBatch(batchWriter, NetworkTime.localTime))
|
||||
{
|
||||
NetworkClient.OnTransportData(batchWriter.ToArraySegment(), Channels.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkWriterPool.Recycle(writer);
|
||||
}
|
||||
|
||||
// should we still process a disconnected event?
|
||||
if (disconnectedEventPending)
|
||||
{
|
||||
disconnectedEventPending = false;
|
||||
NetworkClient.OnDisconnectedEvent?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Disconnects this connection.</summary>
|
||||
internal void DisconnectInternal()
|
||||
{
|
||||
// set not ready and handle clientscene disconnect in any case
|
||||
// (might be client or host mode here)
|
||||
// TODO remove redundant state. have one source of truth for .ready!
|
||||
isReady = false;
|
||||
NetworkClient.ready = false;
|
||||
}
|
||||
|
||||
/// <summary>Disconnects this connection.</summary>
|
||||
public override void Disconnect()
|
||||
{
|
||||
connectionToClient.DisconnectInternal();
|
||||
DisconnectInternal();
|
||||
|
||||
// simulate what a true remote connection would do:
|
||||
// first, the server should remove it:
|
||||
// TODO should probably be in connectionToClient.DisconnectInternal
|
||||
// because that's the NetworkServer's connection!
|
||||
NetworkServer.RemoveLocalConnection();
|
||||
|
||||
// then call OnTransportDisconnected for proper disconnect handling,
|
||||
// callbacks & cleanups.
|
||||
// => otherwise OnClientDisconnected() is never called!
|
||||
// => see NetworkClientTests.DisconnectCallsOnClientDisconnect_HostMode()
|
||||
NetworkClient.OnTransportDisconnected();
|
||||
}
|
||||
|
||||
// true because local connections never timeout
|
||||
internal override bool IsAlive(float timeout) => true;
|
||||
}
|
||||
}
|
||||
11
Assets/Mirror/Runtime/LocalConnections.cs.meta
Normal file
11
Assets/Mirror/Runtime/LocalConnections.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a88758df7db2043d6a9d926e0b6d4191
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user