Commit f6ed3c6f authored by cann-alberto's avatar cann-alberto
Browse files

first project commit

parent 4487b14f
// 'double' precision variants for some of Unity's Mathf functions.
using System.Runtime.CompilerServices;
namespace Mirror
{
public static class Mathd
{
// Unity 2020 doesn't have Math.Clamp yet.
/// <summary>Clamps value between 0 and 1 and returns value.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp(double value, double min, double max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}
/// <summary>Clamps value between 0 and 1 and returns value.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp01(double value) => Clamp(value, 0, 1);
/// <summary>Calculates the linear parameter t that produces the interpolant value within the range [a, b].</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double InverseLerp(double a, double b, double value) =>
a != b ? Clamp01((value - a) / (b - a)) : 0;
/// <summary>Linearly interpolates between a and b by t with no limit to t.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double LerpUnclamped(double a, double b, double t) =>
a + (b - a) * t;
}
}
fileFormatVersion: 2
guid: 5f74084b91c74df2839b426c4a381373
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
// Pool to avoid allocations (from libuv2k)
// API consistent with Microsoft's ObjectPool<T>.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Mirror
{
public class Pool<T>
{
// Mirror is single threaded, no need for concurrent collections.
// stack increases the chance that a reused writer remains in cache.
readonly Stack<T> objects = new Stack<T>();
// some types might need additional parameters in their constructor, so
// we use a Func<T> generator
readonly Func<T> objectGenerator;
public Pool(Func<T> objectGenerator, int initialCapacity)
{
this.objectGenerator = objectGenerator;
// allocate an initial pool so we have fewer (if any)
// allocations in the first few frames (or seconds).
for (int i = 0; i < initialCapacity; ++i)
objects.Push(objectGenerator());
}
// take an element from the pool, or create a new one if empty
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Get() => objects.Count > 0 ? objects.Pop() : objectGenerator();
// return an element to the pool
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Return(T item)
{
// make sure we can't accidentally insert null values into the pool.
// debugging this would be hard since it would only show on get().
if (item == null)
throw new ArgumentNullException(nameof(item));
objects.Push(item);
}
// count to see how many objects are in the pool. useful for tests.
public int Count => objects.Count;
}
}
fileFormatVersion: 2
guid: 845bb05fa349344c3811022f4f15dfbc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Standalone algorithms & structs to help build Mirror.
\ No newline at end of file
fileFormatVersion: 2
guid: da033671de7d49e0838223a997c56bf1
timeCreated: 1667486850
\ No newline at end of file
// TimeSample from Mirror II.
// simple profiling sample, averaged for display in statistics.
// usable in builds without unitiy profiler overhead etc.
//
// .average may safely be called from main thread while Begin/End is in another.
// i.e. worker threads, transport, etc.
using System.Diagnostics;
using System.Threading;
namespace Mirror
{
public struct TimeSample
{
// UnityEngine.Time isn't thread safe. use stopwatch instead.
readonly Stopwatch watch;
// remember when Begin was called
double beginTime;
// keep accumulating times over the given interval.
// (not readonly. we modify its contents.)
ExponentialMovingAverage ema;
// average in seconds.
// code often runs in sub-millisecond time. float is more precise.
//
// set with Interlocked for thread safety.
// can be read from main thread while sampling happens in other thread.
public double average; // THREAD SAFE
// average over N begin/end captures
public TimeSample(int n)
{
watch = new Stopwatch();
watch.Start();
ema = new ExponentialMovingAverage(n);
beginTime = 0;
average = 0;
}
// begin is called before the code to be sampled
public void Begin()
{
// remember when Begin was called.
// keep StopWatch running so we can average over the given interval.
beginTime = watch.Elapsed.TotalSeconds;
// Debug.Log($"Begin @ {beginTime:F4}");
}
// end is called after the code to be sampled
public void End()
{
// add duration in seconds to accumulated durations
double elapsed = watch.Elapsed.TotalSeconds - beginTime;
ema.Add(elapsed);
// expose new average thread safely
Interlocked.Exchange(ref average, ema.Value);
}
}
}
fileFormatVersion: 2
guid: 26c32f6429554546a88d800c846c74ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
namespace Mirror
{
// Handles network messages on client and server
public delegate void NetworkMessageDelegate(NetworkConnection conn, NetworkReader reader, int channelId);
// Handles requests to spawn objects on the client
public delegate GameObject SpawnDelegate(Vector3 position, uint assetId);
public delegate GameObject SpawnHandlerDelegate(SpawnMessage msg);
// Handles requests to unspawn objects on the client
public delegate void UnSpawnDelegate(GameObject spawned);
// channels are const ints instead of an enum so people can add their own
// channels (can't extend an enum otherwise).
//
// note that Mirror is slowly moving towards quake style networking which
// will only require reliable for handshake, and unreliable for the rest.
// so eventually we can change this to an Enum and transports shouldn't
// add custom channels anymore.
public static class Channels
{
public const int Reliable = 0; // ordered
public const int Unreliable = 1; // unordered
}
public static class Utils
{
// detect headless / dedicated server mode
// SystemInfo.graphicsDeviceType is never null in the editor.
// UNITY_SERVER works in builds for all Unity versions 2019 LTS and later.
// For Unity 2019 / 2020, there is no way to detect Server Build checkbox
// state in Build Settings, so they never auto-start headless server / client.
// UNITY_SERVER works in the editor in Unity 2021 LTS and later
// because that's when Dedicated Server platform was added.
// It is intentional for editor play mode to auto-start headless server / client
// when Dedicated Server platform is selected in the editor so that editor
// acts like a headless build to every extent possible for testing / debugging.
public static bool IsHeadless() =>
#if UNITY_SERVER
true;
#else
SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null;
#endif
// detect WebGL mode
public const bool IsWebGL =
#if UNITY_WEBGL
true;
#else
false;
#endif
// detect Debug mode
public const bool IsDebug =
#if DEBUG
true;
#else
false;
#endif
public static uint GetTrueRandomUInt()
{
// use Crypto RNG to avoid having time based duplicates
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] bytes = new byte[4];
rng.GetBytes(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
}
public static bool IsPrefab(GameObject obj)
{
#if UNITY_EDITOR
return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj);
#else
return false;
#endif
}
// simplified IsSceneObject check from Mirror II
public static bool IsSceneObject(NetworkIdentity identity)
{
// original UNET / Mirror still had the IsPersistent check.
// it never fires though. even for Prefabs dragged to the Scene.
// (see Scene Objects example scene.)
// #if UNITY_EDITOR
// if (UnityEditor.EditorUtility.IsPersistent(identity.gameObject))
// return false;
// #endif
return identity.gameObject.hideFlags != HideFlags.NotEditable &&
identity.gameObject.hideFlags != HideFlags.HideAndDontSave &&
identity.sceneId != 0;
}
public static bool IsSceneObjectWithPrefabParent(GameObject gameObject, out GameObject prefab)
{
prefab = null;
#if UNITY_EDITOR
if (!UnityEditor.PrefabUtility.IsPartOfPrefabInstance(gameObject))
{
return false;
}
prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
#endif
if (prefab == null)
{
Debug.LogError($"Failed to find prefab parent for scene object [name:{gameObject.name}]");
return false;
}
return true;
}
// is a 2D point in screen? (from ummorpg)
// (if width = 1024, then indices from 0..1023 are valid (=1024 indices)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPointInScreen(Vector2 point) =>
0 <= point.x && point.x < Screen.width &&
0 <= point.y && point.y < Screen.height;
// pretty print bytes as KB/MB/GB/etc. from DOTSNET
// long to support > 2GB
// divides by floats to return "2.5MB" etc.
public static string PrettyBytes(long bytes)
{
// bytes
if (bytes < 1024)
return $"{bytes} B";
// kilobytes
else if (bytes < 1024L * 1024L)
return $"{(bytes / 1024f):F2} KB";
// megabytes
else if (bytes < 1024 * 1024L * 1024L)
return $"{(bytes / (1024f * 1024f)):F2} MB";
// gigabytes
return $"{(bytes / (1024f * 1024f * 1024f)):F2} GB";
}
// pretty print seconds as hours:minutes:seconds(.milliseconds/100)s.
// double for long running servers.
public static string PrettySeconds(double seconds)
{
TimeSpan t = TimeSpan.FromSeconds(seconds);
string res = "";
if (t.Days > 0) res += $"{t.Days}d";
if (t.Hours > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Hours}h";
if (t.Minutes > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Minutes}m";
// 0.5s, 1.5s etc. if any milliseconds. 1s, 2s etc. if any seconds
if (t.Milliseconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}.{(t.Milliseconds / 100)}s";
else if (t.Seconds > 0) res += $"{(res.Length > 0 ? " " : "")}{t.Seconds}s";
// if the string is still empty because the value was '0', then at least
// return the seconds instead of returning an empty string
return res != "" ? res : "0s";
}
// universal .spawned function
public static NetworkIdentity GetSpawnedInServerOrClient(uint netId)
{
// server / host mode: use the one from server.
// host mode has access to all spawned.
if (NetworkServer.active)
{
NetworkServer.spawned.TryGetValue(netId, out NetworkIdentity entry);
return entry;
}
// client
if (NetworkClient.active)
{
NetworkClient.spawned.TryGetValue(netId, out NetworkIdentity entry);
return entry;
}
return null;
}
// keep a GUI window in screen.
// for example. if it's at x=1000 and screen is resized to w=500,
// it won't get lost in the invisible area etc.
public static Rect KeepInScreen(Rect rect)
{
// ensure min
rect.x = Math.Max(rect.x, 0);
rect.y = Math.Max(rect.y, 0);
// ensure max
rect.x = Math.Min(rect.x, Screen.width - rect.width);
rect.y = Math.Min(rect.y, Screen.width - rect.height);
return rect;
}
// create local connections pair and connect them
public static void CreateLocalConnections(
out LocalConnectionToClient connectionToClient,
out LocalConnectionToServer connectionToServer)
{
connectionToServer = new LocalConnectionToServer();
connectionToClient = new LocalConnectionToClient();
connectionToServer.connectionToClient = connectionToClient;
connectionToClient.connectionToServer = connectionToServer;
}
public static bool IsSceneActive(string scene)
{
Scene activeScene = SceneManager.GetActiveScene();
return activeScene.path == scene ||
activeScene.name == scene;
}
}
}
fileFormatVersion: 2
guid: b530ce39098b54374a29ad308c8e4554
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
#pragma warning disable CS0659 // 'Vector3Long' overrides Object.Equals(object o) but does not override Object.GetHashCode()
#pragma warning disable CS0661 // 'Vector3Long' defines operator == or operator != but does not override Object.GetHashCode()
// Vector3Long by mischa (based on game engine project)
using System;
using System.Runtime.CompilerServices;
namespace Mirror
{
public struct Vector3Long
{
public long x;
public long y;
public long z;
public static readonly Vector3Long zero = new Vector3Long(0, 0, 0);
public static readonly Vector3Long one = new Vector3Long(1, 1, 1);
public static readonly Vector3Long forward = new Vector3Long(0, 0, 1);
public static readonly Vector3Long back = new Vector3Long(0, 0, -1);
public static readonly Vector3Long left = new Vector3Long(-1, 0, 0);
public static readonly Vector3Long right = new Vector3Long(1, 0, 0);
public static readonly Vector3Long up = new Vector3Long(0, 1, 0);
public static readonly Vector3Long down = new Vector3Long(0, -1, 0);
// constructor /////////////////////////////////////////////////////////
public Vector3Long(long x, long y, long z)
{
this.x = x;
this.y = y;
this.z = z;
}
// operators ///////////////////////////////////////////////////////////
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Long operator +(Vector3Long a, Vector3Long b) =>
new Vector3Long(a.x + b.x, a.y + b.y, a.z + b.z);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Long operator -(Vector3Long a, Vector3Long b) =>
new Vector3Long(a.x - b.x, a.y - b.y, a.z - b.z);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Long operator -(Vector3Long v) =>
new Vector3Long(-v.x, -v.y, -v.z);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Long operator *(Vector3Long a, long n) =>
new Vector3Long(a.x * n, a.y * n, a.z * n);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Long operator *(long n, Vector3Long a) =>
new Vector3Long(a.x * n, a.y * n, a.z * n);
// == returns true if approximately equal (with epsilon).
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector3Long a, Vector3Long b) =>
a.x == b.x &&
a.y == b.y &&
a.z == b.z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector3Long a, Vector3Long b) => !(a == b);
// NO IMPLICIT System.Numerics.Vector3Long conversion because double<->float
// would silently lose precision in large worlds.
// [i] component index. useful for iterating all components etc.
public long this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default: throw new IndexOutOfRangeException($"Vector3Long[{index}] out of range.");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default: throw new IndexOutOfRangeException($"Vector3Long[{index}] out of range.");
}
}
}
// instance functions //////////////////////////////////////////////////
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => $"({x} {y} {z})";
// equality ////////////////////////////////////////////////////////////
// implement Equals & HashCode explicitly for performance.
// calling .Equals (instead of "==") checks for exact equality.
// (API compatibility)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Vector3Long other) =>
x == other.x && y == other.y && z == other.z;
// Equals(object) can reuse Equals(Vector4)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object other) =>
other is Vector3Long vector4 && Equals(vector4);
#if UNITY_2021_3_OR_NEWER
// Unity 2019/2020 don't have HashCode.Combine yet.
// this is only to avoid reflection. without defining, it works too.
// default generated by rider
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => HashCode.Combine(x, y, z);
#endif
}
}
fileFormatVersion: 2
guid: 18efa4e349254185ad257401dd24628b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
// For future reference, here is what Transports need to do in Mirror:
//
// Connecting:
// * Transports are responsible to call either OnConnected || OnDisconnected
// in a certain time after a Connect was called. It can not end in limbo.
//
// Disconnecting:
// * Connections might disconnect voluntarily by the other end.
// * Connections might be disconnect involuntarily by the server.
// * Either way, Transports need to detect it and call OnDisconnected.
//
// Timeouts:
// * Transports should expose a configurable timeout
// * Transports are responsible for calling OnDisconnected after a timeout
//
// Channels:
// * Default channel is Reliable, as in reliable ordered (OR DISCONNECT)
// * Where possible, Unreliable should be supported (unordered, no guarantee)
//
// Other:
// * Transports functions are all bound to the main thread.
// (Transports can use other threads in the background if they manage them)
// * Transports should only process messages while the component is enabled.
//
using System;
using UnityEngine;
namespace Mirror
{
/// <summary>Abstract transport layer component</summary>
public abstract class Transport : MonoBehaviour
{
/// <summary>The current transport used by Mirror.</summary>
public static Transport active;
/// <summary>Is this transport available in the current platform?</summary>
public abstract bool Available();
/// <summary>Is this transported encrypted for secure communication?</summary>
public virtual bool IsEncrypted => false;
/// <summary>If encrypted, which cipher is used?</summary>
public virtual string EncryptionCipher => "";
// client //////////////////////////////////////////////////////////////
/// <summary>Called by Transport when the client connected to the server.</summary>
public Action OnClientConnected;
/// <summary>Called by Transport when the client received a message from the server.</summary>
public Action<ArraySegment<byte>, int> OnClientDataReceived;
/// <summary>Called by Transport when the client sent a message to the server.</summary>
// Transports are responsible for calling it because:
// - groups it together with OnReceived responsibility
// - allows transports to decide if anything was sent or not
// - allows transports to decide the actual used channel (i.e. tcp always sending reliable)
public Action<ArraySegment<byte>, int> OnClientDataSent;
/// <summary>Called by Transport when the client encountered an error.</summary>
public Action<TransportError, string> OnClientError;
/// <summary>Called by Transport when the client encountered an error.</summary>
public Action<Exception> OnClientTransportException;
/// <summary>Called by Transport when the client disconnected from the server.</summary>
public Action OnClientDisconnected;
// server //////////////////////////////////////////////////////////////
/// <summary>Called by Transport when a new client connected to the server.</summary>
public Action<int> OnServerConnected;
/// <summary>Called by Transport when the server received a message from a client.</summary>
public Action<int, ArraySegment<byte>, int> OnServerDataReceived;
/// <summary>Called by Transport when the server sent a message to a client.</summary>
// Transports are responsible for calling it because:
// - groups it together with OnReceived responsibility
// - allows transports to decide if anything was sent or not
// - allows transports to decide the actual used channel (i.e. tcp always sending reliable)
public Action<int, ArraySegment<byte>, int> OnServerDataSent;
/// <summary>Called by Transport when a server's connection encountered a problem.</summary>
/// If a Disconnect will also be raised, raise the Error first.
public Action<int, TransportError, string> OnServerError;
/// <summary>Called by Transport when a server's connection encountered a problem.</summary>
/// If a Disconnect will also be raised, raise the Error first.
public Action<int, Exception> OnServerTransportException;
/// <summary>Called by Transport when a client disconnected from the server.</summary>
public Action<int> OnServerDisconnected;
// client functions ////////////////////////////////////////////////////
/// <summary>True if the client is currently connected to the server.</summary>
public abstract bool ClientConnected();
/// <summary>Connects the client to the server at the address.</summary>
public abstract void ClientConnect(string address);
/// <summary>Connects the client to the server at the Uri.</summary>
public virtual void ClientConnect(Uri uri)
{
// By default, to keep backwards compatibility, just connect to the host
// in the uri
ClientConnect(uri.Host);
}
/// <summary>Sends a message to the server over the given channel.</summary>
// The ArraySegment is only valid until returning. Copy if needed.
public abstract void ClientSend(ArraySegment<byte> segment, int channelId = Channels.Reliable);
/// <summary>Disconnects the client from the server</summary>
public abstract void ClientDisconnect();
// server functions ////////////////////////////////////////////////////
/// <summary>Returns server address as Uri.</summary>
// Useful for NetworkDiscovery.
public abstract Uri ServerUri();
/// <summary>True if the server is currently listening for connections.</summary>
public abstract bool ServerActive();
/// <summary>Start listening for connections.</summary>
public abstract void ServerStart();
/// <summary>Send a message to a client over the given channel.</summary>
public abstract void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId = Channels.Reliable);
/// <summary>Disconnect a client from the server.</summary>
public abstract void ServerDisconnect(int connectionId);
/// <summary>Get a client's address on the server.</summary>
// Can be useful for Game Master IP bans etc.
public abstract string ServerGetClientAddress(int connectionId);
/// <summary>Stop listening and disconnect all connections.</summary>
public abstract void ServerStop();
/// <summary>Maximum message size for the given channel.</summary>
// Different channels often have different sizes, ranging from MTU to
// several megabytes.
//
// Needs to return a value at all times, even if the Transport isn't
// running or available because it's needed for initializations.
public abstract int GetMaxPacketSize(int channelId = Channels.Reliable);
/// <summary>Recommended Batching threshold for this transport.</summary>
// Uses GetMaxPacketSize by default.
// Some transports like kcp support large max packet sizes which should
// not be used for batching all the time because they end up being too
// slow (head of line blocking etc.).
public virtual int GetBatchThreshold(int channelId = Channels.Reliable)
{
return GetMaxPacketSize(channelId);
}
// block Update & LateUpdate to show warnings if Transports still use
// them instead of using
// Client/ServerEarlyUpdate: to process incoming messages
// Client/ServerLateUpdate: to process outgoing messages
// those are called by NetworkClient/Server at the right time.
//
// allows transports to implement the proper network update order of:
// process_incoming()
// update_world()
// process_outgoing()
//
// => see NetworkLoop.cs for detailed explanations!
#pragma warning disable UNT0001 // Empty Unity message
public void Update() {}
public void LateUpdate() {}
#pragma warning restore UNT0001 // Empty Unity message
/// <summary>
/// NetworkLoop NetworkEarly/LateUpdate were added for a proper network
/// update order. the goal is to:
/// process_incoming()
/// update_world()
/// process_outgoing()
/// in order to avoid unnecessary latency and data races.
/// </summary>
// => split into client and server parts so that we can cleanly call
// them from NetworkClient/Server
// => VIRTUAL for now so we can take our time to convert transports
// without breaking anything.
public virtual void ClientEarlyUpdate() {}
public virtual void ServerEarlyUpdate() {}
public virtual void ClientLateUpdate() {}
public virtual void ServerLateUpdate() {}
/// <summary>Shut down the transport, both as client and server</summary>
public abstract void Shutdown();
/// <summary>Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown.</summary>
public virtual void OnApplicationQuit()
{
// stop transport (e.g. to shut down threads)
// (when pressing Stop in the Editor, Unity keeps threads alive
// until we press Start again. so if Transports use threads, we
// really want them to end now and not after next start)
Shutdown();
}
}
}
fileFormatVersion: 2
guid: cfffcac25d6d64ced9de620159e221b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
// Mirror transport error code enum.
// most transport implementations should use a subset of this,
// and then translate the transport error codes to mirror error codes.
namespace Mirror
{
public enum TransportError : byte
{
DnsResolve, // failed to resolve a host name
Refused, // connection refused by other end. server full etc.
Timeout, // ping timeout or dead link
Congestion, // more messages than transport / network can process
InvalidReceive, // recv invalid packet (possibly intentional attack)
InvalidSend, // user tried to send invalid data
ConnectionClosed, // connection closed voluntarily or lost involuntarily
Unexpected // unexpected error / exception, requires fix.
}
}
fileFormatVersion: 2
guid: ce162bdedd704db9b8c35d163f0c1d54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
// safety fuse for weaver to flip.
// runtime can check this to ensure weaving succeded.
// otherwise running server/client would give lots of random 'writer not found' etc. errors.
// this is much cleaner.
//
// note that ILPostProcessor errors already block entering playmode.
// however, issues could still stop the weaving from running at all.
// WeaverFuse can check if it actually ran.
namespace Mirror
{
public static class WeaverFuse
{
// this trick only works for ILPostProcessor.
// CompilationFinishedHook can't weaver Mirror.dll.
public static bool Weaved() =>
#if UNITY_2020_3_OR_NEWER
false;
#else
true;
#endif
}
}
fileFormatVersion: 2
guid: 4de3dfbcbd2e41fcac947c04bcac52c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 2539267b6934a4026a505690a1e1eda2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
// Android NetworkDiscovery Multicast fix
// https://github.com/vis2k/Mirror/pull/2887
using UnityEditor;
using UnityEngine;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using System.Xml;
using System.IO;
#if UNITY_ANDROID
using UnityEditor.Android;
#endif
[InitializeOnLoad]
public class AndroidManifestHelper : IPreprocessBuildWithReport, IPostprocessBuildWithReport
#if UNITY_ANDROID
, IPostGenerateGradleAndroidProject
#endif
{
public int callbackOrder { get { return 99999; } }
#if UNITY_ANDROID
public void OnPostGenerateGradleAndroidProject(string path)
{
string manifestFolder = Path.Combine(path, "src/main");
string sourceFile = manifestFolder + "/AndroidManifest.xml";
// Load android manifest file
XmlDocument doc = new XmlDocument();
doc.Load(sourceFile);
string androidNamepsaceURI;
XmlElement element = (XmlElement)doc.SelectSingleNode("/manifest");
if (element == null)
{
UnityEngine.Debug.LogError("Could not find manifest tag in android manifest.");
return;
}
// Get android namespace URI from the manifest
androidNamepsaceURI = element.GetAttribute("xmlns:android");
if (string.IsNullOrEmpty(androidNamepsaceURI))
{
UnityEngine.Debug.LogError("Could not find Android Namespace in manifest.");
return;
}
AddOrRemoveTag(doc,
androidNamepsaceURI,
"/manifest",
"uses-permission",
"android.permission.CHANGE_WIFI_MULTICAST_STATE",
true,
false);
AddOrRemoveTag(doc,
androidNamepsaceURI,
"/manifest",
"uses-permission",
"android.permission.INTERNET",
true,
false);
doc.Save(sourceFile);
}
#endif
static void AddOrRemoveTag(XmlDocument doc, string @namespace, string path, string elementName, string name, bool required, bool modifyIfFound, params string[] attrs) // name, value pairs
{
var nodes = doc.SelectNodes(path + "/" + elementName);
XmlElement element = null;
foreach (XmlElement e in nodes)
{
if (name == null || name == e.GetAttribute("name", @namespace))
{
element = e;
break;
}
}
if (required)
{
if (element == null)
{
var parent = doc.SelectSingleNode(path);
element = doc.CreateElement(elementName);
element.SetAttribute("name", @namespace, name);
parent.AppendChild(element);
}
for (int i = 0; i < attrs.Length; i += 2)
{
if (modifyIfFound || string.IsNullOrEmpty(element.GetAttribute(attrs[i], @namespace)))
{
if (attrs[i + 1] != null)
{
element.SetAttribute(attrs[i], @namespace, attrs[i + 1]);
}
else
{
element.RemoveAttribute(attrs[i], @namespace);
}
}
}
}
else
{
if (element != null && modifyIfFound)
{
element.ParentNode.RemoveChild(element);
}
}
}
public void OnPostprocessBuild(BuildReport report) {}
public void OnPreprocessBuild(BuildReport report) {}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment