Decompiled source of BLOODLINK v0.114.0
BepInEx/plugins/LiteNetLib.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using LiteNetLib.Layers; using LiteNetLib.Utils; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Ruslan Pyrch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2026 Ruslan Pyrch")] [assembly: AssemblyDescription("Lite reliable UDP library for .NET, Mono, and .NET Core")] [assembly: AssemblyFileVersion("2.1.4")] [assembly: AssemblyInformationalVersion("1.0.0+4d3de1e93abaead30199bf572f4a3363f854e14b")] [assembly: AssemblyProduct("LiteNetLib")] [assembly: AssemblyTitle("LiteNetLib")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RevenantX/LiteNetLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.4.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } } namespace LiteNetLib { internal abstract class BaseChannel { protected readonly LiteNetPeer Peer; protected readonly Queue<NetPacket> OutgoingQueue = new Queue<NetPacket>(64); private int _isAddedToPeerChannelSendQueue; public int PacketsInQueue => OutgoingQueue.Count; protected BaseChannel(LiteNetPeer peer) { Peer = peer; } public void AddToQueue(NetPacket packet) { lock (OutgoingQueue) { OutgoingQueue.Enqueue(packet); } AddToPeerChannelSendQueue(); } protected void AddToPeerChannelSendQueue() { if (Interlocked.CompareExchange(ref _isAddedToPeerChannelSendQueue, 1, 0) == 0) { Peer.AddToReliableChannelSendQueue(this); } } public bool SendAndCheckQueue() { bool num = SendNextPackets(); if (!num) { Interlocked.Exchange(ref _isAddedToPeerChannelSendQueue, 0); } return num; } public abstract bool SendNextPackets(); public abstract bool ProcessPacket(NetPacket packet); } internal enum ConnectionRequestResult { None, Accept, Reject, RejectForce } public class LiteConnectionRequest { private readonly LiteNetManager _listener; private int _used; internal NetConnectRequestPacket InternalPacket; public readonly IPEndPoint RemoteEndPoint; public NetDataReader Data => InternalPacket.Data; internal ConnectionRequestResult Result { get; private set; } internal void UpdateRequest(NetConnectRequestPacket connectRequest) { if (connectRequest.ConnectionTime >= InternalPacket.ConnectionTime && (connectRequest.ConnectionTime != InternalPacket.ConnectionTime || connectRequest.ConnectionNumber != InternalPacket.ConnectionNumber)) { InternalPacket = connectRequest; } } private bool TryActivate() { return Interlocked.CompareExchange(ref _used, 1, 0) == 0; } internal LiteConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket, LiteNetManager listener) { InternalPacket = requestPacket; RemoteEndPoint = remoteEndPoint; _listener = listener; } public LiteNetPeer AcceptIfKey(string key) { if (!TryActivate()) { return null; } try { if (Data.GetString() == key) { Result = ConnectionRequestResult.Accept; } } catch { NetDebug.WriteError("[AC] Invalid incoming data"); } if (Result == ConnectionRequestResult.Accept) { return _listener.OnConnectionSolved(this, null, 0, 0); } Result = ConnectionRequestResult.Reject; _listener.OnConnectionSolved(this, null, 0, 0); return null; } public LiteNetPeer Accept() { if (!TryActivate()) { return null; } Result = ConnectionRequestResult.Accept; return _listener.OnConnectionSolved(this, null, 0, 0); } public void Reject(byte[] rejectData, int start, int length, bool force) { if (TryActivate()) { Result = (force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject); _listener.OnConnectionSolved(this, rejectData, start, length); } } public void Reject(byte[] rejectData, int start, int length) { Reject(rejectData, start, length, force: false); } public void RejectForce(byte[] rejectData, int start, int length) { Reject(rejectData, start, length, force: true); } public void RejectForce() { Reject(null, 0, 0, force: true); } public void RejectForce(byte[] rejectData) { Reject(rejectData, 0, rejectData.Length, force: true); } public void RejectForce(NetDataWriter rejectData) { Reject(rejectData.Data, 0, rejectData.Length, force: true); } public void Reject() { Reject(null, 0, 0, force: false); } public void Reject(byte[] rejectData) { Reject(rejectData, 0, rejectData.Length, force: false); } public void Reject(NetDataWriter rejectData) { Reject(rejectData.Data, 0, rejectData.Length, force: false); } } public class ConnectionRequest : LiteConnectionRequest { internal ConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket, LiteNetManager listener) : base(remoteEndPoint, requestPacket, listener) { } public new NetPeer AcceptIfKey(string key) { return (NetPeer)base.AcceptIfKey(key); } public new NetPeer Accept() { return (NetPeer)base.Accept(); } } public enum UnconnectedMessageType { BasicMessage, Broadcast } public enum DisconnectReason { ConnectionFailed, Timeout, HostUnreachable, NetworkUnreachable, RemoteConnectionClose, DisconnectPeerCalled, ConnectionRejected, InvalidProtocol, UnknownHost, Reconnect, PeerToPeerConnection, PeerNotFound } public struct DisconnectInfo { public DisconnectReason Reason; public SocketError SocketErrorCode; public NetPacketReader AdditionalData; } public interface INetEventListener { void OnPeerConnected(NetPeer peer); void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); void OnNetworkError(IPEndPoint endPoint, SocketError socketError); void OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod); void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); void OnNetworkLatencyUpdate(NetPeer peer, int latency); void OnConnectionRequest(ConnectionRequest request); void OnMessageDelivered(NetPeer peer, object userData) { } void OnNtpResponse(NtpPacket packet) { } void OnPeerAddressChanged(NetPeer peer, IPEndPoint previousAddress) { } } public interface ILiteNetEventListener { void OnPeerConnected(LiteNetPeer peer); void OnPeerDisconnected(LiteNetPeer peer, DisconnectInfo disconnectInfo); void OnNetworkError(IPEndPoint endPoint, SocketError socketError) { } void OnNetworkReceive(LiteNetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod); void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { } void OnNetworkLatencyUpdate(LiteNetPeer peer, int latency) { } void OnConnectionRequest(LiteConnectionRequest request); void OnPeerAddressChanged(LiteNetPeer peer, IPEndPoint previousAddress) { } void OnMessageDelivered(LiteNetPeer peer, object userData) { } } public class EventBasedNetListener : INetEventListener { public delegate void OnPeerConnected(NetPeer peer); public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError); public delegate void OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod); public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency); public delegate void OnConnectionRequest(ConnectionRequest request); public delegate void OnDeliveryEvent(NetPeer peer, object userData); public delegate void OnNtpResponseEvent(NtpPacket packet); public delegate void OnPeerAddressChangedEvent(NetPeer peer, IPEndPoint previousAddress); public event OnPeerConnected PeerConnectedEvent; public event OnPeerDisconnected PeerDisconnectedEvent; public event OnNetworkError NetworkErrorEvent; public event OnNetworkReceive NetworkReceiveEvent; public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; public event OnConnectionRequest ConnectionRequestEvent; public event OnDeliveryEvent DeliveryEvent; public event OnNtpResponseEvent NtpResponseEvent; public event OnPeerAddressChangedEvent PeerAddressChangedEvent; public void ClearPeerConnectedEvent() { this.PeerConnectedEvent = null; } public void ClearPeerDisconnectedEvent() { this.PeerDisconnectedEvent = null; } public void ClearNetworkErrorEvent() { this.NetworkErrorEvent = null; } public void ClearNetworkReceiveEvent() { this.NetworkReceiveEvent = null; } public void ClearNetworkReceiveUnconnectedEvent() { this.NetworkReceiveUnconnectedEvent = null; } public void ClearNetworkLatencyUpdateEvent() { this.NetworkLatencyUpdateEvent = null; } public void ClearConnectionRequestEvent() { this.ConnectionRequestEvent = null; } public void ClearDeliveryEvent() { this.DeliveryEvent = null; } public void ClearNtpResponseEvent() { this.NtpResponseEvent = null; } public void ClearPeerAddressChangedEvent() { this.PeerAddressChangedEvent = null; } void INetEventListener.OnPeerConnected(NetPeer peer) { this.PeerConnectedEvent?.Invoke(peer); } void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { this.PeerDisconnectedEvent?.Invoke(peer, disconnectInfo); } void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) { this.NetworkErrorEvent?.Invoke(endPoint, socketErrorCode); } void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod) { this.NetworkReceiveEvent?.Invoke(peer, reader, channelNumber, deliveryMethod); } void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { this.NetworkReceiveUnconnectedEvent?.Invoke(remoteEndPoint, reader, messageType); } void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) { this.NetworkLatencyUpdateEvent?.Invoke(peer, latency); } void INetEventListener.OnConnectionRequest(ConnectionRequest request) { this.ConnectionRequestEvent?.Invoke(request); } void INetEventListener.OnMessageDelivered(NetPeer peer, object userData) { this.DeliveryEvent?.Invoke(peer, userData); } void INetEventListener.OnNtpResponse(NtpPacket packet) { this.NtpResponseEvent?.Invoke(packet); } void INetEventListener.OnPeerAddressChanged(NetPeer peer, IPEndPoint previousAddress) { this.PeerAddressChangedEvent?.Invoke(peer, previousAddress); } } public class EventBasedLiteNetListener : ILiteNetEventListener { public delegate void OnPeerConnected(LiteNetPeer peer); public delegate void OnPeerDisconnected(LiteNetPeer peer, DisconnectInfo disconnectInfo); public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError); public delegate void OnNetworkReceive(LiteNetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod); public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); public delegate void OnNetworkLatencyUpdate(LiteNetPeer peer, int latency); public delegate void OnConnectionRequest(LiteConnectionRequest request); public delegate void OnDeliveryEvent(LiteNetPeer peer, object userData); public delegate void OnPeerAddressChangedEvent(LiteNetPeer peer, IPEndPoint previousAddress); public event OnPeerConnected PeerConnectedEvent; public event OnPeerDisconnected PeerDisconnectedEvent; public event OnNetworkError NetworkErrorEvent; public event OnNetworkReceive NetworkReceiveEvent; public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; public event OnConnectionRequest ConnectionRequestEvent; public event OnDeliveryEvent DeliveryEvent; public event OnPeerAddressChangedEvent PeerAddressChangedEvent; public void ClearPeerConnectedEvent() { this.PeerConnectedEvent = null; } public void ClearPeerDisconnectedEvent() { this.PeerDisconnectedEvent = null; } public void ClearNetworkErrorEvent() { this.NetworkErrorEvent = null; } public void ClearNetworkReceiveEvent() { this.NetworkReceiveEvent = null; } public void ClearNetworkReceiveUnconnectedEvent() { this.NetworkReceiveUnconnectedEvent = null; } public void ClearNetworkLatencyUpdateEvent() { this.NetworkLatencyUpdateEvent = null; } public void ClearConnectionRequestEvent() { this.ConnectionRequestEvent = null; } public void ClearDeliveryEvent() { this.DeliveryEvent = null; } public void ClearPeerAddressChangedEvent() { this.PeerAddressChangedEvent = null; } void ILiteNetEventListener.OnPeerConnected(LiteNetPeer peer) { this.PeerConnectedEvent?.Invoke(peer); } void ILiteNetEventListener.OnPeerDisconnected(LiteNetPeer peer, DisconnectInfo disconnectInfo) { this.PeerDisconnectedEvent?.Invoke(peer, disconnectInfo); } void ILiteNetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) { this.NetworkErrorEvent?.Invoke(endPoint, socketErrorCode); } void ILiteNetEventListener.OnNetworkReceive(LiteNetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod) { this.NetworkReceiveEvent?.Invoke(peer, reader, deliveryMethod); } void ILiteNetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { this.NetworkReceiveUnconnectedEvent?.Invoke(remoteEndPoint, reader, messageType); } void ILiteNetEventListener.OnNetworkLatencyUpdate(LiteNetPeer peer, int latency) { this.NetworkLatencyUpdateEvent?.Invoke(peer, latency); } void ILiteNetEventListener.OnConnectionRequest(LiteConnectionRequest request) { this.ConnectionRequestEvent?.Invoke(request); } void ILiteNetEventListener.OnMessageDelivered(LiteNetPeer peer, object userData) { this.DeliveryEvent?.Invoke(peer, userData); } void ILiteNetEventListener.OnPeerAddressChanged(LiteNetPeer peer, IPEndPoint previousAddress) { this.PeerAddressChangedEvent?.Invoke(peer, previousAddress); } } public sealed class NetConnectRequestPacket { public const int HeaderSize = 18; public readonly long ConnectionTime; public byte ConnectionNumber; public readonly byte[] TargetAddress; public readonly NetDataReader Data; public readonly int PeerId; private NetConnectRequestPacket(long connectionTime, byte connectionNumber, int localId, byte[] targetAddress, NetDataReader data) { ConnectionTime = connectionTime; ConnectionNumber = connectionNumber; TargetAddress = targetAddress; Data = data; PeerId = localId; } internal static int GetProtocolId(NetPacket packet) { return BitConverter.ToInt32(packet.RawData, 1); } internal static NetConnectRequestPacket FromData(NetPacket packet) { if (packet.ConnectionNumber >= 4) { return null; } long connectionTime = BitConverter.ToInt64(packet.RawData, 5); int localId = BitConverter.ToInt32(packet.RawData, 13); int num = packet.RawData[17]; if (num != 16 && num != 28) { return null; } byte[] array = new byte[num]; Buffer.BlockCopy(packet.RawData, 18, array, 0, num); NetDataReader netDataReader = new NetDataReader(null, 0, 0); if (packet.Size > 18 + num) { netDataReader.SetSource(packet.RawData, 18 + num, packet.Size); } return new NetConnectRequestPacket(connectionTime, packet.ConnectionNumber, localId, array, netDataReader); } internal static NetPacket Make(ReadOnlySpan<byte> connectData, SocketAddress addressBytes, long connectTime, int localId) { NetPacket netPacket = new NetPacket(PacketProperty.ConnectRequest, connectData.Length + addressBytes.Size); FastBitConverter.GetBytes(netPacket.RawData, 1, 13); FastBitConverter.GetBytes(netPacket.RawData, 5, connectTime); FastBitConverter.GetBytes(netPacket.RawData, 13, localId); netPacket.RawData[17] = (byte)addressBytes.Size; for (int i = 0; i < addressBytes.Size; i++) { netPacket.RawData[18 + i] = addressBytes[i]; } connectData.CopyTo(netPacket.RawData.AsSpan(18 + addressBytes.Size)); return netPacket; } } internal sealed class NetConnectAcceptPacket { public const int Size = 15; public readonly long ConnectionTime; public readonly byte ConnectionNumber; public readonly int PeerId; public readonly bool PeerNetworkChanged; private NetConnectAcceptPacket(long connectionTime, byte connectionNumber, int peerId, bool peerNetworkChanged) { ConnectionTime = connectionTime; ConnectionNumber = connectionNumber; PeerId = peerId; PeerNetworkChanged = peerNetworkChanged; } public static NetConnectAcceptPacket FromData(NetPacket packet) { if (packet.Size != 15) { return null; } long connectionTime = BitConverter.ToInt64(packet.RawData, 1); byte b = packet.RawData[9]; if (b >= 4) { return null; } byte b2 = packet.RawData[10]; if (b2 > 1) { return null; } int num = BitConverter.ToInt32(packet.RawData, 11); if (num < 0) { return null; } return new NetConnectAcceptPacket(connectionTime, b, num, b2 == 1); } public static NetPacket Make(long connectTime, byte connectNum, int localPeerId) { NetPacket netPacket = new NetPacket(PacketProperty.ConnectAccept, 0); FastBitConverter.GetBytes(netPacket.RawData, 1, connectTime); netPacket.RawData[9] = connectNum; FastBitConverter.GetBytes(netPacket.RawData, 11, localPeerId); return netPacket; } public static NetPacket MakeNetworkChanged(LiteNetPeer peer) { NetPacket netPacket = new NetPacket(PacketProperty.PeerNotFound, 14); FastBitConverter.GetBytes(netPacket.RawData, 1, peer.ConnectTime); netPacket.RawData[9] = peer.ConnectionNum; netPacket.RawData[10] = 1; FastBitConverter.GetBytes(netPacket.RawData, 11, peer.RemoteId); return netPacket; } } public class LiteNetManager : IEnumerable<LiteNetPeer>, IEnumerable { public struct NetPeerEnumerator<T> : IEnumerator<T>, IEnumerator, IDisposable where T : LiteNetPeer { private readonly T _initialPeer; private T _p; public T Current => _p; object IEnumerator.Current => _p; public NetPeerEnumerator(T p) { _initialPeer = p; _p = null; } public void Dispose() { } public bool MoveNext() { _p = ((_p == null) ? _initialPeer : ((T)_p.NextPeer)); return _p != null; } public void Reset() { throw new NotSupportedException(); } } private struct Slot { internal int HashCode; internal int Next; internal LiteNetPeer Value; } private readonly Random _randomGenerator = new Random(); private const int MinLatencyThreshold = 5; private Thread _logicThread; private bool _manualMode; private readonly AutoResetEvent _updateTriggerEvent = new AutoResetEvent(initialState: true); private NetEvent _pendingEventHead; private NetEvent _pendingEventTail; private NetEvent _netEventPoolHead; private readonly ILiteNetEventListener _netEventListener; private readonly Dictionary<IPEndPoint, LiteConnectionRequest> _requestsDict = new Dictionary<IPEndPoint, LiteConnectionRequest>(); private long _connectedPeersCount; private readonly PacketLayerBase _extraPacketLayer; private int _lastPeerId; private ConcurrentQueue<int> _peerIds = new ConcurrentQueue<int>(); private readonly object _eventLock = new object(); private volatile bool _isRunning; private bool _dropPacket; public bool UnconnectedMessagesEnabled; public bool NatPunchEnabled; public int UpdateTime = 15; public int PingInterval = 1000; public int DisconnectTimeout = 5000; public bool SimulatePacketLoss; public bool SimulateLatency; public int SimulationPacketLossChance = 10; public int SimulationMinLatency = 30; public int SimulationMaxLatency = 100; public bool UnsyncedEvents; public bool UnsyncedReceiveEvent; public bool UnsyncedDeliveryEvent; public bool BroadcastReceiveEnabled; public int ReconnectDelay = 500; public int MaxConnectAttempts = 10; public bool ReuseAddress; public bool DontRoute; public readonly NetStatistics Statistics = new NetStatistics(); public bool EnableStatistics; public ushort MaxFragmentsCount = ushort.MaxValue; private readonly Lazy<NatPunchModule> _natPunchModule; public bool AutoRecycle; public bool IPv6Enabled = true; public int MtuOverride; public bool MtuDiscovery; public bool UseNativeSockets; public bool DisconnectOnUnreachable; public bool AllowPeerAddressChange; public int MaxPacketPerManualReceive = 256; private const int MaxPrimeArrayLength = 2147483587; private const int HashPrime = 101; private const int Lower31BitMask = int.MaxValue; private static readonly int[] Primes; private int[] _buckets; private Slot[] _slots; private int _count; private int _lastIndex; private int _freeList = -1; private LiteNetPeer[] _peersArray = new LiteNetPeer[32]; protected readonly ReaderWriterLockSlim _peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); protected volatile LiteNetPeer _headPeer; private NetPacket _poolHead; private int _poolCount; private readonly object _poolLock = new object(); public int PacketPoolSize = 1000; protected Socket _udpSocketv4; private Socket _udpSocketv6; private Thread _receiveThread; private IPEndPoint _bufferEndPointv4; private IPEndPoint _bufferEndPointv6; private const int SioUdpConnreset = -1744830452; private static readonly IPAddress MulticastAddressV6; public static readonly bool IPv6Support; internal bool NotConnected; public int ReceivePollingTime = 50000; public NatPunchModule NatPunchModule => _natPunchModule.Value; public bool IsRunning => _isRunning; public int LocalPort { get; private set; } public LiteNetPeer FirstPeer => _headPeer; public int ConnectedPeersCount => (int)Interlocked.Read(ref _connectedPeersCount); public int ExtraPacketSizeForLayer => _extraPacketLayer?.ExtraPacketSizeForLayer ?? 0; public int PoolCount => _poolCount; public short Ttl { get { return _udpSocketv4.Ttl; } internal set { _udpSocketv4.Ttl = value; } } public LiteNetManager(ILiteNetEventListener listener, PacketLayerBase extraPacketLayer = null) { _netEventListener = listener; _natPunchModule = new Lazy<NatPunchModule>(() => new NatPunchModule(this)); _extraPacketLayer = extraPacketLayer; } internal void ConnectionLatencyUpdated(LiteNetPeer fromPeer, int latency) { CreateEvent(NetEvent.EType.ConnectionLatencyUpdated, fromPeer, null, SocketError.Success, latency, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); } internal void MessageDelivered(LiteNetPeer fromPeer, object userData) { CreateEvent(NetEvent.EType.MessageDelivered, fromPeer, null, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0, null, userData); } internal void DisconnectPeerForce(LiteNetPeer peer, DisconnectReason reason, SocketError socketErrorCode, NetPacket eventData) { DisconnectPeer(peer, reason, socketErrorCode, force: true, null, 0, 0, eventData); } private void DisconnectPeer(LiteNetPeer peer, DisconnectReason reason, SocketError socketErrorCode, bool force, byte[] data, int start, int count, NetPacket eventData) { switch (peer.Shutdown(data, start, count, force)) { case ShutdownResult.None: return; case ShutdownResult.WasConnected: Interlocked.Decrement(ref _connectedPeersCount); break; } CreateEvent(NetEvent.EType.Disconnect, peer, null, socketErrorCode, 0, reason, null, DeliveryMethod.Unreliable, 0, eventData); } private void CreateEvent(NetEvent.EType type, LiteNetPeer peer = null, IPEndPoint remoteEndPoint = null, SocketError errorCode = SocketError.Success, int latency = 0, DisconnectReason disconnectReason = DisconnectReason.ConnectionFailed, LiteConnectionRequest connectionRequest = null, DeliveryMethod deliveryMethod = DeliveryMethod.Unreliable, byte channelNumber = 0, NetPacket readerSource = null, object userData = null) { bool flag = UnsyncedEvents; switch (type) { case NetEvent.EType.Connect: Interlocked.Increment(ref _connectedPeersCount); break; case NetEvent.EType.MessageDelivered: flag = UnsyncedDeliveryEvent; break; } NetEvent netEvent; lock (_eventLock) { netEvent = _netEventPoolHead; if (netEvent == null) { netEvent = new NetEvent(this); } else { _netEventPoolHead = netEvent.Next; } } netEvent.Next = null; netEvent.Type = type; netEvent.DataReader.SetSource(readerSource, readerSource?.HeaderSize ?? 0); netEvent.Peer = peer; netEvent.RemoteEndPoint = remoteEndPoint; netEvent.Latency = latency; netEvent.ErrorCode = errorCode; netEvent.DisconnectReason = disconnectReason; netEvent.ConnectionRequest = connectionRequest; netEvent.DeliveryMethod = deliveryMethod; netEvent.ChannelNumber = channelNumber; netEvent.UserData = userData; if (flag || _manualMode) { ProcessEvent(netEvent); return; } lock (_eventLock) { if (_pendingEventTail == null) { _pendingEventHead = netEvent; } else { _pendingEventTail.Next = netEvent; } _pendingEventTail = netEvent; } } protected virtual void ProcessEvent(NetEvent evt) { bool isNull = evt.DataReader.IsNull; switch (evt.Type) { case NetEvent.EType.Connect: _netEventListener.OnPeerConnected(evt.Peer); break; case NetEvent.EType.Disconnect: { DisconnectInfo disconnectInfo = default(DisconnectInfo); disconnectInfo.Reason = evt.DisconnectReason; disconnectInfo.AdditionalData = evt.DataReader; disconnectInfo.SocketErrorCode = evt.ErrorCode; DisconnectInfo disconnectInfo2 = disconnectInfo; _netEventListener.OnPeerDisconnected(evt.Peer, disconnectInfo2); break; } case NetEvent.EType.Receive: _netEventListener.OnNetworkReceive(evt.Peer, evt.DataReader, evt.DeliveryMethod); break; case NetEvent.EType.ReceiveUnconnected: _netEventListener.OnNetworkReceiveUnconnected(evt.RemoteEndPoint, evt.DataReader, UnconnectedMessageType.BasicMessage); break; case NetEvent.EType.Broadcast: _netEventListener.OnNetworkReceiveUnconnected(evt.RemoteEndPoint, evt.DataReader, UnconnectedMessageType.Broadcast); break; case NetEvent.EType.Error: _netEventListener.OnNetworkError(evt.RemoteEndPoint, evt.ErrorCode); break; case NetEvent.EType.ConnectionLatencyUpdated: _netEventListener.OnNetworkLatencyUpdate(evt.Peer, evt.Latency); break; case NetEvent.EType.ConnectionRequest: _netEventListener.OnConnectionRequest(evt.ConnectionRequest); break; case NetEvent.EType.MessageDelivered: _netEventListener.OnMessageDelivered(evt.Peer, evt.UserData); break; case NetEvent.EType.PeerAddressChanged: { _peersLock.EnterUpgradeableReadLock(); IPEndPoint iPEndPoint = null; if (ContainsPeer(evt.Peer)) { _peersLock.EnterWriteLock(); RemovePeerFromSet(evt.Peer); iPEndPoint = new IPEndPoint(evt.Peer.Address, evt.Peer.Port); evt.Peer.FinishEndPointChange(evt.RemoteEndPoint); AddPeerToSet(evt.Peer); _peersLock.ExitWriteLock(); } _peersLock.ExitUpgradeableReadLock(); if (iPEndPoint != null) { _netEventListener.OnPeerAddressChanged(evt.Peer, iPEndPoint); } break; } } if (isNull) { RecycleEvent(evt); } else if (AutoRecycle) { evt.DataReader.RecycleInternal(); } } internal void RecycleEvent(NetEvent evt) { evt.Peer = null; evt.ErrorCode = SocketError.Success; evt.RemoteEndPoint = null; evt.ConnectionRequest = null; lock (_eventLock) { evt.Next = _netEventPoolHead; _netEventPoolHead = evt; } } protected virtual void ProcessNtpRequests(float elapsedMilliseconds) { } private void UpdateLogic() { List<LiteNetPeer> list = new List<LiteNetPeer>(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (_isRunning) { try { float num = (float)((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0); num = ((num <= 0f) ? 0.001f : num); stopwatch.Restart(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if (liteNetPeer.ConnectionState == ConnectionState.Disconnected && liteNetPeer.TimeSinceLastPacket > (float)DisconnectTimeout) { list.Add(liteNetPeer); } else { liteNetPeer.Update(num); } } if (list.Count > 0) { _peersLock.EnterWriteLock(); for (int i = 0; i < list.Count; i++) { RemovePeer(list[i], enableWriteLock: false); } _peersLock.ExitWriteLock(); list.Clear(); } ProcessNtpRequests(num); int num2 = UpdateTime - (int)stopwatch.ElapsedMilliseconds; if (num2 > 0) { _updateTriggerEvent.WaitOne(num2); } } catch (ThreadAbortException) { return; } catch (Exception ex2) { NetDebug.WriteError("[NM] LogicThread error: " + ex2); } } stopwatch.Stop(); } [Conditional("DEBUG")] [Conditional("SIMULATE_NETWORK")] private void ProcessDelayedPackets() { _ = SimulateLatency; } public void ManualUpdate(float elapsedMilliseconds) { if (!_manualMode) { return; } for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if (liteNetPeer.ConnectionState == ConnectionState.Disconnected && liteNetPeer.TimeSinceLastPacket > (float)DisconnectTimeout) { RemovePeer(liteNetPeer, enableWriteLock: false); } else { liteNetPeer.Update(elapsedMilliseconds); } } ProcessNtpRequests(elapsedMilliseconds); } protected virtual LiteNetPeer CreateOutgoingPeer(IPEndPoint remoteEndPoint, int id, byte connectNum, ReadOnlySpan<byte> connectData) { return new LiteNetPeer(this, remoteEndPoint, id, connectNum, connectData); } protected virtual LiteNetPeer CreateIncomingPeer(LiteConnectionRequest request, int id) { return new LiteNetPeer(this, request, id); } protected virtual LiteNetPeer CreateRejectPeer(IPEndPoint remoteEndPoint, int id) { return new LiteNetPeer(this, remoteEndPoint, id); } protected virtual LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket) { return new LiteConnectionRequest(remoteEndPoint, requestPacket, this); } internal LiteNetPeer OnConnectionSolved(LiteConnectionRequest request, byte[] rejectData, int start, int length) { LiteNetPeer actualValue = null; if (request.Result == ConnectionRequestResult.RejectForce) { if (rejectData != null && length > 0) { NetPacket netPacket = PoolGetWithProperty(PacketProperty.Disconnect, length); netPacket.ConnectionNumber = request.InternalPacket.ConnectionNumber; FastBitConverter.GetBytes(netPacket.RawData, 1, request.InternalPacket.ConnectionTime); if (netPacket.Size >= NetConstants.PossibleMtu[0]) { NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU!"); } else { Buffer.BlockCopy(rejectData, start, netPacket.RawData, 9, length); } SendRawAndRecycle(netPacket, request.RemoteEndPoint); } lock (_requestsDict) { _requestsDict.Remove(request.RemoteEndPoint); } } else { lock (_requestsDict) { if (!TryGetPeer(request.RemoteEndPoint, out actualValue)) { if (request.Result == ConnectionRequestResult.Reject) { actualValue = CreateRejectPeer(request.RemoteEndPoint, GetNextPeerId()); actualValue.Reject(request.InternalPacket, rejectData, start, length); AddPeer(actualValue); } else { actualValue = CreateIncomingPeer(request, GetNextPeerId()); AddPeer(actualValue); CreateEvent(NetEvent.EType.Connect, actualValue, null, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); } } _requestsDict.Remove(request.RemoteEndPoint); } } return actualValue; } private int GetNextPeerId() { if (!_peerIds.TryDequeue(out var result)) { return _lastPeerId++; } return result; } private void ProcessConnectRequest(IPEndPoint remoteEndPoint, LiteNetPeer netPeer, NetConnectRequestPacket connRequest) { if (netPeer != null) { ConnectRequestResult connectRequestResult = netPeer.ProcessConnectRequest(connRequest); switch (connectRequestResult) { default: return; case ConnectRequestResult.Reconnection: DisconnectPeerForce(netPeer, DisconnectReason.Reconnect, SocketError.Success, null); RemovePeer(netPeer, enableWriteLock: true); break; case ConnectRequestResult.NewConnection: RemovePeer(netPeer, enableWriteLock: true); break; case ConnectRequestResult.P2PLose: DisconnectPeerForce(netPeer, DisconnectReason.PeerToPeerConnection, SocketError.Success, null); RemovePeer(netPeer, enableWriteLock: true); break; } if (connectRequestResult != ConnectRequestResult.P2PLose) { connRequest.ConnectionNumber = (byte)((netPeer.ConnectionNum + 1) % 4); } } LiteConnectionRequest value; lock (_requestsDict) { if (_requestsDict.TryGetValue(remoteEndPoint, out value)) { value.UpdateRequest(connRequest); return; } value = CreateConnectionRequest(remoteEndPoint, connRequest); _requestsDict.Add(remoteEndPoint, value); } CreateEvent(NetEvent.EType.ConnectionRequest, null, null, SocketError.Success, 0, DisconnectReason.ConnectionFailed, value, DeliveryMethod.Unreliable, 0); } private void OnMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) { if (packet.Size == 0) { PoolRecycle(packet); return; } _dropPacket = false; if (!_dropPacket) { HandleMessageReceived(packet, remoteEndPoint); } } [Conditional("DEBUG")] [Conditional("SIMULATE_NETWORK")] private void HandleSimulateLatency(NetPacket packet, IPEndPoint remoteEndPoint) { _ = SimulateLatency; } [Conditional("DEBUG")] [Conditional("SIMULATE_NETWORK")] private void HandleSimulatePacketLoss() { if (SimulatePacketLoss && _randomGenerator.NextDouble() * 100.0 < (double)SimulationPacketLossChance) { _dropPacket = true; } } internal virtual bool CustomMessageHandle(NetPacket packet, IPEndPoint remoteEndPoint) { return false; } private void HandleMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) { int size = packet.Size; if (EnableStatistics) { Statistics.IncrementPacketsReceived(); Statistics.AddBytesReceived(size); } if (CustomMessageHandle(packet, remoteEndPoint)) { return; } if (_extraPacketLayer != null) { _extraPacketLayer.ProcessInboundPacket(ref remoteEndPoint, ref packet.RawData, ref packet.Size); if (packet.Size == 0) { return; } } if (!packet.Verify()) { NetDebug.WriteError("[NM] DataReceived: bad!"); PoolRecycle(packet); return; } switch (packet.Property) { case PacketProperty.ConnectRequest: if (NetConnectRequestPacket.GetProtocolId(packet) != 13) { SendRawAndRecycle(PoolGetWithProperty(PacketProperty.InvalidProtocol), remoteEndPoint); return; } break; case PacketProperty.Broadcast: if (BroadcastReceiveEnabled) { CreateEvent(NetEvent.EType.Broadcast, null, remoteEndPoint, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0, packet); } return; case PacketProperty.UnconnectedMessage: if (UnconnectedMessagesEnabled) { CreateEvent(NetEvent.EType.ReceiveUnconnected, null, remoteEndPoint, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0, packet); } return; case PacketProperty.NatMessage: if (NatPunchEnabled) { NatPunchModule.ProcessMessage(remoteEndPoint, packet); } return; } LiteNetPeer actualValue = remoteEndPoint as LiteNetPeer; bool flag = actualValue != null || TryGetPeer(remoteEndPoint, out actualValue); if (flag && EnableStatistics) { actualValue.Statistics.IncrementPacketsReceived(); actualValue.Statistics.AddBytesReceived(size); } switch (packet.Property) { case PacketProperty.ConnectRequest: { NetConnectRequestPacket netConnectRequestPacket = NetConnectRequestPacket.FromData(packet); if (netConnectRequestPacket != null) { ProcessConnectRequest(remoteEndPoint, actualValue, netConnectRequestPacket); } break; } case PacketProperty.PeerNotFound: if (flag) { if (actualValue.ConnectionState == ConnectionState.Connected) { if (packet.Size == 1) { actualValue.ResetMtu(); SendRaw(NetConnectAcceptPacket.MakeNetworkChanged(actualValue), remoteEndPoint); } else if (packet.Size == 2 && packet.RawData[1] == 1) { DisconnectPeerForce(actualValue, DisconnectReason.PeerNotFound, SocketError.Success, null); } } } else { if (packet.Size <= 1) { break; } bool flag2 = false; if (AllowPeerAddressChange) { NetConnectAcceptPacket netConnectAcceptPacket = NetConnectAcceptPacket.FromData(packet); if (netConnectAcceptPacket != null && netConnectAcceptPacket.PeerNetworkChanged && netConnectAcceptPacket.PeerId < _peersArray.Length) { _peersLock.EnterUpgradeableReadLock(); LiteNetPeer liteNetPeer = _peersArray[netConnectAcceptPacket.PeerId]; _peersLock.ExitUpgradeableReadLock(); if (liteNetPeer != null && liteNetPeer.ConnectTime == netConnectAcceptPacket.ConnectionTime && liteNetPeer.ConnectionNum == netConnectAcceptPacket.ConnectionNumber) { if (liteNetPeer.ConnectionState == ConnectionState.Connected) { liteNetPeer.InitiateEndPointChange(); CreateEvent(NetEvent.EType.PeerAddressChanged, liteNetPeer, remoteEndPoint, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); } flag2 = true; } } } PoolRecycle(packet); if (!flag2) { NetPacket netPacket = PoolGetWithProperty(PacketProperty.PeerNotFound, 1); netPacket.RawData[1] = 1; SendRawAndRecycle(netPacket, remoteEndPoint); } } break; case PacketProperty.InvalidProtocol: if (flag && actualValue.ConnectionState == ConnectionState.Outgoing) { DisconnectPeerForce(actualValue, DisconnectReason.InvalidProtocol, SocketError.Success, null); } break; case PacketProperty.Disconnect: if (flag) { DisconnectResult disconnectResult = actualValue.ProcessDisconnect(packet); if (disconnectResult == DisconnectResult.None) { PoolRecycle(packet); break; } DisconnectPeerForce(actualValue, (disconnectResult == DisconnectResult.Disconnect) ? DisconnectReason.RemoteConnectionClose : DisconnectReason.ConnectionRejected, SocketError.Success, packet); } else { PoolRecycle(packet); } SendRawAndRecycle(PoolGetWithProperty(PacketProperty.ShutdownOk), remoteEndPoint); break; case PacketProperty.ConnectAccept: if (flag) { NetConnectAcceptPacket netConnectAcceptPacket2 = NetConnectAcceptPacket.FromData(packet); if (netConnectAcceptPacket2 != null && actualValue.ProcessConnectAccept(netConnectAcceptPacket2)) { CreateEvent(NetEvent.EType.Connect, actualValue, null, SocketError.Success, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); } } break; default: if (flag) { actualValue.ProcessPacket(packet); } else { SendRawAndRecycle(PoolGetWithProperty(PacketProperty.PeerNotFound), remoteEndPoint); } break; } } internal void CreateReceiveEvent(NetPacket packet, DeliveryMethod method, byte channelNumber, int headerSize, LiteNetPeer fromPeer) { if (UnsyncedEvents || UnsyncedReceiveEvent || _manualMode) { NetEvent netEvent; lock (_eventLock) { netEvent = _netEventPoolHead; if (netEvent == null) { netEvent = new NetEvent(this); } else { _netEventPoolHead = netEvent.Next; } } netEvent.Next = null; netEvent.Type = NetEvent.EType.Receive; netEvent.DataReader.SetSource(packet, headerSize); netEvent.Peer = fromPeer; netEvent.DeliveryMethod = method; netEvent.ChannelNumber = channelNumber; ProcessEvent(netEvent); return; } lock (_eventLock) { NetEvent netEvent = _netEventPoolHead; if (netEvent == null) { netEvent = new NetEvent(this); } else { _netEventPoolHead = netEvent.Next; } netEvent.Next = null; netEvent.Type = NetEvent.EType.Receive; netEvent.DataReader.SetSource(packet, headerSize); netEvent.Peer = fromPeer; netEvent.DeliveryMethod = method; netEvent.ChannelNumber = channelNumber; if (_pendingEventTail == null) { _pendingEventHead = netEvent; } else { _pendingEventTail.Next = netEvent; } _pendingEventTail = netEvent; } } public void SendToAll(NetDataWriter writer, DeliveryMethod options) { SendToAll(writer.Data, 0, writer.Length, options); } public void SendToAll(byte[] data, DeliveryMethod options) { SendToAll(data, 0, data.Length, options); } public void SendToAll(byte[] data, int start, int length, DeliveryMethod options) { try { _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { liteNetPeer.Send(data, start, length, options); } } finally { _peersLock.ExitReadLock(); } } public void SendToAll(NetDataWriter writer, DeliveryMethod options, LiteNetPeer excludePeer) { SendToAll(writer.Data, 0, writer.Length, options, excludePeer); } public void SendToAll(byte[] data, DeliveryMethod options, LiteNetPeer excludePeer) { SendToAll(data, 0, data.Length, options, excludePeer); } public void SendToAll(byte[] data, int start, int length, DeliveryMethod options, LiteNetPeer excludePeer) { try { _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if (liteNetPeer != excludePeer) { liteNetPeer.Send(data, start, length, options); } } } finally { _peersLock.ExitReadLock(); } } public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options) { SendToAll(data, options, null); } public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options, LiteNetPeer excludePeer) { try { _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if (liteNetPeer != excludePeer) { liteNetPeer.Send(data, options); } } } finally { _peersLock.ExitReadLock(); } } public bool SendUnconnectedMessage(ReadOnlySpan<byte> message, IPEndPoint remoteEndPoint) { int headerSize = NetPacket.GetHeaderSize(PacketProperty.UnconnectedMessage); NetPacket netPacket = PoolGetPacket(message.Length + headerSize); netPacket.Property = PacketProperty.UnconnectedMessage; message.CopyTo(new Span<byte>(netPacket.RawData, headerSize, message.Length)); return SendRawAndRecycle(netPacket, remoteEndPoint) > 0; } public bool Start() { return Start(0); } public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port) { return Start(addressIPv4, addressIPv6, port, manualMode: false); } public bool Start(string addressIPv4, string addressIPv6, int port) { IPAddress addressIPv7 = NetUtils.ResolveAddress(addressIPv4); IPAddress addressIPv8 = NetUtils.ResolveAddress(addressIPv6); return Start(addressIPv7, addressIPv8, port); } public bool Start(int port) { return Start(IPAddress.Any, IPAddress.IPv6Any, port); } public bool StartInManualMode(IPAddress addressIPv4, IPAddress addressIPv6, int port) { return Start(addressIPv4, addressIPv6, port, manualMode: true); } public bool StartInManualMode(string addressIPv4, string addressIPv6, int port) { IPAddress addressIPv7 = NetUtils.ResolveAddress(addressIPv4); IPAddress addressIPv8 = NetUtils.ResolveAddress(addressIPv6); return StartInManualMode(addressIPv7, addressIPv8, port); } public bool StartInManualMode(int port) { return StartInManualMode(IPAddress.Any, IPAddress.IPv6Any, port); } public bool SendUnconnectedMessage(byte[] message, IPEndPoint remoteEndPoint) { return SendUnconnectedMessage(message, 0, message.Length, remoteEndPoint); } public bool SendUnconnectedMessage(NetDataWriter writer, string address, int port) { return SendUnconnectedMessage(writer.Data, 0, writer.Length, NetUtils.MakeEndPoint(address, port)); } public bool SendUnconnectedMessage(NetDataWriter writer, IPEndPoint remoteEndPoint) { return SendUnconnectedMessage(writer.Data, 0, writer.Length, remoteEndPoint); } public bool SendUnconnectedMessage(byte[] message, int start, int length, IPEndPoint remoteEndPoint) { NetPacket packet = PoolGetWithData(PacketProperty.UnconnectedMessage, message, start, length); return SendRawAndRecycle(packet, remoteEndPoint) > 0; } public void TriggerUpdate() { _updateTriggerEvent.Set(); } public void PollEvents() { if (_manualMode) { if (_udpSocketv4 != null) { ManualReceive(_udpSocketv4, _bufferEndPointv4); } if (_udpSocketv6 != null && _udpSocketv6 != _udpSocketv4) { ManualReceive(_udpSocketv6, _bufferEndPointv6); } } else if (!UnsyncedEvents) { NetEvent netEvent; lock (_eventLock) { netEvent = _pendingEventHead; _pendingEventHead = null; _pendingEventTail = null; } while (netEvent != null) { NetEvent next = netEvent.Next; ProcessEvent(netEvent); netEvent = next; } } } public LiteNetPeer Connect(string address, int port, string key) { return Connect(address, port, NetDataWriter.FromString(key)); } public LiteNetPeer Connect(string address, int port, NetDataWriter connectionData) { IPEndPoint target; try { target = NetUtils.MakeEndPoint(address, port); } catch { CreateEvent(NetEvent.EType.Disconnect, null, null, SocketError.Success, 0, DisconnectReason.UnknownHost, null, DeliveryMethod.Unreliable, 0); return null; } return Connect(target, connectionData); } public LiteNetPeer Connect(IPEndPoint target, string key) { return Connect(target, NetDataWriter.FromString(key)); } public LiteNetPeer Connect(IPEndPoint target, NetDataWriter connectionData) { if (!_isRunning) { throw new InvalidOperationException("Client is not running"); } lock (_requestsDict) { if (_requestsDict.ContainsKey(target)) { return null; } byte connectNum = 0; if (TryGetPeer(target, out var actualValue)) { ConnectionState connectionState = actualValue.ConnectionState; if (connectionState == ConnectionState.Outgoing || connectionState == ConnectionState.Connected) { return actualValue; } connectNum = (byte)((actualValue.ConnectionNum + 1) % 4); RemovePeer(actualValue, enableWriteLock: true); } actualValue = CreateOutgoingPeer(target, GetNextPeerId(), connectNum, connectionData.AsReadOnlySpan()); AddPeer(actualValue); return actualValue; } } public LiteNetPeer Connect(IPEndPoint target, ReadOnlySpan<byte> connectionData) { if (!_isRunning) { throw new InvalidOperationException("Client is not running"); } lock (_requestsDict) { if (_requestsDict.ContainsKey(target)) { return null; } byte connectNum = 0; if (TryGetPeer(target, out var actualValue)) { ConnectionState connectionState = actualValue.ConnectionState; if (connectionState == ConnectionState.Outgoing || connectionState == ConnectionState.Connected) { return actualValue; } connectNum = (byte)((actualValue.ConnectionNum + 1) % 4); RemovePeer(actualValue, enableWriteLock: true); } actualValue = CreateOutgoingPeer(target, GetNextPeerId(), connectNum, connectionData); AddPeer(actualValue); return actualValue; } } public void Stop() { Stop(sendDisconnectMessages: true); } public void Stop(bool sendDisconnectMessages) { if (_isRunning) { bool simulateLatency = SimulateLatency; SimulateLatency = false; for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { liteNetPeer.Shutdown(null, 0, 0, !sendDisconnectMessages); } CloseSocket(); SimulateLatency = simulateLatency; _updateTriggerEvent.Set(); if (!_manualMode) { _logicThread.Join(); _logicThread = null; } ClearPeerSet(); _peerIds = new ConcurrentQueue<int>(); _lastPeerId = 0; _connectedPeersCount = 0L; _pendingEventHead = null; _pendingEventTail = null; } } public int GetPeersCount(ConnectionState peerState) { int num = 0; _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if ((liteNetPeer.ConnectionState & peerState) != 0) { num++; } } _peersLock.ExitReadLock(); return num; } public void GetPeers(List<LiteNetPeer> peers, ConnectionState peerState) { peers.Clear(); _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { if ((liteNetPeer.ConnectionState & peerState) != 0) { peers.Add(liteNetPeer); } } _peersLock.ExitReadLock(); } public void GetConnectedPeers(List<LiteNetPeer> peers) { GetPeers(peers, ConnectionState.Connected); } public void DisconnectAll() { DisconnectAll(null, 0, 0); } public void DisconnectAll(byte[] data, int start, int count) { _peersLock.EnterReadLock(); for (LiteNetPeer liteNetPeer = _headPeer; liteNetPeer != null; liteNetPeer = liteNetPeer.NextPeer) { DisconnectPeer(liteNetPeer, DisconnectReason.DisconnectPeerCalled, SocketError.Success, force: false, data, start, count, null); } _peersLock.ExitReadLock(); } public void DisconnectPeerForce(LiteNetPeer peer) { DisconnectPeerForce(peer, DisconnectReason.DisconnectPeerCalled, SocketError.Success, null); } public void DisconnectPeer(LiteNetPeer peer) { DisconnectPeer(peer, null, 0, 0); } public void DisconnectPeer(LiteNetPeer peer, byte[] data) { DisconnectPeer(peer, data, 0, data.Length); } public void DisconnectPeer(LiteNetPeer peer, NetDataWriter writer) { DisconnectPeer(peer, writer.Data, 0, writer.Length); } public void DisconnectPeer(LiteNetPeer peer, byte[] data, int start, int count) { DisconnectPeer(peer, DisconnectReason.DisconnectPeerCalled, SocketError.Success, force: false, data, start, count, null); } public NetPeerEnumerator<LiteNetPeer> GetEnumerator() { return new NetPeerEnumerator<LiteNetPeer>(_headPeer); } IEnumerator<LiteNetPeer> IEnumerable<LiteNetPeer>.GetEnumerator() { return new NetPeerEnumerator<LiteNetPeer>(_headPeer); } IEnumerator IEnumerable.GetEnumerator() { return new NetPeerEnumerator<LiteNetPeer>(_headPeer); } private static int HashSetGetPrime(int min) { int[] primes = Primes; foreach (int num in primes) { if (num >= min) { return num; } } for (int j = min | 1; j < int.MaxValue; j += 2) { if (IsPrime(j) && (j - 1) % 101 != 0) { return j; } } return min; static bool IsPrime(int candidate) { if (((uint)candidate & (true ? 1u : 0u)) != 0) { int num2 = (int)Math.Sqrt(candidate); for (int k = 3; k <= num2; k += 2) { if (candidate % k == 0) { return false; } } return true; } return candidate == 2; } } private void ClearPeerSet() { _peersLock.EnterWriteLock(); _headPeer = null; if (_lastIndex > 0) { Array.Clear(_slots, 0, _lastIndex); Array.Clear(_buckets, 0, _buckets.Length); _lastIndex = 0; _count = 0; _freeList = -1; } _peersArray = new LiteNetPeer[32]; _peersLock.ExitWriteLock(); } protected bool ContainsPeer(LiteNetPeer item) { if (item == null) { NetDebug.WriteError($"Contains peer null: {item}"); return false; } if (_buckets != null) { int num = item.GetHashCode() & 0x7FFFFFFF; for (int num2 = _buckets[num % _buckets.Length] - 1; num2 >= 0; num2 = _slots[num2].Next) { if (_slots[num2].HashCode == num && _slots[num2].Value.Equals(item)) { return true; } } } return false; } public LiteNetPeer GetPeerById(int id) { if (id < 0 || id >= _peersArray.Length) { return null; } return _peersArray[id]; } public bool TryGetPeerById(int id, out LiteNetPeer peer) { peer = GetPeerById(id); return peer != null; } private void AddPeer(LiteNetPeer peer) { if (peer == null) { NetDebug.WriteError($"Add peer null: {peer}"); return; } _peersLock.EnterWriteLock(); if (_headPeer != null) { peer.NextPeer = _headPeer; _headPeer.PrevPeer = peer; } _headPeer = peer; AddPeerToSet(peer); if (peer.Id >= _peersArray.Length) { int num = _peersArray.Length * 2; while (peer.Id >= num) { num *= 2; } Array.Resize(ref _peersArray, num); } _peersArray[peer.Id] = peer; _peersLock.ExitWriteLock(); } private void RemovePeer(LiteNetPeer peer, bool enableWriteLock) { if (enableWriteLock) { _peersLock.EnterWriteLock(); } if (!RemovePeerFromSet(peer)) { if (enableWriteLock) { _peersLock.ExitWriteLock(); } return; } if (peer == _headPeer) { _headPeer = peer.NextPeer; } if (peer.PrevPeer != null) { peer.PrevPeer.NextPeer = peer.NextPeer; } if (peer.NextPeer != null) { peer.NextPeer.PrevPeer = peer.PrevPeer; } peer.PrevPeer = null; _peersArray[peer.Id] = null; _peerIds.Enqueue(peer.Id); if (enableWriteLock) { _peersLock.ExitWriteLock(); } } protected bool RemovePeerFromSet(LiteNetPeer peer) { if (_buckets == null || peer == null) { return false; } int num = peer.GetHashCode() & 0x7FFFFFFF; int num2 = num % _buckets.Length; int num3 = -1; for (int num4 = _buckets[num2] - 1; num4 >= 0; num4 = _slots[num4].Next) { if (_slots[num4].HashCode == num && _slots[num4].Value.Equals(peer)) { if (num3 < 0) { _buckets[num2] = _slots[num4].Next + 1; } else { _slots[num3].Next = _slots[num4].Next; } _slots[num4].HashCode = -1; _slots[num4].Value = null; _slots[num4].Next = _freeList; _count--; if (_count == 0) { _lastIndex = 0; _freeList = -1; } else { _freeList = num4; } return true; } num3 = num4; } return false; } private bool TryGetPeer(IPEndPoint endPoint, out LiteNetPeer actualValue) { if (_buckets != null) { int num = endPoint.GetHashCode() & 0x7FFFFFFF; _peersLock.EnterReadLock(); for (int num2 = _buckets[num % _buckets.Length] - 1; num2 >= 0; num2 = _slots[num2].Next) { if (_slots[num2].HashCode == num && _slots[num2].Value.Equals(endPoint)) { actualValue = _slots[num2].Value; _peersLock.ExitReadLock(); return true; } } _peersLock.ExitReadLock(); } actualValue = null; return false; } private bool TryGetPeer(SocketAddress saddr, out LiteNetPeer actualValue) { if (_buckets != null) { int num = saddr.GetHashCode() & 0x7FFFFFFF; _peersLock.EnterReadLock(); for (int num2 = _buckets[num % _buckets.Length] - 1; num2 >= 0; num2 = _slots[num2].Next) { if (_slots[num2].HashCode == num && _slots[num2].Value.Serialize().Equals(saddr)) { actualValue = _slots[num2].Value; _peersLock.ExitReadLock(); return true; } } _peersLock.ExitReadLock(); } actualValue = null; return false; } protected bool AddPeerToSet(LiteNetPeer value) { if (_buckets == null) { int num = HashSetGetPrime(0); _buckets = new int[num]; _slots = new Slot[num]; } int num2 = value.GetHashCode() & 0x7FFFFFFF; int num3 = num2 % _buckets.Length; for (int num4 = _buckets[num2 % _buckets.Length] - 1; num4 >= 0; num4 = _slots[num4].Next) { if (_slots[num4].HashCode == num2 && _slots[num4].Value.Equals(value)) { return false; } } int num5; if (_freeList >= 0) { num5 = _freeList; _freeList = _slots[num5].Next; } else { if (_lastIndex == _slots.Length) { int num6 = 2 * _count; num6 = (((uint)num6 > 2147483587u && 2147483587 > _count) ? 2147483587 : HashSetGetPrime(num6)); Slot[] array = new Slot[num6]; Array.Copy(_slots, 0, array, 0, _lastIndex); _buckets = new int[num6]; for (int i = 0; i < _lastIndex; i++) { int num7 = array[i].HashCode % num6; array[i].Next = _buckets[num7] - 1; _buckets[num7] = i + 1; } _slots = array; num3 = num2 % _buckets.Length; } num5 = _lastIndex; _lastIndex++; } _slots[num5].HashCode = num2; _slots[num5].Value = value; _slots[num5].Next = _buckets[num3] - 1; _buckets[num3] = num5 + 1; _count++; return true; } private NetPacket PoolGetWithData(PacketProperty property, byte[] data, int start, int length) { int headerSize = NetPacket.GetHeaderSize(property); NetPacket netPacket = PoolGetPacket(length + headerSize); netPacket.Property = property; Buffer.BlockCopy(data, start, netPacket.RawData, headerSize, length); return netPacket; } private NetPacket PoolGetWithProperty(PacketProperty property, int size) { NetPacket netPacket = PoolGetPacket(size + NetPacket.GetHeaderSize(property)); netPacket.Property = property; return netPacket; } private NetPacket PoolGetWithProperty(PacketProperty property) { NetPacket netPacket = PoolGetPacket(NetPacket.GetHeaderSize(property)); netPacket.Property = property; return netPacket; } internal NetPacket PoolGetPacket(int size) { if (size > NetConstants.MaxPacketSize) { return new NetPacket(size); } NetPacket poolHead; lock (_poolLock) { poolHead = _poolHead; if (poolHead == null) { return new NetPacket(size); } _poolHead = _poolHead.Next; _poolCount--; } poolHead.Size = size; if (poolHead.RawData.Length < size) { poolHead.RawData = new byte[size]; } return poolHead; } internal void PoolRecycle(NetPacket packet) { if (packet.RawData.Length > NetConstants.MaxPacketSize || _poolCount >= PacketPoolSize) { return; } packet.RawData[0] = 0; lock (_poolLock) { packet.Next = _poolHead; _poolHead = packet; _poolCount++; } } static LiteNetManager() { Primes = new int[72] { 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 }; MulticastAddressV6 = IPAddress.Parse("ff02::1"); IPv6Support = Socket.OSSupportsIPv6; } private bool ProcessError(SocketException ex) { switch (ex.SocketErrorCode) { case SocketError.NotConnected: NotConnected = true; return true; case SocketError.OperationAborted: case SocketError.Interrupted: case SocketError.NotSocket: return true; default: NetDebug.WriteError($"[R]Error code: {(int)ex.SocketErrorCode} - {ex}"); CreateEvent(NetEvent.EType.Error, null, null, ex.SocketErrorCode, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); break; case SocketError.WouldBlock: case SocketError.MessageSize: case SocketError.NetworkReset: case SocketError.ConnectionReset: case SocketError.TimedOut: break; } return false; } private void ManualReceive(Socket socket, EndPoint bufferEndPoint) { try { int num = MaxPacketPerManualReceive; while (socket.Available > 0 && (num > 0 || MaxPacketPerManualReceive == 0) && ReceiveFrom(socket, ref bufferEndPoint) > 0) { num--; } } catch (SocketException ex) { ProcessError(ex); } catch (ObjectDisposedException) { } catch (Exception ex3) { NetDebug.WriteError("[NM] SocketReceiveThread error: " + ex3); } } private void NativeReceiveLogic() { IntPtr handle = _udpSocketv4.Handle; IntPtr s2 = _udpSocketv6?.Handle ?? IntPtr.Zero; byte[] address2 = new byte[16]; byte[] address3 = new byte[28]; IPEndPoint tempEndPoint = new IPEndPoint(IPAddress.Any, 0); List<Socket> list = new List<Socket>(2); Socket udpSocketv = _udpSocketv4; Socket udpSocketv2 = _udpSocketv6; NetPacket packet = PoolGetPacket(NetConstants.MaxPacketSize); while (_isRunning) { try { if (udpSocketv2 == null) { if (!NativeReceiveFrom(handle, address2)) { break; } continue; } bool flag = false; if (udpSocketv.Available != 0 || list.Contains(udpSocketv)) { if (!NativeReceiveFrom(handle, address2)) { break; } flag = true; } if (udpSocketv2.Available != 0 || list.Contains(udpSocketv2)) { if (!NativeReceiveFrom(s2, address3)) { break; } flag = true; } list.Clear(); if (!flag) { list.Add(udpSocketv); list.Add(udpSocketv2); Socket.Select(list, null, null, ReceivePollingTime); } } catch (SocketException ex) { if (ProcessError(ex)) { break; } } catch (ObjectDisposedException) { break; } catch (ThreadAbortException) { break; } catch (Exception ex4) { NetDebug.WriteError("[NM] SocketReceiveThread error: " + ex4); } } bool NativeReceiveFrom(IntPtr s, byte[] address) { int socketAddressSize = address.Length; packet.Size = NativeSocket.RecvFrom(s, packet.RawData, NetConstants.MaxPacketSize, address, ref socketAddressSize); if (packet.Size == 0) { return true; } if (packet.Size == -1) { return !ProcessError(new SocketException((int)NativeSocket.GetSocketError())); } short num = (short)((address[1] << 8) | address[0]); tempEndPoint.Port = (ushort)((address[2] << 8) | address[3]); if ((NativeSocket.UnixMode && num == 10) || (!NativeSocket.UnixMode && num == 23)) { uint num2 = (uint)((address[27] << 24) + (address[26] << 16) + (address[25] << 8) + address[24]); tempEndPoint.Address = new IPAddress(new ReadOnlySpan<byte>(address, 8, 16), num2); } else { long newAddress = (uint)((address[4] & 0xFF) | ((address[5] << 8) & 0xFF00) | ((address[6] << 16) & 0xFF0000) | (address[7] << 24)); tempEndPoint.Address = new IPAddress(newAddress); } if (TryGetPeer(tempEndPoint, out var actualValue)) { OnMessageReceived(packet, actualValue); } else { OnMessageReceived(packet, tempEndPoint); tempEndPoint = new IPEndPoint(IPAddress.Any, 0); } packet = PoolGetPacket(NetConstants.MaxPacketSize); return true; } } private int ReceiveFrom(Socket s, ref EndPoint bufferEndPoint) { NetPacket netPacket = PoolGetPacket(NetConstants.MaxPacketSize); netPacket.Size = s.ReceiveFrom(netPacket.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); OnMessageReceived(netPacket, (IPEndPoint)bufferEndPoint); return netPacket.Size; } private void ReceiveLogic() { EndPoint bufferEndPoint = new IPEndPoint(IPAddress.Any, 0); EndPoint bufferEndPoint2 = new IPEndPoint(IPAddress.IPv6Any, 0); List<Socket> list = new List<Socket>(2); Socket udpSocketv = _udpSocketv4; Socket udpSocketv2 = _udpSocketv6; while (_isRunning) { try { if (udpSocketv2 == null) { if (udpSocketv.Available != 0 || udpSocketv.Poll(ReceivePollingTime, SelectMode.SelectRead)) { ReceiveFrom(udpSocketv, ref bufferEndPoint); } continue; } bool flag = false; if (udpSocketv.Available != 0 || list.Contains(udpSocketv)) { ReceiveFrom(udpSocketv, ref bufferEndPoint); flag = true; } if (udpSocketv2.Available != 0 || list.Contains(udpSocketv2)) { ReceiveFrom(udpSocketv2, ref bufferEndPoint2); flag = true; } list.Clear(); if (!flag) { list.Add(udpSocketv); list.Add(udpSocketv2); Socket.Select(list, null, null, ReceivePollingTime); } } catch (SocketException ex) { if (ProcessError(ex)) { break; } } catch (ObjectDisposedException) { break; } catch (ThreadAbortException) { break; } catch (Exception ex4) { NetDebug.WriteError("[NM] SocketReceiveThread error: " + ex4); } } } public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { if (IsRunning && !NotConnected) { return false; } NotConnected = false; _manualMode = manualMode; UseNativeSockets = UseNativeSockets && NativeSocket.IsSupported; _udpSocketv4 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); if (!BindSocket(_udpSocketv4, new IPEndPoint(addressIPv4, port))) { return false; } LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port; _isRunning = true; if (_manualMode) { _bufferEndPointv4 = new IPEndPoint(IPAddress.Any, 0); } if (IPv6Support && IPv6Enabled) { _udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort))) { if (_manualMode) { _bufferEndPointv6 = new IPEndPoint(IPAddress.IPv6Any, 0); } } else { _udpSocketv6 = null; } } if (!manualMode) { ThreadStart start = ReceiveLogic; if (UseNativeSockets) { start = NativeReceiveLogic; } _receiveThread = new Thread(start) { Name = $"ReceiveThread({LocalPort})", IsBackground = true }; _receiveThread.Start(); if (_logicThread == null) { _logicThread = new Thread(UpdateLogic) { Name = "LogicThread", IsBackground = true }; _logicThread.Start(); } } return true; } private bool BindSocket(Socket socket, IPEndPoint ep) { socket.ReceiveTimeout = 500; socket.SendTimeout = 500; socket.ReceiveBufferSize = 1048576; socket.SendBufferSize = 1048576; socket.Blocking = true; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { socket.IOControl(-1744830452, new byte[1], null); } catch { } } try { socket.ExclusiveAddressUse = !ReuseAddress; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, ReuseAddress); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, DontRoute); } catch { } if (ep.AddressFamily == AddressFamily.InterNetwork) { Ttl = 255; try { socket.EnableBroadcast = true; } catch (SocketException ex) { NetDebug.WriteError($"[B]Broadcast error: {ex.SocketErrorCode}"); } if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { socket.DontFragment = true; } catch (SocketException ex2) { NetDebug.WriteError($"[B]DontFragment error: {ex2.SocketErrorCode}"); } } } try { socket.Bind(ep); if (ep.AddressFamily == AddressFamily.InterNetworkV6) { try { socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(MulticastAddressV6)); } catch (Exception) { } } } catch (SocketException ex4) { switch (ex4.SocketErrorCode) { case SocketError.AddressAlreadyInUse: if (socket.AddressFamily == AddressFamily.InterNetworkV6) { try { socket.DualMode = false; socket.Bind(ep); } catch (SocketException ex5) { NetDebug.WriteError($"[B]Bind exception: {ex5}, errorCode: {ex5.SocketErrorCode}"); return false; } return true; } break; case SocketError.AddressFamilyNotSupported: return true; } NetDebug.WriteError($"[B]Bind exception: {ex4}, errorCode: {ex4.SocketErrorCode}"); return false; } return true; } internal int SendRawAndRecycle(NetPacket packet, IPEndPoint remoteEndPoint) { int result = SendRaw(packet.RawData, 0, packet.Size, remoteEndPoint); PoolRecycle(packet); return result; } internal int SendRaw(NetPacket packet, IPEndPoint remoteEndPoint) { return SendRaw(packet.RawData, 0, packet.Size, remoteEndPoint); } internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEndPoint) { if (!_isRunning) { return 0; } NetPacket netPacket = null; if (_extraPacketLayer != null) { netPacket = PoolGetPacket(length + _extraPacketLayer.ExtraPacketSizeForLayer); Buffer.BlockCopy(message, start, netPacket.RawData, 0, length); start = 0; _extraPacketLayer.ProcessOutBoundPacket(ref remoteEndPoint, ref netPacket.RawData, ref start, ref length); message = netPacket.RawData; } int result = SendRawCore(message, start, length, remoteEndPoint); if (netPacket != null) { PoolRecycle(netPacket); } return result; } internal unsafe int SendRawCore(byte[] message, int start, int length, IPEndPoint remoteEndPoint) { if (!_isRunning) { return 0; } Socket socket = _udpSocketv4; if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support) { socket = _udpSocketv6; if (socket == null) { return 0; } } int num; try { if (UseNativeSockets && remoteEndPoint is LiteNetPeer liteNetPeer) { fixed (byte* pinnedBuffer = &message[start]) { num = NativeSocket.SendTo(socket.Handle, pinnedBuffer, length, liteNetPeer.NativeAddress, liteNetPeer.NativeAddress.Length); } if (num == -1) { throw NativeSocket.GetSocketException(); } } else { num = socket.SendTo(message, start, length, SocketFlags.None, remoteEndPoint); } } catch (SocketException ex) { switch (ex.SocketErrorCode) { case SocketError.Interrupted: case SocketError.NoBufferSpaceAvailable: return 0; case SocketError.MessageSize: return 0; case SocketError.NetworkUnreachable: case SocketError.HostUnreachable: if (DisconnectOnUnreachable && remoteEndPoint is LiteNetPeer peer) { DisconnectPeerForce(peer, (ex.SocketErrorCode == SocketError.HostUnreachable) ? DisconnectReason.HostUnreachable : DisconnectReason.NetworkUnreachable, ex.SocketErrorCode, null); } CreateEvent(NetEvent.EType.Error, null, remoteEndPoint, ex.SocketErrorCode, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); return -1; case SocketError.Shutdown: CreateEvent(NetEvent.EType.Error, null, remoteEndPoint, ex.SocketErrorCode, 0, DisconnectReason.ConnectionFailed, null, DeliveryMethod.Unreliable, 0); return -1; default: NetDebug.WriteError($"[S] {ex}"); return -1; } } catch (Exception arg) { NetDebug.WriteError($"[S] {arg}"); return 0; } if (num <= 0) { return 0; } if (EnableStatistics) { Statistics.IncrementPacketsSent(); Statistics.AddBytesSent(length); } return num; } public bool SendBroadcast(NetDataWriter writer, int port) { return SendBroadcast(writer.Data, 0, writer.Length, port); } public bool SendBroadcast(byte[] data, int port) { return SendBroadcast(data, 0, data.Length, port); } public bool SendBroadcast(byte[] data, int start, int length, int port) { if (!IsRunning) { return false; } NetPacket netPacket; if (_extraPacketLayer != null) { int headerSize = NetPacket.GetHeaderSize(PacketProperty.Broadcast); netPacket = PoolGetPacket(headerSize + length + _extraPacketLayer.ExtraPacketSizeForLayer); netPacket.Property = PacketProperty.Broadcast; Buffer.BlockCopy(data, start, netPacket.RawData, headerSize, length); int offset = 0; int length2 = length + headerSize; IPEndPoint endPoint = null; _extraPacketLayer.ProcessOutBoundPacket(ref endPoint, ref netPacket.RawData, ref offset, ref length2); } else { netPacket = PoolGetWithData(PacketProperty.Broadcast, data, start, length); } bool flag = false; bool flag2 = false; try { flag = _udpSocketv4.SendTo(netPacket.RawData, 0, netPacket.Size, SocketFlags.None, new IPEndPoint(IPAddress.Broadcast, port)) > 0; if (_udpSocketv6 != null) { flag2 = _udpSocketv6.SendTo(netPacket.RawData, 0, netPacket.Size, SocketFlags.None, new IPEndPoint(MulticastAddressV6, port)) > 0; } } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.HostUnreachable) { return flag; } NetDebug.WriteError($"[S][MCAST] {ex}"); return flag; } catch (Exception arg) { NetDebug.WriteError($"[S][MCAST] {arg}"); return flag; } finally { PoolRecycle(netPacket); } return flag || flag2; } private void CloseSocket() { _isRunning = false; if (_receiveThread != null && _receiveThread != Thread.CurrentThread) { _receiveThread.Join(); } _receiveThread = null; _udpSocketv4?.Close(); _udpSocketv6?.Close(); _udpSocketv4 = null; _udpSocketv6 = null; } } [Flags] public enum ConnectionState : byte { Outgoing = 2, Connected = 4, ShutdownRequested = 8, Disconnected = 0x10, EndPointChange = 0x20, Any = 0x2E } internal enum ConnectRequestResult { None, P2PLose, Reconnection, NewConnection } internal enum DisconnectResult { None, Reject, Disconnect } internal enum ShutdownResult { None, Success, WasConnected } public class LiteNetPeer : IPEndPoint { private sealed class IncomingFragments { public readonly NetPacket[] Fragments; public readonly ushort TotalFragments; public readonly byte ChannelId; public int ReceivedCount; public int TotalSize; public IncomingFragments(ushort totalFragments, byte channelId) { TotalFragments = totalFragments; ChannelId = channelId; Fragments = new NetPacket[totalFragments]; } public void RecycleAll(LiteNetManager netManager) { for (int i = 0; i < Fragments.Length; i++) { NetPacket netPacket = Fragments[i]; if (netPacket != null) { netManager.PoolRecycle(netPacket); Fragments[i] = null; } } } } private int _rtt; private int _avgRtt; private int _rttCount; private float _resendDelay = 27f; private float _pingSendTimer; private float _rttResetTimer; private readonly Stopwatch _pingTimer = new Stopwatch(); private float _timeSinceLastPacket; private long _remoteDelta; private readonly object _shutdownLock = new object(); internal volatile LiteNetPeer NextPeer; internal LiteNetPeer PrevPeer; private NetPacket[] _unreliableSecondQueue; private NetPacket[] _unreliableChannel; private int _unreliablePendingCount; private readonly object _unreliableChannelLock = new object(); private int _mtu; private int _mtuIdx; private bool _finishMtu; private float _mtuCheckTimer; private int _mtuCheckAttempts; private const int MtuCheckDelay = 1000; private const int MaxMtuCheckAttempts = 4; private readonly object _mtuMutex = new object(); private int _fragmentId; private readonly Dictionary<ushort, IncomingFragments> _holdedFragments; private readonly Dictionary<ushort, ushort> _deliveredFragments; private readonly NetPacket _mergeData; private int _mergePos; private int _mergeCount; private int _connectAttempts; private float _connectTimer; private long _connectTime; private byte _connectNum; private ConnectionState _connectionState; private NetPacket _shutdownPacket; private const int ShutdownDelay = 300; private float _shutdownTimer; private readonly NetPacket _pingPacket; private readonly NetPacket _pongPacket; private readonly NetPacket _connectRequestPacket; private readonly NetPacket _connectAcceptPacket; public readonly LiteNetManager NetManager; public readonly int Id; public float ResendFixedDelay = 25f; public float ResendRttMultiplier = 2.1f; public object Tag; public readonly NetStatistics Statistics; private SocketAddress _cachedSocketAddr; private int _cachedHashCode; private ReliableChannel _reliableChannel; private ReliableChannel _reliableUnorderedChannel; private SequencedChannel _sequencedChannel; internal byte[] NativeAddress; internal byte ConnectionNum { get { return _connectNum; } private set { _connectNum = value; _mergeData.ConnectionNumber = value; _pingPacket.ConnectionNumber = value; _pongPacket.ConnectionNumber = value; } } public ConnectionState ConnectionState => _connectionState; internal long ConnectTime => _connectTime; public int RemoteId { get; private set; } public int Ping => _avgRtt / 2; public int RoundTripTime => _avgRtt; public int Mtu => _mtu; public long RemoteTimeDelta => _remoteDelta; public DateTime RemoteUtcTime => new DateTime(DateTime.UtcNow.Ticks + _remoteDelta); public float TimeSinceLastPacket => _timeSinceLastPacket; internal float ResendDelay => _resendDelay; protected virtual int ChannelsCount => 1; public override SocketAddress Serialize() { return _cachedSocketAddr; } public override int GetHashCode() { return _cachedHashCode; } internal LiteNetPeer(LiteNetManager netManager, IPEndPoint remoteEndPoint, int id) : base(remoteEndPoint.Address, remoteEndPoint.Port) { Id = id; Statistics = new NetStatistics(); NetManager = netManager; _cachedSocketAddr = base.Serialize(); if (NetManager.UseNativeSockets) { NativeAddress = new byte[_cachedSocketAddr.Size]; for (int i = 0; i < _cachedSocketAddr.Size; i++) { NativeAddress[i] = _cachedSocketAddr[i]; } } _cachedHashCode = base.GetHashCode(); ResetMtu(); _connectionState = ConnectionState.Connected; _mergeData = new NetPacket(PacketProperty.Merged, NetConstants.MaxPacketSize); _pongPacket = new NetPacket(PacketProperty.Pong, 0); _pingPacket = new NetPacket(PacketProperty.Ping, 0) { Sequence = 1 }; _unreliableSecondQueue = new NetPacket[8]; _unreliableChannel = new NetPacket[8]; _holdedFragments = new Dictionary<ushort, IncomingFragments>(); _deliveredFragments = new Dictionary<ushort, ushort>(); } internal void InitiateEndPointChange() { ResetMtu(); _connectionState = ConnectionState.EndPointChange; } internal void FinishEndPointChange(IPEndPoint newEndPoint) { if (_connectionState != ConnectionState.EndPointChange) { return; } _connectionState = ConnectionState.Connected; base.Address = newEndPoint.Address; base.Port = newEndPoint.Port; _cachedSocketAddr = base.Serialize(); if (NetManager.UseNativeSockets) { NativeAddress = new byte[_cachedSocketAddr.Size]; for (int i = 0; i < _cachedSocketAddr.Size; i++) { NativeAddress[i] = _cachedSocketAddr[i]; } } _cachedHashCode = base.GetHashCode(); } internal void ResetMtu() { _finishMtu = !NetManager.MtuDiscovery; if (NetManager.MtuOverride > 0) { OverrideMtu(NetManager.MtuOverride); } else { SetMtu(0); } } private void SetMtu(int mtuIdx) { _mtuIdx = mtuIdx; _mtu = NetConstants.PossibleMtu[mtuIdx] - NetManager.ExtraPacketSizeForLayer; } private void OverrideMtu(int mtuValue) { _mtu = mtuValue; _finishMtu = true; } public int GetPacketsCountInReliableQueue(bool ordered) { return (ordered ? _reliableChannel : _reliableUnorderedChannel)?.PacketsInQueue ?? 0; } public PooledPacket CreatePacketFromPool(DeliveryMethod deliveryMethod) { int mtu = _mtu; NetPacket netPacket = NetManager.PoolGetPacket(mtu); if (deliveryMethod == DeliveryMethod.Unreliable) { netPacket.Property = PacketProperty.Unreliable; return new PooledPacket(netPacket, mtu, 0); } netPacket.Property = PacketProperty.Channeled; return new PooledPacket(netPacket, mtu, (byte)deliveryMethod); } public void SendPooledPacket(PooledPacket packet, int userDataSize) { if (_connectionState != ConnectionState.Connected) { return; } packet._packet.Size = packet.UserDataOffset + userDataSize; if (packet._packet.Property == PacketProperty.Channeled) { CreateChannel(packet._channelNumber).AddToQueue(packet._packet); return; } lock (_unreliableChannelLock) { if (_unreliablePendingCount == _unreliableChannel.Length) { Array.Resize(ref _unreliableChannel, _unreliablePendingCount * 2); } _unreliableChannel[_unreliablePendingCount++] = packet._packet; } } internal virtual BaseChannel CreateChannel(byte channelNumber) { switch ((DeliveryMethod)channelNumber) { case DeliveryMethod.ReliableOrdered: case DeliveryMethod.ReliableSequenced: return _reliableChannel ?? (_reliableChannel = new ReliableChannel(this, ordered: true, 2)); case DeliveryMethod.ReliableUnordered: return _reliableUnorderedChannel ?? (_reliableUnorderedChannel = new ReliableChannel(this, ordered: false, channelNumber)); case DeliveryMethod.Sequenced: return _sequencedChannel ?? (_sequencedChannel = new SequencedChannel(this, reliable: true, channelNumber)); default: throw new Exception("Invalid channel type"); } } internal LiteNetPeer(LiteNetManager netManager, IPEndPoint remoteEndPoint, int id, byte connectNum, ReadOnlySpan<byte> connectData) : this(netManager, remoteEndPoint, id) { _connectTime = DateTime.UtcNow.Ticks; _connectionState = ConnectionState.Outgoing; ConnectionNum = connectNum; _connectRequestPacket = NetConnectRequestPacket.Make(connectData, remoteEndPoint.Serialize(), _connectTime, id); _connectRequestPacket.ConnectionNumber = connectNum; NetManager.SendRaw(_connectRequestPacket, this); } internal LiteNetPeer(LiteNetManager netManager, LiteConnectionRequest request, int id) : this(netManager, request.RemoteEndPoint, id) { _connectTime = request.InternalPacket.ConnectionTime; ConnectionNum = request.InternalPacket.ConnectionNumber; RemoteId = request.InternalPacket.PeerId; _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, ConnectionNum, id); _connectionState = ConnectionState.Connected; NetManager.SendRaw(_connectAcceptPacket, this); } internal void Reject(NetConnectRequestPacket requestData, byte[] data, int start, int length) { _connectTime = requestData.ConnectionTime; _connectNum = requestData.ConnectionNumber; Shutdown(data, start, length, force: false); } internal bool ProcessConnectAccept(NetConnectAcceptPacket packet) { if (_connectionState != ConnectionState.Outgoing) { return false; } if (packet.ConnectionTime != _connectTime) { return false; } ConnectionNum = packet.ConnectionNumber; RemoteId = packet.PeerId; Interlocked.Exchange(ref _timeSinceLastPacket, 0f); _connectionState = ConnectionState.Connected; return true; } public int GetMaxSinglePacketSize(DeliveryMethod options) { return _mtu - NetPacket.GetHeaderSize((options != DeliveryMethod.Unreliable) ? PacketProperty.Channeled : PacketProperty.Unreliable); } public void SendWithDeliveryEvent(byte[] data, DeliveryMethod deliveryMethod, object userData) { if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != 0) { throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); } SendInternal(new ReadOnlySpan<byte>(data, 0, data.Length), 0, deliveryMethod, userData); } public void SendWithDeliveryEvent(byte[] data, int start, int length, DeliveryMethod deliveryMethod, object userData) { if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != 0) { throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); } SendInternal(new ReadOnlySpan<byte>(data, start, length), 0, deliveryMethod, userData); } public void SendWithDeliveryEvent(NetDataWriter dataWriter, DeliveryMethod deliveryMethod, object userData) { if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != 0) { throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); } SendInternal(dataWriter.AsReadOnlySpan(), 0, deliveryMethod, userData); } public void Send(byte[] data, DeliveryMethod deliveryMethod) { SendInternal(new ReadOnlySpan<byte>(data, 0, data.Length), 0, deliveryMethod, null); } public void Send(NetDataWriter dataWriter, DeliveryMethod deliveryMethod) { SendInternal(dataWriter.AsReadOnlySpan(), 0, deliveryMethod, null); } public void Send(byte[] data, int start, int length, DeliveryMethod options) { SendInternal(new ReadOnlySpan<byte>(data, start, length), 0, options, null); } public void SendWithDeliveryEvent(ReadOnlySpan<byte> data, DeliveryMethod deliveryMethod, object userData) { if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != 0) { throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); } SendInternal(data, 0, deliveryMethod, userData); } public void Send(ReadOnlySpan<byte> data, DeliveryMethod deliveryMethod) { SendInternal(data, 0, deliveryMethod, null); } protected void SendInternal(ReadOnlySpan<byte> data, byte channelNumber, DeliveryMethod deliveryMethod, object userData) { if (_connectionState != ConnectionState.Connected || channelNumber >= ChannelsCount) { return; } BaseChannel baseChannel = null; PacketProperty property; if (deliveryMethod == DeliveryMethod.Unreliable) { property = PacketProperty.Unreliable; } else { property = PacketProperty.Channeled; baseChannel = CreateChannel((byte)((uint)(channelNumber * 4) + (uint)deliveryMethod)); } int headerSize = NetPacket.GetHeaderSize(property); int mtu = _mtu; int num = data.Length; if (num + headerSize > mtu) { if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != 0) { throw new TooBigPacketException("Unreliable or ReliableSequenced packet size exceeded maximum of " + (mtu - headerSize) + " bytes, Check allowed size by GetMaxSinglePacketSize()"); } int num2 = mtu - headerSize - 6; int num3 = num / num2 + ((num % num2 != 0) ? 1 : 0); if (num3 > NetManager.MaxFragmentsCount) { throw new TooBigPacketException("Data was split in " + num3 + " fragments, which exceeds " + NetManager.MaxFragmentsCount); } ushort fragmentId = (ushort)Interlocked.Increment(ref _fragmentId); for (ushort num4 = 0; num4 < num3; num4++) { int num5 = ((num > num2) ? num2 : num); NetPacket netPacket = NetManager.PoolGetPacket(headerSize + num5 + 6); netPacket.Property = property; netPacket.UserData = userData; netPacket.FragmentId = fragmentId; netPacket.FragmentPart = num4; netPacket.FragmentsTotal = (ushort)num3; netPacket.MarkFragmented(); data.Slice(num4 * num2, num5).CopyTo(new Span<byte>(netPacket.RawData, 10, num5)); baseChannel.AddToQueue(netPacket); num -= num5; } return; } NetPacket netPacket2 = NetManager.PoolGetPacket(headerSize + num); netPacket2.Property = property; data.CopyTo(new Span<byte>(netPacket2.RawData, headerSize, num)); netPacket2.UserData = userData; if (baseChannel == null) { lock (_unreliableChannelLock) { if (_unreliablePendingCount == _unreliableChannel.Length) { Array.Resize(ref _unreliableChannel, _unreliablePendingCount * 2); } _unreliableChannel[_unreliablePendingCount++] = netPacket2; return; } } baseChannel.AddToQueue(netPacket2); } public void Disconnect(byte[] data) { NetManager.DisconnectPeer(this, data); } public void Disconnect(NetDataWriter writer) { NetManager.DisconnectPeer(this, writer); } public void Disconnect(byte[] data, int start, int count) { NetManager.DisconnectPeer(this, data, start, count); } public void Disconnect() { NetManager.DisconnectPeer(this); } internal DisconnectResult ProcessDisconnect(NetPacket packet) { if ((_connectionState == ConnectionState.Connected || _connectionState == ConnectionState.Outgoing) && packet.Size >= 9 && BitConverter.ToInt64(packet.RawData, 1) == _connectTime && packet.ConnectionNumber == _connectNum) { if (_connectionState != ConnectionState.Connected) { return DisconnectResult.Reject; } return DisconnectResult.Disconnect; } return DisconnectResult.None; } internal virtual void AddToReliableChannelSendQueue(BaseChannel channel) { } internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) { lock (_shutdownLock) { if (_connectionState == ConnectionState.Disconnected || _connectionState == ConnectionState.ShutdownRequested) { return ShutdownResult.None; } ShutdownResult result = ((_connectionState != ConnectionState.Connected) ? ShutdownResult.Success : ShutdownResult.WasConnected); if (force) { _connectionState = ConnectionState.Disconnected; return result; } Interlocked.Exchange(ref _timeSinceLastPacket, 0f); _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length) { ConnectionNumber = _connectNum }; FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); if (_shutdownPacket.Size >= _mtu) { NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); } else if (data != null && length > 0) { Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); } _connectionState = ConnectionState.ShutdownRequested; NetManager.SendRaw(_shutdownPacket, this); return result; } } private void UpdateRoundTripTime(int roundTripTime) { _rtt += roundTripTime; _rttCount++; _avgRtt = _rtt / _rttCount; _resendDelay = ResendFixedDelay + (float)_avgRtt * ResendRttMultiplier; } internal void AddReliablePacket(DeliveryMethod method, NetPacket p) { ushort packetFragId; IncomingFragments incomingFragments; NetPacket resultingPacket; if (p.IsFragmented) { if (p.FragmentsTotal == 0 || p.FragmentsTotal > NetManager.MaxFragmentsCount) { NetManager.PoolRecycle(p); NetDebug.WriteError($"Invalid FragmentsTotal: {p.FragmentsTotal}"); return; } if (p.FragmentPart >= p.FragmentsTotal) { NetManager.PoolRecycle(p); NetDebug.WriteError($"FragmentPart {p.FragmentPart} >= FragmentsTotal {p.FragmentsTotal}"); return; } packetFragId = p.FragmentId; byte channelId = p.ChannelId; if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments)) { if (_holdedFragments.Count >= 32 * ChannelsCount * 2) { NetManager.PoolRecycle(p); return; } incomingFragments = new IncomingFragments(p.FragmentsTotal, p.ChannelId); _holdedFragments.Add(packetFragId, incomingFragments); } else if (p.FragmentsTotal != incomingFragments.TotalFragments || p.ChannelId != incomingFragments.ChannelId) { NetManager.PoolRecycle(p); NetDebug.WriteError("Fragment metadata mismatch"); return; } NetPacket[] fragments = incomingFragments.Fragments; if (fragments[p.FragmentPart] != null) { NetManager.PoolRecycle(p); NetDebug.WriteError("Invalid fragment packet"); return; } fragments[p.FragmentPart] = p; incomingFragments.ReceivedCount++; incomingFragments.TotalSize += p.Size - 10; if (incomingFragments.ReceivedCount != incomingFragments.TotalFragments) { return; } resultingPacket = NetManager.PoolGetPacket(incomingFragments.TotalSize); int num = 0; for (ushort num2 = 0; num2 < incomingFragments.TotalFragments; num2++) { NetPacket netPacket = fragments[num2]; if (netPacket == null) { AbortReassembly($"Fragment {num2} missing during reassembly"); return; } if (netPacket.Size > netPacket.RawData.Length) { AbortReassembly($"Fragment error size: {netPacket.Size} > fragment.RawData.Length: {netPacket.RawData.Length}"); return; } int num3 = netPacket.Size - 10; if (num + num3 > resultingPacket.RawData.Length) { AbortReassembly($"Fragment error pos: {num + num3} >= resultPacketSize: {resultingPacket.RawData.Length}"); return; } Buffer.BlockCopy(netPacket.RawData, 10, resultingPacket.RawData, num, num3); num += num3; NetManager.PoolRecycle(netPacket); fragments[num2] = null; } _holdedFragments.Remove(packetFragId); NetManager.CreateReceiveEvent(resultingPacket, method, (byte)(channelId / 4), 0, this); } else { NetManager.CreateReceiveEvent(p, method, (byte)(p.ChannelId / 4), 4, this); } void AbortReassembly(string error) { _holdedFragments.Remove(packetFragId); incomingFragments.RecycleAll(NetManager); NetManager.PoolRecycle(resultingPacket); NetDebug.WriteError(error); } } private void ProcessMtuPacket(NetPacket packet) { if (packet.Size < NetConstants.PossibleMtu[0]) { return; } int num = BitConverter.ToInt32(packet.RawData, 1); int num2 = BitConverter.ToInt32(packet.RawData, packet.Size - 4); if (num != packet.Size || num != num2 || num > NetConstants.MaxPacketSize) { NetDebug.WriteError($"[MTU] Broken packet. RMTU {num}, EMTU {num2}, PSIZE {packet.Size}"); } else if (packet.Property == PacketProperty.MtuCheck) { _mtuCheckAttempts = 0; packet.Property = PacketProperty.MtuOk; NetManager.SendRawAndRecycle(packet, this); } else if (num > _mtu && !_finishMtu && num == NetConstants.PossibleMtu[_mtuIdx + 1] - NetManager.ExtraPacketSizeForLayer) { lock (_mtuMutex) { SetMtu(_mtuIdx + 1); } if (_mtuIdx == NetConstants.PossibleMtu.Length - 1) { _finishMtu = true; } NetManager.PoolRecycle(packet); } } private void UpdateMtuLogic(float deltaTime) { if (_finishMtu) { return; } _mtuCheckTimer += deltaTime; if (_mtuCheckTimer < 1000f) { return; } _mtuCheckTimer = 0f; _mtuCheckAttempts++; if (_mtuCheckAttempts >= 4) { _finishMtu = true; return; } lock (_mtuMutex) { if (_mtuIdx < NetConstants.PossibleMtu.Length - 1) { int num = NetConstants.PossibleMtu[_mtuIdx + 1] - NetManager.ExtraPacketSizeForLayer; NetPacket netPacket = NetManager.PoolGetPacket(num); netPacket.Property = PacketProperty.MtuCheck; FastBitConverter.GetBytes(netPacket.RawData, 1, num); FastBitConverter.GetBytes(netPacket.RawData, netPacket.Size - 4, num); if (NetManager.SendRawAndRecycle(netPacket, this) <= 0) { _finishMtu = true; } } } } internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket connRequest) { switch (_connectionState) { case ConnectionState.Outgoing: { if (connRequest.ConnectionTime < _connectTime) { return ConnectRequestResult.P2PLose; } if (connRequest.ConnectionTime != _connectTime) { break; } byte[] targetAddress = connRequest.TargetAddress; for (int num = _cachedSocketAddr.Size - 1; num >= 0; num--) { byte b = _cachedSocketAddr[num]; if (b != targetAddress[num] && b < targetAddress[num]) { return ConnectRequestResult.P2PLose; } } break; } case ConnectionState.Connected: if (connRequest.ConnectionTime == _connectTime) { NetManager.SendRaw(_connectAcceptPacket, this); } else if (connRequest.ConnectionTime > _connectTime) { return ConnectRequestResult.Reconnection; } break; case ConnectionState.ShutdownRequested: case ConnectionState.Disconnected: if (connRequest.ConnectionTime >= _connectTime) { return ConnectRequestResult.NewConnection; } break; } return ConnectRequestResult.None; } internal virtual void ProcessChanneled(NetPacket packet) { if (packet.ChannelId >= 4 || packet.ChannelId == 3) { NetManager.PoolRecycle(packet); } else if (!CreateChannel(packet.ChannelId).ProcessPacket(packet)) { NetManager.PoolRecycle(packet); } } internal void ProcessPacket(NetPacket packet) { if (_connectionState == ConnectionState.Outgoing || _connectionState == ConnectionState.Disconnected) { NetManager.PoolRecycle(packet); return; } if (packet.Property == PacketProperty.ShutdownOk) { if (_connectionState == ConnectionState.ShutdownRequested) { _connectionState = ConnectionState.Disconnected; } NetManager.PoolRecycle(packet); return; } if (packet.ConnectionNumber != _connectNum) { NetManager.PoolRecycle(packet); return; } Interlocked.Exchange(ref _timeSinceLastPacket, 0f); switch (packet.Property) { case PacketProperty.Merged: { int num2 = 1; while (num2 < packet.Size) { ushort num3 = BitConverter.ToUInt16(packet.RawData, num2); if (num3 == 0) { break; } num2 += 2; if (packet.Size - num2 < num3) { break; } NetPacket netPacket = NetManager.PoolGetPacket(num3); Buffer.BlockCopy(packet.RawData, num2, netPacket.RawData, 0, num3); netPacket.Size = num3; if (!netPacket.Verify()) { break; } num2 += num3; ProcessPacket(netPacket); } NetManager.PoolRecycle(packet); break; } case PacketProperty.Ping: if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pongPacket.Sequence) > 0) { FastBitConverter.GetBytes(_pongPacket.RawData, 3, DateTime.UtcNow.Ticks); _pongPacket.Sequence = packet.Sequence; NetManager.SendRaw(_pongPacket, this); } NetManager.PoolRecycle(packet); break; case PacketProperty.Pong: if (packet.Sequence == _pingPacket.Sequence) { _pingTimer.Stop(); int num = (int)_pingTimer.ElapsedMilliseconds; _remoteDelta = BitConverter.ToInt64(packet.RawData, 3) + (long)num * 10000L / 2 - DateTime.UtcNow.Ticks; UpdateRoundTripT
BepInEx/plugins/ULTRAKILL.Bloodlink.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LiteNetLib; using LiteNetLib.Layers; using LiteNetLib.Utils; using ULTRAKILL.Bloodlink.Combat; using ULTRAKILL.Bloodlink.Core; using ULTRAKILL.Bloodlink.Enemies; using ULTRAKILL.Bloodlink.Levels; using ULTRAKILL.Bloodlink.Networking; using ULTRAKILL.Bloodlink.Players; using ULTRAKILL.Bloodlink.UI; using ULTRAKILL.Enemy; using ULTRAKILL.Portal; using Unity.Collections; using Unity.Jobs; using Unity.Mathematics; using Unity.Networking.Transport; using Unity.Networking.Transport.Relay; using Unity.Networking.Transport.Utilities; using Unity.Services.Authentication; using Unity.Services.Core; using Unity.Services.Core.Internal; using Unity.Services.Qos; using Unity.Services.Relay; using Unity.Services.Relay.Models; using Unity.Services.Relay.Scheduler; using UnityEngine; using UnityEngine.AI; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ULTRAKILL.Bloodlink")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ULTRAKILL.Bloodlink")] [assembly: AssemblyTitle("ULTRAKILL.Bloodlink")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace ULTRAKILL.Bloodlink.UI { [HarmonyPatch(typeof(MainMenuAgony), "Start")] internal static class MainMenuMultiplayerButtonPatch { private static void Postfix(MainMenuAgony __instance) { if ((Object)(object)((Component)__instance).GetComponent<MainMenuMultiplayerButton>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<MainMenuMultiplayerButton>(); BloodlinkPlugin.Instance?.LogMainMenuInjected(); } } } internal sealed class MainMenuMultiplayerButton : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__5_0; internal void <Start>b__5_0() { BloodlinkPlugin.Instance?.OpenMultiplayerPanel(); } } private GameObject canvasObject; internal static bool UiPresent { get; private set; } private void Start() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Expected O, but got Unknown canvasObject = new GameObject("Bloodlink Multiplayer Menu Button", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); MainMenuAgony component = ((Component)this).GetComponent<MainMenuAgony>(); GameObject val = (((Object)(object)component != (Object)null) ? component.mainMenu : null); canvasObject.transform.SetParent(((Object)(object)val != (Object)null) ? val.transform : ((Component)this).transform, false); Canvas component2 = canvasObject.GetComponent<Canvas>(); component2.renderMode = (RenderMode)0; component2.sortingOrder = 1000; component2.overrideSorting = true; CanvasScaler component3 = canvasObject.GetComponent<CanvasScaler>(); component3.uiScaleMode = (ScaleMode)1; component3.referenceResolution = new Vector2(1920f, 1080f); component3.matchWidthOrHeight = 0.5f; GameObject val2 = new GameObject("Multiplayer", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val2.transform.SetParent(canvasObject.transform, false); RectTransform component4 = val2.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 0f); component4.anchorMax = new Vector2(0f, 0f); component4.pivot = new Vector2(0f, 0f); component4.anchoredPosition = new Vector2(56f, 48f); component4.sizeDelta = new Vector2(300f, 74f); Image component5 = val2.GetComponent<Image>(); ((Graphic)component5).color = new Color(0.12f, 0.035f, 0.045f, 0.98f); Button component6 = val2.GetComponent<Button>(); ((Selectable)component6).targetGraphic = (Graphic)(object)component5; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)component6).navigation = navigation; ((Selectable)component6).transition = (Transition)1; ColorBlock colors = default(ColorBlock); ((ColorBlock)(ref colors)).normalColor = Color.white; ((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.76f, 0.76f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.78f, 0.52f, 0.52f, 1f); ((ColorBlock)(ref colors)).selectedColor = Color.white; ((ColorBlock)(ref colors)).disabledColor = new Color(0.45f, 0.45f, 0.45f, 0.6f); ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((ColorBlock)(ref colors)).fadeDuration = 0.08f; ((Selectable)component6).colors = colors; Outline obj = val2.AddComponent<Outline>(); ((Shadow)obj).effectColor = new Color(0.42f, 0.025f, 0.04f, 0.95f); ((Shadow)obj).effectDistance = new Vector2(1.5f, -1.5f); ButtonClickedEvent onClick = component6.onClick; object obj2 = <>c.<>9__5_0; if (obj2 == null) { UnityAction val3 = delegate { BloodlinkPlugin.Instance?.OpenMultiplayerPanel(); }; <>c.<>9__5_0 = val3; obj2 = (object)val3; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); GameObject val4 = new GameObject("Accent", new Type[2] { typeof(RectTransform), typeof(Image) }); val4.transform.SetParent(val2.transform, false); RectTransform component7 = val4.GetComponent<RectTransform>(); component7.anchorMin = new Vector2(0f, 0f); component7.anchorMax = new Vector2(0f, 1f); component7.pivot = new Vector2(0f, 0.5f); component7.anchoredPosition = Vector2.zero; component7.sizeDelta = new Vector2(5f, 0f); ((Graphic)val4.GetComponent<Image>()).color = new Color(0.9f, 0.045f, 0.065f, 1f); ((Graphic)val4.GetComponent<Image>()).raycastTarget = false; CreateLabel(val2.transform, "Title", "MULTIPLAYER", 25, (FontStyle)1, (TextAnchor)6, new Vector2(28f, 0.45f), new Vector2(-12f, -8f)); ((Graphic)CreateLabel(val2.transform, "Subtitle", "HOST / JOIN / CO-OP", 12, (FontStyle)1, (TextAnchor)0, new Vector2(28f, 8f), new Vector2(-12f, -42f))).color = new Color(0.84f, 0.72f, 0.72f, 1f); UiPresent = true; } private static Text CreateLabel(Transform parent, string objectName, string value, int fontSize, FontStyle fontStyle, TextAnchor alignment, Vector2 offsetMin, Vector2 offsetMax) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(objectName, new Type[2] { typeof(RectTransform), typeof(Text) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = offsetMin; component.offsetMax = offsetMax; Text component2 = val.GetComponent<Text>(); component2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); if ((Object)(object)component2.font == (Object)null) { component2.font = Font.CreateDynamicFontFromOSFont("Arial", fontSize); } component2.text = value; component2.fontSize = fontSize; component2.fontStyle = fontStyle; component2.alignment = alignment; ((Graphic)component2).color = Color.white; ((Graphic)component2).raycastTarget = false; return component2; } private void OnEnable() { if ((Object)(object)canvasObject != (Object)null) { UiPresent = true; } } private void OnDisable() { UiPresent = false; } private void OnDestroy() { UiPresent = false; if ((Object)(object)canvasObject != (Object)null) { Object.Destroy((Object)(object)canvasObject); } } } internal sealed class MuseumChessPanel : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__8_0; internal void <TryCreate>b__8_0() { MuseumChessSession.Promotion = (byte)(MuseumChessSession.Promotion % 4 + 1); } } private Button versus; private Button promotion; private Button bot; private Text versusText; private Text promotionText; private GameObject container; private float nextSearch; private void Update() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)versus == (Object)null) { if (!(Time.unscaledTime < nextSearch)) { nextSearch = Time.unscaledTime + 1f; TryCreate(); } } else { BloodlinkPlugin instance = BloodlinkPlugin.Instance; ((Selectable)versus).interactable = (Object)(object)instance != (Object)null && instance.IsConnected && instance.Network.Players.Count >= 2; versusText.text = "VS PLAYER" + (MuseumChessSession.Active ? ("\n" + MuseumChessSession.Status) : "\nHOST: WHITE / GUEST: BLACK"); ((Selectable)bot).interactable = !MuseumChessSession.Active || ((Object)(object)instance != (Object)null && instance.IsHost); promotionText.text = "PROMOTION: " + ((object)(PieceType)MuseumChessSession.Promotion/*cast due to .constrained prefix*/).ToString().ToUpperInvariant(); } } private void TryCreate() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Expected O, but got Unknown ChessManager component = ((Component)this).GetComponent<ChessManager>(); Button val = null; Button[] array = Resources.FindObjectsOfTypeAll<Button>(); foreach (Button val2 in array) { if ((Object)(object)val2 == (Object)null || ((Component)val2).gameObject.scene != ((Component)this).gameObject.scene || (Object)(object)((Component)((Component)val2).transform).GetComponentInParent<Canvas>() == (Object)null) { continue; } for (int j = 0; j < ((UnityEventBase)val2.onClick).GetPersistentEventCount(); j++) { if (((UnityEventBase)val2.onClick).GetPersistentTarget(j) == (Object)(object)component) { val = val2; break; } } if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { return; } RectTransform component2 = ((Component)val).GetComponent<RectTransform>(); container = new GameObject("Bloodlink Chess Multiplayer", new Type[3] { typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(LayoutElement) }); container.transform.SetParent(((Component)val).transform.parent, false); container.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); RectTransform component3 = container.GetComponent<RectTransform>(); component3.anchorMin = component2.anchorMin; component3.anchorMax = component2.anchorMax; component3.pivot = component2.pivot; Rect rect = component2.rect; float num = Mathf.Max(38f, ((Rect)(ref rect)).height); rect = component2.rect; component3.sizeDelta = new Vector2(Mathf.Max(260f, ((Rect)(ref rect)).width), num * 3f + 12f); component3.anchoredPosition = component2.anchoredPosition + Vector2.down * (num + 8f); VerticalLayoutGroup component4 = container.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component4).spacing = 6f; bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component4).childControlHeight = true); ((HorizontalOrVerticalLayoutGroup)component4).childControlWidth = childControlWidth; ((HorizontalOrVerticalLayoutGroup)component4).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)component4).childForceExpandHeight = false; container.GetComponent<LayoutElement>().preferredHeight = num * 3f + 12f; LayoutElement component5 = container.GetComponent<LayoutElement>(); rect = component2.rect; component5.preferredWidth = Mathf.Max(260f, ((Rect)(ref rect)).width); versus = CreateButton("VS PLAYER", num, out versusText); ((UnityEvent)versus.onClick).AddListener(new UnityAction(MuseumChessSession.RequestStart)); bot = CreateButton("VS BOT", num, out var _); ((UnityEvent)bot.onClick).AddListener(new UnityAction(MuseumChessSession.StartBotGame)); promotion = CreateButton("PROMOTION: QUEEN", num, out promotionText); ButtonClickedEvent onClick = promotion.onClick; object obj = <>c.<>9__8_0; if (obj == null) { UnityAction val3 = delegate { MuseumChessSession.Promotion = (byte)(MuseumChessSession.Promotion % 4 + 1); }; <>c.<>9__8_0 = val3; obj = (object)val3; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } private Button CreateButton(string label, float height, out Text text) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(label, new Type[4] { typeof(RectTransform), typeof(Image), typeof(Button), typeof(LayoutElement) }); val.transform.SetParent(container.transform, false); ((Graphic)val.GetComponent<Image>()).color = new Color(0.18f, 0.025f, 0.025f, 0.98f); val.GetComponent<LayoutElement>().preferredHeight = height; Button component = val.GetComponent<Button>(); ((Selectable)component).targetGraphic = (Graphic)(object)val.GetComponent<Image>(); GameObject val2 = new GameObject("Label", new Type[2] { typeof(RectTransform), typeof(Text) }); val2.transform.SetParent(val.transform, false); RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = new Vector2(6f, 2f); component2.offsetMax = new Vector2(-6f, -2f); text = val2.GetComponent<Text>(); text.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); text.text = label; text.fontSize = 17; text.fontStyle = (FontStyle)1; text.alignment = (TextAnchor)4; ((Graphic)text).color = Color.white; ((Graphic)text).raycastTarget = false; return component; } private void OnDestroy() { if ((Object)(object)container != (Object)null) { Object.Destroy((Object)(object)container); } } } } namespace ULTRAKILL.Bloodlink.Players { internal sealed class CosmeticProjectileFlight : MonoBehaviour { private Vector3 velocity; private Vector3 gravity; private Vector3 angularVelocity; private float remaining = 5f; public void Initialize(Vector3 initialVelocity, Vector3 gravityAcceleration, Vector3 initialAngularVelocity, float lifetime = 5f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) velocity = initialVelocity; gravity = gravityAcceleration; angularVelocity = initialAngularVelocity; remaining = Mathf.Clamp(lifetime, 0.1f, 10f); } private void Update() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(Time.unscaledDeltaTime, 0.05f); Transform transform = ((Component)this).transform; transform.position += velocity * num; velocity += gravity * num; ((Component)this).transform.Rotate(angularVelocity * 57.29578f * num, (Space)0); remaining -= num; if (remaining <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } public sealed class RemotePlayerVisual : MonoBehaviour { private struct TimedSnapshot { public PlayerSnapshot State; public float ReceivedAt; } private readonly List<TimedSnapshot> buffer = new List<TimedSnapshot>(8); private readonly List<Animator> animators = new List<Animator>(); private readonly Dictionary<Animator, HashSet<int>> animatorParameterHashes = new Dictionary<Animator, HashSet<int>>(); private readonly List<GameObject> remoteCoinInstances = new List<GameObject>(); private readonly List<GameObject> remoteNailInstances = new List<GameObject>(); private readonly List<GameObject> remoteRocketInstances = new List<GameObject>(); private Renderer[] visualRenderers; private MaterialPropertyBlock[] appearanceBlocks; private uint lastPrimaryColor = uint.MaxValue; private uint lastSecondaryColor = uint.MaxValue; private uint lastLightColor = uint.MaxValue; private byte lastGlowIntensity; private GameObject[] baseWeapons; private GameObject[] alternateWeapons; private Transform modelRoot; private Transform remoteHead; private Transform remoteRightArm; private Transform remoteChest; private Quaternion modelBaseLocalRotation = Quaternion.identity; private float landingLayerWeight; private TextMesh nameplate; private TextMesh nameplateShadow; private uint lastReceivedTick; private bool hasReceivedSnapshot; private Transform recoilingWeapon; private Vector3 weaponRestPosition; private Quaternion weaponRestRotation; private float recoilUntil; private int lastDeadState = -1; private float nextAnimatorDiagnosticAt; private byte lastWeaponSlot = byte.MaxValue; private byte lastWeaponVariation = byte.MaxValue; private bool hasWeaponState; private bool lastWeaponAlternate; private Vector3 sampledPlanarVelocity; private bool hasRenderedPosition; public uint PlayerId { get; private set; } internal bool HasRenderableModel { get { if (visualRenderers == null || visualRenderers.Length == 0) { return false; } for (int i = 0; i < visualRenderers.Length; i++) { Renderer val = visualRenderers[i]; if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy) { SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null) { return true; } MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { return true; } } } return false; } } public static RemotePlayerVisual Create(PlayerAnimations template, uint playerId, string playerName) { return Create(template, null, playerId, playerName); } public static RemotePlayerVisual Create(PlayerAnimations template, Transform sourcePlayerRoot, uint playerId, string playerName) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0599: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Expected O, but got Unknown //IL_0612: Unknown result type (might be due to invalid IL or missing references) //IL_069d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Bloodlink Remote Player " + playerId); RemotePlayerVisual remotePlayerVisual = val.AddComponent<RemotePlayerVisual>(); remotePlayerVisual.PlayerId = playerId; GameObject val2 = new GameObject("Remote V1 Runtime Model"); val2.transform.SetParent(val.transform, false); val2.SetActive(false); GameObject val3 = Object.Instantiate<GameObject>(((Component)template).gameObject, val2.transform, false); ((Object)val3).name = "Remote V1 Rig"; val3.transform.localPosition = (((Object)(object)sourcePlayerRoot != (Object)null) ? sourcePlayerRoot.InverseTransformPoint(((Component)template).transform.position) : ((Component)template).transform.localPosition); val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = GetRelativeScale(((Component)template).transform, sourcePlayerRoot); Behaviour[] componentsInChildren = val3.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val4 in componentsInChildren) { Animator val5 = (Animator)(object)((val4 is Animator) ? val4 : null); if ((Object)(object)val5 != (Object)null) { ((Behaviour)val5).enabled = true; val5.applyRootMotion = false; val5.cullingMode = (AnimatorCullingMode)0; val5.updateMode = (AnimatorUpdateMode)2; if (!remotePlayerVisual.animators.Contains(val5)) { remotePlayerVisual.animators.Add(val5); } } else { val4.enabled = false; } } Collider[] componentsInChildren2 = val3.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } Rigidbody[] componentsInChildren3 = val3.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody obj in componentsInChildren3) { obj.isKinematic = true; obj.useGravity = false; } Camera[] componentsInChildren4 = val3.GetComponentsInChildren<Camera>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { ((Behaviour)componentsInChildren4[i]).enabled = false; } AudioSource[] componentsInChildren5 = val3.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource obj2 in componentsInChildren5) { obj2.Stop(); ((Behaviour)obj2).enabled = false; } remotePlayerVisual.modelRoot = val3.transform; remotePlayerVisual.modelBaseLocalRotation = Quaternion.identity; Renderer[] componentsInChildren6 = val2.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj3 in componentsInChildren6) { obj3.enabled = true; ((Component)obj3).gameObject.layer = 0; SkinnedMeshRenderer val6 = (SkinnedMeshRenderer)(object)((obj3 is SkinnedMeshRenderer) ? obj3 : null); if ((Object)(object)val6 != (Object)null) { val6.updateWhenOffscreen = true; } } remotePlayerVisual.visualRenderers = val2.GetComponentsInChildren<Renderer>(true); remotePlayerVisual.appearanceBlocks = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[remotePlayerVisual.visualRenderers.Length]; for (int j = 0; j < remotePlayerVisual.appearanceBlocks.Length; j++) { remotePlayerVisual.appearanceBlocks[j] = new MaterialPropertyBlock(); } remotePlayerVisual.baseWeapons = RemapWeapons(template.weapons, ((Component)template).transform, val3.transform); remotePlayerVisual.alternateWeapons = RemapWeapons(template.altweapons, ((Component)template).transform, val3.transform); PlayerAnimations component = val3.GetComponent<PlayerAnimations>(); remotePlayerVisual.remoteHead = (((Object)(object)component != (Object)null) ? component.head : null); remotePlayerVisual.remoteRightArm = (((Object)(object)component != (Object)null) ? component.rightArm : null); remotePlayerVisual.remoteChest = (((Object)(object)component != (Object)null) ? component.chest : null); MonoBehaviour[] componentsInChildren7 = val3.GetComponentsInChildren<MonoBehaviour>(true); for (int i = 0; i < componentsInChildren7.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren7[i]); } val2.SetActive(true); val3.SetActive(true); foreach (Animator animator in remotePlayerVisual.animators) { animator.Rebind(); ((Behaviour)animator).enabled = true; animator.applyRootMotion = false; animator.speed = 1f; animator.updateMode = (AnimatorUpdateMode)2; animator.cullingMode = (AnimatorCullingMode)0; animator.Update(0f); remotePlayerVisual.CacheAnimatorParameters(animator); } BloodlinkPlugin instance = BloodlinkPlugin.Instance; if ((Object)(object)instance != (Object)null) { foreach (Animator animator2 in remotePlayerVisual.animators) { RuntimeAnimatorController runtimeAnimatorController = animator2.runtimeAnimatorController; instance.LogRemoteAnimatorDiagnostics("Remote V1 animator initialized for player " + playerId + ": controller=" + (((Object)(object)runtimeAnimatorController != (Object)null) ? ((Object)runtimeAnimatorController).name : "<none>") + ", avatar=" + (((Object)(object)animator2.avatar != (Object)null) ? ((Object)animator2.avatar).name : "<none>") + ", parameters=" + GetAnimatorParameterSummary(animator2) + ", enabled=" + ((Behaviour)animator2).isActiveAndEnabled + "."); } } GameObject val7 = new GameObject("Remote Player Name", new Type[1] { typeof(TextMesh) }); val7.transform.SetParent(val.transform, false); val7.transform.localPosition = new Vector3(0f, 2.1f, 0f); remotePlayerVisual.nameplate = val7.GetComponent<TextMesh>(); remotePlayerVisual.nameplate.text = playerName ?? ("Player " + playerId); remotePlayerVisual.nameplate.fontSize = 64; remotePlayerVisual.nameplate.characterSize = 0.075f; remotePlayerVisual.nameplate.anchor = (TextAnchor)4; remotePlayerVisual.nameplate.alignment = (TextAlignment)1; remotePlayerVisual.nameplate.color = new Color(1f, 0.87f, 0.82f, 1f); remotePlayerVisual.nameplate.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); ((Renderer)((Component)remotePlayerVisual.nameplate).GetComponent<MeshRenderer>()).sortingOrder = 100; GameObject val8 = new GameObject("Remote Player Name Shadow", new Type[1] { typeof(TextMesh) }); val8.transform.SetParent(val.transform, false); val8.transform.localPosition = new Vector3(0f, 2.1f, 0.005f); remotePlayerVisual.nameplateShadow = val8.GetComponent<TextMesh>(); remotePlayerVisual.nameplateShadow.font = remotePlayerVisual.nameplate.font; remotePlayerVisual.nameplateShadow.fontSize = remotePlayerVisual.nameplate.fontSize; remotePlayerVisual.nameplateShadow.characterSize = remotePlayerVisual.nameplate.characterSize; remotePlayerVisual.nameplateShadow.anchor = (TextAnchor)4; remotePlayerVisual.nameplateShadow.alignment = (TextAlignment)1; remotePlayerVisual.nameplateShadow.color = new Color(0f, 0f, 0f, 0.92f); ((Renderer)((Component)remotePlayerVisual.nameplateShadow).GetComponent<MeshRenderer>()).sortingOrder = 99; remotePlayerVisual.nameplateShadow.text = remotePlayerVisual.nameplate.text; return remotePlayerVisual; } private static Vector3 GetRelativeScale(Transform source, Transform sourceRoot) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sourceRoot == (Object)null) { return source.localScale; } Vector3 lossyScale = source.lossyScale; Vector3 lossyScale2 = sourceRoot.lossyScale; return new Vector3((Mathf.Abs(lossyScale2.x) > 0.0001f) ? (lossyScale.x / lossyScale2.x) : lossyScale.x, (Mathf.Abs(lossyScale2.y) > 0.0001f) ? (lossyScale.y / lossyScale2.y) : lossyScale.y, (Mathf.Abs(lossyScale2.z) > 0.0001f) ? (lossyScale.z / lossyScale2.z) : lossyScale.z); } private static Transform RemapTransform(Transform source, Transform sourceRoot, Transform cloneRoot) { if ((Object)(object)source == (Object)null) { return null; } string relativePath = GetRelativePath(source, sourceRoot); if (!string.IsNullOrEmpty(relativePath)) { return cloneRoot.Find(relativePath); } return null; } private static GameObject[] RemapWeapons(GameObject[] source, Transform sourceRoot, Transform cloneRoot) { if (source == null) { return Array.Empty<GameObject>(); } GameObject[] array = (GameObject[])(object)new GameObject[source.Length]; for (int i = 0; i < source.Length; i++) { if (!((Object)(object)source[i] == (Object)null)) { string relativePath = GetRelativePath(source[i].transform, sourceRoot); Transform val = (string.IsNullOrEmpty(relativePath) ? null : cloneRoot.Find(relativePath)); array[i] = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); } } return array; } private static string GetRelativePath(Transform target, Transform root) { List<string> list = new List<string>(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Insert(0, ((Object)val).name); val = val.parent; } if (!((Object)(object)val == (Object)(object)root)) { return string.Empty; } return string.Join("/", list.ToArray()); } public void Push(PlayerSnapshot state) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) if (state == null) { return; } if (!hasReceivedSnapshot || state.Tick != lastReceivedTick) { if (buffer.Count > 0) { TimedSnapshot timedSnapshot = buffer[buffer.Count - 1]; float num = Time.unscaledTime - timedSnapshot.ReceivedAt; if (num > 0.005f && num < 0.5f) { Vector3 val = Vector3.ProjectOnPlane((state.Position - timedSnapshot.State.Position) / num, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 67600f) { sampledPlanarVelocity = val; } } } buffer.Add(new TimedSnapshot { State = state, ReceivedAt = Time.unscaledTime }); lastReceivedTick = state.Tick; hasReceivedSnapshot = true; while (buffer.Count > 12) { buffer.RemoveAt(0); } } if ((Object)(object)nameplate != (Object)null) { bool flag = (state.MovementFlags & 4) != 0; nameplate.text = (flag ? ((state.PlayerName ?? ("Player " + PlayerId)) + "\nDEAD") : ((state.PlayerName ?? ("Player " + PlayerId)) + "\n" + state.Health + " HP")); if ((Object)(object)nameplateShadow != (Object)null) { nameplateShadow.text = nameplate.text; } nameplate.color = (flag ? new Color(0.72f, 0.72f, 0.72f, 1f) : new Color(1f, 0.87f, 0.82f, 1f)); } if ((state.MovementFlags & 4) != 0) { SetWeapon(0, 0); } else { SetWeapon(state.WeaponSlot, state.WeaponVariation, state.WeaponAlternate); } ApplyAppearance(state.PrimaryColor, state.SecondaryColor, state.LightColor, state.GlowIntensity); } private void LateUpdate() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) UpdateWeaponRecoil(); UpdateAnimationLayers(); if (buffer.Count == 0) { return; } float num = Time.unscaledTime - 0.1f; TimedSnapshot timedSnapshot = buffer[0]; TimedSnapshot timedSnapshot2 = buffer[buffer.Count - 1]; if (num <= timedSnapshot.ReceivedAt) { Apply(timedSnapshot.State.Position, timedSnapshot.State.Rotation); Animate(timedSnapshot.State); return; } for (int i = 1; i < buffer.Count; i++) { TimedSnapshot timedSnapshot3 = buffer[i]; if (num <= timedSnapshot3.ReceivedAt) { TimedSnapshot timedSnapshot4 = buffer[i - 1]; float num2 = Mathf.Max(0.001f, timedSnapshot3.ReceivedAt - timedSnapshot4.ReceivedAt); float num3 = Mathf.Clamp01((num - timedSnapshot4.ReceivedAt) / num2); Apply(Vector3.Lerp(timedSnapshot4.State.Position, timedSnapshot3.State.Position, num3), Quaternion.Slerp(timedSnapshot4.State.Rotation, timedSnapshot3.State.Rotation, num3)); Animate(timedSnapshot3.State); return; } } float num4 = Mathf.Clamp(num - timedSnapshot2.ReceivedAt, 0f, 0.1f); Apply(timedSnapshot2.State.Position + timedSnapshot2.State.Velocity * num4, timedSnapshot2.State.Rotation); Animate(timedSnapshot2.State); } public void PlayWeaponFire(byte slot, byte variation, byte fireKind, Quaternion aimRotation, bool weaponAlternate = false) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) SetWeapon(slot, variation, weaponAlternate); int num = ((slot > 0) ? (slot - 1) : 255); GameObject[] array = (lastWeaponAlternate ? alternateWeapons : baseWeapons); if (num >= array.Length || (Object)(object)array[num] == (Object)null) { return; } Transform transform = array[num].transform; PlayMuzzleFlash(((Component)transform).gameObject, slot, fireKind, aimRotation); foreach (Animator animator in animators) { SetFloatIfPresent(animator, "ShootSpeed", 1f); SetTriggerIfPresent(animator, (slot == 5 && fireKind == 9) ? "Spray" : "Shoot"); } if ((Object)(object)recoilingWeapon != (Object)(object)transform) { RestoreWeaponRecoil(); recoilingWeapon = transform; weaponRestPosition = transform.localPosition; weaponRestRotation = transform.localRotation; } recoilUntil = Time.unscaledTime + 0.075f; transform.localPosition = weaponRestPosition + Vector3.back * 0.055f; transform.localRotation = weaponRestRotation * Quaternion.Euler(-5f, 0f, 0f); } public void PlayPlayerAnimation(PlayerAnimationEvent animation) { if (animation == null) { return; } foreach (Animator animator in animators) { if (animation.Action == PlayerAnimationAction.Punch) { SetFloatIfPresent(animator, "PunchSpeed", animation.Speed); SetTriggerIfPresent(animator, "Punch"); } else if (animation.Action == PlayerAnimationAction.CoinToss) { SetTriggerIfPresent(animator, "CoinToss"); } else if (animation.Action == PlayerAnimationAction.Parry) { SetTriggerIfPresent(animator, "Parry"); } else if (animation.Action == PlayerAnimationAction.Jump) { SetTriggerIfPresent(animator, "Jump"); } else if (animation.Action == PlayerAnimationAction.Land) { landingLayerWeight = Mathf.Clamp01(animation.Speed); if (animator.layerCount > 1) { animator.SetLayerWeight(1, landingLayerWeight); } } } } public void PlayCoinProjectile(CoinProjectileEvent coin) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) if (coin == null || coin.OwnerPlayerId != PlayerId) { return; } GameObject[] array = (lastWeaponAlternate ? alternateWeapons : baseWeapons); if (array == null || array.Length == 0 || (Object)(object)array[0] == (Object)null) { return; } GameObject val = null; Revolver componentInChildren = array[0].GetComponentInChildren<Revolver>(true); if ((Object)(object)componentInChildren != (Object)null) { val = componentInChildren.coin; } if ((Object)(object)val == (Object)null) { return; } PlayPrefabOneShots(val, coin.Position); for (int num = remoteCoinInstances.Count - 1; num >= 0; num--) { if ((Object)(object)remoteCoinInstances[num] == (Object)null) { remoteCoinInstances.RemoveAt(num); } } while (remoteCoinInstances.Count >= 8) { if ((Object)(object)remoteCoinInstances[0] != (Object)null) { Object.Destroy((Object)(object)remoteCoinInstances[0]); } remoteCoinInstances.RemoveAt(0); } GameObject val2 = InstantiateCosmeticProjectile(val, coin.Position, coin.Rotation, coin.Velocity, coin.Gravity, coin.AngularVelocity, 5f, "Bloodlink Remote Coin " + PlayerId); if (!((Object)(object)val2 == (Object)null)) { remoteCoinInstances.Add(val2); } } public void PlayNailProjectile(NailProjectileEvent projectile) { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (projectile == null || projectile.OwnerPlayerId != PlayerId) { return; } GameObject[] array = (lastWeaponAlternate ? alternateWeapons : baseWeapons); if (array == null || array.Length <= 2 || (Object)(object)array[2] == (Object)null) { return; } Nailgun componentInChildren = array[2].GetComponentInChildren<Nailgun>(true); if ((Object)(object)componentInChildren == (Object)null) { return; } GameObject val = ((projectile.VisualKind == 1 || projectile.VisualKind == 3) ? componentInChildren.heatedNail : componentInChildren.nail); if ((Object)(object)val == (Object)null) { return; } for (int num = remoteNailInstances.Count - 1; num >= 0; num--) { if ((Object)(object)remoteNailInstances[num] == (Object)null) { remoteNailInstances.RemoveAt(num); } } while (remoteNailInstances.Count >= 40) { if ((Object)(object)remoteNailInstances[0] != (Object)null) { Object.Destroy((Object)(object)remoteNailInstances[0]); } remoteNailInstances.RemoveAt(0); } GameObject val2 = InstantiateCosmeticProjectile(val, projectile.Position, projectile.Rotation, projectile.Velocity, projectile.Gravity, projectile.AngularVelocity, 3f, "Bloodlink Remote Nail Projectile " + PlayerId); if (!((Object)(object)val2 == (Object)null)) { remoteNailInstances.Add(val2); } } public void PlayRocketProjectile(RocketProjectileEvent projectile) { //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if (projectile == null || projectile.OwnerPlayerId != PlayerId) { return; } GameObject[] array = (lastWeaponAlternate ? alternateWeapons : baseWeapons); if (array == null || array.Length <= 4 || (Object)(object)array[4] == (Object)null) { return; } RocketLauncher componentInChildren = array[4].GetComponentInChildren<RocketLauncher>(true); if ((Object)(object)componentInChildren == (Object)null) { return; } GameObject val = ((projectile.VisualKind == 1) ? (((Object)(object)componentInChildren.cannonBall != (Object)null) ? ((Component)componentInChildren.cannonBall).gameObject : null) : ((projectile.VisualKind != 2) ? componentInChildren.rocket : (((Object)(object)componentInChildren.napalmProjectile != (Object)null) ? ((Component)componentInChildren.napalmProjectile).gameObject : null))); if ((Object)(object)val == (Object)null) { return; } for (int num = remoteRocketInstances.Count - 1; num >= 0; num--) { if ((Object)(object)remoteRocketInstances[num] == (Object)null) { remoteRocketInstances.RemoveAt(num); } } while (remoteRocketInstances.Count >= 12) { if ((Object)(object)remoteRocketInstances[0] != (Object)null) { Object.Destroy((Object)(object)remoteRocketInstances[0]); } remoteRocketInstances.RemoveAt(0); } GameObject val2 = InstantiateCosmeticProjectile(val, projectile.Position, projectile.Rotation, projectile.Velocity, projectile.Gravity, projectile.AngularVelocity, 4f, "Bloodlink Remote Rocket Projectile " + PlayerId); if (!((Object)(object)val2 == (Object)null)) { remoteRocketInstances.Add(val2); } } private static GameObject InstantiateCosmeticProjectile(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 gravity, Vector3 angularVelocity, float lifetime, string objectName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return null; } GameObject val = new GameObject("Bloodlink Inactive Projectile Guard"); val.SetActive(false); GameObject val2 = Object.Instantiate<GameObject>(prefab, position, rotation, val.transform); if ((Object)(object)val2 == (Object)null) { Object.Destroy((Object)(object)val); return null; } ((Object)val2).name = objectName; val2.SetActive(false); Behaviour[] componentsInChildren = val2.GetComponentsInChildren<Behaviour>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Collider[] componentsInChildren2 = val2.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } Rigidbody[] componentsInChildren3 = val2.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody obj in componentsInChildren3) { obj.isKinematic = true; obj.useGravity = false; obj.velocity = Vector3.zero; obj.angularVelocity = Vector3.zero; } AudioSource[] componentsInChildren4 = val2.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource obj2 in componentsInChildren4) { obj2.Stop(); ((Behaviour)obj2).enabled = false; } Renderer[] componentsInChildren5 = val2.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren5.Length; i++) { componentsInChildren5[i].enabled = true; } val2.AddComponent<CosmeticProjectileFlight>().Initialize(velocity, gravity, angularVelocity, lifetime); val2.transform.SetParent((Transform)null, true); Object.Destroy((Object)(object)val); val2.SetActive(true); return val2; } private static void PlayMuzzleFlash(GameObject weapon, byte slot, byte fireKind, Quaternion aimRotation) { //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Expected O, but got Unknown if ((Object)(object)weapon == (Object)null) { return; } GameObject val = null; Transform val2 = null; switch (slot) { case 1: { Revolver componentInChildren4 = weapon.GetComponentInChildren<Revolver>(true); if ((Object)(object)componentInChildren4 != (Object)null && (Object)(object)componentInChildren4.gunBarrel != (Object)null) { val2 = componentInChildren4.gunBarrel.transform; } break; } case 2: { Shotgun componentInChildren5 = weapon.GetComponentInChildren<Shotgun>(true); if ((Object)(object)componentInChildren5 != (Object)null) { val = componentInChildren5.muzzleFlash; if (componentInChildren5.shootPoints != null && componentInChildren5.shootPoints.Length != 0) { val2 = componentInChildren5.shootPoints[0]; } } break; } case 3: { Nailgun componentInChildren2 = weapon.GetComponentInChildren<Nailgun>(true); if (!((Object)(object)componentInChildren2 != (Object)null)) { break; } val = ((fireKind == 7) ? componentInChildren2.muzzleFlash2 : componentInChildren2.muzzleFlash); if (componentInChildren2.shootPoints != null && componentInChildren2.shootPoints.Length != 0) { int num = Mathf.Clamp(componentInChildren2.barrelNum, 0, componentInChildren2.shootPoints.Length - 1); if ((Object)(object)componentInChildren2.shootPoints[num] != (Object)null) { val2 = componentInChildren2.shootPoints[num].transform; } } break; } case 4: { Railcannon componentInChildren3 = weapon.GetComponentInChildren<Railcannon>(true); if ((Object)(object)componentInChildren3 != (Object)null) { val2 = componentInChildren3.shootPoint; } break; } case 5: { RocketLauncher componentInChildren = weapon.GetComponentInChildren<RocketLauncher>(true); if (!((Object)(object)componentInChildren != (Object)null)) { break; } val = componentInChildren.muzzleFlash; val2 = componentInChildren.shootPoint; if (fireKind != 9) { break; } ParticleSystem napalmMuzzleFlashParticles = componentInChildren.napalmMuzzleFlashParticles; if ((Object)(object)napalmMuzzleFlashParticles != (Object)null) { if ((Object)(object)val2 == (Object)null) { val2 = ((Component)napalmMuzzleFlashParticles).transform; } ((Component)napalmMuzzleFlashParticles).transform.SetPositionAndRotation(val2.position, aimRotation); napalmMuzzleFlashParticles.Play(true); return; } break; } } if ((Object)(object)val2 == (Object)null) { val2 = weapon.transform; } if ((Object)(object)val != (Object)null) { PlayPrefabOneShots(val, val2.position); GameObject val3 = Object.Instantiate<GameObject>(val, val2.position, aimRotation); AudioSource[] componentsInChildren = val3.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource obj in componentsInChildren) { obj.Stop(); ((Behaviour)obj).enabled = false; } Collider[] componentsInChildren2 = val3.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } Rigidbody[] componentsInChildren3 = val3.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody obj2 in componentsInChildren3) { obj2.isKinematic = true; obj2.useGravity = false; } ParticleSystem[] componentsInChildren4 = val3.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { componentsInChildren4[i].Play(true); } Object.Destroy((Object)(object)val3, 1.25f); } else { GameObject val4 = new GameObject("Bloodlink Remote Muzzle Flash"); val4.transform.SetPositionAndRotation(val2.position, aimRotation); Light obj3 = val4.AddComponent<Light>(); obj3.type = (LightType)2; obj3.color = ((slot == 4) ? new Color(0.2f, 0.8f, 1f) : new Color(1f, 0.32f, 0.08f)); obj3.intensity = ((slot == 4) ? 5f : 2.5f); obj3.range = ((slot == 4) ? 5f : 2.25f); Object.Destroy((Object)val4, 0.08f); } } private static void PlayPrefabOneShots(GameObject prefab, Vector3 position) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown if ((Object)(object)prefab == (Object)null) { return; } AudioSource[] componentsInChildren = prefab.GetComponentsInChildren<AudioSource>(true); int num = 0; for (int i = 0; i < componentsInChildren.Length; i++) { if (num >= 4) { break; } AudioSource val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.clip == (Object)null) && !val.loop) { GameObject val2 = new GameObject("Bloodlink spatial sound"); val2.transform.position = position; AudioSource val3 = val2.AddComponent<AudioSource>(); val3.clip = val.clip; val3.volume = Mathf.Clamp01(val.volume); val3.pitch = Mathf.Clamp(val.pitch, 0.25f, 3f); val3.spatialBlend = 1f; val3.minDistance = Mathf.Max(0.1f, val.minDistance); val3.maxDistance = Mathf.Max(val3.minDistance + 0.1f, Mathf.Min(80f, val.maxDistance)); val3.rolloffMode = val.rolloffMode; val3.dopplerLevel = 0f; val3.Play(); Object.Destroy((Object)val2, Mathf.Max(0.25f, val.clip.length / Mathf.Max(0.25f, Mathf.Abs(val3.pitch)) + 0.2f)); num++; } } } private void UpdateWeaponRecoil() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)recoilingWeapon == (Object)null)) { if (Time.unscaledTime >= recoilUntil) { RestoreWeaponRecoil(); return; } float num = Mathf.Clamp01((recoilUntil - Time.unscaledTime) / 0.075f); recoilingWeapon.localPosition = weaponRestPosition + Vector3.back * (0.055f * num); recoilingWeapon.localRotation = weaponRestRotation * Quaternion.Euler(-5f * num, 0f, 0f); } } private void RestoreWeaponRecoil() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)recoilingWeapon != (Object)null) { recoilingWeapon.localPosition = weaponRestPosition; recoilingWeapon.localRotation = weaponRestRotation; } recoilingWeapon = null; recoilUntil = 0f; } private void Apply(Vector3 position, Quaternion rotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) float y = ((Quaternion)(ref rotation)).eulerAngles.y; if (hasRenderedPosition) { Vector3 val = position - ((Component)this).transform.position; if (((Vector3)(ref val)).sqrMagnitude < 400f) { position = Vector3.Lerp(((Component)this).transform.position, position, PlayerPositionCorrectionPolicy.RemoteBlend(Time.unscaledDeltaTime)); } } hasRenderedPosition = true; ((Component)this).transform.SetPositionAndRotation(position, Quaternion.Euler(0f, y, 0f)); Camera main = Camera.main; if ((Object)(object)main != (Object)null && (Object)(object)nameplate != (Object)null) { Quaternion rotation2 = Quaternion.LookRotation(((Component)nameplate).transform.position - ((Component)main).transform.position); ((Component)nameplate).transform.rotation = rotation2; if ((Object)(object)nameplateShadow != (Object)null) { ((Component)nameplateShadow).transform.rotation = rotation2; } } } private void Animate(PlayerSnapshot state) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) if (animators.Count == 0) { return; } Vector3 val = Vector3.ProjectOnPlane(state.Velocity, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.25f && ((Vector3)(ref sampledPlanarVelocity)).sqrMagnitude > 0.25f) { val = sampledPlanarVelocity; } Vector3 val2 = ((Component)this).transform.InverseTransformDirection(val) / 15f; bool flag = (state.MovementFlags & 1) != 0; bool flag2 = (state.MovementFlags & 2) != 0; bool flag3 = (state.MovementFlags & 8) != 0; bool flag4 = state.WeaponSlot >= 3; bool flag5 = (state.MovementFlags & 4) != 0 && state.Health == 0; if (lastDeadState != (flag5 ? 1 : 0)) { lastDeadState = (flag5 ? 1 : 0); foreach (Animator animator in animators) { SetBoolIfPresent(animator, "Dead", flag5); SetBoolIfPresent(animator, "IsDead", flag5); if (flag5) { SetTriggerIfPresent(animator, "Death"); SetTriggerIfPresent(animator, "Die"); } } if (!flag5) { SetWeapon(state.WeaponSlot, state.WeaponVariation, state.WeaponAlternate); } } foreach (Animator animator2 in animators) { SetBoolIfPresent(animator2, "Dodging", flag && !flag2); SetBoolIfPresent(animator2, "Sliding", flag2); SetBoolIfPresent(animator2, "InAir", !flag3); SetBoolIfPresent(animator2, "BigWeapon", flag4); SetFloatIfPresent(animator2, "VelX", flag5 ? 0f : val2.x); SetFloatIfPresent(animator2, "VelY", flag5 ? 0f : val2.z); } if (Time.unscaledTime >= nextAnimatorDiagnosticAt) { nextAnimatorDiagnosticAt = Time.unscaledTime + 5f; BloodlinkPlugin instance = BloodlinkPlugin.Instance; if ((Object)(object)instance != (Object)null) { foreach (Animator animator3 in animators) { if (!((Object)(object)animator3 == (Object)null) && animator3.isInitialized && !((Object)(object)animator3.runtimeAnimatorController == (Object)null) && animator3.layerCount != 0) { AnimatorStateInfo currentAnimatorStateInfo = animator3.GetCurrentAnimatorStateInfo(0); instance.LogRemoteAnimatorDiagnostics("Remote V1 animation state player " + PlayerId + ": state=" + ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash + ", time=" + ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime.ToString("F2") + ", SnapshotVel=" + ((Vector3)(ref state.Velocity)).ToString("F2") + ", LocalVel=" + ((Vector3)(ref val2)).ToString("F2") + ", Flags=" + state.MovementFlags + ", Dead=" + flag5 + ", VelX=" + animator3.GetFloat("VelX").ToString("F2") + ", VelY=" + animator3.GetFloat("VelY").ToString("F2") + ", InAir=" + animator3.GetBool("InAir") + ", Sliding=" + animator3.GetBool("Sliding") + ", Dodging=" + animator3.GetBool("Dodging") + "."); } } } } UpdateModelFacing(state, flag2); ApplyRemoteAim(state.ViewRotation, flag4); } private void UpdateModelFacing(PlayerSnapshot state, bool sliding) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)modelRoot == (Object)null)) { Quaternion val = Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f) * modelBaseLocalRotation; Vector3 val2 = Vector3.ProjectOnPlane(state.Velocity, Vector3.up); if (sliding && ((Vector3)(ref val2)).sqrMagnitude > 1f) { val = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up) * modelBaseLocalRotation; } modelRoot.rotation = Quaternion.Slerp(modelRoot.rotation, val, 1f - Mathf.Exp(-12f * Time.unscaledDeltaTime)); } } private void UpdateAnimationLayers() { if (landingLayerWeight <= 0f) { return; } landingLayerWeight = Mathf.MoveTowards(landingLayerWeight, 0f, Time.unscaledDeltaTime * 3f); foreach (Animator animator in animators) { if ((Object)(object)animator != (Object)null && animator.layerCount > 1) { animator.SetLayerWeight(1, landingLayerWeight); } } } private void ApplyRemoteAim(Quaternion viewRotation, bool bigWeapon) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)remoteHead != (Object)null) { remoteHead.rotation = viewRotation; } if ((Object)(object)remoteChest != (Object)null) { float num = ((Quaternion)(ref viewRotation)).eulerAngles.x; if (num > 180f) { num -= 360f; } remoteChest.localRotation = Quaternion.Euler(num * 0.35f, 0f, 0f); } if (!((Object)(object)remoteRightArm == (Object)null)) { if (!bigWeapon) { AimRemoteArm(remoteRightArm, viewRotation); } if (remoteRightArm.childCount > 0) { AimRemoteArm(remoteRightArm.GetChild(0), viewRotation); } } } private static void AimRemoteArm(Transform arm, Quaternion viewRotation) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)arm == (Object)null)) { arm.rotation = viewRotation; arm.Rotate(Vector3.right, 90f, (Space)1); arm.Rotate(Vector3.up, 180f, (Space)1); } } private void SetWeapon(byte slot, byte variation, bool? alternate = null) { bool flag = alternate ?? lastWeaponAlternate; if (hasWeaponState && lastWeaponSlot == slot && lastWeaponVariation == variation && lastWeaponAlternate == flag) { return; } bool flag2 = hasWeaponState; hasWeaponState = true; lastWeaponSlot = slot; lastWeaponVariation = variation; lastWeaponAlternate = flag; int num = ((slot > 0) ? (slot - 1) : 255); for (int i = 0; i < baseWeapons.Length; i++) { if ((Object)(object)baseWeapons[i] != (Object)null) { baseWeapons[i].SetActive(i == num && !flag); } } for (int j = 0; j < alternateWeapons.Length; j++) { if ((Object)(object)alternateWeapons[j] != (Object)null) { alternateWeapons[j].SetActive(j == num && flag); } } if (!flag2) { return; } foreach (Animator animator in animators) { SetTriggerIfPresent(animator, "ChangeWeapon"); } } private void ApplyAppearance(uint primary, uint secondary, uint light, byte glow) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (primary == lastPrimaryColor && secondary == lastSecondaryColor && light == lastLightColor && glow == lastGlowIntensity) { return; } lastPrimaryColor = primary; lastSecondaryColor = secondary; lastLightColor = light; lastGlowIntensity = glow; Color val = PlayerAppearanceColor.Unpack(primary); Color val2 = PlayerAppearanceColor.Unpack(secondary); Color val3 = PlayerAppearanceColor.Unpack(light); Color val4 = val3 * ((float)(int)glow / 255f); int num = Shader.PropertyToID("_Color"); int num2 = Shader.PropertyToID("_BaseColor"); int num3 = Shader.PropertyToID("_EmissionColor"); for (int i = 0; i < visualRenderers.Length; i++) { Renderer val5 = visualRenderers[i]; if (!((Object)(object)val5 == (Object)null)) { string text = (((Object)(object)val5.sharedMaterial != (Object)null) ? ((Object)val5.sharedMaterial).name : string.Empty); string hint = (((Object)((Component)val5).gameObject).name + " " + text).ToLowerInvariant(); Color val6 = (IsLightDetail(hint) ? val3 : (IsSecondaryDetail(hint) ? val2 : val)); MaterialPropertyBlock val7 = appearanceBlocks[i]; val5.GetPropertyBlock(val7); val7.SetColor(num, val6); val7.SetColor(num2, val6); val7.SetColor(num3, val4); val5.SetPropertyBlock(val7); } } } private static bool IsLightDetail(string hint) { if (!hint.Contains("eye") && !hint.Contains("light") && !hint.Contains("glow") && !hint.Contains("emiss")) { return hint.Contains("led"); } return true; } private static bool IsSecondaryDetail(string hint) { if (!hint.Contains("secondary") && !hint.Contains("accent") && !hint.Contains("trim") && !hint.Contains("panel")) { return hint.Contains("joint"); } return true; } private void SetBoolIfPresent(Animator animator, string name, bool value) { if (HasParameter(animator, name, (AnimatorControllerParameterType)4)) { animator.SetBool(name, value); } } private void SetFloatIfPresent(Animator animator, string name, float value) { if (HasParameter(animator, name, (AnimatorControllerParameterType)1)) { animator.SetFloat(name, value); } } private void SetTriggerIfPresent(Animator animator, string name) { if (HasParameter(animator, name, (AnimatorControllerParameterType)9)) { animator.SetTrigger(name); } } private void CacheAnimatorParameters(Animator animator) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)animator == (Object)null)) { HashSet<int> hashSet = new HashSet<int>(); AnimatorControllerParameter[] parameters = animator.parameters; foreach (AnimatorControllerParameter val in parameters) { hashSet.Add(ParameterKey(val.nameHash, val.type)); } animatorParameterHashes[animator] = hashSet; } } private static string GetAnimatorParameterSummary(Animator animator) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)animator == (Object)null) { return "<no animator>"; } AnimatorControllerParameter[] parameters = animator.parameters; StringBuilder stringBuilder = new StringBuilder(parameters.Length * 16); for (int i = 0; i < parameters.Length; i++) { if (i != 0) { stringBuilder.Append(", "); } stringBuilder.Append(parameters[i].name).Append(':').Append(parameters[i].type); } return stringBuilder.ToString(); } private bool HasParameter(Animator animator, string name, AnimatorControllerParameterType type) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)animator == (Object)null) { return false; } if (!animatorParameterHashes.TryGetValue(animator, out var value) || value.Count == 0) { CacheAnimatorParameters(animator); } if (animatorParameterHashes.TryGetValue(animator, out value)) { return value.Contains(ParameterKey(Animator.StringToHash(name), type)); } return false; } private static int ParameterKey(int nameHash, AnimatorControllerParameterType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected I4, but got Unknown return (nameHash * 397) ^ type; } } internal sealed class SpectatorController { private bool wasDead; private float deathStartedAt; private uint followedPlayerId; private readonly List<PlayerSnapshot> livingPlayers = new List<PlayerSnapshot>(4); private CameraController detachedCameraController; private Transform detachedCamera; private Transform originalCameraParent; private Vector3 originalCameraLocalPosition; private Quaternion originalCameraLocalRotation; private bool originalControllerEnabled; private bool cameraDetached; private Rigidbody frozenBody; private bool bodyWasKinematic; private bool bodyUsedGravity; private Vector3 cameraVelocity; private bool respawnRequested; public bool IsActive { get; private set; } public bool ShowHud { get; private set; } public string Status { get; private set; } = "Spectator"; public bool ConsumeRespawnRequest() { if (!respawnRequested) { return false; } respawnRequested = false; return true; } public void PrepareForRespawn() { RestoreCamera(); wasDead = false; bool isActive = (ShowHud = false); IsActive = isActive; followedPlayerId = 0u; respawnRequested = false; } public void Update(NewMovement localPlayer, NetworkService network) { //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)localPlayer == (Object)null || network == null || !network.IsConnected || !localPlayer.dead) { RestoreCamera(); wasDead = false; IsActive = false; ShowHud = false; followedPlayerId = 0u; respawnRequested = false; return; } if (!wasDead) { wasDead = true; deathStartedAt = Time.unscaledTime; } if (Time.unscaledTime - deathStartedAt < 2.1f) { ShowHud = false; Status = "ELIMINATED / spectator starts after the death sequence"; return; } ShowHud = true; if (Input.GetKeyDown((KeyCode)114)) { respawnRequested = true; } if ((Object)(object)localPlayer.deathSequence != (Object)null && ((Component)localPlayer.deathSequence).gameObject.activeSelf) { ((Component)localPlayer.deathSequence).gameObject.SetActive(false); } livingPlayers.Clear(); foreach (PlayerSnapshot value in network.Players.Values) { if (value.PlayerId != network.LocalPlayerId && (value.MovementFlags & 4) == 0 && network.HasFreshPlayerSnapshot(value.PlayerId, 3f)) { livingPlayers.Add(value); } } livingPlayers.Sort(ComparePlayerIds); if (livingPlayers.Count == 0) { IsActive = false; Status = "WAITING / no fresh living teammate snapshot"; return; } int num = livingPlayers.FindIndex((PlayerSnapshot player) => player.PlayerId == followedPlayerId); if (num < 0) { num = 0; } if (Input.GetKeyDown((KeyCode)93)) { num = (num + 1) % livingPlayers.Count; } else if (Input.GetKeyDown((KeyCode)91)) { num = (num + livingPlayers.Count - 1) % livingPlayers.Count; } PlayerSnapshot playerSnapshot = livingPlayers[num]; if (followedPlayerId != playerSnapshot.PlayerId) { cameraVelocity = Vector3.zero; } followedPlayerId = playerSnapshot.PlayerId; IsActive = true; Status = "SPECTATING / " + playerSnapshot.PlayerName + " / [ and ] switch / R respawn / " + playerSnapshot.Health + " HP"; CameraController cc = localPlayer.cc; if (!((Object)(object)cc == (Object)null) && !((Object)(object)cc.cam == (Object)null)) { DetachCamera(cc); } } private static int ComparePlayerIds(PlayerSnapshot left, PlayerSnapshot right) { return left.PlayerId.CompareTo(right.PlayerId); } public void LateUpdate(NewMovement localPlayer, NetworkService network) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) if (!ShowHud || !IsActive || (Object)(object)localPlayer == (Object)null || network == null || !network.IsConnected || !localPlayer.dead) { return; } PlayerSnapshot playerSnapshot = null; foreach (PlayerSnapshot value in network.Players.Values) { if (value.PlayerId == followedPlayerId && (value.MovementFlags & 4) == 0 && network.HasFreshPlayerSnapshot(value.PlayerId, 3f)) { playerSnapshot = value; break; } } if (playerSnapshot == null || (Object)(object)localPlayer.cc == (Object)null || (Object)(object)localPlayer.cc.cam == (Object)null) { return; } Transform transform = ((Component)localPlayer.cc.cam).transform; if (!cameraDetached) { DetachCamera(localPlayer.cc); } Vector3 position = playerSnapshot.Position; if ((Object)(object)BloodlinkPlugin.Instance != (Object)null) { BloodlinkPlugin.Instance.TryGetSpectatorPose(playerSnapshot.PlayerId, out position); } float num = Mathf.Min(Time.unscaledDeltaTime, 0.05f); Quaternion val = Quaternion.Slerp(transform.rotation, playerSnapshot.ViewRotation, 1f - Mathf.Exp(-10f * num)); Vector3 val2 = position + Vector3.up * 0.65f; Vector3 val3 = -(val * Vector3.forward); float num2 = 3.25f; RaycastHit[] array = Physics.SphereCastAll(val2, 0.18f, val3, num2, -5, (QueryTriggerInteraction)1); for (int i = 0; i < array.Length; i++) { RaycastHit val4 = array[i]; if (!((Object)(object)((RaycastHit)(ref val4)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<NewMovement>() != (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<RemotePlayerVisual>() != (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<EnemyIdentifier>() != (Object)null)) { num2 = Mathf.Min(num2, Mathf.Max(0.25f, ((RaycastHit)(ref val4)).distance - 0.15f)); } } transform.position = Vector3.SmoothDamp(transform.position, val2 + val3 * num2, ref cameraVelocity, 0.13f, 120f, num); transform.rotation = val; } private void DetachCamera(CameraController controller) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (cameraDetached || (Object)(object)controller == (Object)null || (Object)(object)controller.cam == (Object)null) { return; } detachedCameraController = controller; originalControllerEnabled = ((Behaviour)controller).enabled; detachedCamera = ((Component)controller.cam).transform; originalCameraParent = detachedCamera.parent; originalCameraLocalPosition = detachedCamera.localPosition; originalCameraLocalRotation = detachedCamera.localRotation; ((Behaviour)controller).enabled = false; NewMovement val = ((Component)controller).GetComponentInParent<NewMovement>(); if ((Object)(object)val == (Object)null) { val = MonoSingleton<NewMovement>.Instance; } if ((Object)(object)val != (Object)null && (Object)(object)val.rb != (Object)null) { frozenBody = val.rb; bodyWasKinematic = frozenBody.isKinematic; bodyUsedGravity = frozenBody.useGravity; if (!frozenBody.isKinematic) { frozenBody.velocity = Vector3.zero; frozenBody.angularVelocity = Vector3.zero; } frozenBody.isKinematic = true; frozenBody.useGravity = false; } cameraVelocity = Vector3.zero; detachedCamera.SetParent((Transform)null, true); cameraDetached = true; } private void RestoreCamera() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)frozenBody != (Object)null) { frozenBody.isKinematic = bodyWasKinematic; frozenBody.useGravity = bodyUsedGravity; frozenBody = null; } if (cameraDetached) { if ((Object)(object)detachedCamera != (Object)null) { detachedCamera.SetParent(originalCameraParent, false); detachedCamera.localPosition = originalCameraLocalPosition; detachedCamera.localRotation = originalCameraLocalRotation; } if ((Object)(object)detachedCameraController != (Object)null) { ((Behaviour)detachedCameraController).enabled = originalControllerEnabled; } detachedCameraController = null; detachedCamera = null; originalCameraParent = null; cameraDetached = false; cameraVelocity = Vector3.zero; } } } internal sealed class V1AppearancePreview : IDisposable { private const int PreviewLayer = 29; private readonly RemotePlayerVisual visual; private readonly Transform modelRoot; private readonly Camera camera; private readonly RenderTexture texture; private readonly Light keyLight; private float yaw; private float distance = 4.1f; private uint tick; public bool AutoRotate = true; public Texture Texture => (Texture)(object)texture; public bool IsAvailable { get { if ((Object)(object)visual != (Object)null && (Object)(object)modelRoot != (Object)null) { return (Object)(object)camera != (Object)null; } return false; } } public void Rotate(float amount) { yaw = Mathf.Repeat(yaw + amount, 360f); AutoRotate = false; } public void Zoom(float amount) { distance = Mathf.Clamp(distance + amount, 2.5f, 6f); } public void ResetView() { yaw = 0f; distance = 4.1f; AutoRotate = true; } public void PlayAction(PlayerAnimationAction action) { visual?.PlayPlayerAnimation(new PlayerAnimationEvent { Action = action, Speed = 1f }); } private V1AppearancePreview(RemotePlayerVisual visual, Transform modelRoot, Camera camera, RenderTexture texture, Light keyLight) { this.visual = visual; this.modelRoot = modelRoot; this.camera = camera; this.texture = texture; this.keyLight = keyLight; } public static V1AppearancePreview Create(PlayerAnimations template) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)template == (Object)null) { return null; } RemotePlayerVisual remotePlayerVisual = RemotePlayerVisual.Create(template, uint.MaxValue, "APPEARANCE PREVIEW"); ((Object)remotePlayerVisual).name = "Bloodlink V1 Appearance Preview"; ((Component)remotePlayerVisual).transform.position = new Vector3(50000f, 50000f, 50000f); Transform val = ((Component)remotePlayerVisual).transform.Find("Remote V1 Runtime Model"); if ((Object)(object)val == (Object)null) { Object.Destroy((Object)(object)((Component)remotePlayerVisual).gameObject); return null; } TextMesh[] componentsInChildren = ((Component)remotePlayerVisual).GetComponentsInChildren<TextMesh>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.SetActive(false); } SetLayerRecursively(((Component)remotePlayerVisual).transform, 29); GameObject val2 = new GameObject("Bloodlink Appearance Preview Camera") { hideFlags = (HideFlags)61 }; SetLayerRecursively(val2.transform, 29); Camera val3 = val2.AddComponent<Camera>(); ((Behaviour)val3).enabled = false; val3.clearFlags = (CameraClearFlags)2; val3.backgroundColor = new Color(0.075f, 0.025f, 0.03f, 1f); val3.cullingMask = 536870912; val3.fieldOfView = 34f; val3.nearClipPlane = 0.05f; val3.farClipPlane = 40f; val3.allowHDR = false; val3.allowMSAA = true; RenderTexture val4 = new RenderTexture(384, 384, 16, (RenderTextureFormat)0) { name = "Bloodlink V1 Appearance Preview", antiAliasing = 2, hideFlags = (HideFlags)61 }; val4.Create(); val3.targetTexture = val4; GameObject val5 = new GameObject("Bloodlink Appearance Preview Light") { hideFlags = (HideFlags)61 }; SetLayerRecursively(val5.transform, 29); Light val6 = val5.AddComponent<Light>(); val6.type = (LightType)1; val6.color = new Color(1f, 0.78f, 0.72f); val6.intensity = 1.15f; val6.cullingMask = 536870912; val5.transform.rotation = Quaternion.Euler(28f, -32f, 0f); return new V1AppearancePreview(remotePlayerVisual, val, val3, val4, val6); } public void Render(uint primary, uint secondary, uint lights, byte glow, byte weaponSlot, byte weaponVariation) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)visual == (Object)null) && !((Object)(object)modelRoot == (Object)null) && !((Object)(object)camera == (Object)null)) { if (AutoRotate) { yaw = Mathf.Repeat(yaw + Time.unscaledDeltaTime * 18f, 360f); } modelRoot.localRotation = Quaternion.Euler(0f, yaw, 0f); visual.Push(new PlayerSnapshot { PlayerId = uint.MaxValue, PlayerName = string.Empty, Position = ((Component)visual).transform.position, Rotation = ((Component)visual).transform.rotation, ViewRotation = Quaternion.identity, WeaponSlot = (byte)Mathf.Clamp((int)weaponSlot, 1, 5), WeaponVariation = weaponVariation, PrimaryColor = primary, SecondaryColor = secondary, LightColor = lights, GlowIntensity = glow, MovementFlags = 8, Tick = ++tick }); Vector3 val = modelRoot.position + Vector3.up * 1f; ((Component)camera).transform.position = val + new Vector3(0f, 0.16f, distance); ((Component)camera).transform.rotation = Quaternion.LookRotation(val - ((Component)camera).transform.position, Vector3.up); camera.Render(); } } public void Dispose() { if ((Object)(object)camera != (Object)null) { Object.Destroy((Object)(object)((Component)camera).gameObject); } if ((Object)(object)keyLight != (Object)null) { Object.Destroy((Object)(object)((Component)keyLight).gameObject); } if ((Object)(object)texture != (Object)null) { texture.Release(); Object.Destroy((Object)(object)tex
BepInEx/plugins/Unity.Networking.Transport.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using AOT; using Microsoft.CodeAnalysis; using Unity.Baselib.LowLevel; using Unity.Burst; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Mathematics; using Unity.Networking.Transport.Error; using Unity.Networking.Transport.Protocols; using Unity.Networking.Transport.Relay; using Unity.Networking.Transport.Utilities; using Unity.Networking.Transport.Utilities.LowLevel.Unsafe; using Unity.Services.Relay.Models; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("Unity.Networking.Transport.EditorTests")] [assembly: InternalsVisibleTo("Unity.Networking.Transport.RuntimeTests")] [assembly: InternalsVisibleTo("Unity.Networking.Transport.PlayTests.Performance")] [assembly: InternalsVisibleTo("Unity.InternalAPINetworkingBridge.001")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Unity.Networking.Transport")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Unity.Networking.Transport")] [assembly: AssemblyTitle("Unity.Networking.Transport")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } } namespace Unity.Networking.Transport { internal static class Base64 { private unsafe static int FromBase64_Decode_UTF16(byte* startInputPtr, int inputLength, byte* startDestPtr, int destLength) { if (inputLength == 0) { return 0; } if (inputLength % 4 != 0) { Debug.LogError((object)"Base64 string's length must be multiple of 4"); return -1; } if (destLength < inputLength / 4 * 3 - 2) { Debug.LogError((object)"Dest array is too small"); return -1; } byte* ptr = startDestPtr; int num = inputLength / 4; byte* ptr2 = stackalloc byte[256]; UnsafeUtility.MemSet((void*)ptr2, byte.MaxValue, 256L); for (byte b = 0; b < "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".Length; b++) { ptr2[(int)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b]] = b; } ptr2[61] = 0; for (int i = 0; i < num - 1; i++) { byte b2 = ptr2[(int)(*startInputPtr)]; byte b3 = ptr2[(int)startInputPtr[2]]; byte b4 = ptr2[(int)startInputPtr[4]]; byte b5 = ptr2[(int)startInputPtr[6]]; if (b2 == byte.MaxValue || b3 == byte.MaxValue || b4 == byte.MaxValue || b5 == byte.MaxValue) { Debug.LogError((object)"Invalid Base64 symbol"); return -1; } *(startDestPtr++) = (byte)((b2 << 2) | (b3 >> 4)); *(startDestPtr++) = (byte)((b3 << 4) | (b4 >> 2)); *(startDestPtr++) = (byte)((b4 << 6) | b5); startInputPtr += 8; } byte b6 = startInputPtr[4]; byte b7 = startInputPtr[6]; byte b8 = ptr2[(int)(*startInputPtr)]; byte b9 = ptr2[(int)startInputPtr[2]]; byte b10 = ptr2[(int)b6]; byte b11 = ptr2[(int)b7]; if (b8 == byte.MaxValue || b9 == byte.MaxValue || b10 == byte.MaxValue || b11 == byte.MaxValue) { Debug.LogError((object)"Invalid Base64 symbol"); return -1; } *(startDestPtr++) = (byte)((b8 << 2) | (b9 >> 4)); if (b6 != 61) { if (b7 == 61) { if (destLength < inputLength / 4 * 3 - 1) { Debug.LogError((object)"Dest array is too small"); return -1; } *(startDestPtr++) = (byte)((b9 << 4) | (b10 >> 2)); } else { if (destLength < inputLength / 4 * 3) { Debug.LogError((object)"Dest array is too small"); return -1; } *(startDestPtr++) = (byte)((b9 << 4) | (b10 >> 2)); *(startDestPtr++) = (byte)((b10 << 6) | b11); } } return (int)(startDestPtr - ptr); } public unsafe static int FromBase64String(string base64, byte* dest, int destMaxLength) { int result; fixed (char* startInputPtr = base64) { result = FromBase64_Decode_UTF16((byte*)startInputPtr, base64.Length, dest, destMaxLength); } return result; } } internal struct UnsafeBaselibNetworkArray : IDisposable { [NativeDisableUnsafePtrRestriction] private UnsafePtrList<Baselib_RegisteredNetwork_Buffer> m_BufferPool; public unsafe UnsafeBaselibNetworkArray(int capacity, int typeSize) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) long num = typeSize; num = capacity * typeSize; int num2 = capacity; num2 = 1; m_BufferPool = new UnsafePtrList<Baselib_RegisteredNetwork_Buffer>(num2, AllocatorHandle.op_Implicit((Allocator)4), (NativeArrayOptions)0); Baselib_Memory_PageSizeInfo* ptr = (Baselib_Memory_PageSizeInfo*)stackalloc Baselib_Memory_PageSizeInfo[1]; Binding.Baselib_Memory_GetPageSizeInfo(ptr); ulong defaultPageSize = ((Baselib_Memory_PageSizeInfo)ptr).defaultPageSize; for (int i = 0; i < num2; i++) { ulong num3 = 1uL; if ((ulong)num > defaultPageSize) { num3 = (ulong)math.ceil((double)num / (double)defaultPageSize); } Baselib_RegisteredNetwork_Buffer* ptr2 = (Baselib_RegisteredNetwork_Buffer*)UnsafeUtility.Malloc((long)UnsafeUtility.SizeOf<Baselib_RegisteredNetwork_Buffer>(), UnsafeUtility.AlignOf<Baselib_RegisteredNetwork_Buffer>(), (Allocator)4); Baselib_ErrorState val = default(Baselib_ErrorState); Baselib_Memory_PageAllocation val2 = Binding.Baselib_Memory_AllocatePages(((Baselib_Memory_PageSizeInfo)ptr).defaultPageSize, num3, 1uL, (Baselib_Memory_PageState)4, &val); if ((int)val.code != 0) { break; } UnsafeUtility.MemSet((void*)val2.ptr, (byte)0, (long)(val2.pageCount * val2.pageSize)); Unsafe.Write(ptr2, Binding.Baselib_RegisteredNetwork_Buffer_Register(val2, &val)); if ((int)val.code != 0) { Binding.Baselib_Memory_ReleasePages(val2, &val); Unsafe.Write(ptr2, default(Baselib_RegisteredNetwork_Buffer)); } m_BufferPool.Add((void*)ptr2); } } public unsafe void Dispose() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) Baselib_ErrorState val = default(Baselib_ErrorState); for (int i = 0; i < m_BufferPool.Length; i++) { Baselib_RegisteredNetwork_Buffer* intPtr = m_BufferPool[i]; Baselib_Memory_PageAllocation allocation = ((Baselib_RegisteredNetwork_Buffer)intPtr).allocation; Binding.Baselib_RegisteredNetwork_Buffer_Deregister(*intPtr); Binding.Baselib_Memory_ReleasePages(allocation, &val); UnsafeUtility.Free((void*)intPtr, (Allocator)4); } } public unsafe Baselib_RegisteredNetwork_BufferSlice AtIndexAsSlice(int index, uint elementSize) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) uint num = 0u; Baselib_RegisteredNetwork_Buffer* ptr = null; ptr = m_BufferPool[0]; num = elementSize * (uint)index; IntPtr data = (IntPtr)((byte*)(void*)((Baselib_Memory_PageAllocation)(&((Baselib_RegisteredNetwork_Buffer)ptr).allocation)).ptr + num); Baselib_RegisteredNetwork_BufferSlice result = default(Baselib_RegisteredNetwork_BufferSlice); result.id = ((Baselib_RegisteredNetwork_Buffer)ptr).id; result.data = data; result.offset = num; result.size = elementSize; return result; } } public static class BaselibNetworkParameterExtensions { internal const int k_defaultRxQueueSize = 64; internal const int k_defaultTxQueueSize = 64; internal const uint k_defaultMaximumPayloadSize = 2000u; public static ref NetworkSettings WithBaselibNetworkInterfaceParameters(this ref NetworkSettings settings, int receiveQueueCapacity = 64, int sendQueueCapacity = 64, uint maximumPayloadSize = 2000u) { BaselibNetworkParameter parameter = new BaselibNetworkParameter { receiveQueueCapacity = receiveQueueCapacity, sendQueueCapacity = sendQueueCapacity, maximumPayloadSize = maximumPayloadSize }; settings.AddRawParameterStruct(ref parameter); return ref settings; } public static BaselibNetworkParameter GetBaselibNetworkInterfaceParameters(this ref NetworkSettings settings) { if (!settings.TryGet<BaselibNetworkParameter>(out var parameter)) { parameter.receiveQueueCapacity = 64; parameter.sendQueueCapacity = 64; parameter.maximumPayloadSize = 2000u; } return parameter; } } public struct BaselibNetworkParameter : INetworkParameter { public int receiveQueueCapacity; public int sendQueueCapacity; public uint maximumPayloadSize; public bool Validate() { bool result = true; if (receiveQueueCapacity <= 0) { result = false; Debug.LogError((object)string.Format("{0} value ({1}) must be greater than 0", "receiveQueueCapacity", receiveQueueCapacity)); } if (sendQueueCapacity <= 0) { result = false; Debug.LogError((object)string.Format("{0} value ({1}) must be greater than 0", "sendQueueCapacity", sendQueueCapacity)); } if (maximumPayloadSize == 0) { result = false; Debug.LogError((object)string.Format("{0} value ({1}) must be greater than 0", "maximumPayloadSize", maximumPayloadSize)); } return result; } } [BurstCompile] public struct BaselibNetworkInterface : INetworkInterface, IDisposable { internal struct Payloads : IDisposable { public UnsafeAtomicFreeList m_Handles; public UnsafeBaselibNetworkArray m_PayloadArray; public UnsafeBaselibNetworkArray m_EndpointArray; private uint m_PayloadSize; public int InUse => m_Handles.InUse; public int Capacity => m_Handles.Capacity; public bool IsCreated => m_Handles.IsCreated; public Payloads(int capacity, uint maxPayloadSize) { m_PayloadSize = maxPayloadSize; m_Handles = new UnsafeAtomicFreeList(capacity, (Allocator)4); m_PayloadArray = new UnsafeBaselibNetworkArray(capacity, (int)maxPayloadSize); m_EndpointArray = new UnsafeBaselibNetworkArray(capacity, 28); } public void Dispose() { m_Handles.Dispose(); m_PayloadArray.Dispose(); m_EndpointArray.Dispose(); } public Baselib_RegisteredNetwork_Request GetRequestFromHandle(int handle) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) return new Baselib_RegisteredNetwork_Request { payload = m_PayloadArray.AtIndexAsSlice(handle, m_PayloadSize), remoteEndpoint = new Baselib_RegisteredNetwork_Endpoint { slice = m_EndpointArray.AtIndexAsSlice(handle, 28u) } }; } public int AcquireHandle() { return m_Handles.Pop(); } public void ReleaseHandle(int handle) { m_Handles.Push(handle); } } internal enum SocketStatus { SocketNormal, SocketNeedsRecreate, SocketFailed } internal struct BaselibData { public Baselib_RegisteredNetwork_Socket_UDP m_Socket; public SocketStatus m_SocketStatus; public Payloads m_PayloadsTx; public NetworkInterfaceEndPoint m_LocalEndpoint; public long m_LastUpdateTime; public long m_LastSocketRecreateTime; public uint m_NumSocketRecreate; } [BurstCompile] private struct FlushSendJob : IJob { public Payloads Tx; [NativeDisableContainerSafetyRestriction] public NativeArray<BaselibData> Baselib; public unsafe void Execute() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) Baselib_RegisteredNetwork_CompletionResult* ptr = (Baselib_RegisteredNetwork_CompletionResult*)stackalloc Baselib_RegisteredNetwork_CompletionResult[64]; Baselib_ErrorState val = default(Baselib_ErrorState); for (int i = 0; i < Tx.Capacity; i++) { Baselib_RegisteredNetwork_ProcessStatus val2 = Binding.Baselib_RegisteredNetwork_Socket_UDP_ProcessSend(Baselib[0].m_Socket, &val); if ((int)val.code != 0) { Debug.LogError((object)$"Error on baselib processing send ({val.code})"); MarkSocketAsNeedingRecreate(Baselib); return; } if ((int)val2 != 1) { break; } } int num = 0; long num2 = (long)Tx.Capacity / 64L + 1; while ((num = (int)Binding.Baselib_RegisteredNetwork_Socket_UDP_DequeueSend(Baselib[0].m_Socket, ptr, 64u, &val)) > 0) { if ((int)val.code != 0) { MarkSocketAsNeedingRecreate(Baselib); break; } for (int j = 0; j < num; j++) { Tx.ReleaseHandle((int)((Baselib_RegisteredNetwork_CompletionResult)((byte*)ptr + (nint)j * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_CompletionResult>())).requestUserdata - 1); } if (num2-- < 0) { break; } } } } [BurstCompile] private struct ReceiveJob : IJob { public NetworkPacketReceiver Receiver; public Payloads Rx; [NativeDisableContainerSafetyRestriction] public NativeArray<BaselibData> Baselib; public unsafe void Execute() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) Baselib_ErrorState val = default(Baselib_ErrorState); BaselibData baselibData = Baselib[0]; baselibData.m_LastUpdateTime = Receiver.LastUpdateTime; Baselib[0] = baselibData; int num = 0; while ((int)Binding.Baselib_RegisteredNetwork_Socket_UDP_ProcessRecv(Baselib[0].m_Socket, &val) == 1 && num++ < Rx.Capacity) { } Baselib_RegisteredNetwork_CompletionResult* ptr = (Baselib_RegisteredNetwork_CompletionResult*)stackalloc Baselib_RegisteredNetwork_CompletionResult[64]; int num2 = 0; int num3 = 0; int num4 = 0; do { num4 = (int)Binding.Baselib_RegisteredNetwork_Socket_UDP_DequeueRecv(Baselib[0].m_Socket, ptr, 64u, &val); if ((int)val.code != 0) { Receiver.ReceiveErrorCode = -10; return; } num2 += num4; for (int i = 0; i < num4; i++) { if ((int)((Baselib_RegisteredNetwork_CompletionResult)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_CompletionResult>())).status == 0) { num3++; continue; } int bytesTransferred = (int)((Baselib_RegisteredNetwork_CompletionResult)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_CompletionResult>())).bytesTransferred; if (bytesTransferred > 0) { int handle = (int)((Baselib_RegisteredNetwork_CompletionResult)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_CompletionResult>())).requestUserdata - 1; Baselib_RegisteredNetwork_Request requestFromHandle = Rx.GetRequestFromHandle(handle); Baselib_RegisteredNetwork_BufferSlice slice = requestFromHandle.remoteEndpoint.slice; NetworkInterfaceEndPoint address = new NetworkInterfaceEndPoint { dataLength = (int)slice.size }; UnsafeUtility.MemCpy((void*)address.data, (void*)slice.data, (long)(int)slice.size); Receiver.AppendPacket(requestFromHandle.payload.data, ref address, bytesTransferred); Rx.ReleaseHandle(handle); } } } while ((long)num4 == 64); if (num2 > 0 && num3 == num2) { MarkSocketAsNeedingRecreate(Baselib); } int num5 = ScheduleAllReceives(Baselib[0].m_Socket, ref Rx); if (num5 < 0) { Receiver.ReceiveErrorCode = num5; MarkSocketAsNeedingRecreate(Baselib); } } } public static BaselibNetworkParameter DefaultParameters = new BaselibNetworkParameter { receiveQueueCapacity = 64, sendQueueCapacity = 64, maximumPayloadSize = 2000u }; private BaselibNetworkParameter configuration; private const int k_defaultRxQueueSize = 64; private const int k_defaultTxQueueSize = 64; private const int k_defaultMaximumPayloadSize = 2000; private const uint k_MaxNumSocketRecreate = 1000u; private const uint k_RequestsBatchSize = 64u; [ReadOnly] internal NativeArray<BaselibData> m_Baselib; [NativeDisableContainerSafetyRestriction] private Payloads m_PayloadsRx; [NativeDisableContainerSafetyRestriction] private Payloads m_PayloadsTx; private UnsafeBaselibNetworkArray m_LocalAndTempEndpoint; private static TransportFunctionPointer<NetworkSendInterface.BeginSendMessageDelegate> BeginSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.BeginSendMessageDelegate>((NetworkSendInterface.BeginSendMessageDelegate)BeginSendMessage); private static TransportFunctionPointer<NetworkSendInterface.EndSendMessageDelegate> EndSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.EndSendMessageDelegate>((NetworkSendInterface.EndSendMessageDelegate)EndSendMessage); private static TransportFunctionPointer<NetworkSendInterface.AbortSendMessageDelegate> AbortSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.AbortSendMessageDelegate>((NetworkSendInterface.AbortSendMessageDelegate)AbortSendMessage); public NetworkInterfaceEndPoint LocalEndPoint => m_Baselib[0].m_LocalEndpoint; public bool IsCreated => m_Baselib.IsCreated; public int CreateInterfaceEndPoint(NetworkEndPoint address, out NetworkInterfaceEndPoint endpoint) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return CreateInterfaceEndPoint(address.rawNetworkAddress, out endpoint); } private unsafe int CreateInterfaceEndPoint(Baselib_NetworkAddress address, out NetworkInterfaceEndPoint endpoint) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected I4, but got Unknown Baselib_RegisteredNetwork_BufferSlice val = m_LocalAndTempEndpoint.AtIndexAsSlice(0, 28u); Baselib_ErrorState val2 = default(Baselib_ErrorState); endpoint = default(NetworkInterfaceEndPoint); Baselib_RegisteredNetwork_Endpoint val3 = Binding.Baselib_RegisteredNetwork_Endpoint_Create(&address, val, &val2); if ((int)val2.code != 0) { return (int)val2.code; } endpoint.dataLength = (int)val3.slice.size; fixed (byte* data = endpoint.data) { void* ptr = data; UnsafeUtility.MemCpy(ptr, (void*)val3.slice.data, (long)endpoint.dataLength); } return 0; } private unsafe NetworkInterfaceEndPoint GetLocalEndPoint(Baselib_RegisteredNetwork_Socket_UDP socket) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Baselib_ErrorState val = default(Baselib_ErrorState); Baselib_NetworkAddress address = default(Baselib_NetworkAddress); Binding.Baselib_RegisteredNetwork_Socket_UDP_GetNetworkAddress(socket, &address, &val); NetworkInterfaceEndPoint endpoint = default(NetworkInterfaceEndPoint); if ((int)val.code != 0) { return endpoint; } CreateInterfaceEndPoint(address, out endpoint); return endpoint; } public unsafe NetworkEndPoint GetGenericEndPoint(NetworkInterfaceEndPoint endpoint) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) NetworkEndPoint result = default(NetworkEndPoint); Baselib_ErrorState val = default(Baselib_ErrorState); Baselib_RegisteredNetwork_BufferSlice slice = m_LocalAndTempEndpoint.AtIndexAsSlice(0, 28u); Baselib_RegisteredNetwork_Endpoint val2 = default(Baselib_RegisteredNetwork_Endpoint); val2.slice = slice; val2.slice.size = (uint)endpoint.dataLength; UnsafeUtility.MemCpy((void*)val2.slice.data, (void*)endpoint.data, (long)endpoint.dataLength); Binding.Baselib_RegisteredNetwork_Endpoint_GetNetworkAddress(val2, &result.rawNetworkAddress, &val); if ((int)val.code != 0) { return default(NetworkEndPoint); } return result; } public int Initialize(NetworkSettings settings) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) configuration = settings.GetBaselibNetworkInterfaceParameters(); m_Baselib = new NativeArray<BaselibData>(1, (Allocator)4, (NativeArrayOptions)1); BaselibData baselibData = default(BaselibData); m_PayloadsTx = new Payloads(configuration.sendQueueCapacity, configuration.maximumPayloadSize); m_PayloadsRx = new Payloads(configuration.receiveQueueCapacity, configuration.maximumPayloadSize); m_LocalAndTempEndpoint = new UnsafeBaselibNetworkArray(2, 28); baselibData.m_PayloadsTx = m_PayloadsTx; m_Baselib[0] = baselibData; return 0; } public void Dispose() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (m_Baselib[0].m_Socket.handle != IntPtr.Zero) { Binding.Baselib_RegisteredNetwork_Socket_UDP_Close(m_Baselib[0].m_Socket); } m_LocalAndTempEndpoint.Dispose(); if (m_PayloadsTx.IsCreated) { m_PayloadsTx.Dispose(); } if (m_PayloadsRx.IsCreated) { m_PayloadsRx.Dispose(); } m_Baselib.Dispose(); } private static void MarkSocketAsNeedingRecreate(NativeArray<BaselibData> baselib) { BaselibData baselibData = baselib[0]; baselibData.m_SocketStatus = SocketStatus.SocketNeedsRecreate; baselib[0] = baselibData; } private void RecreateSocket(long updateTime) { BaselibData baselibData = m_Baselib[0]; if (baselibData.m_LastSocketRecreateTime == baselibData.m_LastUpdateTime || baselibData.m_NumSocketRecreate >= 1000) { Debug.LogError((object)"Unrecoverable socket failure. An unknown condition is preventing the application from reliably creating sockets."); baselibData.m_SocketStatus = SocketStatus.SocketFailed; m_Baselib[0] = baselibData; return; } Debug.LogWarning((object)"Socket error encountered; attempting recovery by creating a new one."); Bind(baselibData.m_LocalEndpoint); baselibData = m_Baselib[0]; baselibData.m_LastSocketRecreateTime = updateTime; baselibData.m_NumSocketRecreate++; m_Baselib[0] = baselibData; } public JobHandle ScheduleReceive(NetworkPacketReceiver receiver, JobHandle dep) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (m_Baselib[0].m_SocketStatus == SocketStatus.SocketNeedsRecreate) { RecreateSocket(receiver.LastUpdateTime); } if (m_Baselib[0].m_SocketStatus == SocketStatus.SocketFailed) { receiver.ReceiveErrorCode = -10; return dep; } return IJobExtensions.Schedule<ReceiveJob>(new ReceiveJob { Baselib = m_Baselib, Rx = m_PayloadsRx, Receiver = receiver }, dep); } public JobHandle ScheduleSend(NativeQueue<QueuedSendMessage> sendQueue, JobHandle dep) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (m_Baselib[0].m_SocketStatus != SocketStatus.SocketNormal) { return dep; } return IJobExtensions.Schedule<FlushSendJob>(new FlushSendJob { Baselib = m_Baselib, Tx = m_PayloadsTx }, dep); } public unsafe int Bind(NetworkInterfaceEndPoint endpoint) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Invalid comparison between Unknown and I4 //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unsupported input type for neg. //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected I4, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) BaselibData baselibData = m_Baselib[0]; Baselib_RegisteredNetwork_BufferSlice val = m_LocalAndTempEndpoint.AtIndexAsSlice(0, 28u); UnsafeUtility.MemCpy((void*)val.data, (void*)endpoint.data, (long)endpoint.dataLength); Baselib_ErrorState val2 = default(Baselib_ErrorState); Baselib_RegisteredNetwork_Endpoint val3 = default(Baselib_RegisteredNetwork_Endpoint); val3.slice = val; Baselib_NetworkAddress address = default(Baselib_NetworkAddress); Binding.Baselib_RegisteredNetwork_Endpoint_GetNetworkAddress(val3, &address, &val2); bool flag = WouldBindFailWithoutAddressReuse(address); Baselib_RegisteredNetwork_Socket_UDP socket = checked(Binding.Baselib_RegisteredNetwork_Socket_UDP_Create(&address, (Baselib_NetworkAddress_AddressReuse)1, (uint)configuration.sendQueueCapacity, (uint)configuration.receiveQueueCapacity, &val2)); if ((int)val2.code != 0) { if ((int)val2.code == 67108865) { Debug.LogError((object)"Failed to bind the socket because address is already in use. It is likely that another process is already listening on the same port."); } if ((int)val2.code != -1) { return 0 - val2.code; } return -10; } if (m_Baselib[0].m_Socket.handle != IntPtr.Zero) { Binding.Baselib_RegisteredNetwork_Socket_UDP_Close(m_Baselib[0].m_Socket); m_PayloadsRx.Dispose(); m_PayloadsRx = new Payloads(configuration.receiveQueueCapacity, configuration.maximumPayloadSize); } int num = ScheduleAllReceives(socket, ref m_PayloadsRx); if (num < 0) { return num; } if (baselibData.m_SocketStatus != SocketStatus.SocketNeedsRecreate && flag) { ushort port = GetGenericEndPoint(endpoint).Port; Debug.LogWarning((object)($"Port {port} is likely already in use by another application. " + "Socket was still created, but expect erroneous behavior. This condition will become a failure starting in version 2.0 of Unity Transport.")); } baselibData.m_Socket = socket; baselibData.m_SocketStatus = SocketStatus.SocketNormal; baselibData.m_LocalEndpoint = GetLocalEndPoint(socket); m_Baselib[0] = baselibData; return 0; } private unsafe bool WouldBindFailWithoutAddressReuse(Baselib_NetworkAddress address) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) Baselib_ErrorState val = default(Baselib_ErrorState); Baselib_RegisteredNetwork_Socket_UDP val2 = checked(Binding.Baselib_RegisteredNetwork_Socket_UDP_Create(&address, (Baselib_NetworkAddress_AddressReuse)0, (uint)configuration.sendQueueCapacity, (uint)configuration.receiveQueueCapacity, &val)); if ((int)val.code == 0) { Binding.Baselib_RegisteredNetwork_Socket_UDP_Close(val2); } return (int)val.code == 67108865; } public int Listen() { return 0; } public unsafe NetworkSendInterface CreateSendInterface() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) return new NetworkSendInterface { BeginSendMessage = BeginSendMessageFunctionPointer, EndSendMessage = EndSendMessageFunctionPointer, AbortSendMessage = AbortSendMessageFunctionPointer, UserData = (IntPtr)NativeArrayUnsafeUtility.GetUnsafePtr<BaselibData>(m_Baselib) }; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.BeginSendMessageDelegate))] private unsafe static int BeginSendMessage(out NetworkInterfaceSendHandle handle, IntPtr userData, int requiredPayloadSize) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) BaselibData* ptr = (BaselibData*)(void*)userData; handle = default(NetworkInterfaceSendHandle); int num = ptr->m_PayloadsTx.AcquireHandle(); if (num < 0) { return -5; } Baselib_RegisteredNetwork_Request requestFromHandle = ptr->m_PayloadsTx.GetRequestFromHandle(num); if ((int)requestFromHandle.payload.size < requiredPayloadSize) { ptr->m_PayloadsTx.ReleaseHandle(num); return -4; } handle.id = num; handle.size = 0; handle.data = requestFromHandle.payload.data; handle.capacity = (int)requestFromHandle.payload.size; return 0; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.EndSendMessageDelegate))] private unsafe static int EndSendMessage(ref NetworkInterfaceSendHandle handle, ref NetworkInterfaceEndPoint address, IntPtr userData, ref NetworkSendQueueHandle sendQueueHandle) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) BaselibData* ptr = (BaselibData*)(void*)userData; int id = handle.id; Baselib_RegisteredNetwork_Request requestFromHandle = ptr->m_PayloadsTx.GetRequestFromHandle(id); requestFromHandle.requestUserdata = (IntPtr)(id + 1); requestFromHandle.payload.size = (uint)handle.size; NetworkInterfaceEndPoint networkInterfaceEndPoint = address; UnsafeUtility.MemCpy((void*)requestFromHandle.remoteEndpoint.slice.data, (void*)networkInterfaceEndPoint.data, (long)address.dataLength); Baselib_RegisteredNetwork_Request* ptr2 = &requestFromHandle; Baselib_ErrorState val = default(Baselib_ErrorState); int num = (int)Binding.Baselib_RegisteredNetwork_Socket_UDP_ScheduleSend(ptr->m_Socket, ptr2, 1u, &val); if ((int)val.code != 0 || (long)num != 1) { ptr->m_PayloadsTx.ReleaseHandle(id); return -5; } return handle.size; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.AbortSendMessageDelegate))] private unsafe static void AbortSendMessage(ref NetworkInterfaceSendHandle handle, IntPtr userData) { BaselibData* ptr = (BaselibData*)(void*)userData; int id = handle.id; ptr->m_PayloadsTx.ReleaseHandle(id); } private unsafe static int ScheduleAllReceives(Baselib_RegisteredNetwork_Socket_UDP socket, ref Payloads PayloadsRx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Invalid comparison between Unknown and I4 //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unsupported input type for neg. //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected I4, but got Unknown Baselib_ErrorState val = default(Baselib_ErrorState); Baselib_RegisteredNetwork_Request* ptr = (Baselib_RegisteredNetwork_Request*)stackalloc Baselib_RegisteredNetwork_Request[64]; int num = 0; do { for (num = 0; (long)num < 64L; num++) { if (PayloadsRx.InUse >= PayloadsRx.Capacity) { break; } int num2 = PayloadsRx.AcquireHandle(); Unsafe.Write((byte*)ptr + (nint)num * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_Request>(), PayloadsRx.GetRequestFromHandle(num2)); ((Baselib_RegisteredNetwork_Request)((byte*)ptr + (nint)num * (nint)Unsafe.SizeOf<Baselib_RegisteredNetwork_Request>())).requestUserdata = (IntPtr)num2 + 1; } if (num <= 0) { continue; } Binding.Baselib_RegisteredNetwork_Socket_UDP_ScheduleRecv(socket, ptr, (uint)num, &val); if ((int)val.code != 0) { if ((int)val.code != -1) { return 0 - val.code; } return -10; } } while ((long)num == 64); return 0; } private bool ValidateParameters(BaselibNetworkParameter param) { if (param.receiveQueueCapacity <= 0) { return false; } if (param.sendQueueCapacity <= 0) { return false; } return true; } private bool TryExtractParameters(out BaselibNetworkParameter config, params INetworkParameter[] param) { for (int i = 0; i < param.Length; i++) { if (param[i] is BaselibNetworkParameter && ValidateParameters((BaselibNetworkParameter)(object)param[i])) { config = (BaselibNetworkParameter)(object)param[i]; return true; } } config = default(BaselibNetworkParameter); return false; } } [StructLayout(LayoutKind.Explicit)] internal struct UIntFloat { [FieldOffset(0)] public float floatValue; [FieldOffset(0)] public uint intValue; [FieldOffset(0)] public double doubleValue; [FieldOffset(0)] public ulong longValue; } public struct DataStreamWriter { private struct StreamData { public unsafe byte* buffer; public int length; public int capacity; public ulong bitBuffer; public int bitIndex; public int failedWrites; } [NativeDisableUnsafePtrRestriction] private StreamData m_Data; internal IntPtr m_SendHandleData; public unsafe static bool IsLittleEndian { get { uint num = 1u; byte* ptr = (byte*)(&num); return *ptr == 1; } } public unsafe bool IsCreated => m_Data.buffer != null; public bool HasFailedWrites => m_Data.failedWrites > 0; public int Capacity => m_Data.capacity; public int Length { get { SyncBitData(); return m_Data.length + (m_Data.bitIndex + 7 >> 3); } } public int LengthInBits { get { SyncBitData(); return m_Data.length * 8 + m_Data.bitIndex; } } public DataStreamWriter(int length, Allocator allocator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) Initialize(out this, new NativeArray<byte>(length, allocator, (NativeArrayOptions)1)); } public DataStreamWriter(NativeArray<byte> data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Initialize(out this, data); } public unsafe DataStreamWriter(byte* data, int length) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) NativeArray<byte> data2 = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>((void*)data, length, (Allocator)0); Initialize(out this, data2); } public unsafe NativeArray<byte> AsNativeArray() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>((void*)m_Data.buffer, Length, (Allocator)0); } private unsafe static void Initialize(out DataStreamWriter self, NativeArray<byte> data) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) self.m_SendHandleData = IntPtr.Zero; self.m_Data.capacity = data.Length; self.m_Data.length = 0; self.m_Data.buffer = (byte*)NativeArrayUnsafeUtility.GetUnsafePtr<byte>(data); self.m_Data.bitBuffer = 0uL; self.m_Data.bitIndex = 0; self.m_Data.failedWrites = 0; } private static short ByteSwap(short val) { return (short)(((val & 0xFF) << 8) | ((val >> 8) & 0xFF)); } private static int ByteSwap(int val) { return ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val >> 8) & 0xFF00) | ((val >> 24) & 0xFF); } private unsafe void SyncBitData() { int num = m_Data.bitIndex; if (num > 0) { ulong num2 = m_Data.bitBuffer; int num3 = 0; while (num > 0) { m_Data.buffer[m_Data.length + num3] = (byte)num2; num -= 8; num2 >>= 8; num3++; } } } public unsafe void Flush() { while (m_Data.bitIndex > 0) { m_Data.buffer[m_Data.length++] = (byte)m_Data.bitBuffer; m_Data.bitIndex -= 8; m_Data.bitBuffer >>= 8; } m_Data.bitIndex = 0; } public unsafe bool WriteBytes(byte* data, int bytes) { if (m_Data.length + (m_Data.bitIndex + 7 >> 3) + bytes > m_Data.capacity) { m_Data.failedWrites++; return false; } Flush(); UnsafeUtility.MemCpy((void*)(m_Data.buffer + m_Data.length), (void*)data, (long)bytes); m_Data.length += bytes; return true; } public unsafe bool WriteByte(byte value) { return WriteBytes(&value, 1); } public unsafe bool WriteBytes(NativeArray<byte> value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return WriteBytes((byte*)NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr<byte>(value), value.Length); } public unsafe bool WriteShort(short value) { return WriteBytes((byte*)(&value), 2); } public unsafe bool WriteUShort(ushort value) { return WriteBytes((byte*)(&value), 2); } public unsafe bool WriteInt(int value) { return WriteBytes((byte*)(&value), 4); } public unsafe bool WriteUInt(uint value) { return WriteBytes((byte*)(&value), 4); } public unsafe bool WriteLong(long value) { return WriteBytes((byte*)(&value), 8); } public unsafe bool WriteULong(ulong value) { return WriteBytes((byte*)(&value), 8); } public unsafe bool WriteShortNetworkByteOrder(short value) { short num = (IsLittleEndian ? ByteSwap(value) : value); return WriteBytes((byte*)(&num), 2); } public bool WriteUShortNetworkByteOrder(ushort value) { return WriteShortNetworkByteOrder((short)value); } public unsafe bool WriteIntNetworkByteOrder(int value) { int num = (IsLittleEndian ? ByteSwap(value) : value); return WriteBytes((byte*)(&num), 4); } public bool WriteUIntNetworkByteOrder(uint value) { return WriteIntNetworkByteOrder((int)value); } public bool WriteFloat(float value) { UIntFloat uIntFloat = new UIntFloat { floatValue = value }; return WriteInt((int)uIntFloat.intValue); } private unsafe void FlushBits() { while (m_Data.bitIndex >= 8) { m_Data.buffer[m_Data.length++] = (byte)m_Data.bitBuffer; m_Data.bitIndex -= 8; m_Data.bitBuffer >>= 8; } } private void WriteRawBitsInternal(uint value, int numbits) { m_Data.bitBuffer |= (ulong)value << m_Data.bitIndex; m_Data.bitIndex += numbits; } public bool WriteRawBits(uint value, int numbits) { if (m_Data.length + (m_Data.bitIndex + numbits + 7 >> 3) > m_Data.capacity) { m_Data.failedWrites++; return false; } WriteRawBitsInternal(value, numbits); FlushBits(); return true; } public unsafe bool WritePackedUInt(uint value, NetworkCompressionModel model) { int num = model.CalculateBucket(value); uint num2 = model.bucketOffsets[num]; int num3 = model.bucketSizes[num]; ushort num4 = model.encodeTable[num]; if (m_Data.length + (m_Data.bitIndex + (num4 & 0xFF) + num3 + 7 >> 3) > m_Data.capacity) { m_Data.failedWrites++; return false; } WriteRawBitsInternal((uint)(num4 >> 8), num4 & 0xFF); WriteRawBitsInternal(value - num2, num3); FlushBits(); return true; } public bool WritePackedULong(ulong value, NetworkCompressionModel model) { return WritePackedUInt((uint)(value >> 32), model) & WritePackedUInt((uint)(value & 0xFFFFFFFFu), model); } public bool WritePackedInt(int value, NetworkCompressionModel model) { uint value2 = (uint)((value >> 31) ^ (value << 1)); return WritePackedUInt(value2, model); } public bool WritePackedLong(long value, NetworkCompressionModel model) { ulong value2 = (ulong)((value >> 63) ^ (value << 1)); return WritePackedULong(value2, model); } public bool WritePackedFloat(float value, NetworkCompressionModel model) { return WritePackedFloatDelta(value, 0f, model); } public bool WritePackedUIntDelta(uint value, uint baseline, NetworkCompressionModel model) { int value2 = (int)(baseline - value); return WritePackedInt(value2, model); } public bool WritePackedIntDelta(int value, int baseline, NetworkCompressionModel model) { int value2 = baseline - value; return WritePackedInt(value2, model); } public bool WritePackedLongDelta(long value, long baseline, NetworkCompressionModel model) { long value2 = baseline - value; return WritePackedLong(value2, model); } public bool WritePackedULongDelta(ulong value, ulong baseline, NetworkCompressionModel model) { long value2 = (long)(baseline - value); return WritePackedLong(value2, model); } public bool WritePackedFloatDelta(float value, float baseline, NetworkCompressionModel model) { int num = 0; if (value != baseline) { num = 32; } if (m_Data.length + (m_Data.bitIndex + 1 + num + 7 >> 3) > m_Data.capacity) { m_Data.failedWrites++; return false; } if (num == 0) { WriteRawBitsInternal(0u, 1); } else { WriteRawBitsInternal(1u, 1); UIntFloat uIntFloat = new UIntFloat { floatValue = value }; WriteRawBitsInternal(uIntFloat.intValue, num); } FlushBits(); return true; } public unsafe bool WriteFixedString32(FixedString32Bytes str) { int bytes = (int)str + 2; byte* data = (byte*)(&str); return WriteBytes(data, bytes); } public unsafe bool WriteFixedString64(FixedString64Bytes str) { int bytes = (int)str + 2; byte* data = (byte*)(&str); return WriteBytes(data, bytes); } public unsafe bool WriteFixedString128(FixedString128Bytes str) { int bytes = (int)str + 2; byte* data = (byte*)(&str); return WriteBytes(data, bytes); } public unsafe bool WriteFixedString512(FixedString512Bytes str) { int bytes = (int)str + 2; byte* data = (byte*)(&str); return WriteBytes(data, bytes); } public unsafe bool WriteFixedString4096(FixedString4096Bytes str) { int bytes = (int)str + 2; byte* data = (byte*)(&str); return WriteBytes(data, bytes); } public unsafe bool WritePackedFixedString32Delta(FixedString32Bytes str, FixedString32Bytes baseline, NetworkCompressionModel model) { ushort length = (ushort)str; byte* data = (byte*)(&str) + 2; return WritePackedFixedStringDelta(data, length, (byte*)(&baseline) + 2, (uint)baseline, model); } public unsafe bool WritePackedFixedString64Delta(FixedString64Bytes str, FixedString64Bytes baseline, NetworkCompressionModel model) { ushort length = (ushort)str; byte* data = (byte*)(&str) + 2; return WritePackedFixedStringDelta(data, length, (byte*)(&baseline) + 2, (uint)baseline, model); } public unsafe bool WritePackedFixedString128Delta(FixedString128Bytes str, FixedString128Bytes baseline, NetworkCompressionModel model) { ushort length = (ushort)str; byte* data = (byte*)(&str) + 2; return WritePackedFixedStringDelta(data, length, (byte*)(&baseline) + 2, (uint)baseline, model); } public unsafe bool WritePackedFixedString512Delta(FixedString512Bytes str, FixedString512Bytes baseline, NetworkCompressionModel model) { ushort length = (ushort)str; byte* data = (byte*)(&str) + 2; return WritePackedFixedStringDelta(data, length, (byte*)(&baseline) + 2, (uint)baseline, model); } public unsafe bool WritePackedFixedString4096Delta(FixedString4096Bytes str, FixedString4096Bytes baseline, NetworkCompressionModel model) { ushort length = (ushort)str; byte* data = (byte*)(&str) + 2; return WritePackedFixedStringDelta(data, length, (byte*)(&baseline) + 2, (uint)baseline, model); } private unsafe bool WritePackedFixedStringDelta(byte* data, uint length, byte* baseData, uint baseLength, NetworkCompressionModel model) { StreamData data2 = m_Data; if (!WritePackedUIntDelta(length, baseLength, model)) { return false; } bool flag = false; if (length <= baseLength) { for (uint num = 0u; num < length; num++) { flag |= !WritePackedUIntDelta(data[num], baseData[num], model); } } else { for (uint num2 = 0u; num2 < baseLength; num2++) { flag |= !WritePackedUIntDelta(data[num2], baseData[num2], model); } for (uint num3 = baseLength; num3 < length; num3++) { flag |= !WritePackedUInt(data[num3], model); } } if (flag) { m_Data = data2; m_Data.failedWrites++; } return !flag; } public void Clear() { m_Data.length = 0; m_Data.bitIndex = 0; m_Data.bitBuffer = 0uL; m_Data.failedWrites = 0; } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private void CheckRead() { } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private void CheckWrite() { } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private static void CheckAllocator(Allocator allocator) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)allocator != 2) { throw new InvalidOperationException("DataStreamWriters can only be created with temp memory"); } } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private static void CheckBits(uint value, int numbits) { if (numbits < 0 || numbits > 32) { throw new ArgumentOutOfRangeException("Invalid number of bits"); } if ((ulong)value >= (ulong)(1L << numbits)) { throw new ArgumentOutOfRangeException("Value does not fit in the specified number of bits"); } } } public struct DataStreamReader { private struct Context { public int m_ReadByteIndex; public int m_BitIndex; public ulong m_BitBuffer; public int m_FailedReads; } [NativeDisableUnsafePtrRestriction] private unsafe byte* m_bufferPtr; private Context m_Context; private int m_Length; public bool IsLittleEndian => DataStreamWriter.IsLittleEndian; public bool HasFailedReads => m_Context.m_FailedReads > 0; public int Length => m_Length; public unsafe bool IsCreated => m_bufferPtr != null; public DataStreamReader(NativeArray<byte> array) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Initialize(out this, array); } public unsafe DataStreamReader(byte* data, int length) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) NativeArray<byte> array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>((void*)data, length, (Allocator)0); Initialize(out this, array); } private unsafe static void Initialize(out DataStreamReader self, NativeArray<byte> array) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) self.m_bufferPtr = (byte*)NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr<byte>(array); self.m_Length = array.Length; self.m_Context = default(Context); } private static short ByteSwap(short val) { return (short)(((val & 0xFF) << 8) | ((val >> 8) & 0xFF)); } private static int ByteSwap(int val) { return ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val >> 8) & 0xFF00) | ((val >> 24) & 0xFF); } public unsafe void ReadBytes(byte* data, int length) { if (GetBytesRead() + length > m_Length) { m_Context.m_FailedReads++; UnsafeUtility.MemClear((void*)data, (long)length); return; } m_Context.m_ReadByteIndex -= m_Context.m_BitIndex >> 3; m_Context.m_BitIndex = 0; m_Context.m_BitBuffer = 0uL; UnsafeUtility.MemCpy((void*)data, (void*)(m_bufferPtr + m_Context.m_ReadByteIndex), (long)length); m_Context.m_ReadByteIndex += length; } public unsafe void ReadBytes(NativeArray<byte> array) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ReadBytes((byte*)NativeArrayUnsafeUtility.GetUnsafePtr<byte>(array), array.Length); } public int GetBytesRead() { return m_Context.m_ReadByteIndex - (m_Context.m_BitIndex >> 3); } public int GetBitsRead() { return (m_Context.m_ReadByteIndex << 3) - m_Context.m_BitIndex; } public void SeekSet(int pos) { if (pos > m_Length) { m_Context.m_FailedReads++; return; } m_Context.m_ReadByteIndex = pos; m_Context.m_BitIndex = 0; m_Context.m_BitBuffer = 0uL; } public unsafe byte ReadByte() { byte result = default(byte); ReadBytes(&result, 1); return result; } public unsafe short ReadShort() { short result = default(short); ReadBytes((byte*)(&result), 2); return result; } public unsafe ushort ReadUShort() { ushort result = default(ushort); ReadBytes((byte*)(&result), 2); return result; } public unsafe int ReadInt() { int result = default(int); ReadBytes((byte*)(&result), 4); return result; } public unsafe uint ReadUInt() { uint result = default(uint); ReadBytes((byte*)(&result), 4); return result; } public unsafe long ReadLong() { long result = default(long); ReadBytes((byte*)(&result), 8); return result; } public unsafe ulong ReadULong() { ulong result = default(ulong); ReadBytes((byte*)(&result), 8); return result; } public unsafe short ReadShortNetworkByteOrder() { short num = default(short); ReadBytes((byte*)(&num), 2); if (!IsLittleEndian) { return num; } return ByteSwap(num); } public ushort ReadUShortNetworkByteOrder() { return (ushort)ReadShortNetworkByteOrder(); } public unsafe int ReadIntNetworkByteOrder() { int num = default(int); ReadBytes((byte*)(&num), 4); if (!IsLittleEndian) { return num; } return ByteSwap(num); } public uint ReadUIntNetworkByteOrder() { return (uint)ReadIntNetworkByteOrder(); } public float ReadFloat() { UIntFloat uIntFloat = new UIntFloat { intValue = (uint)ReadInt() }; return uIntFloat.floatValue; } public unsafe uint ReadPackedUInt(NetworkCompressionModel model) { FillBitBuffer(); uint num = 63u; uint num2 = (uint)(int)m_Context.m_BitBuffer & num; ushort num3 = model.decodeTable[(int)num2]; int num4 = num3 >> 8; int num5 = num3 & 0xFF; if (m_Context.m_BitIndex < num5) { m_Context.m_FailedReads++; return 0u; } m_Context.m_BitBuffer >>= num5; m_Context.m_BitIndex -= num5; uint num6 = model.bucketOffsets[num4]; int numbits = model.bucketSizes[num4]; return ReadRawBitsInternal(numbits) + num6; } private unsafe void FillBitBuffer() { while (m_Context.m_BitIndex <= 56 && m_Context.m_ReadByteIndex < m_Length) { m_Context.m_BitBuffer |= (ulong)m_bufferPtr[m_Context.m_ReadByteIndex++] << m_Context.m_BitIndex; m_Context.m_BitIndex += 8; } } private uint ReadRawBitsInternal(int numbits) { if (m_Context.m_BitIndex < numbits) { m_Context.m_FailedReads++; return 0u; } int result = (int)((long)m_Context.m_BitBuffer & ((1L << numbits) - 1)); m_Context.m_BitBuffer >>= numbits; m_Context.m_BitIndex -= numbits; return (uint)result; } public uint ReadRawBits(int numbits) { FillBitBuffer(); return ReadRawBitsInternal(numbits); } public ulong ReadPackedULong(NetworkCompressionModel model) { return ((ulong)ReadPackedUInt(model) << 32) | ReadPackedUInt(model); } public int ReadPackedInt(NetworkCompressionModel model) { uint num = ReadPackedUInt(model); return (int)((num >> 1) ^ (0 - (num & 1))); } public long ReadPackedLong(NetworkCompressionModel model) { ulong num = ReadPackedULong(model); return (long)((num >> 1) ^ (0L - (num & 1))); } public float ReadPackedFloat(NetworkCompressionModel model) { return ReadPackedFloatDelta(0f, model); } public int ReadPackedIntDelta(int baseline, NetworkCompressionModel model) { int num = ReadPackedInt(model); return baseline - num; } public uint ReadPackedUIntDelta(uint baseline, NetworkCompressionModel model) { uint num = (uint)ReadPackedInt(model); return baseline - num; } public long ReadPackedLongDelta(long baseline, NetworkCompressionModel model) { long num = ReadPackedLong(model); return baseline - num; } public ulong ReadPackedULongDelta(ulong baseline, NetworkCompressionModel model) { ulong num = (ulong)ReadPackedLong(model); return baseline - num; } public float ReadPackedFloatDelta(float baseline, NetworkCompressionModel model) { FillBitBuffer(); if (ReadRawBitsInternal(1) == 0) { return baseline; } int numbits = 32; return new UIntFloat { intValue = ReadRawBitsInternal(numbits) }.floatValue; } public unsafe FixedString32Bytes ReadFixedString32() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FixedString32Bytes result = default(FixedString32Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString32Bytes)ReadFixedString(data, ((FixedString32Bytes)(ref result)).Capacity); return result; } public unsafe FixedString64Bytes ReadFixedString64() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FixedString64Bytes result = default(FixedString64Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString64Bytes)ReadFixedString(data, ((FixedString64Bytes)(ref result)).Capacity); return result; } public unsafe FixedString128Bytes ReadFixedString128() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FixedString128Bytes result = default(FixedString128Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString128Bytes)ReadFixedString(data, ((FixedString128Bytes)(ref result)).Capacity); return result; } public unsafe FixedString512Bytes ReadFixedString512() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FixedString512Bytes result = default(FixedString512Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString512Bytes)ReadFixedString(data, ((FixedString512Bytes)(ref result)).Capacity); return result; } public unsafe FixedString4096Bytes ReadFixedString4096() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FixedString4096Bytes result = default(FixedString4096Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString4096Bytes)ReadFixedString(data, ((FixedString4096Bytes)(ref result)).Capacity); return result; } public unsafe ushort ReadFixedString(byte* data, int maxLength) { ushort num = ReadUShort(); if (num > maxLength) { return 0; } ReadBytes(data, num); return num; } public unsafe FixedString32Bytes ReadPackedFixedString32Delta(FixedString32Bytes baseline, NetworkCompressionModel model) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) FixedString32Bytes result = default(FixedString32Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString32Bytes)ReadPackedFixedStringDelta(data, ((FixedString32Bytes)(ref result)).Capacity, (byte*)(&baseline) + 2, (ushort)baseline, model); return result; } public unsafe FixedString64Bytes ReadPackedFixedString64Delta(FixedString64Bytes baseline, NetworkCompressionModel model) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) FixedString64Bytes result = default(FixedString64Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString64Bytes)ReadPackedFixedStringDelta(data, ((FixedString64Bytes)(ref result)).Capacity, (byte*)(&baseline) + 2, (ushort)baseline, model); return result; } public unsafe FixedString128Bytes ReadPackedFixedString128Delta(FixedString128Bytes baseline, NetworkCompressionModel model) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) FixedString128Bytes result = default(FixedString128Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString128Bytes)ReadPackedFixedStringDelta(data, ((FixedString128Bytes)(ref result)).Capacity, (byte*)(&baseline) + 2, (ushort)baseline, model); return result; } public unsafe FixedString512Bytes ReadPackedFixedString512Delta(FixedString512Bytes baseline, NetworkCompressionModel model) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) FixedString512Bytes result = default(FixedString512Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString512Bytes)ReadPackedFixedStringDelta(data, ((FixedString512Bytes)(ref result)).Capacity, (byte*)(&baseline) + 2, (ushort)baseline, model); return result; } public unsafe FixedString4096Bytes ReadPackedFixedString4096Delta(FixedString4096Bytes baseline, NetworkCompressionModel model) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) FixedString4096Bytes result = default(FixedString4096Bytes); byte* data = (byte*)(&result) + 2; result = (FixedString4096Bytes)ReadPackedFixedStringDelta(data, ((FixedString4096Bytes)(ref result)).Capacity, (byte*)(&baseline) + 2, (ushort)baseline, model); return result; } public unsafe ushort ReadPackedFixedStringDelta(byte* data, int maxLength, byte* baseData, ushort baseLength, NetworkCompressionModel model) { uint num = ReadPackedUIntDelta(baseLength, model); if (num > (uint)maxLength) { return 0; } if (num <= baseLength) { for (int i = 0; i < num; i++) { data[i] = (byte)ReadPackedUIntDelta(baseData[i], model); } } else { for (int j = 0; j < baseLength; j++) { data[j] = (byte)ReadPackedUIntDelta(baseData[j], model); } for (int k = baseLength; k < num; k++) { data[k] = (byte)ReadPackedUInt(model); } } return (ushort)num; } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private void CheckRead() { } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private static void CheckBits(int numbits) { if (numbits < 0 || numbits > 32) { throw new ArgumentOutOfRangeException("Invalid number of bits"); } } } internal static class HMACSHA256 { public unsafe static void ComputeHash(byte* keyValue, int keyArrayLength, byte* messageBytes, int messageLength, byte* result) { byte* ptr = stackalloc byte[32]; SHA256.SHA256State sHA256State = SHA256.SHA256State.Create(); if (keyArrayLength > 64) { sHA256State.Update(keyValue, keyArrayLength); sHA256State.Final(ptr); keyValue = ptr; keyArrayLength = 32; } byte* ptr2 = stackalloc byte[64]; for (int i = 0; i < keyArrayLength; i++) { ptr2[i] = (byte)(0x36 ^ keyValue[i]); } for (int j = keyArrayLength; j < 64; j++) { ptr2[j] = 54; } sHA256State = SHA256.SHA256State.Create(); sHA256State.Update(ptr2, 64); sHA256State.Update(messageBytes, messageLength); sHA256State.Final(result); for (int k = 0; k < keyArrayLength; k++) { ptr2[k] = (byte)(0x5C ^ keyValue[k]); } for (int l = keyArrayLength; l < 64; l++) { ptr2[l] = 92; } sHA256State = SHA256.SHA256State.Create(); sHA256State.Update(ptr2, 64); sHA256State.Update(result, 32); sHA256State.Final(result); } } public struct NetworkPacketReceiver { [Flags] public enum AppendPacketMode { None = 0, NoCopyNeeded = 1 } internal NetworkDriver m_Driver; public long LastUpdateTime => m_Driver.LastUpdateTime; public int ReceiveErrorCode { set { m_Driver.ReceiveErrorCode = value; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IntPtr AllocateMemory(ref int dataLen) { return m_Driver.AllocateMemory(ref dataLen); } public unsafe bool AppendPacket(IntPtr data, ref NetworkInterfaceEndPoint address, int dataLen, AppendPacketMode mode = AppendPacketMode.None) { if ((mode & AppendPacketMode.NoCopyNeeded) != AppendPacketMode.None) { m_Driver.AppendPacket(data, ref address, dataLen); return true; } int dataLen2 = dataLen; IntPtr intPtr = m_Driver.AllocateMemory(ref dataLen2); if (intPtr == IntPtr.Zero || dataLen2 < dataLen) { OutOfMemoryError(); return false; } UnsafeUtility.MemCpy(intPtr.ToPointer(), data.ToPointer(), (long)dataLen); m_Driver.AppendPacket(intPtr, ref address, dataLen); return true; } public bool IsAddressUsed(NetworkInterfaceEndPoint address) { return m_Driver.IsAddressUsed(address); } private void OutOfMemoryError() { ReceiveErrorCode = 10040; } } [Flags] public enum SendHandleFlags { AllocatedByDriver = 1 } public struct NetworkInterfaceSendHandle { public IntPtr data; public int capacity; public int size; public int id; public SendHandleFlags flags; } public struct NetworkSendQueueHandle { private IntPtr handle; internal unsafe static NetworkSendQueueHandle ToTempHandle(ParallelWriter<QueuedSendMessage> sendQueue) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) void* ptr = UnsafeUtility.Malloc((long)UnsafeUtility.SizeOf<ParallelWriter<QueuedSendMessage>>(), UnsafeUtility.AlignOf<ParallelWriter<QueuedSendMessage>>(), (Allocator)2); UnsafeUtility.WriteArrayElement<ParallelWriter<QueuedSendMessage>>(ptr, 0, sendQueue); return new NetworkSendQueueHandle { handle = (IntPtr)ptr }; } public unsafe ParallelWriter<QueuedSendMessage> FromHandle() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return UnsafeUtility.ReadArrayElement<ParallelWriter<QueuedSendMessage>>((void*)handle, 0); } } public struct NetworkSendInterface { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int BeginSendMessageDelegate(out NetworkInterfaceSendHandle handle, IntPtr userData, int requiredPayloadSize); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int EndSendMessageDelegate(ref NetworkInterfaceSendHandle handle, ref NetworkInterfaceEndPoint address, IntPtr userData, ref NetworkSendQueueHandle sendQueue); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void AbortSendMessageDelegate(ref NetworkInterfaceSendHandle handle, IntPtr userData); public TransportFunctionPointer<BeginSendMessageDelegate> BeginSendMessage; public TransportFunctionPointer<EndSendMessageDelegate> EndSendMessage; public TransportFunctionPointer<AbortSendMessageDelegate> AbortSendMessage; [NativeDisableUnsafePtrRestriction] public IntPtr UserData; } public interface INetworkInterface : IDisposable { NetworkInterfaceEndPoint LocalEndPoint { get; } int Initialize(NetworkSettings settings); JobHandle ScheduleReceive(NetworkPacketReceiver receiver, JobHandle dep); JobHandle ScheduleSend(NativeQueue<QueuedSendMessage> sendQueue, JobHandle dep); int Bind(NetworkInterfaceEndPoint endpoint); int Listen(); NetworkSendInterface CreateSendInterface(); int CreateInterfaceEndPoint(NetworkEndPoint address, out NetworkInterfaceEndPoint endpoint); NetworkEndPoint GetGenericEndPoint(NetworkInterfaceEndPoint endpoint); } internal struct IPCManager { [StructLayout(LayoutKind.Explicit)] internal struct IPCData { [FieldOffset(0)] public int from; [FieldOffset(4)] public int length; [FieldOffset(8)] public unsafe fixed byte data[1400]; } public static IPCManager Instance; private NativeMultiQueue<IPCData> m_IPCQueue; private NativeHashMap<ushort, int> m_IPCChannels; internal static JobHandle ManagerAccessHandle; private int m_RefCount; public bool IsCreated => m_IPCQueue.IsCreated; public void AddRef() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (m_RefCount == 0) { m_IPCQueue = new NativeMultiQueue<IPCData>(128); m_IPCChannels = new NativeHashMap<ushort, int>(64, AllocatorHandle.op_Implicit((Allocator)4)); } m_RefCount++; } public void Release() { m_RefCount--; if (m_RefCount == 0) { ((JobHandle)(ref ManagerAccessHandle)).Complete(); m_IPCQueue.Dispose(); m_IPCChannels.Dispose(); } } internal unsafe void Update(NetworkInterfaceEndPoint local, NativeQueue<QueuedSendMessage> queue) { QueuedSendMessage queuedSendMessage = default(QueuedSendMessage); while (queue.TryDequeue(ref queuedSendMessage)) { IPCData value = default(IPCData); UnsafeUtility.MemCpy((void*)value.data, (void*)queuedSendMessage.Data, (long)queuedSendMessage.DataLength); value.length = queuedSendMessage.DataLength; value.from = *(int*)local.data; m_IPCQueue.Enqueue(*(int*)queuedSendMessage.Dest.data, value); } } public unsafe NetworkInterfaceEndPoint CreateEndPoint(ushort port) { ((JobHandle)(ref ManagerAccessHandle)).Complete(); int num = 0; if (port == 0) { int num2 = default(int); while (num == 0) { port = RandomHelpers.GetRandomUShort(); if (!m_IPCChannels.TryGetValue(port, ref num2)) { num = m_IPCChannels.Count + 1; m_IPCChannels.TryAdd(port, num); } } } else if (!m_IPCChannels.TryGetValue(port, ref num)) { num = m_IPCChannels.Count + 1; m_IPCChannels.TryAdd(port, num); } NetworkInterfaceEndPoint result = new NetworkInterfaceEndPoint { dataLength = 4 }; *(int*)result.data = num; return result; } public unsafe bool GetEndPointPort(NetworkInterfaceEndPoint ep, out ushort port) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) ((JobHandle)(ref ManagerAccessHandle)).Complete(); int num = *(int*)ep.data; NativeArray<int> valueArray = m_IPCChannels.GetValueArray(AllocatorHandle.op_Implicit((Allocator)2)); NativeArray<ushort> keyArray = m_IPCChannels.GetKeyArray(AllocatorHandle.op_Implicit((Allocator)2)); port = 0; for (int i = 0; i < m_IPCChannels.Count; i++) { if (valueArray[i] == num) { port = keyArray[i]; return true; } } return false; } public unsafe int PeekNext(NetworkInterfaceEndPoint local, void* slice, out int length, out NetworkInterfaceEndPoint from) { ((JobHandle)(ref ManagerAccessHandle)).Complete(); from = default(NetworkInterfaceEndPoint); length = 0; if (m_IPCQueue.Peek(*(int*)local.data, out var value)) { UnsafeUtility.MemCpy(slice, (void*)value.data, (long)value.length); length = value.length; } GetEndPointByHandle(value.from, out from); return length; } public unsafe int ReceiveMessageEx(NetworkInterfaceEndPoint local, void* payloadData, int payloadLen, ref NetworkInterfaceEndPoint remote) { if (!m_IPCQueue.Peek(*(int*)local.data, out var value)) { return 0; } GetEndPointByHandle(value.from, out remote); int num = Math.Min(payloadLen, value.length); UnsafeUtility.MemCpy(payloadData, (void*)value.data, (long)num); if (num < value.length) { return -10040; } m_IPCQueue.Dequeue(*(int*)local.data, out value); return num; } private unsafe void GetEndPointByHandle(int handle, out NetworkInterfaceEndPoint endpoint) { NetworkInterfaceEndPoint networkInterfaceEndPoint = new NetworkInterfaceEndPoint { dataLength = 4 }; *(int*)networkInterfaceEndPoint.data = handle; endpoint = networkInterfaceEndPoint; } } [BurstCompile] public struct IPCNetworkInterface : INetworkInterface, IDisposable { [BurstCompile] private struct SendUpdate : IJob { public IPCManager ipcManager; public NativeQueue<QueuedSendMessage> ipcQueue; [ReadOnly] public NativeArray<NetworkInterfaceEndPoint> localEndPoint; public void Execute() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) ipcManager.Update(localEndPoint[0], ipcQueue); } } [BurstCompile] private struct ReceiveJob : IJob { public NetworkPacketReceiver receiver; public IPCManager ipcManager; public NetworkInterfaceEndPoint localEndPoint; public unsafe void Execute() { receiver.ReceiveErrorCode = 0; IntPtr intPtr; NetworkInterfaceEndPoint address; int num; do { int dataLen = 1400; intPtr = receiver.AllocateMemory(ref dataLen); if (intPtr == IntPtr.Zero) { break; } address = default(NetworkInterfaceEndPoint); num = NativeReceive(intPtr.ToPointer(), dataLen, ref address); if (num <= 0) { if (num != 0) { receiver.ReceiveErrorCode = -num; } break; } } while (receiver.AppendPacket(intPtr, ref address, num, NetworkPacketReceiver.AppendPacketMode.NoCopyNeeded)); } private unsafe int NativeReceive(void* data, int length, ref NetworkInterfaceEndPoint address) { return ipcManager.ReceiveMessageEx(localEndPoint, data, length, ref address); } } [ReadOnly] private NativeArray<NetworkInterfaceEndPoint> m_LocalEndPoint; private static TransportFunctionPointer<NetworkSendInterface.BeginSendMessageDelegate> BeginSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.BeginSendMessageDelegate>((NetworkSendInterface.BeginSendMessageDelegate)BeginSendMessage); private static TransportFunctionPointer<NetworkSendInterface.EndSendMessageDelegate> EndSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.EndSendMessageDelegate>((NetworkSendInterface.EndSendMessageDelegate)EndSendMessage); private static TransportFunctionPointer<NetworkSendInterface.AbortSendMessageDelegate> AbortSendMessageFunctionPointer = new TransportFunctionPointer<NetworkSendInterface.AbortSendMessageDelegate>((NetworkSendInterface.AbortSendMessageDelegate)AbortSendMessage); public NetworkInterfaceEndPoint LocalEndPoint => m_LocalEndPoint[0]; public int CreateInterfaceEndPoint(NetworkEndPoint address, out NetworkInterfaceEndPoint endpoint) { if (!address.IsLoopback && !address.IsAny) { endpoint = default(NetworkInterfaceEndPoint); return -9; } endpoint = IPCManager.Instance.CreateEndPoint(address.Port); return 0; } public NetworkEndPoint GetGenericEndPoint(NetworkInterfaceEndPoint endpoint) { if (!IPCManager.Instance.GetEndPointPort(endpoint, out var port)) { return default(NetworkEndPoint); } return NetworkEndPoint.LoopbackIpv4.WithPort(port); } public int Initialize(NetworkSettings settings) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) IPCManager.Instance.AddRef(); m_LocalEndPoint = new NativeArray<NetworkInterfaceEndPoint>(1, (Allocator)4, (NativeArrayOptions)1); NetworkInterfaceEndPoint endpoint = default(NetworkInterfaceEndPoint); int num = 0; if ((num = CreateInterfaceEndPoint(NetworkEndPoint.LoopbackIpv4, out endpoint)) != 0) { return num; } m_LocalEndPoint[0] = endpoint; return 0; } public void Dispose() { m_LocalEndPoint.Dispose(); IPCManager.Instance.Release(); } public JobHandle ScheduleReceive(NetworkPacketReceiver receiver, JobHandle dep) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) dep = IJobExtensions.Schedule<ReceiveJob>(new ReceiveJob { receiver = receiver, ipcManager = IPCManager.Instance, localEndPoint = LocalEndPoint }, JobHandle.CombineDependencies(dep, IPCManager.ManagerAccessHandle)); IPCManager.ManagerAccessHandle = dep; return dep; } public JobHandle ScheduleSend(NativeQueue<QueuedSendMessage> sendQueue, JobHandle dep) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) dep = IJobExtensions.Schedule<SendUpdate>(new SendUpdate { ipcManager = IPCManager.Instance, ipcQueue = sendQueue, localEndPoint = m_LocalEndPoint }, JobHandle.CombineDependencies(dep, IPCManager.ManagerAccessHandle)); IPCManager.ManagerAccessHandle = dep; return dep; } public int Bind(NetworkInterfaceEndPoint endpoint) { m_LocalEndPoint[0] = endpoint; return 0; } public int Listen() { return 0; } public NetworkSendInterface CreateSendInterface() { return new NetworkSendInterface { BeginSendMessage = BeginSendMessageFunctionPointer, EndSendMessage = EndSendMessageFunctionPointer, AbortSendMessage = AbortSendMessageFunctionPointer }; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.BeginSendMessageDelegate))] private unsafe static int BeginSendMessage(out NetworkInterfaceSendHandle handle, IntPtr userData, int requiredPayloadSize) { handle.id = 0; handle.size = 0; handle.capacity = requiredPayloadSize; handle.data = (IntPtr)UnsafeUtility.Malloc((long)handle.capacity, 8, (Allocator)2); handle.flags = (SendHandleFlags)0; return 0; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.EndSendMessageDelegate))] private unsafe static int EndSendMessage(ref NetworkInterfaceSendHandle handle, ref NetworkInterfaceEndPoint address, IntPtr userData, ref NetworkSendQueueHandle sendQueueHandle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ParallelWriter<QueuedSendMessage> val = sendQueueHandle.FromHandle(); QueuedSendMessage queuedSendMessage = new QueuedSendMessage { Dest = address, DataLength = handle.size }; UnsafeUtility.MemCpy((void*)queuedSendMessage.Data, (void*)handle.data, (long)handle.size); val.Enqueue(queuedSendMessage); return handle.size; } [BurstCompile(DisableDirectCall = true)] [MonoPInvokeCallback(typeof(NetworkSendInterface.AbortSendMessageDelegate))] private static void AbortSendMessage(ref NetworkInterfaceSendHandle handle, IntPtr userData) { } } public struct NetworkCompressionModel : IDisposable { internal static readonly byte[] k_BucketSizes = new byte[16] { 0, 0, 1, 2, 3, 4, 6, 8, 10, 12, 15, 18, 21, 24, 27, 32 }; internal static readonly uint[] k_BucketOffsets = new uint[16] { 0u, 1u, 2u, 4u, 8u, 16u, 32u, 96u, 352u, 1376u, 5472u, 38240u, 300384u, 2397536u, 19174752u, 153392480u }; internal static readonly int[] k_FirstBucketCandidate = new int[33] { 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 6, 5, 4, 3, 2, 1, 1, 0 }; internal static readonly byte[] k_DefaultModelData = new byte[19] { 16, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 0, 0 }; internal const int k_AlphabetSize = 16; internal const int k_MaxHuffmanSymbolLength = 6; internal const int k_MaxContexts = 1; internal unsafe fixed ushort encodeTable[16]; internal unsafe fixed ushort decodeTable[64]; internal unsafe fixed byte bucketSizes[16]; internal unsafe fixed uint bucketOffsets[16]; public void Dispose() { } public unsafe NetworkCompressionModel(Allocator allocator) { for (int i = 0; i < 16; i++) { bucketSizes[i] = k_BucketSizes[i]; bucketOffsets[i] = k_BucketOffsets[i]; } byte[] array = k_DefaultModelData; int num = 1; byte[,] array2 = new byte[num, 16]; int num2 = 0; _ = array[num2++]; for (int j = 0; j < 16; j++) { byte b = array[num2++]; for (int k = 0; k < num; k++) { array2[k, j] = b; } } int num3 = array[num2] | (array[num2 + 1] << 8); num2 += 2; for (int l = 0; l < num3; l++) { int num4 = array[num2] | (array[num2 + 1] << 8); num2 += 2; _ = array[num2++]; for (int m = 0; m < 16; m++) { byte b2 = array[num2++]; array2[num4, m] = b2; } } byte[] array3 = new byte[16]; ushort[] array4 = new ushort[64]; byte[] array5 = new byte[16]; for (int n = 0; n < num; n++) { for (int num5 = 0; num5 < 16; num5++) { array3[num5] = array2[n, num5]; } GenerateHuffmanCodes(array5, 0, array3, 0, 16, 6); GenerateHuffmanDecodeTable(array4, 0, array3, array5, 16, 6); for (int num6 = 0; num6 < 16; num6++) { encodeTable[n * 16 + num6] = (ushort)((array5[num6] << 8) | array2[n, num6]); } for (int num7 = 0; num7 < 64; num7++) { decodeTable[n * 64 + num7] = array4[num7]; } } } private static void GenerateHuffmanCodes(byte[] symboLCodes, int symbolCodesOffset, byte[] symbolLengths, int symbolLengthsOffset, int alphabetSize, int maxCodeLength) { byte[] array = new byte[maxCodeLength + 1]; byte[,] array2 = new byte[maxCodeLength + 1, alphabetSize]; for (int i = 0; i < alphabetSize; i++) { int num = symbolLengths[i + symbolLengthsOffset]; array2[num, array[num]++] = (byte)i; } uint num2 = 0u; for (int j = 1; j <= maxCodeLength; j++) { int num3 = array[j]; for (int k = 0; k < num3; k++) { int num4 = array2[j, k]; symboLCodes[num4 + symbolCodesOffset] = (byte)ReverseBits(num2++, j); } num2 <<= 1; } } private static uint ReverseBits(uint value, int num_bits) { value = ((value & 0x55555555) << 1) | ((value & 0xAAAAAAAAu) >> 1); value = ((value & 0x33333333) << 2) | ((value & 0xCCCCCCCCu) >> 2); value = ((value & 0xF0F0F0F) << 4) | ((value & 0xF0F0F0F0u) >> 4); value = ((value & 0xFF00FF) << 8) | ((value & 0xFF00FF00u) >> 8); value = (value << 16) | (value >> 16); return value >> 32 - num_bits; } private static void GenerateHuffmanDecodeTable(ushort[] decodeTable, int decodeTableOffset, byte[] symbolLengths, byte[] symbolCodes, int alphabetSize, int maxCodeLength) { uint num = (uint)(1 << maxCodeLength); for (int i = 0; i < alphabetSize; i++) { int num2 = symbolLengths[i]; if (num2 > 0) { uint num3 = symbolCodes[i]; uint num4 = (uint)(1 << num2); do { decodeTable[decodeTableOffset + num3] = (ushort)((i << 8) | num2); num3 += num4; } while (num3 < num); } } } public unsafe int CalculateBucket(uint value) { int num = k_FirstBucketCandidate[math.lzcnt(value)]; if (num + 1 < 16 && value >= bucketOffsets[num + 1]) { num++; } return num; } } public struct NetworkConnection : IEquatable<NetworkConnection> { public enum State { Disconnected, Connecting, Connected } internal int m_NetworkId; internal int m_NetworkVersion; public bool IsCreated => m_NetworkVersion != 0; public int InternalId => m_NetworkId; public int Disconnect(NetworkDriver driver) { return driver.Disconnect(this); } public NetworkEvent.Type PopEvent(NetworkDriver driver, out DataStreamReader stream) { return driver.PopEventForConnection(this, out stream); } public NetworkEvent.Type PopEvent(NetworkDriver driver, out DataStreamReader stream, out NetworkPipeline pipeline) { return driver.PopEventForConnection(this, out stream, out pipeline); } public int Close(NetworkDriver driver) { if (m_NetworkId >= 0) { return driver.Disconnect(this); } return -1; } public State GetState(NetworkDriver driver) { return driver.GetConnectionState(this); } public static bool operator ==(NetworkConnection lhs, NetworkConnection rhs) { if (lhs.m_NetworkId == rhs.m_NetworkId) { return lhs.m_NetworkVersion == rhs.m_NetworkVersion; } return false; } public static bool operator !=(NetworkConnection lhs, NetworkConnection rhs) { if (lhs.m_NetworkId == rhs.m_NetworkId) { return lhs.m_NetworkVersion != rhs.m_NetworkVersion; } return true; } public override bool Equals(object o) { return this == (NetworkConnection)o; } public bool Equals(NetworkConnection o) { return this == o; } public override int GetHashCode() { return (m_NetworkId << 8) ^ m_NetworkVersion; } } public struct QueuedSendMessage { public unsafe fixed byte Data[1400]; public NetworkInterfaceEndPoint Dest; public int DataLength; } public struct NetworkDriver : IDisposable { public struct Concurrent { private struct PendingSend { public NetworkPipeline Pipeline; public NetworkConnection Connection; public NetworkInterfaceSendHandle SendHandle; public int headerSize; } internal NetworkSendInterface m_NetworkSendInterface; internal NetworkProtocol m_NetworkProtocolInterface; internal NetworkEventQueue.Concurrent m_EventQueue; internal NativeArray<byte> m_DisconnectReasons; [ReadOnly] internal NativeList<Connection> m_ConnectionList; [ReadOnly] internal NativeList<byte> m_DataStream; internal NetworkPipelineProcessor.Concurrent m_PipelineProcessor; internal UdpCHeader.HeaderFlags m_DefaultHeaderFlags; internal ParallelWriter<QueuedSendMessage> m_ConcurrentParallelSendQueue; public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader) { NetworkPipeline pipeline; return PopEventForConnection(connectionId, out reader, out pipeline); } public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader, out NetworkPipeline pipeline) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) pipeline = default(NetworkPipeline); reader = default(DataStreamReader); if (connectionId.m_NetworkId < 0 || connectionId.m_NetworkId >= m_ConnectionList.Length || m_ConnectionList[connectionId.m_NetworkId].Version != connectionId.m_NetworkVersion) { return NetworkEvent.Type.Empty; } int offset; int size; int pipelineId; NetworkEvent.Type num = m_EventQueue.PopEventForConnection(connectionId.m_NetworkId, out offset, out size, out pipelineId); pipeline = new NetworkPipeline { Id = pipelineId }; if (num == NetworkEvent.Type.Disconnect && offset < 0) { reader = new DataStreamReader(m_DisconnectReasons.GetSubArray(math.abs(offset), 1)); return num; } if (size > 0) { reader = new DataStreamReader(NativeList<byte>.op_Implicit(m_DataStream).GetSubArray(offset, size)); } return num; } public int MaxHeaderSize(NetworkPipeline pipe) { int num = m_NetworkProtocolInterface.PaddingSize; if (pipe.Id > 0) { num += m_PipelineProcessor.SendHeaderCapacity(pipe) + 1; } return num; } internal int MaxProtocolHeaderSize() { return m_NetworkProtocolInterface.PaddingSize; } public int BeginSend(NetworkConnection id, out DataStreamWriter writer, int requiredPayloadSize = 0) { return BeginSend(NetworkPipeline.Null, id, out writer, requiredPayloadSize); } public unsafe int BeginSend(NetworkPipeline pipe, NetworkConnection id, out DataStreamWriter writer, int requiredPayloadSize = 0) { //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) writer = default(DataStreamWriter); if (id.m_NetworkId < 0 || id.m_NetworkId >= m_ConnectionList.Length) { return -1; } Connection connection = m_ConnectionList[id.m_NetworkId]; if (connection.Version != id.m_NetworkVersion) { return -2; } if (connection.State != NetworkConnection.State.Connected) { return -3; } int num = ((pipe.Id > 0) ? (m_PipelineProcessor.SendHeaderCapacity(pipe) + 1) : 0); int num2 = m_PipelineProcessor.PayloadCapacity(pipe); int payloadOffset; int num3 = m_NetworkProtocolInterface.ComputePacketOverhead.Ptr.Invoke(ref connection, out payloadOffset); int num4 = ((num2 == 0) ? (1400 - num3 - num) : num2); int num5 = ((num2 == 0) ? 1400 : (num2 + num3 + num)); if (num4 < requiredPayloadSize) { return -4; } if (requiredPayloadSize > 0 && num4 > requiredPayloadSize) { int num6 = num4 - requiredPayloadSize; num4 -= num6; num5 -= num6; } NetworkInterfaceSendHandle handle = default(NetworkInterfaceSendHandle); if (num5 > 1400) { handle.data = (IntPtr)UnsafeUtility.Malloc((long)num5, 8, (Allocator)2); handle.capacity = num5; handle.id = 0; handle.size = 0; handle.flags = SendHandleFlags.AllocatedByDriver; } else { int num7 = m_NetworkSendInterface.BeginSendMessage.Ptr.Invoke(out handle, m_NetworkSendInterface.UserData, num5); if (num7 != 0) { return num7; } } if (handle.capacity < num5) { return -4; } NativeArray<byte> data = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>((void*)((byte*)(void*)handle.data + payloadOffset + num), num4, (Allocator)0); writer = new DataStreamWriter(data); writer.m_SendHandleData = (IntPtr)UnsafeUtility.Malloc((long)UnsafeUtility.SizeOf<PendingSend>(), UnsafeUtility.AlignOf<PendingSend>(), (Allocator)2); *(PendingSend*)(void*)writer.m_SendHandleData = new PendingSend { Pipeline = pipe, Connection = id, SendHandle = handle, headerSize = payloadOffset }; return 0; } public unsafe int EndSend(DataStreamWriter writer) { PendingSend* ptr = (PendingSend*)(void*)writer.m_SendHandleData; if (ptr == null || ptr->Connection == default(NetworkConnection)) { return -8; } if (m_ConnectionList[ptr->Connection.m_NetworkId].Version != ptr->Connection.m_NetworkVersion) { return -2; } if (writer.HasFailedWrites) { AbortSend(writer); return -4; } PendingSend pendingSend = *(PendingSend*)(void*)writer.m_SendHandleData; ptr->Connection = default(NetworkConnection); pendingSend.SendHandle.size = pendingSend.headerSize + writer.Length; int num = 0; if (pendingSend.Pipeline.Id > 0) { pendingSend.SendHandle.size += m_PipelineProcessor.SendHeaderCapacity(pendingSend.Pipeline) + 1; UdpCHeader.HeaderFlags defaultHeaderFlags = m_DefaultHeaderFlags; m_DefaultHeaderFlags = UdpCHeader.HeaderFlags.HasPipeline; num = m_PipelineProcessor.Send(this, pendingSend.Pipeline, pendingSend.Connection, pendingSend.SendHandle, pendingSend.headerSize); m_DefaultHeaderFlags = defaultHeaderFlags; } else { num = CompleteSend(pendingSend.Connection, pendingSend.SendHandle, (m_DefaultHeaderFlags & UdpCHeader.HeaderFlags.HasPipeline) != 0); } if (num <= 0) { return num; } return writer.Length; } public unsafe void AbortSend(DataStreamWriter writer) { PendingSend* ptr = (PendingSend*)(void*)writer.m_SendHandleData; if (ptr == null || ptr->Connection == default(NetworkConnection)) { Debug.LogError((object)"AbortSend without matching BeginSend"); return; } PendingSend pendingSend = *(PendingSend*)(void*)writer.m_SendHandleData; ptr->Connection = default(NetworkConnection); AbortSend(pendingSend.SendHandle); } internal unsafe int CompleteSend(NetworkConnection sendConnect
BepInEx/plugins/Unity.Services.Authentication.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using Unity.Services.Authentication.Generated; using Unity.Services.Authentication.Internal; using Unity.Services.Authentication.Shared; using Unity.Services.Core; using Unity.Services.Core.Configuration.Internal; using Unity.Services.Core.Environments.Internal; using Unity.Services.Core.Internal; using Unity.Services.Core.Scheduler.Internal; using Unity.Services.Core.Telemetry.Internal; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Scripting; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AlwaysLinkAssembly] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Editor")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Internal1")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Internal2")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Internal3")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Internal4")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Unity")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.Tests")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.EditorTests")] [assembly: InternalsVisibleTo("Unity.Services.Authentication.TestUtils")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Unity.Services.Authentication")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Unity.Services.Authentication")] [assembly: AssemblyTitle("Unity.Services.Authentication")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Unity.Services.Authentication { public static class AuthenticationService { private static IAuthenticationService s_Instance; public static IAuthenticationService Instance { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (s_Instance == null) { throw new ServicesInitializationException("Singleton is not initialized. Please call UnityServices.InitializeAsync() to initialize."); } return s_Instance; } internal set { s_Instance = value; } } } internal class AuthenticationServiceInternal : IAuthenticationService { private const string k_ProfileRegex = "^[a-zA-Z0-9_-]{1,30}$"; private const string k_IdProviderNameRegex = "^oidc-[a-z0-9-_\\.]{1,15}$"; private const string k_SteamIdentityRegex = "^[a-zA-Z0-9]{5,30}$"; private readonly IProfile m_Profile; private readonly IJwtDecoder m_JwtDecoder; private readonly IAuthenticationCache m_Cache; private readonly IActionScheduler m_Scheduler; private readonly IAuthenticationMetrics m_Metrics; public bool IsSignedIn { get { if (State != AuthenticationState.Authorized && State != AuthenticationState.Refreshing) { return State == AuthenticationState.Expired; } return true; } } public bool IsAuthorized { get { if (State != AuthenticationState.Authorized) { return State == AuthenticationState.Refreshing; } return true; } } public bool IsExpired => State == AuthenticationState.Expired; public bool SessionTokenExists => !string.IsNullOrEmpty(SessionTokenComponent.SessionToken); public string Profile => m_Profile.Current; public string AccessToken => AccessTokenComponent.AccessToken; public string PlayerId => PlayerIdComponent.PlayerId; public string PlayerName => PlayerNameComponent.PlayerName; public PlayerInfo PlayerInfo { get; internal set; } internal long? ExpirationActionId { get; set; } internal long? RefreshActionId { get; set; } internal AccessTokenComponent AccessTokenComponent { get; } internal EnvironmentIdComponent EnvironmentIdComponent { get; } internal PlayerIdComponent PlayerIdComponent { get; } internal PlayerNameComponent PlayerNameComponent { get; } internal SessionTokenComponent SessionTokenComponent { get; } internal AuthenticationState State { get; set; } internal IAuthenticationSettings Settings { get; } internal IAuthenticationNetworkClient NetworkClient { get; set; } internal IPlayerNamesApi PlayerNamesApi { get; set; } internal IAuthenticationExceptionHandler ExceptionHandler { get; set; } public event Action<RequestFailedException> SignInFailed; public event Action SignedIn; public event Action SignedOut; public event Action Expired; public event Action<RequestFailedException> UpdatePasswordFailed; internal event Action<AuthenticationState, AuthenticationState> StateChanged; internal AuthenticationServiceInternal(IAuthenticationSettings settings, IAuthenticationNetworkClient networkClient, IPlayerNamesApi playerNamesApi, IProfile profile, IJwtDecoder jwtDecoder, IAuthenticationCache cache, IActionScheduler scheduler, IAuthenticationMetrics metrics, AccessTokenComponent accessToken, EnvironmentIdComponent environmentId, PlayerIdComponent playerId, PlayerNameComponent playerName, SessionTokenComponent sessionToken) { Settings = settings; NetworkClient = networkClient; PlayerNamesApi = playerNamesApi; m_Profile = profile; m_JwtDecoder = jwtDecoder; m_Cache = cache; m_Scheduler = scheduler; m_Metrics = metrics; ExceptionHandler = new AuthenticationExceptionHandler(m_Metrics); AccessTokenComponent = accessToken; EnvironmentIdComponent = environmentId; PlayerIdComponent = playerId; PlayerNameComponent = playerName; SessionTokenComponent = sessionToken; State = AuthenticationState.SignedOut; MigrateCache(); PlayerIdComponent.PlayerIdChanged += OnPlayerIdChanged; Expired += delegate { m_Metrics.SendExpiredSessionMetric(); }; } private void OnPlayerIdChanged(string playerId) { PlayerNameComponent.Clear(); } public Task SignInAnonymouslyAsync(SignInOptions options = null) { if (State == AuthenticationState.SignedOut || State == AuthenticationState.Expired) { if (SessionTokenExists) { string sessionToken = SessionTokenComponent.SessionToken; if (string.IsNullOrEmpty(sessionToken)) { SessionTokenComponent.Clear(); RequestFailedException exception = ExceptionHandler.BuildClientSessionTokenNotExistsException(); SendSignInFailedEvent(exception, forceSignOut: true); return Task.FromException((Exception)(object)exception); } return HandleSignInRequestAsync(() => NetworkClient.SignInWithSessionTokenAsync(sessionToken)); } if (options == null || options.CreateAccount) { return HandleSignInRequestAsync(NetworkClient.SignInAnonymouslyAsync); } SessionTokenComponent.Clear(); RequestFailedException exception2 = ExceptionHandler.BuildClientSessionTokenNotExistsException(); SendSignInFailedEvent(exception2, forceSignOut: true); return Task.FromException((Exception)(object)exception2); } RequestFailedException exception3 = ExceptionHandler.BuildClientInvalidStateException(State); SendSignInFailedEvent(exception3, forceSignOut: false); return Task.FromException((Exception)(object)exception3); } public Task SignInWithAppleAsync(string idToken, SignInOptions options = null) { return SignInWithExternalTokenAsync("apple.com", new SignInWithExternalTokenRequest { IdProvider = "apple.com", Token = idToken, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithAppleAsync(string idToken, LinkOptions options = null) { return LinkWithExternalTokenAsync("apple.com", new LinkWithExternalTokenRequest { IdProvider = "apple.com", Token = idToken, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkAppleAsync() { return UnlinkExternalTokenAsync("apple.com"); } public Task SignInWithAppleGameCenterAsync(string signature, string teamPlayerId, string publicKeyURL, string salt, ulong timestamp, SignInOptions options = null) { return SignInWithExternalTokenAsync("apple-game-center", new SignInWithAppleGameCenterRequest { IdProvider = "apple-game-center", Token = signature, AppleGameCenterConfig = new AppleGameCenterConfig { TeamPlayerId = teamPlayerId, PublicKeyURL = publicKeyURL, Salt = salt, Timestamp = timestamp }, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithAppleGameCenterAsync(string signature, string teamPlayerId, string publicKeyURL, string salt, ulong timestamp, LinkOptions options = null) { return LinkWithExternalTokenAsync("apple-game-center", new LinkWithAppleGameCenterRequest { IdProvider = "apple-game-center", Token = signature, AppleGameCenterConfig = new AppleGameCenterConfig { TeamPlayerId = teamPlayerId, PublicKeyURL = publicKeyURL, Salt = salt, Timestamp = timestamp }, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkAppleGameCenterAsync() { return UnlinkExternalTokenAsync("apple-game-center"); } public Task SignInWithGoogleAsync(string idToken, SignInOptions options = null) { return SignInWithExternalTokenAsync("google.com", new SignInWithExternalTokenRequest { IdProvider = "google.com", Token = idToken, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithGoogleAsync(string idToken, LinkOptions options = null) { return LinkWithExternalTokenAsync("google.com", new LinkWithExternalTokenRequest { IdProvider = "google.com", Token = idToken, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkGoogleAsync() { return UnlinkExternalTokenAsync("google.com"); } public Task SignInWithGooglePlayGamesAsync(string authCode, SignInOptions options = null) { return SignInWithExternalTokenAsync("google-play-games", new SignInWithExternalTokenRequest { IdProvider = "google-play-games", Token = authCode, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithGooglePlayGamesAsync(string authCode, LinkOptions options = null) { return LinkWithExternalTokenAsync("google-play-games", new LinkWithExternalTokenRequest { IdProvider = "google-play-games", Token = authCode, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkGooglePlayGamesAsync() { return UnlinkExternalTokenAsync("google-play-games"); } public Task SignInWithFacebookAsync(string accessToken, SignInOptions options = null) { return SignInWithExternalTokenAsync("facebook.com", new SignInWithExternalTokenRequest { IdProvider = "facebook.com", Token = accessToken, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithFacebookAsync(string accessToken, LinkOptions options = null) { return LinkWithExternalTokenAsync("facebook.com", new LinkWithExternalTokenRequest { IdProvider = "facebook.com", Token = accessToken, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkFacebookAsync() { return UnlinkExternalTokenAsync("facebook.com"); } [Obsolete("This method is deprecated as of version 2.7.1. Please use the SignInWithSteamAsync method with the 'identity' parameter for better security.")] public Task SignInWithSteamAsync(string sessionTicket, SignInOptions options = null) { return SignInWithExternalTokenAsync("steampowered.com", new SignInWithSteamRequest { IdProvider = "steampowered.com", Token = sessionTicket, SignInOnly = (options != null && !options.CreateAccount) }); } [Obsolete("This method is deprecated as of version 2.7.1. Please use the LinkWithSteamAsync method with the 'identity' parameter for better security.")] public Task LinkWithSteamAsync(string sessionTicket, LinkOptions options = null) { return LinkWithExternalTokenAsync("steampowered.com", new LinkWithSteamRequest { IdProvider = "steampowered.com", Token = sessionTicket, ForceLink = (options?.ForceLink ?? false) }); } public Task SignInWithSteamAsync(string sessionTicket, string identity, SignInOptions options = null) { ValidateSteamIdentity(identity); return SignInWithExternalTokenAsync("steampowered.com", new SignInWithSteamRequest { IdProvider = "steampowered.com", Token = sessionTicket, SteamConfig = new SteamConfig { identity = identity }, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithSteamAsync(string sessionTicket, string identity, LinkOptions options = null) { ValidateSteamIdentity(identity); return LinkWithExternalTokenAsync("steampowered.com", new LinkWithSteamRequest { IdProvider = "steampowered.com", Token = sessionTicket, SteamConfig = new SteamConfig { identity = identity }, ForceLink = (options?.ForceLink ?? false) }); } private void ValidateSteamIdentity(string identity) { if (string.IsNullOrEmpty(identity)) { throw ExceptionHandler.BuildUnknownException("Identity cannot be null or empty."); } if (!Regex.IsMatch(identity, "^[a-zA-Z0-9]{5,30}$")) { throw ExceptionHandler.BuildUnknownException("The provided identity must only contain alphanumeric characters and be between 5 and 30 characters in length."); } } public Task UnlinkSteamAsync() { return UnlinkExternalTokenAsync("steampowered.com"); } public Task SignInWithOculusAsync(string nonce, string userId, SignInOptions options = null) { return SignInWithExternalTokenAsync("oculus", new SignInWithOculusRequest { IdProvider = "oculus", Token = nonce, OculusConfig = new OculusConfig { UserId = userId }, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithOculusAsync(string nonce, string userId, LinkOptions options = null) { return LinkWithExternalTokenAsync("oculus", new LinkWithOculusRequest { IdProvider = "oculus", Token = nonce, OculusConfig = new OculusConfig { UserId = userId }, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkOculusAsync() { return UnlinkExternalTokenAsync("oculus"); } public Task SignInWithOpenIdConnectAsync(string idProviderName, string idToken, SignInOptions options = null) { if (!ValidateOpenIdConnectIdProviderName(idProviderName)) { throw ExceptionHandler.BuildInvalidIdProviderNameException(); } return SignInWithExternalTokenAsync(idProviderName, new SignInWithExternalTokenRequest { IdProvider = idProviderName, Token = idToken, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithOpenIdConnectAsync(string idProviderName, string idToken, LinkOptions options = null) { if (!ValidateOpenIdConnectIdProviderName(idProviderName)) { throw ExceptionHandler.BuildInvalidIdProviderNameException(); } return LinkWithExternalTokenAsync(idProviderName, new LinkWithExternalTokenRequest { IdProvider = idProviderName, Token = idToken, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkOpenIdConnectAsync(string idProviderName) { if (!ValidateOpenIdConnectIdProviderName(idProviderName)) { throw ExceptionHandler.BuildInvalidIdProviderNameException(); } return UnlinkExternalTokenAsync(idProviderName); } public Task SignInWithUsernamePasswordAsync(string username, string password) { return SignInWithUsernamePasswordRequestAsync(BuildUsernamePasswordRequest(username, password)); } public Task SignUpWithUsernamePasswordAsync(string username, string password) { return SignUpWithUsernamePasswordRequestAsync(BuildUsernamePasswordRequest(username, password)); } public Task AddUsernamePasswordAsync(string username, string password) { return AddUsernamePasswordRequestAsync(BuildUsernamePasswordRequest(username, password)); } public Task UpdatePasswordAsync(string currentPassword, string newPassword) { if (string.IsNullOrEmpty(currentPassword) || string.IsNullOrEmpty(newPassword)) { throw ExceptionHandler.BuildInvalidCredentialsException(); } return UpdatePasswordRequestAsync(new UpdatePasswordRequest { Password = currentPassword, NewPassword = newPassword }); } public Task SignInWithUnityAsync(string token, SignInOptions options = null) { return SignInWithExternalTokenAsync("unity", new SignInWithExternalTokenRequest { IdProvider = "unity", Token = token, SignInOnly = (options != null && !options.CreateAccount) }); } public Task LinkWithUnityAsync(string token, LinkOptions options = null) { return LinkWithExternalTokenAsync("unity", new LinkWithExternalTokenRequest { IdProvider = "unity", Token = token, ForceLink = (options?.ForceLink ?? false) }); } public Task UnlinkUnityAsync() { return UnlinkExternalTokenAsync("unity"); } public async Task DeleteAccountAsync() { if (IsAuthorized) { try { await NetworkClient.DeleteAccountAsync(PlayerId); SignOut(clearCredentials: true); return; } catch (WebRequestException exception) { throw ExceptionHandler.ConvertException(exception); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } public void SignOut(bool clearCredentials = false) { AccessTokenComponent.Clear(); PlayerInfo = null; if (clearCredentials) { SessionTokenComponent.Clear(); PlayerIdComponent.Clear(); PlayerNameComponent.Clear(); } CancelScheduledRefresh(); CancelScheduledExpiration(); ChangeState(AuthenticationState.SignedOut); } public void SwitchProfile(string profile) { if (State == AuthenticationState.SignedOut) { if (!string.IsNullOrEmpty(profile) && Regex.Match(profile, "^[a-zA-Z0-9_-]{1,30}$").Success) { m_Profile.Current = profile; return; } throw ExceptionHandler.BuildClientInvalidProfileException(); } throw ExceptionHandler.BuildClientInvalidStateException(State); } public void ClearSessionToken() { if (State == AuthenticationState.SignedOut) { SessionTokenComponent.Clear(); return; } throw ExceptionHandler.BuildClientInvalidStateException(State); } public async Task<PlayerInfo> GetPlayerInfoAsync() { if (IsAuthorized) { try { PlayerInfo = new PlayerInfo(await NetworkClient.GetPlayerInfoAsync(PlayerId)); return PlayerInfo; } catch (WebRequestException exception) { throw ExceptionHandler.ConvertException(exception); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } public async Task<string> GetPlayerNameAsync() { if (IsAuthorized) { try { PlayerNamesApi.Configuration.AccessToken = AccessTokenComponent.AccessToken; Player data = (await PlayerNamesApi.GetNameAsync(PlayerId)).Data; PlayerNameComponent.PlayerName = data.Name; return data.Name; } catch (ApiException ex) { if (ex.Response.StatusCode == 404) { PlayerNameComponent.Clear(); return null; } throw ExceptionHandler.ConvertException(ex); } catch (Exception ex2) { throw ExceptionHandler.BuildUnknownException(ex2.Message); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } public async Task<string> UpdatePlayerNameAsync(string playerName) { if (IsAuthorized) { if (string.IsNullOrWhiteSpace(playerName) || playerName.Any(char.IsWhiteSpace)) { throw ExceptionHandler.BuildInvalidPlayerNameException(); } try { PlayerNamesApi.Configuration.AccessToken = AccessTokenComponent.AccessToken; string text = (await PlayerNamesApi.UpdateNameAsync(PlayerId, new UpdateNameRequest(playerName))).Data?.Name; if (string.IsNullOrWhiteSpace(text)) { throw ExceptionHandler.BuildUnknownException("Invalid player name response"); } PlayerNameComponent.PlayerName = text; return text; } catch (ApiException exception) { throw ExceptionHandler.ConvertException(exception); } catch (Exception ex) { throw ExceptionHandler.BuildUnknownException(ex.Message); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } internal Task SignInWithExternalTokenAsync(string idProvider, SignInWithExternalTokenRequest request, bool enableRefresh = true) { if (State == AuthenticationState.SignedOut || State == AuthenticationState.Expired) { return HandleSignInRequestAsync(() => NetworkClient.SignInWithExternalTokenAsync(idProvider, request), enableRefresh); } RequestFailedException exception = ExceptionHandler.BuildClientInvalidStateException(State); SendSignInFailedEvent(exception, forceSignOut: false); return Task.FromException((Exception)(object)exception); } internal async Task LinkWithExternalTokenAsync(string idProvider, LinkWithExternalTokenRequest request) { if (IsAuthorized) { try { LinkResponse linkResponse = await NetworkClient.LinkWithExternalTokenAsync(idProvider, request); PlayerInfo?.AddExternalIdentity(linkResponse.User?.ExternalIds?.FirstOrDefault((ExternalIdentity x) => x.ProviderId == request.IdProvider)); return; } catch (WebRequestException exception) { throw ExceptionHandler.ConvertException(exception); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } internal async Task UnlinkExternalTokenAsync(string idProvider) { if (IsAuthorized) { string text = PlayerInfo?.GetIdentityId(idProvider); if (text == null) { throw ExceptionHandler.BuildClientUnlinkExternalIdNotFoundException(); } try { await NetworkClient.UnlinkExternalTokenAsync(idProvider, new UnlinkRequest { IdProvider = idProvider, ExternalId = text }); PlayerInfo.RemoveIdentity(idProvider); return; } catch (WebRequestException exception) { throw ExceptionHandler.ConvertException(exception); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } internal Task SignInWithUsernamePasswordRequestAsync(UsernamePasswordRequest request, bool enableRefresh = true) { if (State == AuthenticationState.SignedOut || State == AuthenticationState.Expired) { return HandleSignInRequestAsync(() => NetworkClient.SignInWithUsernamePasswordAsync(request), enableRefresh); } RequestFailedException exception = ExceptionHandler.BuildClientInvalidStateException(State); SendSignInFailedEvent(exception, forceSignOut: false); return Task.FromException((Exception)(object)exception); } internal Task SignUpWithUsernamePasswordRequestAsync(UsernamePasswordRequest request, bool enableRefresh = true) { if (State == AuthenticationState.SignedOut || State == AuthenticationState.Expired) { return HandleSignInRequestAsync(() => NetworkClient.SignUpWithUsernamePasswordAsync(request), enableRefresh); } RequestFailedException exception = ExceptionHandler.BuildClientInvalidStateException(State); SendSignInFailedEvent(exception, forceSignOut: false); return Task.FromException((Exception)(object)exception); } internal async Task AddUsernamePasswordRequestAsync(UsernamePasswordRequest request) { if (IsAuthorized) { try { SignInResponse signInResponse = await NetworkClient.AddUsernamePasswordAsync(request); PlayerInfo.Username = signInResponse.User?.Username; return; } catch (WebRequestException exception) { throw ExceptionHandler.ConvertException(exception); } catch (Exception ex) { throw ExceptionHandler.BuildUnknownException(ex.Message); } } throw ExceptionHandler.BuildClientInvalidStateException(State); } internal Task UpdatePasswordRequestAsync(UpdatePasswordRequest request, bool enableRefresh = true) { if (IsAuthorized) { return HandleUpdatePasswordRequestAsync(() => NetworkClient.UpdatePasswordAsync(request), enableRefresh); } return Task.FromException((Exception)(object)ExceptionHandler.BuildClientInvalidStateException(State)); } internal Task RefreshAccessTokenAsync() { if (IsSignedIn) { if (State == AuthenticationState.Expired) { return Task.CompletedTask; } string sessionToken = SessionTokenComponent.SessionToken; if (string.IsNullOrEmpty(sessionToken)) { return Task.CompletedTask; } return StartRefreshAsync(sessionToken); } return Task.CompletedTask; } internal async Task HandleSignInRequestAsync(Func<Task<SignInResponse>> signInRequest, bool enableRefresh = true) { try { ChangeState(AuthenticationState.SigningIn); CompleteSignIn(await signInRequest(), enableRefresh); } catch (RequestFailedException ex) { RequestFailedException exception = ex; SendSignInFailedEvent(exception, forceSignOut: true); throw; } catch (WebRequestException exception2) { RequestFailedException ex2 = ExceptionHandler.ConvertException(exception2); if (ex2.ErrorCode == AuthenticationErrorCodes.InvalidSessionToken) { SessionTokenComponent.Clear(); Logger.Log("The session token is invalid and has been cleared. The associated account is no longer accessible through this login method."); } SendSignInFailedEvent(ex2, forceSignOut: true); throw ex2; } } internal async Task HandleUpdatePasswordRequestAsync(Func<Task<SignInResponse>> updatePasswordRequest, bool enableRefresh = true) { try { CompleteSignIn(await updatePasswordRequest(), enableRefresh); } catch (RequestFailedException ex) { RequestFailedException exception = ex; SendUpdatePasswordFailedEvent(exception, forceSignOut: false); throw; } catch (WebRequestException exception2) { RequestFailedException ex2 = ExceptionHandler.ConvertException(exception2); if (ex2.ErrorCode == AuthenticationErrorCodes.InvalidSessionToken) { SessionTokenComponent.Clear(); Logger.Log("The session token is invalid and has been cleared. The associated account is no longer accessible through this login method."); } SendUpdatePasswordFailedEvent(ex2, forceSignOut: false); throw ex2; } } internal async Task StartRefreshAsync(string sessionToken) { ChangeState(AuthenticationState.Refreshing); try { CompleteSignIn(await NetworkClient.SignInWithSessionTokenAsync(sessionToken)); } catch (RequestFailedException) { Logger.LogWarning("The access token is not valid. Retry and refresh again."); if (State != AuthenticationState.Expired) { Expire(); } } catch (WebRequestException) { if (State == AuthenticationState.Refreshing) { Logger.LogWarning("Failed to refresh access token due to network error or internal server error, will retry later."); ChangeState(AuthenticationState.Authorized); ScheduleRefresh(Settings.RefreshAttemptFrequency); } } } internal void CompleteSignIn(SignInResponse response, bool enableRefresh = true) { try { AccessToken accessToken = m_JwtDecoder.Decode<AccessToken>(response.IdToken); if (accessToken == null) { throw AuthenticationException.Create(51, "Failed to decode and verify access token."); } AccessTokenComponent.AccessToken = response.IdToken; if (accessToken.Audience != null) { EnvironmentIdComponent.EnvironmentId = accessToken.Audience.FirstOrDefault((string s) => s.StartsWith("envId:"))?.Substring(6); } PlayerInfo = ((response.User != null) ? new PlayerInfo(response.User) : new PlayerInfo(response.UserId)); PlayerIdComponent.PlayerId = response.UserId; SessionTokenComponent.SessionToken = response.SessionToken; int num = response.ExpiresIn - Settings.AccessTokenRefreshBuffer; int num2 = response.ExpiresIn - Settings.AccessTokenExpiryBuffer; AccessTokenComponent.ExpiryTime = DateTime.UtcNow.AddSeconds(num2); if (enableRefresh) { ScheduleRefresh(num); } ScheduleExpiration(num2); ChangeState(AuthenticationState.Authorized); } catch (AuthenticationException) { throw; } catch (Exception innerException) { throw AuthenticationException.Create(0, "Unknown error completing sign-in.", innerException); } } internal void ScheduleRefresh(double delay) { CancelScheduledRefresh(); DateTime value = DateTime.UtcNow.AddSeconds(delay); DateTime? expiryTime = AccessTokenComponent.ExpiryTime; if (value < expiryTime) { RefreshActionId = m_Scheduler.ScheduleAction((Action)ExecuteScheduledRefresh, delay); } } internal void ScheduleExpiration(double delay) { CancelScheduledExpiration(); ExpirationActionId = m_Scheduler.ScheduleAction((Action)ExecuteScheduledExpiration, delay); } internal void ExecuteScheduledRefresh() { RefreshActionId = null; RefreshAccessTokenAsync(); } internal void ExecuteScheduledExpiration() { ExpirationActionId = null; Expire(); } internal void CancelScheduledRefresh() { if (RefreshActionId.HasValue) { m_Scheduler.CancelAction(RefreshActionId.Value); RefreshActionId = null; } } internal void CancelScheduledExpiration() { if (ExpirationActionId.HasValue) { m_Scheduler.CancelAction(ExpirationActionId.Value); ExpirationActionId = null; } } internal void Expire() { AccessTokenComponent.Clear(); CancelScheduledRefresh(); CancelScheduledExpiration(); ChangeState(AuthenticationState.Expired); } internal void MigrateCache() { try { SessionTokenComponent.Migrate(); } catch (Exception exception) { Logger.LogException(exception); } } private void ChangeState(AuthenticationState newState) { if (State != newState) { AuthenticationState state = State; State = newState; HandleStateChanged(state, newState); } } private void HandleStateChanged(AuthenticationState oldState, AuthenticationState newState) { this.StateChanged?.Invoke(oldState, newState); switch (newState) { case AuthenticationState.Authorized: if (oldState != AuthenticationState.Refreshing) { this.SignedIn?.Invoke(); } break; case AuthenticationState.SignedOut: if (oldState != AuthenticationState.SigningIn) { this.SignedOut?.Invoke(); } break; case AuthenticationState.Expired: this.Expired?.Invoke(); break; case AuthenticationState.SigningIn: case AuthenticationState.Refreshing: break; } } private void SendSignInFailedEvent(RequestFailedException exception, bool forceSignOut) { this.SignInFailed?.Invoke(exception); if (forceSignOut) { SignOut(); } } private void SendUpdatePasswordFailedEvent(RequestFailedException exception, bool forceSignOut) { this.UpdatePasswordFailed?.Invoke(exception); if (forceSignOut) { SignOut(); } } private bool ValidateOpenIdConnectIdProviderName(string idProviderName) { if (!string.IsNullOrEmpty(idProviderName)) { return Regex.Match(idProviderName, "^oidc-[a-z0-9-_\\.]{1,15}$").Success; } return false; } private UsernamePasswordRequest BuildUsernamePasswordRequest(string username, string password) { if (!ValidateCredentials(username, password)) { throw ExceptionHandler.BuildInvalidCredentialsException(); } return new UsernamePasswordRequest { Username = username, Password = password }; } private bool ValidateCredentials(string username, string password) { if (!string.IsNullOrEmpty(username)) { return !string.IsNullOrEmpty(password); } return false; } } internal enum AuthenticationState { SignedOut, SigningIn, Authorized, Refreshing, Expired } public static class AuthenticationExtensions { internal const string ProfileKey = "com.unity.services.authentication.profile"; private const string k_ProfileRegex = "^[a-zA-Z0-9_-]{1,30}$"; public static InitializationOptions SetProfile(this InitializationOptions options, string profile) { if (string.IsNullOrEmpty(profile) || !Regex.Match(profile, "^[a-zA-Z0-9_-]{1,30}$").Success) { throw AuthenticationException.Create(AuthenticationErrorCodes.ClientInvalidProfile, "Invalid profile name. The profile may only contain alphanumeric values, '-', '_', and must be no longer than 30 characters."); } return options.SetOption("com.unity.services.authentication.profile", profile); } } internal class AuthenticationPackageInitializer : IInitializablePackage { private const string k_CloudEnvironmentKey = "com.unity.services.core.cloud-environment"; private const string k_StagingEnvironment = "staging"; public Task Initialize(CoreRegistry registry) { AuthenticationSettings settings = new AuthenticationSettings(); IActionScheduler serviceComponent = registry.GetServiceComponent<IActionScheduler>(); IEnvironments serviceComponent2 = registry.GetServiceComponent<IEnvironments>(); ICloudProjectId serviceComponent3 = registry.GetServiceComponent<ICloudProjectId>(); IProjectConfiguration serviceComponent4 = registry.GetServiceComponent<IProjectConfiguration>(); ProfileComponent profile = new ProfileComponent(serviceComponent4.GetString("com.unity.services.authentication.profile", "default")); AuthenticationMetrics metrics = new AuthenticationMetrics(registry.GetServiceComponent<IMetricsFactory>()); JwtDecoder jwtDecoder = new JwtDecoder(); AuthenticationCache cache = new AuthenticationCache(serviceComponent3, profile); AccessTokenComponent accessToken = new AccessTokenComponent(); EnvironmentIdComponent environmentId = new EnvironmentIdComponent(); PlayerIdComponent playerId = new PlayerIdComponent(cache); PlayerNameComponent playerName = new PlayerNameComponent(cache); SessionTokenComponent sessionToken = new SessionTokenComponent(cache); NetworkConfiguration configuration = new NetworkConfiguration(); NetworkHandler networkHandler = new NetworkHandler(configuration); string playerAuthHost = GetPlayerAuthHost(serviceComponent4); PlayerNamesApi playerNamesApi = new PlayerNamesApi(new AuthenticationApiClient(configuration), new ApiConfiguration { BasePath = GetPlayerNamesHost(serviceComponent4) }); AuthenticationNetworkClient networkClient = new AuthenticationNetworkClient(playerAuthHost, serviceComponent3, serviceComponent2, networkHandler, accessToken); AuthenticationServiceInternal authenticationServiceInternal = (AuthenticationServiceInternal)(AuthenticationService.Instance = new AuthenticationServiceInternal(settings, networkClient, playerNamesApi, profile, jwtDecoder, cache, serviceComponent, metrics, accessToken, environmentId, playerId, playerName, sessionToken)); registry.RegisterServiceComponent<IAccessToken>((IAccessToken)(object)authenticationServiceInternal.AccessTokenComponent); registry.RegisterServiceComponent<IEnvironmentId>((IEnvironmentId)(object)authenticationServiceInternal.EnvironmentIdComponent); registry.RegisterServiceComponent<IPlayerId>((IPlayerId)(object)authenticationServiceInternal.PlayerIdComponent); return Task.CompletedTask; } [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] private static void Register() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) CoreRegistration val = CoreRegistry.Instance.RegisterPackage<AuthenticationPackageInitializer>(new AuthenticationPackageInitializer()); val = ((CoreRegistration)(ref val)).DependsOn<IEnvironments>(); val = ((CoreRegistration)(ref val)).DependsOn<IActionScheduler>(); val = ((CoreRegistration)(ref val)).DependsOn<ICloudProjectId>(); val = ((CoreRegistration)(ref val)).DependsOn<IProjectConfiguration>(); val = ((CoreRegistration)(ref val)).DependsOn<IMetricsFactory>(); val = ((CoreRegistration)(ref val)).ProvidesComponent<IPlayerId>(); val = ((CoreRegistration)(ref val)).ProvidesComponent<IAccessToken>(); ((CoreRegistration)(ref val)).ProvidesComponent<IEnvironmentId>(); } private string GetPlayerAuthHost(IProjectConfiguration projectConfiguration) { if (((projectConfiguration != null) ? projectConfiguration.GetString("com.unity.services.core.cloud-environment", (string)null) : null) == "staging") { return "https://player-auth-stg.services.api.unity.com"; } return "https://player-auth.services.api.unity.com"; } private string GetPlayerNamesHost(IProjectConfiguration projectConfiguration) { if (((projectConfiguration != null) ? projectConfiguration.GetString("com.unity.services.core.cloud-environment", (string)null) : null) == "staging") { return "https://social-stg.services.api.unity.com/v1"; } return "https://social.services.api.unity.com/v1"; } } public static class AuthenticationErrorCodes { public static readonly int MinValue = 10000; public static readonly int ClientInvalidUserState = 10000; public static readonly int ClientNoActiveSession = 10001; public static readonly int InvalidParameters = 10002; public static readonly int AccountAlreadyLinked = 10003; public static readonly int AccountLinkLimitExceeded = 10004; public static readonly int ClientUnlinkExternalIdNotFound = 10005; public static readonly int ClientInvalidProfile = 10006; public static readonly int InvalidSessionToken = 10007; } public sealed class AuthenticationException : RequestFailedException { private AuthenticationException(int errorCode, string message, Exception innerException = null) : base(errorCode, message, innerException) { } public static RequestFailedException Create(int errorCode, string message, Exception innerException = null) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if (errorCode < AuthenticationErrorCodes.MinValue) { return new RequestFailedException(errorCode, message, innerException); } return (RequestFailedException)(object)new AuthenticationException(errorCode, message, innerException); } } internal class AuthenticationExceptionHandler : IAuthenticationExceptionHandler { private IAuthenticationMetrics Metrics { get; } public AuthenticationExceptionHandler(IAuthenticationMetrics metrics) { Metrics = metrics; } public RequestFailedException BuildClientInvalidStateException(AuthenticationState state) { string message = string.Empty; switch (state) { case AuthenticationState.SignedOut: message = "Invalid state for this operation. The player is signed out."; break; case AuthenticationState.SigningIn: message = "Invalid state for this operation. The player is already signing in."; break; case AuthenticationState.Authorized: case AuthenticationState.Refreshing: message = "Invalid state for this operation. The player is already signed in."; break; case AuthenticationState.Expired: message = "Invalid state for this operation. The player session has expired."; break; } Metrics.SendClientInvalidStateExceptionMetric(); return AuthenticationException.Create(AuthenticationErrorCodes.ClientInvalidUserState, message); } public RequestFailedException BuildClientInvalidProfileException() { return AuthenticationException.Create(AuthenticationErrorCodes.ClientInvalidProfile, "Invalid profile name. The profile may only contain alphanumeric values, '-', '_', and must be no longer than 30 characters."); } public RequestFailedException BuildClientUnlinkExternalIdNotFoundException() { Metrics.SendUnlinkExternalIdNotFoundExceptionMetric(); return AuthenticationException.Create(AuthenticationErrorCodes.ClientUnlinkExternalIdNotFound, "No external id was found to unlink from the provider. Use GetPlayerInfoAsync to load the linked external ids."); } public RequestFailedException BuildClientSessionTokenNotExistsException() { Metrics.SendClientSessionTokenNotExistsExceptionMetric(); return AuthenticationException.Create(AuthenticationErrorCodes.ClientNoActiveSession, "There is no cached session token."); } public RequestFailedException BuildUnknownException(string error) { return AuthenticationException.Create(0, error); } public RequestFailedException BuildInvalidIdProviderNameException() { return AuthenticationException.Create(AuthenticationErrorCodes.InvalidParameters, "Invalid IdProviderName. The Id Provider name should start with 'oidc-' and have between 6 and 20 characters (including 'oidc-')"); } public RequestFailedException BuildInvalidPlayerNameException() { return AuthenticationException.Create(AuthenticationErrorCodes.InvalidParameters, "Invalid Player Name. Player names cannot be empty or contain spaces."); } public RequestFailedException BuildInvalidCredentialsException() { return AuthenticationException.Create(AuthenticationErrorCodes.InvalidParameters, "Username and/or Password are not in the correct format"); } public RequestFailedException ConvertException(WebRequestException exception) { //IL_00be: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); string value = $"Request failed: {exception.ResponseCode}, {exception.Message}"; stringBuilder.Append(value); if (exception.ResponseHeaders != null && exception.ResponseHeaders.TryGetValue("x-request-id", out var value2)) { stringBuilder.Append(", request-id: " + value2); } Logger.Log(stringBuilder.ToString()); if (exception.NetworkError) { Metrics.SendNetworkErrorMetric(); return AuthenticationException.Create(1, "Network Error: " + exception.Message, exception); } try { AuthenticationErrorResponse authenticationErrorResponse = IsolatedJsonConvert.DeserializeObject<AuthenticationErrorResponse>(exception.Message, SerializerSettings.DefaultSerializerSettings); return AuthenticationException.Create(MapErrorCodes(authenticationErrorResponse.Title), authenticationErrorResponse.Detail, exception); } catch (JsonException ex) { JsonException innerException = ex; return AuthenticationException.Create(0, "Failed to deserialize server response.", (Exception)(object)innerException); } catch (Exception) { return AuthenticationException.Create(0, "Unknown error deserializing server response. ", exception); } } public RequestFailedException ConvertException(ApiException exception) { return (RequestFailedException)(exception?.Type switch { ApiExceptionType.InvalidParameters => AuthenticationException.Create(AuthenticationErrorCodes.InvalidParameters, exception.Message), ApiExceptionType.Deserialization => AuthenticationException.Create(0, exception.Message), ApiExceptionType.Network => CreateNetworkException(exception), ApiExceptionType.Http => CreateHttpException(exception), _ => CreateUnknownException(exception), }); } private static RequestFailedException CreateNetworkException(ApiException exception) { return (RequestFailedException)(exception?.Response?.StatusCode switch { 503 => AuthenticationException.Create(3, exception.Message), 504 => AuthenticationException.Create(2, exception.Message), _ => AuthenticationException.Create(1, exception.Message), }); } private static RequestFailedException CreateHttpException(ApiException exception) { return (RequestFailedException)(exception?.Response?.StatusCode switch { 400 => AuthenticationException.Create(55, exception.Message), 401 => AuthenticationException.Create(51, exception.Message), 403 => AuthenticationException.Create(53, exception.Message), 404 => AuthenticationException.Create(54, exception.Message), 408 => AuthenticationException.Create(2, exception.Message), 429 => AuthenticationException.Create(50, exception.Message), _ => AuthenticationException.Create(55, exception.Message), }); } private static RequestFailedException CreateUnknownException(Exception exception) { return AuthenticationException.Create(0, "Unknown Error: " + exception.Message); } private int MapErrorCodes(string serverErrorTitle) { return serverErrorTitle switch { "ENTITY_EXISTS" => AuthenticationErrorCodes.AccountAlreadyLinked, "LINKED_ACCOUNT_LIMIT_EXCEEDED" => AuthenticationErrorCodes.AccountLinkLimitExceeded, "INVALID_PARAMETERS" => AuthenticationErrorCodes.InvalidParameters, "INVALID_SESSION_TOKEN" => AuthenticationErrorCodes.InvalidSessionToken, "PERMISSION_DENIED" => AuthenticationErrorCodes.InvalidParameters, "UNAUTHORIZED_REQUEST" => 51, _ => 0, }; } } internal interface IAuthenticationExceptionHandler { RequestFailedException BuildClientInvalidStateException(AuthenticationState state); RequestFailedException BuildClientInvalidProfileException(); RequestFailedException BuildClientUnlinkExternalIdNotFoundException(); RequestFailedException BuildClientSessionTokenNotExistsException(); RequestFailedException BuildUnknownException(string error); RequestFailedException BuildInvalidIdProviderNameException(); RequestFailedException BuildInvalidPlayerNameException(); RequestFailedException BuildInvalidCredentialsException(); RequestFailedException ConvertException(WebRequestException exception); RequestFailedException ConvertException(ApiException exception); } public interface IAuthenticationService { bool IsSignedIn { get; } bool IsAuthorized { get; } bool IsExpired { get; } string AccessToken { get; } string PlayerId { get; } string PlayerName { get; } string Profile { get; } bool SessionTokenExists { get; } PlayerInfo PlayerInfo { get; } event Action SignedIn; event Action SignedOut; event Action Expired; event Action<RequestFailedException> SignInFailed; Task SignInAnonymouslyAsync(SignInOptions options = null); Task SignInWithAppleAsync(string idToken, SignInOptions options = null); Task LinkWithAppleAsync(string idToken, LinkOptions options = null); Task UnlinkAppleAsync(); Task SignInWithAppleGameCenterAsync(string signature, string teamPlayerId, string publicKeyURL, string salt, ulong timestamp, SignInOptions options = null); Task LinkWithAppleGameCenterAsync(string signature, string teamPlayerId, string publicKeyURL, string salt, ulong timestamp, LinkOptions options = null); Task UnlinkAppleGameCenterAsync(); Task SignInWithGoogleAsync(string idToken, SignInOptions options = null); Task LinkWithGoogleAsync(string idToken, LinkOptions options = null); Task UnlinkGoogleAsync(); Task SignInWithGooglePlayGamesAsync(string authCode, SignInOptions options = null); Task LinkWithGooglePlayGamesAsync(string authCode, LinkOptions options = null); Task UnlinkGooglePlayGamesAsync(); Task SignInWithFacebookAsync(string accessToken, SignInOptions options = null); Task LinkWithFacebookAsync(string accessToken, LinkOptions options = null); Task UnlinkFacebookAsync(); Task SignInWithSteamAsync(string sessionTicket, string identity, SignInOptions options = null); [Obsolete("This method is deprecated as of version 2.7.1. Please use the SignInWithSteamAsync method with the 'identity' parameter for better security.")] Task SignInWithSteamAsync(string sessionTicket, SignInOptions options = null); Task LinkWithSteamAsync(string sessionTicket, string identity, LinkOptions options = null); [Obsolete("This method is deprecated as of version 2.7.1. Please use the LinkWithSteamAsync method with the 'identity' parameter for better security.")] Task LinkWithSteamAsync(string sessionTicket, LinkOptions options = null); Task UnlinkSteamAsync(); Task SignInWithOculusAsync(string nonce, string userId, SignInOptions options = null); Task LinkWithOculusAsync(string nonce, string userId, LinkOptions options = null); Task UnlinkOculusAsync(); Task SignInWithOpenIdConnectAsync(string idProviderName, string idToken, SignInOptions options = null); Task LinkWithOpenIdConnectAsync(string idProviderName, string idToken, LinkOptions options = null); Task UnlinkOpenIdConnectAsync(string idProviderName); Task SignInWithUnityAsync(string token, SignInOptions options = null); Task LinkWithUnityAsync(string token, LinkOptions options = null); Task UnlinkUnityAsync(); Task SignInWithUsernamePasswordAsync(string username, string password); Task SignUpWithUsernamePasswordAsync(string username, string password); Task AddUsernamePasswordAsync(string username, string password); Task UpdatePasswordAsync(string currentPassword, string newPassword); Task DeleteAccountAsync(); Task<PlayerInfo> GetPlayerInfoAsync(); Task<string> GetPlayerNameAsync(); Task<string> UpdatePlayerNameAsync(string name); void SignOut(bool clearCredentials = false); void SwitchProfile(string profile); void ClearSessionToken(); } internal class AuthenticationMetrics : IAuthenticationMetrics { private const string k_PackageName = "com.unity.services.authentication"; private const string k_NetworkErrorKey = "network_error_event"; private const string k_ExpiredSessionKey = "expired_session_event"; private const string k_ClientInvalidStateExceptionKey = "client_invalid_state_exception_event"; private const string k_UnlinkExternalIdNotFoundExceptionKey = "unlink_external_id_not_found_exception_event"; private const string k_ClientSessionTokenNotExistsExceptionKey = "client_session_token_not_exists_exception_event"; private readonly IMetrics m_Metrics; internal AuthenticationMetrics(IMetricsFactory metricsFactory) { m_Metrics = metricsFactory.Create("com.unity.services.authentication"); } public void SendNetworkErrorMetric() { m_Metrics.SendSumMetric("network_error_event", 1.0, (IDictionary<string, string>)null); } public void SendExpiredSessionMetric() { m_Metrics.SendSumMetric("expired_session_event", 1.0, (IDictionary<string, string>)null); } public void SendClientInvalidStateExceptionMetric() { m_Metrics.SendSumMetric("client_invalid_state_exception_event", 1.0, (IDictionary<string, string>)null); } public void SendUnlinkExternalIdNotFoundExceptionMetric() { m_Metrics.SendSumMetric("unlink_external_id_not_found_exception_event", 1.0, (IDictionary<string, string>)null); } public void SendClientSessionTokenNotExistsExceptionMetric() { m_Metrics.SendSumMetric("client_session_token_not_exists_exception_event", 1.0, (IDictionary<string, string>)null); } } internal interface IAuthenticationMetrics { void SendNetworkErrorMetric(); void SendExpiredSessionMetric(); void SendClientInvalidStateExceptionMetric(); void SendUnlinkExternalIdNotFoundExceptionMetric(); void SendClientSessionTokenNotExistsExceptionMetric(); } internal class AccessTokenComponent : IAccessToken, IServiceComponent { public string AccessToken { get; internal set; } public DateTime? ExpiryTime { get; internal set; } internal AccessTokenComponent() { } internal void Clear() { AccessToken = null; ExpiryTime = null; } } internal class EnvironmentIdComponent : IEnvironmentId, IServiceComponent { public string EnvironmentId { get; internal set; } internal EnvironmentIdComponent() { } } internal class PlayerIdComponent : IPlayerId, IServiceComponent { private const string k_CacheKey = "player_id"; private readonly IAuthenticationCache m_Cache; public string PlayerId { get { return GetPlayerId(); } internal set { SetPlayerId(value); } } public event Action<string> PlayerIdChanged; internal PlayerIdComponent(IAuthenticationCache cache) { m_Cache = cache; } internal void Clear() { m_Cache.DeleteKey("player_id"); } private string GetPlayerId() { return m_Cache.GetString("player_id"); } private void SetPlayerId(string playerId) { if (PlayerId != playerId) { m_Cache.SetString("player_id", playerId); this.PlayerIdChanged?.Invoke(playerId); } } } internal class PlayerNameComponent : IPlayerName { private const string k_CacheKey = "player_name"; private readonly IAuthenticationCache m_Cache; public string PlayerName { get { return GetPlayerName(); } internal set { SetPlayerName(value); } } public event Action<string> PlayerNameChanged; internal PlayerNameComponent(IAuthenticationCache cache) { m_Cache = cache; } internal void Clear() { m_Cache.DeleteKey("player_name"); } private string GetPlayerName() { return m_Cache.GetString("player_name"); } private void SetPlayerName(string playerName) { if (PlayerName != playerName) { m_Cache.SetString("player_name", playerName); this.PlayerNameChanged?.Invoke(playerName); } } } internal interface IProfile { string Current { get; set; } event Action<ProfileEventArgs> ProfileChange; } internal class ProfileComponent : IProfile { private string _current; public string Current { get { return _current; } set { SetProfile(value); } } public event Action<ProfileEventArgs> ProfileChange; internal ProfileComponent(string profile) { SetProfile(profile); } public void SetProfile(string profile) { _current = profile; this.ProfileChange?.Invoke(new ProfileEventArgs(_current)); } } internal class ProfileEventArgs : EventArgs { public string Profile { get; } public ProfileEventArgs(string profile) { Profile = profile; } } internal class SessionTokenComponent { private const string k_CacheKey = "session_token"; private readonly IAuthenticationCache m_Cache; internal string SessionToken { get { return GetSessionToken(); } set { SetSessionToken(value); } } internal SessionTokenComponent(IAuthenticationCache cache) { m_Cache = cache; } internal void Clear() { m_Cache.DeleteKey("session_token"); } internal void Migrate() { m_Cache.Migrate("session_token"); } private string GetSessionToken() { return m_Cache.GetString("session_token"); } private void SetSessionToken(string sessionToken) { m_Cache.SetString("session_token", sessionToken); } } public sealed class Identity { public string TypeId; public string UserId; internal Identity(ExternalIdentity externalIdentity) { if (externalIdentity != null) { TypeId = externalIdentity.ProviderId; UserId = externalIdentity.ExternalId; } } } public sealed class LinkOptions { public bool ForceLink { get; set; } } public sealed class PlayerInfo { private const string k_OpenIdConnectPrefix = "oidc-"; private const string k_IdProviderNameRegex = "^oidc-[a-z0-9-_\\.]{1,15}$"; public string Id { get; } public DateTime? CreatedAt { get; } public List<Identity> Identities { get; } [CanBeNull] public string Username { get; internal set; } [CanBeNull] public DateTime? LastPasswordUpdate { get; internal set; } internal PlayerInfo(string playerId) { Id = playerId; Identities = new List<Identity>(); } internal PlayerInfo(PlayerInfoResponse response) : this(response.Id, response.CreatedAt, response.ExternalIds, response.UsernamePassword?.Username, response.UsernamePassword?.PasswordUpdatedAt) { } internal PlayerInfo(User user) : this(user.Id, user.CreatedAt, user.ExternalIds, user.UsernameInfo?.Username ?? user.Username, user.UsernameInfo?.PasswordUpdatedAt) { } internal PlayerInfo(string playerId, string createdAt, List<ExternalIdentity> externalIdentities, string username, string lastPasswordUpdate) { Id = playerId; Identities = new List<Identity>(); if (double.TryParse(createdAt, out var result)) { CreatedAt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(result); } if (externalIdentities != null) { foreach (ExternalIdentity externalIdentity in externalIdentities) { Identities.Add(new Identity(externalIdentity)); } } Username = username; if (double.TryParse(lastPasswordUpdate, out var result2)) { LastPasswordUpdate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(result2); } } public string GetFacebookId() { return GetIdentityId("facebook.com"); } public string GetSteamId() { return GetIdentityId("steampowered.com"); } public string GetGoogleId() { return GetIdentityId("google.com"); } public string GetGooglePlayGamesId() { return GetIdentityId("google-play-games"); } public string GetAppleId() { return GetIdentityId("apple.com"); } public string GetAppleGameCenterId() { return GetIdentityId("apple-game-center"); } public string GetOculusId() { return GetIdentityId("oculus"); } public string GetOpenIdConnectId(string idProviderName) { if (!ValidateOpenIdConnectIdProviderName(idProviderName)) { return null; } return GetIdentityId(idProviderName); } public string GetUnityId() { return GetIdentityId("unity"); } public List<Identity> GetOpenIdConnectIdProviders() { return Identities?.FindAll((Identity id) => id.TypeId.StartsWith("oidc-")); } internal string GetIdentityId(string typeId) { return Identities?.FirstOrDefault((Identity x) => x.TypeId == typeId)?.UserId; } internal void AddExternalIdentity(ExternalIdentity externalId) { if (externalId != null) { Identities.Add(new Identity(externalId)); } } internal void RemoveIdentity(string typeId) { Identities?.RemoveAll((Identity x) => x.TypeId == typeId); } private bool ValidateOpenIdConnectIdProviderName(string idProviderName) { if (!string.IsNullOrEmpty(idProviderName)) { return Regex.Match(idProviderName, "^oidc-[a-z0-9-_\\.]{1,15}$").Success; } return false; } } [Serializable] internal class AppleGameCenterConfig { [JsonProperty("teamPlayerId")] public string TeamPlayerId; [JsonProperty("publicKeyUrl")] public string PublicKeyURL; [JsonProperty("salt")] public string Salt; [JsonProperty("timestamp")] public ulong Timestamp; [Preserve] internal AppleGameCenterConfig() { } } [Serializable] internal class LinkWithAppleGameCenterRequest : LinkWithExternalTokenRequest { [JsonProperty("appleGameCenterConfig")] public AppleGameCenterConfig AppleGameCenterConfig; [Preserve] internal LinkWithAppleGameCenterRequest() { } } [Serializable] internal class SignInWithAppleGameCenterRequest : SignInWithExternalTokenRequest { [JsonProperty("appleGameCenterConfig")] public AppleGameCenterConfig AppleGameCenterConfig; [Preserve] internal SignInWithAppleGameCenterRequest() { } } [Serializable] internal class LinkWithExternalTokenRequest { [JsonProperty("idProvider")] public string IdProvider; [JsonProperty("token")] public string Token; [JsonProperty("forceLink")] public bool ForceLink; [Preserve] internal LinkWithExternalTokenRequest() { } } internal class LinkWithSteamRequest : LinkWithExternalTokenRequest { [JsonProperty("steamConfig")] public SteamConfig SteamConfig; [Preserve] internal LinkWithSteamRequest() { } } [Serializable] internal class OculusConfig { [JsonProperty("userId")] public string UserId; [Preserve] internal OculusConfig() { } } [Serializable] internal class LinkWithOculusRequest : LinkWithExternalTokenRequest { [JsonProperty("oculusConfig")] public OculusConfig OculusConfig; [Preserve] internal LinkWithOculusRequest() { } } [Serializable] internal class SignInWithOculusRequest : SignInWithExternalTokenRequest { [JsonProperty("oculusConfig")] public OculusConfig OculusConfig; [Preserve] internal SignInWithOculusRequest() { } } [Serializable] internal class SessionTokenRequest { [JsonProperty("sessionToken")] public string SessionToken; [Preserve] public SessionTokenRequest() { } } [Serializable] internal class SignInWithExternalTokenRequest { [JsonProperty("idProvider")] public string IdProvider; [JsonProperty("token")] public string Token; [JsonProperty("signInOnly")] public bool SignInOnly; [Preserve] internal SignInWithExternalTokenRequest() { } } [Serializable] internal class SignInWithSteamRequest : SignInWithExternalTokenRequest { [JsonProperty("steamConfig")] public SteamConfig SteamConfig; [Preserve] internal SignInWithSteamRequest() { } } internal class SteamConfig { [JsonProperty("identity")] public string identity; [Preserve] internal SteamConfig() { } } [Serializable] internal class UnlinkRequest { [JsonProperty("idProvider")] public string IdProvider; [JsonProperty("externalId")] public string ExternalId; [Preserve] internal UnlinkRequest() { } } [Serializable] internal class UpdatePasswordRequest { [JsonProperty("password")] public string Password; [JsonProperty("newPassword")] public string NewPassword; [Preserve] internal UpdatePasswordRequest() { } } [Serializable] internal class UsernamePasswordRequest { [JsonProperty("username")] public string Username; [JsonProperty("password")] public string Password; [Preserve] internal UsernamePasswordRequest() { } } [Serializable] internal class AuthenticationErrorResponse { [JsonProperty("title")] public string Title; [JsonProperty("detail")] public string Detail; [JsonProperty("status")] public int Status; [Preserve] public AuthenticationErrorResponse() { } } [Serializable] internal class ExternalIdentity { [JsonProperty("providerId")] public string ProviderId; [JsonProperty("externalId")] public string ExternalId; [Preserve] public ExternalIdentity() { } } [Serializable] internal class LinkResponse { [JsonProperty("user")] public User User; [Preserve] public LinkResponse() { } } [Serializable] internal class PlayerInfoResponse { [JsonProperty("id")] public string Id; [JsonProperty("createdAt")] public string CreatedAt; [JsonProperty("externalIds")] public List<ExternalIdentity> ExternalIds; [JsonProperty("username")] [CanBeNull] public string Username; [JsonProperty("usernamepassword")] [CanBeNull] public UsernameInfo UsernamePassword; [Preserve] public PlayerInfoResponse() { } } [Serializable] internal class SignInResponse { [JsonProperty("userId")] public string UserId; [JsonProperty("idToken")] public string IdToken; [JsonProperty("sessionToken")] public string SessionToken; [JsonProperty("expiresIn")] public int ExpiresIn; [JsonProperty("user")] public User User; [Preserve] public SignInResponse() { } } [Serializable] internal class UnlinkResponse { [JsonProperty("user")] public User User; [Preserve] public UnlinkResponse() { } } [Serializable] internal class User { [JsonProperty("id")] public string Id; [JsonProperty("createdAt")] public string CreatedAt; [JsonProperty("externalIds")] public List<ExternalIdentity> ExternalIds; [JsonProperty("username")] [CanBeNull] public string Username; [JsonProperty("UsernameInfo")] [CanBeNull] public UsernameInfo UsernameInfo; [Preserve] public User() { } } internal class UsernameInfo { [JsonProperty("username")] public string Username; [JsonProperty("createdAt")] public string CreatedAt; [JsonProperty("lastLoginAt")] public string LastLoginAt; [JsonProperty("passwordUpdatedAt")] public string PasswordUpdatedAt; [Preserve] public UsernameInfo() { } } internal class AccessToken : BaseJwt { [JsonProperty("aud")] public string[] Audience; [JsonProperty("client_id")] public string ClientId; [JsonProperty("ext")] public AccessTokenExtraClaims Extra; [JsonProperty("iss")] public string Issuer; [JsonProperty("jti")] public string JwtId; [JsonProperty("project_id")] public string ProjectId; [JsonProperty("scp")] public string[] Scope; [JsonProperty("sub")] public string Subject; [Preserve] public AccessToken() { } } internal class AccessTokenExtraClaims { [Preserve] public AccessTokenExtraClaims() { } } internal class BaseJwt { [JsonProperty("exp")] public int ExpirationTimeUnix; [JsonProperty("iat")] public int IssuedAtTimeUnix; [JsonProperty("nbf")] public int NotBeforeTimeUnix; [JsonIgnore] public DateTime? ExpirationTime => ConvertTimestamp(ExpirationTimeUnix); [JsonIgnore] public DateTime? IssuedAtTime => ConvertTimestamp(IssuedAtTimeUnix); [JsonIgnore] public DateTime? NotBeforeTime => ConvertTimestamp(NotBeforeTimeUnix); [Preserve] public BaseJwt() { } protected DateTime? ConvertTimestamp(int timestamp) { if (timestamp != 0) { return DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime; } return null; } } internal class AuthenticationSettings : IAuthenticationSettings { private const int k_AccessTokenRefreshBuffer = 300; private const int k_AccessTokenExpiryBuffer = 15; private const int k_RefreshAttemptFrequency = 30; public int AccessTokenRefreshBuffer { get; internal set; } public int AccessTokenExpiryBuffer { get; internal set; } public int RefreshAttemptFrequency { get; internal set; } internal AuthenticationSettings() { AccessTokenRefreshBuffer = 300; AccessTokenExpiryBuffer = 15; RefreshAttemptFrequency = 30; } internal void Reset() { AccessTokenRefreshBuffer = 300; AccessTokenExpiryBuffer = 15; RefreshAttemptFrequency = 30; } } internal interface IAuthenticationSettings { int AccessTokenRefreshBuffer { get; } int AccessTokenExpiryBuffer { get; } int RefreshAttemptFrequency { get; } } internal interface INetworkConfiguration { int Retries { get; } int Timeout { get; } } internal class NetworkConfiguration : INetworkConfiguration { private const int k_DefaultRetries = 2; private const int k_DefaultTimeout = 10; public int Retries { get; set; } = 2; public int Timeout { get; set; } = 10; } public sealed class SignInOptions { public bool CreateAccount { get; set; } } internal class AuthenticationApiClient : IApiClient { private INetworkConfiguration Configuration { get; } public AuthenticationApiClient(INetworkConfiguration configuration) { Configuration = configuration; } public Task<ApiResponse> GetAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Get, options, configuration, cancellationToken); } public Task<ApiResponse<T>> GetAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Get, options, configuration, cancellationToken); } public Task<ApiResponse> PostAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Post, options, configuration, cancellationToken); } public Task<ApiResponse<T>> PostAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Post, options, configuration, cancellationToken); } public Task<ApiResponse> PutAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Put, options, configuration, cancellationToken); } public Task<ApiResponse<T>> PutAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Put, options, configuration, cancellationToken); } public Task<ApiResponse> DeleteAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Delete, options, configuration, cancellationToken); } public Task<ApiResponse<T>> DeleteAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Delete, options, configuration, cancellationToken); } public Task<ApiResponse> HeadAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Head, options, configuration, cancellationToken); } public Task<ApiResponse<T>> HeadAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Head, options, configuration, cancellationToken); } public Task<ApiResponse> OptionsAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Options, options, configuration, cancellationToken); } public Task<ApiResponse<T>> OptionsAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Options, options, configuration, cancellationToken); } public Task<ApiResponse> PatchAsync(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync(path, WebRequestVerb.Patch, options, configuration, cancellationToken); } public Task<ApiResponse<T>> PatchAsync<T>(string path, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { return SendAsync<T>(path, WebRequestVerb.Patch, options, configuration, cancellationToken); } private async Task<ApiResponse> SendAsync(string path, WebRequestVerb method, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { int attempts = 0; bool flag; do { try { UnityWebRequest request = BuildWebRequest(path, method, options, configuration); try { return await request.SendWebRequestAsync(); } finally { ((IDisposable)request)?.Dispose(); } } catch (ApiException ex) { flag = ex.Type == ApiExceptionType.Network; attempts++; if (attempts >= Configuration.Retries || !flag) { throw; } } } while (flag); return null; } private async Task<ApiResponse<T>> SendAsync<T>(string path, WebRequestVerb method, ApiRequestOptions options, IApiConfiguration configuration, CancellationToken cancellationToken = default(CancellationToken)) { int attempts = 0; bool flag; do { try { UnityWebRequest request = BuildWebRequest(path, method, options, configuration); try { return await request.SendWebRequestAsync<T>(cancellationToken); } finally { ((IDisposable)request)?.Dispose(); } } catch (ApiException ex) { flag = ex.Type == ApiExceptionType.Network; if (attempts >= Configuration.Retries || !flag) { throw; } attempts++; } } while (flag); return null; } internal UnityWebRequest BuildWebRequest(string path, WebRequestVerb method, ApiRequestOptions options, IApiConfiguration configuration) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown ApiRequestPathBuilder apiRequestPathBuilder = new ApiRequestPathBuilder(configuration.BasePath, path); apiRequestPathBuilder.AddPathParameters(options.PathParameters); apiRequestPathBuilder.AddQueryParameters(options.QueryParameters); UnityWebRequest val = new UnityWebRequest(apiRequestPathBuilder.GetFullUri(), method.ToString()); if (configuration.UserAgent != null) { val.SetRequestHeader("User-Agent", configuration.UserAgent); } if (configuration.DefaultHeaders != null) { foreach (KeyValuePair<string, string> defaultHeader in configuration.DefaultHeaders) { val.SetRequestHeader(defaultHeader.Key, defaultHeader.Value); } } if (options.HeaderParameters != null) { foreach (KeyValuePair<string, IList<string>> headerParameter in options.HeaderParameters) { foreach (string item in headerParameter.Value) { val.SetRequestHeader(headerParameter.Key, item); } } } val.timeout = configuration.Timeout; if (options.Data != null) { JsonSerializerSettings settings = new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 }; string s = IsolatedJsonConvert.SerializeObject(options.Data, settings); val.uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(s)); } val.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return val; } } internal class AuthenticationNetworkClient : IAuthenticationNetworkClient { private const string k_AnonymousUrlStem = "/v1/authentication/anonymous"; private const string k_SessionTokenUrlStem = "/v1/authentication/session-token"; private const string k_ExternalTokenUrlStem = "/v1/authentication/external-token"; private const string k_LinkExternalTokenUrlStem = "/v1/authentication/link"; private const string k_UnlinkExternalTokenUrlStem = "/v1/authentication/unlink"; private const string k_UsersUrlStem = "/v1/users"; private const string k_UsernamePasswordSignInUrlStem = "/v1/authentication/usernamepassword/sign-in"; private const string k_UsernamePasswordSignUpUrlStem = "/v1/authentication/usernamepassword/sign-up"; private const string k_UpdatePasswordUrlStem = "/v1/authentication/usernamepassword/update-password"; private readonly string m_AnonymousUrl; private readonly string m_SessionTokenUrl; private readonly string m_ExternalTokenUrl; private readonly string m_LinkExternalTokenUrl; private readonly string m_UnlinkExternalTokenUrl; private readonly string m_UsersUrl; private readonly string m_UsernamePasswordSignInUrl; private readonly string m_UsernamePasswordSignUpUrl; private readonly string m_UpdatePasswordUrl; private readonly Dictionary<string, string> m_CommonHeaders; internal AccessTokenComponent AccessTokenComponent { get; } internal ICloudProjectId CloudProjectIdComponent { get; } internal IEnvironments EnvironmentComponent { get; } internal INetworkHandler NetworkHandler { get; } private string AccessToken => AccessTokenComponent.AccessToken; private string EnvironmentName => EnvironmentComponent.Current; internal AuthenticationNetworkClient(string host, ICloudProjectId cloudProjectId, IEnvironments environment, INetworkHandler networkHandler, AccessTokenComponent accessToken) { AccessTokenComponent = accessToken; CloudProjectIdComponent = cloudProjectId; EnvironmentComponent = environment; NetworkHandler = networkHandler; m_AnonymousUrl = host + "/v1/authentication/anonymous"; m_SessionTokenUrl = host + "/v1/authentication/session-token"; m_ExternalTokenUrl = host + "/v1/authentication/external-token"; m_LinkExternalTokenUrl = host + "/v1/authentication/link"; m_UnlinkExternalTokenUrl = host + "/v1/authentication/unlink"; m_UsersUrl = host + "/v1/users"; m_UsernamePasswordSignInUrl = host + "/v1/authentication/usernamepassword/sign-in"; m_UsernamePasswordSignUpUrl = host + "/v1/authentication/usernamepassword/sign-up"; m_UpdatePasswordUrl = host + "/v1/authentication/usernamepassword/update-password"; m_CommonHeaders = new Dictionary<string, string> { ["ProjectId"] = CloudProjectIdComponent.GetCloudProjectId(), ["Error-Version"] = "v1" }; } public Task<SignInResponse> SignInAnonymouslyAsync() { return NetworkHandler.PostAsync<SignInResponse>(m_AnonymousUrl, WithEnvironment(GetCommonHeaders())); } public Task<SignInResponse> SignInWithSessionTokenAsync(string token) { return NetworkHandler.PostAsync<SignInResponse>(m_SessionTokenUrl, new SessionTokenRequest { SessionToken = token }, WithEnvironment(GetCommonHeaders())); } public Task<SignInResponse> SignInWithExternalTokenAsync(string idProvider, SignInWithExternalTokenRequest externalToken) { string url = m_ExternalTokenUrl + "/" + idProvider; return NetworkHandler.PostAsync<SignInResponse>(url, externalToken, WithEnvironment(GetCommonHeaders())); } public Task<LinkResponse> LinkWithExternalTokenAsync(string idProvider, LinkWithExternalTokenRequest externalToken) { string url = m_LinkExternalTokenUrl + "/" + idProvider; return NetworkHandler.PostAsync<LinkResponse>(url, externalToken, WithEnvironment(WithAccessToken(GetCommonHeaders()))); } public Task<UnlinkResponse> UnlinkExternalTokenAsync(string idProvider, UnlinkRequest request) { string url = m_UnlinkExternalTokenUrl + "/" + idProvider; return NetworkHandler.PostAsync<UnlinkResponse>(url, request, WithEnvironment(WithAccessToken(GetCommonHeaders()))); } public Task<PlayerInfoResponse> GetPlayerInfoAsync(string playerId) { return NetworkHandler.GetAsync<PlayerInfoResponse>(CreateUserRequestUrl(playerId), WithAccessToken(GetCommonHeaders())); } public Task DeleteAccountAsync(string playerId) { return NetworkHandler.DeleteAsync(CreateUserRequestUrl(playerId), WithEnvironment(WithAccessToken(GetCommonHeaders()))); } public Task<SignInResponse> SignInWithUsernamePasswordAsync(UsernamePasswordRequest credentials) { return NetworkHandler.PostAsync<SignInResponse>(m_UsernamePasswordSignInUrl, credentials, WithEnvironment(GetCommonHeaders())); } public Task<SignInResponse> SignUpWithUsernamePasswordAsync(UsernamePasswordRequest credentials) { return NetworkHandler.PostAsync<SignInResponse>(m_UsernamePasswordSignUpUrl, credentials, WithEnvironment(GetCommonHeaders())); } public Task<SignInResponse> AddUsernamePasswordAsync(UsernamePasswordRequest credentials) { return NetworkHandler.PostAsync<SignInResponse>(m_UsernamePasswordSignUpUrl, credentials, WithEnvironment(WithAccessToken(GetCommonHeaders()))); } public Task<SignInResponse> UpdatePasswordAsync(UpdatePasswordRequest credentials) { return NetworkHandler.PostAsync<SignInResponse>(m_UpdatePasswordUrl, credentials, WithEnvironment(WithAccessToken(GetCommonHeaders()))); } private string CreateUserRequestUrl(string user) { return m_UsersUrl + "/" + user; } private Dictionary<string, string> WithAccessToken(Dictionary<string, string> headers) { headers["Authorization"] = "Bearer " + AccessToken; return headers; } private Dictionary<string, string> WithEnvironment(Dictionary<string, string> headers) { string environmentName = EnvironmentName; if (!string.IsNullOrEmpty(environmentName)) { headers["UnityEnvironment"] = environmentName; } return headers; } private Dictionary<string, string> GetCommonHeaders() { return new Dictionary<string, string>(m_CommonHeaders); } } internal static class AuthenticationWebRequestUtils { public static Task<ApiResponse> SendWebRequestAsync(this UnityWebRequest request) { TaskCompletionSource<ApiResponse> tcs = new TaskCompletionSource<ApiResponse>(); UnityWebRequestAsyncOperation val = request.SendWebRequest(); if (((AsyncOperation)val).isDone) { ProcessResponse(tcs, request); } else { ((AsyncOperation)val).completed += delegate { ProcessResponse(tcs, request); }; } return tcs.Task; } public static Task<ApiResponse<T>> SendWebRequestAsync<T>(this UnityWebRequest request, CancellationToken cancellationToken) { TaskCompletionSource<ApiResponse<T>> tcs = new TaskCompletionSource<ApiResponse<T>>(); cancellationToken.Register(delegate { tcs.SetCanceled(); }); UnityWebRequestAsyncOperation val = request.SendWebRequest(); if (((AsyncOperation)val).isDone) { ProcessResponse(tcs, request); } else { ((AsyncOperation)val).completed += delegate { ProcessResponse(tcs, request); }; } return tcs.Task; } private static void ProcessResponse(TaskCompletionSource<ApiResponse> tcs, UnityWebRequest request) { ApiResponse obj = new ApiResponse { StatusCode = (int)request.responseCode, ErrorText = request.error }; DownloadHandler downloadHandler = request.downloadHandler; obj.RawContent = ((downloadHandler != null) ? downloadHandler.text : null); ApiResponse apiResponse = obj; string error = request.error; DownloadHandler downloadHandler2 = request.downloadHandler; string message = error + "\n" + ((downloadHandler2 != null) ? downloadHandler2.text : null); if (IsNetworkError(request)) { tcs.SetException(new ApiException(ApiExceptionType.Network, message, apiResponse)); } else if (IsHttpError(request)) { tcs.SetException(new ApiException(ApiExceptionType.Http, message, apiResponse)); } else { tcs.SetResult(apiResponse); } } private static void ProcessResponse<T>(TaskCompletionSource<ApiResponse<T>> tcs, UnityWebRequest request) { ApiResponse<T> obj = new ApiResponse<T> { StatusCode = (int)request.responseCode, ErrorText = request.error }; DownloadHandler downloadHandler = request.downloadHandler; obj.RawContent = ((downloadHandler != null) ? downloadHandler.text : null); ApiResponse<T> apiResponse = obj; string error = request.error; DownloadHandler downloadHandler2 = request.downloadHandler; string message = error + "\n" + ((downloadHandler2 != null) ? downloadHandler2.text : null); if (IsNetworkError(request)) { tcs.SetException(new ApiException(ApiExceptionType.Network, message, apiResponse)); return; } if (IsHttpError(request)) { tcs.SetException(new ApiException(ApiExceptionType.Http, message, apiResponse)); return; } try { DownloadHandler downloadHandler3 = request.downloadHandler; if (!string.IsNullOrEmpty((downloadHandler3 != null) ? downloadHandler3.text : null)) { DownloadHandler downloadHandler4 = request.downloadHandler; apiResponse.Data = IsolatedJsonConvert.DeserializeObject<T>((downloadHandler4 != null) ? downloadHandler4.text : null, SerializerSettings.DefaultSerializerSettings); } } catch (Exception) { tcs.SetException(new ApiException(ApiExceptionType.Deserialization, $"Deserialization of type '{typeof(T)}' failed.", apiResponse)); return; } tcs.SetResult(apiResponse); } public static bool IsNetworkError(UnityWebRequest request) { return request.responseCode >= 500; } public static bool IsHttpError(UnityWebRequest request) { if (request.responseCode >= 400) { return request.responseCode < 500; } return false; } } internal static class HttpUtilities { public static IDictionary<string, string> ParseQueryString(string queryString) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); string[] array = queryString.Split('?', '&'); foreach (string text in array) { int num = text.IndexOf('='); if (num >= 0) { string key = UnescapeUrlString(text.Substring(0, num)); string value = UnescapeUrlString(text.Substring(num + 1)); dictionary[key] = value; } } return dictionary; } public static string EncodeQueryString(IDictionary<string, string> queryParams) { StringBuilder stringBuilder = new StringBuilder(); bool flag = true; foreach (KeyValuePair<string, string> queryParam in queryParams) { if (!flag) { stringBuilder.Append('&'); } else { flag = false; } stringBuilder.Append(EscapeUrlString(queryParam.Key)).Append('=').Append(EscapeUrlString(queryParam.Value)); } return stringBuilder.ToString(); } private static string EscapeUrlString(string rawString) { return Uri.EscapeDataString(rawString); } private static string UnescapeUrlString(string urlString) { return Uri.UnescapeDataString(urlString); } } internal interface IAuthenticationNetworkClient { Task<SignInResponse> SignInAnonymouslyAsync(); Task<SignInResponse> SignInWithSessionTokenAsync(string token); Task<SignInResponse> SignInWithExternalTokenAsync(string idProvider, SignInWithExternalTokenRequest externalToken); Task<LinkResponse> LinkWithExternalTokenAsync(string idProvider, LinkWithExternalTokenRequest externalToken); Task<UnlinkResponse> UnlinkExternalTokenAsync(string idProvider, UnlinkRequest request); Task<PlayerInfoResponse> GetPlayerInfoAsync(string playerId); Task DeleteAccountAsync(string playerId); Task<SignInResponse> SignInWithUsernamePasswordAsync(UsernamePasswordRequest credentials); Task<SignInResponse> SignUpWithUsernamePasswordAsync(UsernamePasswordRequest credentials); Task<SignInResponse> AddUsernamePasswordAsync(UsernamePasswordRequest credentials); Task<SignInResponse> UpdatePasswordAsync(UpdatePasswordRequest credentials); } internal interface INetworkHandler { Task<T> GetAsync<T>(string url, IDictionary<string, string> headers = null); Task<T> PostAsync<T>(string url, IDictionary<string, string> headers = null); Task<T> PostAsync<T>(string url, object payload, IDictionary<string, string> headers = null); Task<T> PutAsync<T>(string url, object payload, IDictionary<string, string> headers = null); Task DeleteAsync(string url, IDictionary<string, string> headers = null); Task<T> DeleteAsync<T>(string url, IDictionary<string, string> headers = null); } internal class NetworkHandler : INetworkHandler { public static class ContentType { public const string Json = "application/json"; } private INetworkConfiguration Configuration { get; } public NetworkHandler(INetworkConfiguration configuration) { Configuration = configuration; } public Task<T> GetAsync<T>(string url, IDictionary<string, string> headers = null) { return new WebRequest(Configuration, WebRequestVerb.Get, url, headers, null, "application/json").SendAsync<T>(); } public Task<T> PostAsync<T>(string url, IDictionary<string, string> headers = null) { return new WebRequest(Configuration, WebRequestVerb.Post, url, headers, null, "application/json").SendAsync<T>(); } public Task<T> PostAsync<T>(string url, object payload, IDictionary<string, string> headers = null) { string payload2 = ((payload != null) ? IsolatedJsonConvert.SerializeObject(payload, SerializerSettings.DefaultSerializerSettings) : null); return new WebRequest(Configuration, WebRequestVerb.Post, url, headers, payload2, "application/json").SendAsync<T>(); } public Task<T> PutAsync<T>(string url, object payload, IDictionary<string, string> headers = null) { string payload2 = ((payload != null) ? IsolatedJsonConvert.SerializeObject(payload, SerializerSettings.DefaultSerializerSettings) : null); return new WebRequest(Configuration, WebRequestVerb.Put, url, headers, payload2, "application/json").SendAsync<T>(); } public Task DeleteAsync(string url, IDictionary<string, string> headers = null) { return new WebRequest(Configuration, WebRequestVerb.Delete, url, headers, null, "application/json").SendAsync(); } public Task<T> DeleteAsync<T>(string url, IDictionary<string, string> headers = null) { return new WebRequest(Configuration, WebRequestVerb.Delete, url, headers, null, "application/json").SendAsync<T>(); } } internal class WebRequest { private readonly WebRequestVerb m_Verb; private readonly string m_Url; private readonly IDictionary<string, string> m_Headers; private readonly string m_Payload; private readonly string m_PayloadContentType; private readonly JsonSerializerSettings m_JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1 }; internal INetworkConfiguration Configuration { get; } internal int Retries { get; private set; } internal WebRequest(INetworkConfiguration configuration, WebRequestVerb verb, string url, IDictionary<string, string> headers, string payload, string payloadContentType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown Configuration = configuration; m_Verb = verb; m_Url = url; m_Headers = headers; m_Payload = payload; m_PayloadContentType = payloadContentType; } internal Task SendAsync() { return SendAttemptAsync(new TaskCompletionSource<string>()); } internal async Task<T> SendAsync<T>() { string value = await SendAttemptAsync(new TaskCompletionSource<string>()); if (string.IsNullOrEmpty(value)) { return default(T); } try { return IsolatedJsonConvert.DeserializeObject<T>(value, m_JsonSerializerSettings); } catch (Exception ex) { string text = "Failed to deserialize object!"; Logger.Log(text + " " + ex.Message); throw new WebRequestException(isNetworkError: false, isServerError: false, isDeserializationError: true, 0L, text); } } private Task<string> SendAttemptAsync(TaskCompletionSource<string> tcs) { try { UnityWebRequest request = Build(); ((AsyncOperation)request.SendWebRequest()).completed += delegate { WebRequest webRequest = this; TaskCompletionSource<string> tcs2 = tcs; long responseCode = request.responseCode; bool isNetworkError = RequestHasNetworkError(request); bool isServerError = RequestHasServerError(request); string error = request.error; DownloadHandler downloadHandler = request.downloadHandler; webRequest.RequestCompleted(tcs2, responseCode, isNetworkError, isServerError, error, (downloadHandler != null) ? downloadHandler.text : null, request.GetResponseHeaders()); request.Dispose(); }; } catch (Exception exception) { tcs.SetException(exception); } return tcs.Task; } internal UnityWebRequest Build() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0088: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ed: Expected O, but got Unknown UnityWebRequest val; switch (m_Verb) { case WebRequestVerb.Post: val = (UnityWebRequest)((!string.IsNullOrEmpty(m_Payload)) ? ((object)new UnityWebRequest(m_Url, "POST") { uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(m_Payload)), downloadHandler = (DownloadHandler)new DownloadHandlerBuffer() }) : ((object)UnityWebRequest.Post(m_Url, string.Empty))); break; case WebRequestVerb.Get: val = UnityWebRequest.Get(m_Url); break; case WebRequestVerb.Put: if (string.IsNullOrEmpty(m_Payload)) { throw new ArgumentException("PUT payload cannot be empty."); } val = new UnityWebRequest(m_Url, "PUT") { uploadHandler = (UploadHandler)new UploadHandlerRaw(Encoding.UTF8.GetBytes(m_Payload)), downloadHandler = (DownloadHandler)new DownloadHandlerBuffer() }; break; case WebRequestVerb.Delete: val = UnityWebRequest.Delete(m_Url); val.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); break; default: throw new ArgumentException("Unknown verb " + m_Verb); } if (!string.IsNullOrEmpty(m_PayloadContentType)) { val.SetRequestHeader("Content-Type", m_PayloadContentType); } if (m_Headers != null) { foreach (KeyValuePair<string, string> header in m_Headers) { val.SetRequestHeader(header.Key, header.Value); } } val.timeout = Configuration.Timeout; return val; } internal void RequestCompleted(TaskCompletionSource<string> tcs, long responseCode, bool isNetworkError, bool isServerError, string errorText, string bodyText, IDictionary<string, string> headers) { if (isNetworkError && Retries < Configuration.Retries) { Logger.LogWarning("Network error detected, retrying..."); Retries++; SendAttemptAsync(tcs); } else if (isNetworkError || isServerError) { string text = ((isServerError && !string.IsNullOrEmpty(bodyText)) ? bodyText : errorText); WebRequestException exception = new WebRequestException(isNetworkError, isServerError, isDeserializationError: false, responseCode, text, headers); tcs.SetException(exception); Logger.LogWarning("Request completed with error: " + text); } else { tcs.SetResult(bodyText); } } private bool RequestHasServerError(UnityWebRequest request) { return request.responseCode >= 400; } private bool RequestHasNetworkError(UnityWebRequest request) { if (request.isNetworkError) { return request.error != "Redirect limit exceeded"; } return false; } } internal class WebRequestException : Exception { public bool NetworkError { get; private set; } public bool DeserializationError { get; private set; } public bool ServerError { get; private set; } public long ResponseCode { get; private set; } public IDictionary<string, string> ResponseHeaders { get; private set; } internal WebRequestException(bool isNetworkError, bool isServerError, bool isDeserializationError, long responseCode, string errorMessage, IDictionary<string, string> responseHeaders = null) : base(errorMessage) { NetworkError = isNetworkError; ServerError = isServerError; DeserializationError = isDeserializationError; ResponseCode = responseCode; ResponseHeaders = responseHeaders; } } internal enum WebRequestVerb { Delete, Get, Head, Options, Patch, Post, Put } internal class AuthenticationCache : IAuthenticationCache, ICache { private ICloudProjectId m_CloudProjectId; private IProfile m_Profile; public string CloudProjectId => m_CloudProjectId.GetCloudProjectId(); public string Profile => m_Profile.Current; private string Prefix => CloudProjectId + "." + Profile + ".unity.services.authentication."; private string OldPrefix => "unity.services.authentication."; public AuthenticationCache(ICloudProjectId cloudProjectId, IProfile profile) { m_CloudProjectId = cloudProjectId; m_Profile = profile; } public bool HasKey(string key) { return PlayerPrefs.HasKey(GetKey(key)); } public void DeleteKey(string key) { PlayerPrefs.DeleteKey(GetKey(key)); } [CanBeNull] public string GetString(string key) { if (!HasKey(key)) { return null; } return PlayerPrefs.GetString(GetKey(key)); } public void SetString(string key, string value) { PlayerPrefs.SetString(GetKey(key), value); PlayerPrefs.Save(); } public void Migrate(string key) { string oldKey = GetOldKey(key); if (PlayerPrefs.HasKey(oldKey)) { PlayerPrefs.SetString(GetKey(key), PlayerPrefs.GetString(oldKey)); PlayerPrefs.DeleteKey(oldKey); } } internal string GetKey(string key) { return Prefix + key; } internal string GetOldKey(string key) { return OldPrefix + key; } } internal interface IAuthenticationCache : ICache { string Profile { get; } string CloudProjectId { get; } void Migrate(string key); } internal interface ICache { bool HasKey(string key); void DeleteKey(string key); void SetString(string key, string value); string GetString(string key); } internal static class IdProviderKeys { internal const string Apple = "apple.com"; internal const string Facebook = "facebook.com"; internal const string AppleGameCenter = "apple-game-center"; internal const string Google = "google.com"; internal const string GooglePlayGames = "google-play-games"; internal const string Oculus = "oculus"; internal const string OpenIDConnect = "oidc-"; internal const string Steam = "steampowered.com"; internal const string UsernamePassword = "usernamepassword"; internal const string Unity = "unity"; } internal static class IsolatedJsonConvert { [DebuggerStepThrough] public static string SerializeObject(object value) { return SerializeObject(value, (Type)null, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static string SerializeObject(object value, Formatting formatting) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return SerializeObject(value, formatting, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static string SerializeObject(object value, params JsonConverter[] converters) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown JsonSerializerSettings val = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : ((JsonSerializerSettings)null)); JsonSerializerSettings settings = val; return SerializeObject(value, (Type)null, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, Formatting formatting, p
BepInEx/plugins/Unity.Services.QoS.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; using Unity.Collections; using Unity.Jobs; using Unity.Networking.QoS; using Unity.Services.Authentication.Internal; using Unity.Services.Core.Configuration.Internal; using Unity.Services.Core.Internal; using Unity.Services.Core.Telemetry.Internal; using Unity.Services.Qos; using Unity.Services.Qos.Apis.QosDiscovery; using Unity.Services.Qos.Http; using Unity.Services.Qos.Internal; using Unity.Services.Qos.Models; using Unity.Services.Qos.QosDiscovery; using Unity.Services.Qos.Runner; using Unity.Services.Qos.Scheduler; using Unity.Services.Qos.V2; using Unity.Services.Qos.V2.Apis.QosDiscovery; using Unity.Services.Qos.V2.Http; using Unity.Services.Qos.V2.Models; using Unity.Services.Qos.V2.QosDiscovery; using Unity.Services.Qos.V2.Scheduler; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Scripting; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AlwaysLinkAssembly] [assembly: InternalsVisibleTo("Unity.Services.Qos.Tests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Unity.Services.QoS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Unity.Services.QoS")] [assembly: AssemblyTitle("Unity.Services.QoS")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } } namespace Unity.Networking.QoS { internal struct InternalQosResult { internal const uint InvalidLatencyValue = uint.MaxValue; internal const float InvalidPacketLossValue = float.MaxValue; internal uint RequestsSent; internal uint ResponsesReceived; internal uint InvalidRequests; internal uint InvalidResponses; internal uint DuplicateResponses; internal FcType FcType; internal byte FcUnits; internal uint AggregateLatencyMs; internal uint AverageLatencyMs { get { if (ResponsesReceived == 0) { return uint.MaxValue; } return AggregateLatencyMs / ResponsesReceived; } } internal float PacketLoss { get { if (RequestsSent != 0 && ResponsesReceived <= RequestsSent) { return 1f - (float)ResponsesReceived / (float)RequestsSent; } return float.MaxValue; } } internal void AddAggregateLatency(uint amountMs) { AggregateLatencyMs += amountMs; } } internal struct QosJob : IQosJob, IJob { private struct InternalQosServer { public readonly NetworkEndPoint RemoteEndpoint; public readonly DateTime BackoffUntilUtc; public readonly int Idx; private int m_FirstIdx; private ushort m_RequestIdentifier; public int FirstIdx { get { return m_FirstIdx; } set { m_FirstIdx = value; } } public ushort RequestIdentifier { get { return m_RequestIdentifier; } set { m_RequestIdentifier = value; } } public bool Duplicate => m_FirstIdx != Idx; public string Address => RemoteEndpoint.Address; public InternalQosServer(NetworkEndPoint remote, DateTime backoffUntilUtc, int idx) { RemoteEndpoint = remote; BackoffUntilUtc = backoffUntilUtc; Idx = idx; m_FirstIdx = idx; m_RequestIdentifier = 0; } } public NativeArray<InternalQosResult> QosResults { get; } internal QosJob(IList<UcgQosServer> qosServers, string title) { this = default(QosJob); throw new NotImplementedException(); } public void Execute() { throw new NotImplementedException(); } public JobHandle Schedule<T>(JobHandle dependsOn = default(JobHandle)) where T : struct, IJob { throw new NotImplementedException(); } public void Dispose() { throw new NotImplementedException(); } } internal enum NetworkFamily { Invalid = 0, Ipv4 = 2, Ipv6 = 23 } internal struct NetworkEndPoint { internal string Address { get { throw new NotImplementedException(); } } } internal static class QosHelper { private const ulong WSAEWOULDBLOCK = 10035uL; private const ulong WSAETIMEDOUT = 10060uL; private const ulong EAGAIN_EWOULDBLOCK_1 = 11uL; private const ulong EAGAIN_EWOULDBLOCK_2 = 35uL; internal static bool WouldBlock(ulong errorcode) { if (errorcode != 10035 && errorcode != 10060 && errorcode != 11) { return errorcode == 35; } return true; } internal static bool ExpiredUtc(DateTime timeUtc) { return DateTime.UtcNow > timeUtc; } internal static string Since(DateTime dt) { return $"{(DateTime.UtcNow - dt).TotalMilliseconds:F0}ms"; } } internal class QosRequest { private const int MinPacketLen = 15; private const int MaxPacketLen = 1500; private const byte RequestMagic = 89; private const int ConstructedPacketLen = 14; private byte m_Magic = 89; private byte m_VerAndFlow; private byte m_TitleLen; private byte[] m_Title; private byte m_Sequence; private ushort m_Identifier; private ulong m_Timestamp; private ushort m_PacketLength = 14; internal byte Magic => m_Magic; internal byte Version => (byte)((m_VerAndFlow >> 4) & 0xF); internal byte FlowControl => (byte)(m_VerAndFlow & 0xF); internal byte[] Title { get { return m_Title; } set { if (15 + value.Length > 1500) { throw new ArgumentException($"Encoded title would make the QosPacket have size {15 + value.Length}. Max size is {1500}."); } m_Title = value; m_TitleLen = (byte)(m_Title.Length + 1); m_PacketLength = (ushort)(14 + m_Title.Length); } } internal byte Sequence { get { return m_Sequence; } set { m_Sequence = value; } } internal ushort Identifier { get { return m_Identifier; } set { m_Identifier = value; } } internal ulong Timestamp { get { return m_Timestamp; } set { m_Timestamp = value; } } internal int Length => m_PacketLength; internal (uint, int) Send(IntPtr socketHandle, NetworkEndPoint endPoint, DateTime expireTimeUtc) { throw new NotImplementedException(); } } internal enum FcType { None, Throttle, Ban } internal class QosResponse { private const int MinPacketLen = 13; private const int MaxPacketLen = 1500; private const byte ResponseMagic = 149; private const byte ResponseVersion = 0; private byte m_Magic; private byte m_VerAndFlow; private byte m_Sequence; private ushort m_Identifier; private ulong m_Timestamp; private int m_LatencyMs; private ushort m_PacketLength; internal byte Magic => m_Magic; internal byte Version => (byte)((m_VerAndFlow >> 4) & 0xF); internal byte FlowControl => (byte)(m_VerAndFlow & 0xF); internal byte Sequence => m_Sequence; internal ushort Identifier => m_Identifier; internal ulong Timestamp => m_Timestamp; internal ushort Length => m_PacketLength; internal int LatencyMs => m_LatencyMs; internal (int received, int errorCode) Recv(IntPtr socketHandle, bool wait, DateTime expireTimeUtc, ref NetworkEndPoint endPoint) { throw new NotImplementedException(); } internal void Deserialize(IntPtr msgData) { throw new NotImplementedException(); } internal bool Verify(uint maxSequence, ref string error) { if (Length < 13) { error = $"response is too small got {Length} bytes min expected {13} bytes"; return false; } if (Magic != 149) { error = $"response contains an invalid signature 0x{Magic:X} expected 0x{(byte)149:X}"; return false; } if (Version != 0) { error = $"response contains an invalid version {Version} expected {(byte)0}"; return false; } if (Sequence > maxSequence) { error = $"response contains an invalid sequence {Sequence} max expected {maxSequence}"; return false; } return true; } internal (FcType type, byte units) ParseFlowControl() { if (FlowControl == 0) { return (type: FcType.None, units: 0); } int num = (((FlowControl & 8) == 0) ? 1 : 2); byte b = (byte)(FlowControl & 7); if (num == 2) { b++; } return (type: (FcType)num, units: b); } } [Serializable] internal struct UcgQosServer { internal string regionid; internal string ipv4; internal string ipv6; internal ushort port; [NonSerialized] [HideInInspector] internal DateTime BackoffUntilUtc; public override string ToString() { if (!string.IsNullOrEmpty(ipv6)) { return $"[{ipv6}]:{port}, {regionid}, {BackoffUntilUtc}"; } if (!string.IsNullOrEmpty(ipv4)) { return $"{ipv4}:{port}, {regionid}, {BackoffUntilUtc}"; } return ""; } } } namespace Unity.Services.Core { public static class UnityServicesExtensions { public static IQosService GetQosService(this IUnityServices unityServices) { return unityServices.GetService<IQosService>(); } } } namespace Unity.Services.Qos { internal class Configuration { public string BasePath; public int? RequestTimeout; public int? NumberOfRetries; public IDictionary<string, string> Headers; public Configuration(string basePath, int? requestTimeout, int? numRetries, IDictionary<string, string> headers) { BasePath = basePath; RequestTimeout = requestTimeout; NumberOfRetries = numRetries; if (headers == null) { Headers = headers; } else { Headers = new Dictionary<string, string>(headers); } } public static Configuration MergeConfigurations(Configuration a, Configuration b) { if (a == null || b == null) { return a ?? b; } Configuration configuration = new Configuration(a.BasePath, a.RequestTimeout, a.NumberOfRetries, a.Headers); if (configuration.BasePath == null) { configuration.BasePath = b.BasePath; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (b.Headers != null) { foreach (KeyValuePair<string, string> header in b.Headers) { dictionary[header.Key] = header.Value; } } if (configuration.Headers != null) { foreach (KeyValuePair<string, string> header2 in configuration.Headers) { dictionary[header2.Key] = header2.Value; } } configuration.Headers = dictionary; configuration.RequestTimeout = configuration.RequestTimeout ?? b.RequestTimeout; configuration.NumberOfRetries = configuration.NumberOfRetries ?? b.NumberOfRetries; return configuration; } } internal class QosResults : IQosResults, IServiceComponent { private WrappedQosService _qosService; internal QosResults(WrappedQosService qosService) { _qosService = qosService; } public Task<IList<QosResult>> GetSortedQosResultsAsync(string service, IList<string> regions) { return _qosService.GetSortedInternalQosResultsAsync(service, regions); } } internal class Response { public Dictionary<string, string> Headers { get; } public long Status { get; set; } public Response(Unity.Services.Qos.Http.HttpClientResponse httpResponse) { Headers = httpResponse.Headers; Status = httpResponse.StatusCode; } } internal class Response<T> : Response { public T Result { get; } public Response(Unity.Services.Qos.Http.HttpClientResponse httpResponse, T result) : base(httpResponse) { Result = result; } } internal class QosPackageInitializer : IInitializablePackageV2, IInitializablePackage { private const string k_CloudEnvironmentKey = "com.unity.services.core.cloud-environment"; private const string k_PackageName = "com.unity.services.qos"; private const string k_StagingEnvironment = "staging"; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] internal static void InitializeOnLoad() { new QosPackageInitializer().Register(CorePackageRegistry.Instance); } public void Register(CorePackageRegistry registry) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) CoreRegistration val = registry.Register<QosPackageInitializer>(this); val = ((CoreRegistration)(ref val)).DependsOn<IAccessToken>(); val = ((CoreRegistration)(ref val)).DependsOn<IMetricsFactory>(); val = ((CoreRegistration)(ref val)).DependsOn<IProjectConfiguration>(); val = ((CoreRegistration)(ref val)).ProvidesComponent<IQosResults>(); ((CoreRegistration)(ref val)).ProvidesComponent<IQosServiceComponent>(); } internal void Register(CoreRegistry registry) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) CoreRegistration val = registry.RegisterPackage<QosPackageInitializer>(this); val = ((CoreRegistration)(ref val)).DependsOn<IAccessToken>(); val = ((CoreRegistration)(ref val)).DependsOn<IMetricsFactory>(); val = ((CoreRegistration)(ref val)).DependsOn<IProjectConfiguration>(); val = ((CoreRegistration)(ref val)).ProvidesComponent<IQosResults>(); ((CoreRegistration)(ref val)).ProvidesComponent<IQosServiceComponent>(); } public Task Initialize(CoreRegistry registry) { QosService.Instance = InitializeService(registry); return Task.CompletedTask; } public Task InitializeInstanceAsync(CoreRegistry registry) { InitializeService(registry); return Task.CompletedTask; } private IQosService InitializeService(CoreRegistry registry) { IProjectConfiguration serviceComponent = registry.GetServiceComponent<IProjectConfiguration>(); IAccessToken serviceComponent2 = registry.GetServiceComponent<IAccessToken>(); IMetrics metrics = registry.GetServiceComponent<IMetricsFactory>().Create("com.unity.services.qos"); Unity.Services.Qos.Http.HttpClient httpClient = new Unity.Services.Qos.Http.HttpClient(); InternalQosDiscoveryService internalQosDiscoveryService = new InternalQosDiscoveryService(GetHost(serviceComponent), httpClient, serviceComponent2); Unity.Services.Qos.V2.Http.HttpClient httpClient2 = new Unity.Services.Qos.V2.Http.HttpClient(); Unity.Services.Qos.V2.Configuration configuration = new Unity.Services.Qos.V2.Configuration(GetHost(serviceComponent), 10, 4, null); WrappedQosService wrappedQosService = new WrappedQosService(qosDiscoveryApiClientV2: new Unity.Services.Qos.V2.Apis.QosDiscovery.QosDiscoveryApiClient(httpClient2, serviceComponent2, configuration), qosDiscoveryApiClient: internalQosDiscoveryService.QosDiscoveryApi, qosRunner: new BaselibQosRunner(), accessToken: serviceComponent2, metrics: metrics); registry.RegisterService<IQosService>((IQosService)wrappedQosService); registry.RegisterServiceComponent<IQosResults>((IQosResults)(object)new QosResults(wrappedQosService)); registry.RegisterServiceComponent<IQosServiceComponent>((IQosServiceComponent)new QosServiceComponent(wrappedQosService)); return wrappedQosService; } private string GetHost(IProjectConfiguration projectConfiguration) { if (((projectConfiguration != null) ? projectConfiguration.GetString("com.unity.services.core.cloud-environment", (string)null) : null) == "staging") { return "https://qos-discovery-stg.services.api.unity.com"; } return "https://qos-discovery.services.api.unity.com"; } } internal class InternalQosDiscoveryService { private const int RequestTimeout = 10; private const int NumRetries = 4; public Unity.Services.Qos.Apis.QosDiscovery.IQosDiscoveryApiClient QosDiscoveryApi { get; set; } public Configuration Configuration { get; set; } internal InternalQosDiscoveryService(string host, Unity.Services.Qos.Http.HttpClient httpClient, IAccessToken accessToken = null) { Configuration = new Configuration(host, 10, 4, null); QosDiscoveryApi = new Unity.Services.Qos.Apis.QosDiscovery.QosDiscoveryApiClient(httpClient, accessToken, Configuration); } } public static class QosService { public static IQosService Instance { get; internal set; } } public interface IQosService { Task<IList<IQosResult>> GetSortedQosResultsAsync(string service, IList<string> regions); Task<IList<IQosAnnotatedResult>> GetSortedRelayQosResultsAsync(IList<string> regions); Task<IList<IQosAnnotatedResult>> GetSortedMultiplayQosResultsAsync(IList<string> fleet); Task<IList<Unity.Services.Qos.V2.Models.QosServer>> GetAllServersAsync(); Task<IList<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)>> GetQosResultsAsync(IList<Unity.Services.Qos.V2.Models.QosServer> servers); } public interface IQosMeasurements { int AverageLatencyMs { get; } float PacketLossPercent { get; } } public interface IQosResult { string Region { get; } int AverageLatencyMs { get; } float PacketLossPercent { get; } } public interface IQosAnnotatedResult : IQosResult { Dictionary<string, List<string>> Annotations { get; } } public interface IQosServiceComponent : IServiceComponent { IQosService Service { get; } } internal class QosServiceComponent : IQosServiceComponent, IServiceComponent { public IQosService Service { get; } internal QosServiceComponent(IQosService qos) { Service = qos; } } internal class WrappedQosService : IQosService { private const string ResultLatencyMetricName = "qos_result_latency_ms"; private const string ResultPacketLossMetricName = "qos_result_packet_loss"; private const string MetricServiceNameLabelName = "qos_service_name"; private const string MetricServiceRegionLabelName = "qos_service_region"; private const string MetricClientCountryLabelName = "qos_client_country"; private const string MetricClientRegionLabelName = "qos_client_region"; private const string MetricClientBestResultLabelName = "qos_best_result"; private const string MetricClientBestResultLabelTrueValue = "true"; private Unity.Services.Qos.Apis.QosDiscovery.IQosDiscoveryApiClient _qosDiscoveryApiClient; private Unity.Services.Qos.V2.Apis.QosDiscovery.IQosDiscoveryApiClient _qosDiscoveryApiClientV2; private IQosRunner _qosRunner; private IAccessToken _accessToken; private IMetrics _metrics; private string _latestCountryForTelemetry; private string _latestRegionForTelemetry; private string _getAllServersEtag = ""; private IList<Unity.Services.Qos.V2.Models.QosServer> _getAllServersCached; internal WrappedQosService(Unity.Services.Qos.Apis.QosDiscovery.IQosDiscoveryApiClient qosDiscoveryApiClient, Unity.Services.Qos.V2.Apis.QosDiscovery.IQosDiscoveryApiClient qosDiscoveryApiClientV2, IQosRunner qosRunner, IAccessToken accessToken, IMetrics metrics) { _qosDiscoveryApiClient = qosDiscoveryApiClient; _qosDiscoveryApiClientV2 = qosDiscoveryApiClientV2; _qosRunner = qosRunner; _accessToken = accessToken; _metrics = metrics; } public async Task<IList<IQosResult>> GetSortedQosResultsAsync(string service, IList<string> regions) { return (await GetSortedInternalQosResultsAsync(service, regions)).Select(MapToPublicQosResult).ToList(); } internal async Task<IList<QosResult>> GetSortedInternalQosResultsAsync(string service, IList<string> regions) { throw new UnsupportedEditorVersionException("QoS SDK does not support this version of Unity, please upgrade to 2020.3.34f1+, 2021.3.2f1+, 2022.2.0a10+, or newer."); } private List<QosResult> SortResults(IList<QosResult> results) { return (from q in results orderby q.AverageLatencyMs, q.PacketLossPercent select q).ToList(); } public async Task<IList<IQosAnnotatedResult>> GetSortedRelayQosResultsAsync(IList<string> regions) { return await GetSortedInternalServiceQosResultsAsync("relay", regions, null); } public async Task<IList<IQosAnnotatedResult>> GetSortedMultiplayQosResultsAsync(IList<string> fleet) { return await GetSortedInternalServiceQosResultsAsync("multiplay", null, fleet); } public async Task<IList<Unity.Services.Qos.V2.Models.QosServer>> GetAllServersAsync() { GetAllServersRequest request = new GetAllServersRequest(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(_getAllServersEtag)) { dictionary.Add("If-None-Match", _getAllServersEtag); } Unity.Services.Qos.V2.Configuration operationConfiguration = new Unity.Services.Qos.V2.Configuration(null, null, null, dictionary); try { Unity.Services.Qos.V2.Response<Unity.Services.Qos.V2.Models.QosServersResponseBody> response = await _qosDiscoveryApiClientV2.GetAllServersAsync(request, operationConfiguration); response.Headers.TryGetValue("ETag", out _getAllServersEtag); _getAllServersCached = response.Result.Data.Servers; response.Headers.TryGetValue("X-Client-Country", out _latestCountryForTelemetry); response.Headers.TryGetValue("X-Client-Region", out _latestRegionForTelemetry); } catch (Unity.Services.Qos.V2.Http.HttpException ex) { if (304 == ex.Response.StatusCode) { return _getAllServersCached; } throw; } return _getAllServersCached; } public async Task<IList<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)>> GetQosResultsAsync(IList<Unity.Services.Qos.V2.Models.QosServer> servers) { List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)> list = await _qosRunner.MeasureQosV2Async(servers); SendResultsMetricsV2(list); return list; } private void SendResultsMetricsV2(IReadOnlyCollection<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)> qosResults) { SendResultsMetricsV2ForService(qosResults, (Unity.Services.Qos.V2.Models.QosServer qs) => qs.Annotations.RelayRegionId, "relay"); SendResultsMetricsV2ForService(qosResults, (Unity.Services.Qos.V2.Models.QosServer qs) => qs.Annotations.MultiplayRegionId, "multiplay"); } private void SendResultsMetricsV2ForService(IReadOnlyCollection<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)> allResults, Func<Unity.Services.Qos.V2.Models.QosServer, List<string>> regionGetter, string service) { List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)> list = (from t in allResults where regionGetter(t.Item1) != null && regionGetter(t.Item1).Count > 0 orderby t.Item2.AverageLatencyMs, t.Item2.PacketLossPercent select t).ToList(); for (int num = 0; num < list.Count; num++) { (Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements) tuple = list[num]; SendResultMetrics(service, _latestCountryForTelemetry, _latestRegionForTelemetry, regionGetter(tuple.Item1)[0], tuple.Item2.AverageLatencyMs, tuple.Item2.PacketLossPercent, num == 0); } } internal async Task<IList<IQosAnnotatedResult>> GetSortedInternalServiceQosResultsAsync(string service, IList<string> regions, IList<string> fleet) { throw new UnsupportedEditorVersionException("QoS SDK does not support this version of Unity, please upgrade to 2020.3.34f1+, 2021.3.2f1+, 2022.2.0a10+, or newer."); } private List<IQosAnnotatedResult> SortServiceResults(IList<QosAnnotatedResult> results) { return (from q in (from q in results where q.AverageLatencyMs != int.MaxValue && (double)q.PacketLossPercent >= 0.0 && (double)q.PacketLossPercent < 1.0 group q by q.Region).Select((Func<IGrouping<string, QosAnnotatedResult>, IQosAnnotatedResult>)((IGrouping<string, QosAnnotatedResult> q) => new QosResult(q.Key, (int)Math.Round(q.Select((QosAnnotatedResult x) => x.AverageLatencyMs).Average()), q.Select((QosAnnotatedResult x) => x.PacketLossPercent).Average(), q.Select((QosAnnotatedResult x) => x.Annotations).First()))).ToList() orderby q.AverageLatencyMs, q.PacketLossPercent select q).ToList(); } private void SendResultsMetrics(IList<QosResult> sortedResults, string service, Response discoveryResponse) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) discoveryResponse.Headers.TryGetValue("X-Client-Country", out var value); discoveryResponse.Headers.TryGetValue("X-Client-Region", out var value2); for (int i = 0; i < sortedResults.Count; i++) { QosResult val = sortedResults[i]; SendResultMetrics(service, value, value2, val.Region, val.AverageLatencyMs, val.PacketLossPercent, i == 0); } } private void SendResultsMetrics(IList<IQosResult> sortedResults, string service, Response discoveryResponse) { discoveryResponse.Headers.TryGetValue("X-Client-Country", out var value); discoveryResponse.Headers.TryGetValue("X-Client-Region", out var value2); for (int i = 0; i < sortedResults.Count; i++) { IQosResult qosResult = sortedResults[i]; SendResultMetrics(service, value, value2, qosResult.Region, qosResult.AverageLatencyMs, qosResult.PacketLossPercent, i == 0); } } private void SendResultMetrics(string service, string clientCountry, string clientRegion, string region, int averageLatencyMs, float packetLossPercent, bool isBest) { IDictionary<string, string> dictionary = new Dictionary<string, string>(); dictionary.Add("qos_service_name", service); dictionary.Add("qos_service_region", region); if (!string.IsNullOrEmpty(clientCountry)) { dictionary.Add("qos_client_country", clientCountry); } if (!string.IsNullOrEmpty(clientRegion)) { dictionary.Add("qos_client_region", clientRegion); } if (isBest) { dictionary.Add("qos_best_result", "true"); } _metrics.SendHistogramMetric("qos_result_latency_ms", (double)averageLatencyMs, dictionary); _metrics.SendHistogramMetric("qos_result_packet_loss", (double)packetLossPercent, dictionary); } private IQosResult MapToPublicQosResult(QosResult internalQosResult) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new QosResult(internalQosResult.Region, internalQosResult.AverageLatencyMs, internalQosResult.PacketLossPercent); } } internal class QosResult : IQosAnnotatedResult, IQosResult { public string Region { get; } public int AverageLatencyMs { get; } public float PacketLossPercent { get; } public Dictionary<string, List<string>> Annotations { get; } public QosResult(string region, int averageLatencyMs, float packetLossPercent, Dictionary<string, List<string>> annotations = null) { Region = region; AverageLatencyMs = averageLatencyMs; PacketLossPercent = packetLossPercent; Annotations = annotations ?? new Dictionary<string, List<string>>(); } } internal class UnsupportedEditorVersionException : Exception { public UnsupportedEditorVersionException() { } public UnsupportedEditorVersionException(string message) : base(message) { } } } namespace Unity.Services.Qos.V2 { internal class Configuration { public string BasePath; public int? RequestTimeout; public int? NumberOfRetries; public IDictionary<string, string> Headers; public Configuration(string basePath, int? requestTimeout, int? numRetries, IDictionary<string, string> headers) { BasePath = basePath; RequestTimeout = requestTimeout; NumberOfRetries = numRetries; if (headers == null) { Headers = new Dictionary<string, string>(); } else { Headers = new Dictionary<string, string>(headers); } } public static Configuration MergeConfigurations(Configuration a, Configuration b) { if (a == null || b == null) { return a ?? b; } Configuration configuration = new Configuration(a.BasePath, a.RequestTimeout, a.NumberOfRetries, a.Headers); if (configuration.BasePath == null) { configuration.BasePath = b.BasePath; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (b.Headers != null) { foreach (KeyValuePair<string, string> header in b.Headers) { dictionary[header.Key] = header.Value; } } if (configuration.Headers != null) { foreach (KeyValuePair<string, string> header2 in configuration.Headers) { dictionary[header2.Key] = header2.Value; } } configuration.Headers = dictionary; configuration.RequestTimeout = configuration.RequestTimeout ?? b.RequestTimeout; configuration.NumberOfRetries = configuration.NumberOfRetries ?? b.NumberOfRetries; return configuration; } } internal class Response { public Dictionary<string, string> Headers { get; } public long Status { get; set; } public Response(Unity.Services.Qos.V2.Http.HttpClientResponse httpResponse) { Headers = httpResponse.Headers; Status = httpResponse.StatusCode; } } internal class Response<T> : Response { public T Result { get; } public Response(Unity.Services.Qos.V2.Http.HttpClientResponse httpResponse, T result) : base(httpResponse) { Result = result; } } } namespace Unity.Services.Qos.V2.Scheduler { internal static class EngineStateHelper { public static bool IsPlaying; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { IsPlaying = Application.isPlaying; } } internal static class ThreadHelper { private static SynchronizationContext _unitySynchronizationContext; private static TaskScheduler _taskScheduler; private static int _mainThreadId; public static SynchronizationContext SynchronizationContext => _unitySynchronizationContext; public static TaskScheduler TaskScheduler => _taskScheduler; public static int MainThreadId => _mainThreadId; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { _unitySynchronizationContext = SynchronizationContext.Current; _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); _mainThreadId = Thread.CurrentThread.ManagedThreadId; } } } namespace Unity.Services.Qos.V2.Models { [Preserve] [DataContract(Name = "ErrorResponseBody")] internal class ErrorResponseBody { [Preserve] [DataMember(Name = "type", IsRequired = true, EmitDefaultValue = true)] public string Type { get; } [Preserve] [DataMember(Name = "title", IsRequired = true, EmitDefaultValue = true)] public string Title { get; } [Preserve] [DataMember(Name = "status", IsRequired = true, EmitDefaultValue = true)] public int Status { get; } [Preserve] [DataMember(Name = "code", IsRequired = true, EmitDefaultValue = true)] public int Code { get; } [Preserve] [DataMember(Name = "detail", IsRequired = true, EmitDefaultValue = true)] public string Detail { get; } [Preserve] [DataMember(Name = "instance", EmitDefaultValue = false)] public string Instance { get; } [Preserve] [DataMember(Name = "details", EmitDefaultValue = false)] public List<Unity.Services.Qos.V2.Http.IDeserializable> Details { get; } [Preserve] public ErrorResponseBody(string type, string title, int status, int code, string detail, string instance = null, List<object> details = null) { Type = type; Title = title; Status = status; Code = code; Detail = detail; Instance = instance; Details = Unity.Services.Qos.V2.Http.JsonObject.GetNewJsonObjectResponse(details); } internal string SerializeAsPathParam() { string text = ""; if (Type != null) { text = text + "type," + Type + ","; } if (Title != null) { text = text + "title," + Title + ","; } text = text + "status," + Status + ","; text = text + "code," + Code + ","; if (Detail != null) { text = text + "detail," + Detail + ","; } if (Instance != null) { text = text + "instance," + Instance + ","; } if (Details != null) { text = text + "details," + Details.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Type != null) { string value = Type.ToString(); dictionary.Add("type", value); } if (Title != null) { string value2 = Title.ToString(); dictionary.Add("title", value2); } string value3 = Status.ToString(); dictionary.Add("status", value3); string value4 = Code.ToString(); dictionary.Add("code", value4); if (Detail != null) { string value5 = Detail.ToString(); dictionary.Add("detail", value5); } if (Instance != null) { string value6 = Instance.ToString(); dictionary.Add("instance", value6); } if (Details != null) { string value7 = Details.ToString(); dictionary.Add("details", value7); } return dictionary; } } internal interface IOneOf { Type Type { get; } object Value { get; } } [Preserve] [DataContract(Name = "QosServer")] public class QosServer { [Preserve] [DataMember(Name = "endpoints", IsRequired = true, EmitDefaultValue = true)] public List<string> Endpoints { get; } [Preserve] [DataMember(Name = "annotations", IsRequired = true, EmitDefaultValue = true)] public QosServerAnnotations Annotations { get; } [Preserve] public QosServer(List<string> endpoints, QosServerAnnotations annotations) { Endpoints = endpoints; Annotations = annotations; } internal string SerializeAsPathParam() { string text = ""; if (Endpoints != null) { text = text + "endpoints," + Endpoints.ToString() + ","; } if (Annotations != null) { text = text + "annotations," + Annotations.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Endpoints != null) { string value = Endpoints.ToString(); dictionary.Add("endpoints", value); } return dictionary; } } [Preserve] [DataContract(Name = "QosServerAnnotations")] public class QosServerAnnotations { [Preserve] [DataMember(Name = "projectId", EmitDefaultValue = false)] public List<string> ProjectId { get; } [Preserve] [DataMember(Name = "environmentId", EmitDefaultValue = false)] public List<string> EnvironmentId { get; } [Preserve] [DataMember(Name = "relayRegionId", EmitDefaultValue = false)] public List<string> RelayRegionId { get; } [Preserve] [DataMember(Name = "multiplayRegionId", EmitDefaultValue = false)] public List<string> MultiplayRegionId { get; } [Preserve] [DataMember(Name = "multiplayFleetId", EmitDefaultValue = false)] public List<string> MultiplayFleetId { get; } [Preserve] [DataMember(Name = "matchmakerQueueName", EmitDefaultValue = false)] public List<string> MatchmakerQueueName { get; } [Preserve] [DataMember(Name = "matchmakerPoolId", EmitDefaultValue = false)] public List<string> MatchmakerPoolId { get; } [Preserve] public QosServerAnnotations(List<string> projectId = null, List<string> environmentId = null, List<string> relayRegionId = null, List<string> multiplayRegionId = null, List<string> multiplayFleetId = null, List<string> matchmakerQueueName = null, List<string> matchmakerPoolId = null) { ProjectId = projectId; EnvironmentId = environmentId; RelayRegionId = relayRegionId; MultiplayRegionId = multiplayRegionId; MultiplayFleetId = multiplayFleetId; MatchmakerQueueName = matchmakerQueueName; MatchmakerPoolId = matchmakerPoolId; } internal string SerializeAsPathParam() { string text = ""; if (ProjectId != null) { text = text + "projectId," + ProjectId.ToString() + ","; } if (EnvironmentId != null) { text = text + "environmentId," + EnvironmentId.ToString() + ","; } if (RelayRegionId != null) { text = text + "relayRegionId," + RelayRegionId.ToString() + ","; } if (MultiplayRegionId != null) { text = text + "multiplayRegionId," + MultiplayRegionId.ToString() + ","; } if (MultiplayFleetId != null) { text = text + "multiplayFleetId," + MultiplayFleetId.ToString() + ","; } if (MatchmakerQueueName != null) { text = text + "matchmakerQueueName," + MatchmakerQueueName.ToString() + ","; } if (MatchmakerPoolId != null) { text = text + "matchmakerPoolId," + MatchmakerPoolId.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (ProjectId != null) { string value = ProjectId.ToString(); dictionary.Add("projectId", value); } if (EnvironmentId != null) { string value2 = EnvironmentId.ToString(); dictionary.Add("environmentId", value2); } if (RelayRegionId != null) { string value3 = RelayRegionId.ToString(); dictionary.Add("relayRegionId", value3); } if (MultiplayRegionId != null) { string value4 = MultiplayRegionId.ToString(); dictionary.Add("multiplayRegionId", value4); } if (MultiplayFleetId != null) { string value5 = MultiplayFleetId.ToString(); dictionary.Add("multiplayFleetId", value5); } if (MatchmakerQueueName != null) { string value6 = MatchmakerQueueName.ToString(); dictionary.Add("matchmakerQueueName", value6); } if (MatchmakerPoolId != null) { string value7 = MatchmakerPoolId.ToString(); dictionary.Add("matchmakerPoolId", value7); } return dictionary; } } [Preserve] [DataContract(Name = "QosServersList")] internal class QosServersList { [Preserve] [DataMember(Name = "servers", IsRequired = true, EmitDefaultValue = true)] public List<QosServer> Servers { get; } [Preserve] public QosServersList(List<QosServer> servers) { Servers = servers; } internal string SerializeAsPathParam() { string text = ""; if (Servers != null) { text = text + "servers," + Servers.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "QosServersResponseBody")] internal class QosServersResponseBody { [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public QosServersList Data { get; } [Preserve] public QosServersResponseBody(QosServersList data) { Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } } namespace Unity.Services.Qos.V2.Http { internal abstract class BaseApiClient { protected readonly IHttpClient HttpClient; public BaseApiClient(IHttpClient httpClient) { HttpClient = httpClient ?? new HttpClient(); } } [Serializable] internal class DeserializationException : Exception { public DeserializationException() { } public DeserializationException(string message) : base(message) { } private DeserializationException(string message, Exception inner) : base(message, inner) { } } internal enum MissingMemberHandling { Error, Ignore } internal class DeserializationSettings { public MissingMemberHandling MissingMemberHandling; } internal class HttpClient : IHttpClient { public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout); } public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout, boundary); } private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, byte[] body, IDictionary<string, string> headers, int requestTimeout) { return await CreateHttpClientResponse(method, url, body, headers, requestTimeout); } private async Task<HttpClientResponse> CreateHttpClientResponse(string method, string url, byte[] body, IDictionary<string, string> headers, int requestTimeout) { return await (await Task.Factory.StartNew(async delegate { UnityWebRequest request = new UnityWebRequest(url, method); try { foreach (KeyValuePair<string, string> header in headers) { request.SetRequestHeader(header.Key, header.Value); } request.timeout = requestTimeout; if (body != null && (method == "POST" || method == "PUT" || method == "PATCH")) { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); } request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return await SendWebRequest(request); } finally { ((IDisposable)request)?.Dispose(); } }, CancellationToken.None, TaskCreationOptions.None, Unity.Services.Qos.V2.Scheduler.ThreadHelper.TaskScheduler)); } private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, List<IMultipartFormSection> body, IDictionary<string, string> headers, int requestTimeout, string boundary = null) { return await (await Task.Factory.StartNew(async delegate { byte[] boundary2 = (string.IsNullOrEmpty(boundary) ? UnityWebRequest.GenerateBoundary() : Encoding.Default.GetBytes(boundary)); UnityWebRequest val = new UnityWebRequest(url, method); foreach (KeyValuePair<string, string> header in headers) { val.SetRequestHeader(header.Key, header.Value); } val.timeout = requestTimeout; val = SetupMultipartRequest(val, body, boundary2); val.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return await SendWebRequest(val); }, CancellationToken.None, TaskCreationOptions.None, Unity.Services.Qos.V2.Scheduler.ThreadHelper.TaskScheduler)); } private static UnityWebRequest SetupMultipartRequest(UnityWebRequest request, List<IMultipartFormSection> multipartFormSections, byte[] boundary) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown byte[] array = null; if (multipartFormSections != null && multipartFormSections.Count != 0) { array = UnityWebRequest.SerializeFormSections(multipartFormSections, boundary); } UploadHandler val = (UploadHandler)new UploadHandlerRaw(array); val.contentType = "multipart/form-data; boundary=" + Encoding.UTF8.GetString(boundary, 0, boundary.Length); request.uploadHandler = val; request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return request; } private UnityWebRequestAsyncOperation SendWebRequest(UnityWebRequest request) { return request.SendWebRequest(); } } internal class HttpClientResponse { public Dictionary<string, string> Headers { get; } public long StatusCode { get; } public bool IsHttpError { get; } public bool IsNetworkError { get; } public byte[] Data { get; } public string ErrorMessage { get; } public HttpClientResponse(Dictionary<string, string> headers, long statusCode, bool isHttpError, bool isNetworkError, byte[] data, string errorMessage) { Headers = headers; StatusCode = statusCode; IsHttpError = isHttpError; IsNetworkError = isNetworkError; Data = data; ErrorMessage = errorMessage; } } [Serializable] [Preserve] internal class HttpException : Exception { [Preserve] public HttpClientResponse Response; [Preserve] public HttpException() { } [Preserve] public HttpException(string message) : base(message) { } [Preserve] public HttpException(string message, Exception inner) : base(message, inner) { } [Preserve] public HttpException(HttpClientResponse response) : base($"({response.StatusCode}) {response.ErrorMessage}") { Response = response; } } [Serializable] [Preserve] internal class HttpException<T> : HttpException { [Preserve] public T ActualError; [Preserve] public HttpException() { } [Preserve] public HttpException(string message) : base(message) { } [Preserve] public HttpException(string message, Exception inner) : base(message, inner) { } [Preserve] public HttpException(HttpClientResponse response, T actualError) : base(response) { ActualError = actualError; } } [Preserve] [JsonConverter(typeof(JsonObjectConverter))] internal interface IDeserializable { string GetAsString(); T GetAs<T>(DeserializationSettings deserializationSettings = null); } internal interface IHttpClient { Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout); Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null); } internal static class IsolatedJsonConvert { [DebuggerStepThrough] public static string SerializeObject(object value) { return SerializeObject(value, null, null); } [DebuggerStepThrough] public static string SerializeObject(object value, JsonSerializerSettings settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, Type type, JsonSerializerSettings settings) { JsonSerializer jsonSerializer = JsonSerializer.Create(settings); return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); JsonTextWriter val = new JsonTextWriter((TextWriter)stringWriter); try { ((JsonWriter)val).Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize((JsonWriter)(object)val, value, type); } finally { ((IDisposable)val)?.Dispose(); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object DeserializeObject(string value, Type type) { return DeserializeObject(value, type, null); } [DebuggerStepThrough] public static T DeserializeObject<T>(string value, JsonSerializerSettings settings) { return (T)DeserializeObject(value, typeof(T), settings); } public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown JsonSerializer val = JsonSerializer.Create(settings); JsonTextReader val2 = new JsonTextReader((TextReader)new StringReader(value)); try { return val.Deserialize((JsonReader)(object)val2, type); } finally { ((IDisposable)val2)?.Dispose(); } } } internal static class JsonHelpers { [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] internal static void RegisterTypesForAOT() { AotHelper.EnsureType<StringEnumConverter>(); AotHelper.EnsureType<JsonObjectConverter>(); } internal static bool TryParseJson<T>(this string @this, out T result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown bool success = true; JsonSerializerSettings settings = new JsonSerializerSettings { Error = delegate(object sender, ErrorEventArgs args) { success = false; args.ErrorContext.Handled = true; }, MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; result = IsolatedJsonConvert.DeserializeObject<T>(@this, settings); return success; } } [Preserve] [JsonConverter(typeof(JsonObjectConverter))] internal class JsonObject : IDeserializable { [Preserve] internal object obj; [Preserve] internal JsonObject(object obj) { this.obj = obj; } public string GetAsString() { try { if (obj == null) { return ""; } if (obj.GetType() == typeof(string)) { return obj.ToString(); } return IsolatedJsonConvert.SerializeObject(obj); } catch (Exception) { throw new InvalidOperationException("Failed to convert JsonObject to string."); } } public T GetAs<T>(DeserializationSettings deserializationSettings = null) { //IL_003d: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown deserializationSettings = deserializationSettings ?? new DeserializationSettings(); JsonSerializerSettings settings = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)(deserializationSettings.MissingMemberHandling == MissingMemberHandling.Error) }; try { return IsolatedJsonConvert.DeserializeObject<T>(IsolatedJsonConvert.SerializeObject(obj), settings); } catch (JsonSerializationException ex) { throw new DeserializationException(((Exception)ex).Message); } catch (Exception) { throw new DeserializationException("Unable to deserialize object."); } } public T GetAs<T>() { return GetAs<T>(null); } internal static IDeserializable GetNewJsonObjectResponse(object o) { return new JsonObject(o); } internal static List<IDeserializable> GetNewJsonObjectResponse(List<object> o) { return o?.Select((Func<object, IDeserializable>)((object v) => new JsonObject(v))).ToList(); } internal static List<List<IDeserializable>> GetNewJsonObjectResponse(List<List<object>> o) { return o?.Select((List<object> l) => ((IEnumerable<object>)l).Select((Func<object, IDeserializable>)((object v) => (v != null) ? new JsonObject(v) : null)).ToList()).ToList(); } internal static Dictionary<string, IDeserializable> GetNewJsonObjectResponse(Dictionary<string, object> o) { return o?.ToDictionary((Func<KeyValuePair<string, object>, string>)((KeyValuePair<string, object> kv) => kv.Key), (Func<KeyValuePair<string, object>, IDeserializable>)((KeyValuePair<string, object> kv) => new JsonObject(kv.Value))); } internal static Dictionary<string, List<IDeserializable>> GetNewJsonObjectResponse(Dictionary<string, List<object>> o) { return o?.ToDictionary((KeyValuePair<string, List<object>> kv) => kv.Key, (KeyValuePair<string, List<object>> kv) => GetNewJsonObjectResponse(kv.Value)); } } [Preserve] internal class JsonObjectConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { JsonObject jsonObject = (JsonObject)value; if (jsonObject.obj == null) { writer.WriteNull(); } else { JToken.FromObject(jsonObject.obj, serializer).WriteTo(writer, Array.Empty<JsonConverter>()); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType != 11) { if (reader.Value != null) { return new JsonObject(reader.Value); } try { return new JsonObject(JObject.Load(reader)); } catch (JsonReaderException) { return new JsonObject(JArray.Load(reader)); } } return new JsonObject(null); } public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } } [Preserve] internal class JsonObjectCollectionConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { object obj = value; Type type = value.GetType(); if (type == typeof(Dictionary<string, IDeserializable>)) { obj = (Dictionary<string, IDeserializable>)value; } else if (type == typeof(List<IDeserializable>)) { obj = (List<IDeserializable>)value; } else if (type == typeof(List<List<IDeserializable>>)) { obj = (List<List<IDeserializable>>)value; } if (obj == null) { writer.WriteNull(); } else { JToken.FromObject(obj).WriteTo(writer, Array.Empty<JsonConverter>()); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType != 11) { List<object> obj = (List<object>)reader.Value; List<JsonObject> list = new List<JsonObject>(); { foreach (object item in obj) { list.Add(new JsonObject(item)); } return list; } } return null; } public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } } [Serializable] internal class ResponseDeserializationException : Exception { public HttpClientResponse response; public ResponseDeserializationException() { } public ResponseDeserializationException(string message) : base(message) { } private ResponseDeserializationException(Exception inner, string message) : base(message, inner) { } public ResponseDeserializationException(HttpClientResponse httpClientResponse) : base("Unable to Deserialize Http Client Response") { response = httpClientResponse; } public ResponseDeserializationException(HttpClientResponse httpClientResponse, string message) : base(message) { response = httpClientResponse; } public ResponseDeserializationException(HttpClientResponse httpClientResponse, Exception inner, string message) : base(message, inner) { response = httpClientResponse; } } internal static class ResponseHandler { private static List<IDeserializable> DeserializeListOfJsonObjects(List<object> objectList) { List<IDeserializable> list = new List<IDeserializable>(); foreach (object @object in objectList) { list.Add(new JsonObject(@object)); } return list; } public static T TryDeserializeResponse<T>(HttpClientResponse response) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown JsonSerializerSettings settings = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; try { return IsolatedJsonConvert.DeserializeObject<T>(GetDeserializedJson(response.Data), settings); } catch (Exception ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } } public static object TryDeserializeResponse(HttpClientResponse response, Type type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown JsonSerializerSettings settings = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; try { return IsolatedJsonConvert.DeserializeObject(GetDeserializedJson(response.Data), type, settings); } catch (Exception ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } } private static string GetDeserializedJson(byte[] data) { if (data != null) { return Encoding.UTF8.GetString(data); } return null; } public static void HandleAsyncResponse(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap) { if (statusCodeToTypeMap.ContainsKey(response.StatusCode.ToString())) { Type type = statusCodeToTypeMap[response.StatusCode.ToString()]; if ((type != null && response.IsHttpError) || response.IsNetworkError) { if (typeof(Unity.Services.Qos.V2.Models.IOneOf).IsAssignableFrom(type)) { throw CreateOneOfException(response, type); } throw CreateHttpException(response, type); } return; } throw new HttpException(response); } private static HttpException CreateOneOfException(HttpClientResponse response, Type responseType) { try { object obj = TryDeserializeResponse(response, responseType); return CreateHttpException(response, ((Unity.Services.Qos.V2.Models.IOneOf)obj).Type); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.InnerException.GetType() == typeof(MissingFieldException)) { throw new ResponseDeserializationException(response, ex2.InnerException, "Discriminator field not found in the parsed json response."); } if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } private static HttpException CreateHttpException(HttpClientResponse response, Type responseType) { Type type = typeof(HttpException<>).MakeGenericType(responseType); try { if (responseType == typeof(Stream)) { object obj = ((response.Data == null) ? new MemoryStream() : new MemoryStream(response.Data)); return (HttpException)Activator.CreateInstance(type, response, obj); } object obj2 = TryDeserializeResponse(response, responseType); return (HttpException)Activator.CreateInstance(type, response, obj2); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } public static T HandleAsyncResponse<T>(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap) where T : class { HandleAsyncResponse(response, statusCodeToTypeMap); try { if (statusCodeToTypeMap[response.StatusCode.ToString()] == typeof(string)) { return ((response.Data == null) ? null : Encoding.UTF8.GetString(response.Data)) as T; } if (statusCodeToTypeMap[response.StatusCode.ToString()] == typeof(Stream)) { return ((response.Data == null) ? new MemoryStream() : new MemoryStream(response.Data)) as T; } return TryDeserializeResponse<T>(response); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } } internal static class UnityWebRequestHelpers { public static TaskAwaiter<HttpClientResponse> GetAwaiter(this UnityWebRequestAsyncOperation asyncOp) { TaskCompletionSource<HttpClientResponse> tcs = new TaskCompletionSource<HttpClientResponse>(); ((AsyncOperation)asyncOp).completed += delegate(AsyncOperation obj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown HttpClientResponse result = CreateHttpClientResponse((UnityWebRequestAsyncOperation)obj); tcs.SetResult(result); }; return tcs.Task.GetAwaiter(); } internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse) { UnityWebRequest webRequest = unityResponse.webRequest; return new HttpClientResponse(webRequest.GetResponseHeaders(), webRequest.responseCode, webRequest.isHttpError, webRequest.isNetworkError, webRequest.downloadHandler.data, webRequest.error); } } } namespace Unity.Services.Qos.V2.Helpers { internal static class AsyncOpRetry { public static AsyncOpRetry<T> FromCreateAsync<T>(Func<int, T> op) { return AsyncOpRetry<T>.FromCreateAsync(op); } } internal class AsyncOpRetry<T> { private uint MaxRetries { get; set; } = 4u; private float JitterMagnitude { get; set; } = 1f; private float DelayScale { get; set; } = 1f; private float MaxDelayTime { get; set; } = 8f; private Func<int, T> CreateOperation { get; set; } private Func<T, bool> RetryCondition { get; set; } private Action<T> OnComplete { get; set; } private AsyncOpRetry(Func<int, T> createAsyncOp) { CreateOperation = createAsyncOp; } private static float AddJitter(float number, float magnitude) { return number + Random.value * magnitude; } private static float Pow2(float exponent, float scale) { return (float)(Math.Pow(2.0, exponent) * (double)scale); } private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale, float jitterMagnitude) { return Math.Min(AddJitter(Pow2(attemptNumber, delayScale), jitterMagnitude), maxDelayTime); } public static AsyncOpRetry<T> FromCreateAsync(Func<int, T> op) { return new AsyncOpRetry<T>(op); } public AsyncOpRetry<T> WithRetryCondition(Func<T, bool> shouldRetry) { RetryCondition = shouldRetry; return this; } public AsyncOpRetry<T> WhenComplete(Action<T> onComplete) { OnComplete = onComplete; return this; } public IEnumerator Run() { T asyncOp = default(T); int attempt = 0; while (attempt <= MaxRetries) { asyncOp = CreateOperation(attempt + 1); yield return asyncOp; Func<T, bool> retryCondition = RetryCondition; if (retryCondition != null && !retryCondition(asyncOp)) { break; } float num = CalculateDelay(attempt, MaxDelayTime, DelayScale, JitterMagnitude); yield return (object)new WaitForSecondsRealtime(num); int num2 = attempt + 1; attempt = num2; } OnComplete?.Invoke(asyncOp); } } } namespace Unity.Services.Qos.V2.ErrorMitigation { internal interface IRetryPolicyProvider { IRetryPolicy<T> ForOperation<T>(Func<int, Task<T>> operation); IRetryPolicy<T> ForOperation<T>(Func<Task<T>> operation); } internal interface IRetryPolicy<T> { IRetryPolicy<T> WithJitterMagnitude(float magnitude); IRetryPolicy<T> WithDelayScale(float scale); IRetryPolicy<T> WithMaxDelayTime(float time); IRetryPolicy<T> WithRetryCondition(Func<T, Task<bool>> shouldRetry); IRetryPolicy<T> UptoMaximumRetries(uint amount); IRetryPolicy<T> HandleException<TException>() where TException : Exception; IRetryPolicy<T> HandleException<TException>(Func<TException, bool> condition) where TException : Exception; Task<T> RunAsync(RetryPolicyConfig retryPolicyConfig = null); } internal class RetryPolicyProvider : IRetryPolicyProvider { public IRetryPolicy<T> ForOperation<T>(Func<int, Task<T>> operation) { return RetryPolicy<T>.ForOperation(operation); } public IRetryPolicy<T> ForOperation<T>(Func<Task<T>> operation) { return RetryPolicy<T>.ForOperation(operation); } } internal class RetryPolicy<T> : IRetryPolicy<T> { private RetryPolicyConfig _retryPolicyConfig = new RetryPolicyConfig(); private Func<int, Task<T>> CreateOperation { get; set; } private Func<T, Task<bool>> RetryCondition { get; set; } private RetryPolicy(Func<int, Task<T>> createAsyncOp) { CreateOperation = createAsyncOp; } private RetryPolicy(Func<Task<T>> createAsyncOp) { CreateOperation = (int _) => createAsyncOp(); } private static float AddJitter(float number, float magnitude) { return number + Random.value * magnitude; } private static float Pow2(float exponent, float scale) { return (float)(Math.Pow(2.0, exponent) * (double)scale); } private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale, float jitterMagnitude) { return Math.Min(AddJitter(Pow2(attemptNumber, delayScale), jitterMagnitude), maxDelayTime); } public IRetryPolicy<T> WithJitterMagnitude(float magnitude) { _retryPolicyConfig.JitterMagnitude = magnitude; return this; } public IRetryPolicy<T> WithDelayScale(float scale) { _retryPolicyConfig.DelayScale = scale; return this; } public IRetryPolicy<T> WithMaxDelayTime(float time) { _retryPolicyConfig.MaxDelayTime = time; return this; } public static RetryPolicy<T> ForOperation(Func<int, Task<T>> operation) { return new RetryPolicy<T>(operation); } public static RetryPolicy<T> ForOperation(Func<Task<T>> operation) { return new RetryPolicy<T>(operation); } public IRetryPolicy<T> WithRetryCondition(Func<T, Task<bool>> shouldRetry) { RetryCondition = shouldRetry; return this; } public IRetryPolicy<T> UptoMaximumRetries(uint amount) { _retryPolicyConfig.MaxRetries = amount; return this; } public IRetryPolicy<T> HandleException<TException>() where TException : Exception { _retryPolicyConfig.HandleException<TException>(); return this; } public IRetryPolicy<T> HandleException<TException>(Func<TException, bool> condition) where TException : Exception { _retryPolicyConfig.HandleException(condition); return this; } public async Task<T> RunAsync(RetryPolicyConfig retryPolicyConfig = null) { T opResult = default(T); if (retryPolicyConfig == null) { retryPolicyConfig = _retryPolicyConfig; } int attempt = 0; while (attempt <= retryPolicyConfig.MaxRetries) { try { opResult = await CreateOperation(attempt + 1); } catch (Exception e) { if (!retryPolicyConfig.IsHandledException(e)) { throw; } } if (RetryCondition != null && opResult != null) { if (!(await RetryCondition(opResult))) { break; } } else if (opResult != null) { break; } await Task.Delay((int)(CalculateDelay(attempt, retryPolicyConfig.MaxDelayTime, retryPolicyConfig.DelayScale, retryPolicyConfig.JitterMagnitude) * 1000f)); int num = attempt + 1; attempt = num; } return opResult; } } internal delegate Exception ExceptionPredicate(Exception ex); internal class RetryPolicyConfig { private float _jitterMagnitude = 1f; private float _delayScale = 1f; private float _maxDelayTime = 8f; private List<ExceptionPredicate> _exceptionsToHandle = new List<ExceptionPredicate>(); public uint MaxRetries { get; set; } = 4u; public float JitterMagnitude { get { return _jitterMagnitude; } set { _jitterMagnitude = Mathf.Clamp(value, 0.001f, 1f); } } public float DelayScale { get { return _delayScale; } set { _delayScale = Mathf.Clamp(value, 0.05f, 1f); } } public float MaxDelayTime { get { return _maxDelayTime; } set { _maxDelayTime = Mathf.Clamp(value, 0.1f, 60f); } } public void HandleException<TException>() where TException : Exception { _exceptionsToHandle.Add((Exception exception) => (!(exception is TException)) ? null : exception); } public void HandleException<TException>(Func<TException, bool> condition) where TException : Exception { _exceptionsToHandle.Add((Exception exception) => (!(exception is TException arg) || !condition(arg)) ? null : exception); } public bool IsHandledException(Exception e) { if (_exceptionsToHandle != null) { foreach (ExceptionPredicate item in _exceptionsToHandle) { if (item(e) == e) { return true; } } } return false; } } internal class StatusCodePolicyConfig { private IDictionary<long, bool> _statusCodesToHandleDict = new Dictionary<long, bool> { { 408L, true }, { 429L, true }, { 502L, true }, { 503L, true }, { 504L, true } }; public void HandleStatusCode(long code) { if (_statusCodesToHandleDict.ContainsKey(code)) { _statusCodesToHandleDict[code] = true; } else { _statusCodesToHandleDict.Add(new KeyValuePair<long, bool>(code, value: true)); } } public void DontHandleStatusCode(long code) { if (_statusCodesToHandleDict.ContainsKey(code)) { _statusCodesToHandleDict[code] = false; } else { _statusCodesToHandleDict.Add(new KeyValuePair<long, bool>(code, value: false)); } } public void Clear() { _statusCodesToHandleDict.Clear(); } public bool IsHandledStatusCode(long code) { return _statusCodesToHandleDict.Contains(new KeyValuePair<long, bool>(code, value: true)); } } } namespace Unity.Services.Qos.V2.QosDiscovery { internal static class JsonSerialization { public static byte[] Serialize<T>(T obj) { return Encoding.UTF8.GetBytes(SerializeToString(obj)); } public static string SerializeToString<T>(T obj) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return IsolatedJsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 }); } } [Preserve] internal class QosDiscoveryApiBaseRequest { private static readonly Regex JsonRegex = new Regex("application\\/json(;\\s)?((charset=utf8|q=[0-1]\\.\\d)(\\s)?)*"); [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, string key, string value) { key = UnityWebRequest.EscapeURL(key); value = UnityWebRequest.EscapeURL(value); queryParams.Add(key + "=" + value); return queryParams; } [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, string key, List<string> values, string style, bool explode) { if (explode) { foreach (string value in values) { string text = UnityWebRequest.EscapeURL(value); queryParams.Add(UnityWebRequest.EscapeURL(key) + "=" + text); } } else { string text2 = UnityWebRequest.EscapeURL(key) + "="; foreach (string value2 in values) { text2 = text2 + UnityWebRequest.EscapeURL(value2) + ","; } text2 = text2.Remove(text2.Length - 1); queryParams.Add(text2); } return queryParams; } [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, Dictionary<string, string> modelVars) { foreach (string key in modelVars.Keys) { string text = UnityWebRequest.EscapeURL(modelVars[key]); queryParams.Add(UnityWebRequest.EscapeURL(key) + "=" + text); } return queryParams; } [Preserve] public List<string> AddParamsToQueryParams<T>(List<string> queryParams, string key, T value) { if (queryParams == null) { queryParams = new List<string>(); } key = UnityWebRequest.EscapeURL(key); string text = UnityWebRequest.EscapeURL(value.ToString()); queryParams.Add(key + "=" + text); return queryParams; } [Preserve] public string GetPathParamString(List<string> pathParam) { string text = ""; foreach (string item in pathParam) { text = text + UnityWebRequest.EscapeURL(item) + ","; } return text.Remove(text.Length - 1); } public byte[] ConstructBody(Stream stream) { if (stream != null) { using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } return null; } public byte[] ConstructBody(string s) { return Encoding.UTF8.GetBytes(s); } public byte[] ConstructBody(object o) { return JsonSerialization.Serialize(o); } public string GenerateAcceptHeader(string[] accepts) { if (accepts.Length == 0) { return null; } for (int i = 0; i < accepts.Length; i++) { if (string.Equals(accepts[i], "application/json", StringComparison.OrdinalIgnoreCase)) { return "application/json"; } } return string.Join(", ", accepts); } public string GenerateContentTypeHeader(string[] contentTypes) { if (contentTypes.Length == 0) { return null; } for (int i = 0; i < contentTypes.Length; i++) { if (!string.IsNullOrWhiteSpace(contentTypes[i]) && JsonRegex.IsMatch(contentTypes[i])) { return contentTypes[i]; } } return contentTypes[0]; } public IMultipartFormSection GenerateMultipartFormFileSection(string paramName, FileStream stream, string contentType) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return (IMultipartFormSection)new MultipartFormFileSection(paramName, ConstructBody(stream), GetFileName(stream.Name), contentType); } public IMultipartFormSection GenerateMultipartFormFileSection(string paramName, Stream stream, string contentType) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return (IMultipartFormSection)new MultipartFormFileSection(paramName, ConstructBody(stream), Guid.NewGuid().ToString(), contentType); } private string GetFileName(string filePath) { return Path.GetFileName(filePath); } } [Preserve] internal class GetAllServersRequest : QosDiscoveryApiBaseRequest { private string PathAndQueryParams; [Preserve] public Guid XRequestId { get; } [Preserve] public string XUser { get; } [Preserve] public string XUserType { get; } [Preserve] public GetAllServersRequest(Guid xRequestId = default(Guid), string xUser = null, string xUserType = null) { XRequestId = xRequestId; XUser = xUser; XUserType = xUserType; PathAndQueryParams = "/v2alpha1/servers"; } public string ConstructUrl(string requestBasePath) { return requestBasePath + PathAndQueryParams; } public byte[] ConstructBody() { return null; } public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken, Configuration operationConfiguration = null) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(accessToken.AccessToken)) { dictionary.Add("authorization", "Bearer " + accessToken.AccessToken); } dictionary.Add("Unity-Client-Version", Application.unityVersion); dictionary.Add("Unity-Client-Mode", Unity.Services.Qos.V2.Scheduler.EngineStateHelper.IsPlaying ? "play" : "edit"); string[] contentTypes = new string[0]; string[] accepts = new string[2] { "application/json", "application/problem+json" }; string value = GenerateAcceptHeader(accepts); if (!string.IsNullOrEmpty(value)) { dictionary.Add("Accept", value); } string text = "GET"; string value2 = GenerateContentTypeHeader(contentTypes); if (!string.IsNullOrEmpty(value2)) { dictionary.Add("Content-Type", value2); } else if (text == "POST" || text == "PATCH") { dictionary.Add("Content-Type", "application/json"); } if (!XRequestId.Equals(default(Guid))) { dictionary.Add("X-Request-Id", XRequestId.ToString()); } if (!string.IsNullOrEmpty(XUser)) { dictionary.Add("X-User", XUser); } if (!string.IsNullOrEmpty(XUserType)) { dictionary.Add("X-User-Type", XUserType); } if (operationConfiguration != null && operationConfiguration.Headers != null) { foreach (KeyValuePair<string, string> header in operationConfiguration.Headers) { dictionary[header.Key] = header.Value; } } return dictionary; } } } namespace Unity.Services.Qos.V2.Apis.QosDiscovery { internal interface IQosDiscoveryApiClient { Task<Response<Unity.Services.Qos.V2.Models.QosServersResponseBody>> GetAllServersAsync(GetAllServersRequest request, Configuration operationConfiguration = null); } internal class QosDiscoveryApiClient : Unity.Services.Qos.V2.Http.BaseApiClient, IQosDiscoveryApiClient { private IAccessToken _accessToken; private const int _baseTimeout = 10; private Configuration _configuration; public Configuration Configuration { get { Configuration b = new Configuration("http://localhost", 10, 4, null); return Configuration.MergeConfigurations(_configuration, b); } set { _configuration = value; } } public QosDiscoveryApiClient(Unity.Services.Qos.V2.Http.IHttpClient httpClient, IAccessToken accessToken, Configuration configuration = null) : base(httpClient) { _configuration = configuration; _accessToken = accessToken; } public async Task<Response<Unity.Services.Qos.V2.Models.QosServersResponseBody>> GetAllServersAsync(GetAllServersRequest request, Configuration operationConfiguration = null) { Dictionary<string, Type> statusCodeToTypeMap = new Dictionary<string, Type> { { "200", typeof(Unity.Services.Qos.V2.Models.QosServersResponseBody) }, { "400", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) }, { "401", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) }, { "403", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) }, { "429", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) }, { "500", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) }, { "503", typeof(Unity.Services.Qos.V2.Models.ErrorResponseBody) } }; Configuration configuration = Configuration.MergeConfigurations(operationConfiguration, Configuration); Unity.Services.Qos.V2.Http.HttpClientResponse obj = await HttpClient.MakeRequestAsync("GET", request.ConstructUrl(configuration.BasePath), request.ConstructBody(), request.ConstructHeaders(_accessToken, configuration), configuration.RequestTimeout ?? 10); Unity.Services.Qos.V2.Models.QosServersResponseBody result = Unity.Services.Qos.V2.Http.ResponseHandler.HandleAsyncResponse<Unity.Services.Qos.V2.Models.QosServersResponseBody>(obj, statusCodeToTypeMap); return new Response<Unity.Services.Qos.V2.Models.QosServersResponseBody>(obj, result); } } } namespace Unity.Services.Qos.Scheduler { internal static class EngineStateHelper { public static bool IsPlaying; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { IsPlaying = Application.isPlaying; } } internal static class ThreadHelper { private static SynchronizationContext _unitySynchronizationContext; private static TaskScheduler _taskScheduler; private static int _mainThreadId; public static SynchronizationContext SynchronizationContext => _unitySynchronizationContext; public static TaskScheduler TaskScheduler => _taskScheduler; public static int MainThreadId => _mainThreadId; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { _unitySynchronizationContext = SynchronizationContext.Current; _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); _mainThreadId = Thread.CurrentThread.ManagedThreadId; } } } namespace Unity.Services.Qos.Runner { internal delegate IQosJob QosJobProvider(IList<UcgQosServer> servers, string title); internal delegate Task<IPAddress[]> DnsResolver(string host); internal class BaselibQosRunner : IQosRunner { internal struct QosMeasurementImpl : IQosMeasurements { public int AverageLatencyMs { get; } public float PacketLossPercent { get; } public QosMeasurementImpl(int averageLatencyMs, float packetLossPercent) { AverageLatencyMs = averageLatencyMs; PacketLossPercent = packetLossPercent; } } private QosJobProvider _qosJobProvider = (IList<UcgQosServer> servers, string title) => new QosJob(servers, title); private DnsResolver _dnsResolver = Dns.GetHostAddressesAsync; public BaselibQosRunner(QosJobProvider qosJobProvider = null, DnsResolver dnsResolver = null) { if (qosJobProvider != null) { _qosJobProvider = qosJobProvider; } if (dnsResolver != null) { _dnsResolver = dnsResolver; } } public async Task<List<QosResult>> MeasureQosAsync(IList<Unity.Services.Qos.Models.QosServer> servers) { List<UcgQosServer> convertedServers = (from s in await Task.WhenAll(servers.Select(ToUcgFormat)) where s.HasValue select s.Value).ToList(); List<QosResult> results = new List<QosResult>(); IQosJob qosJob = await RunQosJob(convertedServers); if (servers.Count() == ((IEnumerable<InternalQosResult>)(object)qosJob.QosResults).Count()) { results = ParseResults((IEnumerable<InternalQosResult>)(object)qosJob.QosResults, servers); } qosJob.Dispose(); qosJob.QosResults.Dispose(); return results; } public async Task<List<QosAnnotatedResult>> MeasureQosAsync(IList<QosServiceServer> servers) { List<UcgQosServer> convertedServers = (from s in await Task.WhenAll(servers.Select(ToUcgFormat)) where s.HasValue select s.Value).ToList(); List<QosAnnotatedResult> results = new List<QosAnnotatedResult>(); IQosJob qosJob = await RunQosJob(convertedServers); if (servers.Count() == ((IEnumerable<InternalQosResult>)(object)qosJob.QosResults).Count()) { results = ParseResults((IEnumerable<InternalQosResult>)(object)qosJob.QosResults, servers); } qosJob.Dispose(); qosJob.QosResults.Dispose(); return results; } public async Task<List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)>> MeasureQosV2Async(IList<Unity.Services.Qos.V2.Models.QosServer> servers) { List<Unity.Services.Qos.Models.QosServer> servers2 = servers.ToList().ConvertAll((Unity.Services.Qos.V2.Models.QosServer q) => new Unity.Services.Qos.Models.QosServer(q.Endpoints, "unused")); List<QosResult> list = await MeasureQosAsync(servers2); List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)> list2 = new List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)>(list.Count); if (list.Count == 0 || list.Count != servers.Count) { return list2; } List<QosMeasurementImpl> list3 = list.ConvertAll((QosResult qr) => new QosMeasurementImpl(qr.AverageLatencyMs, qr.PacketLossPercent)); for (int num = 0; num < servers.Count; num++) { list2.Add((servers[num], list3[num])); } return list2; } private async Task<IQosJob> RunQosJob(List<UcgQosServer> convertedServers) { string title = "QoS request"; IQosJob job = _qosJobProvider(convertedServers, title); JobHandle handle = job.Schedule<QosJob>(default(JobHandle)); while (!((JobHandle)(ref handle)).IsCompleted) { await Task.Yield(); } ((JobHandle)(ref handle)).Complete(); return job; } private async Task<UcgQosServer?> ToUcgFormat(Unity.Services.Qos.Models.QosServer server) { string serverEndpoint = server.Endpoints[0]; string region = server.Region; return await ToUcgFormat(serverEndpoint, region); } private async Task<UcgQosServer?> ToUcgFormat(QosServiceServer server) { string serverEndpoint = server.Endpoints[0]; string region = server.Region; return await ToUcgFormat(serverEndpoint, region); } private async Task<UcgQosServer?> ToUcgFormat(string serverEndpoint, string serverRegion) { if (!Uri.TryCreate("udp://" + serverEndpoint, UriKind.Absolute, out Uri uri)) { Debug.LogError((object)("Could not create address from endpoint: '" + serverEndpoint + "'")); return null; } if (uri.Port == -1) { Debug.LogError((object)("Missing or invalid port in endpoint: '" + serverEndpoint + "'")); return null; } IPAddress[] array = await _dnsResolver(uri.Host); if (array.Length == 0) { Debug.LogError((object)("No addresses could be resolved for host " + uri.Host)); return null; } IPAddress iPAddress = array[0]; UcgQosServer value = new UcgQosServer { regionid = serverRegion, ipv6 = null, port = Convert.ToUInt16(uri.Port), BackoffUntilUtc = default(DateTime) }; if (iPAddress.AddressFamily == AddressFamily.InterNetwork) { value.ipv4 = iPAddress.ToString(); } else if (iPAddress.AddressFamily == AddressFamily.InterNetworkV6) { value.ipv6 = iPAddress.ToString(); } return value; } private static List<QosResult> ParseResults(IEnumerable<InternalQosResult> ucgResults, IEnumerable<Unity.Services.Qos.Models.QosServer> servers) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) List<QosResult> list = new List<QosResult>(); using IEnumerator<Unity.Services.Qos.Models.QosServer> enumerator = servers.GetEnumerator(); foreach (InternalQosResult ucgResult in ucgResults) { enumerator.MoveNext(); if (enumerator.Current == null) { break; } int averageLatencyMs = (int)((ucgResult.AverageLatencyMs > int.MaxValue) ? int.MaxValue : ucgResult.AverageLatencyMs); list.Add(new QosResult { Region = enumerator.Current.Region, AverageLatencyMs = averageLatencyMs, PacketLossPercent = ucgResult.PacketLoss }); } return list; } private static List<QosAnnotatedResult> ParseResults(IEnumerable<InternalQosResult> ucgResults, IEnumerable<QosServiceServer> servers) { List<QosAnnotatedResult> list = new List<QosAnnotatedResult>(); using IEnumerator<QosServiceServer> enumerator = servers.GetEnumerator(); foreach (InternalQosResult ucgResult in ucgResults) { enumerator.MoveNext(); if (enumerator.Current == null) { break; } int averageLatencyMs = (int)((ucgResult.AverageLatencyMs > int.MaxValue) ? int.MaxValue : ucgResult.AverageLatencyMs); list.Add(new QosAnnotatedResult { Region = enumerator.Current.Region, AverageLatencyMs = averageLatencyMs, PacketLossPercent = ucgResult.PacketLoss, Annotations = enumerator.Current.Annotations }); } return list; } } internal interface IQosJob : IJob { NativeArray<InternalQosResult> QosResults { get; } JobHandle Schedule<T>(JobHandle dependsOn = default(JobHandle)) where T : struct, IJob; void Dispose(); } internal interface IQosRunner { Task<List<QosResult>> MeasureQosAsync(IList<Unity.Services.Qos.Models.QosServer> servers); Task<List<QosAnnotatedResult>> MeasureQosAsync(IList<QosServiceServer> servers); Task<List<(Unity.Services.Qos.V2.Models.QosServer, IQosMeasurements)>> MeasureQosV2Async(IList<Unity.Services.Qos.V2.Models.QosServer> servers); } public struct QosAnnotatedResult { public string Region; public int AverageLatencyMs; public float PacketLossPercent; public Dictionary<string, List<string>> Annotations; } } namespace Unity.Services.Qos.Models { [Preserve] [DataContract(Name = "ErrorResponseBody")] internal class ErrorResponseBody { [Preserve] [DataMember(Name = "type", IsRequired = true, EmitDefaultValue = true)] public string Type { get; } [Preserve] [DataMember(Name = "title", IsRequired = true, EmitDefaultValue = true)] public string Title { get; } [Preserve] [DataMember(Name = "status", IsRequired = true, EmitDefaultValue = true)] public int Status { get; } [Preserve] [DataMember(Name = "code", IsRequired = true, EmitDefaultValue = true)] public int Code { get; } [Preserve] [DataMember(Name = "detail", IsRequired = true, EmitDefaultValue = true)] public string Detail { get; } [Preserve] [DataMember(Name = "instance", EmitDefaultValue = false)] public string Instance { get; } [Preserve] [DataMember(Name = "details", EmitDefaultValue = false)] public List<Unity.Services.Qos.Http.IDeserializable> Details { get; } [Preserve] public ErrorResponseBody(string type, string title, int status, int code, string detail, string instance = null, List<object> details = null) { Type = type; Title = title; Status = status; Code = code; Detail = detail; Instance = instance; Details = Unity.Services.Qos.Http.JsonObject.GetNewJsonObjectResponse(details); } internal string SerializeAsPathParam() { string text = ""; if (Type != null) { text = text + "type," + Type + ","; } if (Title != null) { text = text + "title," + Title + ","; } text = text + "status," + Status + ","; text = text + "code," + Code + ","; if (Detail != null) { text = text + "detail," + Detail + ","; } if (Instance != null) { text = text + "instance," + Instance + ","; } if (Details != null) { text = text + "details," + Details.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Type != null) { string value = Type.ToString(); dictionary.Add("type", value); } if (Title != null) { string value2 = Title.ToString(); dictionary.Add("title", value2); } string value3 = Status.ToString(); dictionary.Add("status", value3); string value4 = Code.ToString(); dictionary.Add("code", value4); if (Detail != null) { string value5 = Detail.ToString(); dictionary.Add("detail", value5); } if (Instance != null) { string value6 = Instance.ToString(); dictionary.Add("instance", value6); } if (Details != null) { string value7 = Details.ToString(); dictionary.Add("details", value7); } return dictionary; } } [Preserve] [DataContract(Name = "KeyValuePair")] internal class KeyValuePair { [Preserve] [DataMember(Name = "key", IsRequired = true, EmitDefaultValue = true)] public string Key { get; } [Preserve] [DataMember(Name = "value", IsRequired = true, EmitDefaultValue = true)] public string Value { get; } [Preserve] public KeyValuePair(string key, string value) { Key = key; Value = value; } } internal interface IOneOf { Type Type { get; } object Value { get; } } [Preserve] [DataContract(Name = "QosServer")] internal class QosServer { [Preserve] [DataMember(Name = "endpoints", IsRequired = true, EmitDefaultValue = true)] public List<string> Endpoints { get; } [Preserve] [DataMember(Name = "region", IsRequired = true, EmitDefaultValue = true)] public string Region { get; } [Preserve] [DataMember(Name = "services", EmitDefaultValue = false)] public List<string> Services { get; } [Preserve] public QosServer(List<string> endpoints, string region, List<string> services = null) { Endpoints = endpoints; Region = region; Services = services; } internal string SerializeAsPathParam() { string text = ""; if (Endpoints != null) { text = text + "endpoints," + Endpoints.ToString() + ","; } if (Region != null) { text = text + "region," + Region + ","; } if (Services != null) { text = text + "services," + Services.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Endpoints != null) { string value = Endpoints.ToString(); dictionary.Add("endpoints", value); } if (Region != null) { string value2 = Region.ToString(); dictionary.Add("region", value2); } if (Services != null) { string value3 = Services.ToString(); dictionary.Add("services", value3); } return dictionary; } } [Preserve] [DataContract(Name = "QosServersList")] internal class QosServersList { [Preserve] [DataMember(Name = "servers", IsRequired = true, EmitDefaultValue = true)] public List<QosServer> Servers { get; } [Preserve] public QosServersList(List<QosServer> servers) { Servers = servers; } internal string SerializeAsPathParam() { string text = ""; if (Servers != null) { text = text + "servers," + Servers.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "QosServersResponseBody")] internal class QosServersResponseBody { [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public QosServersList Data { get; } [Preserve] public QosServersResponseBody(QosServersList data) { Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "QosServiceServer")] internal class QosServiceServer { [Preserve] [DataMember(Name = "endpoints", IsRequired = true, EmitDefaultValue = true)] public List<string> Endpoints { get; } [Preserve] [DataMember(Name = "region", IsRequired = true, EmitDefaultValue = true)] public string Region { get; } [Preserve] [DataMember(Name = "annotations", EmitDefaultValue = false)] public Dictionary<string, List<string>> Annotations { get; } [Preserve] public QosServiceServer(List<string> endpoints, string region, Dictionary<string, List<string>> annotations = null) { Endpoints = endpoints; Region = region; Annotations = annotations; } internal string SerializeAsPathParam() { string text = ""; if (Endpoints != null) { text = text + "endpoints," + Endpoints.ToString() + ","; } if (Region != null) { text = text + "region," + Region + ","; } if (Annotations != null) { text = text + "annotations," + Annotations.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Endpoints != null) { string value = Endpoints.ToString(); dictionary.Add("endpoints", value); } if (Region != null) { string value2 = Region.ToString(); dictionary.Add("region", value2); } if (Annotations != null) { string value3 = Annotations.ToString(); dictionary.Add("annotations", value3); } return dictionary; } } [Preserve] [DataContract(Name = "QosServiceServersList")] internal class QosServiceServersList { [Preserve] [DataMember(Name = "servers", IsRequired = true, EmitDefaultValue = true)] public List<QosServiceServer> Servers { get; } [Preserve] public QosServiceServersList(List<QosServiceServer> servers) { Servers = servers; } internal string SerializeAsPathParam() { string text = ""; if (Servers != null) { text = text + "servers," + Servers.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "QosServiceServersResponseBody")] internal class QosServiceServersResponseBody { [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public QosServiceServersList Data { get; } [Preserve] public QosServiceServersResponseBody(QosServiceServersList data) { Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } } namespace Unity.Services.Qos.Http { internal abstract class BaseApiClient { protected readonly IHttpClient HttpClient; public BaseApiClient(IHttpClient httpClient) { HttpClient = httpClient ?? new HttpClient(); } } [Serializable] internal class DeserializationException : Exception { public DeserializationException() { } public DeserializationException(string message) : base(message) { } private DeserializationException(string message, Exception inner) : base(message, inner) { } } internal enum MissingMemberHandling { Error, Ignore } internal class DeserializationSettings { public MissingMemberHandling MissingMemberHandling; } internal class HttpClient : IHttpClient { public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout); } public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout, boundary); } private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, byte[] body, IDictiona
BepInEx/plugins/Unity.Services.Relay.dll
Decompiled 13 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; using Unity.Services.Authentication.Internal; using Unity.Services.Core; using Unity.Services.Core.Configuration.Internal; using Unity.Services.Core.Internal; using Unity.Services.Qos.Internal; using Unity.Services.Relay.Apis.RelayAllocations; using Unity.Services.Relay.Http; using Unity.Services.Relay.Models; using Unity.Services.Relay.RelayAllocations; using Unity.Services.Relay.Scheduler; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Scripting; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("Unity.Services.Relay.Tests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Unity.Services.Relay")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Unity.Services.Relay")] [assembly: AssemblyTitle("Unity.Services.Relay")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } } namespace Unity.Services.Relay { internal class Configuration { public string BasePath; public int? RequestTimeout; public int? NumberOfRetries; public IDictionary<string, string> Headers; public Configuration(string basePath, int? requestTimeout, int? numRetries, IDictionary<string, string> headers) { BasePath = basePath; RequestTimeout = requestTimeout; NumberOfRetries = numRetries; if (headers == null) { Headers = headers; } else { Headers = new Dictionary<string, string>(headers); } } public static Configuration MergeConfigurations(Configuration a, Configuration b) { if (a == null || b == null) { return a ?? b; } Configuration configuration = new Configuration(a.BasePath, a.RequestTimeout, a.NumberOfRetries, a.Headers); if (configuration.BasePath == null) { configuration.BasePath = b.BasePath; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (b.Headers != null) { foreach (KeyValuePair<string, string> header in b.Headers) { dictionary[header.Key] = header.Value; } } if (configuration.Headers != null) { foreach (KeyValuePair<string, string> header2 in configuration.Headers) { dictionary[header2.Key] = header2.Value; } } configuration.Headers = dictionary; configuration.RequestTimeout = configuration.RequestTimeout ?? b.RequestTimeout; configuration.NumberOfRetries = configuration.NumberOfRetries ?? b.NumberOfRetries; return configuration; } } internal class Response { public Dictionary<string, string> Headers { get; } public long Status { get; set; } public Response(HttpClientResponse httpResponse) { Headers = httpResponse.Headers; Status = httpResponse.StatusCode; } } internal class Response<T> : Response { public T Result { get; } public Response(HttpClientResponse httpResponse, T result) : base(httpResponse) { Result = result; } } internal class RelayServiceProvider : IInitializablePackage { [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] private static void Register() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) CoreRegistration val = CoreRegistry.Instance.RegisterPackage<RelayServiceProvider>(new RelayServiceProvider()); ((CoreRegistration)(ref val)).DependsOn<IAccessToken>(); ((CoreRegistration)(ref val)).DependsOn<IProjectConfiguration>(); ((CoreRegistration)(ref val)).DependsOn<IQosResults>(); } public Task Initialize(CoreRegistry registry) { HttpClient httpClient = new HttpClient(); IAccessToken serviceComponent = registry.GetServiceComponent<IAccessToken>(); IProjectConfiguration serviceComponent2 = registry.GetServiceComponent<IProjectConfiguration>(); IQosResults serviceComponent3 = registry.GetServiceComponent<IQosResults>(); if (serviceComponent != null) { RelayServiceSdk.Instance = new InternalRelayService(httpClient, serviceComponent2, serviceComponent, serviceComponent3); } return Task.CompletedTask; } } internal class InternalRelayService : IRelayServiceSdk { private const string k_CloudEnvironmentKey = "com.unity.services.core.cloud-environment"; private const string k_StagingEnvironment = "staging"; public IRelayAllocationsApiClient AllocationsApi { get; set; } public Configuration Configuration { get; set; } public IAccessToken AccessToken { get; set; } public IQosResults QosResults { get; set; } public InternalRelayService(HttpClient httpClient, IProjectConfiguration projectConfiguration = null, IAccessToken accessToken = null, IQosResults qosResults = null) { AllocationsApi = new RelayAllocationsApiClient(httpClient, accessToken); Configuration = new Configuration(GetHost(projectConfiguration), 10, 4, null); AccessToken = accessToken; QosResults = qosResults; } private string GetHost(IProjectConfiguration projectConfiguration) { if (((projectConfiguration != null) ? projectConfiguration.GetString("com.unity.services.core.cloud-environment", (string)null) : null) == "staging") { return "https://relay-allocations-stg.services.api.unity.com"; } return "https://relay-allocations.services.api.unity.com"; } } internal static class RelayServiceSdk { public static IRelayServiceSdk Instance { get; internal set; } } internal interface IRelayServiceSdk { IRelayAllocationsApiClient AllocationsApi { get; set; } Configuration Configuration { get; set; } IAccessToken AccessToken { get; set; } IQosResults QosResults { get; set; } } internal static class ApiErrorExtender { public static RelayExceptionReason GetExceptionReason(this ErrorResponseBody error) { RelayExceptionReason result = RelayExceptionReason.Unknown; if (error.Code != 15000) { if (Enum.IsDefined(typeof(RelayExceptionReason), error.Code)) { result = (RelayExceptionReason)error.Code; } } else if (Enum.IsDefined(typeof(RelayExceptionReason), error.Status)) { result = (RelayExceptionReason)error.Status; } return result; } public static RelayExceptionReason GetExceptionReason(this HttpClientResponse error) { RelayExceptionReason result = RelayExceptionReason.Unknown; if (error.IsHttpError) { int num = (int)error.StatusCode + 15000; if (Enum.IsDefined(typeof(RelayExceptionReason), num)) { result = (RelayExceptionReason)num; } } else if (error.IsNetworkError) { result = RelayExceptionReason.NetworkError; } return result; } public static string GetExceptionMessage(this ErrorResponseBody error) { string text = error.Title + ": " + error.Detail; foreach (Unity.Services.Relay.Models.KeyValuePair item in error.Details ?? new List<Unity.Services.Relay.Models.KeyValuePair>()) { text = text + "\n" + item.Key + ": " + item.Value; } return text; } } public enum RelayExceptionReason { Min = 15000, NoError = 15000, InvalidRequest = 15001, InactiveProject = 15006, RegionNotFound = 15007, AllocationNotFound = 15008, JoinCodeNotFound = 15009, NoSuitableRelay = 15010, InvalidArgument = 15400, Unauthorized = 15401, PaymentRequired = 15402, Forbidden = 15403, EntityNotFound = 15404, MethodNotAllowed = 15405, NotAcceptable = 15406, ProxyAuthenticationRequired = 15407, RequestTimeOut = 15408, Conflict = 15409, Gone = 15410, LengthRequired = 15411, PreconditionFailed = 15412, RequestEntityTooLarge = 15413, RequestUriTooLong = 15414, UnsupportedMediaType = 15415, RangeNotSatisfiable = 15416, ExpectationFailed = 15417, Teapot = 15418, Misdirected = 15421, UnprocessableTransaction = 15422, Locked = 15423, FailedDependency = 15424, TooEarly = 15425, UpgradeRequired = 15426, PreconditionRequired = 15428, RateLimited = 15429, RequestHeaderFieldsTooLarge = 15431, UnavailableForLegalReasons = 15451, InternalServerError = 15500, NotImplemented = 15501, BadGateway = 15502, ServiceUnavailable = 15503, GatewayTimeout = 15504, HttpVersionNotSupported = 15505, VariantAlsoNegotiates = 15506, InsufficientStorage = 15507, LoopDetected = 15508, NotExtended = 15510, NetworkAuthenticationRequired = 15511, NetworkError = 15998, Unknown = 15999, Max = 15999 } public class RelayServiceException : RequestFailedException { public RelayExceptionReason Reason { get; private set; } public ErrorResponseBody ApiError => (((Exception)this).InnerException as HttpException<ErrorResponseBody>)?.ActualError; public RelayServiceException(RelayExceptionReason reason, string message, Exception innerException) : base((int)reason, message, innerException) { Reason = reason; } public RelayServiceException(RelayExceptionReason reason, string message) : base((int)reason, message) { Reason = reason; } public RelayServiceException(long errorCode, string message) : base((int)errorCode, message) { if (Enum.IsDefined(typeof(RelayExceptionReason), errorCode)) { Reason = (RelayExceptionReason)errorCode; } else { Reason = RelayExceptionReason.Unknown; } } public RelayServiceException(Exception innerException) : base(15999, "Unknown Relay Service Exception", innerException) { } } public interface IRelayService { Task<Allocation> CreateAllocationAsync(int maxConnections, string region = null); Task<string> GetJoinCodeAsync(Guid allocationId); Task<JoinAllocation> JoinAllocationAsync(string joinCode); Task<List<Region>> ListRegionsAsync(); } public interface IRelayServiceSDK : IRelayService { } public interface IRelayServiceSDKConfiguration { void SetAllocationsServiceBasePath(string basePath); } public static class RelayService { private static IRelayService service; public static IRelayService Instance { get { if (service != null) { return service; } service = new WrappedRelayService(RelayServiceSdk.Instance ?? throw new InvalidOperationException("Attempting to call Relay Services requires initializing Core Registry. Call 'UnityServices.InitializeAsync' first!")); return service; } } } public static class Relay { public static IRelayServiceSDK Instance => (IRelayServiceSDK)RelayService.Instance; } internal class WrappedRelayService : IRelayService, IRelayServiceSDK, IRelayServiceSDKConfiguration { private const string QosRelayServiceName = "relay"; internal IRelayServiceSdk m_RelayService { get; set; } internal WrappedRelayService(IRelayServiceSdk relayService) { m_RelayService = relayService; } public async Task<Allocation> CreateAllocationAsync(int maxConnections, string region = null) { EnsureSignedIn(); if (maxConnections <= 0) { throw new ArgumentException("Maximum number of connections for an allocation must be greater than 0!"); } if (m_RelayService.QosResults == null) { throw new Exception("Qos component should not be null, check that is is properly initialized."); } if (string.IsNullOrEmpty(region)) { try { List<string> list = (await ListRegionsAsync()).Select((Region r) => r.Id).ToList(); IList<QosResult> list2 = await m_RelayService.QosResults.GetSortedQosResultsAsync("relay", (IList<string>)list); if (list2.Any()) { region = list2[0].Region; Debug.Log((object)("best region is " + region)); } } catch (Exception ex) { Debug.LogWarning((object)("Could not do Qos region selection. Will use default." + Environment.NewLine + "QoS failed due to [" + ex.GetType().Name + "]. Reason: " + ex.Message)); } } try { return (await m_RelayService.AllocationsApi.CreateAllocationAsync(new CreateAllocationRequest(new AllocationRequest(maxConnections, region)), m_RelayService.Configuration)).Result.Data.Allocation; } catch (HttpException<ErrorResponseBody> ex2) { throw new RelayServiceException(ex2.ActualError.GetExceptionReason(), ex2.ActualError.GetExceptionMessage(), ex2); } catch (HttpException ex3) { if (ex3.Response.IsHttpError) { throw new RelayServiceException(ex3.Response.GetExceptionReason(), ex3.Response.ErrorMessage, ex3); } if (ex3.Response.IsNetworkError) { throw new RelayServiceException(RelayExceptionReason.NetworkError, ex3.Response.ErrorMessage); } throw new RequestFailedException(15999, "Something went wrong.", (Exception)ex3); } } public async Task<string> GetJoinCodeAsync(Guid allocationId) { EnsureSignedIn(); if (allocationId == Guid.Empty) { throw new ArgumentNullException("AllocationId cannot be null or empty!"); } try { return (await m_RelayService.AllocationsApi.CreateJoincodeAsync(new CreateJoincodeRequest(new JoinCodeRequest(allocationId)), m_RelayService.Configuration)).Result.Data.JoinCode; } catch (HttpException<ErrorResponseBody> ex) { throw new RelayServiceException(ex.ActualError.GetExceptionReason(), ex.ActualError.GetExceptionMessage(), ex); } catch (HttpException ex2) { if (ex2.Response.IsHttpError) { throw new RelayServiceException(ex2.Response.GetExceptionReason(), ex2.Response.ErrorMessage, ex2); } if (ex2.Response.IsNetworkError) { throw new RelayServiceException(RelayExceptionReason.NetworkError, ex2.Response.ErrorMessage); } throw new RequestFailedException(15999, "Something went wrong.", (Exception)ex2); } } public async Task<JoinAllocation> JoinAllocationAsync(string joinCode) { EnsureSignedIn(); if (string.IsNullOrWhiteSpace(joinCode)) { throw new ArgumentNullException("JoinCode must be non-null, non-empty, and cannot contain only whitespace!"); } try { return (await m_RelayService.AllocationsApi.JoinRelayAsync(new JoinRelayRequest(new JoinRequest(joinCode)), m_RelayService.Configuration)).Result.Data.Allocation; } catch (HttpException<ErrorResponseBody> ex) { throw new RelayServiceException(ex.ActualError.GetExceptionReason(), ex.ActualError.GetExceptionMessage(), ex); } catch (HttpException ex2) { if (ex2.Response.IsHttpError) { throw new RelayServiceException(ex2.Response.GetExceptionReason(), ex2.Response.ErrorMessage, ex2); } if (ex2.Response.IsNetworkError) { throw new RelayServiceException(RelayExceptionReason.NetworkError, ex2.Response.ErrorMessage); } throw new RequestFailedException(15999, "Something went wrong.", (Exception)ex2); } } public async Task<List<Region>> ListRegionsAsync() { EnsureSignedIn(); try { return (await m_RelayService.AllocationsApi.ListRegionsAsync(new ListRegionsRequest(), m_RelayService.Configuration)).Result.Data.Regions; } catch (HttpException<ErrorResponseBody> ex) { throw new RelayServiceException(ex.ActualError.GetExceptionReason(), ex.ActualError.GetExceptionMessage(), ex); } catch (HttpException ex2) { if (ex2.Response.IsHttpError) { throw new RelayServiceException(ex2.Response.GetExceptionReason(), ex2.Response.ErrorMessage, ex2); } if (ex2.Response.IsNetworkError) { throw new RelayServiceException(RelayExceptionReason.NetworkError, ex2.Response.ErrorMessage); } throw new RequestFailedException(15999, "Something went wrong.", (Exception)ex2); } } public void SetAllocationsServiceBasePath(string allocationsBasePath) { m_RelayService.Configuration.BasePath = allocationsBasePath; } private void EnsureSignedIn() { if (m_RelayService.AccessToken.AccessToken == null) { throw new RelayServiceException(RelayExceptionReason.Unauthorized, "You are not signed in to the Authentication Service. Please sign in."); } } } } namespace Unity.Services.Relay.Scheduler { internal static class EngineStateHelper { public static bool IsPlaying; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { IsPlaying = Application.isPlaying; } } public static class GameObjectFactory { public static GameObject CreateCoreSdkGameObject() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0037: Expected O, but got Unknown Random random = new Random(); GameObject val = new GameObject("_SdkCore-" + random.Next(0, int.MaxValue)); val.AddComponent<TaskSchedulerThreaded>(); Object.DontDestroyOnLoad((Object)val); return val; } } public abstract class TaskScheduler : MonoBehaviour { public abstract void ScheduleBackgroundTask(Action task); public abstract bool IsMainThread(); public abstract void ScheduleMainThreadTask(Action task); public void ScheduleOrExecuteOnMain(Action action) { if (IsMainThread()) { action?.Invoke(); } else { ScheduleMainThreadTask(action); } } } public sealed class TaskSchedulerThreaded : TaskScheduler { private Queue<Action> m_mainThreadTaskQueue = new Queue<Action>(); private object m_lock = new object(); private Thread m_mainThread; private void Start() { m_mainThread = Thread.CurrentThread; } public override bool IsMainThread() { return m_mainThread == Thread.CurrentThread; } public override void ScheduleBackgroundTask(Action task) { ThreadPool.QueueUserWorkItem(delegate { task(); }); } public override void ScheduleMainThreadTask(Action task) { lock (m_lock) { m_mainThreadTaskQueue.Enqueue(task); } } private void Update() { Queue<Action> queue = null; lock (m_lock) { queue = new Queue<Action>(m_mainThreadTaskQueue); m_mainThreadTaskQueue.Clear(); } foreach (Action item in queue) { item(); } } } public sealed class TaskSchedulerWebGL : TaskScheduler { private Queue<Action> m_mainThreadTaskQueue = new Queue<Action>(); public override void ScheduleBackgroundTask(Action task) { ScheduleMainThreadTask(task); } public override bool IsMainThread() { return false; } public override void ScheduleMainThreadTask(Action task) { m_mainThreadTaskQueue.Enqueue(task); } private void Update() { ((m_mainThreadTaskQueue.Count > 0) ? m_mainThreadTaskQueue.Dequeue() : null)?.Invoke(); } } internal static class ThreadHelper { private static SynchronizationContext _unitySynchronizationContext; private static System.Threading.Tasks.TaskScheduler _taskScheduler; private static int _mainThreadId; public static SynchronizationContext SynchronizationContext => _unitySynchronizationContext; public static System.Threading.Tasks.TaskScheduler TaskScheduler => _taskScheduler; public static int MainThreadId => _mainThreadId; [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] public static void Init() { _unitySynchronizationContext = SynchronizationContext.Current; _taskScheduler = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext(); _mainThreadId = Thread.CurrentThread.ManagedThreadId; } } } namespace Unity.Services.Relay.Models { [Preserve] [DataContract(Name = "AllocateResponseBody")] public class AllocateResponseBody { [Preserve] [DataMember(Name = "meta", IsRequired = true, EmitDefaultValue = true)] public ResponseMeta Meta { get; } [Preserve] [DataMember(Name = "links", EmitDefaultValue = false)] public ResponseLinks Links { get; } [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public AllocationData Data { get; } [Preserve] public AllocateResponseBody(ResponseMeta meta, AllocationData data, ResponseLinks links = null) { Meta = meta; Links = links; Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Meta != null) { text = text + "meta," + Meta.ToString() + ","; } if (Links != null) { text = text + "links," + Links.ToString() + ","; } if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "Allocation")] public class Allocation { [Preserve] [DataMember(Name = "allocationId", IsRequired = true, EmitDefaultValue = true)] public Guid AllocationId { get; } [Preserve] [DataMember(Name = "serverEndpoints", IsRequired = true, EmitDefaultValue = true)] public List<RelayServerEndpoint> ServerEndpoints { get; } [Preserve] [DataMember(Name = "relayServer", IsRequired = true, EmitDefaultValue = true)] public RelayServer RelayServer { get; } [Preserve] [DataMember(Name = "key", IsRequired = true, EmitDefaultValue = true)] public byte[] Key { get; } [Preserve] [DataMember(Name = "connectionData", IsRequired = true, EmitDefaultValue = true)] public byte[] ConnectionData { get; } [Preserve] [DataMember(Name = "allocationIdBytes", IsRequired = true, EmitDefaultValue = true)] public byte[] AllocationIdBytes { get; } [Preserve] [DataMember(Name = "region", IsRequired = true, EmitDefaultValue = true)] public string Region { get; } [Preserve] public Allocation(Guid allocationId, List<RelayServerEndpoint> serverEndpoints, RelayServer relayServer, byte[] key, byte[] connectionData, byte[] allocationIdBytes, string region) { AllocationId = allocationId; ServerEndpoints = serverEndpoints; RelayServer = relayServer; Key = key; ConnectionData = connectionData; AllocationIdBytes = allocationIdBytes; Region = region; } internal string SerializeAsPathParam() { string text = ""; _ = AllocationId; text = text + "allocationId," + AllocationId.ToString() + ","; if (ServerEndpoints != null) { text = text + "serverEndpoints," + ServerEndpoints.ToString() + ","; } if (RelayServer != null) { text = text + "relayServer," + RelayServer.ToString() + ","; } if (Key != null) { text = text + "key," + Key.ToString() + ","; } if (ConnectionData != null) { text = text + "connectionData," + ConnectionData.ToString() + ","; } if (AllocationIdBytes != null) { text = text + "allocationIdBytes," + AllocationIdBytes.ToString() + ","; } if (Region != null) { text = text + "region," + Region; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); _ = AllocationId; string value = AllocationId.ToString(); dictionary.Add("allocationId", value); if (Key != null) { string value2 = Key.ToString(); dictionary.Add("key", value2); } if (ConnectionData != null) { string value3 = ConnectionData.ToString(); dictionary.Add("connectionData", value3); } if (AllocationIdBytes != null) { string value4 = AllocationIdBytes.ToString(); dictionary.Add("allocationIdBytes", value4); } if (Region != null) { string value5 = Region.ToString(); dictionary.Add("region", value5); } return dictionary; } } [Preserve] [DataContract(Name = "AllocationData")] public class AllocationData { [Preserve] [DataMember(Name = "allocation", IsRequired = true, EmitDefaultValue = true)] public Allocation Allocation { get; } [Preserve] public AllocationData(Allocation allocation) { Allocation = allocation; } internal string SerializeAsPathParam() { string text = ""; if (Allocation != null) { text = text + "allocation," + Allocation.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "AllocationRequest")] public class AllocationRequest { [Preserve] [DataMember(Name = "maxConnections", IsRequired = true, EmitDefaultValue = true)] public int MaxConnections { get; } [Preserve] [DataMember(Name = "region", EmitDefaultValue = false)] public string Region { get; } [Preserve] public AllocationRequest(int maxConnections, string region = null) { MaxConnections = maxConnections; Region = region; } internal string SerializeAsPathParam() { string text = ""; text = text + "maxConnections," + MaxConnections + ","; if (Region != null) { text = text + "region," + Region; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); string value = MaxConnections.ToString(); dictionary.Add("maxConnections", value); if (Region != null) { string value2 = Region.ToString(); dictionary.Add("region", value2); } return dictionary; } } [Preserve] [DataContract(Name = "ErrorResponseBody")] public class ErrorResponseBody { [Preserve] [DataMember(Name = "status", IsRequired = true, EmitDefaultValue = true)] public int Status { get; } [Preserve] [DataMember(Name = "detail", IsRequired = true, EmitDefaultValue = true)] public string Detail { get; } [Preserve] [DataMember(Name = "title", IsRequired = true, EmitDefaultValue = true)] public string Title { get; } [Preserve] [DataMember(Name = "details", EmitDefaultValue = false)] public List<KeyValuePair> Details { get; } [Preserve] [DataMember(Name = "type", IsRequired = true, EmitDefaultValue = true)] public string Type { get; } [Preserve] [DataMember(Name = "code", IsRequired = true, EmitDefaultValue = true)] public int Code { get; } [Preserve] public ErrorResponseBody(int status, string detail, string title, string type, int code, List<KeyValuePair> details = null) { Status = status; Detail = detail; Title = title; Details = details; Type = type; Code = code; } internal string SerializeAsPathParam() { string text = ""; text = text + "status," + Status + ","; if (Detail != null) { text = text + "detail," + Detail + ","; } if (Title != null) { text = text + "title," + Title + ","; } if (Details != null) { text = text + "details," + Details.ToString() + ","; } if (Type != null) { text = text + "type," + Type + ","; } return text + "code," + Code; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); string value = Status.ToString(); dictionary.Add("status", value); if (Detail != null) { string value2 = Detail.ToString(); dictionary.Add("detail", value2); } if (Title != null) { string value3 = Title.ToString(); dictionary.Add("title", value3); } if (Type != null) { string value4 = Type.ToString(); dictionary.Add("type", value4); } string value5 = Code.ToString(); dictionary.Add("code", value5); return dictionary; } } [Preserve] [DataContract(Name = "JoinAllocation")] public class JoinAllocation { [Preserve] [DataMember(Name = "allocationId", IsRequired = true, EmitDefaultValue = true)] public Guid AllocationId { get; } [Preserve] [DataMember(Name = "serverEndpoints", IsRequired = true, EmitDefaultValue = true)] public List<RelayServerEndpoint> ServerEndpoints { get; } [Preserve] [DataMember(Name = "relayServer", IsRequired = true, EmitDefaultValue = true)] public RelayServer RelayServer { get; } [Preserve] [DataMember(Name = "key", IsRequired = true, EmitDefaultValue = true)] public byte[] Key { get; } [Preserve] [DataMember(Name = "connectionData", IsRequired = true, EmitDefaultValue = true)] public byte[] ConnectionData { get; } [Preserve] [DataMember(Name = "allocationIdBytes", IsRequired = true, EmitDefaultValue = true)] public byte[] AllocationIdBytes { get; } [Preserve] [DataMember(Name = "region", IsRequired = true, EmitDefaultValue = true)] public string Region { get; } [Preserve] [DataMember(Name = "hostConnectionData", IsRequired = true, EmitDefaultValue = true)] public byte[] HostConnectionData { get; } [Preserve] public JoinAllocation(Guid allocationId, List<RelayServerEndpoint> serverEndpoints, RelayServer relayServer, byte[] key, byte[] connectionData, byte[] allocationIdBytes, string region, byte[] hostConnectionData) { AllocationId = allocationId; ServerEndpoints = serverEndpoints; RelayServer = relayServer; Key = key; ConnectionData = connectionData; AllocationIdBytes = allocationIdBytes; Region = region; HostConnectionData = hostConnectionData; } internal string SerializeAsPathParam() { string text = ""; _ = AllocationId; text = text + "allocationId," + AllocationId.ToString() + ","; if (ServerEndpoints != null) { text = text + "serverEndpoints," + ServerEndpoints.ToString() + ","; } if (RelayServer != null) { text = text + "relayServer," + RelayServer.ToString() + ","; } if (Key != null) { text = text + "key," + Key.ToString() + ","; } if (ConnectionData != null) { text = text + "connectionData," + ConnectionData.ToString() + ","; } if (AllocationIdBytes != null) { text = text + "allocationIdBytes," + AllocationIdBytes.ToString() + ","; } if (Region != null) { text = text + "region," + Region + ","; } if (HostConnectionData != null) { text = text + "hostConnectionData," + HostConnectionData.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); _ = AllocationId; string value = AllocationId.ToString(); dictionary.Add("allocationId", value); if (Key != null) { string value2 = Key.ToString(); dictionary.Add("key", value2); } if (ConnectionData != null) { string value3 = ConnectionData.ToString(); dictionary.Add("connectionData", value3); } if (AllocationIdBytes != null) { string value4 = AllocationIdBytes.ToString(); dictionary.Add("allocationIdBytes", value4); } if (Region != null) { string value5 = Region.ToString(); dictionary.Add("region", value5); } if (HostConnectionData != null) { string value6 = HostConnectionData.ToString(); dictionary.Add("hostConnectionData", value6); } return dictionary; } } [Preserve] [DataContract(Name = "JoinAllocation_allOf")] public class JoinAllocationAllOf { [Preserve] [DataMember(Name = "hostConnectionData", IsRequired = true, EmitDefaultValue = true)] public byte[] HostConnectionData { get; } [Preserve] public JoinAllocationAllOf(byte[] hostConnectionData) { HostConnectionData = hostConnectionData; } internal string SerializeAsPathParam() { string text = ""; if (HostConnectionData != null) { text = text + "hostConnectionData," + HostConnectionData.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (HostConnectionData != null) { string value = HostConnectionData.ToString(); dictionary.Add("hostConnectionData", value); } return dictionary; } } [Preserve] [DataContract(Name = "JoinCodeData")] public class JoinCodeData { [Preserve] [DataMember(Name = "joinCode", IsRequired = true, EmitDefaultValue = true)] public string JoinCode { get; } [Preserve] public JoinCodeData(string joinCode) { JoinCode = joinCode; } internal string SerializeAsPathParam() { string text = ""; if (JoinCode != null) { text = text + "joinCode," + JoinCode; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (JoinCode != null) { string value = JoinCode.ToString(); dictionary.Add("joinCode", value); } return dictionary; } } [Preserve] [DataContract(Name = "JoinCodeRequest")] public class JoinCodeRequest { [Preserve] [DataMember(Name = "allocationId", IsRequired = true, EmitDefaultValue = true)] public Guid AllocationId { get; } [Preserve] public JoinCodeRequest(Guid allocationId) { AllocationId = allocationId; } internal string SerializeAsPathParam() { string text = ""; _ = AllocationId; return text + "allocationId," + AllocationId; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); _ = AllocationId; string value = AllocationId.ToString(); dictionary.Add("allocationId", value); return dictionary; } } [Preserve] [DataContract(Name = "JoinCodeResponseBody")] public class JoinCodeResponseBody { [Preserve] [DataMember(Name = "meta", IsRequired = true, EmitDefaultValue = true)] public ResponseMeta Meta { get; } [Preserve] [DataMember(Name = "links", IsRequired = true, EmitDefaultValue = true)] public ResponseLinks Links { get; } [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public JoinCodeData Data { get; } [Preserve] public JoinCodeResponseBody(ResponseMeta meta, ResponseLinks links, JoinCodeData data) { Meta = meta; Links = links; Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Meta != null) { text = text + "meta," + Meta.ToString() + ","; } if (Links != null) { text = text + "links," + Links.ToString() + ","; } if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "JoinData")] public class JoinData { [Preserve] [DataMember(Name = "allocation", IsRequired = true, EmitDefaultValue = true)] public JoinAllocation Allocation { get; } [Preserve] public JoinData(JoinAllocation allocation) { Allocation = allocation; } internal string SerializeAsPathParam() { string text = ""; if (Allocation != null) { text = text + "allocation," + Allocation.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "JoinRequest")] public class JoinRequest { [Preserve] [DataMember(Name = "joinCode", IsRequired = true, EmitDefaultValue = true)] public string JoinCode { get; } [Preserve] public JoinRequest(string joinCode) { JoinCode = joinCode; } internal string SerializeAsPathParam() { string text = ""; if (JoinCode != null) { text = text + "joinCode," + JoinCode; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (JoinCode != null) { string value = JoinCode.ToString(); dictionary.Add("joinCode", value); } return dictionary; } } [Preserve] [DataContract(Name = "JoinResponseBody")] public class JoinResponseBody { [Preserve] [DataMember(Name = "meta", IsRequired = true, EmitDefaultValue = true)] public ResponseMeta Meta { get; } [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public JoinData Data { get; } [Preserve] public JoinResponseBody(ResponseMeta meta, JoinData data) { Meta = meta; Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Meta != null) { text = text + "meta," + Meta.ToString() + ","; } if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "KeyValuePair")] public class KeyValuePair { [Preserve] [DataMember(Name = "key", IsRequired = true, EmitDefaultValue = true)] public string Key { get; } [Preserve] [DataMember(Name = "value", IsRequired = true, EmitDefaultValue = true)] public string Value { get; } [Preserve] public KeyValuePair(string key, string value) { Key = key; Value = value; } internal string SerializeAsPathParam() { string text = ""; if (Key != null) { text = text + "key," + Key + ","; } if (Value != null) { text = text + "value," + Value; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Key != null) { string value = Key.ToString(); dictionary.Add("key", value); } if (Value != null) { string value2 = Value.ToString(); dictionary.Add("value", value2); } return dictionary; } } [Preserve] [DataContract(Name = "Region")] public class Region { [Preserve] [DataMember(Name = "id", IsRequired = true, EmitDefaultValue = true)] public string Id { get; } [Preserve] [DataMember(Name = "description", IsRequired = true, EmitDefaultValue = true)] public string Description { get; } [Preserve] public Region(string id, string description) { Id = id; Description = description; } internal string SerializeAsPathParam() { string text = ""; if (Id != null) { text = text + "id," + Id + ","; } if (Description != null) { text = text + "description," + Description; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Id != null) { string value = Id.ToString(); dictionary.Add("id", value); } if (Description != null) { string value2 = Description.ToString(); dictionary.Add("description", value2); } return dictionary; } } [Preserve] [DataContract(Name = "RegionsData")] public class RegionsData { [Preserve] [DataMember(Name = "regions", IsRequired = true, EmitDefaultValue = true)] public List<Region> Regions { get; } [Preserve] public RegionsData(List<Region> regions) { Regions = regions; } internal string SerializeAsPathParam() { string text = ""; if (Regions != null) { text = text + "regions," + Regions.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } [Preserve] [DataContract(Name = "RegionsResponseBody")] public class RegionsResponseBody { [Preserve] [DataMember(Name = "data", IsRequired = true, EmitDefaultValue = true)] public RegionsData Data { get; } [Preserve] public RegionsResponseBody(RegionsData data) { Data = data; } internal string SerializeAsPathParam() { string text = ""; if (Data != null) { text = text + "data," + Data.ToString(); } return text; } internal Dictionary<string, string> GetAsQueryParam() { return new Dictionary<string, string>(); } } public interface IOneOf { Type Type { get; } object Value { get; } } [Preserve] [DataContract(Name = "RelayServer")] public class RelayServer { [Preserve] [DataMember(Name = "ipV4", IsRequired = true, EmitDefaultValue = true)] public string IpV4 { get; } [Preserve] [DataMember(Name = "port", IsRequired = true, EmitDefaultValue = true)] public int Port { get; } [Preserve] public RelayServer(string ipV4, int port) { IpV4 = ipV4; Port = port; } internal string SerializeAsPathParam() { string text = ""; if (IpV4 != null) { text = text + "ipV4," + IpV4 + ","; } return text + "port," + Port; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (IpV4 != null) { string value = IpV4.ToString(); dictionary.Add("ipV4", value); } string value2 = Port.ToString(); dictionary.Add("port", value2); return dictionary; } } [Preserve] [DataContract(Name = "RelayServerEndpoint")] public class RelayServerEndpoint { [Preserve] [JsonConverter(typeof(StringEnumConverter))] public enum NetworkOptions { [EnumMember(Value = "udp")] Udp = 1, [EnumMember(Value = "tcp")] Tcp } public const string ConnectionTypeUdp = "udp"; public const string ConnectionTypeDtls = "dtls"; public const string ConnectionTypeWss = "wss"; [Preserve] [DataMember(Name = "connectionType", IsRequired = true, EmitDefaultValue = true)] public string ConnectionType { get; } [Preserve] [JsonConverter(typeof(StringEnumConverter))] [DataMember(Name = "network", IsRequired = true, EmitDefaultValue = true)] public NetworkOptions Network { get; } [Preserve] [DataMember(Name = "reliable", IsRequired = true, EmitDefaultValue = true)] public bool Reliable { get; } [Preserve] [DataMember(Name = "secure", IsRequired = true, EmitDefaultValue = true)] public bool Secure { get; } [Preserve] [DataMember(Name = "host", IsRequired = true, EmitDefaultValue = true)] public string Host { get; } [Preserve] [DataMember(Name = "port", IsRequired = true, EmitDefaultValue = true)] public int Port { get; } [Preserve] public RelayServerEndpoint(string connectionType, NetworkOptions network, bool reliable, bool secure, string host, int port) { ConnectionType = connectionType; Network = network; Reliable = reliable; Secure = secure; Host = host; Port = port; } internal string SerializeAsPathParam() { string text = ""; if (ConnectionType != null) { text = text + "connectionType," + ConnectionType + ","; } text = text + "network," + Network.ToString() + ","; text = text + "reliable," + Reliable + ","; text = text + "secure," + Secure + ","; if (Host != null) { text = text + "host," + Host + ","; } return text + "port," + Port; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (ConnectionType != null) { string value = ConnectionType.ToString(); dictionary.Add("connectionType", value); } string value2 = Network.ToString(); dictionary.Add("network", value2); string value3 = Reliable.ToString(); dictionary.Add("reliable", value3); string value4 = Secure.ToString(); dictionary.Add("secure", value4); if (Host != null) { string value5 = Host.ToString(); dictionary.Add("host", value5); } string value6 = Port.ToString(); dictionary.Add("port", value6); return dictionary; } } [Preserve] [DataContract(Name = "ResponseLinks")] public class ResponseLinks { [Preserve] [DataMember(Name = "next", EmitDefaultValue = false)] public string Next { get; } [Preserve] public ResponseLinks(string next = null) { Next = next; } internal string SerializeAsPathParam() { string text = ""; if (Next != null) { text = text + "next," + Next; } return text; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (Next != null) { string value = Next.ToString(); dictionary.Add("next", value); } return dictionary; } } [Preserve] [DataContract(Name = "ResponseMeta")] public class ResponseMeta { [Preserve] [DataMember(Name = "requestId", IsRequired = true, EmitDefaultValue = true)] public string RequestId { get; } [Preserve] [DataMember(Name = "status", IsRequired = true, EmitDefaultValue = true)] public int Status { get; } [Preserve] public ResponseMeta(string requestId, int status) { RequestId = requestId; Status = status; } internal string SerializeAsPathParam() { string text = ""; if (RequestId != null) { text = text + "requestId," + RequestId + ","; } return text + "status," + Status; } internal Dictionary<string, string> GetAsQueryParam() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (RequestId != null) { string value = RequestId.ToString(); dictionary.Add("requestId", value); } string value2 = Status.ToString(); dictionary.Add("status", value2); return dictionary; } } } namespace Unity.Services.Relay.Http { internal abstract class BaseApiClient { protected readonly IHttpClient HttpClient; public BaseApiClient(IHttpClient httpClient) { HttpClient = httpClient ?? new HttpClient(); } } [Serializable] internal class DeserializationException : Exception { public DeserializationException() { } public DeserializationException(string message) : base(message) { } private DeserializationException(string message, Exception inner) : base(message, inner) { } } public enum MissingMemberHandling { Error, Ignore } public class DeserializationSettings { public MissingMemberHandling MissingMemberHandling; } internal class HttpClient : IHttpClient { public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout); } public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null) { return await CreateWebRequestAsync(method.ToUpper(), url, body, headers, requestTimeout, boundary); } private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, byte[] body, IDictionary<string, string> headers, int requestTimeout) { return await CreateHttpClientResponse(method, url, body, headers, requestTimeout); } private async Task<HttpClientResponse> CreateHttpClientResponse(string method, string url, byte[] body, IDictionary<string, string> headers, int requestTimeout) { return await (await Task.Factory.StartNew(async delegate { UnityWebRequest request = new UnityWebRequest(url, method); try { foreach (KeyValuePair<string, string> header in headers) { request.SetRequestHeader(header.Key, header.Value); } request.timeout = requestTimeout; if (body != null && (method == "POST" || method == "PUT" || method == "PATCH")) { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body); } request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return await SendWebRequest(request); } finally { ((IDisposable)request)?.Dispose(); } }, CancellationToken.None, TaskCreationOptions.None, ThreadHelper.TaskScheduler)); } private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, List<IMultipartFormSection> body, IDictionary<string, string> headers, int requestTimeout, string boundary = null) { return await (await Task.Factory.StartNew(async delegate { byte[] boundary2 = (string.IsNullOrEmpty(boundary) ? UnityWebRequest.GenerateBoundary() : Encoding.Default.GetBytes(boundary)); UnityWebRequest val = new UnityWebRequest(url, method); foreach (KeyValuePair<string, string> header in headers) { val.SetRequestHeader(header.Key, header.Value); } val.timeout = requestTimeout; val = SetupMultipartRequest(val, body, boundary2); val.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return await SendWebRequest(val); }, CancellationToken.None, TaskCreationOptions.None, ThreadHelper.TaskScheduler)); } private static UnityWebRequest SetupMultipartRequest(UnityWebRequest request, List<IMultipartFormSection> multipartFormSections, byte[] boundary) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown byte[] array = null; if (multipartFormSections != null && multipartFormSections.Count != 0) { array = UnityWebRequest.SerializeFormSections(multipartFormSections, boundary); } UploadHandler val = (UploadHandler)new UploadHandlerRaw(array); val.contentType = "multipart/form-data; boundary=" + Encoding.UTF8.GetString(boundary, 0, boundary.Length); request.uploadHandler = val; request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); return request; } private UnityWebRequestAsyncOperation SendWebRequest(UnityWebRequest request) { return request.SendWebRequest(); } } internal class HttpClientResponse { public Dictionary<string, string> Headers { get; } public long StatusCode { get; } public bool IsHttpError { get; } public bool IsNetworkError { get; } public byte[] Data { get; } public string ErrorMessage { get; } public HttpClientResponse(Dictionary<string, string> headers, long statusCode, bool isHttpError, bool isNetworkError, byte[] data, string errorMessage) { Headers = headers; StatusCode = statusCode; IsHttpError = isHttpError; IsNetworkError = isNetworkError; Data = data; ErrorMessage = errorMessage; } } [Serializable] [Preserve] internal class HttpException : Exception { [Preserve] public HttpClientResponse Response; [Preserve] public HttpException() { } [Preserve] public HttpException(string message) : base(message) { } [Preserve] public HttpException(string message, Exception inner) : base(message, inner) { } [Preserve] public HttpException(HttpClientResponse response) : base($"({response.StatusCode}) {response.ErrorMessage}") { Response = response; } } [Serializable] [Preserve] internal class HttpException<T> : HttpException { [Preserve] public T ActualError; [Preserve] public HttpException() { } [Preserve] public HttpException(string message) : base(message) { } [Preserve] public HttpException(string message, Exception inner) : base(message, inner) { } [Preserve] public HttpException(HttpClientResponse response, T actualError) : base(response) { ActualError = actualError; } } [Preserve] [JsonConverter(typeof(JsonObjectConverter))] internal interface IDeserializable { string GetAsString(); T GetAs<T>(DeserializationSettings deserializationSettings = null); } internal interface IHttpClient { Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout); Task<HttpClientResponse> MakeRequestAsync(string method, string url, List<IMultipartFormSection> body, Dictionary<string, string> headers, int requestTimeout, string boundary = null); } internal static class JsonHelpers { [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] internal static void RegisterTypesForAOT() { AotHelper.EnsureType<StringEnumConverter>(); AotHelper.EnsureType<JsonObjectConverter>(); } internal static bool TryParseJson<T>(this string @this, out T result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown bool success = true; JsonSerializerSettings val = new JsonSerializerSettings { Error = delegate(object sender, ErrorEventArgs args) { success = false; args.ErrorContext.Handled = true; }, MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; result = JsonConvert.DeserializeObject<T>(@this, val); return success; } } [Preserve] [JsonConverter(typeof(JsonObjectConverter))] internal class JsonObject : IDeserializable { [Preserve] internal object obj; [Preserve] internal JsonObject(object obj) { this.obj = obj; } public string GetAsString() { try { if (obj == null) { return ""; } if (obj.GetType() == typeof(string)) { return obj.ToString(); } return JsonConvert.SerializeObject(obj); } catch (Exception) { throw new InvalidOperationException("Failed to convert JsonObject to string."); } } public T GetAs<T>(DeserializationSettings deserializationSettings = null) { //IL_0065: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown deserializationSettings = deserializationSettings ?? new DeserializationSettings(); JsonSerializerSettings val = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)(deserializationSettings.MissingMemberHandling == MissingMemberHandling.Error) }; try { T val2 = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj), val); List<string> list = ValidateObject(val2); if (list.Count > 0) { throw new DeserializationException(string.Join("\n", list)); } return val2; } catch (DeserializationException) { throw; } catch (JsonSerializationException ex2) { throw new DeserializationException(((Exception)ex2).Message); } catch (Exception) { throw new DeserializationException("Unable to deserialize object."); } } public T GetAs<T>() { return GetAs<T>(null); } public static IDeserializable GetNewJsonObjectResponse(object o) { return new JsonObject(o); } public static List<IDeserializable> GetNewJsonObjectResponse(List<object> o) { return o?.Select((Func<object, IDeserializable>)((object v) => new JsonObject(v))).ToList(); } public static List<List<IDeserializable>> GetNewJsonObjectResponse(List<List<object>> o) { return o?.Select((List<object> l) => ((IEnumerable<object>)l).Select((Func<object, IDeserializable>)((object v) => (v != null) ? new JsonObject(v) : null)).ToList()).ToList(); } public static Dictionary<string, IDeserializable> GetNewJsonObjectResponse(Dictionary<string, object> o) { return o?.ToDictionary((Func<KeyValuePair<string, object>, string>)((KeyValuePair<string, object> kv) => kv.Key), (Func<KeyValuePair<string, object>, IDeserializable>)((KeyValuePair<string, object> kv) => new JsonObject(kv.Value))); } public static Dictionary<string, List<IDeserializable>> GetNewJsonObjectResponse(Dictionary<string, List<object>> o) { return o?.ToDictionary((KeyValuePair<string, List<object>> kv) => kv.Key, (KeyValuePair<string, List<object>> kv) => GetNewJsonObjectResponse(kv.Value)); } private List<string> ValidateObject<T>(T objectToCheck, List<string> errors = null) { if (errors == null) { errors = new List<string>(); } if (objectToCheck != null) { if (typeof(IEnumerable).IsAssignableFrom(typeof(T))) { foreach (object item in (IEnumerable)(object)objectToCheck) { ValidateFieldInfos(item, errors); ValidatePropertyInfos(item, errors); } } else { ValidateFieldInfos(objectToCheck, errors); ValidatePropertyInfos(objectToCheck, errors); } } return errors; } private void ValidatePropertyInfos<T>(T objectToCheck, List<string> errors) { PropertyInfo[] properties = objectToCheck.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.GetIndexParameters().Length != 0) { for (int j = 0; j < propertyInfo.GetIndexParameters().Length; j++) { object value = propertyInfo.GetValue(objectToCheck, new object[1] { j }); string name = propertyInfo.Name; string name2 = objectToCheck.GetType().Name; ValidateValue(value, name2, "Property", name, errors); } } else { object value2 = propertyInfo.GetValue(objectToCheck); string name3 = propertyInfo.Name; string name4 = objectToCheck.GetType().Name; ValidateValue(value2, name4, "Property", name3, errors); } } } private void ValidateFieldInfos<T>(T objectToCheck, List<string> errors) { FieldInfo[] fields = objectToCheck.GetType().GetFields(); foreach (FieldInfo obj in fields) { object value = obj.GetValue(objectToCheck); string name = obj.Name; string name2 = objectToCheck.GetType().Name; ValidateValue(value, name2, "Field", name, errors); } } private void ValidateValue(object value, string objectName, string memberType, string memberName, List<string> errors) { if (!(value is ValueType) && !(value is string)) { if (value is JObject) { errors.Add(memberType + ": \"" + memberName + "\" on Type: \"" + objectName + "\" must not be of type `object` or `dynamic`"); } else { ValidateObject(value, errors); } } } } [Preserve] internal class JsonObjectConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { JsonObject jsonObject = (JsonObject)value; if (jsonObject.obj == null) { writer.WriteNull(); } else { JToken.FromObject(jsonObject.obj).WriteTo(writer, Array.Empty<JsonConverter>()); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType != 11) { if (reader.Value != null) { return new JsonObject(reader.Value); } try { return new JsonObject(JObject.Load(reader)); } catch (JsonReaderException) { return new JsonObject(JArray.Load(reader)); } } return new JsonObject(null); } public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } } [Preserve] internal class JsonObjectCollectionConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { object obj = value; Type type = value.GetType(); if (type == typeof(Dictionary<string, IDeserializable>)) { obj = (Dictionary<string, IDeserializable>)value; } else if (type == typeof(List<IDeserializable>)) { obj = (List<IDeserializable>)value; } else if (type == typeof(List<List<IDeserializable>>)) { obj = (List<List<IDeserializable>>)value; } if (obj == null) { writer.WriteNull(); } else { JToken.FromObject(obj).WriteTo(writer, Array.Empty<JsonConverter>()); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType != 11) { List<object> obj = (List<object>)reader.Value; List<JsonObject> list = new List<JsonObject>(); { foreach (object item in obj) { list.Add(new JsonObject(item)); } return list; } } return null; } public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } } [Serializable] internal class ResponseDeserializationException : Exception { public HttpClientResponse response; public ResponseDeserializationException() { } public ResponseDeserializationException(string message) : base(message) { } private ResponseDeserializationException(Exception inner, string message) : base(message, inner) { } public ResponseDeserializationException(HttpClientResponse httpClientResponse) : base("Unable to Deserialize Http Client Response") { response = httpClientResponse; } public ResponseDeserializationException(HttpClientResponse httpClientResponse, string message) : base(message) { response = httpClientResponse; } public ResponseDeserializationException(HttpClientResponse httpClientResponse, Exception inner, string message) : base(message, inner) { response = httpClientResponse; } } internal static class ResponseHandler { private static List<IDeserializable> DeserializeListOfJsonObjects(List<object> objectList) { List<IDeserializable> list = new List<IDeserializable>(); foreach (object @object in objectList) { list.Add(new JsonObject(@object)); } return list; } public static T TryDeserializeResponse<T>(HttpClientResponse response) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown JsonSerializerSettings val = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; try { return JsonConvert.DeserializeObject<T>(GetDeserializedJson(response.Data), val); } catch (Exception ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } } public static object TryDeserializeResponse(HttpClientResponse response, Type type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown JsonSerializerSettings val = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)0, ReferenceLoopHandling = (ReferenceLoopHandling)1 }; try { return JsonConvert.DeserializeObject(GetDeserializedJson(response.Data), type, val); } catch (Exception ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } } private static string GetDeserializedJson(byte[] data) { return Encoding.UTF8.GetString(data); } public static void HandleAsyncResponse(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap) { if (statusCodeToTypeMap.ContainsKey(response.StatusCode.ToString())) { Type type = statusCodeToTypeMap[response.StatusCode.ToString()]; if ((type != null && response.IsHttpError) || response.IsNetworkError) { if (typeof(IOneOf).IsAssignableFrom(type)) { throw CreateOneOfException(response, type); } throw CreateHttpException(response, type); } return; } throw new HttpException(response); } private static HttpException CreateOneOfException(HttpClientResponse response, Type responseType) { try { object obj = TryDeserializeResponse(response, responseType); return CreateHttpException(response, ((IOneOf)obj).Type); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.InnerException.GetType() == typeof(MissingFieldException)) { throw new ResponseDeserializationException(response, ex2.InnerException, "Discriminator field not found in the parsed json response."); } if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } private static HttpException CreateHttpException(HttpClientResponse response, Type responseType) { Type type = typeof(HttpException<>).MakeGenericType(responseType); try { if (responseType == typeof(Stream)) { object obj = ((response.Data == null) ? new MemoryStream() : new MemoryStream(response.Data)); return (HttpException)Activator.CreateInstance(type, response, obj); } object obj2 = TryDeserializeResponse(response, responseType); return (HttpException)Activator.CreateInstance(type, response, obj2); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } public static T HandleAsyncResponse<T>(HttpClientResponse response, Dictionary<string, Type> statusCodeToTypeMap) where T : class { HandleAsyncResponse(response, statusCodeToTypeMap); try { if (statusCodeToTypeMap[response.StatusCode.ToString()] == typeof(Stream)) { return ((response.Data == null) ? new MemoryStream() : new MemoryStream(response.Data)) as T; } return TryDeserializeResponse<T>(response); } catch (ArgumentException ex) { throw new ResponseDeserializationException(response, ex.Message); } catch (MissingFieldException inner) { throw new ResponseDeserializationException(response, inner, "Discriminator field not found in the parsed json response."); } catch (ResponseDeserializationException ex2) { if (ex2.response == null) { throw new ResponseDeserializationException(response, ex2.Message); } throw; } catch (Exception ex3) { throw new ResponseDeserializationException(response, ex3, ex3.Message); } } } internal static class UnityWebRequestHelpers { public static TaskAwaiter<HttpClientResponse> GetAwaiter(this UnityWebRequestAsyncOperation asyncOp) { TaskCompletionSource<HttpClientResponse> tcs = new TaskCompletionSource<HttpClientResponse>(); ((AsyncOperation)asyncOp).completed += delegate(AsyncOperation obj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown HttpClientResponse result = CreateHttpClientResponse((UnityWebRequestAsyncOperation)obj); tcs.SetResult(result); }; return tcs.Task.GetAwaiter(); } internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse) { UnityWebRequest webRequest = unityResponse.webRequest; return new HttpClientResponse(webRequest.GetResponseHeaders(), webRequest.responseCode, webRequest.isHttpError, webRequest.isNetworkError, webRequest.downloadHandler.data, webRequest.error); } } } namespace Unity.Services.Relay.Helpers { internal static class AsyncOpRetry { public static AsyncOpRetry<T> FromCreateAsync<T>(Func<int, T> op) { return AsyncOpRetry<T>.FromCreateAsync(op); } } internal class AsyncOpRetry<T> { private uint MaxRetries { get; set; } = 4u; private float JitterMagnitude { get; set; } = 1f; private float DelayScale { get; set; } = 1f; private float MaxDelayTime { get; set; } = 8f; private Func<int, T> CreateOperation { get; set; } private Func<T, bool> RetryCondition { get; set; } private Action<T> OnComplete { get; set; } private AsyncOpRetry(Func<int, T> createAsyncOp) { CreateOperation = createAsyncOp; } private static float AddJitter(float number, float magnitude) { return number + Random.value * magnitude; } private static float Pow2(float exponent, float scale) { return (float)(Math.Pow(2.0, exponent) * (double)scale); } private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale, float jitterMagnitude) { return Math.Min(AddJitter(Pow2(attemptNumber, delayScale), jitterMagnitude), maxDelayTime); } public static AsyncOpRetry<T> FromCreateAsync(Func<int, T> op) { return new AsyncOpRetry<T>(op); } public AsyncOpRetry<T> WithRetryCondition(Func<T, bool> shouldRetry) { RetryCondition = shouldRetry; return this; } public AsyncOpRetry<T> WhenComplete(Action<T> onComplete) { OnComplete = onComplete; return this; } public IEnumerator Run() { T asyncOp = default(T); int attempt = 0; while (attempt <= MaxRetries) { asyncOp = CreateOperation(attempt + 1); yield return asyncOp; Func<T, bool> retryCondition = RetryCondition; if (retryCondition != null && !retryCondition(asyncOp)) { break; } float num = CalculateDelay(attempt, MaxDelayTime, DelayScale, JitterMagnitude); yield return (object)new WaitForSecondsRealtime(num); int num2 = attempt + 1; attempt = num2; } OnComplete?.Invoke(asyncOp); } } } namespace Unity.Services.Relay.ErrorMitigation { internal interface IRetryPolicyProvider { IRetryPolicy<T> ForOperation<T>(Func<int, Task<T>> operation); IRetryPolicy<T> ForOperation<T>(Func<Task<T>> operation); } internal interface IRetryPolicy<T> { IRetryPolicy<T> WithJitterMagnitude(float magnitude); IRetryPolicy<T> WithDelayScale(float scale); IRetryPolicy<T> WithMaxDelayTime(float time); IRetryPolicy<T> WithRetryCondition(Func<T, Task<bool>> shouldRetry); IRetryPolicy<T> UptoMaximumRetries(uint amount); IRetryPolicy<T> HandleException<TException>() where TException : Exception; IRetryPolicy<T> HandleException<TException>(Func<TException, bool> condition) where TException : Exception; Task<T> RunAsync(RetryPolicyConfig retryPolicyConfig = null); } internal class RetryPolicyProvider : IRetryPolicyProvider { public IRetryPolicy<T> ForOperation<T>(Func<int, Task<T>> operation) { return RetryPolicy<T>.ForOperation(operation); } public IRetryPolicy<T> ForOperation<T>(Func<Task<T>> operation) { return RetryPolicy<T>.ForOperation(operation); } } internal class RetryPolicy<T> : IRetryPolicy<T> { private RetryPolicyConfig _retryPolicyConfig = new RetryPolicyConfig(); private Func<int, Task<T>> CreateOperation { get; set; } private Func<T, Task<bool>> RetryCondition { get; set; } private RetryPolicy(Func<int, Task<T>> createAsyncOp) { CreateOperation = createAsyncOp; } private RetryPolicy(Func<Task<T>> createAsyncOp) { CreateOperation = (int _) => createAsyncOp(); } private static float AddJitter(float number, float magnitude) { return number + Random.value * magnitude; } private static float Pow2(float exponent, float scale) { return (float)(Math.Pow(2.0, exponent) * (double)scale); } private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale, float jitterMagnitude) { return Math.Min(AddJitter(Pow2(attemptNumber, delayScale), jitterMagnitude), maxDelayTime); } public IRetryPolicy<T> WithJitterMagnitude(float magnitude) { _retryPolicyConfig.JitterMagnitude = magnitude; return this; } public IRetryPolicy<T> WithDelayScale(float scale) { _retryPolicyConfig.DelayScale = scale; return this; } public IRetryPolicy<T> WithMaxDelayTime(float time) { _retryPolicyConfig.MaxDelayTime = time; return this; } public static RetryPolicy<T> ForOperation(Func<int, Task<T>> operation) { return new RetryPolicy<T>(operation); } public static RetryPolicy<T> ForOperation(Func<Task<T>> operation) { return new RetryPolicy<T>(operation); } public IRetryPolicy<T> WithRetryCondition(Func<T, Task<bool>> shouldRetry) { RetryCondition = shouldRetry; return this; } public IRetryPolicy<T> UptoMaximumRetries(uint amount) { _retryPolicyConfig.MaxRetries = amount; return this; } public IRetryPolicy<T> HandleException<TException>() where TException : Exception { _retryPolicyConfig.HandleException<TException>(); return this; } public IRetryPolicy<T> HandleException<TException>(Func<TException, bool> condition) where TException : Exception { _retryPolicyConfig.HandleException(condition); return this; } public async Task<T> RunAsync(RetryPolicyConfig retryPolicyConfig = null) { T opResult = default(T); if (retryPolicyConfig == null) { retryPolicyConfig = _retryPolicyConfig; } int attempt = 0; while (attempt <= retryPolicyConfig.MaxRetries) { try { opResult = await CreateOperation(attempt + 1); } catch (Exception e) { if (!retryPolicyConfig.IsHandledException(e)) { throw; } } if (RetryCondition != null && opResult != null) { if (!(await RetryCondition(opResult))) { break; } } else if (opResult != null) { break; } await Task.Delay((int)(CalculateDelay(attempt, retryPolicyConfig.MaxDelayTime, retryPolicyConfig.DelayScale, retryPolicyConfig.JitterMagnitude) * 1000f)); int num = attempt + 1; attempt = num; } return opResult; } } internal delegate Exception ExceptionPredicate(Exception ex); internal class RetryPolicyConfig { private float _jitterMagnitude = 1f; private float _delayScale = 1f; private float _maxDelayTime = 8f; private List<ExceptionPredicate> _exceptionsToHandle = new List<ExceptionPredicate>(); public uint MaxRetries { get; set; } = 4u; public float JitterMagnitude { get { return _jitterMagnitude; } set { _jitterMagnitude = Mathf.Clamp(value, 0.001f, 1f); } } public float DelayScale { get { return _delayScale; } set { _delayScale = Mathf.Clamp(value, 0.05f, 1f); } } public float MaxDelayTime { get { return _maxDelayTime; } set { _maxDelayTime = Mathf.Clamp(value, 0.1f, 60f); } } public void HandleException<TException>() where TException : Exception { _exceptionsToHandle.Add((Exception exception) => (!(exception is TException)) ? null : exception); } public void HandleException<TException>(Func<TException, bool> condition) where TException : Exception { _exceptionsToHandle.Add((Exception exception) => (!(exception is TException arg) || !condition(arg)) ? null : exception); } public bool IsHandledException(Exception e) { if (_exceptionsToHandle != null) { foreach (ExceptionPredicate item in _exceptionsToHandle) { if (item(e) == e) { return true; } } } return false; } } internal class StatusCodePolicyConfig { private IDictionary<long, bool> _statusCodesToHandleDict = new Dictionary<long, bool> { { 408L, true }, { 429L, true }, { 502L, true }, { 503L, true }, { 504L, true } }; public void HandleStatusCode(long code) { if (_statusCodesToHandleDict.ContainsKey(code)) { _statusCodesToHandleDict[code] = true; } else { _statusCodesToHandleDict.Add(new KeyValuePair<long, bool>(code, value: true)); } } public void DontHandleStatusCode(long code) { if (_statusCodesToHandleDict.ContainsKey(code)) { _statusCodesToHandleDict[code] = false; } else { _statusCodesToHandleDict.Add(new KeyValuePair<long, bool>(code, value: false)); } } public void Clear() { _statusCodesToHandleDict.Clear(); } public bool IsHandledStatusCode(long code) { return _statusCodesToHandleDict.Contains(new KeyValuePair<long, bool>(code, value: true)); } } } namespace Unity.Services.Relay.RelayAllocations { internal static class JsonSerialization { public static byte[] Serialize<T>(T obj) { return Encoding.UTF8.GetBytes(SerializeToString(obj)); } public static string SerializeToString<T>(T obj) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return JsonConvert.SerializeObject((object)obj, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 }); } } [Preserve] internal class RelayAllocationsApiBaseRequest { private static readonly Regex JsonRegex = new Regex("application\\/json(;\\s)?((charset=utf8|q=[0-1]\\.\\d)(\\s)?)*"); [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, string key, string value) { key = UnityWebRequest.EscapeURL(key); value = UnityWebRequest.EscapeURL(value); queryParams.Add(key + "=" + value); return queryParams; } [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, string key, List<string> values, string style, bool explode) { if (explode) { foreach (string value in values) { string text = UnityWebRequest.EscapeURL(value); queryParams.Add(UnityWebRequest.EscapeURL(key) + "=" + text); } } else { string text2 = UnityWebRequest.EscapeURL(key) + "="; foreach (string value2 in values) { text2 = text2 + UnityWebRequest.EscapeURL(value2) + ","; } text2 = text2.Remove(text2.Length - 1); queryParams.Add(text2); } return queryParams; } [Preserve] public List<string> AddParamsToQueryParams(List<string> queryParams, Dictionary<string, string> modelVars) { foreach (string key in modelVars.Keys) { string text = UnityWebRequest.EscapeURL(modelVars[key]); queryParams.Add(UnityWebRequest.EscapeURL(key) + "=" + text); } return queryParams; } [Preserve] public List<string> AddParamsToQueryParams<T>(List<string> queryParams, string key, T value) { if (queryParams == null) { queryParams = new List<string>(); } key = UnityWebRequest.EscapeURL(key); string text = UnityWebRequest.EscapeURL(value.ToString()); queryParams.Add(key + "=" + text); return queryParams; } [Preserve] public string GetPathParamString(List<string> pathParam) { string text = ""; foreach (string item in pathParam) { text = text + UnityWebRequest.EscapeURL(item) + ","; } return text.Remove(text.Length - 1); } public byte[] ConstructBody(Stream stream) { if (stream != null) { using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } return null; } public byte[] ConstructBody(string s) { return Encoding.UTF8.GetBytes(s); } public byte[] ConstructBody(object o) { return JsonSerialization.Serialize(o); } public string GenerateAcceptHeader(string[] accepts) { if (accepts.Length == 0) { return null; } for (int i = 0; i < accepts.Length; i++) { if (string.Equals(accepts[i], "application/json", StringComparison.OrdinalIgnoreCase)) { return "application/json"; } } return string.Join(", ", accepts); } public string GenerateContentTypeHeader(string[] contentTypes) { if (contentTypes.Length == 0) { return null; } for (int i = 0; i < contentTypes.Length; i++) { if (!string.IsNullOrWhiteSpace(contentTypes[i]) && JsonRegex.IsMatch(contentTypes[i])) { return contentTypes[i]; } } return contentTypes[0]; } public IMultipartFormSection GenerateMultipartFormFileSection(string paramName, FileStream stream, string contentType) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return (IMultipartFormSection)new MultipartFormFileSection(paramName, ConstructBody(stream), GetFileName(stream.Name), contentType); } public IMultipartFormSection GenerateMultipartFormFileSection(string paramName, Stream stream, string contentType) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return (IMultipartFormSection)new MultipartFormFileSection(paramName, ConstructBody(stream), Guid.NewGuid().ToString(), contentType); } private string GetFileName(string filePath) { return Path.GetFileName(filePath); } } [Preserve] internal class CreateAllocationRequest : RelayAllocationsApiBaseRequest { private string PathAndQueryParams; [Preserve] public AllocationRequest AllocationRequest { get; } [Preserve] public CreateAllocationRequest(AllocationRequest allocationRequest) { AllocationRequest = allocationRequest; PathAndQueryParams = "/v1/allocate"; } public string ConstructUrl(string requestBasePath) { return requestBasePath + PathAndQueryParams; } public byte[] ConstructBody() { return ConstructBody(AllocationRequest); } public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken, Configuration operationConfiguration = null) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(accessToken.AccessToken)) { dictionary.Add("authorization", "Bearer " + accessToken.AccessToken); } dictionary.Add("Unity-Client-Version", Application.unityVersion); dictionary.Add("Unity-Client-Mode", EngineStateHelper.IsPlaying ? "play" : "edit"); string[] contentTypes = new string[1] { "application/json" }; string[] accepts = new string[2] { "application/json", "application/problem+json" }; string value = GenerateAcceptHeader(accepts); if (!string.IsNullOrEmpty(value)) { dictionary.Add("Accept", value); } string text = "POST"; string value2 = GenerateContentTypeHeader(contentTypes); if (!string.IsNullOrEmpty(value2)) { dictionary.Add("Content-Type", value2); } else if (text == "POST" || text == "PATCH") { dictionary.Add("Content-Type", "application/json"); } if (operationConfiguration != null && operationConfiguration.Headers != null) { foreach (KeyValuePair<string, string> header in operationConfiguration.Headers) { dictionary[header.Key] = header.Value; } } return dictionary; } } [Preserve] internal class CreateJoincodeRequest : RelayAllocationsApiBaseRequest { private string PathAndQueryParams; [Preserve] public JoinCodeRequest JoinCodeRequest { get; } [Preserve] public CreateJoincodeRequest(JoinCodeRequest joinCodeRequest) { JoinCodeRequest = joinCodeRequest; PathAndQueryParams = "/v1/joincode"; } public string ConstructUrl(string requestBasePath) { return requestBasePath + PathAndQueryParams; } public byte[] ConstructBody() { return ConstructBody(JoinCodeRequest); } public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken, Configuration operationConfiguration = null) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(accessToken.AccessToken)) { dictionary.Add("authorization", "Bearer " + accessToken.AccessToken); } dictionary.Add("Unity-Client-Version", Application.unityVersion); dictionary.Add("Unity-Client-Mode", EngineStateHelper.IsPlaying ? "play" : "edit"); string[] contentTypes = new string[1] { "application/json" }; string[] accepts = new string[2] { "application/json", "application/problem+json" }; string value = GenerateAcceptHeader(accepts); if (!string.IsNullOrEmpty(value)) { dictionary.Add("Accept", value); } string text = "POST"; string value2 = GenerateContentTypeHeader(contentTypes); if (!string.IsNullOrEmpty(value2)) { dictionary.Add("Content-Type", value2); } else if (text == "POST" || text == "PATCH") { dictionary.Add("Content-Type", "application/json"); } if (operationConfiguration != null && operationConfiguration.Headers != null) { foreach (KeyValuePair<string, string> header in operationConfiguration.Headers) { dictionary[header.Key] = header.Value; } } return dictionary; } } [Preserve] internal class JoinRelayRequest : RelayAllocationsApiBaseRequest { private string PathAndQueryParams; [Preserve] public JoinRequest JoinRequest { get; } [Preserve] public JoinRelayRequest(JoinRequest joinRequest) { JoinRequest = joinRequest; PathAndQueryParams = "/v1/join"; } public string ConstructUrl(string requestBasePath) { return requestBasePath + PathAndQueryParams; } public byte[] ConstructBody() { return ConstructBody(JoinRequest); } public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken, Configuration operationConfiguration = null) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(accessToken.AccessToken)) { dictionary.Add("authorization", "Bearer " + accessToken.AccessToken); } dictionary.Add("Unity-Client-Version", Application.unityVersion); dictionary.Add("Unity-Client-Mode", EngineStateHelper.IsPlaying ? "play" : "edit"); string[] contentTypes = new string[1] { "application/json" }; string[] accepts = new string[2] { "application/json", "application/problem+json" }; string value = GenerateAcceptHeader(accepts); if (!string.IsNullOrEmpty(value)) { dictionary.Add("Accept", value); } string text = "POST"; string value2 = GenerateContentTypeHeader(contentTypes); if (!string.IsNullOrEmpty(value2)) { dictionary.Add("Content-Type", value2); } else if (text == "POST" || text == "PATCH") { dictionary.Add("Content-Type", "application/json"); } if (operationConfiguration != null && operationConfiguration.Headers != null) { foreach (KeyValuePair<string, string> header in operationConfiguration.Headers) { dictionary[header.Key] = header.Value; } } return dictionary; } } [Preserve] internal class ListRegionsRequest : RelayAllocationsApiBaseRequest { private string PathAndQueryParams; [Preserve] public ListRegionsRequest() { PathAndQueryParams = "/v1/regions"; } public string ConstructUrl(string requestBasePath) { return requestBasePath + PathAndQueryParams; } public byte[] ConstructBody() { return null; } public Dictionary<string, string> ConstructHeaders(IAccessToken accessToken, Configuration operationConfiguration = null) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(accessToken.AccessToken)) { dictionary.Add("authorization", "Bearer " + accessToken.AccessToken); } dictionary.Add("Unity-Client-Version", Application.unityVersion); dictionary.Add("Unity-Client-Mode", EngineStateHelper.IsPlaying ? "play" : "edit"); string[] contentTypes = new string[0]; string[] accepts = new string[2] { "application/json", "application/problem+json" }; string value = GenerateAcceptHeader(accepts); if (!string.IsNullOrEmpty(value)) { dictionary.Add("Accept", value); } string text = "GET"; string value2 = GenerateContentTypeHeader(contentTypes); if (!string.IsNullOrEmpty(value2)) { dictionary.Add("Content-Type", value2); } else if (text == "POST" || text == "PATCH") { dictionary.Add("Content-Type", "application/json"); } if (operationConfiguration != null && operationConfiguration.Headers != null) { foreach (KeyValuePair<string, string> header in operationConfiguration.Headers) { dictionary[header.Key] = header.Value; } } return dictionary; } } } namespace Unity.Services.Relay.Apis.RelayAllocations { internal interface IRelayAllocationsApiClient { Task<Response<AllocateResponseBody>> CreateAllocationAsync(CreateAllocationRequest request, Configuration operationConfiguration = null); Task<Response<JoinCodeResponseBody>> CreateJoincodeAsync(CreateJoincodeRequest request, Configuration operationConfiguration = null); Task<Response<JoinResponseBody>> JoinRelayAsync(JoinRelayRequest request, Configuration operationConfiguration = null); Task<Response<RegionsResponseBody>> ListRegionsAsync(ListRegionsRequest request, Configuration operationConfiguration = null); } internal class RelayAllocationsApiClient : BaseApiClient, IRelayAllocationsApiClient { private IAccessToken _accessToken; private const int _baseTimeout = 10; private Configuration _configuration; public Configuration Configuration { get { Configuration b = new Configuration("https://relay-allocations.services.api.unity.com", 10, 4, null); return Configuration.MergeConfigurations(_configuration, b); } set { _configuration = value; } } public RelayAllocationsApiClient(IHttpClient httpClient, IAccessToken accessToken, Configuration configuration = null) : base(httpClient) { _configuration = configuration; _accessToken = accessToken; } public async Task<Response<AllocateResponseBody>> CreateAllocationAsync(CreateAllocationRequest request, Configuration operationConfiguration = null) { Dictionary<string, Type> statusCodeToTypeMap = new Dictionary<string, Type> { { "201", typeof(AllocateResponseBody) }, { "400", typeof(ErrorResponseBody) }, { "401", typeof(ErrorResponseBody) }, { "403", typeof(ErrorResponseBody) }, { "429", typeof(ErrorResponseBody) }, { "500", typeof(ErrorResponseBody) }, { "503", typeof(ErrorResponseBody) } }; Configuration configuration = Configuration.MergeConfigurations(operationConfiguration, Configuration); HttpClientResponse obj = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(configuration.BasePath), request.ConstructBody(), request.ConstructHeaders(_accessToken, configuration), configuration.RequestTimeout ?? 10); AllocateResponseBody result = ResponseHandler.HandleAsyncResponse<AllocateResponseBody>(obj, statusCodeToTypeMap); return new Response<AllocateResponseBody>(obj, result); } public async Task<Response<JoinCodeResponseBody>> CreateJoincodeAsync(CreateJoincodeRequest request, Configuration operationConfiguration = null) { Dictionary<string, Type> statusCodeToTypeMap = new Dictionary<string, Type> { { "200", typeof(JoinCodeResponseBody) }, { "201", typeof(JoinCodeResponseBody) }, { "400", typeof(ErrorResponseBody) }, { "401", typeof(ErrorResponseBody) }, { "403", typeof(ErrorResponseBody) }, { "404", typeof(ErrorResponseBody) }, { "429", typeof(ErrorResponseBody) }, { "500", typeof(ErrorResponseBody) } }; Configuration configuration = Configuration.MergeConfigurations(operationConfiguration, Configuration); HttpClientResponse obj = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(configuration.BasePath), request.ConstructBody(), request.ConstructHeaders(_accessToken, configuration), configuration.RequestTimeout ?? 10); JoinCodeResponseBody result = ResponseHandler.HandleAsyncResponse<JoinCodeResponseBody>(obj, statusCodeToTypeMap); return new Response<JoinCodeResponseBody>(obj, result); } public async Task<Response<JoinResponseBody>> JoinRelayAsync(JoinRelayRequest request, Configuration operationConfiguration = null) { Dictionary<string, Type> statusCodeToTypeMap = new Dictionary<string, Type> { { "200", typeof(JoinResponseBody) }, { "400", typeof(ErrorResponseBody) }, { "401", typeof(ErrorResponseBody) }, { "403", typeof(ErrorResponseBody) }, { "404", typeof(ErrorResponseBody) }, { "429", typeof(ErrorResponseBody) }, { "500", typeof(ErrorResponseBody) } }; Configuration configuration = Configuration.MergeConfigurations(operationConfiguration, Configuration); HttpClientResponse obj = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(configuration.BasePath), request.ConstructBody(), request.ConstructHeaders(_accessToken, configuration), configuration.RequestTimeout ?? 10); JoinResponseBody result = ResponseHandler.HandleAsyncResponse<JoinResponseBody>(obj, statusCodeToTypeMap); return new Response<JoinResponseBody>(obj, result); } public async Task<Response<RegionsResponseBody>> ListRegionsAsync(ListRegionsRequest request, Configuration operationConfiguration = null) { Dictionary<string, Type> statusCodeToTypeMap = new Dictionary<string, Type> { { "200", typeof(RegionsResponseBody) }, { "400", typeof(ErrorResponseBody) }, { "401", typeof(ErrorResponseBody) }, { "403", typeof(ErrorResponseBody) }, { "429", typeof(ErrorResponseBody) }, { "500", typeof(ErrorResponseBody) } }; Configuration configuration = Configuration.MergeConfigurations(operationConfiguration, Configuration); HttpClientResponse obj = await HttpClient.MakeRequestAsync("GET", request.ConstructUrl(configuration.BasePath), request.ConstructBody(), request.ConstructHeaders(_accessToken, configuration), configuration.RequestTimeout ?? 10); RegionsResponseBody result = ResponseHandler.HandleAsyncResponse<RegionsResponseBody>(obj, statusCodeToTypeMap); return new Response<RegionsResponseBody>(obj, result); } } }